aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2008-05-24 23:07:16 -0400
committerKevin O'Connor <kevin@koconnor.net>2008-05-24 23:07:16 -0400
commit0f803e460e907c4b8ad5c121ea977d30f87b98dc (patch)
treebd09fc31363f6d1548874e25e62a7c60d61c5355
parent72743f1d1f19979fcd9c35a0baf3e287091e8eef (diff)
downloadseabios-0f803e460e907c4b8ad5c121ea977d30f87b98dc.tar.gz
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.
-rw-r--r--src/config.h4
-rw-r--r--src/ioport.h2
-rw-r--r--src/pci.c84
-rw-r--r--src/pci.h26
-rw-r--r--src/pcibios.c87
-rw-r--r--src/rombios32.c34
6 files changed, 131 insertions, 106 deletions
diff --git a/src/config.h b/src/config.h
index 4ae23dcf..75f5a7f9 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 fe0d7ce8..a51d7135 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 2dd617b7..8d19b811 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 48d47699..b54cd371 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 44a6369e..3e9468a5 100644
--- a/src/pcibios.c
+++ b/src/pcibios.c
@@ -44,7 +44,7 @@ struct pir_table {
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 @@ struct pir_table {
.slot_nr = 5,
},
}
-#endif // CONFIG_PCIBIOS
+#endif // CONFIG_PIRTABLE
};
@@ -146,56 +146,35 @@ handle_1ab101(struct bregs *regs)
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 @@ handle_1ab108(struct bregs *regs)
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 @@ handle_1ab109(struct bregs *regs)
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 @@ handle_1ab10a(struct bregs *regs)
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 @@ handle_1ab10b(struct bregs *regs)
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 @@ handle_1ab10c(struct bregs *regs)
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 @@ handle_1ab10d(struct bregs *regs)
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 @@ handle_1ab1XX(struct bregs *regs)
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 @@ handle_1ab1(struct bregs *regs)
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 fde32a95..6c35b0a7 100644
--- a/src/rombios32.c
+++ b/src/rombios32.c
@@ -197,7 +197,7 @@ static u32 pci_bios_bigmem_addr;
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 @@ static void pci_set_io_region_addr(PCIDevice *d, int region_num, u32 addr)
/* 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 @@ copy_bios(PCIDevice *d, int v)
(__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 @@ static void bios_shadow_init(PCIDevice *d)
// 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 @@ static void bios_shadow_init(PCIDevice *d)
// 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 @@ static void bios_lock_shadow_ram(void)
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_relocation_start, smm_relocation_end;
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 @@ static void smm_init(PCIDevice *d)
;
/* 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 @@ static void smm_init(PCIDevice *d)
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 @@ static void pci_bios_init_device(PCIDevice *d)
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 @@ static void pci_bios_init_device(PCIDevice *d)
}
}
-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) {