PCI enhancements.

Allow one to enable/disable PIR tables separately from PCI BIOS support.
Use standard PORT_* defs for 0xcf8/0xcfc port accesses.
Don't pass PCIDevice pointers around - the struct is small enough to
    pass in a register.
Extract out pci_find_device and pci_find_class functions from PCI BIOS
    code.
Remove PCI_FIXED_HOST_BRIDGE check - the check is too late if standard
    PCI support isn't available.  If standard support is available,
    then the code should be okay to run.
diff --git a/src/config.h b/src/config.h
index 4ae23dc..75f5a7f 100644
--- a/src/config.h
+++ b/src/config.h
@@ -16,6 +16,7 @@
 // Configure as a payload coreboot payload.
 #define CONFIG_COREBOOT 0
 
+// Send debugging information to serial port
 #define CONFIG_DEBUG_SERIAL 0
 
 #define CONFIG_FLOPPY_SUPPORT 1
@@ -24,6 +25,9 @@
 #define CONFIG_KBD_CALL_INT15_4F 1
 #define CONFIG_CDROM_BOOT 1
 #define CONFIG_CDROM_EMU 1
+// Support built-in PIR table in 0xf000 segment
+#define CONFIG_PIRTABLE 1
+// Support int 1a/b1 PCI BIOS calls
 #define CONFIG_PCIBIOS 1
 
 /* define it if the (emulated) hardware supports SMM mode */
diff --git a/src/ioport.h b/src/ioport.h
index fe0d7ce..a51d713 100644
--- a/src/ioport.h
+++ b/src/ioport.h
@@ -39,6 +39,8 @@
 #define PORT_FD_DATA           0x03f5
 #define PORT_HD_DATA           0x03f6
 #define PORT_FD_DIR            0x03f7
+#define PORT_PCI_CMD           0x0cf8
+#define PORT_PCI_DATA          0x0cfc
 #define PORT_BIOS_DEBUG        0x0403
 #define PORT_BIOS_APM          0x8900
 
diff --git a/src/pci.c b/src/pci.c
index 2dd617b..8d19b81 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -1,38 +1,86 @@
 #include "pci.h" // PCIDevice
 #include "ioport.h" // outl
 
-void pci_config_writel(PCIDevice *d, u32 addr, u32 val)
+void pci_config_writel(PCIDevice d, u32 addr, u32 val)
 {
-    outl(0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc), 0xcf8);
-    outl(val, 0xcfc);
+    outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
+         , PORT_PCI_CMD);
+    outl(val, PORT_PCI_DATA);
 }
 
-void pci_config_writew(PCIDevice *d, u32 addr, u16 val)
+void pci_config_writew(PCIDevice d, u32 addr, u16 val)
 {
-    outl(0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc), 0xcf8);
-    outw(val, 0xcfc + (addr & 2));
+    outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
+         , PORT_PCI_CMD);
+    outw(val, PORT_PCI_DATA + (addr & 2));
 }
 
-void pci_config_writeb(PCIDevice *d, u32 addr, u8 val)
+void pci_config_writeb(PCIDevice d, u32 addr, u8 val)
 {
-    outl(0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc), 0xcf8);
-    outb(val, 0xcfc + (addr & 3));
+    outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
+         , PORT_PCI_CMD);
+    outb(val, PORT_PCI_DATA + (addr & 3));
 }
 
-u32 pci_config_readl(PCIDevice *d, u32 addr)
+u32 pci_config_readl(PCIDevice d, u32 addr)
 {
-    outl(0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc), 0xcf8);
-    return inl(0xcfc);
+    outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
+         , PORT_PCI_CMD);
+    return inl(PORT_PCI_DATA);
 }
 
-u16 pci_config_readw(PCIDevice *d, u32 addr)
+u16 pci_config_readw(PCIDevice d, u32 addr)
 {
-    outl(0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc), 0xcf8);
-    return inw(0xcfc + (addr & 2));
+    outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
+         , PORT_PCI_CMD);
+    return inw(PORT_PCI_DATA + (addr & 2));
 }
 
-u8 pci_config_readb(PCIDevice *d, u32 addr)
+u8 pci_config_readb(PCIDevice d, u32 addr)
 {
-    outl(0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc), 0xcf8);
-    return inb(0xcfc + (addr & 3));
+    outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
+         , PORT_PCI_CMD);
+    return inb(PORT_PCI_DATA + (addr & 3));
+}
+
+int
+pci_find_device(u16 vendid, u16 devid, int index, PCIDevice *dev)
+{
+    int devfn;
+    u32 id = (devid << 16) | vendid;
+    for (devfn=0; devfn<0x100; devfn++) {
+        PCIDevice d = pci_bd(0, devfn);
+        u32 v = pci_config_readl(d, 0x00);
+        if (v != id)
+            continue;
+        if (index) {
+            index--;
+            continue;
+        }
+        // Found it.
+        *dev = d;
+        return 0;
+    }
+    return -1;
+}
+
+int
+pci_find_class(u32 classid, int index, PCIDevice *dev)
+{
+    int devfn;
+    u32 id = classid << 8;
+    for (devfn=0; devfn<0x100; devfn++) {
+        PCIDevice d = pci_bd(0, devfn);
+        u32 v = pci_config_readl(d, 0x08);
+        if (v != id)
+            continue;
+        if (index) {
+            index--;
+            continue;
+        }
+        // Found it.
+        *dev = d;
+        return 0;
+    }
+    return -1;
 }
diff --git a/src/pci.h b/src/pci.h
index 48d4769..b54cd37 100644
--- a/src/pci.h
+++ b/src/pci.h
@@ -4,15 +4,25 @@
 #include "types.h" // u32
 
 typedef struct PCIDevice {
-    int bus;
-    int devfn;
+    u8 bus;
+    u8 devfn;
 } PCIDevice;
 
-void pci_config_writel(PCIDevice *d, u32 addr, u32 val);
-void pci_config_writew(PCIDevice *d, u32 addr, u16 val);
-void pci_config_writeb(PCIDevice *d, u32 addr, u8 val);
-u32 pci_config_readl(PCIDevice *d, u32 addr);
-u16 pci_config_readw(PCIDevice *d, u32 addr);
-u8 pci_config_readb(PCIDevice *d, u32 addr);
+static inline PCIDevice
+pci_bd(u8 bus, u8 devfn)
+{
+    struct PCIDevice d = {bus, devfn};
+    return d;
+}
+
+void pci_config_writel(PCIDevice d, u32 addr, u32 val);
+void pci_config_writew(PCIDevice d, u32 addr, u16 val);
+void pci_config_writeb(PCIDevice d, u32 addr, u8 val);
+u32 pci_config_readl(PCIDevice d, u32 addr);
+u16 pci_config_readw(PCIDevice d, u32 addr);
+u8 pci_config_readb(PCIDevice d, u32 addr);
+
+int pci_find_device(u16 vendid, u16 devid, int index, PCIDevice *dev);
+int pci_find_class(u32 classid, int index, PCIDevice *dev);
 
 #endif
diff --git a/src/pcibios.c b/src/pcibios.c
index 44a6369..3e9468a 100644
--- a/src/pcibios.c
+++ b/src/pcibios.c
@@ -44,7 +44,7 @@
     struct pir pir;
     struct pir_slot slots[6];
 } PACKED PIR_TABLE VISIBLE16 __attribute__((aligned(16))) = {
-#if CONFIG_PCIBIOS
+#if CONFIG_PIRTABLE
     .pir = {
         .signature = 0x52495024, // "$PIR"
         .version = 0x0100,
@@ -116,7 +116,7 @@
             .slot_nr = 5,
         },
     }
-#endif // CONFIG_PCIBIOS
+#endif // CONFIG_PIRTABLE
 };
 
 
@@ -146,56 +146,35 @@
 static void
 handle_1ab102(struct bregs *regs)
 {
-    u32 dev = (regs->cx << 16) | regs->dx;
-    u16 index = regs->si;
-    int i;
-    for (i=0; i<0x100; i++) {
-        PCIDevice d = {0, i};
-        u32 v = pci_config_readl(&d, 0);
-        if (v != dev)
-            continue;
-        if (index) {
-            index--;
-            continue;
-        }
-        // Found it.
-        regs->bx = i;
-        set_code_success(regs);
+    PCIDevice d;
+    int ret = pci_find_device(regs->cx, regs->dx, regs->si, &d);
+    if (ret) {
+        set_code_fail(regs, RET_DEVICE_NOT_FOUND);
         return;
     }
-    set_code_fail(regs, RET_DEVICE_NOT_FOUND);
+    regs->bx = d.devfn;
+    set_code_success(regs);
 }
 
 // find class code
 static void
 handle_1ab103(struct bregs *regs)
 {
-    u32 code = regs->ecx << 8;
-    u16 index = regs->si;
-    int i;
-    for (i=0; i<0x100; i++) {
-        PCIDevice d = {0, i};
-        u32 v = pci_config_readl(&d, 0x08);
-        if (v != code)
-            continue;
-        if (index) {
-            index--;
-            continue;
-        }
-        // Found it.
-        regs->bx = i;
-        set_code_success(regs);
+    PCIDevice d;
+    int ret = pci_find_class(regs->ecx, regs->si, &d);
+    if (ret) {
+        set_code_fail(regs, RET_DEVICE_NOT_FOUND);
         return;
     }
-    set_code_fail(regs, RET_DEVICE_NOT_FOUND);
+    regs->bx = d.devfn;
+    set_code_success(regs);
 }
 
 // read configuration byte
 static void
 handle_1ab108(struct bregs *regs)
 {
-    PCIDevice d = {regs->bh, regs->bl};
-    regs->cl = pci_config_readb(&d, regs->di);
+    regs->cl = pci_config_readb(pci_bd(regs->bh, regs->bl), regs->di);
     set_code_success(regs);
 }
 
@@ -203,8 +182,7 @@
 static void
 handle_1ab109(struct bregs *regs)
 {
-    PCIDevice d = {regs->bh, regs->bl};
-    regs->cx = pci_config_readw(&d, regs->di);
+    regs->cx = pci_config_readw(pci_bd(regs->bh, regs->bl), regs->di);
     set_code_success(regs);
 }
 
@@ -212,8 +190,7 @@
 static void
 handle_1ab10a(struct bregs *regs)
 {
-    PCIDevice d = {regs->bh, regs->bl};
-    regs->ecx = pci_config_readl(&d, regs->di);
+    regs->ecx = pci_config_readl(pci_bd(regs->bh, regs->bl), regs->di);
     set_code_success(regs);
 }
 
@@ -221,8 +198,7 @@
 static void
 handle_1ab10b(struct bregs *regs)
 {
-    PCIDevice d = {regs->bh, regs->bl};
-    pci_config_writeb(&d, regs->di, regs->cl);
+    pci_config_writeb(pci_bd(regs->bh, regs->bl), regs->di, regs->cl);
     set_code_success(regs);
 }
 
@@ -230,8 +206,7 @@
 static void
 handle_1ab10c(struct bregs *regs)
 {
-    PCIDevice d = {regs->bh, regs->bl};
-    pci_config_writew(&d, regs->di, regs->cx);
+    pci_config_writew(pci_bd(regs->bh, regs->bl), regs->di, regs->cx);
     set_code_success(regs);
 }
 
@@ -239,8 +214,7 @@
 static void
 handle_1ab10d(struct bregs *regs)
 {
-    PCIDevice d = {regs->bh, regs->bl};
-    pci_config_writel(&d, regs->di, regs->ecx);
+    pci_config_writel(pci_bd(regs->bh, regs->bl), regs->di, regs->ecx);
     set_code_success(regs);
 }
 
@@ -248,6 +222,11 @@
 static void
 handle_1ab10e(struct bregs *regs)
 {
+    if (! CONFIG_PIRTABLE) {
+        set_code_fail(regs, RET_FUNC_NOT_SUPPORTED);
+        return;
+    }
+
     // Validate and update size.
     u16 size = GET_FARVAR(regs->es, *(u16*)(regs->di+0));
     u32 pirsize = sizeof(PIR_TABLE.slots);
@@ -280,8 +259,6 @@
     set_code_fail(regs, RET_FUNC_NOT_SUPPORTED);
 }
 
-#define PCI_FIXED_HOST_BRIDGE 0x12378086 // i440FX PCI bridge
-
 void
 handle_1ab1(struct bregs *regs)
 {
@@ -292,20 +269,6 @@
         return;
     }
 
-    outl(0x80000000, 0x0cf8);
-    u32 v = inl(0x0cfc);
-    if (
-#ifdef PCI_FIXED_HOST_BRIDGE
-        v != PCI_FIXED_HOST_BRIDGE
-#else
-        v == 0xffffffff
-#endif
-        ) {
-        // Device not present
-        set_code_fail(regs, 0xff);
-        return;
-    }
-
     switch (regs->al) {
     case 0x01: handle_1ab101(regs); break;
     case 0x02: handle_1ab102(regs); break;
diff --git a/src/rombios32.c b/src/rombios32.c
index fde32a9..6c35b0a 100644
--- a/src/rombios32.c
+++ b/src/rombios32.c
@@ -197,7 +197,7 @@
 static u8 pci_irqs[4] = { 11, 9, 11, 9 };
 static PCIDevice i440_pcidev;
 
-static void pci_set_io_region_addr(PCIDevice *d, int region_num, u32 addr)
+static void pci_set_io_region_addr(PCIDevice d, int region_num, u32 addr)
 {
     u16 cmd;
     u32 ofs, old_addr;
@@ -227,15 +227,15 @@
 /* return the global irq number corresponding to a given device irq
    pin. We could also use the bus number to have a more precise
    mapping. */
-static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+static int pci_slot_get_pirq(PCIDevice pci_dev, int irq_num)
 {
     int slot_addend;
-    slot_addend = (pci_dev->devfn >> 3) - 1;
+    slot_addend = (pci_dev.devfn >> 3) - 1;
     return (irq_num + slot_addend) & 3;
 }
 
 static void
-copy_bios(PCIDevice *d, int v)
+copy_bios(PCIDevice d, int v)
 {
     pci_config_writeb(d, 0x59, v);
     memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE, 0x10000);
@@ -249,7 +249,7 @@
             (__addr - __start < __size); \
         })
 
-static void bios_shadow_init(PCIDevice *d)
+static void bios_shadow_init(PCIDevice d)
 {
     bios_table_cur_addr = 0xf0000 | OFFSET_freespace2_start;
     bios_table_end_addr = 0xf0000 | OFFSET_freespace2_end;
@@ -268,7 +268,7 @@
         // Current code is in shadowed area.  Perform the copy from
         // the code that is in the temporary location.
         u32 pos = (u32)copy_bios - 0xf0000 + BIOS_TMP_STORAGE;
-        void (*func)(PCIDevice *, int) = (void*)pos;
+        void (*func)(PCIDevice, int) = (void*)pos;
         func(d, v);
     } else {
         copy_bios(d, v);
@@ -277,12 +277,12 @@
     // Clear the area just copied.
     memset((void *)BIOS_TMP_STORAGE, 0, 0x10000);
 
-    i440_pcidev = *d;
+    i440_pcidev = d;
 }
 
 static void bios_lock_shadow_ram(void)
 {
-    PCIDevice *d = &i440_pcidev;
+    PCIDevice d = i440_pcidev;
     int v;
 
     wbinvd();
@@ -291,7 +291,7 @@
     pci_config_writeb(d, 0x59, v);
 }
 
-static void pci_bios_init_bridges(PCIDevice *d)
+static void pci_bios_init_bridges(PCIDevice d)
 {
     u16 vendor_id, device_id;
 
@@ -396,7 +396,7 @@
 extern u8 smm_code_start, smm_code_end;
 
 #if (CONFIG_USE_SMM == 1)
-static void smm_init(PCIDevice *d)
+static void smm_init(PCIDevice d)
 {
     u32 value;
 
@@ -422,7 +422,7 @@
             ;
 
         /* enable the SMM memory window */
-        pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x48);
+        pci_config_writeb(i440_pcidev, 0x72, 0x02 | 0x48);
 
         /* copy the SMM code */
         memcpy((void *)0xa8000, &smm_code_start,
@@ -430,12 +430,12 @@
         wbinvd();
 
         /* close the SMM memory window and enable normal SMM */
-        pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x08);
+        pci_config_writeb(i440_pcidev, 0x72, 0x02 | 0x08);
     }
 }
 #endif
 
-static void pci_bios_init_device(PCIDevice *d)
+static void pci_bios_init_device(PCIDevice d)
 {
     int class;
     u32 *paddr;
@@ -445,7 +445,7 @@
     vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
     device_id = pci_config_readw(d, PCI_DEVICE_ID);
     BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n",
-            d->bus, d->devfn, vendor_id, device_id);
+            d.bus, d.devfn, vendor_id, device_id);
     switch(class) {
     case 0x0101:
         if (vendor_id == 0x8086 && device_id == 0x7010) {
@@ -537,16 +537,14 @@
     }
 }
 
-void pci_for_each_device(void (*init_func)(PCIDevice *d))
+void pci_for_each_device(void (*init_func)(PCIDevice d))
 {
-    PCIDevice d1, *d = &d1;
     int bus, devfn;
     u16 vendor_id, device_id;
 
     for(bus = 0; bus < 1; bus++) {
         for(devfn = 0; devfn < 256; devfn++) {
-            d->bus = bus;
-            d->devfn = devfn;
+            PCIDevice d = pci_bd(bus, devfn);
             vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
             device_id = pci_config_readw(d, PCI_DEVICE_ID);
             if (vendor_id != 0xffff || device_id != 0xffff) {