Only touch PCI functions > 0 on multi-function devices; rescan max pci each time.

Some single-function devices will respond to all sub-functions - and
    this confuses things.  So, when scanning the PCI bus make sure to
    only touch function 0 on single-function devices.
Since the bus scanning code is necessarily complex now, we might as
    well implement max bus detection inline with all pci scans.  So,
    there is no need to scan for the max bus at startup.
diff --git a/src/optionroms.c b/src/optionroms.c
index 1c1b791..0d5f34b 100644
--- a/src/optionroms.c
+++ b/src/optionroms.c
@@ -271,9 +271,8 @@
         }
     } else {
         // Find and deploy PCI roms.
-        int max = GET_VAR(CS, MaxBDF);
-        int bdf;
-        for (bdf=0; bdf < max; bdf++) {
+        int bdf, max;
+        foreachpci(bdf, max, 0) {
             u16 v = pci_config_readw(bdf, PCI_CLASS_DEVICE);
             if (v == 0x0000 || v == 0xffff || v == PCI_CLASS_DISPLAY_VGA)
                 continue;
diff --git a/src/pci.c b/src/pci.c
index 91a7ca5..20838bf 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -5,7 +5,7 @@
 //
 // This file may be distributed under the terms of the GNU GPLv3 license.
 
-#include "pci.h" // MaxBDF
+#include "pci.h" // pci_config_writel
 #include "ioport.h" // outl
 #include "util.h" // dprintf
 #include "config.h" // CONFIG_*
@@ -48,37 +48,42 @@
     return inb(PORT_PCI_DATA + (addr & 3));
 }
 
-#if MODE16
-int MaxBDF VISIBLE16 = 0x0100;
-#endif
-
-// Find the maximum bus number.
-void
-pci_bus_setup()
+int
+pci_next(int bdf, int *pmax)
 {
-    dprintf(3, "Scan for max PCI bus\n");
+    if (pci_bdf_to_fn(bdf) == 1
+        && (pci_config_readb(bdf-1, PCI_HEADER_TYPE) & 0x80) == 0)
+        // Last found device wasn't a multi-function device - skip to
+        // the next device.
+        bdf += 7;
 
-    int max = 0x0100;
-    int bdf;
-    for (bdf=0; bdf < max; bdf++) {
-        u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
-        if (v == 0xffffffff || v == 0x00000000
-            || v == 0x0000ffff || v == 0xffff0000)
-            // No device present.
-            continue;
-        v = pci_config_readb(bdf, PCI_HEADER_TYPE);
-        v &= 0x7f;
-        if (v != PCI_HEADER_TYPE_BRIDGE && v != PCI_HEADER_TYPE_CARDBUS)
-            // Not a bridge
-            continue;
+    int max = *pmax;
+    for (;;) {
+        if (bdf >= max)
+            return -1;
+
+        u16 v = pci_config_readw(bdf, PCI_VENDOR_ID);
+        if (v != 0x0000 && v != 0xffff)
+            // Device is present.
+            break;
+
+        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)
-            max = newmax;
+            *pmax = newmax;
     }
-    SET_VAR(CS, MaxBDF, max);
 
-    dprintf(1, "Found %d PCI buses\n", pci_bdf_to_bus(max));
+    return bdf;
 }
 
 // Search for a device with the specified vendor and device ids.
@@ -86,9 +91,8 @@
 pci_find_device(u16 vendid, u16 devid, int start_bdf)
 {
     u32 id = (devid << 16) | vendid;
-    int max = GET_VAR(CS, MaxBDF);
-    int bdf;
-    for (bdf=start_bdf; bdf < max; bdf++) {
+    int bdf, max;
+    foreachpci(bdf, max, start_bdf) {
         u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
         if (v != id)
             continue;
@@ -102,9 +106,8 @@
 int
 pci_find_classprog(u32 classprog, int start_bdf)
 {
-    int max = GET_VAR(CS, MaxBDF);
-    int bdf;
-    for (bdf=start_bdf; bdf < max; bdf++) {
+    int bdf, max;
+    foreachpci(bdf, max, start_bdf) {
         u32 v = pci_config_readl(bdf, PCI_CLASS_REVISION);
         if ((v>>8) != classprog)
             continue;
@@ -118,9 +121,8 @@
 int
 pci_find_class(u16 classid, int start_bdf)
 {
-    int max = GET_VAR(CS, MaxBDF);
-    int bdf;
-    for (bdf=start_bdf; bdf < max; bdf++) {
+    int bdf, max;
+    foreachpci(bdf, max, start_bdf) {
         u16 v = pci_config_readw(bdf, PCI_CLASS_DEVICE);
         if (v != classid)
             continue;
diff --git a/src/pci.h b/src/pci.h
index a18cfb7..fc39fa0 100644
--- a/src/pci.h
+++ b/src/pci.h
@@ -23,12 +23,15 @@
 u16 pci_config_readw(u16 bdf, u32 addr);
 u8 pci_config_readb(u16 bdf, u32 addr);
 
-void pci_bus_setup();
 int pci_find_device(u16 vendid, u16 devid, int start_bdf);
 int pci_find_classprog(u32 classprog, int start_bdf);
 int pci_find_class(u16 classid, int start_bdf);
 
-extern int MaxBDF;
+int pci_next(int bdf, int *pmax);
+#define foreachpci(BDF, MAX, START)                     \
+    for (MAX=0x0100, BDF=pci_next((START), &MAX)        \
+         ; BDF >= 0                                     \
+         ; BDF=pci_next(BDF+1, &MAX))
 
 // pirtable.c
 void create_pirtable();
diff --git a/src/pcibios.c b/src/pcibios.c
index 65e4a18..93cdc46 100644
--- a/src/pcibios.c
+++ b/src/pcibios.c
@@ -20,9 +20,14 @@
 static void
 handle_1ab101(struct bregs *regs)
 {
+    // Find max bus.
+    int bdf, max;
+    foreachpci(bdf, max, 0) {
+    }
+
     regs->al = 0x01; // Flags - "Config Mechanism #1" supported.
     regs->bx = 0x0210; // PCI version 2.10
-    regs->cl = pci_bdf_to_bus(GET_VAR(CS, MaxBDF) - 1);
+    regs->cl = pci_bdf_to_bus(max - 1);
     regs->edx = 0x20494350; // "PCI "
     // XXX - bochs bios code sets edi to point to 32bit code - but no
     // reference to this in spec.
diff --git a/src/pciinit.c b/src/pciinit.c
index 9b6e9f6..28bee74 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -189,18 +189,6 @@
     }
 }
 
-static void pci_for_each_device(void (*init_func)(u16 bdf))
-{
-    int max = GET_VAR(CS, MaxBDF);
-    int bdf;
-    for (bdf = 0; bdf < max; bdf++) {
-        u16 vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
-        u16 device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
-        if (vendor_id != 0xffff || device_id != 0xffff)
-            init_func(bdf);
-    }
-}
-
 void
 pci_bios_setup(void)
 {
@@ -214,7 +202,11 @@
     if (pci_bios_bigmem_addr < 0x90000000)
         pci_bios_bigmem_addr = 0x90000000;
 
-    pci_for_each_device(pci_bios_init_bridges);
-
-    pci_for_each_device(pci_bios_init_device);
+    int bdf, max;
+    foreachpci(bdf, max, 0) {
+        pci_bios_init_bridges(bdf);
+    }
+    foreachpci(bdf, max, 0) {
+        pci_bios_init_device(bdf);
+    }
 }
diff --git a/src/post.c b/src/post.c
index 68a473c..3aec90b 100644
--- a/src/post.c
+++ b/src/post.c
@@ -195,7 +195,6 @@
     timer_setup();
     mathcp_setup();
 
-    pci_bus_setup();
     smp_probe_setup();
 
     memmap_setup();