summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2011-01-10 00:48:45 -0500
committerKevin O'Connor <kevin@koconnor.net>2011-01-10 00:48:45 -0500
commitd08eb9c968e519a0b1ba63702acb2115ad536318 (patch)
treeddfcaf5dc860cb47e1885a2dd86befa52ee5599f
parent89a1efd95c4f3ee349fa36c31526ae880820ce19 (diff)
Add ability to track PCI paths and add to build_pci_path().
Improve device path descriptions of devices on PCI buses.
-rw-r--r--src/boot.c17
-rw-r--r--src/pci.c29
-rw-r--r--src/pci.h5
-rw-r--r--src/post.c1
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