This allows SeaBIOS to retrieve MCFG base and size when it initializes
pxb host bridges.

A backlink to PXBPCIEHost is added in PXBDev to achieve above goal

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 hw/pci-bridge/pci_expander_bridge.c         | 55 +++++++++++++++++++++++++++++
 include/hw/pci-bridge/pci_expander_bridge.h |  1 +
 2 files changed, 56 insertions(+)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index d28a64c..c685c75 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -49,11 +49,18 @@ typedef struct PXBBus {
 #define PROP_PXB_PCIE_MAX_BUS "max_bus"
 #define PROP_PXB_NUMA_NODE "numa_node"
 
+typedef struct PXBPCIEHost PXBPCIEHost;
+typedef struct PXBDev PXBDev;
+
 typedef struct PXBDev {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
 
+    /* backlink to PXBPCIEHost, this makes it easier to get
+     * mcfg properties in pxb-pcie-host bridge */
+    PXBPCIEHost *pxbhost;
+
     uint32_t domain_nr; /* PCI domain number, non-zero means separate domain */
     uint8_t max_bus;    /* max bus number to use(including this one) */
     uint8_t bus_nr;
@@ -350,9 +357,15 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool 
pcie, Error **errp)
     if (pcie) {
         g_assert (pxb->max_bus >= pxb->bus_nr);
         ds = qdev_create(NULL, TYPE_PXB_PCIE_HOST);
+        /* attach it under /machine, so that we can resolve a valid path in
+         * object_property_set_link below */
+        object_property_add_child(qdev_get_machine(), "pxb-pcie-host[*]", 
OBJECT(ds), NULL);
 
+        /* set link and backlink between PXBPCIEHost and PXBDev */
         object_property_set_link(OBJECT(ds), OBJECT(pxb),
                                  PROP_PXB_PCIE_DEV, errp);
+        object_property_set_link(OBJECT(pxb), OBJECT(ds),
+                                 PROP_PXB_PCIE_HOST, errp);
 
         /* will be overwritten by firmware, but kept for readability */
         qdev_prop_set_uint64(ds, PCIE_HOST_MCFG_BASE,
@@ -421,6 +434,36 @@ static void pxb_dev_exitfn(PCIDevice *pci_dev)
     pxb_dev_list = g_list_remove(pxb_dev_list, pxb);
 }
 
+static uint32_t pxb_pcie_config_read(PCIDevice *d, uint32_t address, int len)
+{
+    PXBDev *pxb = convert_to_pxb(d);
+    uint32_t val;
+    Object *host;
+
+   switch (address) {
+    case MCH_HOST_BRIDGE_PCIEXBAR:
+        host = object_property_get_link(OBJECT(pxb), PROP_PXB_PCIE_HOST, NULL);
+        assert(host);
+        val = object_property_get_uint(host, PCIE_HOST_MCFG_BASE, NULL) & 
0xFFFFFFFF;
+        break;
+    case MCH_HOST_BRIDGE_PCIEXBAR + 4:
+        host = object_property_get_link(OBJECT(pxb), PROP_PXB_PCIE_HOST, NULL);
+        assert(host);
+        val = (object_property_get_uint(host, PCIE_HOST_MCFG_BASE, NULL) >> 
32) & 0xFFFFFFFF;
+        break;
+    case MCH_HOST_BRIDGE_PCIEXBAR + 8:  // Fix me!
+        host = object_property_get_link(OBJECT(pxb), PROP_PXB_PCIE_HOST, NULL);
+        assert(host);
+        val = object_property_get_uint(host, PCIE_HOST_MCFG_SIZE, NULL) & 
0xFFFFFFFF;
+        break;
+    default:
+        val = pci_default_read_config(d, address, len);
+        break;
+    }
+
+    return val;
+}
+
 static Property pxb_dev_properties[] = {
     /* Note: 0 is not a legal PXB bus number. */
     DEFINE_PROP_UINT8(PROP_PXB_BUS_NR, PXBDev, bus_nr, 0),
@@ -455,6 +498,16 @@ static void pxb_dev_class_init(ObjectClass *klass, void 
*data)
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 }
 
+static void pxb_pcie_dev_initfn(Object *obj)
+{
+    PXBDev *pxb = PXB_PCIE_DEV(obj);
+
+    /* Add backlink to pxb-pcie-host */
+    object_property_add_link(obj, PROP_PXB_PCIE_HOST, TYPE_PXB_PCIE_HOST,
+                         (Object **)&pxb->pxbhost,
+                         qdev_prop_allow_set_link_before_realize, 0, NULL);
+}
+
 static const TypeInfo pxb_dev_info = {
     .name          = TYPE_PXB_DEVICE,
     .parent        = TYPE_PCI_DEVICE,
@@ -486,6 +539,7 @@ static void pxb_pcie_dev_class_init(ObjectClass *klass, 
void *data)
 
     k->realize = pxb_pcie_dev_realize;
     k->exit = pxb_dev_exitfn;
+    k->config_read = pxb_pcie_config_read;
     k->vendor_id = PCI_VENDOR_ID_REDHAT;
     k->device_id = PCI_DEVICE_ID_REDHAT_PXB_PCIE;
     k->class_id = PCI_CLASS_BRIDGE_HOST;
@@ -500,6 +554,7 @@ static const TypeInfo pxb_pcie_dev_info = {
     .name          = TYPE_PXB_PCIE_DEVICE,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PXBDev),
+    .instance_init = pxb_pcie_dev_initfn,
     .class_init    = pxb_pcie_dev_class_init,
     .interfaces = (InterfaceInfo[]) {
         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
diff --git a/include/hw/pci-bridge/pci_expander_bridge.h 
b/include/hw/pci-bridge/pci_expander_bridge.h
index 870c4cd..1119210 100644
--- a/include/hw/pci-bridge/pci_expander_bridge.h
+++ b/include/hw/pci-bridge/pci_expander_bridge.h
@@ -2,6 +2,7 @@
 #define HW_PCI_EXPANDER_H
 
 #define PROP_PXB_PCIE_DEV "pxbdev"
+#define PROP_PXB_PCIE_HOST "x-pxb-host"
 
 #define PROP_PXB_PCIE_DOMAIN_NR "domain_nr"
 #define PROP_PXB_BUS_NR "bus_nr"
-- 
2.7.4


Reply via email to