1 /****************************************************************************
3 * BIOS emulator and interface
4 * to Realmode X86 Emulator Library
6 * Copyright (C) 1996-1999 SciTech Software, Inc.
8 * ========================================================================
10 * Permission to use, copy, modify, distribute, and sell this software and
11 * its documentation for any purpose is hereby granted without fee,
12 * provided that the above copyright notice appear in all copies and that
13 * both that copyright notice and this permission notice appear in
14 * supporting documentation, and that the name of the authors not be used
15 * in advertising or publicity pertaining to distribution of the software
16 * without specific, written prior permission. The authors makes no
17 * representations about the suitability of this software for any purpose.
18 * It is provided "as is" without express or implied warranty.
20 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
21 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
22 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
23 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
24 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
25 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26 * PERFORMANCE OF THIS SOFTWARE.
28 * ========================================================================
32 * Developer: Kendall Bennett
34 * Description: This file includes BIOS emulator I/O and memory access
37 ****************************************************************************/
41 /*------------------------------- Macros ----------------------------------*/
43 /* Macros to read and write values to x86 bus memory. Replace these as
44 * necessary if you need to do something special to access memory over
45 * the bus on a particular processor family.
48 #define readb(base,off) *((u8*)((u32)(base) + (off)))
49 #define readw(base,off) *((u16*)((u32)(base) + (off)))
50 #define readl(base,off) *((u32*)((u32)(base) + (off)))
51 #define writeb(v,base,off) *((u8*)((u32)(base) + (off))) = (v)
52 #define writew(v,base,off) *((u16*)((u32)(base) + (off))) = (v)
53 #define writel(v,base,off) *((u32*)((u32)(base) + (off))) = (v)
55 /*----------------------------- Implementation ----------------------------*/
58 # define DEBUG_MEM() (M.x86.debug & DEBUG_MEM_TRACE_F)
63 /****************************************************************************
65 addr - Emulator memory address to read
68 Byte value read from emulator memory.
71 Reads a byte value from the emulator memory. We have three distinct memory
72 regions that are handled differently, which this function handles.
73 ****************************************************************************/
79 if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
80 val = *(u8*)(_BE_env.biosmem_base + addr - 0xC0000);
82 else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
83 val = readb(_BE_env.busmem_base, addr - 0xA0000);
85 else if (addr > M.mem_size - 1) {
86 DB( printk("mem_read: address %#lx out of range!\n", addr);)
90 val = *(u8*)(M.mem_base + addr);
93 printk("%#08x 1 -> %#x\n", addr, val);)
97 /****************************************************************************
99 addr - Emulator memory address to read
102 Word value read from emulator memory.
105 Reads a word value from the emulator memory. We have three distinct memory
106 regions that are handled differently, which this function handles.
107 ****************************************************************************/
113 if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
114 #ifdef __BIG_ENDIAN__
117 val = ( *(u8*)(_BE_env.biosmem_base + addr) |
118 (*(u8*)(_BE_env.biosmem_base + addr + 1) << 8));
122 val = *(u16*)(_BE_env.biosmem_base + addr - 0xC0000);
124 else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
125 #ifdef __BIG_ENDIAN__
128 val = ( readb(_BE_env.busmem_base, addr) |
129 (readb(_BE_env.busmem_base, addr + 1) << 8));
133 val = readw(_BE_env.busmem_base, addr - 0xA0000);
135 else if (addr > M.mem_size - 2) {
136 DB( printk("mem_read: address %#lx out of range!\n", addr);)
140 #ifdef __BIG_ENDIAN__
142 val = ( *(u8*)(M.mem_base + addr) |
143 (*(u8*)(M.mem_base + addr + 1) << 8));
147 val = *(u16*)(M.mem_base + addr);
150 printk("%#08x 2 -> %#x\n", addr, val);)
154 /****************************************************************************
156 addr - Emulator memory address to read
159 Long value read from emulator memory.
162 Reads a long value from the emulator memory. We have three distinct memory
163 regions that are handled differently, which this function handles.
164 ****************************************************************************/
170 if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
171 #ifdef __BIG_ENDIAN__
174 val = ( *(u8*)(_BE_env.biosmem_base + addr + 0) |
175 (*(u8*)(_BE_env.biosmem_base + addr + 1) << 8) |
176 (*(u8*)(_BE_env.biosmem_base + addr + 2) << 16) |
177 (*(u8*)(_BE_env.biosmem_base + addr + 3) << 24));
181 val = *(u32*)(_BE_env.biosmem_base + addr - 0xC0000);
183 else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
184 #ifdef __BIG_ENDIAN__
187 val = ( readb(_BE_env.busmem_base, addr) |
188 (readb(_BE_env.busmem_base, addr + 1) << 8) |
189 (readb(_BE_env.busmem_base, addr + 2) << 16) |
190 (readb(_BE_env.busmem_base, addr + 3) << 24));
194 val = readl(_BE_env.busmem_base, addr - 0xA0000);
196 else if (addr > M.mem_size - 4) {
197 DB( printk("mem_read: address %#lx out of range!\n", addr);)
201 #ifdef __BIG_ENDIAN__
203 val = ( *(u8*)(M.mem_base + addr + 0) |
204 (*(u8*)(M.mem_base + addr + 1) << 8) |
205 (*(u8*)(M.mem_base + addr + 2) << 16) |
206 (*(u8*)(M.mem_base + addr + 3) << 24));
210 val = *(u32*)(M.mem_base + addr);
213 printk("%#08x 4 -> %#x\n", addr, val);)
217 /****************************************************************************
219 addr - Emulator memory address to read
223 Writes a byte value to emulator memory. We have three distinct memory
224 regions that are handled differently, which this function handles.
225 ****************************************************************************/
231 printk("%#08x 1 <- %#x\n", addr, val);)
232 if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
233 *(u8*)(_BE_env.biosmem_base + addr - 0xC0000) = val;
235 else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
236 writeb(val, _BE_env.busmem_base, addr - 0xA0000);
238 else if (addr > M.mem_size-1) {
239 DB( printk("mem_write: address %#lx out of range!\n", addr);)
243 *(u8*)(M.mem_base + addr) = val;
247 /****************************************************************************
249 addr - Emulator memory address to read
253 Writes a word value to emulator memory. We have three distinct memory
254 regions that are handled differently, which this function handles.
255 ****************************************************************************/
261 printk("%#08x 2 <- %#x\n", addr, val);)
262 if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
263 #ifdef __BIG_ENDIAN__
266 *(u8*)(_BE_env.biosmem_base + addr + 0) = (val >> 0) & 0xff;
267 *(u8*)(_BE_env.biosmem_base + addr + 1) = (val >> 8) & 0xff;
271 *(u16*)(_BE_env.biosmem_base + addr - 0xC0000) = val;
273 else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
274 #ifdef __BIG_ENDIAN__
277 writeb(val >> 0, _BE_env.busmem_base, addr);
278 writeb(val >> 8, _BE_env.busmem_base, addr + 1);
282 writew(val, _BE_env.busmem_base, addr - 0xA0000);
284 else if (addr > M.mem_size-2) {
285 DB( printk("mem_write: address %#lx out of range!\n", addr);)
289 #ifdef __BIG_ENDIAN__
291 *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff;
292 *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff;
296 *(u16*)(M.mem_base + addr) = val;
300 /****************************************************************************
302 addr - Emulator memory address to read
306 Writes a long value to emulator memory. We have three distinct memory
307 regions that are handled differently, which this function handles.
308 ****************************************************************************/
314 printk("%#08x 4 <- %#x\n", addr, val);)
315 if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
316 #ifdef __BIG_ENDIAN__
319 *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff;
320 *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff;
321 *(u8*)(M.mem_base + addr + 2) = (val >> 16) & 0xff;
322 *(u8*)(M.mem_base + addr + 3) = (val >> 24) & 0xff;
326 *(u32*)(M.mem_base + addr - 0xC0000) = val;
328 else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
329 #ifdef __BIG_ENDIAN__
332 writeb(val >> 0, _BE_env.busmem_base, addr);
333 writeb(val >> 8, _BE_env.busmem_base, addr + 1);
334 writeb(val >> 16, _BE_env.busmem_base, addr + 1);
335 writeb(val >> 24, _BE_env.busmem_base, addr + 1);
339 writel(val, _BE_env.busmem_base, addr - 0xA0000);
341 else if (addr > M.mem_size-4) {
342 DB( printk("mem_write: address %#lx out of range!\n", addr);)
346 #ifdef __BIG_ENDIAN__
348 *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff;
349 *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff;
350 *(u8*)(M.mem_base + addr + 2) = (val >> 16) & 0xff;
351 *(u8*)(M.mem_base + addr + 3) = (val >> 24) & 0xff;
355 *(u32*)(M.mem_base + addr) = val;
359 /* Debug functions to do ISA/PCI bus port I/O */
362 #define DEBUG_IO() (M.x86.debug & DEBUG_IO_TRACE_F)
364 u8 X86API BE_inb(int port)
366 u8 val = PM_inpb(port);
368 printk("%04X:%04X: inb.%04X -> %02X\n",M.x86.saved_cs, M.x86.saved_ip, (ushort)port, val);
372 u16 X86API BE_inw(int port)
374 u16 val = PM_inpw(port);
376 printk("%04X:%04X: inw.%04X -> %04X\n",M.x86.saved_cs, M.x86.saved_ip, (ushort)port, val);
380 u32 X86API BE_inl(int port)
382 u32 val = PM_inpd(port);
384 printk("%04X:%04X: inl.%04X -> %08X\n",M.x86.saved_cs, M.x86.saved_ip, (ushort)port, val);
388 void X86API BE_outb(int port, u8 val)
391 printk("%04X:%04X: outb.%04X <- %02X\n",M.x86.saved_cs, M.x86.saved_ip, (ushort)port, val);
395 void X86API BE_outw(int port, u16 val)
398 printk("%04X:%04X: outw.%04X <- %04X\n",M.x86.saved_cs, M.x86.saved_ip, (ushort)port, val);
402 void X86API BE_outl(int port, u32 val)
405 printk("%04X:%04X: outl.%04X <- %08X\n",M.x86.saved_cs, M.x86.saved_ip, (ushort)port, val);