qemu-devel
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]