📄 besys.c
字号:
/****************************************************************************** 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 <sys/param.h>#include "machine/pio.h"#include "biosemui.h"#include "pcibios.h"#define printk printf/* XXX temporary fix */#define isa_in8(x) in8rb((x) + 0xe0000000)#define isa_out8(x, y) out8rb((x) + 0xe0000000, y)#define isa_in16(x) in16rb((x) + 0xe0000000)#define isa_out16(x, y) out16rb((x) + 0xe0000000, y)#define isa_in32(x) in32rb((x) + 0xe0000000)#define isa_out32(x, y) out32rb((x) + 0xe0000000, y)/*------------------------------- 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 X86EMU_DEBUG# define DEBUG_MEM() (M.x86.debug & DEBUG_MEM_TRACE_F)#else# define DEBUG_MEM()#endif/****************************************************************************PARAMETERS:addr - Emulator memory address to readRETURNS:Byte value read from emulator memory.REMARKS:Reads a byte value from the emulator memory. We have three distinct memoryregions 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 readRETURNS:Word value read from emulator memory.REMARKS:Reads a word value from the emulator memory. We have three distinct memoryregions 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) { addr -= 0xC0000; val = ( *(u8*)(_BE_env.biosmem_base + addr) | (*(u8*)(_BE_env.biosmem_base + addr + 1) << 8));DB( addr += 0xC0000;) } else if (addr >= 0xA0000 && addr <= 0xFFFFF) { addr -= 0xA0000; val = ( readb(_BE_env.busmem_base, addr) | (readb(_BE_env.busmem_base, addr + 1) << 8));DB( addr += 0xA0000;) } else if (addr > M.mem_size - 2) {DB( printk("mem_read: address %#lx out of range!\n", addr);) HALT_SYS(); } else { val = ( *(u8*)(M.mem_base + addr) | (*(u8*)(M.mem_base + addr + 1) << 8)); }DB( if (DEBUG_MEM()) printk("%#08x 2 -> %#x\n", addr, val);) return val;}/****************************************************************************PARAMETERS:addr - Emulator memory address to readRETURNS:Long value read from emulator memory.REMARKS:Reads a long value from the emulator memory. We have three distinct memoryregions 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) { 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));DB( addr += 0xC0000;) } else if (addr >= 0xA0000 && addr <= 0xFFFFF) { 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));DB( addr += 0xA0000;) } else if (addr > M.mem_size - 4) {DB( printk("mem_read: address %#lx out of range!\n", addr);) HALT_SYS(); } else { 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)); }DB( if (DEBUG_MEM()) printk("%#08x 4 -> %#x\n", addr, val);) return val;}/****************************************************************************PARAMETERS:addr - Emulator memory address to readval - Value to storeREMARKS:Writes a byte value to emulator memory. We have three distinct memoryregions 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 readval - Value to storeREMARKS:Writes a word value to emulator memory. We have three distinct memoryregions 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) { addr -= 0xC0000; *(u8*)(_BE_env.biosmem_base + addr + 0) = (val >> 0) & 0xff; *(u8*)(_BE_env.biosmem_base + addr + 1) = (val >> 8) & 0xff; } else if (addr >= 0xA0000 && addr <= 0xFFFFF) { addr -= 0xA0000; writeb(val >> 0, _BE_env.busmem_base, addr); writeb(val >> 8, _BE_env.busmem_base, addr + 1); } else if (addr > M.mem_size-2) {DB( printk("mem_write: address %#lx out of range!\n", addr);) HALT_SYS(); } else { *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff; *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff; }}/****************************************************************************PARAMETERS:addr - Emulator memory address to readval - Value to storeREMARKS:Writes a long value to emulator memory. We have three distinct memoryregions 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) { 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 if (addr >= 0xA0000 && addr <= 0xFFFFF) { 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 if (addr > M.mem_size-4) {DB( printk("mem_write: address %#lx out of range!\n", addr);) HALT_SYS(); } else { *(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; }}/* Debug functions to do ISA/PCI bus port I/O */#ifdef X86EMU_DEBUG#define DEBUG_IO() (M.x86.debug & DEBUG_IO_TRACE_F)#endifstatic int PIT_toggle = 1;/* Holding area for PCI config cycle address register */static int cf8_val;static int cf8_bus;static int cf8_fnc;static int cf8_reg;u8 X86API BE_inb(X86EMU_pioAddr port){ u8 val; static unsigned timer_tmp; if (port == 0x40) { if ((PIT_toggle = !PIT_toggle) == 0) val = timer_tmp & 0xff; else { val = (timer_tmp & 0xff00) >> 8; timer_tmp++; } } else if (port == 0x61) { if ((PIT_toggle = !PIT_toggle) == 0) val = 0; else val = 0xff; return val; } else if ((port & 0xfffffffc) == 0xcfc) { pcibios_read_config_byte(cf8_bus, cf8_fnc, cf8_reg + (port & 3), &val); } else { val = isa_in8(port); } DB(if (DEBUG_IO()) printk("%04X:%04X: inb.%04X -> %02X\n",M.x86.saved_cs, M.x86.saved_ip, (u16)port, val);) return val;}u16 X86API BE_inw(X86EMU_pioAddr port){ u16 val; if ((port & 0xfffffffc) == 0xcfc) { pcibios_read_config_word(cf8_bus, cf8_fnc, cf8_reg + (port & 3), &val); } else { val = isa_in16(port); } DB(if (DEBUG_IO()) printk("%04X:%04X: inw.%04X -> %04X\n",M.x86.saved_cs, M.x86.saved_ip, (u16)port, val);) return val;}u32 X86API BE_inl(X86EMU_pioAddr port){ u32 val; if (port == 0xcfc) { pcibios_read_config_dword(cf8_bus, cf8_fnc, cf8_reg, &val); return val; } else if (port == 0xcfc) { val = cf8_val; return val; } else { val = isa_in32(port); } DB(if (DEBUG_IO()) printk("%04X:%04X: inl.%04X -> %08X\n",M.x86.saved_cs, M.x86.saved_ip, (u16)port, val);) return val;}void X86API BE_outb(X86EMU_pioAddr port, u8 val){ if (port == 0x43) { PIT_toggle = 1; } else if ((port & 0xfffffffc) == 0xcfc) { pcibios_write_config_byte(cf8_bus, cf8_fnc, cf8_reg + (port & 3), val); } else { DB(if (DEBUG_IO()) printk("%04X:%04X: outb.%04X <- %02X\n",M.x86.saved_cs, M.x86.saved_ip, (u16)port, val);) isa_out8(port,val); }}void X86API BE_outw(X86EMU_pioAddr port, u16 val){ if ((port & 0xfffffffc) == 0xcfc) { pcibios_write_config_word(cf8_bus, cf8_fnc, cf8_reg + (port & 3), val); } else { DB(if (DEBUG_IO()) printk("%04X:%04X: outw.%04X <- %04X\n",M.x86.saved_cs, M.x86.saved_ip, (u16)port, val);) isa_out16(port,val); }}void X86API BE_outl(X86EMU_pioAddr port, u32 val){ if (port == 0xcf8) { cf8_bus = (val >> 16) & 0xff; cf8_fnc = (val >> 8) & 0xff; cf8_reg = val & 0xff; cf8_val = val; } else if (port == 0xcfc) { pcibios_write_config_dword(cf8_bus, cf8_fnc, cf8_reg, val); } else { DB(if (DEBUG_IO()) printk("%04X:%04X: outl.%04X <- %08X\n",M.x86.saved_cs, M.x86.saved_ip, (u16)port, val);) isa_out32(port,val); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -