summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2009-11-18 14:12:57 -0500
committerAdam Jackson <ajax@redhat.com>2009-12-02 15:50:29 -0500
commitb2fbe63bdf3522c5d3df5eda2ca3c3b8770c02c9 (patch)
treed34d74aab2c6612e3cfe5cff40ea9762a5e2c7d3
parentb2b3c3bfdac23c1c8e33f47b28f22c1d4a78cc71 (diff)
Add pci_device_get_parent_bridge()
Copied from linuxPci.c in the X server. Acked-by: Tiago Vignatti <tiago.vignatti@nokia.com> Signed-off-by: Adam Jackson <ajax@redhat.com>
-rw-r--r--include/pciaccess.h2
-rw-r--r--src/common_bridge.c40
2 files changed, 42 insertions, 0 deletions
diff --git a/include/pciaccess.h b/include/pciaccess.h
index 067954f..8128656 100644
--- a/include/pciaccess.h
+++ b/include/pciaccess.h
@@ -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);
diff --git a/src/common_bridge.c b/src/common_bridge.c
index 7f26bdc..f37420f 100644
--- a/src/common_bridge.c
+++ b/src/common_bridge.c
@@ -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;
+}