diff options
author | Adam Jackson <ajax@redhat.com> | 2009-11-18 14:12:57 -0500 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2009-12-02 15:50:29 -0500 |
commit | b2fbe63bdf3522c5d3df5eda2ca3c3b8770c02c9 (patch) | |
tree | d34d74aab2c6612e3cfe5cff40ea9762a5e2c7d3 | |
parent | b2b3c3bfdac23c1c8e33f47b28f22c1d4a78cc71 (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.h | 2 | ||||
-rw-r--r-- | src/common_bridge.c | 40 |
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; +} |