Overhaul PCI config functions.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 9 Nov 2008 20:33:47 +0000 (15:33 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Sun, 9 Nov 2008 20:33:47 +0000 (15:33 -0500)
Remove PCIDevice struct and replace with a "u16" with BDF -
    Bus/Device/Function.  This simplifies the code in several places.
Also, scan for and store the maximum PCI bus found during startup.
    The previous config option CONFIG_PCI_BUS_COUNT is no longer
    needed and has been removed.

src/acpi.c
src/ata.c
src/config.h
src/optionroms.c
src/pci.c
src/pci.h
src/pcibios.c
src/pciinit.c
src/post.c
src/shadow.c
src/smm.c

index db4bbb84403b1d049a88f5d14f21fa95bde52188..a1c8b8288003c672d8967d482ca52728d8e38494 100644 (file)
@@ -282,10 +282,9 @@ void acpi_bios_init(void)
     dprintf(3, "init ACPI tables\n");
 
     // This code is hardcoded for PIIX4 Power Management device.
-    PCIDevice d;
-    int ret = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3
-                              , 0, &d);
-    if (ret)
+    int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3
+                              , 0);
+    if (bdf < 0)
         // Device not found
         return;
 
@@ -364,7 +363,7 @@ void acpi_bios_init(void)
     fadt->dsdt = cpu_to_le32(dsdt_addr);
     fadt->model = 1;
     fadt->reserved1 = 0;
-    int pm_sci_int = pci_config_readb(d, PCI_INTERRUPT_LINE);
+    int pm_sci_int = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
     fadt->sci_int = cpu_to_le16(pm_sci_int);
     fadt->smi_cmd = cpu_to_le32(BUILD_SMI_CMD_IO_ADDR);
     fadt->acpi_enable = 0xf1;
index 1cb51eff1a043be0bf7d71de0cd49bc18baaec03..2b384f67c9c2b6f4bc38503e0ee913e61c710d1c 100644 (file)
--- a/src/ata.c
+++ b/src/ata.c
@@ -909,31 +909,29 @@ ata_init()
     }
 
     // Scan PCI bus for ATA adapters
-    int count=0, index=0;
+    int count=0, bdf=-1;
     u16 classid = PCI_CLASS_STORAGE_OTHER; // SATA first
     while (count<CONFIG_MAX_ATA_INTERFACES-1) {
-        PCIDevice d;
-        int ret = pci_find_class(classid, index, &d);
-        if (ret) {
+        bdf = pci_find_class(classid, bdf+1);
+        if (bdf < 0) {
             if (classid == PCI_CLASS_STORAGE_IDE)
                 // Done
                 break;
-            classid = 0x0101; // PATA controllers
-            index = 0;
+            classid = PCI_CLASS_STORAGE_IDE; // PATA controllers
+            bdf = -1;
             continue;
         }
-        index++;
 
-        u8 irq = pci_config_readb(d, PCI_INTERRUPT_LINE);
+        u8 irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
         SET_EBDA(ata.channels[count].irq, irq);
-        SET_EBDA(ata.channels[count].pci_bdf, pci_to_bdf(d));
+        SET_EBDA(ata.channels[count].pci_bdf, bdf);
 
-        u8 prog_if = pci_config_readb(d, PCI_CLASS_PROG);
+        u8 prog_if = pci_config_readb(bdf, PCI_CLASS_PROG);
         u32 port1, port2;
 
-        if (classid != 0x0101 || prog_if & 1) {
-            port1 = pci_config_readl(d, PCI_BASE_ADDRESS_0) & ~3;
-            port2 = pci_config_readl(d, PCI_BASE_ADDRESS_1) & ~3;
+        if (classid != PCI_CLASS_STORAGE_IDE || prog_if & 1) {
+            port1 = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) & ~3;
+            port2 = pci_config_readl(bdf, PCI_BASE_ADDRESS_1) & ~3;
         } else {
             port1 = 0x1f0;
             port2 = 0x3f0;
@@ -943,9 +941,9 @@ ata_init()
         dprintf(1, "ATA controller %d at %x/%x\n", count, port1, port2);
         count++;
 
-        if (classid != 0x0101 || prog_if & 4) {
-            port1 = pci_config_readl(d, PCI_BASE_ADDRESS_2) & ~3;
-            port2 = pci_config_readl(d, PCI_BASE_ADDRESS_3) & ~3;
+        if (classid != PCI_CLASS_STORAGE_IDE || prog_if & 4) {
+            port1 = pci_config_readl(bdf, PCI_BASE_ADDRESS_2) & ~3;
+            port2 = pci_config_readl(bdf, PCI_BASE_ADDRESS_3) & ~3;
         } else {
             port1 = 0x170;
             port2 = 0x370;
index 222017cec551628dcdc24284d9c3beaaad3f29aa..2d9d396ff4ca53f1b8c21e3c31434617e97442b6 100644 (file)
@@ -35,8 +35,6 @@
 #define CONFIG_CDROM_EMU 1
 // Support int 1a/b1 PCI BIOS calls
 #define CONFIG_PCIBIOS 1
-// Maximum number of PCI busses.
-#define CONFIG_PCI_BUS_COUNT 2
 // Support int 15/53 APM BIOS calls
 #define CONFIG_APMBIOS 1
 // Support int 19/18 system bootup support
index aa6f8bb85da9e0a070dffc897bab0a737fd6681d..0f34589d2aa1c023671dd07d13d5248c3a63ad7b 100644 (file)
@@ -162,13 +162,11 @@ add_ipl(struct rom_header *rom, struct pnp_data *pnp)
 
 // Check if an option rom is at a hardcoded location for a device.
 static struct rom_header *
-lookup_hardcode(PCIDevice d)
+lookup_hardcode(u16 bdf)
 {
-    if (OPTIONROM_BDF_1
-        && OPTIONROM_BDF_1 == pci_to_bdf(d))
+    if (OPTIONROM_BDF_1 && OPTIONROM_BDF_1 == bdf)
         return (struct rom_header *)OPTIONROM_MEM_1;
-    else if (OPTIONROM_BDF_2
-        && OPTIONROM_BDF_2 == pci_to_bdf(d))
+    else if (OPTIONROM_BDF_2 && OPTIONROM_BDF_2 == bdf)
         return (struct rom_header *)OPTIONROM_MEM_2;
     // XXX - check LAR when in coreboot?
     return NULL;
@@ -176,18 +174,18 @@ lookup_hardcode(PCIDevice d)
 
 // Map the option rom of a given PCI device.
 static struct rom_header *
-map_optionrom(PCIDevice d)
+map_optionrom(u16 bdf)
 {
-    u32 orig = pci_config_readl(d, PCI_ROM_ADDRESS);
-    pci_config_writel(d, PCI_ROM_ADDRESS, ~PCI_ROM_ADDRESS_ENABLE);
-    u32 sz = pci_config_readl(d, PCI_ROM_ADDRESS);
+    u32 orig = pci_config_readl(bdf, PCI_ROM_ADDRESS);
+    pci_config_writel(bdf, PCI_ROM_ADDRESS, ~PCI_ROM_ADDRESS_ENABLE);
+    u32 sz = pci_config_readl(bdf, PCI_ROM_ADDRESS);
 
     if (!sz || sz == 0xffffffff)
         goto fail;
 
     // Looks like a rom - map it to just above end of memory.
     u32 mappos = ALIGN(GET_EBDA(ram_size), OPTION_ROM_ALIGN);
-    pci_config_writel(d, PCI_ROM_ADDRESS, mappos | PCI_ROM_ADDRESS_ENABLE);
+    pci_config_writel(bdf, PCI_ROM_ADDRESS, mappos | PCI_ROM_ADDRESS_ENABLE);
 
     struct rom_header *rom = (struct rom_header *)mappos;
     if (rom->signature != OPTION_ROM_SIGNATURE)
@@ -196,17 +194,17 @@ map_optionrom(PCIDevice d)
     return rom;
 fail:
     // Not valid - restore original and exit.
-    pci_config_writel(d, PCI_ROM_ADDRESS, orig);
+    pci_config_writel(bdf, PCI_ROM_ADDRESS, orig);
     return NULL;
 }
 
 // Attempt to map and initialize the option rom on a given PCI device.
 static struct rom_header *
-init_optionrom(PCIDevice d)
+init_optionrom(u16 bdf)
 {
-    struct rom_header *rom = lookup_hardcode(d);
+    struct rom_header *rom = lookup_hardcode(bdf);
     if (! rom)
-        rom = map_optionrom(d);
+        rom = map_optionrom(bdf);
     if (! rom)
         // No ROM present.
         return NULL;
@@ -214,12 +212,12 @@ init_optionrom(PCIDevice d)
     u32 romsize = rom->size * 512;
     if (next_rom + romsize > BUILD_BIOS_ADDR) {
         // Option rom doesn't fit.
-        dprintf(1, "Option rom %x doesn't fit.", pci_to_bdf(d));
-        pci_config_writel(d, PCI_ROM_ADDRESS, next_rom);
+        dprintf(1, "Option rom %x doesn't fit.", bdf);
+        pci_config_writel(bdf, PCI_ROM_ADDRESS, next_rom);
         return NULL;
     }
     memcpy((void*)next_rom, rom, romsize);
-    pci_config_writel(d, PCI_ROM_ADDRESS, next_rom);
+    pci_config_writel(bdf, PCI_ROM_ADDRESS, next_rom);
     rom = (struct rom_header *)next_rom;
 
     if (! is_valid_rom(rom))
@@ -227,7 +225,7 @@ init_optionrom(PCIDevice d)
 
     if (get_pnp_rom(rom))
         // Init the PnP rom.
-        callrom(rom, OPTION_ROM_INITVECTOR, pci_to_bdf(d));
+        callrom(rom, OPTION_ROM_INITVECTOR, bdf);
 
     next_rom += ALIGN(rom->size * 512, OPTION_ROM_ALIGN);
 
@@ -265,15 +263,13 @@ optionrom_setup()
         }
     } else {
         // Find and deploy PCI roms.
-        int devfn, bus;
-        for (bus=0; bus < CONFIG_PCI_BUS_COUNT; bus++) {
-            for (devfn=0; devfn<0x100; devfn++) {
-                PCIDevice d = pci_bd(bus, devfn);
-                u16 v = pci_config_readw(d, PCI_CLASS_DEVICE);
-                if (v == 0x0000 || v == 0xffff || v == PCI_CLASS_DISPLAY_VGA)
-                    continue;
-                init_optionrom(d);
-            }
+        int max = GET_VAR(CS, MaxBDF);
+        int bdf;
+        for (bdf=0; bdf < max; bdf++) {
+            u16 v = pci_config_readw(bdf, PCI_CLASS_DEVICE);
+            if (v == 0x0000 || v == 0xffff || v == PCI_CLASS_DISPLAY_VGA)
+                continue;
+            init_optionrom(bdf);
         }
     }
 
@@ -327,16 +323,15 @@ vga_setup()
         next_rom += ALIGN(rom->size * 512, OPTION_ROM_ALIGN);
     } else {
         // Find and deploy PCI VGA rom.
-        PCIDevice d;
-        int ret = pci_find_class(PCI_CLASS_DISPLAY_VGA, 0, &d);
-        if (ret)
+        int bdf = pci_find_class(PCI_CLASS_DISPLAY_VGA, 0);
+        if (bdf < 0)
             // Device not found
             return;
 
-        struct rom_header *rom = init_optionrom(d);
+        struct rom_header *rom = init_optionrom(bdf);
         if (rom && !get_pnp_rom(rom))
             // Call rom even if it isn't a pnp rom.
-            callrom(rom, OPTION_ROM_INITVECTOR, pci_to_bdf(d));
+            callrom(rom, OPTION_ROM_INITVECTOR, bdf);
     }
 
     dprintf(1, "Turning on vga console\n");
index 0d883a2829637f86af4350eeec00092e81b88ca7..f5868865765bf7fab340fd228c3af7e939229947 100644 (file)
--- a/src/pci.c
+++ b/src/pci.c
 //
 // This file may be distributed under the terms of the GNU GPLv3 license.
 
-#include "pci.h" // PCIDevice
+#include "pci.h" // MaxBDF
 #include "ioport.h" // outl
 #include "util.h" // dprintf
 #include "config.h" // CONFIG_*
 #include "pci_regs.h" // PCI_VENDOR_ID
+#include "farptr.h" // SET_VAR
 
-void pci_config_writel(PCIDevice d, u32 addr, u32 val)
+void pci_config_writel(u16 bdf, u32 addr, u32 val)
 {
-    outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
-         , PORT_PCI_CMD);
+    outl(0x80000000 | (bdf << 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(u16 bdf, u32 addr, u16 val)
 {
-    outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
-         , PORT_PCI_CMD);
+    outl(0x80000000 | (bdf << 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(u16 bdf, u32 addr, u8 val)
 {
-    outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
-         , PORT_PCI_CMD);
+    outl(0x80000000 | (bdf << 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(u16 bdf, u32 addr)
 {
-    outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
-         , PORT_PCI_CMD);
+    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
     return inl(PORT_PCI_DATA);
 }
 
-u16 pci_config_readw(PCIDevice d, u32 addr)
+u16 pci_config_readw(u16 bdf, u32 addr)
 {
-    outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
-         , PORT_PCI_CMD);
+    outl(0x80000000 | (bdf << 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(u16 bdf, u32 addr)
 {
-    outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
-         , PORT_PCI_CMD);
+    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
     return inb(PORT_PCI_DATA + (addr & 3));
 }
 
+#if MODE16
+int MaxBDF VISIBLE16;
+#endif
+
+// Find the maximum bus number.
+void
+pci_bus_setup()
+{
+    dprintf(3, "Scan for max PCI bus\n");
+
+    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;
+        v = pci_config_readl(bdf, PCI_PRIMARY_BUS);
+        int newmax = (v & 0xff00) + 0x0100;
+        if (newmax > max)
+            max = newmax;
+    }
+    SET_VAR(CS, MaxBDF, max);
+
+    dprintf(1, "Found %d PCI buses\n", pci_bdf_to_bus(max));
+}
+
+// Search for a device with the specified vendor and device ids.
 int
-pci_find_device(u16 vendid, u16 devid, int index, PCIDevice *dev)
+pci_find_device(u16 vendid, u16 devid, int start_bdf)
 {
-    int devfn, bus;
     u32 id = (devid << 16) | vendid;
-    for (bus=0; bus < CONFIG_PCI_BUS_COUNT; bus++) {
-        for (devfn=0; devfn<0x100; devfn++) {
-            PCIDevice d = pci_bd(bus, devfn);
-            u32 v = pci_config_readl(d, PCI_VENDOR_ID);
-            if (v != id)
-                continue;
-            if (index) {
-                index--;
-                continue;
-            }
-            // Found it.
-            *dev = d;
-            return 0;
-        }
+    int max = GET_VAR(CS, MaxBDF);
+    int bdf;
+    for (bdf=start_bdf; bdf < max; bdf++) {
+        u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
+        if (v != id)
+            continue;
+        // Found it.
+        return bdf;
     }
     return -1;
 }
 
 // Search for a device with the specified class id and prog-if.
 int
-pci_find_classprog(u32 classprog, int index, PCIDevice *dev)
+pci_find_classprog(u32 classprog, int start_bdf)
 {
-    int devfn, bus;
-    for (bus=0; bus < CONFIG_PCI_BUS_COUNT; bus++) {
-        for (devfn=0; devfn<0x100; devfn++) {
-            PCIDevice d = pci_bd(bus, devfn);
-            u32 v = pci_config_readl(d, 0x08);
-            if ((v>>8) != classprog)
-                continue;
-            if (index) {
-                index--;
-                continue;
-            }
-            // Found it.
-            *dev = d;
-            return 0;
-        }
+    int max = GET_VAR(CS, MaxBDF);
+    int bdf;
+    for (bdf=start_bdf; bdf < max; bdf++) {
+        u32 v = pci_config_readl(bdf, PCI_CLASS_REVISION);
+        if ((v>>8) != classprog)
+            continue;
+        // Found it.
+        return bdf;
     }
     return -1;
 }
 
 // Search for a device with the specified class id.
 int
-pci_find_class(u16 classid, int index, PCIDevice *dev)
+pci_find_class(u16 classid, int start_bdf)
 {
-    int devfn, bus;
-    for (bus=0; bus < CONFIG_PCI_BUS_COUNT; bus++) {
-        for (devfn=0; devfn<0x100; devfn++) {
-            PCIDevice d = pci_bd(bus, devfn);
-            u16 v = pci_config_readw(d, PCI_CLASS_DEVICE);
-            if (v != classid)
-                continue;
-            if (index) {
-                index--;
-                continue;
-            }
-            // Found it.
-            *dev = d;
-            return 0;
-        }
+    int max = GET_VAR(CS, MaxBDF);
+    int bdf;
+    for (bdf=start_bdf; bdf < max; bdf++) {
+        u16 v = pci_config_readw(bdf, PCI_CLASS_DEVICE);
+        if (v != classid)
+            continue;
+        // Found it.
+        return bdf;
     }
     return -1;
 }
index cb3b786843ec6b2b6cf45fe97feaa92b6c6e4aed..a18cfb7e217ee231d924f584aaea16bd44e08eb9 100644 (file)
--- a/src/pci.h
+++ b/src/pci.h
@@ -3,21 +3,12 @@
 
 #include "types.h" // u32
 
-typedef struct PCIDevice {
-    u8 bus;
-    u8 devfn;
-} PCIDevice;
-
-static inline PCIDevice pci_bd(u8 bus, u8 devfn) {
-    struct PCIDevice d = {bus, devfn};
-    return d;
-}
-static inline u16 pci_to_bdf(PCIDevice d) {
-    return (d.bus << 8) | d.devfn;
-}
 static inline u8 pci_bdf_to_bus(u16 bdf) {
     return bdf >> 8;
 }
+static inline u8 pci_bdf_to_devfn(u16 bdf) {
+    return bdf & 0xff;
+}
 static inline u8 pci_bdf_to_dev(u16 bdf) {
     return (bdf >> 3) & 0x1f;
 }
@@ -25,16 +16,19 @@ static inline u8 pci_bdf_to_fn(u16 bdf) {
     return bdf & 0x07;
 }
 
-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);
+void pci_config_writel(u16 bdf, u32 addr, u32 val);
+void pci_config_writew(u16 bdf, u32 addr, u16 val);
+void pci_config_writeb(u16 bdf, u32 addr, u8 val);
+u32 pci_config_readl(u16 bdf, u32 addr);
+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);
 
-int pci_find_device(u16 vendid, u16 devid, int index, PCIDevice *dev);
-int pci_find_classprog(u32 classprog, int index, PCIDevice *dev);
-int pci_find_class(u16 classid, int index, PCIDevice *dev);
+extern int MaxBDF;
 
 // pirtable.c
 void create_pirtable();
index c8281cba0011fb1e0087f019a23e961f5c1a4db9..65e4a18c0607ea7422fd7b5a64fce57af48dd21a 100644 (file)
@@ -22,7 +22,7 @@ handle_1ab101(struct bregs *regs)
 {
     regs->al = 0x01; // Flags - "Config Mechanism #1" supported.
     regs->bx = 0x0210; // PCI version 2.10
-    regs->cl = CONFIG_PCI_BUS_COUNT - 1;
+    regs->cl = pci_bdf_to_bus(GET_VAR(CS, MaxBDF) - 1);
     regs->edx = 0x20494350; // "PCI "
     // XXX - bochs bios code sets edi to point to 32bit code - but no
     // reference to this in spec.
@@ -33,14 +33,17 @@ handle_1ab101(struct bregs *regs)
 static void
 handle_1ab102(struct bregs *regs)
 {
-    PCIDevice d;
-    int ret = pci_find_device(regs->dx, regs->cx, regs->si, &d);
-    if (ret) {
-        set_code_fail(regs, RET_DEVICE_NOT_FOUND);
-        return;
-    }
-    regs->bh = d.bus;
-    regs->bl = d.devfn;
+    int bdf = -1;
+    int count = regs->si;
+    do {
+        bdf = pci_find_device(regs->dx, regs->cx, bdf+1);
+        if (bdf < 0) {
+            set_code_fail(regs, RET_DEVICE_NOT_FOUND);
+            return;
+        }
+    } while (count--);
+
+    regs->bx = bdf;
     set_code_success(regs);
 }
 
@@ -48,14 +51,17 @@ handle_1ab102(struct bregs *regs)
 static void
 handle_1ab103(struct bregs *regs)
 {
-    PCIDevice d;
-    int ret = pci_find_classprog(regs->ecx, regs->si, &d);
-    if (ret) {
-        set_code_fail(regs, RET_DEVICE_NOT_FOUND);
-        return;
-    }
-    regs->bh = d.bus;
-    regs->bl = d.devfn;
+    int bdf = -1;
+    int count = regs->si;
+    do {
+        bdf = pci_find_classprog(regs->ecx, bdf+1);
+        if (bdf < 0) {
+            set_code_fail(regs, RET_DEVICE_NOT_FOUND);
+            return;
+        }
+    } while (count--);
+
+    regs->bx = bdf;
     set_code_success(regs);
 }
 
@@ -63,7 +69,7 @@ handle_1ab103(struct bregs *regs)
 static void
 handle_1ab108(struct bregs *regs)
 {
-    regs->cl = pci_config_readb(pci_bd(regs->bh, regs->bl), regs->di);
+    regs->cl = pci_config_readb(regs->bx, regs->di);
     set_code_success(regs);
 }
 
@@ -71,7 +77,7 @@ handle_1ab108(struct bregs *regs)
 static void
 handle_1ab109(struct bregs *regs)
 {
-    regs->cx = pci_config_readw(pci_bd(regs->bh, regs->bl), regs->di);
+    regs->cx = pci_config_readw(regs->bx, regs->di);
     set_code_success(regs);
 }
 
@@ -79,7 +85,7 @@ handle_1ab109(struct bregs *regs)
 static void
 handle_1ab10a(struct bregs *regs)
 {
-    regs->ecx = pci_config_readl(pci_bd(regs->bh, regs->bl), regs->di);
+    regs->ecx = pci_config_readl(regs->bx, regs->di);
     set_code_success(regs);
 }
 
@@ -87,7 +93,7 @@ handle_1ab10a(struct bregs *regs)
 static void
 handle_1ab10b(struct bregs *regs)
 {
-    pci_config_writeb(pci_bd(regs->bh, regs->bl), regs->di, regs->cl);
+    pci_config_writeb(regs->bx, regs->di, regs->cl);
     set_code_success(regs);
 }
 
@@ -95,7 +101,7 @@ handle_1ab10b(struct bregs *regs)
 static void
 handle_1ab10c(struct bregs *regs)
 {
-    pci_config_writew(pci_bd(regs->bh, regs->bl), regs->di, regs->cx);
+    pci_config_writew(regs->bx, regs->di, regs->cx);
     set_code_success(regs);
 }
 
@@ -103,7 +109,7 @@ handle_1ab10c(struct bregs *regs)
 static void
 handle_1ab10d(struct bregs *regs)
 {
-    pci_config_writel(pci_bd(regs->bh, regs->bl), regs->di, regs->ecx);
+    pci_config_writel(regs->bx, regs->di, regs->ecx);
     set_code_success(regs);
 }
 
index 66ff76aa9e1047e1a628bd7052b553a83a730416..9b6e9f64fca58adb825dd9f08d207bdb590cac11 100644 (file)
@@ -6,7 +6,7 @@
 // This file may be distributed under the terms of the GNU GPLv3 license.
 
 #include "util.h" // dprintf
-#include "pci.h" // PCIDevice
+#include "pci.h" // pci_config_readl
 #include "biosvar.h" // GET_EBDA
 #include "pci_ids.h" // PCI_VENDOR_ID_INTEL
 #include "pci_regs.h" // PCI_COMMAND
@@ -24,7 +24,7 @@ static u32 pci_bios_bigmem_addr;
 /* host irqs corresponding to PCI irqs A-D */
 static u8 pci_irqs[4] = { 11, 9, 11, 9 };
 
-static void pci_set_io_region_addr(PCIDevice d, int region_num, u32 addr)
+static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
 {
     u16 cmd;
     u32 ofs, old_addr;
@@ -35,38 +35,35 @@ static void pci_set_io_region_addr(PCIDevice d, int region_num, u32 addr)
         ofs = 0x10 + region_num * 4;
     }
 
-    old_addr = pci_config_readl(d, ofs);
+    old_addr = pci_config_readl(bdf, ofs);
 
-    pci_config_writel(d, ofs, addr);
+    pci_config_writel(bdf, ofs, addr);
     dprintf(1, "region %d: 0x%08x\n", region_num, addr);
 
     /* enable memory mappings */
-    cmd = pci_config_readw(d, PCI_COMMAND);
+    cmd = pci_config_readw(bdf, PCI_COMMAND);
     if ( region_num == PCI_ROM_SLOT )
         cmd |= 2;
     else if (old_addr & PCI_ADDRESS_SPACE_IO)
         cmd |= 1;
     else
         cmd |= 2;
-    pci_config_writew(d, PCI_COMMAND, cmd);
+    pci_config_writew(bdf, PCI_COMMAND, cmd);
 }
 
 /* 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(u16 bdf, int irq_num)
 {
-    int slot_addend;
-    slot_addend = (pci_dev.devfn >> 3) - 1;
+    int slot_addend = pci_bdf_to_dev(bdf) - 1;
     return (irq_num + slot_addend) & 3;
 }
 
-static void pci_bios_init_bridges(PCIDevice d)
+static void pci_bios_init_bridges(u16 bdf)
 {
-    u16 vendor_id, device_id;
-
-    vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
-    device_id = pci_config_readw(d, PCI_DEVICE_ID);
+    u16 vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
+    u16 device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
 
     if (vendor_id == PCI_VENDOR_ID_INTEL
         && (device_id == PCI_DEVICE_ID_INTEL_82371SB_0
@@ -83,7 +80,7 @@ static void pci_bios_init_bridges(PCIDevice d)
             /* set to trigger level */
             elcr[irq >> 3] |= (1 << (irq & 7));
             /* activate irq remapping in PIIX */
-            pci_config_writeb(d, 0x60 + i, irq);
+            pci_config_writeb(bdf, 0x60 + i, irq);
         }
         outb(elcr[0], 0x4d0);
         outb(elcr[1], 0x4d1);
@@ -92,39 +89,39 @@ static void pci_bios_init_bridges(PCIDevice d)
     }
 }
 
-static void pci_bios_init_device(PCIDevice d)
+static void pci_bios_init_device(u16 bdf)
 {
     int class;
     u32 *paddr;
     int i, pin, pic_irq, vendor_id, device_id;
 
-    class = pci_config_readw(d, PCI_CLASS_DEVICE);
-    vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
-    device_id = pci_config_readw(d, PCI_DEVICE_ID);
-    dprintf(1, "PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n",
-            d.bus, d.devfn, vendor_id, device_id);
+    class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
+    vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
+    device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
+    dprintf(1, "PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n"
+            , pci_bdf_to_bus(bdf), pci_bdf_to_devfn(bdf), vendor_id, device_id);
     switch(class) {
     case 0x0101:
         if (vendor_id == PCI_VENDOR_ID_INTEL
             && (device_id == PCI_DEVICE_ID_INTEL_82371SB_1
                 || device_id == PCI_DEVICE_ID_INTEL_82371AB)) {
             /* PIIX3/PIIX4 IDE */
-            pci_config_writew(d, 0x40, 0x8000); // enable IDE0
-            pci_config_writew(d, 0x42, 0x8000); // enable IDE1
+            pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0
+            pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1
             goto default_map;
         } else {
             /* IDE: we map it as in ISA mode */
-            pci_set_io_region_addr(d, 0, 0x1f0);
-            pci_set_io_region_addr(d, 1, 0x3f4);
-            pci_set_io_region_addr(d, 2, 0x170);
-            pci_set_io_region_addr(d, 3, 0x374);
+            pci_set_io_region_addr(bdf, 0, 0x1f0);
+            pci_set_io_region_addr(bdf, 1, 0x3f4);
+            pci_set_io_region_addr(bdf, 2, 0x170);
+            pci_set_io_region_addr(bdf, 3, 0x374);
         }
         break;
     case 0x0300:
         if (vendor_id != 0x1234)
             goto default_map;
         /* VGA: map frame buffer to default Bochs VBE address */
-        pci_set_io_region_addr(d, 0, 0xE0000000);
+        pci_set_io_region_addr(bdf, 0, 0xE0000000);
         break;
     case 0x0800:
         /* PIC */
@@ -132,7 +129,7 @@ static void pci_bios_init_device(PCIDevice d)
             /* IBM */
             if (device_id == 0x0046 || device_id == 0xFFFF) {
                 /* MPIC & MPIC2 */
-                pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
+                pci_set_io_region_addr(bdf, 0, 0x80800000 + 0x00040000);
             }
         }
         break;
@@ -140,7 +137,7 @@ static void pci_bios_init_device(PCIDevice d)
         if (vendor_id == PCI_VENDOR_ID_APPLE &&
             (device_id == 0x0017 || device_id == 0x0022)) {
             /* macio bridge */
-            pci_set_io_region_addr(d, 0, 0x80800000);
+            pci_set_io_region_addr(bdf, 0, 0x80800000);
         }
         break;
     default:
@@ -154,8 +151,8 @@ static void pci_bios_init_device(PCIDevice d)
                 ofs = 0x30;
             else
                 ofs = 0x10 + i * 4;
-            pci_config_writel(d, ofs, 0xffffffff);
-            val = pci_config_readl(d, ofs);
+            pci_config_writel(bdf, ofs, 0xffffffff);
+            val = pci_config_readl(bdf, ofs);
             if (val != 0) {
                 size = (~(val & ~0xf)) + 1;
                 if (val & PCI_ADDRESS_SPACE_IO)
@@ -165,7 +162,7 @@ static void pci_bios_init_device(PCIDevice d)
                 else
                     paddr = &pci_bios_mem_addr;
                 *paddr = ALIGN(*paddr, size);
-                pci_set_io_region_addr(d, i, *paddr);
+                pci_set_io_region_addr(bdf, i, *paddr);
                 *paddr += size;
             }
         }
@@ -173,39 +170,34 @@ static void pci_bios_init_device(PCIDevice d)
     }
 
     /* map the interrupt */
-    pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
+    pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
     if (pin != 0) {
-        pin = pci_slot_get_pirq(d, pin - 1);
+        pin = pci_slot_get_pirq(bdf, pin - 1);
         pic_irq = pci_irqs[pin];
-        pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
+        pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pic_irq);
     }
 
     if (vendor_id == PCI_VENDOR_ID_INTEL
         && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) {
         /* PIIX4 Power Management device (for ACPI) */
         u32 pm_io_base = BUILD_PM_IO_BASE;
-        pci_config_writel(d, 0x40, pm_io_base | 1);
-        pci_config_writeb(d, 0x80, 0x01); /* enable PM io space */
+        pci_config_writel(bdf, 0x40, pm_io_base | 1);
+        pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
         u32 smb_io_base = BUILD_SMB_IO_BASE;
-        pci_config_writel(d, 0x90, smb_io_base | 1);
-        pci_config_writeb(d, 0xd2, 0x09); /* enable SMBus io space */
+        pci_config_writel(bdf, 0x90, smb_io_base | 1);
+        pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
     }
 }
 
-static void pci_for_each_device(void (*init_func)(PCIDevice d))
+static void pci_for_each_device(void (*init_func)(u16 bdf))
 {
-    int bus, devfn;
-    u16 vendor_id, device_id;
-
-    for(bus = 0; bus < 1; bus++) {
-        for(devfn = 0; devfn < 256; 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) {
-                init_func(d);
-            }
-        }
+    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);
     }
 }
 
index 619082b05d42fa3fa863a9be47bbb22c0b1dad83..dc909b2656ff8b8c664dc4d90b4fdb94c4eee966 100644 (file)
@@ -303,6 +303,8 @@ _start()
     debug_serial_setup();
     dprintf(1, "Start bios\n");
 
+    pci_bus_setup();
+
     // Setup for .bss and .data sections
     make_bios_writable();
     clear_bss();
index b99c139ec7ede794b85ebcc6096e1ad5202641ac..1631954534a2f20863e70e298ecebe97020e52c4 100644 (file)
 
 // Enable shadowing and copy bios.
 static void
-copy_bios(PCIDevice d)
+copy_bios(u16 bdf)
 {
-    int v = pci_config_readb(d, 0x59);
+    int v = pci_config_readb(bdf, 0x59);
     v |= 0x30;
-    pci_config_writeb(d, 0x59, v);
+    pci_config_writeb(bdf, 0x59, v);
     memcpy((void *)BUILD_BIOS_ADDR, (void *)BUILD_BIOS_TMP_ADDR
            , BUILD_BIOS_SIZE);
 }
@@ -39,10 +39,8 @@ make_bios_writable()
     dprintf(3, "enabling shadow ram\n");
 
     // Locate chip controlling ram shadowing.
-    PCIDevice d;
-    int ret = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441
-                              , 0, &d);
-    if (ret) {
+    int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, 0);
+    if (bdf < 0) {
         dprintf(1, "Unable to unlock ram - bridge not found\n");
         return;
     }
@@ -57,10 +55,10 @@ make_bios_writable()
         // temporary storage area so that memory does not change under
         // the executing code.
         u32 pos = (u32)copy_bios - BUILD_BIOS_ADDR + BUILD_BIOS_TMP_ADDR;
-        void (*func)(PCIDevice) = (void*)pos;
-        func(d);
+        void (*func)(u16 bdf) = (void*)pos;
+        func(bdf);
     } else {
-        copy_bios(d);
+        copy_bios(bdf);
     }
 
     // Clear the temporary area.
@@ -76,16 +74,14 @@ make_bios_readonly()
 
     dprintf(3, "locking shadow ram\n");
 
-    PCIDevice d;
-    int ret = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441
-                              , 0, &d);
-    if (ret) {
+    int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, 0);
+    if (bdf < 0) {
         dprintf(1, "Unable to lock ram - bridge not found\n");
         return;
     }
 
     wbinvd();
-    int v = pci_config_readb(d, 0x59);
+    int v = pci_config_readb(bdf, 0x59);
     v = (v & 0x0f) | (0x10);
-    pci_config_writeb(d, 0x59, v);
+    pci_config_writeb(bdf, 0x59, v);
 }
index 4e78a25c56f67e7f709009a350fdf17bc225527d..b2140b4a787eb181df2b757c3b6df54a0b101c83 100644 (file)
--- a/src/smm.c
+++ b/src/smm.c
@@ -5,7 +5,7 @@
 //
 // This file may be distributed under the terms of the GNU GPLv3 license.
 
-#include "pci.h" // PCIDevice
+#include "pci.h" // pci_config_writel
 #include "util.h" // wbinvd
 #include "config.h" // CONFIG_*
 #include "ioport.h" // outb
@@ -83,19 +83,18 @@ smm_init()
     dprintf(3, "init smm\n");
 
     // This code is hardcoded for PIIX4 Power Management device.
-    PCIDevice i440_pcidev, d;
-    int ret = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3
-                              , 0, &d);
-    if (ret)
+    int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3
+                              , 0);
+    if (bdf < 0)
         // Device not found
         return;
-    ret = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441
-                          , 0, &i440_pcidev);
-    if (ret)
+    int i440_bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441
+                                   , 0);
+    if (i440_bdf < 0)
         return;
 
     /* check if SMM init is already done */
-    u32 value = pci_config_readl(d, 0x58);
+    u32 value = pci_config_readl(bdf, 0x58);
     if (value & (1 << 25))
         return;
 
@@ -104,7 +103,7 @@ smm_init()
            &smm_relocation_end - &smm_relocation_start);
 
     /* enable SMI generation when writing to the APMC register */
-    pci_config_writel(d, 0x58, value | (1 << 25));
+    pci_config_writel(bdf, 0x58, value | (1 << 25));
 
     /* init APM status port */
     outb(0x01, 0xb3);
@@ -117,13 +116,12 @@ smm_init()
         ;
 
     /* enable the SMM memory window */
-    pci_config_writeb(i440_pcidev, 0x72, 0x02 | 0x48);
+    pci_config_writeb(i440_bdf, 0x72, 0x02 | 0x48);
 
     /* copy the SMM code */
-    memcpy((void *)0xa8000, &smm_code_start,
-           &smm_code_end - &smm_code_start);
+    memcpy((void *)0xa8000, &smm_code_start, &smm_code_end - &smm_code_start);
     wbinvd();
 
     /* close the SMM memory window and enable normal SMM */
-    pci_config_writeb(i440_pcidev, 0x72, 0x02 | 0x08);
+    pci_config_writeb(i440_bdf, 0x72, 0x02 | 0x08);
 }