vgabios: Unify code to generate the vbe mode list.
[seabios.git] / src / pci.c
index ebc6f91b71c8f84ecb849dba34e99fa2123c1b6f..6031c9ffe400c5d9ed737f344612f177091e394e 100644 (file)
--- a/src/pci.c
+++ b/src/pci.c
@@ -8,8 +8,8 @@
 #include "pci.h" // pci_config_writel
 #include "ioport.h" // outl
 #include "util.h" // dprintf
-#include "config.h" // CONFIG_*
-#include "farptr.h" // CONFIG_*
+#include "paravirt.h" // romfile_loadint
+#include "farptr.h" // MAKE_FLATPTR
 #include "pci_regs.h" // PCI_VENDOR_ID
 #include "pci_ids.h" // PCI_CLASS_DISPLAY_VGA
 
@@ -59,71 +59,61 @@ pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
 
 // Helper function for foreachbdf() macro - return next device
 int
-pci_next(int bdf, int *pmax)
+pci_next(int bdf, int bus)
 {
-    if (pci_bdf_to_fn(bdf) == 1
-        && (pci_config_readb(bdf-1, PCI_HEADER_TYPE) & 0x80) == 0)
+    if (pci_bdf_to_fn(bdf) == 0
+        && (pci_config_readb(bdf, PCI_HEADER_TYPE) & 0x80) == 0)
         // Last found device wasn't a multi-function device - skip to
         // the next device.
-        bdf += 7;
+        bdf += 8;
+    else
+        bdf += 1;
 
-    int max = *pmax;
     for (;;) {
-        if (bdf >= max) {
-            if (CONFIG_PCI_ROOT1 && bdf <= (CONFIG_PCI_ROOT1 << 8))
-                bdf = CONFIG_PCI_ROOT1 << 8;
-            else if (CONFIG_PCI_ROOT2 && bdf <= (CONFIG_PCI_ROOT2 << 8))
-                bdf = CONFIG_PCI_ROOT2 << 8;
-            else
-               return -1;
-            *pmax = max = bdf + 0x0100;
-        }
+        if (pci_bdf_to_bus(bdf) != bus)
+            return -1;
 
         u16 v = pci_config_readw(bdf, PCI_VENDOR_ID);
         if (v != 0x0000 && v != 0xffff)
             // Device is present.
-            break;
+            return bdf;
 
         if (pci_bdf_to_fn(bdf) == 0)
             bdf += 8;
         else
             bdf += 1;
     }
-
-    // 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 newmax = (v & 0xff00) + 0x0100;
-        if (newmax > max)
-            *pmax = newmax;
-    }
-
-    return bdf;
 }
 
 struct pci_device *PCIDevices;
 int MaxPCIBus VAR16VISIBLE;
 
+// Check if PCI is available at all
+int
+pci_probe_host(void)
+{
+    outl(0x80000000, PORT_PCI_CMD);
+    if (inl(PORT_PCI_CMD) != 0x80000000) {
+        dprintf(1, "Detected non-PCI system\n");
+        return -1;
+    }
+    return 0;
+}
+
 // Find all PCI devices and populate PCIDevices linked list.
 void
-pci_probe(void)
+pci_probe_devices(void)
 {
     dprintf(3, "PCI probe\n");
-    if (CONFIG_PCI_ROOT1 && CONFIG_PCI_ROOT1 > MaxPCIBus)
-        MaxPCIBus = CONFIG_PCI_ROOT1;
-    if (CONFIG_PCI_ROOT2 && CONFIG_PCI_ROOT2 > MaxPCIBus)
-        MaxPCIBus = CONFIG_PCI_ROOT2;
-
     struct pci_device *busdevs[256];
     memset(busdevs, 0, sizeof(busdevs));
     struct pci_device **pprev = &PCIDevices;
+    int extraroots = romfile_loadint("etc/extra-pci-roots", 0);
     int bus = -1, lastbus = 0, rootbuses = 0, count=0;
-    while (bus < MaxPCIBus) {
+    while (bus < 0xff && (bus < MaxPCIBus || rootbuses < extraroots)) {
         bus++;
-        int bdf, max;
-        foreachbdf_in_bus(bdf, max, bus) {
+        int bdf;
+        foreachbdf(bdf, bus) {
             // Create new pci_device struct and add to list.
             struct pci_device *dev = malloc_tmp(sizeof(*dev));
             if (!dev) {
@@ -143,6 +133,8 @@ pci_probe(void)
                     rootbuses++;
                 lastbus = bus;
                 rootbus = rootbuses;
+                if (bus > MaxPCIBus)
+                    MaxPCIBus = bus;
             } else {
                 rootbus = parent->rootbus;
             }