[rtems commit] pc386: scan all functions of multi-function PCI devices

Gedare Bloom gedare at rtems.org
Wed Dec 24 03:30:05 UTC 2014


Module:    rtems
Branch:    4.10
Commit:    0863e8e3903d1d4fa04df3bdf847931240570bfa
Changeset: http://git.rtems.org/rtems/commit/?id=0863e8e3903d1d4fa04df3bdf847931240570bfa

Author:    Till Strauman <strauman at slac.stanford.edu>
Date:      Tue Dec 23 22:27:25 2014 -0500

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

---

 c/src/lib/libbsp/i386/shared/pci/pcibios.c | 30 +++++++++++++++++++++++-------
 1 file 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 cdb8a6f..c23d483 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;
-           }
         }
       }
     }



More information about the vc mailing list