diff options
Diffstat (limited to 'board/MAI/bios_emulator/scitech/src/biosemu')
-rw-r--r-- | board/MAI/bios_emulator/scitech/src/biosemu/besys.c | 408 | ||||
-rw-r--r-- | board/MAI/bios_emulator/scitech/src/biosemu/bios.c | 250 | ||||
-rw-r--r-- | board/MAI/bios_emulator/scitech/src/biosemu/biosemu.c | 445 | ||||
-rw-r--r-- | board/MAI/bios_emulator/scitech/src/biosemu/biosemui.h | 79 | ||||
-rw-r--r-- | board/MAI/bios_emulator/scitech/src/biosemu/makefile | 99 | ||||
-rw-r--r-- | board/MAI/bios_emulator/scitech/src/biosemu/makefile.cross | 10 | ||||
-rw-r--r-- | board/MAI/bios_emulator/scitech/src/biosemu/warmboot.c | 569 |
7 files changed, 1860 insertions, 0 deletions
diff --git a/board/MAI/bios_emulator/scitech/src/biosemu/besys.c b/board/MAI/bios_emulator/scitech/src/biosemu/besys.c new file mode 100644 index 0000000..7f7ea99 --- /dev/null +++ b/board/MAI/bios_emulator/scitech/src/biosemu/besys.c @@ -0,0 +1,408 @@ +/**************************************************************************** +* +* BIOS emulator and interface +* to Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: This file includes BIOS emulator I/O and memory access +* functions. +* +****************************************************************************/ + +#include "biosemui.h" + +/*------------------------------- Macros ----------------------------------*/ + +/* Macros to read and write values to x86 bus memory. Replace these as + * necessary if you need to do something special to access memory over + * the bus on a particular processor family. + */ + +#define readb(base,off) *((u8*)((u32)(base) + (off))) +#define readw(base,off) *((u16*)((u32)(base) + (off))) +#define readl(base,off) *((u32*)((u32)(base) + (off))) +#define writeb(v,base,off) *((u8*)((u32)(base) + (off))) = (v) +#define writew(v,base,off) *((u16*)((u32)(base) + (off))) = (v) +#define writel(v,base,off) *((u32*)((u32)(base) + (off))) = (v) + +/*----------------------------- Implementation ----------------------------*/ + +#ifdef DEBUG +# define DEBUG_MEM() (M.x86.debug & DEBUG_MEM_TRACE_F) +#else +# define DEBUG_MEM() +#endif + +/**************************************************************************** +PARAMETERS: +addr - Emulator memory address to read + +RETURNS: +Byte value read from emulator memory. + +REMARKS: +Reads a byte value from the emulator memory. We have three distinct memory +regions that are handled differently, which this function handles. +****************************************************************************/ +u8 X86API BE_rdb( + u32 addr) +{ + u8 val = 0; + + if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) { + val = *(u8*)(_BE_env.biosmem_base + addr - 0xC0000); + } + else if (addr >= 0xA0000 && addr <= 0xFFFFF) { + val = readb(_BE_env.busmem_base, addr - 0xA0000); + } + else if (addr > M.mem_size - 1) { +DB( printk("mem_read: address %#lx out of range!\n", addr);) + HALT_SYS(); + } + else { + val = *(u8*)(M.mem_base + addr); + } +DB( if (DEBUG_MEM()) + printk("%#08x 1 -> %#x\n", addr, val);) + return val; +} + +/**************************************************************************** +PARAMETERS: +addr - Emulator memory address to read + +RETURNS: +Word value read from emulator memory. + +REMARKS: +Reads a word value from the emulator memory. We have three distinct memory +regions that are handled differently, which this function handles. +****************************************************************************/ +u16 X86API BE_rdw( + u32 addr) +{ + u16 val = 0; + + if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) { +#ifdef __BIG_ENDIAN__ + if (addr & 0x1) { + addr -= 0xC0000; + val = ( *(u8*)(_BE_env.biosmem_base + addr) | + (*(u8*)(_BE_env.biosmem_base + addr + 1) << 8)); + } + else +#endif + val = *(u16*)(_BE_env.biosmem_base + addr - 0xC0000); + } + else if (addr >= 0xA0000 && addr <= 0xFFFFF) { +#ifdef __BIG_ENDIAN__ + if (addr & 0x1) { + addr -= 0xA0000; + val = ( readb(_BE_env.busmem_base, addr) | + (readb(_BE_env.busmem_base, addr + 1) << 8)); + } + else +#endif + val = readw(_BE_env.busmem_base, addr - 0xA0000); + } + else if (addr > M.mem_size - 2) { +DB( printk("mem_read: address %#lx out of range!\n", addr);) + HALT_SYS(); + } + else { +#ifdef __BIG_ENDIAN__ + if (addr & 0x1) { + val = ( *(u8*)(M.mem_base + addr) | + (*(u8*)(M.mem_base + addr + 1) << 8)); + } + else +#endif + val = *(u16*)(M.mem_base + addr); + } +DB( if (DEBUG_MEM()) + printk("%#08x 2 -> %#x\n", addr, val);) + return val; +} + +/**************************************************************************** +PARAMETERS: +addr - Emulator memory address to read + +RETURNS: +Long value read from emulator memory. + +REMARKS: +Reads a long value from the emulator memory. We have three distinct memory +regions that are handled differently, which this function handles. +****************************************************************************/ +u32 X86API BE_rdl( + u32 addr) +{ + u32 val = 0; + + if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) { +#ifdef __BIG_ENDIAN__ + if (addr & 0x3) { + addr -= 0xC0000; + val = ( *(u8*)(_BE_env.biosmem_base + addr + 0) | + (*(u8*)(_BE_env.biosmem_base + addr + 1) << 8) | + (*(u8*)(_BE_env.biosmem_base + addr + 2) << 16) | + (*(u8*)(_BE_env.biosmem_base + addr + 3) << 24)); + } + else +#endif + val = *(u32*)(_BE_env.biosmem_base + addr - 0xC0000); + } + else if (addr >= 0xA0000 && addr <= 0xFFFFF) { +#ifdef __BIG_ENDIAN__ + if (addr & 0x3) { + addr -= 0xA0000; + val = ( readb(_BE_env.busmem_base, addr) | + (readb(_BE_env.busmem_base, addr + 1) << 8) | + (readb(_BE_env.busmem_base, addr + 2) << 16) | + (readb(_BE_env.busmem_base, addr + 3) << 24)); + } + else +#endif + val = readl(_BE_env.busmem_base, addr - 0xA0000); + } + else if (addr > M.mem_size - 4) { +DB( printk("mem_read: address %#lx out of range!\n", addr);) + HALT_SYS(); + } + else { +#ifdef __BIG_ENDIAN__ + if (addr & 0x3) { + val = ( *(u8*)(M.mem_base + addr + 0) | + (*(u8*)(M.mem_base + addr + 1) << 8) | + (*(u8*)(M.mem_base + addr + 2) << 16) | + (*(u8*)(M.mem_base + addr + 3) << 24)); + } + else +#endif + val = *(u32*)(M.mem_base + addr); + } +DB( if (DEBUG_MEM()) + printk("%#08x 4 -> %#x\n", addr, val);) + return val; +} + +/**************************************************************************** +PARAMETERS: +addr - Emulator memory address to read +val - Value to store + +REMARKS: +Writes a byte value to emulator memory. We have three distinct memory +regions that are handled differently, which this function handles. +****************************************************************************/ +void X86API BE_wrb( + u32 addr, + u8 val) +{ +DB( if (DEBUG_MEM()) + printk("%#08x 1 <- %#x\n", addr, val);) + if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) { + *(u8*)(_BE_env.biosmem_base + addr - 0xC0000) = val; + } + else if (addr >= 0xA0000 && addr <= 0xFFFFF) { + writeb(val, _BE_env.busmem_base, addr - 0xA0000); + } + else if (addr > M.mem_size-1) { +DB( printk("mem_write: address %#lx out of range!\n", addr);) + HALT_SYS(); + } + else { + *(u8*)(M.mem_base + addr) = val; + } +} + +/**************************************************************************** +PARAMETERS: +addr - Emulator memory address to read +val - Value to store + +REMARKS: +Writes a word value to emulator memory. We have three distinct memory +regions that are handled differently, which this function handles. +****************************************************************************/ +void X86API BE_wrw( + u32 addr, + u16 val) +{ +DB( if (DEBUG_MEM()) + printk("%#08x 2 <- %#x\n", addr, val);) + if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) { +#ifdef __BIG_ENDIAN__ + if (addr & 0x1) { + addr -= 0xC0000; + *(u8*)(_BE_env.biosmem_base + addr + 0) = (val >> 0) & 0xff; + *(u8*)(_BE_env.biosmem_base + addr + 1) = (val >> 8) & 0xff; + } + else +#endif + *(u16*)(_BE_env.biosmem_base + addr - 0xC0000) = val; + } + else if (addr >= 0xA0000 && addr <= 0xFFFFF) { +#ifdef __BIG_ENDIAN__ + if (addr & 0x1) { + addr -= 0xA0000; + writeb(val >> 0, _BE_env.busmem_base, addr); + writeb(val >> 8, _BE_env.busmem_base, addr + 1); + } + else +#endif + writew(val, _BE_env.busmem_base, addr - 0xA0000); + } + else if (addr > M.mem_size-2) { +DB( printk("mem_write: address %#lx out of range!\n", addr);) + HALT_SYS(); + } + else { +#ifdef __BIG_ENDIAN__ + if (addr & 0x1) { + *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff; + *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff; + } + else +#endif + *(u16*)(M.mem_base + addr) = val; + } +} + +/**************************************************************************** +PARAMETERS: +addr - Emulator memory address to read +val - Value to store + +REMARKS: +Writes a long value to emulator memory. We have three distinct memory +regions that are handled differently, which this function handles. +****************************************************************************/ +void X86API BE_wrl( + u32 addr, + u32 val) +{ +DB( if (DEBUG_MEM()) + printk("%#08x 4 <- %#x\n", addr, val);) + if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) { +#ifdef __BIG_ENDIAN__ + if (addr & 0x1) { + addr -= 0xC0000; + *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff; + *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff; + *(u8*)(M.mem_base + addr + 2) = (val >> 16) & 0xff; + *(u8*)(M.mem_base + addr + 3) = (val >> 24) & 0xff; + } + else +#endif + *(u32*)(M.mem_base + addr - 0xC0000) = val; + } + else if (addr >= 0xA0000 && addr <= 0xFFFFF) { +#ifdef __BIG_ENDIAN__ + if (addr & 0x3) { + addr -= 0xA0000; + writeb(val >> 0, _BE_env.busmem_base, addr); + writeb(val >> 8, _BE_env.busmem_base, addr + 1); + writeb(val >> 16, _BE_env.busmem_base, addr + 1); + writeb(val >> 24, _BE_env.busmem_base, addr + 1); + } + else +#endif + writel(val, _BE_env.busmem_base, addr - 0xA0000); + } + else if (addr > M.mem_size-4) { +DB( printk("mem_write: address %#lx out of range!\n", addr);) + HALT_SYS(); + } + else { +#ifdef __BIG_ENDIAN__ + if (addr & 0x1) { + *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff; + *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff; + *(u8*)(M.mem_base + addr + 2) = (val >> 16) & 0xff; + *(u8*)(M.mem_base + addr + 3) = (val >> 24) & 0xff; + } + else +#endif + *(u32*)(M.mem_base + addr) = val; + } +} + +/* Debug functions to do ISA/PCI bus port I/O */ + +#ifdef DEBUG +#define DEBUG_IO() (M.x86.debug & DEBUG_IO_TRACE_F) + +u8 X86API BE_inb(int port) +{ + u8 val = PM_inpb(port); + if (DEBUG_IO()) + printk("%04X:%04X: inb.%04X -> %02X\n",M.x86.saved_cs, M.x86.saved_ip, (ushort)port, val); + return val; +} + +u16 X86API BE_inw(int port) +{ + u16 val = PM_inpw(port); + if (DEBUG_IO()) + printk("%04X:%04X: inw.%04X -> %04X\n",M.x86.saved_cs, M.x86.saved_ip, (ushort)port, val); + return val; +} + +u32 X86API BE_inl(int port) +{ + u32 val = PM_inpd(port); + if (DEBUG_IO()) + printk("%04X:%04X: inl.%04X -> %08X\n",M.x86.saved_cs, M.x86.saved_ip, (ushort)port, val); + return val; +} + +void X86API BE_outb(int port, u8 val) +{ + if (DEBUG_IO()) + printk("%04X:%04X: outb.%04X <- %02X\n",M.x86.saved_cs, M.x86.saved_ip, (ushort)port, val); + PM_outpb(port,val); +} + +void X86API BE_outw(int port, u16 val) +{ + if (DEBUG_IO()) + printk("%04X:%04X: outw.%04X <- %04X\n",M.x86.saved_cs, M.x86.saved_ip, (ushort)port, val); + PM_outpw(port,val); +} + +void X86API BE_outl(int port, u32 val) +{ + if (DEBUG_IO()) + printk("%04X:%04X: outl.%04X <- %08X\n",M.x86.saved_cs, M.x86.saved_ip, (ushort)port, val); + PM_outpd(port,val); +} +#endif diff --git a/board/MAI/bios_emulator/scitech/src/biosemu/bios.c b/board/MAI/bios_emulator/scitech/src/biosemu/bios.c new file mode 100644 index 0000000..3fb4c36 --- /dev/null +++ b/board/MAI/bios_emulator/scitech/src/biosemu/bios.c @@ -0,0 +1,250 @@ +/**************************************************************************** +* +* BIOS emulator and interface +* to Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Module implementing the BIOS specific functions. +* +****************************************************************************/ + +#include "biosemui.h" + +/*----------------------------- Implementation ----------------------------*/ + +/**************************************************************************** +PARAMETERS: +intno - Interrupt number being serviced + +REMARKS: +Handler for undefined interrupts. +****************************************************************************/ +static void X86API undefined_intr( + int intno) +{ + if (BE_rdw(intno * 4 + 2) == BIOS_SEG) + printk("biosEmu: undefined interrupt %xh called!\n",intno); + else + X86EMU_prepareForInt(intno); +} + +/**************************************************************************** +PARAMETERS: +intno - Interrupt number being serviced + +REMARKS: +This function handles the default system BIOS Int 10h (the default is stored +in the Int 42h vector by the system BIOS at bootup). We only need to handle +a small number of special functions used by the BIOS during POST time. +****************************************************************************/ +static void X86API int42( + int intno) +{ + if (M.x86.R_AH == 0x12 && M.x86.R_BL == 0x32) { + if (M.x86.R_AL == 0) { + /* Enable CPU accesses to video memory */ + PM_outpb(0x3c2, PM_inpb(0x3cc) | (u8)0x02); + return; + } + else if (M.x86.R_AL == 1) { + /* Disable CPU accesses to video memory */ + PM_outpb(0x3c2, PM_inpb(0x3cc) & (u8)~0x02); + return; + } +#ifdef DEBUG + else { + printk("biosEmu/bios.int42: unknown function AH=0x12, BL=0x32, AL=%#02x\n",M.x86.R_AL); + } +#endif + } +#ifdef DEBUG + else { + printk("biosEmu/bios.int42: unknown function AH=%#02x, AL=%#02x, BL=%#02x\n",M.x86.R_AH, M.x86.R_AL, M.x86.R_BL); + } +#endif +} + +/**************************************************************************** +PARAMETERS: +intno - Interrupt number being serviced + +REMARKS: +This function handles the default system BIOS Int 10h. If the POST code +has not yet re-vectored the Int 10h BIOS interrupt vector, we handle this +by simply calling the int42 interrupt handler above. Very early in the +BIOS POST process, the vector gets replaced and we simply let the real +mode interrupt handler process the interrupt. +****************************************************************************/ +static void X86API int10( + int intno) +{ + if (BE_rdw(intno * 4 + 2) == BIOS_SEG) + int42(intno); + else + X86EMU_prepareForInt(intno); +} + +/* Result codes returned by the PCI BIOS */ + +#define SUCCESSFUL 0x00 +#define FUNC_NOT_SUPPORT 0x81 +#define BAD_VENDOR_ID 0x83 +#define DEVICE_NOT_FOUND 0x86 +#define BAD_REGISTER_NUMBER 0x87 +#define SET_FAILED 0x88 +#define BUFFER_TOO_SMALL 0x89 + +/**************************************************************************** +PARAMETERS: +intno - Interrupt number being serviced + +REMARKS: +This function handles the default Int 1Ah interrupt handler for the real +mode code, which provides support for the PCI BIOS functions. Since we only +want to allow the real mode BIOS code *only* see the PCI config space for +its own device, we only return information for the specific PCI config +space that we have passed in to the init function. This solves problems +when using the BIOS to warm boot a secondary adapter when there is an +identical adapter before it on the bus (some BIOS'es get confused in this +case). +****************************************************************************/ +static void X86API int1A( + unused) +{ + u16 pciSlot; + + /* Fail if no PCI device information has been registered */ + if (!_BE_env.vgaInfo.pciInfo) + return; + pciSlot = (u16)(_BE_env.vgaInfo.pciInfo->slot.i >> 8); + switch (M.x86.R_AX) { + case 0xB101: /* PCI bios present? */ + M.x86.R_AL = 0x00; /* no config space/special cycle generation support */ + M.x86.R_EDX = 0x20494350; /* " ICP" */ + M.x86.R_BX = 0x0210; /* Version 2.10 */ + M.x86.R_CL = 0; /* Max bus number in system */ + CLEAR_FLAG(F_CF); + break; + case 0xB102: /* Find PCI device */ + M.x86.R_AH = DEVICE_NOT_FOUND; + if (M.x86.R_DX == _BE_env.vgaInfo.pciInfo->VendorID && + M.x86.R_CX == _BE_env.vgaInfo.pciInfo->DeviceID && + M.x86.R_SI == 0) { + M.x86.R_AH = SUCCESSFUL; + M.x86.R_BX = pciSlot; + } + CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); + break; + case 0xB103: /* Find PCI class code */ + M.x86.R_AH = DEVICE_NOT_FOUND; + if (M.x86.R_CL == _BE_env.vgaInfo.pciInfo->Interface && + M.x86.R_CH == _BE_env.vgaInfo.pciInfo->SubClass && + (u8)(M.x86.R_ECX >> 16) == _BE_env.vgaInfo.pciInfo->BaseClass) { + M.x86.R_AH = SUCCESSFUL; + M.x86.R_BX = pciSlot; + } + CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); + break; + case 0xB108: /* Read configuration byte */ + M.x86.R_AH = BAD_REGISTER_NUMBER; + if (M.x86.R_BX == pciSlot) { + M.x86.R_AH = SUCCESSFUL; + M.x86.R_CL = (u8)PCI_accessReg(M.x86.R_DI,0,PCI_READ_BYTE,_BE_env.vgaInfo.pciInfo); + } + CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); + break; + case 0xB109: /* Read configuration word */ + M.x86.R_AH = BAD_REGISTER_NUMBER; + if (M.x86.R_BX == pciSlot) { + M.x86.R_AH = SUCCESSFUL; + M.x86.R_CX = (u16)PCI_accessReg(M.x86.R_DI,0,PCI_READ_WORD,_BE_env.vgaInfo.pciInfo); + } + CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); + break; + case 0xB10A: /* Read configuration dword */ + M.x86.R_AH = BAD_REGISTER_NUMBER; + if (M.x86.R_BX == pciSlot) { + M.x86.R_AH = SUCCESSFUL; + M.x86.R_ECX = (u32)PCI_accessReg(M.x86.R_DI,0,PCI_READ_DWORD,_BE_env.vgaInfo.pciInfo); + } + CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); + break; + case 0xB10B: /* Write configuration byte */ + M.x86.R_AH = BAD_REGISTER_NUMBER; + if (M.x86.R_BX == pciSlot) { + M.x86.R_AH = SUCCESSFUL; + PCI_accessReg(M.x86.R_DI,M.x86.R_CL,PCI_WRITE_BYTE,_BE_env.vgaInfo.pciInfo); + } + CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); + break; + case 0xB10C: /* Write configuration word */ + M.x86.R_AH = BAD_REGISTER_NUMBER; + if (M.x86.R_BX == pciSlot) { + M.x86.R_AH = SUCCESSFUL; + PCI_accessReg(M.x86.R_DI,M.x86.R_CX,PCI_WRITE_WORD,_BE_env.vgaInfo.pciInfo); + } + CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); + break; + case 0xB10D: /* Write configuration dword */ + M.x86.R_AH = BAD_REGISTER_NUMBER; + if (M.x86.R_BX == pciSlot) { + M.x86.R_AH = SUCCESSFUL; + PCI_accessReg(M.x86.R_DI,M.x86.R_ECX,PCI_WRITE_DWORD,_BE_env.vgaInfo.pciInfo); + } + CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); + break; + default: + printk("biosEmu/bios.int1a: unknown function AX=%#04x\n", M.x86.R_AX); + } +} + +/**************************************************************************** +REMARKS: +This function initialises the BIOS emulation functions for the specific +PCI display device. We insulate the real mode BIOS from any other devices +on the bus, so that it will work correctly thinking that it is the only +device present on the bus (ie: avoiding any adapters present in from of +the device we are trying to control). +****************************************************************************/ +void _BE_bios_init( + u32 *intrTab) +{ + int i; + X86EMU_intrFuncs bios_intr_tab[256]; + + for (i = 0; i < 256; ++i) { + intrTab[i] = BIOS_SEG << 16; + bios_intr_tab[i] = undefined_intr; + } + bios_intr_tab[0x10] = int10; + bios_intr_tab[0x1A] = int1A; + bios_intr_tab[0x42] = int42; + X86EMU_setupIntrFuncs(bios_intr_tab); +} diff --git a/board/MAI/bios_emulator/scitech/src/biosemu/biosemu.c b/board/MAI/bios_emulator/scitech/src/biosemu/biosemu.c new file mode 100644 index 0000000..ed2717c --- /dev/null +++ b/board/MAI/bios_emulator/scitech/src/biosemu/biosemu.c @@ -0,0 +1,445 @@ +/**************************************************************************** +* +* BIOS emulator and interface +* to Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Module implementing the system specific functions. This +* module is always compiled and linked in the OS depedent +* libraries, and never in a binary portable driver. +* +****************************************************************************/ + +#include "biosemui.h" +#include <string.h> +#include <stdlib.h> + +/*------------------------- Global Variables ------------------------------*/ + +BE_sysEnv _BE_env; +#ifdef __DRIVER__ +PM_imports _VARAPI _PM_imports; +#endif +static X86EMU_memFuncs _BE_mem = { + BE_rdb, + BE_rdw, + BE_rdl, + BE_wrb, + BE_wrw, + BE_wrl, + }; +#ifdef DEBUG +static X86EMU_pioFuncs _BE_pio = { + BE_inb, + BE_inw, + BE_inl, + BE_outb, + BE_outw, + BE_outl, + }; +#else +static X86EMU_pioFuncs _BE_pio = { + (void*)PM_inpb, + (void*)PM_inpw, + (void*)PM_inpd, + (void*)PM_outpb, + (void*)PM_outpw, + (void*)PM_outpd, + }; +#endif + +/*-------------------------- Implementation -------------------------------*/ + +#define OFF(addr) (u16)(((addr) >> 0) & 0xffff) +#define SEG(addr) (u16)(((addr) >> 4) & 0xf000) + +/**************************************************************************** +PARAMETERS: +debugFlags - Flags to enable debugging options (debug builds only) +memSize - Amount of memory to allocate for real mode machine +info - Pointer to default VGA device information + +REMARKS: +This functions initialises the BElib, and uses the passed in +BIOS image as the BIOS that is used and emulated at 0xC0000. +****************************************************************************/ +ibool PMAPI BE_init( + u32 debugFlags, + int memSize, + BE_VGAInfo *info) +{ +#ifndef __DRIVER__ + PM_init(); +#endif + memset(&M,0,sizeof(M)); + if (memSize < 20480) + PM_fatalError("Emulator requires at least 20Kb of memory!\n"); + if ((M.mem_base = (unsigned long)malloc(memSize)) == NULL) + PM_fatalError("Out of memory!"); + M.mem_size = memSize; + _BE_env.busmem_base = (ulong)PM_mapPhysicalAddr(0xA0000,0x5FFFF,true); + M.x86.debug = debugFlags; + _BE_bios_init((u32*)info->LowMem); + X86EMU_setupMemFuncs(&_BE_mem); + X86EMU_setupPioFuncs(&_BE_pio); + BE_setVGA(info); + return true; +} + +/**************************************************************************** +PARAMETERS: +debugFlags - Flags to enable debugging options (debug builds only) + +REMARKS: +This function allows the application to enable logging and debug flags +on a function call basis, so we can specifically enable logging only +for specific functions that are causing problems in debug mode. +****************************************************************************/ +void PMAPI BE_setDebugFlags( + u32 debugFlags) +{ + M.x86.debug = debugFlags; +} + +/**************************************************************************** +PARAMETERS: +info - Pointer to VGA device information to make current + +REMARKS: +This function sets the VGA BIOS functions in the emulator to point to the +specific VGA BIOS in use. This includes swapping the BIOS interrupt +vectors, BIOS image and BIOS data area to the new BIOS. This allows the +real mode BIOS to be swapped without resetting the entire emulator. +****************************************************************************/ +void PMAPI BE_setVGA( + BE_VGAInfo *info) +{ + _BE_env.vgaInfo.pciInfo = info->pciInfo; + _BE_env.vgaInfo.BIOSImage = info->BIOSImage; + if (info->BIOSImage) { + _BE_env.biosmem_base = (ulong)info->BIOSImage; + _BE_env.biosmem_limit = 0xC0000 + info->BIOSImageLen-1; + } + else { + _BE_env.biosmem_base = _BE_env.busmem_base + 0x20000; + _BE_env.biosmem_limit = 0xC7FFF; + } + if (*((u32*)info->LowMem) == 0) + _BE_bios_init((u32*)info->LowMem); + memcpy((u8*)M.mem_base,info->LowMem,sizeof(info->LowMem)); +} + +/**************************************************************************** +PARAMETERS: +info - Pointer to VGA device information to retrieve current + +REMARKS: +This function returns the VGA BIOS functions currently active in the +emulator, so they can be restored at a later date. +****************************************************************************/ +void PMAPI BE_getVGA( + BE_VGAInfo *info) +{ + info->pciInfo = _BE_env.vgaInfo.pciInfo; + info->BIOSImage = _BE_env.vgaInfo.BIOSImage; + memcpy(info->LowMem,(u8*)M.mem_base,sizeof(info->LowMem)); +} + +/**************************************************************************** +PARAMETERS: +r_seg - Segment for pointer to convert +r_off - Offset for pointer to convert + +REMARKS: +This function maps a real mode pointer in the emulator memory to a protected +mode pointer that can be used to directly access the memory. + +NOTE: The memory is *always* in little endian format, son on non-x86 + systems you will need to do endian translations to access this + memory. +****************************************************************************/ +void * PMAPI BE_mapRealPointer( + uint r_seg, + uint r_off) +{ + u32 addr = ((u32)r_seg << 4) + r_off; + + if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) { + return (void*)(_BE_env.biosmem_base + addr - 0xC0000); + } + else if (addr >= 0xA0000 && addr <= 0xFFFFF) { + return (void*)(_BE_env.busmem_base + addr - 0xA0000); + } + return (void*)(M.mem_base + addr); +} + +/**************************************************************************** +PARAMETERS: +len - Return the length of the VESA buffer +rseg - Place to store VESA buffer segment +roff - Place to store VESA buffer offset + +REMARKS: +This function returns the address of the VESA transfer buffer in real +mode emulator memory. The VESA transfer buffer is always 1024 bytes long, +and located at 15Kb into the start of the real mode memory (16Kb is where +we put the real mode code we execute for issuing interrupts). + +NOTE: The memory is *always* in little endian format, son on non-x86 + systems you will need to do endian translations to access this + memory. +****************************************************************************/ +void * PMAPI BE_getVESABuf( + uint *len, + uint *rseg, + uint *roff) +{ + *len = 1024; + *rseg = SEG(0x03C00); + *roff = OFF(0x03C00); + return (void*)(M.mem_base + ((u32)*rseg << 4) + *roff); +} + +/**************************************************************************** +REMARKS: +Cleans up and exits the emulator. +****************************************************************************/ +void PMAPI BE_exit(void) +{ + free((void*)M.mem_base); + PM_freePhysicalAddr((void*)_BE_env.busmem_base,0x5FFFF); +} + +/**************************************************************************** +PARAMETERS: +seg - Segment of code to call +off - Offset of code to call +regs - Real mode registers to load +sregs - Real mode segment registers to load + +REMARKS: +This functions calls a real mode far function at the specified address, +and loads all the x86 registers from the passed in registers structure. +On exit the registers returned from the call are returned in the same +structures. +****************************************************************************/ +void PMAPI BE_callRealMode( + uint seg, + uint off, + RMREGS *regs, + RMSREGS *sregs) +{ + M.x86.R_EAX = regs->e.eax; + M.x86.R_EBX = regs->e.ebx; + M.x86.R_ECX = regs->e.ecx; + M.x86.R_EDX = regs->e.edx; + M.x86.R_ESI = regs->e.esi; + M.x86.R_EDI = regs->e.edi; + M.x86.R_DS = sregs->ds; + M.x86.R_ES = sregs->es; + M.x86.R_FS = sregs->fs; + M.x86.R_GS = sregs->gs; + M.x86.R_CS = (u16)seg; + M.x86.R_IP = (u16)off; + M.x86.R_SS = SEG(M.mem_size - 1); + M.x86.R_SP = OFF(M.mem_size - 1); + X86EMU_exec(); + regs->e.cflag = M.x86.R_EFLG & F_CF; + regs->e.eax = M.x86.R_EAX; + regs->e.ebx = M.x86.R_EBX; + regs->e.ecx = M.x86.R_ECX; + regs->e.edx = M.x86.R_EDX; + regs->e.esi = M.x86.R_ESI; + regs->e.edi = M.x86.R_EDI; + sregs->ds = M.x86.R_DS; + sregs->es = M.x86.R_ES; + sregs->fs = M.x86.R_FS; + sregs->gs = M.x86.R_GS; +} + +/**************************************************************************** +PARAMETERS: +intno - Interrupt number to execute +in - Real mode registers to load +out - Place to store resulting real mode registers + +REMARKS: +This functions calls a real mode interrupt function at the specified address, +and loads all the x86 registers from the passed in registers structure. +On exit the registers returned from the call are returned in out stucture. +****************************************************************************/ +int PMAPI BE_int86( + int intno, + RMREGS *in, + RMREGS *out) +{ + M.x86.R_EAX = in->e.eax; + M.x86.R_EBX = in->e.ebx; + M.x86.R_ECX = in->e.ecx; + M.x86.R_EDX = in->e.edx; + M.x86.R_ESI = in->e.esi; + M.x86.R_EDI = in->e.edi; + ((u8*)M.mem_base)[0x4000] = 0xCD; + ((u8*)M.mem_base)[0x4001] = (u8)intno; + ((u8*)M.mem_base)[0x4002] = 0xC3; + M.x86.R_CS = SEG(0x04000); + M.x86.R_IP = OFF(0x04000); + M.x86.R_SS = SEG(M.mem_size - 1); + M.x86.R_SP = OFF(M.mem_size - 1); + X86EMU_exec(); + out->e.cflag = M.x86.R_EFLG & F_CF; + out->e.eax = M.x86.R_EAX; + out->e.ebx = M.x86.R_EBX; + out->e.ecx = M.x86.R_ECX; + out->e.edx = M.x86.R_EDX; + out->e.esi = M.x86.R_ESI; + out->e.edi = M.x86.R_EDI; + return out->x.ax; +} + +/**************************************************************************** +PARAMETERS: +intno - Interrupt number to execute +in - Real mode registers to load +out - Place to store resulting real mode registers +sregs - Real mode segment registers to load + +REMARKS: +This functions calls a real mode interrupt function at the specified address, +and loads all the x86 registers from the passed in registers structure. +On exit the registers returned from the call are returned in out stucture. +****************************************************************************/ +int PMAPI BE_int86x( + int intno, + RMREGS *in, + RMREGS *out, + RMSREGS *sregs) +{ + M.x86.R_EAX = in->e.eax; + M.x86.R_EBX = in->e.ebx; + M.x86.R_ECX = in->e.ecx; + M.x86.R_EDX = in->e.edx; + M.x86.R_ESI = in->e.esi; + M.x86.R_EDI = in->e.edi; + M.x86.R_DS = sregs->ds; + M.x86.R_ES = sregs->es; + M.x86.R_FS = sregs->fs; + M.x86.R_GS = sregs->gs; + ((u8*)M.mem_base)[0x4000] = 0xCD; + ((u8*)M.mem_base)[0x4001] = (u8)intno; + ((u8*)M.mem_base)[0x4002] = 0xC3; + M.x86.R_CS = SEG(0x04000); + M.x86.R_IP = OFF(0x04000); + M.x86.R_SS = SEG(M.mem_size - 1); + M.x86.R_SP = OFF(M.mem_size - 1); + X86EMU_exec(); + out->e.cflag = M.x86.R_EFLG & F_CF; + out->e.eax = M.x86.R_EAX; + out->e.ebx = M.x86.R_EBX; + out->e.ecx = M.x86.R_ECX; + out->e.edx = M.x86.R_EDX; + out->e.esi = M.x86.R_ESI; + out->e.edi = M.x86.R_EDI; + sregs->ds = M.x86.R_DS; + sregs->es = M.x86.R_ES; + sregs->fs = M.x86.R_FS; + sregs->gs = M.x86.R_GS; + return out->x.ax; +} + +#ifdef __DRIVER__ + +/**************************************************************************** +REMARKS: +Empty log function for binary portable DLL. The BPD is compiled without +debug information, so very little is logged anyway so it is simpler this +way. +****************************************************************************/ +void printk(const char *msg, ...) +{ +} + +/**************************************************************************** +REMARKS: +Fatal error handler called when a non-imported function is called by the +driver. We leave this to a runtime error so that older applications and +shell drivers will work with newer bpd drivers provided no newer functions +are required by the driver itself. If they are, the application or shell +driver needs to be recompiled. +****************************************************************************/ +static void _PM_fatalErrorHandler(void) +{ + PM_fatalError("Unsupported PM_imports import function called! Please re-compile!\n"); +} + +/**************************************************************************** +PARAMETERS: +beImp - BE library imports +beImp - Generic emulator imports + +RETURNS: +Pointer to exported function list + +REMARKS: +This function initialises the BIOS emulator library and returns the list of +loader library exported functions. +{secret} +****************************************************************************/ +BE_exports * _CEXPORT BE_initLibrary( + PM_imports *pmImp) +{ + static BE_exports _BE_exports = { + sizeof(BE_exports), + BE_init, + BE_setVGA, + BE_getVGA, + BE_mapRealPointer, + BE_getVESABuf, + BE_callRealMode, + BE_int86, + BE_int86x, + NULL, + BE_exit, + }; + int i,max; + ulong *p; + + // Initialize all default imports to point to fatal error handler + // for upwards compatibility. + max = sizeof(_PM_imports)/sizeof(BE_initLibrary_t); + for (i = 0,p = (ulong*)&_PM_imports; i < max; i++) + *p++ = (ulong)_PM_fatalErrorHandler; + + // Now copy all our imported functions + memcpy(&_PM_imports,pmImp,MIN(sizeof(_PM_imports),pmImp->dwSize)); + return &_BE_exports; +} + +#endif /* __DRIVER__ */ diff --git a/board/MAI/bios_emulator/scitech/src/biosemu/biosemui.h b/board/MAI/bios_emulator/scitech/src/biosemu/biosemui.h new file mode 100644 index 0000000..23edebc --- /dev/null +++ b/board/MAI/bios_emulator/scitech/src/biosemu/biosemui.h @@ -0,0 +1,79 @@ +/**************************************************************************** +* +* BIOS emulator and interface +* to Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Internal header file for the BIOS emulator library. +* +****************************************************************************/ + +#ifndef __BIOSEMUI_H +#define __BIOSEMUI_H + +#include <biosemu.h> + +/*---------------------- Macros and type definitions ----------------------*/ + +#ifdef DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +#define BIOS_SEG 0xfff0 + +#define M _X86EMU_env + +/*-------------------------- Function Prototypes --------------------------*/ + +/* bios.c */ + +void _BE_bios_init(u32 *intrTab); +void _BE_setup_funcs(void); + +/* besys.c */ + +u8 X86API BE_rdb(u32 addr); +u16 X86API BE_rdw(u32 addr); +u32 X86API BE_rdl(u32 addr); +void X86API BE_wrb(u32 addr,u8 val); +void X86API BE_wrw(u32 addr,u16 val); +void X86API BE_wrl(u32 addr,u32 val); +#ifdef DEBUG +u8 X86API BE_inb(int port); +u16 X86API BE_inw(int port); +u32 X86API BE_inl(int port); +void X86API BE_outb(int port, u8 val); +void X86API BE_outw(int port, u16 val); +void X86API BE_outl(int port, u32 val); +#endif + +#endif /* __BIOSEMUI_H */ diff --git a/board/MAI/bios_emulator/scitech/src/biosemu/makefile b/board/MAI/bios_emulator/scitech/src/biosemu/makefile new file mode 100644 index 0000000..80730b2 --- /dev/null +++ b/board/MAI/bios_emulator/scitech/src/biosemu/makefile @@ -0,0 +1,99 @@ +############################################################################# +# +# BIOS emulator and interface +# to Realmode X86 Emulator Library +# +# Copyright (C) 1996-1999 SciTech Software, Inc. +# +# ======================================================================== +# +# Permission to use, copy, modify, distribute, and sell this software and +# its documentation for any purpose is hereby granted without fee, +# provided that the above copyright notice appear in all copies and that +# both that copyright notice and this permission notice appear in +# supporting documentation, and that the name of the authors not be used +# in advertising or publicity pertaining to distribution of the software +# without specific, written prior permission. The authors makes no +# representations about the suitability of this software for any purpose. +# It is provided "as is" without express or implied warranty. +# +# THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# +# ======================================================================== +# +# Descripton: Generic makefile for the x86emu library. Requires +# the SciTech Software makefile definitions package to be +# installed, which uses the DMAKE make program. +# +############################################################################# + +.IMPORT .IGNORE: DEBUG + +#---------------------------------------------------------------------------- +# Define the lists of object files +#---------------------------------------------------------------------------- + +DLL_OBJS = dllstart$O _pm_imp$O +BIOS_OBJS = biosemu$O bios$O besys$O +X86_OBJS = sys$O decode$O ops$O ops2$O prim_ops$O fpu$O debug$O +CFLAGS += -DSCITECH -I$(SCITECH)\src\x86emu + +.IF $(BUILD_DLL) + +CFLAGS += -I$(PRIVATE)\include\drvlib -I$(SCITECH)\include\drvlib -D__DRIVER__ +ASFLAGS += -d__DRIVER__ +EXELIBS = drvlib$L + +.ELSE + +.IF $(DEBUG) +CFLAGS += -DDEBUG +.ENDIF +OBJECTS = $(BIOS_OBJS) $(X86_OBJS) +LIBCLEAN = *.dll *.lib *.a +LIBFILE = $(LP)biosemu$L + +.ENDIF + +#---------------------------------------------------------------------------- +# Sample test programs +#---------------------------------------------------------------------------- + +all: $(LIBFILE) warmboot$E + +warmboot$E: warmboot$O $(LIBFILE) + +#---------------------------------------------------------------------------- +# Target to build the Binary Portable DLL target +#---------------------------------------------------------------------------- + +biosemu.dll: $(DLL_OBJS) $(BIOS_OBJS) $(X86_OBJS) + +#---------------------------------------------------------------------------- +# Target to build all Intel binary drivers +#---------------------------------------------------------------------------- + +.PHONY mkdrv: + @build wc11-w32 biosemu.dll -u BUILD_DLL=1 NO_RUNTIME=1 OPT=1 + @$(CP) biosemu.dll $(PRIVATE)\nucleus\graphics\biosemu.bpd + @dmake cleanexe + +.PHONY db: + @build wc11-w32 biosemu.dll BUILD_DLL=1 NO_RUNTIME=1 OPT=1 + @$(CP) biosemu.dll $(PRIVATE)\nucleus\graphics\biosemu.bpd + +#---------------------------------------------------------------------------- +# Define the list of object files to create dependency information for +#---------------------------------------------------------------------------- + +DEPEND_OBJ = warmboot$O $(BIOS_OBJS) $(X86_OBJS) $(DLL_OBJS) +DEPEND_SRC = $(SCITECH)/src/x86emu;$(PRIVATE)/src/common +.SOURCE: $(SCITECH)/src/x86emu $(PRIVATE)/src/common + +.INCLUDE: "$(SCITECH)/makedefs/common.mk" diff --git a/board/MAI/bios_emulator/scitech/src/biosemu/makefile.cross b/board/MAI/bios_emulator/scitech/src/biosemu/makefile.cross new file mode 100644 index 0000000..9141003 --- /dev/null +++ b/board/MAI/bios_emulator/scitech/src/biosemu/makefile.cross @@ -0,0 +1,10 @@ +CC = ppc-elf32-gcc +AR = ppc-elf32-ar + +CFLAGS = -D__DRIVER__ -I../../include -DDEBUG -I. + +BIOS_OBJS = biosemu.o bios.o besys.o +X86_OBJS = sys.o decode.o ops.o prim_ops.o fpu.o debug.o + +libbios.a: $(BIOS_OBJS) + $(AR) rcs libbios.a $(BIOS_OBJS)
\ No newline at end of file diff --git a/board/MAI/bios_emulator/scitech/src/biosemu/warmboot.c b/board/MAI/bios_emulator/scitech/src/biosemu/warmboot.c new file mode 100644 index 0000000..96fa5a0 --- /dev/null +++ b/board/MAI/bios_emulator/scitech/src/biosemu/warmboot.c @@ -0,0 +1,569 @@ +/**************************************************************************** +* +* BIOS emulator and interface +* to Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Module to implement warm booting of all PCI/AGP controllers +* on the bus. We use the x86 real mode emulator to run the +* BIOS on the primary and secondary controllers to bring +* the cards up. +* +****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include "biosemu.h" +#ifndef _MAX_PATH +#define _MAX_PATH 256 +#endif + +/*------------------------- Global Variables ------------------------------*/ + +static PCIDeviceInfo PCI[MAX_PCI_DEVICES]; +static int NumPCI = -1; +static int BridgeIndex[MAX_PCI_DEVICES] = {0}; +static int NumBridges; +static PCIBridgeInfo *AGPBridge = NULL; +static int DeviceIndex[MAX_PCI_DEVICES] = {0}; +static int NumDevices; +static u32 debugFlags = 0; +static BE_VGAInfo VGAInfo[MAX_PCI_DEVICES] = {{0}}; +static ibool useV86 = false; +static ibool forcePost = false; + +/* Length of the BIOS image */ + +#define MAX_BIOSLEN (64 * 1024L) +#define FINAL_BIOSLEN (32 * 1024L) + +/* Macro to determine if the VGA is enabled and responding */ + +#define VGA_NOT_ACTIVE() (forcePost || (PM_inpb(0x3CC) == 0xFF) || ((PM_inpb(0x3CC) & 0x2) == 0)) + +#define ENABLE_DEVICE(device) \ + PCI_writePCIRegB(0x4,PCI[DeviceIndex[device]].Command | 0x7,device) + +#define DISABLE_DEVICE(device) \ + PCI_writePCIRegB(0x4,0,device) + +/* Macros to enable and disable AGP VGA resources */ + +#define ENABLE_AGP_VGA() \ + PCI_accessReg(0x3E,AGPBridge->BridgeControl | 0x8,PCI_WRITE_WORD,(PCIDeviceInfo*)AGPBridge) + +#define DISABLE_AGP_VGA() \ + PCI_accessReg(0x3E,AGPBridge->BridgeControl & ~0x8,PCI_WRITE_WORD,(PCIDeviceInfo*)AGPBridge) + +#define RESTORE_AGP_VGA() \ + PCI_accessReg(0x3E,AGPBridge->BridgeControl,PCI_WRITE_WORD,(PCIDeviceInfo*)AGPBridge) + +/*-------------------------- Implementation -------------------------------*/ + +/**************************************************************************** +RETURNS: +The address to use to map the secondary BIOS (PCI/AGP devices) + +REMARKS: +Searches all the PCI base address registers for the device looking for a +memory mapping that is large enough to hold our ROM BIOS. We usually end up +finding the framebuffer mapping (usually BAR 0x10), and we use this mapping +to map the BIOS for the device into. We use a mapping that is already +assigned to the device to ensure the memory range will be passed through +by any PCI->PCI or AGP->PCI bridge that may be present. + +NOTE: Usually this function is only used for AGP devices, but it may be + used for PCI devices that have already been POST'ed and the BIOS + ROM base address has been zero'ed out. +****************************************************************************/ +static ulong PCI_findBIOSAddr( + int device) +{ + ulong base,size; + int bar; + + for (bar = 0x10; bar <= 0x14; bar++) { + base = PCI_readPCIRegL(bar,device) & ~0xFF; + if (!(base & 0x1)) { + PCI_writePCIRegL(bar,0xFFFFFFFF,device); + size = PCI_readPCIRegL(bar,device) & ~0xFF; + size = ~size+1; + PCI_writePCIRegL(bar,0,device); + if (size >= MAX_BIOSLEN) + return base; + } + } + return 0; +} + +/**************************************************************************** +REMARKS: +Re-writes the PCI base address registers for the secondary PCI controller +with the values from our initial PCI bus enumeration. This fixes up the +values after we have POST'ed the secondary display controller BIOS, which +may have incorrectly re-programmed the base registers the same as the +primary display controller (the case for identical S3 cards). +****************************************************************************/ +static void _PCI_fixupSecondaryBARs(void) +{ + int i; + + for (i = 0; i < NumDevices; i++) { + PCI_writePCIRegL(0x10,PCI[DeviceIndex[i]].BaseAddress10,i); + PCI_writePCIRegL(0x14,PCI[DeviceIndex[i]].BaseAddress14,i); + PCI_writePCIRegL(0x18,PCI[DeviceIndex[i]].BaseAddress18,i); + PCI_writePCIRegL(0x1C,PCI[DeviceIndex[i]].BaseAddress1C,i); + PCI_writePCIRegL(0x20,PCI[DeviceIndex[i]].BaseAddress20,i); + PCI_writePCIRegL(0x24,PCI[DeviceIndex[i]].BaseAddress24,i); + } +} + +/**************************************************************************** +RETURNS: +True if successfully initialised, false if not. + +REMARKS: +This function executes the BIOS POST code on the controller. We assume that +at this stage the controller has its I/O and memory space enabled and +that all other controllers are in a disabled state. +****************************************************************************/ +static void PCI_doBIOSPOST( + int device, + ulong BIOSPhysAddr, + void *mappedBIOS, + ulong BIOSLen) +{ + RMREGS regs; + RMSREGS sregs; + + // Determine the value to store in AX for BIOS POST + regs.x.ax = (u16)(PCI[DeviceIndex[device]].slot.i >> 8); + if (useV86) { + // Post the BIOS using the PM functions (ie: v86 mode on Linux) + if (!PM_doBIOSPOST(regs.x.ax,BIOSPhysAddr,mappedBIOS,BIOSLen)) { + // If the PM function fails, this probably means are we are on + // DOS and can't re-map the real mode 0xC0000 region. In thise + // case if the device is the primary, we can use the real + // BIOS at 0xC0000 directly. + if (device == 0) + PM_doBIOSPOST(regs.x.ax,0xC0000,mappedBIOS,BIOSLen); + } + } + else { + // Setup the X86 emulator for the VGA BIOS + BE_setVGA(&VGAInfo[device]); + + // Execute the BIOS POST code + BE_callRealMode(0xC000,0x0003,®s,&sregs); + + // Cleanup and exit + BE_getVGA(&VGAInfo[device]); + } +} + +/**************************************************************************** +RETURNS: +True if successfully initialised, false if not. + +REMARKS: +Loads and POST's the secondary controllers BIOS, directly from the BIOS +image we can extract over the PCI bus. +****************************************************************************/ +static ibool PCI_postControllers(void) +{ + int device; + ulong BIOSImageLen,mappedBIOSPhys; + uchar *mappedBIOS,*copyOfBIOS; + char filename[_MAX_PATH]; + FILE *f; + + // Disable the primary display controller and AGP VGA pass-through + DISABLE_DEVICE(0); + if (AGPBridge) + DISABLE_AGP_VGA(); + + // Now POST all the secondary controllers + for (device = 0; device < NumDevices; device++) { + // Skip the device if it is not enabled (probably an ISA device) + if (DeviceIndex[device] == -1) + continue; + + // Enable secondary display controller. If the secondary controller + // is on the AGP bus, then enable VGA resources for the AGP device. + ENABLE_DEVICE(device); + if (AGPBridge && AGPBridge->SecondayBusNumber == PCI[DeviceIndex[device]].slot.p.Bus) + ENABLE_AGP_VGA(); + + // Check if the controller has already been POST'ed + if (VGA_NOT_ACTIVE()) { + // Find a viable place to map the secondary PCI BIOS image and map it + printk("Device %d not enabled, so attempting warm boot it\n", device); + + // For AGP devices (and PCI devices that do have the ROM base + // address zero'ed out) we have to map the BIOS to a location + // that is passed by the AGP bridge to the bus. Some AGP devices + // have the ROM base address already set up for us, and some + // do not (we map to one of the existing BAR locations in + // this case). + mappedBIOS = NULL; + if (PCI[DeviceIndex[device]].ROMBaseAddress != 0) + mappedBIOSPhys = PCI[DeviceIndex[device]].ROMBaseAddress & ~0xF; + else + mappedBIOSPhys = PCI_findBIOSAddr(device); + printk("Mapping BIOS image to 0x%08X\n", mappedBIOSPhys); + mappedBIOS = PM_mapPhysicalAddr(mappedBIOSPhys,MAX_BIOSLEN-1,false); + PCI_writePCIRegL(0x30,mappedBIOSPhys | 0x1,device); + BIOSImageLen = mappedBIOS[2] * 512; + if ((copyOfBIOS = malloc(BIOSImageLen)) == NULL) + return false; + memcpy(copyOfBIOS,mappedBIOS,BIOSImageLen); + PM_freePhysicalAddr(mappedBIOS,MAX_BIOSLEN-1); + + // Allocate memory to store copy of BIOS from secondary controllers + VGAInfo[device].pciInfo = &PCI[DeviceIndex[device]]; + VGAInfo[device].BIOSImage = copyOfBIOS; + VGAInfo[device].BIOSImageLen = BIOSImageLen; + + // Restore device mappings + PCI_writePCIRegL(0x30,PCI[DeviceIndex[device]].ROMBaseAddress,device); + PCI_writePCIRegL(0x10,PCI[DeviceIndex[device]].BaseAddress10,device); + PCI_writePCIRegL(0x14,PCI[DeviceIndex[device]].BaseAddress14,device); + + // Now execute the BIOS POST for the device + if (copyOfBIOS[0] == 0x55 && copyOfBIOS[1] == 0xAA) { + printk("Executing BIOS POST for controller.\n"); + PCI_doBIOSPOST(device,mappedBIOSPhys,copyOfBIOS,BIOSImageLen); + } + + // Reset the size of the BIOS image to the final size + VGAInfo[device].BIOSImageLen = FINAL_BIOSLEN; + + // Save the BIOS and interrupt vector information to disk + sprintf(filename,"%s/bios.%02d",PM_getNucleusConfigPath(),device); + if ((f = fopen(filename,"wb")) != NULL) { + fwrite(copyOfBIOS,1,FINAL_BIOSLEN,f); + fwrite(VGAInfo[device].LowMem,1,sizeof(VGAInfo[device].LowMem),f); + fclose(f); + } + } + else { + // Allocate memory to store copy of BIOS from secondary controllers + if ((copyOfBIOS = malloc(FINAL_BIOSLEN)) == NULL) + return false; + VGAInfo[device].pciInfo = &PCI[DeviceIndex[device]]; + VGAInfo[device].BIOSImage = copyOfBIOS; + VGAInfo[device].BIOSImageLen = FINAL_BIOSLEN; + + // Load the BIOS and interrupt vector information from disk + sprintf(filename,"%s/bios.%02d",PM_getNucleusConfigPath(),device); + if ((f = fopen(filename,"rb")) != NULL) { + fread(copyOfBIOS,1,FINAL_BIOSLEN,f); + fread(VGAInfo[device].LowMem,1,sizeof(VGAInfo[device].LowMem),f); + fclose(f); + } + } + + // Fix up all the secondary PCI base address registers + // (restores them all from the values we read previously) + _PCI_fixupSecondaryBARs(); + + // Disable the secondary controller and AGP VGA pass-through + DISABLE_DEVICE(device); + if (AGPBridge) + DISABLE_AGP_VGA(); + } + + // Reenable primary display controller and reset AGP bridge control + if (AGPBridge) + RESTORE_AGP_VGA(); + ENABLE_DEVICE(0); + + // Free physical BIOS image mapping + PM_freePhysicalAddr(mappedBIOS,MAX_BIOSLEN-1); + + // Restore the X86 emulator BIOS info to primary controller + if (!useV86) + BE_setVGA(&VGAInfo[0]); + return true; +} + +/**************************************************************************** +REMARKS: +Enumerates the PCI bus and dumps the PCI configuration information to the +log file. +****************************************************************************/ +static void EnumeratePCI(void) +{ + int i,index; + PCIBridgeInfo *info; + + printk("Displaying enumeration of PCI bus (%d devices, %d display devices)\n", + NumPCI, NumDevices); + for (index = 0; index < NumDevices; index++) + printk(" Display device %d is PCI device %d\n",index,DeviceIndex[index]); + printk("\n"); + printk("Bus Slot Fnc DeviceID SubSystem Rev Class IRQ Int Cmd\n"); + for (i = 0; i < NumPCI; i++) { + printk("%2d %2d %2d %04X:%04X %04X:%04X %02X %02X:%02X %02X %02X %04X ", + PCI[i].slot.p.Bus, + PCI[i].slot.p.Device, + PCI[i].slot.p.Function, + PCI[i].VendorID, + PCI[i].DeviceID, + PCI[i].SubSystemVendorID, + PCI[i].SubSystemID, + PCI[i].RevID, + PCI[i].BaseClass, + PCI[i].SubClass, + PCI[i].InterruptLine, + PCI[i].InterruptPin, + PCI[i].Command); + for (index = 0; index < NumDevices; index++) { + if (DeviceIndex[index] == i) + break; + } + if (index < NumDevices) + printk("<- %d\n", index); + else + printk("\n"); + } + printk("\n"); + printk("DeviceID Stat Ifc Cch Lat Hdr BIST\n"); + for (i = 0; i < NumPCI; i++) { + printk("%04X:%04X %04X %02X %02X %02X %02X %02X ", + PCI[i].VendorID, + PCI[i].DeviceID, + PCI[i].Status, + PCI[i].Interface, + PCI[i].CacheLineSize, + PCI[i].LatencyTimer, + PCI[i].HeaderType, + PCI[i].BIST); + for (index = 0; index < NumDevices; index++) { + if (DeviceIndex[index] == i) + break; + } + if (index < NumDevices) + printk("<- %d\n", index); + else + printk("\n"); + } + printk("\n"); + printk("DeviceID Base10h Base14h Base18h Base1Ch Base20h Base24h ROMBase\n"); + for (i = 0; i < NumPCI; i++) { + printk("%04X:%04X %08X %08X %08X %08X %08X %08X %08X ", + PCI[i].VendorID, + PCI[i].DeviceID, + PCI[i].BaseAddress10, + PCI[i].BaseAddress14, + PCI[i].BaseAddress18, + PCI[i].BaseAddress1C, + PCI[i].BaseAddress20, + PCI[i].BaseAddress24, + PCI[i].ROMBaseAddress); + for (index = 0; index < NumDevices; index++) { + if (DeviceIndex[index] == i) + break; + } + if (index < NumDevices) + printk("<- %d\n", index); + else + printk("\n"); + } + printk("\n"); + printk("DeviceID BAR10Len BAR14Len BAR18Len BAR1CLen BAR20Len BAR24Len ROMLen\n"); + for (i = 0; i < NumPCI; i++) { + printk("%04X:%04X %08X %08X %08X %08X %08X %08X %08X ", + PCI[i].VendorID, + PCI[i].DeviceID, + PCI[i].BaseAddress10Len, + PCI[i].BaseAddress14Len, + PCI[i].BaseAddress18Len, + PCI[i].BaseAddress1CLen, + PCI[i].BaseAddress20Len, + PCI[i].BaseAddress24Len, + PCI[i].ROMBaseAddressLen); + for (index = 0; index < NumDevices; index++) { + if (DeviceIndex[index] == i) + break; + } + if (index < NumDevices) + printk("<- %d\n", index); + else + printk("\n"); + } + printk("\n"); + printk("Displaying enumeration of %d bridge devices\n",NumBridges); + printk("\n"); + printk("DeviceID P# S# B# IOB IOL MemBase MemLimit PreBase PreLimit Ctrl\n"); + for (i = 0; i < NumBridges; i++) { + info = (PCIBridgeInfo*)&PCI[BridgeIndex[i]]; + printk("%04X:%04X %02X %02X %02X %04X %04X %08X %08X %08X %08X %04X\n", + info->VendorID, + info->DeviceID, + info->PrimaryBusNumber, + info->SecondayBusNumber, + info->SubordinateBusNumber, + ((u16)info->IOBase << 8) & 0xF000, + info->IOLimit ? + ((u16)info->IOLimit << 8) | 0xFFF : 0, + ((u32)info->MemoryBase << 16) & 0xFFF00000, + info->MemoryLimit ? + ((u32)info->MemoryLimit << 16) | 0xFFFFF : 0, + ((u32)info->PrefetchableMemoryBase << 16) & 0xFFF00000, + info->PrefetchableMemoryLimit ? + ((u32)info->PrefetchableMemoryLimit << 16) | 0xFFFFF : 0, + info->BridgeControl); + } + printk("\n"); +} + +/**************************************************************************** +RETURNS: +Number of display devices found. + +REMARKS: +This function enumerates the number of available display devices on the +PCI bus, and returns the number found. +****************************************************************************/ +static int PCI_enumerateDevices(void) +{ + int i,j; + PCIBridgeInfo *info; + + // If this is the first time we have been called, enumerate all + // devices on the PCI bus. + if (NumPCI == -1) { + for (i = 0; i < MAX_PCI_DEVICES; i++) + PCI[i].dwSize = sizeof(PCI[i]); + if ((NumPCI = PCI_enumerate(PCI,MAX_PCI_DEVICES)) == 0) + return -1; + + // Build a list of all PCI bridge devices + for (i = 0,NumBridges = 0,BridgeIndex[0] = -1; i < NumPCI; i++) { + if (PCI[i].BaseClass == PCI_BRIDGE_CLASS) { + if (NumBridges < MAX_PCI_DEVICES) + BridgeIndex[NumBridges++] = i; + } + } + + // Now build a list of all display class devices + for (i = 0,NumDevices = 1,DeviceIndex[0] = -1; i < NumPCI; i++) { + if (PCI_IS_DISPLAY_CLASS(&PCI[i])) { + if ((PCI[i].Command & 0x3) == 0x3) { + DeviceIndex[0] = i; + } + else { + if (NumDevices < MAX_PCI_DEVICES) + DeviceIndex[NumDevices++] = i; + } + if (PCI[i].slot.p.Bus != 0) { + // This device is on a different bus than the primary + // PCI bus, so it is probably an AGP device. Find the + // AGP bus device that controls that bus so we can + // control it. + for (j = 0; j < NumBridges; j++) { + info = (PCIBridgeInfo*)&PCI[BridgeIndex[j]]; + if (info->SecondayBusNumber == PCI[i].slot.p.Bus) { + AGPBridge = info; + break; + } + } + } + } + } + + // Enumerate all PCI and bridge devices to log file + EnumeratePCI(); + } + return NumDevices; +} + +FILE *logfile; + +void printk(const char *fmt, ...) +{ + va_list argptr; + va_start(argptr, fmt); + vfprintf(logfile, fmt, argptr); + fflush(logfile); + va_end(argptr); +} + +int main(int argc,char *argv[]) +{ + while (argc > 1) { + if (stricmp(argv[1],"-usev86") == 0) { + useV86 = true; + } + else if (stricmp(argv[1],"-force") == 0) { + forcePost = true; + } +#ifdef DEBUG + else if (stricmp(argv[1],"-decode") == 0) { + debugFlags |= DEBUG_DECODE_F; + } + else if (stricmp(argv[1],"-iotrace") == 0) { + debugFlags |= DEBUG_IO_TRACE_F; + } +#endif + else { + printf("Usage: warmboot [-usev86] [-force] [-decode] [-iotrace]\n"); + exit(-1); + } + argc--; + argv++; + } + if ((logfile = fopen("warmboot.log","w")) == NULL) + exit(1); + + PM_init(); + if (!useV86) { + // Initialise the x86 BIOS emulator + BE_init(false,debugFlags,65536,&VGAInfo[0]); + } + + // Enumerate all devices (which POST's them at the same time) + if (PCI_enumerateDevices() < 1) { + printk("No PCI display devices found!\n"); + return -1; + } + + // Post all the display controller BIOS'es + PCI_postControllers(); + + // Cleanup and exit the emulator + if (!useV86) + BE_exit(); + fclose(logfile); + return 0; +} |