qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 6/7] pci/brdige qdevfy.


From: Isaku Yamahata
Subject: [Qemu-devel] [PATCH 6/7] pci/brdige qdevfy.
Date: Tue, 2 Jun 2009 15:42:49 +0900

pci/brdige qdevfy.

Signed-off-by: Isaku Yamahata <address@hidden>
---
 hw/apb_pci.c |   12 +++---
 hw/pci.c     |  106 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 hw/pci.h     |   15 ++++++--
 hw/pci_ids.h |    2 +
 4 files changed, 109 insertions(+), 26 deletions(-)

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index dac5cd3..e85e28c 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 602eeb0..0ffdfef 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -129,25 +129,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;
@@ -1052,20 +1056,31 @@ static void pci_conf_init_type_01_default(struct 
PCIConfigReg *config_regs)
         pci_conf_initb(config_regs, addr, NULL, ~0);
 }
 
-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;
+    pci_qdev_initfn init;
+} PCIBridgeInfo;
+
+static void pci_bridge_qdev_init(DeviceState *qdev, DeviceInfo *base)
 {
-    PCIDevice *d;
-    uint8_t *pci_conf;
+    PCIDevice *pci_dev = qdev_to_pcidev(qdev);
+    PCIBridgeInfo *info = container_of(base, PCIBridgeInfo, qdev);
 
-    d = pci_register_device_confreg(bus, name, sizeof(PCIDevice),
-                                    devfn, NULL, NULL,
-                                    pci_conf_init_type_01_default);
+    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");
 
-    pci_conf = d->config;
-    pci_config_set_vendor_id(pci_conf, vid);
-    pci_config_set_device_id(pci_conf, did);
+    uint8_t *pci_conf;
+
+    assert(sec_bus <= sub_bus);
+    pci_dev = do_pci_register_device(pci_dev, pci_get_parent_bus(pci_dev),
+                                     pci_name, devfn, NULL, NULL,
+                                     pci_conf_init_type_01_default);
 
+    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
@@ -1076,9 +1091,68 @@ 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_dev);
+}
+
+void pci_bridge_qdev_register(const char* name, int size, pci_qdev_initfn init)
+{
+    PCIBridgeInfo *info;
+
+    info = qemu_mallocz(sizeof(*info));
+    info->init = init;
+    info->qdev.init = pci_bridge_qdev_init;
+    info->qdev.bus_type = BUS_TYPE_PCI;
+
+    qdev_register(name, size, &info->qdev);
+}
+
+/* for compat */
+#define PCI_BRIDGE_DEFAULT      "default PCI to PCI bridge"
+static void pci_bridge_default_qdev_init(PCIDevice *dev)
+{
+    /* nothing */
+}
+
+static void pci_brdige_register_device(void)
+{
+    pci_bridge_qdev_register(PCI_BRIDGE_DEFAULT,
+                             sizeof(PCIDevice), pci_bridge_default_qdev_init);
+}
+device_init(pci_brdige_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 c649442..76f3f28 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -306,15 +306,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)
@@ -339,6 +337,15 @@ void pci_qdev_register(const char *name, int size, 
pci_qdev_initfn init);
 
 PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
 
+void pci_bridge_qdev_register(const char* name, int size,
+                              pci_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 427fcd5..7bc4853 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -93,3 +93,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]