From 096a9b10e68eb1b2087cc30e4fa6d333b6a03d72 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sun, 19 Jun 2011 14:09:20 -0400 Subject: [PATCH] Find all pci devices at startup and cache them for future use. This adds 'struct pci_device' and pci_probe() which will locate and store all found PCI devices in the system at startup. --- src/pci.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/pci.h | 20 ++++++++++++++++++ src/post.c | 1 + 3 files changed, 81 insertions(+) diff --git a/src/pci.c b/src/pci.c index c95baca..f0953e9 100644 --- a/src/pci.c +++ b/src/pci.c @@ -103,6 +103,66 @@ pci_next(int bdf, int *pmax) return bdf; } +struct pci_device *PCIDevices; +int MaxPCIBus; + +void +pci_probe(void) +{ + int rootbuses = 0; + struct pci_device *busdevs[256]; + memset(busdevs, 0, sizeof(busdevs)); + + struct pci_device **pprev = &PCIDevices; + u8 lastbus = 0; + int bdf, max; + foreachbdf(bdf, max) { + // Create new pci_device struct and add to list. + struct pci_device *dev = malloc_tmp(sizeof(*dev)); + if (!dev) { + warn_noalloc(); + return; + } + memset(dev, 0, sizeof(*dev)); + *pprev = dev; + pprev = &dev->next; + + // Find parent device. + u8 bus = pci_bdf_to_bus(bdf), rootbus; + struct pci_device *parent = busdevs[bus]; + if (!parent) { + if (bus != lastbus) + rootbuses++; + lastbus = bus; + rootbus = rootbuses; + } else { + rootbus = parent->rootbus; + } + if (bus > MaxPCIBus) + MaxPCIBus = bus; + + // Populate pci_device info. + dev->bdf = bdf; + dev->parent = parent; + dev->rootbus = rootbus; + u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID); + dev->vendor = vendev & 0xffff; + dev->device = vendev >> 16; + u32 classrev = pci_config_readl(bdf, PCI_CLASS_REVISION); + dev->class = classrev >> 16; + dev->prog_if = classrev >> 8; + dev->revision = classrev & 0xff; + dev->header_type = pci_config_readb(bdf, PCI_HEADER_TYPE); + u8 v = dev->header_type & 0x7f; + if (v == PCI_HEADER_TYPE_BRIDGE || v == PCI_HEADER_TYPE_CARDBUS) { + u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS); + dev->secondary_bus = secbus; + if (secbus > bus && !busdevs[secbus]) + busdevs[secbus] = dev; + } + } +} + // Find a vga device with legacy address decoding enabled. int pci_find_vga(void) diff --git a/src/pci.h b/src/pci.h index 6e9cbf0..f1d84ed 100644 --- a/src/pci.h +++ b/src/pci.h @@ -47,6 +47,26 @@ int pci_find_vga(void); int pci_find_device(u16 vendid, u16 devid); int pci_find_class(u16 classid); +struct pci_device { + u16 bdf; + u8 rootbus; + struct pci_device *next; + struct pci_device *parent; + + // Configuration space device information + u16 vendor, device; + u16 class; + u8 prog_if, revision; + u8 header_type; + u8 secondary_bus; +}; +extern struct pci_device *PCIDevices; +extern int MaxPCIBus; +void pci_probe(void); + +#define foreachpci(PCI) \ + for (PCI=PCIDevices; PCI; PCI=PCI->next) + #define PP_ROOT (1<<17) #define PP_PCIBRIDGE (1<<18) extern int *PCIpaths; diff --git a/src/post.c b/src/post.c index 70d98a6..d8f4acf 100644 --- a/src/post.c +++ b/src/post.c @@ -224,6 +224,7 @@ maininit(void) // Initialize pci pci_setup(); + pci_probe(); pci_path_setup(); smm_init(); -- 2.25.1