X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fpcibios.c;h=31ca37e5caa64a802989371a3f6f7516ffe995c7;hb=5044053c84df0d423cdb61fcf29fe2cba2326f31;hp=44a6369edefb7f99a97091e1aba704771eaa128f;hpb=7913f9df87c16b8a4f0b78530ba4f1249ada772d;p=seabios.git diff --git a/src/pcibios.c b/src/pcibios.c index 44a6369..31ca37e 100644 --- a/src/pcibios.c +++ b/src/pcibios.c @@ -1,128 +1,20 @@ -// Low level ATA disk access +// PCI BIOS (int 1a/b1) calls // // Copyright (C) 2008 Kevin O'Connor // Copyright (C) 2002 MandrakeSoft S.A. // -// This file may be distributed under the terms of the GNU GPLv3 license. +// This file may be distributed under the terms of the GNU LGPLv3 license. #include "types.h" // u32 #include "util.h" // handle_1ab1 #include "pci.h" // pci_config_readl +#include "bregs.h" // struct bregs +#include "biosvar.h" // GET_EBDA +#include "pci_regs.h" // PCI_VENDOR_ID - -/**************************************************************** - * PIR table - ****************************************************************/ - -struct pir { - u32 signature; - u16 version; - u16 size; - u8 router_bus; - u8 router_devfunc; - u16 exclusive_irqs; - u32 compatible_devid; - u32 miniport_data; - u8 reserved[11]; - u8 checksum; -} PACKED; - -struct link_info { - u8 link; - u16 bitmap; -} PACKED; - -struct pir_slot { - u8 bus; - u8 dev; - struct link_info links[4]; - u8 slot_nr; - u8 reserved; -} PACKED; - -struct pir_table { - struct pir pir; - struct pir_slot slots[6]; -} PACKED PIR_TABLE VISIBLE16 __attribute__((aligned(16))) = { -#if CONFIG_PCIBIOS - .pir = { - .signature = 0x52495024, // "$PIR" - .version = 0x0100, - .size = sizeof(struct pir_table), - .router_devfunc = 0x08, - .compatible_devid = 0x70008086, - .checksum = 0x07, // XXX - should auto calculate - }, - .slots = { - { - // first slot entry PCI-to-ISA (embedded) - .dev = 1<<3, - .links = { - {.link = 0x60, .bitmap = 0xdef8}, // INTA# - {.link = 0x61, .bitmap = 0xdef8}, // INTB# - {.link = 0x62, .bitmap = 0xdef8}, // INTC# - {.link = 0x63, .bitmap = 0xdef8}, // INTD# - }, - .slot_nr = 0, // embedded - }, { - // second slot entry: 1st PCI slot - .dev = 2<<3, - .links = { - {.link = 0x61, .bitmap = 0xdef8}, // INTA# - {.link = 0x62, .bitmap = 0xdef8}, // INTB# - {.link = 0x63, .bitmap = 0xdef8}, // INTC# - {.link = 0x60, .bitmap = 0xdef8}, // INTD# - }, - .slot_nr = 1, - }, { - // third slot entry: 2nd PCI slot - .dev = 3<<3, - .links = { - {.link = 0x62, .bitmap = 0xdef8}, // INTA# - {.link = 0x63, .bitmap = 0xdef8}, // INTB# - {.link = 0x60, .bitmap = 0xdef8}, // INTC# - {.link = 0x61, .bitmap = 0xdef8}, // INTD# - }, - .slot_nr = 2, - }, { - // 4th slot entry: 3rd PCI slot - .dev = 4<<3, - .links = { - {.link = 0x63, .bitmap = 0xdef8}, // INTA# - {.link = 0x60, .bitmap = 0xdef8}, // INTB# - {.link = 0x61, .bitmap = 0xdef8}, // INTC# - {.link = 0x62, .bitmap = 0xdef8}, // INTD# - }, - .slot_nr = 3, - }, { - // 5th slot entry: 4rd PCI slot - .dev = 5<<3, - .links = { - {.link = 0x60, .bitmap = 0xdef8}, // INTA# - {.link = 0x61, .bitmap = 0xdef8}, // INTB# - {.link = 0x62, .bitmap = 0xdef8}, // INTC# - {.link = 0x63, .bitmap = 0xdef8}, // INTD# - }, - .slot_nr = 4, - }, { - // 6th slot entry: 5rd PCI slot - .dev = 6<<3, - .links = { - {.link = 0x61, .bitmap = 0xdef8}, // INTA# - {.link = 0x62, .bitmap = 0xdef8}, // INTB# - {.link = 0x63, .bitmap = 0xdef8}, // INTC# - {.link = 0x60, .bitmap = 0xdef8}, // INTD# - }, - .slot_nr = 5, - }, - } -#endif // CONFIG_PCIBIOS -}; - - -/**************************************************************** - * Helper functions - ****************************************************************/ +// romlayout.S +extern void bios32_entry(void); +extern void pcibios32_entry(void); #define RET_FUNC_NOT_SUPPORTED 0x81 #define RET_BAD_VENDOR_ID 0x83 @@ -133,69 +25,67 @@ struct pir_table { static void handle_1ab101(struct bregs *regs) { - regs->ax = 0x0001; - regs->bx = 0x0210; - regs->cx = 0; + regs->al = 0x01; // Flags - "Config Mechanism #1" supported. + regs->bx = 0x0210; // PCI version 2.10 + regs->cl = GET_GLOBAL(MaxPCIBus); regs->edx = 0x20494350; // "PCI " - // XXX - bochs bios code sets edi to point to 32bit code - but no - // reference to this in spec. - set_success(regs); + regs->edi = (u32)pcibios32_entry + BUILD_BIOS_ADDR; + set_code_success(regs); } // find pci device 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; + u32 id = (regs->cx << 16) | regs->dx; + int count = regs->si; + int bus = -1; + while (bus < GET_GLOBAL(MaxPCIBus)) { + bus++; + int bdf; + foreachbdf(bdf, bus) { + u32 v = pci_config_readl(bdf, PCI_VENDOR_ID); + if (v != id) + continue; + if (count--) + continue; + regs->bx = bdf; + set_code_success(regs); + return; } - // Found it. - regs->bx = i; - set_code_success(regs); - return; } - set_code_fail(regs, RET_DEVICE_NOT_FOUND); + set_code_invalid(regs, RET_DEVICE_NOT_FOUND); } // 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; + int count = regs->si; + u32 classprog = regs->ecx; + int bus = -1; + while (bus < GET_GLOBAL(MaxPCIBus)) { + bus++; + int bdf; + foreachbdf(bdf, bus) { + u32 v = pci_config_readl(bdf, PCI_CLASS_REVISION); + if ((v>>8) != classprog) + continue; + if (count--) + continue; + regs->bx = bdf; + set_code_success(regs); + return; } - // Found it. - regs->bx = i; - set_code_success(regs); - return; } - set_code_fail(regs, RET_DEVICE_NOT_FOUND); + set_code_invalid(regs, RET_DEVICE_NOT_FOUND); } // 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(regs->bx, regs->di); set_code_success(regs); } @@ -203,8 +93,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(regs->bx, regs->di); set_code_success(regs); } @@ -212,8 +101,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(regs->bx, regs->di); set_code_success(regs); } @@ -221,8 +109,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(regs->bx, regs->di, regs->cl); set_code_success(regs); } @@ -230,8 +117,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(regs->bx, regs->di, regs->cx); set_code_success(regs); } @@ -239,8 +125,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(regs->bx, regs->di, regs->ecx); set_code_success(regs); } @@ -248,61 +133,55 @@ handle_1ab10d(struct bregs *regs) static void handle_1ab10e(struct bregs *regs) { + struct pir_header *pirtable_g = (void*)(GET_GLOBAL(PirOffset) + 0); + if (! pirtable_g) { + set_code_invalid(regs, RET_FUNC_NOT_SUPPORTED); + return; + } + + struct param_s { + u16 size; + u16 buf_off; + u16 buf_seg; + } *param_far = (void*)(regs->di+0); + // Validate and update size. - u16 size = GET_FARVAR(regs->es, *(u16*)(regs->di+0)); - u32 pirsize = sizeof(PIR_TABLE.slots); - SET_FARVAR(regs->es, *(u16*)(regs->di+0), pirsize); - if (size < pirsize) { - set_code_fail(regs, RET_BUFFER_TOO_SMALL); + u16 bufsize = GET_FARVAR(regs->es, param_far->size); + u16 pirsize = GET_GLOBAL(pirtable_g->size) - sizeof(struct pir_header); + SET_FARVAR(regs->es, param_far->size, pirsize); + if (bufsize < pirsize) { + set_code_invalid(regs, RET_BUFFER_TOO_SMALL); return; } // Get dest buffer. - u8 *d = (u8*)(GET_FARVAR(regs->es, *(u16*)(regs->di+2)) + 0); - u16 destseg = GET_FARVAR(regs->es, *(u16*)(regs->di+4)); + void *buf_far = (void*)(GET_FARVAR(regs->es, param_far->buf_off)+0); + u16 buf_seg = GET_FARVAR(regs->es, param_far->buf_seg); // Memcpy pir table slots to dest buffer. - u8 *p = (u8*)PIR_TABLE.slots; - u8 *end = p + pirsize; - for (; pslots) + get_global_offset() + , pirsize); // XXX - bochs bios sets bx to (1 << 9) | (1 << 11) - regs->bx = GET_VAR(CS, PIR_TABLE.pir.exclusive_irqs); + regs->bx = GET_GLOBAL(pirtable_g->exclusive_irqs); set_code_success(regs); } static void handle_1ab1XX(struct bregs *regs) { - set_code_fail(regs, RET_FUNC_NOT_SUPPORTED); + set_code_unimplemented(regs, RET_FUNC_NOT_SUPPORTED); } -#define PCI_FIXED_HOST_BRIDGE 0x12378086 // i440FX PCI bridge - void handle_1ab1(struct bregs *regs) { //debug_stub(regs); if (! CONFIG_PCIBIOS) { - set_fail(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); + set_invalid(regs); return; } @@ -320,3 +199,39 @@ handle_1ab1(struct bregs *regs) default: handle_1ab1XX(regs); break; } } + + +/**************************************************************** + * 32bit interface + ****************************************************************/ + +// Entry point for 32bit pci bios functions. +void VISIBLE32SEG +handle_pcibios32(struct bregs *regs) +{ + debug_enter(regs, DEBUG_HDL_pcibios32); + handle_1ab1(regs); +} + +struct bios32_s { + u32 signature; + u32 entry; + u8 version; + u8 length; + u8 checksum; + u8 reserved[5]; +} PACKED; + +struct bios32_s BIOS32HEADER __aligned(16) VAR16EXPORT = { + .signature = 0x5f32335f, // _32_ + .length = sizeof(BIOS32HEADER) / 16, +}; + +void +bios32_setup(void) +{ + dprintf(3, "init bios32\n"); + + BIOS32HEADER.entry = (u32)bios32_entry; + BIOS32HEADER.checksum -= checksum(&BIOS32HEADER, sizeof(BIOS32HEADER)); +}