Add pci_device_get_parent_bridge()
authorAdam Jackson <ajax@redhat.com>
Wed, 18 Nov 2009 19:12:57 +0000 (14:12 -0500)
committerAdam Jackson <ajax@redhat.com>
Wed, 2 Dec 2009 20:50:29 +0000 (15:50 -0500)
Copied from linuxPci.c in the X server.

Acked-by: Tiago Vignatti <tiago.vignatti@nokia.com>
Signed-off-by: Adam Jackson <ajax@redhat.com>
include/pciaccess.h
src/common_bridge.c

index 067954f..8128656 100644 (file)
@@ -131,6 +131,8 @@ struct pci_device *pci_device_next(struct pci_device_iterator *iter);
 struct pci_device *pci_device_find_by_slot(uint32_t domain, uint32_t bus,
     uint32_t dev, uint32_t func);
 
+struct pci_device *pci_device_get_parent_bridge(struct pci_device *dev);
+
 void pci_get_strings(const struct pci_id_match *m,
     const char **device_name, const char **vendor_name,
     const char **subdevice_name, const char **subvendor_name);
index 7f26bdc..f37420f 100644 (file)
@@ -322,3 +322,43 @@ pci_device_get_bridge_buses(struct pci_device * dev, int *primary_bus,
 
     return 0;
 }
+
+#define PCI_CLASS_BRIDGE 0x06
+#define PCI_SUBCLASS_BRIDGE_PCI 0x04
+
+struct pci_device *
+pci_device_get_parent_bridge(struct pci_device *dev)
+{
+    struct pci_id_match bridge_match = {
+        PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
+        (PCI_CLASS_BRIDGE << 16) | (PCI_SUBCLASS_BRIDGE_PCI << 8),
+        0
+    };
+
+    struct pci_device *bridge;
+    struct pci_device_iterator *iter;
+
+    if (dev == NULL)
+        return NULL;
+
+    iter = pci_id_match_iterator_create(& bridge_match);
+    if (iter == NULL)
+        return NULL;
+
+    while ((bridge = pci_device_next(iter)) != NULL) {
+        if (bridge->domain == dev->domain) {
+            const struct pci_bridge_info *info =
+                pci_device_get_bridge_info(bridge);
+
+            if (info != NULL) {
+                if (info->secondary_bus == dev->bus) {
+                    break;
+                }
+            }
+        }
+    }
+
+    pci_iterator_destroy(iter);
+
+    return bridge;
+}