]>
Commit | Line | Data |
---|---|---|
69b91039 FB |
1 | /* |
2 | * QEMU PCI bus manager | |
3 | * | |
4 | * Copyright (c) 2004 Fabrice Bellard | |
5fafdf24 | 5 | * |
69b91039 FB |
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | * of this software and associated documentation files (the "Software"), to deal | |
8 | * in the Software without restriction, including without limitation the rights | |
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | * copies of the Software, and to permit persons to whom the Software is | |
11 | * furnished to do so, subject to the following conditions: | |
12 | * | |
13 | * The above copyright notice and this permission notice shall be included in | |
14 | * all copies or substantial portions of the Software. | |
15 | * | |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 | * THE SOFTWARE. | |
23 | */ | |
87ecb68b PB |
24 | #include "hw.h" |
25 | #include "pci.h" | |
376253ec | 26 | #include "monitor.h" |
87ecb68b | 27 | #include "net.h" |
880345c4 | 28 | #include "sysemu.h" |
69b91039 FB |
29 | |
30 | //#define DEBUG_PCI | |
d8d2e079 | 31 | #ifdef DEBUG_PCI |
2e49d64a | 32 | # define PCI_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) |
d8d2e079 IY |
33 | #else |
34 | # define PCI_DPRINTF(format, ...) do { } while (0) | |
35 | #endif | |
69b91039 | 36 | |
30468f78 | 37 | struct PCIBus { |
02e2da45 | 38 | BusState qbus; |
30468f78 FB |
39 | int bus_num; |
40 | int devfn_min; | |
502a5395 | 41 | pci_set_irq_fn set_irq; |
d2b59317 | 42 | pci_map_irq_fn map_irq; |
ee995ffb | 43 | pci_hotplug_fn hotplug; |
30468f78 | 44 | uint32_t config_reg; /* XXX: suppress */ |
5d4e84c8 | 45 | void *irq_opaque; |
30468f78 | 46 | PCIDevice *devices[256]; |
80b3ada7 PB |
47 | PCIDevice *parent_dev; |
48 | PCIBus *next; | |
d2b59317 PB |
49 | /* The bus IRQ state is the logical OR of the connected devices. |
50 | Keep a count of the number of devices with raised IRQs. */ | |
52fc1d83 | 51 | int nirq; |
10c4c98a GH |
52 | int *irq_count; |
53 | }; | |
54 | ||
55 | static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent); | |
56 | ||
57 | static struct BusInfo pci_bus_info = { | |
58 | .name = "PCI", | |
59 | .size = sizeof(PCIBus), | |
60 | .print_dev = pcibus_dev_print, | |
ee6847d1 | 61 | .props = (Property[]) { |
54586bd1 GH |
62 | DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), |
63 | DEFINE_PROP_END_OF_LIST() | |
ee6847d1 | 64 | } |
30468f78 | 65 | }; |
69b91039 | 66 | |
1941d19c | 67 | static void pci_update_mappings(PCIDevice *d); |
d537cf6c | 68 | static void pci_set_irq(void *opaque, int irq_num, int level); |
1941d19c | 69 | |
c227f099 | 70 | target_phys_addr_t pci_mem_base; |
d350d97d AL |
71 | static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET; |
72 | static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU; | |
30468f78 FB |
73 | static PCIBus *first_bus; |
74 | ||
2d1e9f96 JQ |
75 | static const VMStateDescription vmstate_pcibus = { |
76 | .name = "PCIBUS", | |
77 | .version_id = 1, | |
78 | .minimum_version_id = 1, | |
79 | .minimum_version_id_old = 1, | |
80 | .fields = (VMStateField []) { | |
81 | VMSTATE_INT32_EQUAL(nirq, PCIBus), | |
c7bde572 | 82 | VMSTATE_VARRAY_INT32(irq_count, PCIBus, nirq, 0, vmstate_info_int32, int32_t), |
2d1e9f96 | 83 | VMSTATE_END_OF_LIST() |
52fc1d83 | 84 | } |
2d1e9f96 | 85 | }; |
52fc1d83 | 86 | |
b3b11697 | 87 | static int pci_bar(PCIDevice *d, int reg) |
5330de09 | 88 | { |
b3b11697 IY |
89 | uint8_t type; |
90 | ||
91 | if (reg != PCI_ROM_SLOT) | |
92 | return PCI_BASE_ADDRESS_0 + reg * 4; | |
93 | ||
94 | type = d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION; | |
95 | return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS; | |
5330de09 MT |
96 | } |
97 | ||
98 | static void pci_device_reset(PCIDevice *dev) | |
99 | { | |
c0b1905b MT |
100 | int r; |
101 | ||
5330de09 | 102 | memset(dev->irq_state, 0, sizeof dev->irq_state); |
c0b1905b MT |
103 | dev->config[PCI_COMMAND] &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | |
104 | PCI_COMMAND_MASTER); | |
105 | dev->config[PCI_CACHE_LINE_SIZE] = 0x0; | |
106 | dev->config[PCI_INTERRUPT_LINE] = 0x0; | |
107 | for (r = 0; r < PCI_NUM_REGIONS; ++r) { | |
108 | if (!dev->io_regions[r].size) { | |
109 | continue; | |
110 | } | |
b3b11697 | 111 | pci_set_long(dev->config + pci_bar(dev, r), dev->io_regions[r].type); |
c0b1905b MT |
112 | } |
113 | pci_update_mappings(dev); | |
5330de09 MT |
114 | } |
115 | ||
6eaa6847 GN |
116 | static void pci_bus_reset(void *opaque) |
117 | { | |
a60380a5 | 118 | PCIBus *bus = opaque; |
6eaa6847 GN |
119 | int i; |
120 | ||
121 | for (i = 0; i < bus->nirq; i++) { | |
122 | bus->irq_count[i] = 0; | |
123 | } | |
5330de09 MT |
124 | for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { |
125 | if (bus->devices[i]) { | |
126 | pci_device_reset(bus->devices[i]); | |
127 | } | |
6eaa6847 GN |
128 | } |
129 | } | |
130 | ||
21eea4b3 GH |
131 | void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent, |
132 | const char *name, int devfn_min) | |
30468f78 | 133 | { |
52fc1d83 AZ |
134 | static int nbus = 0; |
135 | ||
21eea4b3 | 136 | qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name); |
502a5395 | 137 | bus->devfn_min = devfn_min; |
425c608c | 138 | bus->next = first_bus; |
30468f78 | 139 | first_bus = bus; |
2d1e9f96 | 140 | vmstate_register(nbus++, &vmstate_pcibus, bus); |
a08d4367 | 141 | qemu_register_reset(pci_bus_reset, bus); |
21eea4b3 GH |
142 | } |
143 | ||
144 | PCIBus *pci_bus_new(DeviceState *parent, const char *name, int devfn_min) | |
145 | { | |
146 | PCIBus *bus; | |
147 | ||
148 | bus = qemu_mallocz(sizeof(*bus)); | |
149 | bus->qbus.qdev_allocated = 1; | |
150 | pci_bus_new_inplace(bus, parent, name, devfn_min); | |
151 | return bus; | |
152 | } | |
153 | ||
154 | void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, | |
155 | void *irq_opaque, int nirq) | |
156 | { | |
157 | bus->set_irq = set_irq; | |
158 | bus->map_irq = map_irq; | |
159 | bus->irq_opaque = irq_opaque; | |
160 | bus->nirq = nirq; | |
161 | bus->irq_count = qemu_mallocz(nirq * sizeof(bus->irq_count[0])); | |
162 | } | |
163 | ||
ee995ffb GH |
164 | void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug) |
165 | { | |
166 | bus->qbus.allow_hotplug = 1; | |
167 | bus->hotplug = hotplug; | |
168 | } | |
169 | ||
21eea4b3 GH |
170 | PCIBus *pci_register_bus(DeviceState *parent, const char *name, |
171 | pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, | |
172 | void *irq_opaque, int devfn_min, int nirq) | |
173 | { | |
174 | PCIBus *bus; | |
175 | ||
176 | bus = pci_bus_new(parent, name, devfn_min); | |
177 | pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq); | |
30468f78 FB |
178 | return bus; |
179 | } | |
69b91039 | 180 | |
03587182 GH |
181 | static void pci_register_secondary_bus(PCIBus *bus, |
182 | PCIDevice *dev, | |
183 | pci_map_irq_fn map_irq, | |
184 | const char *name) | |
80b3ada7 | 185 | { |
03587182 | 186 | qbus_create_inplace(&bus->qbus, &pci_bus_info, &dev->qdev, name); |
80b3ada7 PB |
187 | bus->map_irq = map_irq; |
188 | bus->parent_dev = dev; | |
189 | bus->next = dev->bus->next; | |
190 | dev->bus->next = bus; | |
80b3ada7 PB |
191 | } |
192 | ||
502a5395 PB |
193 | int pci_bus_num(PCIBus *s) |
194 | { | |
195 | return s->bus_num; | |
196 | } | |
197 | ||
73534f2f | 198 | static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) |
30ca2aab | 199 | { |
73534f2f | 200 | PCIDevice *s = container_of(pv, PCIDevice, config); |
05fcfada | 201 | uint8_t config[PCI_CONFIG_SPACE_SIZE]; |
52fc1d83 AZ |
202 | int i; |
203 | ||
05fcfada MT |
204 | assert(size == sizeof config); |
205 | qemu_get_buffer(f, config, sizeof config); | |
206 | for (i = 0; i < sizeof config; ++i) | |
bd4b65ee MT |
207 | if ((config[i] ^ s->config[i]) & s->cmask[i] & ~s->wmask[i]) |
208 | return -EINVAL; | |
05fcfada | 209 | memcpy(s->config, config, sizeof config); |
bd4b65ee | 210 | |
1941d19c | 211 | pci_update_mappings(s); |
52fc1d83 | 212 | |
30ca2aab FB |
213 | return 0; |
214 | } | |
215 | ||
73534f2f | 216 | /* just put buffer */ |
84e2e3eb | 217 | static void put_pci_config_device(QEMUFile *f, void *pv, size_t size) |
73534f2f JQ |
218 | { |
219 | const uint8_t *v = pv; | |
220 | qemu_put_buffer(f, v, size); | |
221 | } | |
222 | ||
223 | static VMStateInfo vmstate_info_pci_config = { | |
224 | .name = "pci config", | |
225 | .get = get_pci_config_device, | |
226 | .put = put_pci_config_device, | |
227 | }; | |
228 | ||
229 | const VMStateDescription vmstate_pci_device = { | |
230 | .name = "PCIDevice", | |
231 | .version_id = 2, | |
232 | .minimum_version_id = 1, | |
233 | .minimum_version_id_old = 1, | |
234 | .fields = (VMStateField []) { | |
235 | VMSTATE_INT32_LE(version_id, PCIDevice), | |
236 | VMSTATE_SINGLE(config, PCIDevice, 0, vmstate_info_pci_config, | |
237 | typeof_field(PCIDevice,config)), | |
e369cad7 | 238 | VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2), |
73534f2f JQ |
239 | VMSTATE_END_OF_LIST() |
240 | } | |
241 | }; | |
242 | ||
243 | void pci_device_save(PCIDevice *s, QEMUFile *f) | |
244 | { | |
245 | vmstate_save_state(f, &vmstate_pci_device, s); | |
246 | } | |
247 | ||
248 | int pci_device_load(PCIDevice *s, QEMUFile *f) | |
249 | { | |
250 | return vmstate_load_state(f, &vmstate_pci_device, s, s->version_id); | |
251 | } | |
252 | ||
d350d97d AL |
253 | static int pci_set_default_subsystem_id(PCIDevice *pci_dev) |
254 | { | |
255 | uint16_t *id; | |
256 | ||
257 | id = (void*)(&pci_dev->config[PCI_SUBVENDOR_ID]); | |
258 | id[0] = cpu_to_le16(pci_default_sub_vendor_id); | |
259 | id[1] = cpu_to_le16(pci_default_sub_device_id); | |
260 | return 0; | |
261 | } | |
262 | ||
880345c4 AL |
263 | /* |
264 | * Parse [[<domain>:]<bus>:]<slot>, return -1 on error | |
265 | */ | |
266 | static int pci_parse_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp) | |
267 | { | |
268 | const char *p; | |
269 | char *e; | |
270 | unsigned long val; | |
271 | unsigned long dom = 0, bus = 0; | |
272 | unsigned slot = 0; | |
273 | ||
274 | p = addr; | |
275 | val = strtoul(p, &e, 16); | |
276 | if (e == p) | |
277 | return -1; | |
278 | if (*e == ':') { | |
279 | bus = val; | |
280 | p = e + 1; | |
281 | val = strtoul(p, &e, 16); | |
282 | if (e == p) | |
283 | return -1; | |
284 | if (*e == ':') { | |
285 | dom = bus; | |
286 | bus = val; | |
287 | p = e + 1; | |
288 | val = strtoul(p, &e, 16); | |
289 | if (e == p) | |
290 | return -1; | |
291 | } | |
292 | } | |
293 | ||
294 | if (dom > 0xffff || bus > 0xff || val > 0x1f) | |
295 | return -1; | |
296 | ||
297 | slot = val; | |
298 | ||
299 | if (*e) | |
300 | return -1; | |
301 | ||
302 | /* Note: QEMU doesn't implement domains other than 0 */ | |
303 | if (dom != 0 || pci_find_bus(bus) == NULL) | |
304 | return -1; | |
305 | ||
306 | *domp = dom; | |
307 | *busp = bus; | |
308 | *slotp = slot; | |
309 | return 0; | |
310 | } | |
311 | ||
e9283f8b JK |
312 | int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp, |
313 | unsigned *slotp) | |
880345c4 | 314 | { |
e9283f8b JK |
315 | /* strip legacy tag */ |
316 | if (!strncmp(addr, "pci_addr=", 9)) { | |
317 | addr += 9; | |
318 | } | |
319 | if (pci_parse_devaddr(addr, domp, busp, slotp)) { | |
320 | monitor_printf(mon, "Invalid pci address\n"); | |
880345c4 | 321 | return -1; |
e9283f8b JK |
322 | } |
323 | return 0; | |
880345c4 AL |
324 | } |
325 | ||
49bd1458 | 326 | PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr) |
5607c388 MA |
327 | { |
328 | int dom, bus; | |
329 | unsigned slot; | |
330 | ||
331 | if (!devaddr) { | |
332 | *devfnp = -1; | |
333 | return pci_find_bus(0); | |
334 | } | |
335 | ||
336 | if (pci_parse_devaddr(devaddr, &dom, &bus, &slot) < 0) { | |
337 | return NULL; | |
338 | } | |
339 | ||
340 | *devfnp = slot << 3; | |
341 | return pci_find_bus(bus); | |
342 | } | |
343 | ||
bd4b65ee MT |
344 | static void pci_init_cmask(PCIDevice *dev) |
345 | { | |
346 | pci_set_word(dev->cmask + PCI_VENDOR_ID, 0xffff); | |
347 | pci_set_word(dev->cmask + PCI_DEVICE_ID, 0xffff); | |
348 | dev->cmask[PCI_STATUS] = PCI_STATUS_CAP_LIST; | |
349 | dev->cmask[PCI_REVISION_ID] = 0xff; | |
350 | dev->cmask[PCI_CLASS_PROG] = 0xff; | |
351 | pci_set_word(dev->cmask + PCI_CLASS_DEVICE, 0xffff); | |
352 | dev->cmask[PCI_HEADER_TYPE] = 0xff; | |
353 | dev->cmask[PCI_CAPABILITY_LIST] = 0xff; | |
354 | } | |
355 | ||
b7ee1603 MT |
356 | static void pci_init_wmask(PCIDevice *dev) |
357 | { | |
358 | int i; | |
359 | dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff; | |
360 | dev->wmask[PCI_INTERRUPT_LINE] = 0xff; | |
67a51b48 IY |
361 | pci_set_word(dev->wmask + PCI_COMMAND, |
362 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); | |
b7ee1603 MT |
363 | for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i) |
364 | dev->wmask[i] = 0xff; | |
365 | } | |
366 | ||
69b91039 | 367 | /* -1 for devfn means auto assign */ |
6b1b92d3 PB |
368 | static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, |
369 | const char *name, int devfn, | |
370 | PCIConfigReadFunc *config_read, | |
371 | PCIConfigWriteFunc *config_write) | |
69b91039 | 372 | { |
69b91039 | 373 | if (devfn < 0) { |
30468f78 FB |
374 | for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) { |
375 | if (!bus->devices[devfn]) | |
69b91039 FB |
376 | goto found; |
377 | } | |
378 | return NULL; | |
379 | found: ; | |
07b7d053 MA |
380 | } else if (bus->devices[devfn]) { |
381 | return NULL; | |
69b91039 | 382 | } |
30468f78 | 383 | pci_dev->bus = bus; |
69b91039 FB |
384 | pci_dev->devfn = devfn; |
385 | pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); | |
d2b59317 | 386 | memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state)); |
d350d97d | 387 | pci_set_default_subsystem_id(pci_dev); |
bd4b65ee | 388 | pci_init_cmask(pci_dev); |
b7ee1603 | 389 | pci_init_wmask(pci_dev); |
0ac32c83 FB |
390 | |
391 | if (!config_read) | |
392 | config_read = pci_default_read_config; | |
393 | if (!config_write) | |
394 | config_write = pci_default_write_config; | |
69b91039 FB |
395 | pci_dev->config_read = config_read; |
396 | pci_dev->config_write = config_write; | |
30468f78 | 397 | bus->devices[devfn] = pci_dev; |
e369cad7 | 398 | pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS); |
f16c4abf | 399 | pci_dev->version_id = 2; /* Current pci device vmstate version */ |
69b91039 FB |
400 | return pci_dev; |
401 | } | |
402 | ||
6b1b92d3 PB |
403 | PCIDevice *pci_register_device(PCIBus *bus, const char *name, |
404 | int instance_size, int devfn, | |
405 | PCIConfigReadFunc *config_read, | |
406 | PCIConfigWriteFunc *config_write) | |
407 | { | |
408 | PCIDevice *pci_dev; | |
409 | ||
410 | pci_dev = qemu_mallocz(instance_size); | |
411 | pci_dev = do_pci_register_device(pci_dev, bus, name, devfn, | |
412 | config_read, config_write); | |
413 | return pci_dev; | |
414 | } | |
c227f099 | 415 | static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr) |
5851e08c AL |
416 | { |
417 | return addr + pci_mem_base; | |
418 | } | |
419 | ||
420 | static void pci_unregister_io_regions(PCIDevice *pci_dev) | |
421 | { | |
422 | PCIIORegion *r; | |
423 | int i; | |
424 | ||
425 | for(i = 0; i < PCI_NUM_REGIONS; i++) { | |
426 | r = &pci_dev->io_regions[i]; | |
182f9c8a | 427 | if (!r->size || r->addr == PCI_BAR_UNMAPPED) |
5851e08c | 428 | continue; |
0392a017 | 429 | if (r->type == PCI_BASE_ADDRESS_SPACE_IO) { |
5851e08c AL |
430 | isa_unassign_ioport(r->addr, r->size); |
431 | } else { | |
432 | cpu_register_physical_memory(pci_to_cpu_addr(r->addr), | |
433 | r->size, | |
434 | IO_MEM_UNASSIGNED); | |
435 | } | |
436 | } | |
437 | } | |
438 | ||
a36a344d | 439 | static int pci_unregister_device(DeviceState *dev) |
5851e08c | 440 | { |
a36a344d | 441 | PCIDevice *pci_dev = DO_UPCAST(PCIDevice, qdev, dev); |
e3936fa5 | 442 | PCIDeviceInfo *info = DO_UPCAST(PCIDeviceInfo, qdev, dev->info); |
5851e08c AL |
443 | int ret = 0; |
444 | ||
e3936fa5 GH |
445 | if (info->exit) |
446 | ret = info->exit(pci_dev); | |
5851e08c AL |
447 | if (ret) |
448 | return ret; | |
449 | ||
450 | pci_unregister_io_regions(pci_dev); | |
451 | ||
452 | qemu_free_irqs(pci_dev->irq); | |
5851e08c | 453 | pci_dev->bus->devices[pci_dev->devfn] = NULL; |
5851e08c AL |
454 | return 0; |
455 | } | |
456 | ||
28c2c264 | 457 | void pci_register_bar(PCIDevice *pci_dev, int region_num, |
5fafdf24 | 458 | uint32_t size, int type, |
69b91039 FB |
459 | PCIMapIORegionFunc *map_func) |
460 | { | |
461 | PCIIORegion *r; | |
d7ce493a | 462 | uint32_t addr; |
b7ee1603 | 463 | uint32_t wmask; |
69b91039 | 464 | |
8a8696a3 | 465 | if ((unsigned int)region_num >= PCI_NUM_REGIONS) |
69b91039 | 466 | return; |
a4c20c6a AL |
467 | |
468 | if (size & (size-1)) { | |
469 | fprintf(stderr, "ERROR: PCI region size must be pow2 " | |
470 | "type=0x%x, size=0x%x\n", type, size); | |
471 | exit(1); | |
472 | } | |
473 | ||
69b91039 | 474 | r = &pci_dev->io_regions[region_num]; |
182f9c8a | 475 | r->addr = PCI_BAR_UNMAPPED; |
69b91039 FB |
476 | r->size = size; |
477 | r->type = type; | |
478 | r->map_func = map_func; | |
b7ee1603 MT |
479 | |
480 | wmask = ~(size - 1); | |
b3b11697 | 481 | addr = pci_bar(pci_dev, region_num); |
d7ce493a | 482 | if (region_num == PCI_ROM_SLOT) { |
b7ee1603 | 483 | /* ROM enable bit is writeable */ |
5330de09 | 484 | wmask |= PCI_ROM_ADDRESS_ENABLE; |
d7ce493a | 485 | } |
b0ff8eb2 IY |
486 | pci_set_long(pci_dev->config + addr, type); |
487 | pci_set_long(pci_dev->wmask + addr, wmask); | |
488 | pci_set_long(pci_dev->cmask + addr, 0xffffffff); | |
69b91039 FB |
489 | } |
490 | ||
0ac32c83 FB |
491 | static void pci_update_mappings(PCIDevice *d) |
492 | { | |
493 | PCIIORegion *r; | |
494 | int cmd, i; | |
5330de09 | 495 | uint32_t last_addr, new_addr; |
3b46e624 | 496 | |
b0ff8eb2 | 497 | cmd = pci_get_word(d->config + PCI_COMMAND); |
8a8696a3 | 498 | for(i = 0; i < PCI_NUM_REGIONS; i++) { |
0ac32c83 FB |
499 | r = &d->io_regions[i]; |
500 | if (r->size != 0) { | |
0392a017 | 501 | if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { |
0ac32c83 | 502 | if (cmd & PCI_COMMAND_IO) { |
b3b11697 | 503 | new_addr = pci_get_long(d->config + pci_bar(d, i)); |
0ac32c83 FB |
504 | new_addr = new_addr & ~(r->size - 1); |
505 | last_addr = new_addr + r->size - 1; | |
506 | /* NOTE: we have only 64K ioports on PC */ | |
507 | if (last_addr <= new_addr || new_addr == 0 || | |
508 | last_addr >= 0x10000) { | |
182f9c8a | 509 | new_addr = PCI_BAR_UNMAPPED; |
0ac32c83 FB |
510 | } |
511 | } else { | |
182f9c8a | 512 | new_addr = PCI_BAR_UNMAPPED; |
0ac32c83 FB |
513 | } |
514 | } else { | |
515 | if (cmd & PCI_COMMAND_MEMORY) { | |
b3b11697 | 516 | new_addr = pci_get_long(d->config + pci_bar(d, i)); |
8a8696a3 | 517 | /* the ROM slot has a specific enable bit */ |
5330de09 | 518 | if (i == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE)) |
8a8696a3 | 519 | goto no_mem_map; |
0ac32c83 FB |
520 | new_addr = new_addr & ~(r->size - 1); |
521 | last_addr = new_addr + r->size - 1; | |
522 | /* NOTE: we do not support wrapping */ | |
523 | /* XXX: as we cannot support really dynamic | |
524 | mappings, we handle specific values as invalid | |
525 | mappings. */ | |
526 | if (last_addr <= new_addr || new_addr == 0 || | |
182f9c8a IY |
527 | last_addr == PCI_BAR_UNMAPPED) { |
528 | new_addr = PCI_BAR_UNMAPPED; | |
0ac32c83 FB |
529 | } |
530 | } else { | |
8a8696a3 | 531 | no_mem_map: |
182f9c8a | 532 | new_addr = PCI_BAR_UNMAPPED; |
0ac32c83 FB |
533 | } |
534 | } | |
535 | /* now do the real mapping */ | |
536 | if (new_addr != r->addr) { | |
182f9c8a | 537 | if (r->addr != PCI_BAR_UNMAPPED) { |
0392a017 | 538 | if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { |
0ac32c83 FB |
539 | int class; |
540 | /* NOTE: specific hack for IDE in PC case: | |
541 | only one byte must be mapped. */ | |
5330de09 | 542 | class = pci_get_word(d->config + PCI_CLASS_DEVICE); |
0ac32c83 FB |
543 | if (class == 0x0101 && r->size == 4) { |
544 | isa_unassign_ioport(r->addr + 2, 1); | |
545 | } else { | |
546 | isa_unassign_ioport(r->addr, r->size); | |
547 | } | |
548 | } else { | |
502a5395 | 549 | cpu_register_physical_memory(pci_to_cpu_addr(r->addr), |
5fafdf24 | 550 | r->size, |
0ac32c83 | 551 | IO_MEM_UNASSIGNED); |
f65ed4c1 | 552 | qemu_unregister_coalesced_mmio(r->addr, r->size); |
0ac32c83 FB |
553 | } |
554 | } | |
555 | r->addr = new_addr; | |
182f9c8a | 556 | if (r->addr != PCI_BAR_UNMAPPED) { |
0ac32c83 FB |
557 | r->map_func(d, i, r->addr, r->size, r->type); |
558 | } | |
559 | } | |
560 | } | |
561 | } | |
562 | } | |
563 | ||
5fafdf24 | 564 | uint32_t pci_default_read_config(PCIDevice *d, |
0ac32c83 | 565 | uint32_t address, int len) |
69b91039 | 566 | { |
5029fe12 IY |
567 | uint32_t val = 0; |
568 | assert(len == 1 || len == 2 || len == 4); | |
569 | len = MIN(len, PCI_CONFIG_SPACE_SIZE - address); | |
570 | memcpy(&val, d->config + address, len); | |
571 | return le32_to_cpu(val); | |
0ac32c83 FB |
572 | } |
573 | ||
b7ee1603 | 574 | void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l) |
0ac32c83 | 575 | { |
b7ee1603 MT |
576 | uint8_t orig[PCI_CONFIG_SPACE_SIZE]; |
577 | int i; | |
0ac32c83 | 578 | |
0ac32c83 | 579 | /* not efficient, but simple */ |
b7ee1603 MT |
580 | memcpy(orig, d->config, PCI_CONFIG_SPACE_SIZE); |
581 | for(i = 0; i < l && addr < PCI_CONFIG_SPACE_SIZE; val >>= 8, ++i, ++addr) { | |
582 | uint8_t wmask = d->wmask[addr]; | |
583 | d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask); | |
0ac32c83 | 584 | } |
b7ee1603 MT |
585 | if (memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24) |
586 | || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND]) | |
587 | & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO))) | |
0ac32c83 | 588 | pci_update_mappings(d); |
69b91039 FB |
589 | } |
590 | ||
502a5395 | 591 | void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len) |
69b91039 | 592 | { |
30468f78 FB |
593 | PCIBus *s = opaque; |
594 | PCIDevice *pci_dev; | |
595 | int config_addr, bus_num; | |
3b46e624 | 596 | |
d8d2e079 IY |
597 | #if 0 |
598 | PCI_DPRINTF("pci_data_write: addr=%08x val=%08x len=%d\n", | |
599 | addr, val, len); | |
69b91039 | 600 | #endif |
502a5395 | 601 | bus_num = (addr >> 16) & 0xff; |
80b3ada7 PB |
602 | while (s && s->bus_num != bus_num) |
603 | s = s->next; | |
604 | if (!s) | |
69b91039 | 605 | return; |
502a5395 | 606 | pci_dev = s->devices[(addr >> 8) & 0xff]; |
69b91039 FB |
607 | if (!pci_dev) |
608 | return; | |
502a5395 | 609 | config_addr = addr & 0xff; |
d8d2e079 IY |
610 | PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n", |
611 | pci_dev->name, config_addr, val, len); | |
0ac32c83 | 612 | pci_dev->config_write(pci_dev, config_addr, val, len); |
69b91039 FB |
613 | } |
614 | ||
502a5395 | 615 | uint32_t pci_data_read(void *opaque, uint32_t addr, int len) |
69b91039 | 616 | { |
30468f78 FB |
617 | PCIBus *s = opaque; |
618 | PCIDevice *pci_dev; | |
619 | int config_addr, bus_num; | |
69b91039 FB |
620 | uint32_t val; |
621 | ||
502a5395 | 622 | bus_num = (addr >> 16) & 0xff; |
80b3ada7 PB |
623 | while (s && s->bus_num != bus_num) |
624 | s= s->next; | |
625 | if (!s) | |
69b91039 | 626 | goto fail; |
502a5395 | 627 | pci_dev = s->devices[(addr >> 8) & 0xff]; |
69b91039 FB |
628 | if (!pci_dev) { |
629 | fail: | |
63ce9e0a FB |
630 | switch(len) { |
631 | case 1: | |
632 | val = 0xff; | |
633 | break; | |
634 | case 2: | |
635 | val = 0xffff; | |
636 | break; | |
637 | default: | |
638 | case 4: | |
639 | val = 0xffffffff; | |
640 | break; | |
641 | } | |
69b91039 FB |
642 | goto the_end; |
643 | } | |
502a5395 | 644 | config_addr = addr & 0xff; |
69b91039 | 645 | val = pci_dev->config_read(pci_dev, config_addr, len); |
d8d2e079 IY |
646 | PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x len=%d\n", |
647 | pci_dev->name, config_addr, val, len); | |
69b91039 | 648 | the_end: |
d8d2e079 IY |
649 | #if 0 |
650 | PCI_DPRINTF("pci_data_read: addr=%08x val=%08x len=%d\n", | |
651 | addr, val, len); | |
69b91039 FB |
652 | #endif |
653 | return val; | |
654 | } | |
655 | ||
502a5395 PB |
656 | /***********************************************************/ |
657 | /* generic PCI irq support */ | |
30468f78 | 658 | |
502a5395 | 659 | /* 0 <= irq_num <= 3. level must be 0 or 1 */ |
d537cf6c | 660 | static void pci_set_irq(void *opaque, int irq_num, int level) |
69b91039 | 661 | { |
a60380a5 | 662 | PCIDevice *pci_dev = opaque; |
80b3ada7 PB |
663 | PCIBus *bus; |
664 | int change; | |
3b46e624 | 665 | |
80b3ada7 PB |
666 | change = level - pci_dev->irq_state[irq_num]; |
667 | if (!change) | |
668 | return; | |
d2b59317 | 669 | |
d2b59317 | 670 | pci_dev->irq_state[irq_num] = level; |
5e966ce6 PB |
671 | for (;;) { |
672 | bus = pci_dev->bus; | |
80b3ada7 | 673 | irq_num = bus->map_irq(pci_dev, irq_num); |
5e966ce6 PB |
674 | if (bus->set_irq) |
675 | break; | |
80b3ada7 | 676 | pci_dev = bus->parent_dev; |
80b3ada7 PB |
677 | } |
678 | bus->irq_count[irq_num] += change; | |
d2b59317 | 679 | bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0); |
69b91039 FB |
680 | } |
681 | ||
502a5395 PB |
682 | /***********************************************************/ |
683 | /* monitor info on PCI */ | |
0ac32c83 | 684 | |
6650ee6d PB |
685 | typedef struct { |
686 | uint16_t class; | |
687 | const char *desc; | |
688 | } pci_class_desc; | |
689 | ||
09bc878a | 690 | static const pci_class_desc pci_class_descriptions[] = |
6650ee6d | 691 | { |
4ca9c76f | 692 | { 0x0100, "SCSI controller"}, |
6650ee6d | 693 | { 0x0101, "IDE controller"}, |
dcb5b19a TS |
694 | { 0x0102, "Floppy controller"}, |
695 | { 0x0103, "IPI controller"}, | |
696 | { 0x0104, "RAID controller"}, | |
697 | { 0x0106, "SATA controller"}, | |
698 | { 0x0107, "SAS controller"}, | |
699 | { 0x0180, "Storage controller"}, | |
6650ee6d | 700 | { 0x0200, "Ethernet controller"}, |
dcb5b19a TS |
701 | { 0x0201, "Token Ring controller"}, |
702 | { 0x0202, "FDDI controller"}, | |
703 | { 0x0203, "ATM controller"}, | |
704 | { 0x0280, "Network controller"}, | |
6650ee6d | 705 | { 0x0300, "VGA controller"}, |
dcb5b19a TS |
706 | { 0x0301, "XGA controller"}, |
707 | { 0x0302, "3D controller"}, | |
708 | { 0x0380, "Display controller"}, | |
709 | { 0x0400, "Video controller"}, | |
710 | { 0x0401, "Audio controller"}, | |
711 | { 0x0402, "Phone"}, | |
712 | { 0x0480, "Multimedia controller"}, | |
713 | { 0x0500, "RAM controller"}, | |
714 | { 0x0501, "Flash controller"}, | |
715 | { 0x0580, "Memory controller"}, | |
6650ee6d PB |
716 | { 0x0600, "Host bridge"}, |
717 | { 0x0601, "ISA bridge"}, | |
dcb5b19a TS |
718 | { 0x0602, "EISA bridge"}, |
719 | { 0x0603, "MC bridge"}, | |
6650ee6d | 720 | { 0x0604, "PCI bridge"}, |
dcb5b19a TS |
721 | { 0x0605, "PCMCIA bridge"}, |
722 | { 0x0606, "NUBUS bridge"}, | |
723 | { 0x0607, "CARDBUS bridge"}, | |
724 | { 0x0608, "RACEWAY bridge"}, | |
725 | { 0x0680, "Bridge"}, | |
6650ee6d PB |
726 | { 0x0c03, "USB controller"}, |
727 | { 0, NULL} | |
728 | }; | |
729 | ||
502a5395 | 730 | static void pci_info_device(PCIDevice *d) |
30468f78 | 731 | { |
376253ec | 732 | Monitor *mon = cur_mon; |
502a5395 PB |
733 | int i, class; |
734 | PCIIORegion *r; | |
09bc878a | 735 | const pci_class_desc *desc; |
30468f78 | 736 | |
376253ec | 737 | monitor_printf(mon, " Bus %2d, device %3d, function %d:\n", |
2217dcff | 738 | d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn)); |
b0ff8eb2 | 739 | class = pci_get_word(d->config + PCI_CLASS_DEVICE); |
376253ec | 740 | monitor_printf(mon, " "); |
6650ee6d PB |
741 | desc = pci_class_descriptions; |
742 | while (desc->desc && class != desc->class) | |
743 | desc++; | |
744 | if (desc->desc) { | |
376253ec | 745 | monitor_printf(mon, "%s", desc->desc); |
6650ee6d | 746 | } else { |
376253ec | 747 | monitor_printf(mon, "Class %04x", class); |
72cc6cfe | 748 | } |
376253ec | 749 | monitor_printf(mon, ": PCI device %04x:%04x\n", |
b0ff8eb2 IY |
750 | pci_get_word(d->config + PCI_VENDOR_ID), |
751 | pci_get_word(d->config + PCI_DEVICE_ID)); | |
30468f78 | 752 | |
502a5395 | 753 | if (d->config[PCI_INTERRUPT_PIN] != 0) { |
376253ec AL |
754 | monitor_printf(mon, " IRQ %d.\n", |
755 | d->config[PCI_INTERRUPT_LINE]); | |
30468f78 | 756 | } |
80b3ada7 | 757 | if (class == 0x0604) { |
376253ec | 758 | monitor_printf(mon, " BUS %d.\n", d->config[0x19]); |
80b3ada7 | 759 | } |
502a5395 PB |
760 | for(i = 0;i < PCI_NUM_REGIONS; i++) { |
761 | r = &d->io_regions[i]; | |
762 | if (r->size != 0) { | |
376253ec | 763 | monitor_printf(mon, " BAR%d: ", i); |
0392a017 | 764 | if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { |
376253ec AL |
765 | monitor_printf(mon, "I/O at 0x%04x [0x%04x].\n", |
766 | r->addr, r->addr + r->size - 1); | |
502a5395 | 767 | } else { |
376253ec AL |
768 | monitor_printf(mon, "32 bit memory at 0x%08x [0x%08x].\n", |
769 | r->addr, r->addr + r->size - 1); | |
502a5395 PB |
770 | } |
771 | } | |
77d4bc34 | 772 | } |
8ad12514 | 773 | monitor_printf(mon, " id \"%s\"\n", d->qdev.id ? d->qdev.id : ""); |
80b3ada7 PB |
774 | if (class == 0x0604 && d->config[0x19] != 0) { |
775 | pci_for_each_device(d->config[0x19], pci_info_device); | |
776 | } | |
384d8876 FB |
777 | } |
778 | ||
80b3ada7 | 779 | void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d)) |
384d8876 | 780 | { |
502a5395 | 781 | PCIBus *bus = first_bus; |
384d8876 | 782 | PCIDevice *d; |
502a5395 | 783 | int devfn; |
3b46e624 | 784 | |
80b3ada7 PB |
785 | while (bus && bus->bus_num != bus_num) |
786 | bus = bus->next; | |
502a5395 PB |
787 | if (bus) { |
788 | for(devfn = 0; devfn < 256; devfn++) { | |
789 | d = bus->devices[devfn]; | |
790 | if (d) | |
791 | fn(d); | |
792 | } | |
f2aa58c6 | 793 | } |
f2aa58c6 FB |
794 | } |
795 | ||
376253ec | 796 | void pci_info(Monitor *mon) |
f2aa58c6 | 797 | { |
80b3ada7 | 798 | pci_for_each_device(0, pci_info_device); |
77d4bc34 | 799 | } |
a41b2ff2 | 800 | |
cb457d76 AL |
801 | static const char * const pci_nic_models[] = { |
802 | "ne2k_pci", | |
803 | "i82551", | |
804 | "i82557b", | |
805 | "i82559er", | |
806 | "rtl8139", | |
807 | "e1000", | |
808 | "pcnet", | |
809 | "virtio", | |
810 | NULL | |
811 | }; | |
812 | ||
9d07d757 PB |
813 | static const char * const pci_nic_names[] = { |
814 | "ne2k_pci", | |
815 | "i82551", | |
816 | "i82557b", | |
817 | "i82559er", | |
818 | "rtl8139", | |
819 | "e1000", | |
820 | "pcnet", | |
53c25cea | 821 | "virtio-net-pci", |
cb457d76 AL |
822 | NULL |
823 | }; | |
824 | ||
a41b2ff2 | 825 | /* Initialize a PCI NIC. */ |
33e66b86 | 826 | /* FIXME callers should check for failure, but don't */ |
5607c388 MA |
827 | PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, |
828 | const char *default_devaddr) | |
a41b2ff2 | 829 | { |
5607c388 | 830 | const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr; |
07caea31 MA |
831 | PCIBus *bus; |
832 | int devfn; | |
5607c388 | 833 | PCIDevice *pci_dev; |
9d07d757 | 834 | DeviceState *dev; |
cb457d76 AL |
835 | int i; |
836 | ||
07caea31 MA |
837 | i = qemu_find_nic_model(nd, pci_nic_models, default_model); |
838 | if (i < 0) | |
839 | return NULL; | |
840 | ||
841 | bus = pci_get_bus_devfn(&devfn, devaddr); | |
842 | if (!bus) { | |
843 | qemu_error("Invalid PCI device address %s for device %s\n", | |
844 | devaddr, pci_nic_names[i]); | |
845 | return NULL; | |
846 | } | |
847 | ||
499cf102 | 848 | pci_dev = pci_create(bus, devfn, pci_nic_names[i]); |
9ee05825 | 849 | dev = &pci_dev->qdev; |
dea7b3b9 MM |
850 | if (nd->name) |
851 | dev->id = qemu_strdup(nd->name); | |
1cc33683 | 852 | qdev_set_nic_properties(dev, nd); |
07caea31 MA |
853 | if (qdev_init(dev) < 0) |
854 | return NULL; | |
9ee05825 | 855 | return pci_dev; |
a41b2ff2 PB |
856 | } |
857 | ||
07caea31 MA |
858 | PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, |
859 | const char *default_devaddr) | |
860 | { | |
861 | PCIDevice *res; | |
862 | ||
863 | if (qemu_show_nic_models(nd->model, pci_nic_models)) | |
864 | exit(0); | |
865 | ||
866 | res = pci_nic_init(nd, default_model, default_devaddr); | |
867 | if (!res) | |
868 | exit(1); | |
869 | return res; | |
870 | } | |
871 | ||
80b3ada7 PB |
872 | typedef struct { |
873 | PCIDevice dev; | |
03587182 GH |
874 | PCIBus bus; |
875 | uint32_t vid; | |
876 | uint32_t did; | |
80b3ada7 PB |
877 | } PCIBridge; |
878 | ||
9596ebb7 | 879 | static void pci_bridge_write_config(PCIDevice *d, |
80b3ada7 PB |
880 | uint32_t address, uint32_t val, int len) |
881 | { | |
882 | PCIBridge *s = (PCIBridge *)d; | |
883 | ||
80b3ada7 | 884 | pci_default_write_config(d, address, val, len); |
03587182 | 885 | s->bus.bus_num = d->config[PCI_SECONDARY_BUS]; |
80b3ada7 PB |
886 | } |
887 | ||
3ae80618 AL |
888 | PCIBus *pci_find_bus(int bus_num) |
889 | { | |
890 | PCIBus *bus = first_bus; | |
891 | ||
892 | while (bus && bus->bus_num != bus_num) | |
893 | bus = bus->next; | |
894 | ||
895 | return bus; | |
896 | } | |
897 | ||
898 | PCIDevice *pci_find_device(int bus_num, int slot, int function) | |
899 | { | |
900 | PCIBus *bus = pci_find_bus(bus_num); | |
901 | ||
902 | if (!bus) | |
903 | return NULL; | |
904 | ||
905 | return bus->devices[PCI_DEVFN(slot, function)]; | |
906 | } | |
907 | ||
03587182 | 908 | static int pci_bridge_initfn(PCIDevice *dev) |
80b3ada7 | 909 | { |
03587182 | 910 | PCIBridge *s = DO_UPCAST(PCIBridge, dev, dev); |
480b9f24 | 911 | |
03587182 GH |
912 | pci_config_set_vendor_id(s->dev.config, s->vid); |
913 | pci_config_set_device_id(s->dev.config, s->did); | |
480b9f24 | 914 | |
74c01823 IY |
915 | /* TODO: intial value |
916 | * command register: | |
917 | * According to PCI bridge spec, after reset | |
918 | * bus master bit is off | |
919 | * memory space enable bit is off | |
920 | * According to manual (805-1251.pdf).(See abp_pbi.c for its links.) | |
921 | * the reset value should be zero unless the boot pin is tied high | |
922 | * (which is tru) and thus it should be PCI_COMMAND_MEMORY. | |
923 | * | |
924 | * For now, don't touch the value. | |
925 | * Later command register will be set to zero and apb_pci.c will | |
926 | * override the value. | |
927 | * Same for latency timer, and multi function bit of header type. | |
928 | */ | |
929 | pci_set_word(dev->config + PCI_COMMAND, | |
930 | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); | |
931 | ||
932 | pci_set_word(dev->config + PCI_STATUS, | |
933 | PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK); | |
934 | pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI); | |
935 | dev->config[PCI_LATENCY_TIMER] = 0x10; | |
936 | dev->config[PCI_HEADER_TYPE] = | |
937 | PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; | |
938 | pci_set_word(dev->config + PCI_SEC_STATUS, | |
939 | PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK); | |
03587182 GH |
940 | return 0; |
941 | } | |
80b3ada7 | 942 | |
03587182 GH |
943 | PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did, |
944 | pci_map_irq_fn map_irq, const char *name) | |
945 | { | |
946 | PCIDevice *dev; | |
947 | PCIBridge *s; | |
948 | ||
499cf102 | 949 | dev = pci_create(bus, devfn, "pci-bridge"); |
03587182 GH |
950 | qdev_prop_set_uint32(&dev->qdev, "vendorid", vid); |
951 | qdev_prop_set_uint32(&dev->qdev, "deviceid", did); | |
e23a1b33 | 952 | qdev_init_nofail(&dev->qdev); |
03587182 GH |
953 | |
954 | s = DO_UPCAST(PCIBridge, dev, dev); | |
955 | pci_register_secondary_bus(&s->bus, &s->dev, map_irq, name); | |
956 | return &s->bus; | |
80b3ada7 | 957 | } |
6b1b92d3 | 958 | |
81a322d4 | 959 | static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base) |
6b1b92d3 PB |
960 | { |
961 | PCIDevice *pci_dev = (PCIDevice *)qdev; | |
02e2da45 | 962 | PCIDeviceInfo *info = container_of(base, PCIDeviceInfo, qdev); |
6b1b92d3 | 963 | PCIBus *bus; |
ee995ffb | 964 | int devfn, rc; |
6b1b92d3 | 965 | |
02e2da45 | 966 | bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev)); |
ee6847d1 | 967 | devfn = pci_dev->devfn; |
16eaedf2 | 968 | pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn, |
0aab0d3a | 969 | info->config_read, info->config_write); |
6b1b92d3 | 970 | assert(pci_dev); |
ee995ffb GH |
971 | rc = info->init(pci_dev); |
972 | if (rc != 0) | |
973 | return rc; | |
974 | if (qdev->hotplugged) | |
975 | bus->hotplug(pci_dev, 1); | |
976 | return 0; | |
977 | } | |
978 | ||
979 | static int pci_unplug_device(DeviceState *qdev) | |
980 | { | |
981 | PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev); | |
982 | ||
983 | dev->bus->hotplug(dev, 0); | |
984 | return 0; | |
6b1b92d3 PB |
985 | } |
986 | ||
0aab0d3a | 987 | void pci_qdev_register(PCIDeviceInfo *info) |
6b1b92d3 | 988 | { |
02e2da45 | 989 | info->qdev.init = pci_qdev_init; |
ee995ffb | 990 | info->qdev.unplug = pci_unplug_device; |
a36a344d | 991 | info->qdev.exit = pci_unregister_device; |
10c4c98a | 992 | info->qdev.bus_info = &pci_bus_info; |
074f2fff | 993 | qdev_register(&info->qdev); |
6b1b92d3 PB |
994 | } |
995 | ||
0aab0d3a GH |
996 | void pci_qdev_register_many(PCIDeviceInfo *info) |
997 | { | |
998 | while (info->qdev.name) { | |
999 | pci_qdev_register(info); | |
1000 | info++; | |
1001 | } | |
1002 | } | |
1003 | ||
499cf102 | 1004 | PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name) |
6b1b92d3 PB |
1005 | { |
1006 | DeviceState *dev; | |
1007 | ||
02e2da45 | 1008 | dev = qdev_create(&bus->qbus, name); |
a6307b08 | 1009 | qdev_prop_set_uint32(dev, "addr", devfn); |
71077c1c GH |
1010 | return DO_UPCAST(PCIDevice, qdev, dev); |
1011 | } | |
6b1b92d3 | 1012 | |
71077c1c GH |
1013 | PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name) |
1014 | { | |
499cf102 | 1015 | PCIDevice *dev = pci_create(bus, devfn, name); |
e23a1b33 | 1016 | qdev_init_nofail(&dev->qdev); |
71077c1c | 1017 | return dev; |
6b1b92d3 | 1018 | } |
6f4cbd39 MT |
1019 | |
1020 | static int pci_find_space(PCIDevice *pdev, uint8_t size) | |
1021 | { | |
1022 | int offset = PCI_CONFIG_HEADER_SIZE; | |
1023 | int i; | |
1024 | for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i) | |
1025 | if (pdev->used[i]) | |
1026 | offset = i + 1; | |
1027 | else if (i - offset + 1 == size) | |
1028 | return offset; | |
1029 | return 0; | |
1030 | } | |
1031 | ||
1032 | static uint8_t pci_find_capability_list(PCIDevice *pdev, uint8_t cap_id, | |
1033 | uint8_t *prev_p) | |
1034 | { | |
1035 | uint8_t next, prev; | |
1036 | ||
1037 | if (!(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST)) | |
1038 | return 0; | |
1039 | ||
1040 | for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]); | |
1041 | prev = next + PCI_CAP_LIST_NEXT) | |
1042 | if (pdev->config[next + PCI_CAP_LIST_ID] == cap_id) | |
1043 | break; | |
1044 | ||
1045 | if (prev_p) | |
1046 | *prev_p = prev; | |
1047 | return next; | |
1048 | } | |
1049 | ||
1050 | /* Reserve space and add capability to the linked list in pci config space */ | |
1051 | int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size) | |
1052 | { | |
1053 | uint8_t offset = pci_find_space(pdev, size); | |
1054 | uint8_t *config = pdev->config + offset; | |
1055 | if (!offset) | |
1056 | return -ENOSPC; | |
1057 | config[PCI_CAP_LIST_ID] = cap_id; | |
1058 | config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST]; | |
1059 | pdev->config[PCI_CAPABILITY_LIST] = offset; | |
1060 | pdev->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST; | |
1061 | memset(pdev->used + offset, 0xFF, size); | |
1062 | /* Make capability read-only by default */ | |
1063 | memset(pdev->wmask + offset, 0, size); | |
bd4b65ee MT |
1064 | /* Check capability by default */ |
1065 | memset(pdev->cmask + offset, 0xFF, size); | |
6f4cbd39 MT |
1066 | return offset; |
1067 | } | |
1068 | ||
1069 | /* Unlink capability from the pci config space. */ | |
1070 | void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size) | |
1071 | { | |
1072 | uint8_t prev, offset = pci_find_capability_list(pdev, cap_id, &prev); | |
1073 | if (!offset) | |
1074 | return; | |
1075 | pdev->config[prev] = pdev->config[offset + PCI_CAP_LIST_NEXT]; | |
1076 | /* Make capability writeable again */ | |
1077 | memset(pdev->wmask + offset, 0xff, size); | |
bd4b65ee MT |
1078 | /* Clear cmask as device-specific registers can't be checked */ |
1079 | memset(pdev->cmask + offset, 0, size); | |
6f4cbd39 MT |
1080 | memset(pdev->used + offset, 0, size); |
1081 | ||
1082 | if (!pdev->config[PCI_CAPABILITY_LIST]) | |
1083 | pdev->config[PCI_STATUS] &= ~PCI_STATUS_CAP_LIST; | |
1084 | } | |
1085 | ||
1086 | /* Reserve space for capability at a known offset (to call after load). */ | |
1087 | void pci_reserve_capability(PCIDevice *pdev, uint8_t offset, uint8_t size) | |
1088 | { | |
1089 | memset(pdev->used + offset, 0xff, size); | |
1090 | } | |
1091 | ||
1092 | uint8_t pci_find_capability(PCIDevice *pdev, uint8_t cap_id) | |
1093 | { | |
1094 | return pci_find_capability_list(pdev, cap_id, NULL); | |
1095 | } | |
10c4c98a GH |
1096 | |
1097 | static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent) | |
1098 | { | |
1099 | PCIDevice *d = (PCIDevice *)dev; | |
1100 | const pci_class_desc *desc; | |
1101 | char ctxt[64]; | |
1102 | PCIIORegion *r; | |
1103 | int i, class; | |
1104 | ||
b0ff8eb2 | 1105 | class = pci_get_word(d->config + PCI_CLASS_DEVICE); |
10c4c98a GH |
1106 | desc = pci_class_descriptions; |
1107 | while (desc->desc && class != desc->class) | |
1108 | desc++; | |
1109 | if (desc->desc) { | |
1110 | snprintf(ctxt, sizeof(ctxt), "%s", desc->desc); | |
1111 | } else { | |
1112 | snprintf(ctxt, sizeof(ctxt), "Class %04x", class); | |
1113 | } | |
1114 | ||
1115 | monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, " | |
1116 | "pci id %04x:%04x (sub %04x:%04x)\n", | |
1117 | indent, "", ctxt, | |
2217dcff | 1118 | d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn), |
b0ff8eb2 IY |
1119 | pci_get_word(d->config + PCI_VENDOR_ID), |
1120 | pci_get_word(d->config + PCI_DEVICE_ID), | |
1121 | pci_get_word(d->config + PCI_SUBSYSTEM_VENDOR_ID), | |
1122 | pci_get_word(d->config + PCI_SUBSYSTEM_ID)); | |
10c4c98a GH |
1123 | for (i = 0; i < PCI_NUM_REGIONS; i++) { |
1124 | r = &d->io_regions[i]; | |
1125 | if (!r->size) | |
1126 | continue; | |
1127 | monitor_printf(mon, "%*sbar %d: %s at 0x%x [0x%x]\n", indent, "", | |
0392a017 | 1128 | i, r->type & PCI_BASE_ADDRESS_SPACE_IO ? "i/o" : "mem", |
10c4c98a GH |
1129 | r->addr, r->addr + r->size - 1); |
1130 | } | |
1131 | } | |
03587182 GH |
1132 | |
1133 | static PCIDeviceInfo bridge_info = { | |
1134 | .qdev.name = "pci-bridge", | |
1135 | .qdev.size = sizeof(PCIBridge), | |
1136 | .init = pci_bridge_initfn, | |
1137 | .config_write = pci_bridge_write_config, | |
1138 | .qdev.props = (Property[]) { | |
1139 | DEFINE_PROP_HEX32("vendorid", PCIBridge, vid, 0), | |
1140 | DEFINE_PROP_HEX32("deviceid", PCIBridge, did, 0), | |
1141 | DEFINE_PROP_END_OF_LIST(), | |
1142 | } | |
1143 | }; | |
1144 | ||
1145 | static void pci_register_devices(void) | |
1146 | { | |
1147 | pci_qdev_register(&bridge_info); | |
1148 | } | |
1149 | ||
1150 | device_init(pci_register_devices) |