[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 5/7] pci: PCIBus clean up.
From: |
Isaku Yamahata |
Subject: |
[Qemu-devel] [PATCH 5/7] pci: PCIBus clean up. |
Date: |
Tue, 2 Jun 2009 15:42:48 +0900 |
- use LIST_xxx macros for bus list.
- remove duplicated member in PCIDevice and PCIBus
- introduce helper function to get PCIDevice/PCIBus
Signed-off-by: Isaku Yamahata <address@hidden>
---
hw/pci-hotplug.c | 4 +-
hw/pci.c | 141 +++++++++++++++++++++++++++++++++---------------------
hw/pci.h | 3 +-
3 files changed, 91 insertions(+), 57 deletions(-)
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 4d18ea2..eec65f2 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 2c8dece..602eeb0 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -41,8 +41,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;
@@ -55,7 +55,27 @@ 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 int pci_irq_index;
-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)
{
@@ -103,8 +123,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;
}
@@ -112,11 +132,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;
}
@@ -373,7 +401,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));
@@ -454,7 +481,7 @@ int pci_unregister_device(PCIDevice *pci_dev)
qemu_free_irqs(pci_dev->irq);
pci_irq_index--;
- 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;
}
@@ -645,6 +672,16 @@ void pci_default_write_config(PCIDevice *d,
(callback[i])(d, written[i], mask[i]);
}
+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;
@@ -656,8 +693,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];
@@ -679,8 +715,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];
@@ -730,11 +765,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);
@@ -796,7 +831,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;
@@ -838,12 +874,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];
@@ -905,19 +940,9 @@ PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int
devfn,
return NULL;
}
-typedef struct {
- PCIDevice dev;
- PCIBus *bus;
-} PCIBridge;
-
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)
@@ -930,11 +955,17 @@ PCIDevice *pci_find_device(int bus_num, int slot, int
function)
return bus->devices[PCI_DEVFN(slot, function)];
}
+static PCIBus *pci_bridge_get_secbus(PCIDevice *d)
+{
+ /* assuming only one bus is registered */
+ return qbus_to_pcibus(LIST_FIRST(&d->qdev.child_bus));
+}
+
static void pci_conf_secondary_bus_changed(PCIDevice *d,
uint32_t written, uint32_t mask)
{
- PCIBridge *s = (PCIBridge*) d;
- s->bus->bus_num = s->dev.config[PCI_SECONDARY_BUS];
+ PCIBus *bus = pci_bridge_get_secbus(d);
+ bus->bus_num = d->config[PCI_SECONDARY_BUS];
}
static void pci_conf_init_type_01_default(struct PCIConfigReg *config_regs)
@@ -1024,28 +1055,30 @@ static void pci_conf_init_type_01_default(struct
PCIConfigReg *config_regs)
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;
- s = (PCIBridge *)pci_register_device_confreg(bus, name, sizeof(PCIBridge),
- devfn, NULL, NULL,
-
pci_conf_init_type_01_default);
-
- 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] =
+ PCIDevice *d;
+ uint8_t *pci_conf;
+
+ d = pci_register_device_confreg(bus, name, sizeof(PCIDevice),
+ devfn, NULL, NULL,
+ pci_conf_init_type_01_default);
+
+ 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 cdaceda..c649442 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -242,7 +242,6 @@ struct PCIDevice {
struct PCIConfigReg config_regs[PCI_CONFIG_SPACE_SIZE];
/* the following fields are read only */
- PCIBus *bus;
int devfn;
char name[64];
PCIIORegion io_regions[PCI_NUM_REGIONS];
@@ -314,6 +313,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
- [Qemu-devel] [PATCH 2/7] qemu: make default_write_config use mask table, (continued)
- [Qemu-devel] [PATCH 2/7] qemu: make default_write_config use mask table, Isaku Yamahata, 2009/06/02
- [Qemu-devel] [PATCH 3/7] pci: pci_default_config_write() clean up., Isaku Yamahata, 2009/06/02
- Re: [Qemu-devel] Re: [PATCH 3/7] pci: pci_default_config_write() clean up., Michael S. Tsirkin, 2009/06/10
- Re: [Qemu-devel] Re: [PATCH 3/7] pci: pci_default_config_write() clean up., Isaku Yamahata, 2009/06/15
- Re: [Qemu-devel] Re: [PATCH 3/7] pci: pci_default_config_write() clean up., Michael S. Tsirkin, 2009/06/15
[Qemu-devel] [PATCH 5/7] pci: PCIBus clean up.,
Isaku Yamahata <=
[Qemu-devel] [PATCH 4/7] pci/config: convert pci configuration space handler to use callback., Isaku Yamahata, 2009/06/02