Add ability to track PCI paths and add to build_pci_path().
authorKevin O'Connor <kevin@koconnor.net>
Mon, 10 Jan 2011 05:48:45 +0000 (00:48 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Mon, 10 Jan 2011 05:48:45 +0000 (00:48 -0500)
Improve device path descriptions of devices on PCI buses.

src/boot.c
src/pci.c
src/pci.h
src/post.c

index b59794edb8e90b0fdb3baf2a694a0f435d494f4d..05fb3ddfa09be62df3935b7a99448b179b6b354e 100644 (file)
@@ -99,13 +99,20 @@ build_pci_path(char *buf, int max, const char *devname, int bdf)
 {
     // Build the string path of a bdf - for example: /pci@i0cf8/isa@1,2
     char *p = buf;
-    int bus = pci_bdf_to_bus(bdf);
-    if (bus)
-        // XXX - this isn't the correct path syntax
-        p += snprintf(p, max, "/bus%x", bus);
+    int parent = pci_bdf_to_bus(bdf);
+    if (PCIpaths)
+        parent = PCIpaths[parent];
+    int parentdev = parent & 0xffff;
+    if (parent & PP_PCIBRIDGE) {
+        p = build_pci_path(p, max, "pci-bridge", parentdev);
+    } else {
+        if (parentdev)
+            p += snprintf(p, max, "/pci-root@%x", parentdev);
+        p += snprintf(p, buf+max-p, "%s", FW_PCI_DOMAIN);
+    }
 
     int dev = pci_bdf_to_dev(bdf), fn = pci_bdf_to_fn(bdf);
-    p += snprintf(p, buf+max-p, "%s/%s@%x", FW_PCI_DOMAIN, devname, dev);
+    p += snprintf(p, buf+max-p, "/%s@%x", devname, dev);
     if (fn)
         p += snprintf(p, buf+max-p, ",%x", fn);
     return p;
index 5237f19d2449a14228697a4f06c18f1392100105..45f210d8db0ebf9c0caeb3777f063a3ecf4659eb 100644 (file)
--- a/src/pci.c
+++ b/src/pci.c
@@ -185,6 +185,35 @@ pci_find_class(u16 classid)
     return -1;
 }
 
+int *PCIpaths;
+
+// Build the PCI path designations.
+void
+pci_path_setup(void)
+{
+    PCIpaths = malloc_tmp(sizeof(*PCIpaths) * 256);
+    if (!PCIpaths)
+        return;
+    memset(PCIpaths, 0, sizeof(PCIpaths));
+
+    int roots = 0;
+    int bdf, max;
+    foreachpci(bdf, max) {
+        int bus = pci_bdf_to_bus(bdf);
+        if (! PCIpaths[bus])
+            PCIpaths[bus] = (roots++) | PP_ROOT;
+
+        // Check if found device is a bridge.
+        u32 v = pci_config_readb(bdf, PCI_HEADER_TYPE);
+        v &= 0x7f;
+        if (v == PCI_HEADER_TYPE_BRIDGE || v == PCI_HEADER_TYPE_CARDBUS) {
+            v = pci_config_readl(bdf, PCI_PRIMARY_BUS);
+            int childbus = (v >> 8) & 0xff;
+            PCIpaths[childbus] = bdf | PP_PCIBRIDGE;
+        }
+    }
+}
+
 int pci_init_device(const struct pci_device_id *ids, u16 bdf, void *arg)
 {
     u16 vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
index 46af207fa906973dbf85cc88d2f4fb1ac646336b..9869a26d32d77a801429c98ec6f91d1d2c9315af 100644 (file)
--- a/src/pci.h
+++ b/src/pci.h
@@ -47,6 +47,11 @@ int pci_find_vga(void);
 int pci_find_device(u16 vendid, u16 devid);
 int pci_find_class(u16 classid);
 
+#define PP_ROOT      (1<<17)
+#define PP_PCIBRIDGE (1<<18)
+extern int *PCIpaths;
+void pci_path_setup(void);
+
 int pci_next(int bdf, int *pmax);
 #define foreachpci(BDF, MAX)                    \
     for (MAX=0x0100, BDF=pci_next(0, &MAX)      \
index efcfc85df39d8a683d9fb3ed648d482809b96861..7d2b5f28290e2219b259b41e986adbb155058125 100644 (file)
@@ -217,6 +217,7 @@ maininit(void)
 
     // Initialize pci
     pci_setup();
+    pci_path_setup();
     smm_init();
 
     // Initialize internal tables