summaryrefslogtreecommitdiff
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:29:08 -0500
commit0863e8e3903d1d4fa04df3bdf847931240570bfa (patch)
tree681f8151f5848c9cada41669dbf67e62e42df122
parentf0f2a3dc19e8caddccbb756898b5a413dad9de6a (diff)
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 cdb8a6f2cb..c23d483dd8 100644
--- a/c/src/lib/libbsp/i386/shared/pci/pcibios.c
+++ b/c/src/lib/libbsp/i386/shared/pci/pcibios.c
@@ -232,6 +232,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;
@@ -243,15 +245,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;
- }
}
}
}