aboutsummaryrefslogtreecommitdiff
path: root/hw/pci.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2009-06-30 14:12:08 +0200
committerPaul Brook <paul@codesourcery.com>2009-07-09 13:07:03 +0100
commit10c4c98ab7dc18169b37b76f6ea5e60ebe65222b (patch)
tree94b41a4a26b82720cc8695b66cedbcf135d68669 /hw/pci.c
parent0aab0d3a4a62505ab7e79ee0a67fe3f04f6dae23 (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.c53
1 files changed, 48 insertions, 5 deletions
diff --git a/hw/pci.c b/hw/pci.c
index e82965ff12..f4c749483e 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -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);
+ }
+}