diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2008-11-09 15:33:47 -0500 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2008-11-09 15:33:47 -0500 |
commit | be19cdc4dce80711fad94e6db0ab428761f3170d (patch) | |
tree | 17e4d7ae41c11f268a735f00d69852b0bb701a0f /src | |
parent | ceea03c235f337062b3ded69cc658ea759e254f6 (diff) | |
download | seabios-be19cdc4dce80711fad94e6db0ab428761f3170d.tar.gz |
Overhaul PCI config functions.
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/acpi.c | 9 | ||||
-rw-r--r-- | src/ata.c | 30 | ||||
-rw-r--r-- | src/config.h | 2 | ||||
-rw-r--r-- | src/optionroms.c | 59 | ||||
-rw-r--r-- | src/pci.c | 142 | ||||
-rw-r--r-- | src/pci.h | 36 | ||||
-rw-r--r-- | src/pcibios.c | 52 | ||||
-rw-r--r-- | src/pciinit.c | 98 | ||||
-rw-r--r-- | src/post.c | 2 | ||||
-rw-r--r-- | src/shadow.c | 28 | ||||
-rw-r--r-- | src/smm.c | 26 |
11 files changed, 235 insertions, 249 deletions
@@ -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; @@ -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; diff --git a/src/config.h b/src/config.h index 222017ce..2d9d396f 100644 --- a/src/config.h +++ b/src/config.h @@ -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 diff --git a/src/optionroms.c b/src/optionroms.c index aa6f8bb8..0f34589d 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -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"); @@ -5,119 +5,127 @@ // // 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; } @@ -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(); diff --git a/src/pcibios.c b/src/pcibios.c index c8281cba..65e4a18c 100644 --- a/src/pcibios.c +++ b/src/pcibios.c @@ -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); } diff --git a/src/pciinit.c b/src/pciinit.c index 66ff76aa..9b6e9f64 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -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); } } @@ -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(); diff --git a/src/shadow.c b/src/shadow.c index b99c139e..16319545 100644 --- a/src/shadow.c +++ b/src/shadow.c @@ -20,11 +20,11 @@ // 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); } @@ -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); } |