aboutsummaryrefslogtreecommitdiff
path: root/src/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pci.c')
-rw-r--r--src/pci.c29
1 files changed, 29 insertions, 0 deletions
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);