aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2008-11-09 15:33:47 -0500
committerKevin O'Connor <kevin@koconnor.net>2008-11-09 15:33:47 -0500
commitbe19cdc4dce80711fad94e6db0ab428761f3170d (patch)
tree17e4d7ae41c11f268a735f00d69852b0bb701a0f /src
parentceea03c235f337062b3ded69cc658ea759e254f6 (diff)
downloadseabios-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.c9
-rw-r--r--src/ata.c30
-rw-r--r--src/config.h2
-rw-r--r--src/optionroms.c59
-rw-r--r--src/pci.c142
-rw-r--r--src/pci.h36
-rw-r--r--src/pcibios.c52
-rw-r--r--src/pciinit.c98
-rw-r--r--src/post.c2
-rw-r--r--src/shadow.c28
-rw-r--r--src/smm.c26
11 files changed, 235 insertions, 249 deletions
diff --git a/src/acpi.c b/src/acpi.c
index db4bbb84..a1c8b828 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -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;
diff --git a/src/ata.c b/src/ata.c
index 1cb51eff..2b384f67 100644
--- 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;
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");
diff --git a/src/pci.c b/src/pci.c
index 0d883a28..f5868865 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -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;
}
diff --git a/src/pci.h b/src/pci.h
index cb3b7868..a18cfb7e 100644
--- 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();
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);
}
}
diff --git a/src/post.c b/src/post.c
index 619082b0..dc909b26 100644
--- a/src/post.c
+++ b/src/post.c
@@ -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);
}
diff --git a/src/smm.c b/src/smm.c
index 4e78a25c..b2140b4a 100644
--- 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);
}