summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTill Strauman <strauman@slac.stanford.edu>2014-12-23 22:27:25 -0500
committerGedare Bloom <gedare@rtems.org>2014-12-23 22:27:25 -0500
commit2573e698d1a5f2e481b5b0520a949c4f590bacbd (patch)
tree65944d600559922b2d63dcec4de2bd924b29d1ad
parentlibnetworking: Make rtems_dhcp_failsafe() run time configurable (diff)
downloadrtems-2573e698d1a5f2e481b5b0520a949c4f590bacbd.tar.bz2
pc386: scan all functions of multi-function PCI devices
The current algorithm scans all PCI busses (0..ff) and all devices (0..31) on each bus for bridges and determines the maximum of all subordinate busses encountered. However, the algorithm does not scan all functions present in multi-function devices -- I have a PCI express root complex (82801H) where multiple (non-zero index) functions are 'PCI bridges' whose subordinate bus number is missed by the original algorithm. This commit makes sure that the scan is extended to all functions of multi-function devices. See #2067
-rw-r--r--c/src/lib/libbsp/i386/shared/pci/pcibios.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/c/src/lib/libbsp/i386/shared/pci/pcibios.c b/c/src/lib/libbsp/i386/shared/pci/pcibios.c
index 7767e7c8a0..870721f1f8 100644
--- a/c/src/lib/libbsp/i386/shared/pci/pcibios.c
+++ b/c/src/lib/libbsp/i386/shared/pci/pcibios.c
@@ -228,6 +228,8 @@ pci_bus_count(void)
if ( ucBusCount == 0xff ) {
unsigned char bus;
unsigned char dev;
+ unsigned char fun;
+ unsigned char nfn;
unsigned char hd = 0;
uint32_t d = 0;
int sig;
@@ -239,15 +241,29 @@ pci_bus_count(void)
sig = PCIB_DEVSIG_MAKE(bus,dev,0);
pcib_conf_read32(sig, PCI_VENDOR_ID, &d);
- if ( d != -1 ) {
- pcib_conf_read32(sig, PCI_CLASS_REVISION, &d);
+ if ( -1 == d ) {
+ continue;
+ }
+
+ pcib_conf_read8(sig, PCI_HEADER_TYPE, &hd);
+ nfn = (hd & 0x80) ? PCI_MAX_FUNCTIONS : 1;
+
+ for ( fun=0; fun<nfn; fun++ ) {
+
+ sig = PCIB_DEVSIG_MAKE(bus,dev,fun);
+ pcib_conf_read32(sig, PCI_VENDOR_ID, &d);
+ if ( -1 == d )
+ continue;
+
+ pcib_conf_read32(sig, PCI_CLASS_REVISION, &d);
+
+ if ( (d >> 16) == PCI_CLASS_BRIDGE_PCI ) {
+ pcib_conf_read8(sig, PCI_SUBORDINATE_BUS, &hd);
- if ( (d >> 16) == PCI_CLASS_BRIDGE_PCI ) {
- pcib_conf_read8(sig, PCI_SUBORDINATE_BUS, &hd);
+ if ( hd > ucBusCount )
+ ucBusCount = hd;
+ }
- if ( hd > ucBusCount )
- ucBusCount = hd;
- }
}
}
}