From 0f803e460e907c4b8ad5c121ea977d30f87b98dc Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sat, 24 May 2008 23:07:16 -0400 Subject: [PATCH] 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. --- src/config.h | 4 +++ src/ioport.h | 2 ++ src/pci.c | 84 +++++++++++++++++++++++++++++++++++++---------- src/pci.h | 26 ++++++++++----- src/pcibios.c | 87 ++++++++++++++----------------------------------- src/rombios32.c | 34 +++++++++---------- 6 files changed, 131 insertions(+), 106 deletions(-) diff --git a/src/config.h b/src/config.h index 4ae23dc..75f5a7f 100644 --- a/src/config.h +++ b/src/config.h @@ -16,6 +16,7 @@ // Configure as a payload coreboot payload. #define CONFIG_COREBOOT 0 +// Send debugging information to serial port #define CONFIG_DEBUG_SERIAL 0 #define CONFIG_FLOPPY_SUPPORT 1 @@ -24,6 +25,9 @@ #define CONFIG_KBD_CALL_INT15_4F 1 #define CONFIG_CDROM_BOOT 1 #define CONFIG_CDROM_EMU 1 +// Support built-in PIR table in 0xf000 segment +#define CONFIG_PIRTABLE 1 +// Support int 1a/b1 PCI BIOS calls #define CONFIG_PCIBIOS 1 /* define it if the (emulated) hardware supports SMM mode */ diff --git a/src/ioport.h b/src/ioport.h index fe0d7ce..a51d713 100644 --- a/src/ioport.h +++ b/src/ioport.h @@ -39,6 +39,8 @@ #define PORT_FD_DATA 0x03f5 #define PORT_HD_DATA 0x03f6 #define PORT_FD_DIR 0x03f7 +#define PORT_PCI_CMD 0x0cf8 +#define PORT_PCI_DATA 0x0cfc #define PORT_BIOS_DEBUG 0x0403 #define PORT_BIOS_APM 0x8900 diff --git a/src/pci.c b/src/pci.c index 2dd617b..8d19b81 100644 --- a/src/pci.c +++ b/src/pci.c @@ -1,38 +1,86 @@ #include "pci.h" // PCIDevice #include "ioport.h" // outl -void pci_config_writel(PCIDevice *d, u32 addr, u32 val) +void pci_config_writel(PCIDevice d, u32 addr, u32 val) { - outl(0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc), 0xcf8); - outl(val, 0xcfc); + outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc) + , PORT_PCI_CMD); + outl(val, PORT_PCI_DATA); } -void pci_config_writew(PCIDevice *d, u32 addr, u16 val) +void pci_config_writew(PCIDevice d, u32 addr, u16 val) { - outl(0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc), 0xcf8); - outw(val, 0xcfc + (addr & 2)); + outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc) + , PORT_PCI_CMD); + outw(val, PORT_PCI_DATA + (addr & 2)); } -void pci_config_writeb(PCIDevice *d, u32 addr, u8 val) +void pci_config_writeb(PCIDevice d, u32 addr, u8 val) { - outl(0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc), 0xcf8); - outb(val, 0xcfc + (addr & 3)); + outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc) + , PORT_PCI_CMD); + outb(val, PORT_PCI_DATA + (addr & 3)); } -u32 pci_config_readl(PCIDevice *d, u32 addr) +u32 pci_config_readl(PCIDevice d, u32 addr) { - outl(0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc), 0xcf8); - return inl(0xcfc); + outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc) + , PORT_PCI_CMD); + return inl(PORT_PCI_DATA); } -u16 pci_config_readw(PCIDevice *d, u32 addr) +u16 pci_config_readw(PCIDevice d, u32 addr) { - outl(0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc), 0xcf8); - return inw(0xcfc + (addr & 2)); + outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc) + , PORT_PCI_CMD); + return inw(PORT_PCI_DATA + (addr & 2)); } -u8 pci_config_readb(PCIDevice *d, u32 addr) +u8 pci_config_readb(PCIDevice d, u32 addr) { - outl(0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc), 0xcf8); - return inb(0xcfc + (addr & 3)); + outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc) + , PORT_PCI_CMD); + return inb(PORT_PCI_DATA + (addr & 3)); +} + +int +pci_find_device(u16 vendid, u16 devid, int index, PCIDevice *dev) +{ + int devfn; + u32 id = (devid << 16) | vendid; + for (devfn=0; devfn<0x100; devfn++) { + PCIDevice d = pci_bd(0, devfn); + u32 v = pci_config_readl(d, 0x00); + if (v != id) + continue; + if (index) { + index--; + continue; + } + // Found it. + *dev = d; + return 0; + } + return -1; +} + +int +pci_find_class(u32 classid, int index, PCIDevice *dev) +{ + int devfn; + u32 id = classid << 8; + for (devfn=0; devfn<0x100; devfn++) { + PCIDevice d = pci_bd(0, devfn); + u32 v = pci_config_readl(d, 0x08); + if (v != id) + continue; + if (index) { + index--; + continue; + } + // Found it. + *dev = d; + return 0; + } + return -1; } diff --git a/src/pci.h b/src/pci.h index 48d4769..b54cd37 100644 --- a/src/pci.h +++ b/src/pci.h @@ -4,15 +4,25 @@ #include "types.h" // u32 typedef struct PCIDevice { - int bus; - int devfn; + u8 bus; + u8 devfn; } PCIDevice; -void pci_config_writel(PCIDevice *d, u32 addr, u32 val); -void pci_config_writew(PCIDevice *d, u32 addr, u16 val); -void pci_config_writeb(PCIDevice *d, u32 addr, u8 val); -u32 pci_config_readl(PCIDevice *d, u32 addr); -u16 pci_config_readw(PCIDevice *d, u32 addr); -u8 pci_config_readb(PCIDevice *d, u32 addr); +static inline PCIDevice +pci_bd(u8 bus, u8 devfn) +{ + struct PCIDevice d = {bus, devfn}; + return d; +} + +void pci_config_writel(PCIDevice d, u32 addr, u32 val); +void pci_config_writew(PCIDevice d, u32 addr, u16 val); +void pci_config_writeb(PCIDevice d, u32 addr, u8 val); +u32 pci_config_readl(PCIDevice d, u32 addr); +u16 pci_config_readw(PCIDevice d, u32 addr); +u8 pci_config_readb(PCIDevice d, u32 addr); + +int pci_find_device(u16 vendid, u16 devid, int index, PCIDevice *dev); +int pci_find_class(u32 classid, int index, PCIDevice *dev); #endif diff --git a/src/pcibios.c b/src/pcibios.c index 44a6369..3e9468a 100644 --- a/src/pcibios.c +++ b/src/pcibios.c @@ -44,7 +44,7 @@ struct pir_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 fde32a9..6c35b0a 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) { -- 2.25.1