X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fpcibios.c;h=8b792fb27b4ffed94f6620dba92de6bb222971ad;hb=ded04a3a21b73a7723831e39972a0f6af4a36914;hp=0dafcf11de4865c790834313db14b00bad9d69cb;hpb=b1b7c2a1c3b940b787fdb5da67fc37003e9d7b0e;p=seabios.git diff --git a/src/pcibios.c b/src/pcibios.c index 0dafcf1..8b792fb 100644 --- a/src/pcibios.c +++ b/src/pcibios.c @@ -12,6 +12,10 @@ #include "biosvar.h" // GET_EBDA #include "pci_regs.h" // PCI_VENDOR_ID +// romlayout.S +extern void entry_bios32(void); +extern void entry_pcibios32(void); + #define RET_FUNC_NOT_SUPPORTED 0x81 #define RET_BAD_VENDOR_ID 0x83 #define RET_DEVICE_NOT_FOUND 0x86 @@ -21,17 +25,11 @@ static void handle_1ab101(struct bregs *regs) { - // Find max bus. - int bdf, max; - foreachpci(bdf, max) { - } - regs->al = 0x01; // Flags - "Config Mechanism #1" supported. regs->bx = 0x0210; // PCI version 2.10 - regs->cl = pci_bdf_to_bus(max - 1); + 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. + regs->edi = (u32)entry_pcibios32 + BUILD_BIOS_ADDR; set_code_success(regs); } @@ -41,18 +39,22 @@ handle_1ab102(struct bregs *regs) { u32 id = (regs->cx << 16) | regs->dx; int count = regs->si; - int bdf, max; - foreachpci(bdf, max) { - u32 v = pci_config_readl(bdf, PCI_VENDOR_ID); - if (v != id) - continue; - if (count--) - continue; - regs->bx = bdf; - set_code_success(regs); - return; + 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; + } } - set_code_fail(regs, RET_DEVICE_NOT_FOUND); + set_code_invalid(regs, RET_DEVICE_NOT_FOUND); } // find class code @@ -61,18 +63,22 @@ handle_1ab103(struct bregs *regs) { int count = regs->si; u32 classprog = regs->ecx; - int bdf, max; - foreachpci(bdf, max) { - 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; + 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; + } } - set_code_fail(regs, RET_DEVICE_NOT_FOUND); + set_code_invalid(regs, RET_DEVICE_NOT_FOUND); } // read configuration byte @@ -129,27 +135,33 @@ handle_1ab10e(struct bregs *regs) { struct pir_header *pirtable_g = (void*)(GET_GLOBAL(PirOffset) + 0); if (! pirtable_g) { - set_code_fail(regs, RET_FUNC_NOT_SUPPORTED); + 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)); - u16 pirsize = (GET_GLOBAL(pirtable_g->size) - - sizeof(struct pir_header)); - 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. - u16 d = (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. - memcpy_far(MAKE_FARPTR(destseg, d) - , MAKE_FARPTR(SEG_BIOS, pirtable_g) + memcpy_far(buf_seg, buf_far + , get_global_seg() + , (void*)(pirtable_g->slots) + get_global_offset() , pirsize); // XXX - bochs bios sets bx to (1 << 9) | (1 << 11) @@ -160,7 +172,7 @@ handle_1ab10e(struct bregs *regs) static void handle_1ab1XX(struct bregs *regs) { - set_code_fail(regs, RET_FUNC_NOT_SUPPORTED); + set_code_unimplemented(regs, RET_FUNC_NOT_SUPPORTED); } void @@ -169,7 +181,7 @@ handle_1ab1(struct bregs *regs) //debug_stub(regs); if (! CONFIG_PCIBIOS) { - set_fail(regs); + set_invalid(regs); return; } @@ -187,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)entry_bios32; + BIOS32HEADER.checksum -= checksum(&BIOS32HEADER, sizeof(BIOS32HEADER)); +}