diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2009-06-30 14:12:08 +0200 |
---|---|---|
committer | Paul Brook <paul@codesourcery.com> | 2009-07-09 13:07:03 +0100 |
commit | 10c4c98ab7dc18169b37b76f6ea5e60ebe65222b (patch) | |
tree | 94b41a4a26b82720cc8695b66cedbcf135d68669 /hw/pci.c | |
parent | 0aab0d3a4a62505ab7e79ee0a67fe3f04f6dae23 (diff) |
qdev: replace bus_type enum with bus_info struct.
BusInfo is filled with name and size (pretty much like I did for
DeviceInfo as well). There is also a function pointer to print
bus-specific device information to the monitor. sysbus is hooked
up there, I've also added a print function for PCI.
Device creation is slightly modified as well: The device type search
loop now also checks the bus type while scanning the list instead of
complaining thereafter in case of a mismatch. This effectively gives
each bus a private namespace for device names.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Paul Brook <paul@codesourcery.com>
Diffstat (limited to 'hw/pci.c')
-rw-r--r-- | hw/pci.c | 53 |
1 files changed, 48 insertions, 5 deletions
@@ -45,7 +45,15 @@ struct PCIBus { /* The bus IRQ state is the logical OR of the connected devices. Keep a count of the number of devices with raised IRQs. */ int nirq; - int irq_count[]; + int *irq_count; +}; + +static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent); + +static struct BusInfo pci_bus_info = { + .name = "PCI", + .size = sizeof(PCIBus), + .print_dev = pcibus_dev_print, }; static void pci_update_mappings(PCIDevice *d); @@ -109,14 +117,13 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name, PCIBus *bus; static int nbus = 0; - bus = FROM_QBUS(PCIBus, qbus_create(BUS_TYPE_PCI, - sizeof(PCIBus) + (nirq * sizeof(int)), - parent, name)); + bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, parent, name)); bus->set_irq = set_irq; bus->map_irq = map_irq; bus->irq_opaque = pic; bus->devfn_min = devfn_min; bus->nirq = nirq; + bus->irq_count = qemu_malloc(nirq * sizeof(bus->irq_count[0])); bus->next = first_bus; first_bus = bus; register_savevm("PCIBUS", nbus++, 1, pcibus_save, pcibus_load, bus); @@ -892,7 +899,7 @@ static void pci_qdev_init(DeviceState *qdev, DeviceInfo *base) void pci_qdev_register(PCIDeviceInfo *info) { info->qdev.init = pci_qdev_init; - info->qdev.bus_type = BUS_TYPE_PCI; + info->qdev.bus_info = &pci_bus_info; qdev_register(&info->qdev); } @@ -991,3 +998,39 @@ uint8_t pci_find_capability(PCIDevice *pdev, uint8_t cap_id) { return pci_find_capability_list(pdev, cap_id, NULL); } + +static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent) +{ + PCIDevice *d = (PCIDevice *)dev; + const pci_class_desc *desc; + char ctxt[64]; + PCIIORegion *r; + int i, class; + + class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE))); + desc = pci_class_descriptions; + while (desc->desc && class != desc->class) + desc++; + if (desc->desc) { + snprintf(ctxt, sizeof(ctxt), "%s", desc->desc); + } else { + snprintf(ctxt, sizeof(ctxt), "Class %04x", class); + } + + monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, " + "pci id %04x:%04x (sub %04x:%04x)\n", + indent, "", ctxt, + d->bus->bus_num, d->devfn >> 3, d->devfn & 7, + le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))), + le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))), + le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_VENDOR_ID))), + le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_ID)))); + for (i = 0; i < PCI_NUM_REGIONS; i++) { + r = &d->io_regions[i]; + if (!r->size) + continue; + monitor_printf(mon, "%*sbar %d: %s at 0x%x [0x%x]\n", indent, "", + i, r->type & PCI_ADDRESS_SPACE_IO ? "i/o" : "mem", + r->addr, r->addr + r->size - 1); + } +} |