[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] pci: PCIBus clean up.
From: |
Isaku Yamahata |
Subject: |
[Qemu-devel] [PATCH] pci: PCIBus clean up. |
Date: |
Thu, 18 Jun 2009 19:57:15 +0900 |
User-agent: |
Mutt/1.5.6i |
- use LIST_xxx macros for bus list.
- remove duplicated member in PCIDevice and PCIBus
because qdev layer tracks bus<->device relation.
- introduce helper function to get PCIDevice/PCIBus
Signed-off-by: Isaku Yamahata <address@hidden>
---
Changes
- rebased not to depend on pci callback patch.
- don't eliminate PCIBridge. Keep it
---
hw/pci-hotplug.c | 4 +-
hw/pci.c | 141 +++++++++++++++++++++++++++++++++++-------------------
hw/pci.h | 3 +-
3 files changed, 96 insertions(+), 52 deletions(-)
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 4d49c29..2d50b3b 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -158,8 +158,8 @@ void pci_device_hot_add(Monitor *mon, const char *pci_addr,
const char *type,
if (dev) {
qemu_system_device_hot_add(bus, PCI_SLOT(dev->devfn), 1);
monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
- 0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
- PCI_FUNC(dev->devfn));
+ 0, pci_bus_num(pci_get_parent_bus(dev)),
+ PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
} else
monitor_printf(mon, "failed to add %s\n", opts);
}
diff --git a/hw/pci.c b/hw/pci.c
index 0a738db..3ac73d2 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -40,8 +40,8 @@ struct PCIBus {
SetIRQFunc *low_set_irq;
qemu_irq *irq_opaque;
PCIDevice *devices[256];
- PCIDevice *parent_dev;
- PCIBus *next;
+ LIST_ENTRY(PCIBus) next;
+
/* 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;
@@ -54,7 +54,27 @@ static void pci_set_irq(void *opaque, int irq_num, int
level);
target_phys_addr_t pci_mem_base;
static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
-static PCIBus *first_bus;
+static LIST_HEAD(, PCIBus) first_bus;
+
+static PCIBus *qbus_to_pcibus(struct BusState *qbus)
+{
+ return container_of(qbus, PCIBus, qbus);
+}
+
+static PCIDevice *qdev_to_pcidev(struct DeviceState *qdev)
+{
+ return container_of(qdev, PCIDevice, qdev);
+}
+
+PCIBus *pci_get_parent_bus(PCIDevice *dev)
+{
+ return qbus_to_pcibus(dev->qdev.parent_bus);
+}
+
+PCIDevice *pci_bus_to_dev(PCIBus *bus)
+{
+ return qdev_to_pcidev(bus->qbus.parent);
+}
static void pcibus_save(QEMUFile *f, void *opaque)
{
@@ -102,8 +122,8 @@ PCIBus *pci_register_bus(DeviceState *parent, const char
*name,
bus->irq_opaque = pic;
bus->devfn_min = devfn_min;
bus->nirq = nirq;
- bus->next = first_bus;
- first_bus = bus;
+
+ LIST_INSERT_HEAD(&first_bus, bus, next);
register_savevm("PCIBUS", nbus++, 1, pcibus_save, pcibus_load, bus);
return bus;
}
@@ -111,11 +131,19 @@ PCIBus *pci_register_bus(DeviceState *parent, const char
*name,
static PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn
map_irq)
{
PCIBus *bus;
- bus = qemu_mallocz(sizeof(PCIBus));
+ PCIBus *parent_bus;
+ int devfn_min = qdev_get_prop_int(&dev->qdev, "devfn_min", 0);
+ int nirq = qdev_get_prop_int(&dev->qdev, "nirq", 0);
+
+ bus = FROM_QBUS(PCIBus, qbus_create(BUS_TYPE_PCI,
+ sizeof(PCIBus) + (nirq * sizeof(int)),
+ &dev->qdev, "pci"));
bus->map_irq = map_irq;
- bus->parent_dev = dev;
- bus->next = dev->bus->next;
- dev->bus->next = bus;
+ bus->devfn_min = devfn_min;
+ bus->nirq = nirq;
+
+ parent_bus = pci_get_parent_bus(dev);
+ LIST_INSERT_AFTER(parent_bus, bus, next);
return bus;
}
@@ -252,7 +280,6 @@ static PCIDevice *do_pci_register_device(PCIDevice
*pci_dev, PCIBus *bus,
return NULL;
found: ;
}
- pci_dev->bus = bus;
pci_dev->devfn = devfn;
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
@@ -317,7 +344,7 @@ int pci_unregister_device(PCIDevice *pci_dev)
pci_unregister_io_regions(pci_dev);
qemu_free_irqs(pci_dev->irq);
- pci_dev->bus->devices[pci_dev->devfn] = NULL;
+ pci_get_parent_bus(pci_dev)->devices[pci_dev->devfn] = NULL;
qdev_free(&pci_dev->qdev);
return 0;
}
@@ -571,6 +598,16 @@ void pci_default_write_config(PCIDevice *d,
}
}
+static PCIBus *pci_find_bus_from(PCIBus *from, int bus_num)
+{
+ PCIBus *s = from;
+
+ while (s && s->bus_num != bus_num)
+ s = LIST_NEXT(s, next);
+
+ return s;
+}
+
void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
{
PCIBus *s = opaque;
@@ -582,8 +619,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t
val, int len)
addr, val, len);
#endif
bus_num = (addr >> 16) & 0xff;
- while (s && s->bus_num != bus_num)
- s = s->next;
+ s = pci_find_bus_from(s, bus_num);
if (!s)
return;
pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -605,8 +641,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
uint32_t val;
bus_num = (addr >> 16) & 0xff;
- while (s && s->bus_num != bus_num)
- s= s->next;
+ s = pci_find_bus_from(s, bus_num);
if (!s)
goto fail;
pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -656,11 +691,11 @@ static void pci_set_irq(void *opaque, int irq_num, int
level)
pci_dev->irq_state[irq_num] = level;
for (;;) {
- bus = pci_dev->bus;
+ bus = pci_get_parent_bus(pci_dev);
irq_num = bus->map_irq(pci_dev, irq_num);
if (bus->set_irq)
break;
- pci_dev = bus->parent_dev;
+ pci_dev = pci_bus_to_dev(bus);
}
bus->irq_count[irq_num] += change;
bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
@@ -722,7 +757,8 @@ static void pci_info_device(PCIDevice *d)
const pci_class_desc *desc;
monitor_printf(mon, " Bus %2d, device %3d, function %d:\n",
- d->bus->bus_num, d->devfn >> 3, d->devfn & 7);
+ pci_get_parent_bus(d)->bus_num,
+ d->devfn >> 3, d->devfn & 7);
class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
monitor_printf(mon, " ");
desc = pci_class_descriptions;
@@ -764,12 +800,11 @@ static void pci_info_device(PCIDevice *d)
void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
{
- PCIBus *bus = first_bus;
+ PCIBus *bus;
PCIDevice *d;
int devfn;
- while (bus && bus->bus_num != bus_num)
- bus = bus->next;
+ bus = pci_find_bus_from(LIST_FIRST(&first_bus), bus_num);
if (bus) {
for(devfn = 0; devfn < 256; devfn++) {
d = bus->devices[devfn];
@@ -833,21 +868,31 @@ PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int
devfn,
typedef struct {
PCIDevice dev;
- PCIBus *bus;
} PCIBridge;
+static PCIBridge *pcidev_to_pcibr(PCIDevice *d)
+{
+ return container_of(d, PCIBridge, dev);
+}
+
+static PCIBus *pci_bridge_get_secbus(PCIBridge *bridge)
+{
+ /* assuming only one bus is registered */
+ return qbus_to_pcibus(LIST_FIRST(&bridge->dev.qdev.child_bus));
+}
+
static void pci_bridge_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
- PCIBridge *s = (PCIBridge *)d;
-
if (address == 0x19 || (address == 0x18 && len > 1)) {
+ PCIBridge *bridge = pcidev_to_pcibr(d);
+ PCIBus *bus = pci_bridge_get_secbus(bridge);
if (address == 0x19)
- s->bus->bus_num = val & 0xff;
+ bus->bus_num = val & 0xff;
else
- s->bus->bus_num = (val >> 8) & 0xff;
+ bus->bus_num = (val >> 8) & 0xff;
#if defined(DEBUG_PCI)
- printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
+ printf ("pci-bridge: %s: Assigned bus %d\n", d->name, bus->bus_num);
#endif
}
pci_default_write_config(d, address, val, len);
@@ -855,12 +900,7 @@ static void pci_bridge_write_config(PCIDevice *d,
PCIBus *pci_find_bus(int bus_num)
{
- PCIBus *bus = first_bus;
-
- while (bus && bus->bus_num != bus_num)
- bus = bus->next;
-
- return bus;
+ return pci_find_bus_from(LIST_FIRST(&first_bus), bus_num);
}
PCIDevice *pci_find_device(int bus_num, int slot, int function)
@@ -877,26 +917,29 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t
vid, uint16_t did,
pci_map_irq_fn map_irq, const char *name)
{
PCIBridge *s;
+ PCIDevice *d;
+ uint8_t *pci_conf;
+
s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
devfn, NULL, pci_bridge_write_config);
-
- pci_config_set_vendor_id(s->dev.config, vid);
- pci_config_set_device_id(s->dev.config, did);
-
- s->dev.config[0x04] = 0x06; // command = bus master, pci mem
- s->dev.config[0x05] = 0x00;
- s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
- s->dev.config[0x07] = 0x00; // status = fast devsel
- s->dev.config[0x08] = 0x00; // revision
- s->dev.config[0x09] = 0x00; // programming i/f
- pci_config_set_class(s->dev.config, PCI_CLASS_BRIDGE_PCI);
- s->dev.config[0x0D] = 0x10; // latency_timer
- s->dev.config[PCI_HEADER_TYPE] =
+ d = &s->dev;
+ pci_conf = d->config;
+ pci_config_set_vendor_id(pci_conf, vid);
+ pci_config_set_device_id(pci_conf, did);
+
+ pci_conf[0x04] = 0x06; // command = bus master, pci mem
+ pci_conf[0x05] = 0x00;
+ pci_conf[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
+ pci_conf[0x07] = 0x00; // status = fast devsel
+ pci_conf[0x08] = 0x00; // revision
+ pci_conf[0x09] = 0x00; // programming i/f
+ pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_PCI);
+ pci_conf[0x0D] = 0x10; // latency_timer
+ pci_conf[PCI_HEADER_TYPE] =
PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
- s->dev.config[0x1E] = 0xa0; // secondary status
+ pci_conf[0x1E] = 0xa0; // secondary status
- s->bus = pci_register_secondary_bus(&s->dev, map_irq);
- return s->bus;
+ return pci_register_secondary_bus(d, map_irq);
}
typedef struct {
diff --git a/hw/pci.h b/hw/pci.h
index fcca526..0c0e725 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -143,7 +143,6 @@ struct PCIDevice {
uint8_t config[256];
/* the following fields are read only */
- PCIBus *bus;
int devfn;
char name[64];
PCIIORegion io_regions[PCI_NUM_REGIONS];
@@ -198,6 +197,8 @@ int pci_assign_devaddr(const char *addr, int *domp, int
*busp, unsigned *slotp);
void pci_info(Monitor *mon);
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
pci_map_irq_fn map_irq, const char *name);
+PCIBus *pci_get_parent_bus(PCIDevice *dev);
+PCIDevice *pci_bus_to_dev(PCIBus *bus);
static inline void
pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val)
--
1.6.0.2
--
yamahata
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] pci: PCIBus clean up.,
Isaku Yamahata <=