Statistics
| Branch: | Revision:

root / hw / pci_host.c @ 8d6514f8

History | View | Annotate | Download (6.7 kB)

1
/*
2
 * pci_host.c
3
 *
4
 * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
5
 *                    VA Linux Systems Japan K.K.
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11

12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16

17
 * You should have received a copy of the GNU General Public License along
18
 * with this program; if not, write to the Free Software Foundation, Inc.,
19
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
 */
21

    
22
#include "pci.h"
23
#include "pci_host.h"
24

    
25
/* debug PCI */
26
//#define DEBUG_PCI
27

    
28
#ifdef DEBUG_PCI
29
#define PCI_DPRINTF(fmt, ...) \
30
do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
31
#else
32
#define PCI_DPRINTF(fmt, ...)
33
#endif
34

    
35
/*
36
 * PCI address
37
 * bit 16 - 24: bus number
38
 * bit  8 - 15: devfun number
39
 * bit  0 -  7: offset in configuration space of a given pci device
40
 */
41

    
42
/* the helper functio to get a PCIDeice* for a given pci address */
43
static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
44
{
45
    uint8_t bus_num = (addr >> 16) & 0xff;
46
    uint8_t devfn = (addr >> 8) & 0xff;
47
    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
48
}
49

    
50
void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
51
{
52
    PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr);
53
    uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
54

    
55
    if (!pci_dev)
56
        return;
57

    
58
    PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
59
                __func__, pci_dev->name, config_addr, val, len);
60
    pci_dev->config_write(pci_dev, config_addr, val, len);
61
}
62

    
63
uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
64
{
65
    PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr);
66
    uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
67
    uint32_t val;
68

    
69
    assert(len == 1 || len == 2 || len == 4);
70
    if (!pci_dev) {
71
        return ~0x0;
72
    }
73

    
74
    val = pci_dev->config_read(pci_dev, config_addr, len);
75
    PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
76
                __func__, pci_dev->name, config_addr, val, len);
77

    
78
    return val;
79
}
80

    
81
static void pci_host_config_writel(void *opaque, target_phys_addr_t addr,
82
                                   uint32_t val)
83
{
84
    PCIHostState *s = opaque;
85

    
86
#ifdef TARGET_WORDS_BIGENDIAN
87
    val = bswap32(val);
88
#endif
89
    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
90
                __func__, addr, val);
91
    s->config_reg = val;
92
}
93

    
94
static uint32_t pci_host_config_readl(void *opaque, target_phys_addr_t addr)
95
{
96
    PCIHostState *s = opaque;
97
    uint32_t val = s->config_reg;
98

    
99
#ifdef TARGET_WORDS_BIGENDIAN
100
    val = bswap32(val);
101
#endif
102
    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
103
                __func__, addr, val);
104
    return val;
105
}
106

    
107
static CPUWriteMemoryFunc * const pci_host_config_write[] = {
108
    &pci_host_config_writel,
109
    &pci_host_config_writel,
110
    &pci_host_config_writel,
111
};
112

    
113
static CPUReadMemoryFunc * const pci_host_config_read[] = {
114
    &pci_host_config_readl,
115
    &pci_host_config_readl,
116
    &pci_host_config_readl,
117
};
118

    
119
int pci_host_config_register_io_memory(PCIHostState *s)
120
{
121
    return cpu_register_io_memory(pci_host_config_read,
122
                                  pci_host_config_write, s);
123
}
124

    
125
static void pci_host_config_writel_noswap(void *opaque,
126
                                          target_phys_addr_t addr,
127
                                          uint32_t val)
128
{
129
    PCIHostState *s = opaque;
130

    
131
    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
132
                __func__, addr, val);
133
    s->config_reg = val;
134
}
135

    
136
static uint32_t pci_host_config_readl_noswap(void *opaque,
137
                                             target_phys_addr_t addr)
138
{
139
    PCIHostState *s = opaque;
140
    uint32_t val = s->config_reg;
141

    
142
    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
143
                __func__, addr, val);
144
    return val;
145
}
146

    
147
static CPUWriteMemoryFunc * const pci_host_config_write_noswap[] = {
148
    &pci_host_config_writel_noswap,
149
    &pci_host_config_writel_noswap,
150
    &pci_host_config_writel_noswap,
151
};
152

    
153
static CPUReadMemoryFunc * const pci_host_config_read_noswap[] = {
154
    &pci_host_config_readl_noswap,
155
    &pci_host_config_readl_noswap,
156
    &pci_host_config_readl_noswap,
157
};
158

    
159
int pci_host_config_register_io_memory_noswap(PCIHostState *s)
160
{
161
    return cpu_register_io_memory(pci_host_config_read_noswap,
162
                                  pci_host_config_write_noswap, s);
163
}
164

    
165
static void pci_host_config_writel_ioport(void *opaque,
166
                                          uint32_t addr, uint32_t val)
167
{
168
    PCIHostState *s = opaque;
169

    
170
    PCI_DPRINTF("%s addr %"PRIx32 " val %"PRIx32"\n", __func__, addr, val);
171
    s->config_reg = val;
172
}
173

    
174
static uint32_t pci_host_config_readl_ioport(void *opaque, uint32_t addr)
175
{
176
    PCIHostState *s = opaque;
177
    uint32_t val = s->config_reg;
178

    
179
    PCI_DPRINTF("%s addr %"PRIx32" val %"PRIx32"\n", __func__, addr, val);
180
    return val;
181
}
182

    
183
void pci_host_config_register_ioport(pio_addr_t ioport, PCIHostState *s)
184
{
185
    register_ioport_write(ioport, 4, 4, pci_host_config_writel_ioport, s);
186
    register_ioport_read(ioport, 4, 4, pci_host_config_readl_ioport, s);
187
}
188

    
189
#define PCI_ADDR_T      target_phys_addr_t
190
#define PCI_HOST_SUFFIX _mmio
191

    
192
#include "pci_host_template.h"
193

    
194
static CPUWriteMemoryFunc * const pci_host_data_write_mmio[] = {
195
    pci_host_data_writeb_mmio,
196
    pci_host_data_writew_mmio,
197
    pci_host_data_writel_mmio,
198
};
199

    
200
static CPUReadMemoryFunc * const pci_host_data_read_mmio[] = {
201
    pci_host_data_readb_mmio,
202
    pci_host_data_readw_mmio,
203
    pci_host_data_readl_mmio,
204
};
205

    
206
int pci_host_data_register_io_memory(PCIHostState *s)
207
{
208
    return cpu_register_io_memory(pci_host_data_read_mmio,
209
                                  pci_host_data_write_mmio,
210
                                  s);
211
}
212

    
213
#undef PCI_ADDR_T
214
#undef PCI_HOST_SUFFIX
215

    
216
#define PCI_ADDR_T      uint32_t
217
#define PCI_HOST_SUFFIX _ioport
218

    
219
#include "pci_host_template.h"
220

    
221
void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s)
222
{
223
    register_ioport_write(ioport, 4, 1, pci_host_data_writeb_ioport, s);
224
    register_ioport_write(ioport, 4, 2, pci_host_data_writew_ioport, s);
225
    register_ioport_write(ioport, 4, 4, pci_host_data_writel_ioport, s);
226
    register_ioport_read(ioport, 4, 1, pci_host_data_readb_ioport, s);
227
    register_ioport_read(ioport, 4, 2, pci_host_data_readw_ioport, s);
228
    register_ioport_read(ioport, 4, 4, pci_host_data_readl_ioport, s);
229
}