diff options
author | Till Strauman <strauman@slac.stanford.edu> | 2014-12-23 22:27:25 -0500 |
---|---|---|
committer | Gedare Bloom <gedare@rtems.org> | 2014-12-23 22:27:25 -0500 |
commit | 2573e698d1a5f2e481b5b0520a949c4f590bacbd (patch) | |
tree | 65944d600559922b2d63dcec4de2bd924b29d1ad | |
parent | da10694a489a51534ba189417defbea4162cfd8f (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.c | 30 |
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; - } } } } |