Improve device path descriptions of devices on PCI buses. --- src/boot.c | 17 ++++++++++++----- src/pci.c | 29 +++++++++++++++++++++++++++++ src/pci.h | 5 +++++ src/post.c | 1 + 4 files changed, 47 insertions(+), 5 deletions(-)
diff --git a/src/boot.c b/src/boot.c index b59794e..05fb3dd 100644 --- a/src/boot.c +++ b/src/boot.c @@ -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; diff --git a/src/pci.c b/src/pci.c index 5237f19..45f210d 100644 --- 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); diff --git a/src/pci.h b/src/pci.h index 46af207..9869a26 100644 --- 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) \ diff --git a/src/post.c b/src/post.c index efcfc85..7d2b5f2 100644 --- a/src/post.c +++ b/src/post.c @@ -217,6 +217,7 @@ maininit(void)
// Initialize pci pci_setup(); + pci_path_setup(); smm_init();
// Initialize internal tables