[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/2] pci/brdige qdevfy.
From: |
Isaku Yamahata |
Subject: |
[Qemu-devel] [PATCH 2/2] pci/brdige qdevfy. |
Date: |
Fri, 19 Jun 2009 10:57:46 +0900 |
pci/brdige qdevfy.
Signed-off-by: Isaku Yamahata <address@hidden>
---
Changes
- use PCIBridge
- catch up DeviceInfo change, name, size.
---
hw/apb_pci.c | 12 +++---
hw/pci.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++----------
hw/pci.h | 20 ++++++++--
hw/pci_ids.h | 2 +
4 files changed, 125 insertions(+), 30 deletions(-)
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index b63ccd1..3fb7a92 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -266,11 +266,11 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
/* APB secondary busses */
- *bus2 = pci_bridge_init(s->bus, 8, PCI_VENDOR_ID_SUN,
- PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
- "Advanced PCI Bus secondary bridge 1");
- *bus3 = pci_bridge_init(s->bus, 9, PCI_VENDOR_ID_SUN,
- PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
- "Advanced PCI Bus secondary bridge 2");
+ *bus2 = pci_bridge_create_simple(s->bus, 8, PCI_VENDOR_ID_SUN,
+ PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
+ "Advanced PCI Bus secondary bridge 1");
+ *bus3 = pci_bridge_create_simple(s->bus, 9, PCI_VENDOR_ID_SUN,
+ PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
+ "Advanced PCI Bus secondary bridge 2");
return s->bus;
}
diff --git a/hw/pci.c b/hw/pci.c
index 3ac73d2..def27c7 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -128,25 +128,29 @@ PCIBus *pci_register_bus(DeviceState *parent, const char
*name,
return bus;
}
-static PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn
map_irq)
+/* XXX qemu_irq, nirq */
+static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
+ int bus_num, int devfn_min, int nirq)
{
PCIBus *bus;
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->bus_num = bus_num;
bus->devfn_min = devfn_min;
- bus->nirq = nirq;
parent_bus = pci_get_parent_bus(dev);
LIST_INSERT_AFTER(parent_bus, bus, next);
return bus;
}
+void pci_bridge_set_map_irq(PCIBus *bus, pci_map_irq_fn map_irq)
+{
+ bus->map_irq = map_irq;
+}
+
int pci_bus_num(PCIBus *s)
{
return s->bus_num;
@@ -866,15 +870,17 @@ PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int
devfn,
return NULL;
}
-typedef struct {
- PCIDevice dev;
-} PCIBridge;
-
static PCIBridge *pcidev_to_pcibr(PCIDevice *d)
{
return container_of(d, PCIBridge, dev);
}
+static PCIBridge *qdev_to_pcibr(struct DeviceState *qdev)
+{
+ PCIDevice *d = qdev_to_pcidev(qdev);
+ return pcidev_to_pcibr(d);
+}
+
static PCIBus *pci_bridge_get_secbus(PCIBridge *bridge)
{
/* assuming only one bus is registered */
@@ -913,20 +919,32 @@ PCIDevice *pci_find_device(int bus_num, int slot, int
function)
return bus->devices[PCI_DEVFN(slot, function)];
}
-PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
- pci_map_irq_fn map_irq, const char *name)
+typedef struct {
+ DeviceInfo qdev;
+ pcibr_qdev_initfn init;
+} PCIBridgeInfo;
+
+static void pci_bridge_qdev_init(DeviceState *qdev, DeviceInfo *base)
{
- PCIBridge *s;
- PCIDevice *d;
+ PCIBridge *pci_br = qdev_to_pcibr(qdev);
+ PCIDevice *pci_dev = &pci_br->dev;
+ PCIBridgeInfo *info = container_of(base, PCIBridgeInfo, qdev);
+
+ int devfn = qdev_get_prop_int(qdev, "devfn", -1);
+ int sec_bus = qdev_get_prop_int(qdev, "sec_bus", 0);
+ int sub_bus = qdev_get_prop_int(qdev, "sub_bus", sec_bus);
+ int devfn_min = qdev_get_prop_int(qdev, "devfn_min", 0);
+ int nirq = qdev_get_prop_int(qdev, "nirq", 0);
+ char *pci_name = qdev_get_prop_ptr(qdev, "pci_name");
+
uint8_t *pci_conf;
- s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
- devfn, NULL, pci_bridge_write_config);
- d = &s->dev;
- pci_conf = d->config;
- pci_config_set_vendor_id(pci_conf, vid);
- pci_config_set_device_id(pci_conf, did);
+ assert(sec_bus <= sub_bus);
+ pci_dev = do_pci_register_device(pci_dev, pci_get_parent_bus(pci_dev),
+ pci_name, devfn, NULL,
+ pci_bridge_write_config);
+ pci_conf = pci_dev->config;
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
@@ -937,9 +955,72 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t
vid, uint16_t did,
pci_conf[0x0D] = 0x10; // latency_timer
pci_conf[PCI_HEADER_TYPE] =
PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
+ pci_conf[0x18] = pci_get_parent_bus(pci_dev)->bus_num;// primary bus number
+ pci_conf[0x19] = sec_bus; // secondary bus number
+ pci_conf[0x1A] = sub_bus; // subordinate bus number
pci_conf[0x1E] = 0xa0; // secondary status
- return pci_register_secondary_bus(d, map_irq);
+ pci_register_secondary_bus(pci_dev, sec_bus, devfn_min, nirq);
+
+ /* vid/did, map_irq will be set */
+ info->init(pci_br);
+}
+
+void pci_bridge_qdev_register(const char* name, int size,
+ pcibr_qdev_initfn init)
+{
+ PCIBridgeInfo *info;
+
+ assert(size >= sizeof(PCIBridge));
+ info = qemu_mallocz(sizeof(*info));
+ info->init = init;
+ info->qdev.name = name;
+ info->qdev.size = size;
+ info->qdev.init = pci_bridge_qdev_init;
+ info->qdev.bus_type = BUS_TYPE_PCI;
+
+ qdev_register(&info->qdev);
+}
+
+/* for compat */
+#define PCI_BRIDGE_DEFAULT "default PCI to PCI bridge"
+static void pci_bridge_default_qdev_init(PCIBridge *br)
+{
+ /* nothing */
+}
+
+static void pci_bridge_register_device(void)
+{
+ pci_bridge_qdev_register(PCI_BRIDGE_DEFAULT,
+ sizeof(PCIBridge), pci_bridge_default_qdev_init);
+}
+device_init(pci_bridge_register_device);
+
+PCIBus *pci_bridge_create_simple(PCIBus *bus, int devfn, uint16_t vid,
+ uint16_t did, pci_map_irq_fn map_irq,
+ const char *pci_name)
+{
+ DeviceState *qdev;
+ uint8_t* pci_conf;
+ PCIDevice *d;
+ PCIBus *b;
+ char *pci_name_dup = qemu_strdup(pci_name); /* XXX:leak */
+
+ qdev = qdev_create(&bus->qbus, PCI_BRIDGE_DEFAULT);
+
+ qdev_set_prop_int(qdev, "devfn", devfn);
+ qdev_set_prop_ptr(qdev, "pci_name", pci_name_dup);
+
+ qdev_init(qdev);
+
+ d = qdev_to_pcidev(qdev);
+ pci_conf = d->config;
+ pci_config_set_vendor_id(pci_conf, vid);
+ pci_config_set_device_id(pci_conf, did);
+
+ b = pci_get_parent_bus(d);
+ pci_bridge_set_map_irq(b, map_irq);
+ return b;
}
typedef struct {
diff --git a/hw/pci.h b/hw/pci.h
index 0c0e725..c720d2f 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -190,15 +190,13 @@ int pci_bus_num(PCIBus *s);
void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
PCIBus *pci_find_bus(int bus_num);
PCIDevice *pci_find_device(int bus_num, int slot, int function);
+PCIBus *pci_get_parent_bus(PCIDevice *dev);
+PCIDevice *pci_bus_to_dev(PCIBus *bus);
int pci_read_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp);
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)
@@ -223,6 +221,20 @@ void pci_qdev_register(const char *name, int size,
pci_qdev_initfn init);
PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
+typedef struct {
+ PCIDevice dev;
+} PCIBridge;
+
+typedef void (*pcibr_qdev_initfn)(PCIBridge *br);
+void pci_bridge_qdev_register(const char* name, int size,
+ pcibr_qdev_initfn init);
+
+void pci_bridge_set_map_irq(PCIBus *bus, pci_map_irq_fn map_irq);
+
+PCIBus *pci_bridge_create_simple(PCIBus *bus, int devfn, uint16_t vid,
+ uint16_t did, pci_map_irq_fn map_irq,
+ const char *pci_name);
+
/* lsi53c895a.c */
#define LSI_MAX_DEVS 7
void lsi_scsi_attach(DeviceState *host, BlockDriverState *bd, int id);
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index 3afe674..d91897d 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -95,3 +95,5 @@
#define PCI_DEVICE_ID_INTEL_82371AB 0x7111
#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112
#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
+
+#define PCI_VENDOR_ID_INVALID 0xffff
--
1.6.0.2