]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/MAI/bios_emulator/scitech/src/biosemu/biosemu.c
USB: This patch fix readl in ohci swap reg access.
[people/ms/u-boot.git] / board / MAI / bios_emulator / scitech / src / biosemu / biosemu.c
1 /****************************************************************************
2 *
3 * BIOS emulator and interface
4 * to Realmode X86 Emulator Library
5 *
6 * Copyright (C) 1996-1999 SciTech Software, Inc.
7 *
8 * ========================================================================
9 *
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.
19 *
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.
27 *
28 * ========================================================================
29 *
30 * Language: ANSI C
31 * Environment: Any
32 * Developer: Kendall Bennett
33 *
34 * Description: Module implementing the system specific functions. This
35 * module is always compiled and linked in the OS depedent
36 * libraries, and never in a binary portable driver.
37 *
38 ****************************************************************************/
39
40 #include "biosemui.h"
41 #include <string.h>
42 #include <stdlib.h>
43
44 /*------------------------- Global Variables ------------------------------*/
45
46 BE_sysEnv _BE_env;
47 #ifdef __DRIVER__
48 PM_imports _VARAPI _PM_imports;
49 #endif
50 static X86EMU_memFuncs _BE_mem = {
51 BE_rdb,
52 BE_rdw,
53 BE_rdl,
54 BE_wrb,
55 BE_wrw,
56 BE_wrl,
57 };
58 #ifdef DEBUG
59 static X86EMU_pioFuncs _BE_pio = {
60 BE_inb,
61 BE_inw,
62 BE_inl,
63 BE_outb,
64 BE_outw,
65 BE_outl,
66 };
67 #else
68 static X86EMU_pioFuncs _BE_pio = {
69 (void*)PM_inpb,
70 (void*)PM_inpw,
71 (void*)PM_inpd,
72 (void*)PM_outpb,
73 (void*)PM_outpw,
74 (void*)PM_outpd,
75 };
76 #endif
77
78 /*-------------------------- Implementation -------------------------------*/
79
80 #define OFF(addr) (u16)(((addr) >> 0) & 0xffff)
81 #define SEG(addr) (u16)(((addr) >> 4) & 0xf000)
82
83 /****************************************************************************
84 PARAMETERS:
85 debugFlags - Flags to enable debugging options (debug builds only)
86 memSize - Amount of memory to allocate for real mode machine
87 info - Pointer to default VGA device information
88
89 REMARKS:
90 This functions initialises the BElib, and uses the passed in
91 BIOS image as the BIOS that is used and emulated at 0xC0000.
92 ****************************************************************************/
93 ibool PMAPI BE_init(
94 u32 debugFlags,
95 int memSize,
96 BE_VGAInfo *info)
97 {
98 #ifndef __DRIVER__
99 PM_init();
100 #endif
101 memset(&M,0,sizeof(M));
102 if (memSize < 20480)
103 PM_fatalError("Emulator requires at least 20Kb of memory!\n");
104 if ((M.mem_base = (unsigned long)malloc(memSize)) == NULL)
105 PM_fatalError("Out of memory!");
106 M.mem_size = memSize;
107 _BE_env.busmem_base = (ulong)PM_mapPhysicalAddr(0xA0000,0x5FFFF,true);
108 M.x86.debug = debugFlags;
109 _BE_bios_init((u32*)info->LowMem);
110 X86EMU_setupMemFuncs(&_BE_mem);
111 X86EMU_setupPioFuncs(&_BE_pio);
112 BE_setVGA(info);
113 return true;
114 }
115
116 /****************************************************************************
117 PARAMETERS:
118 debugFlags - Flags to enable debugging options (debug builds only)
119
120 REMARKS:
121 This function allows the application to enable logging and debug flags
122 on a function call basis, so we can specifically enable logging only
123 for specific functions that are causing problems in debug mode.
124 ****************************************************************************/
125 void PMAPI BE_setDebugFlags(
126 u32 debugFlags)
127 {
128 M.x86.debug = debugFlags;
129 }
130
131 /****************************************************************************
132 PARAMETERS:
133 info - Pointer to VGA device information to make current
134
135 REMARKS:
136 This function sets the VGA BIOS functions in the emulator to point to the
137 specific VGA BIOS in use. This includes swapping the BIOS interrupt
138 vectors, BIOS image and BIOS data area to the new BIOS. This allows the
139 real mode BIOS to be swapped without resetting the entire emulator.
140 ****************************************************************************/
141 void PMAPI BE_setVGA(
142 BE_VGAInfo *info)
143 {
144 _BE_env.vgaInfo.pciInfo = info->pciInfo;
145 _BE_env.vgaInfo.BIOSImage = info->BIOSImage;
146 if (info->BIOSImage) {
147 _BE_env.biosmem_base = (ulong)info->BIOSImage;
148 _BE_env.biosmem_limit = 0xC0000 + info->BIOSImageLen-1;
149 }
150 else {
151 _BE_env.biosmem_base = _BE_env.busmem_base + 0x20000;
152 _BE_env.biosmem_limit = 0xC7FFF;
153 }
154 if (*((u32*)info->LowMem) == 0)
155 _BE_bios_init((u32*)info->LowMem);
156 memcpy((u8*)M.mem_base,info->LowMem,sizeof(info->LowMem));
157 }
158
159 /****************************************************************************
160 PARAMETERS:
161 info - Pointer to VGA device information to retrieve current
162
163 REMARKS:
164 This function returns the VGA BIOS functions currently active in the
165 emulator, so they can be restored at a later date.
166 ****************************************************************************/
167 void PMAPI BE_getVGA(
168 BE_VGAInfo *info)
169 {
170 info->pciInfo = _BE_env.vgaInfo.pciInfo;
171 info->BIOSImage = _BE_env.vgaInfo.BIOSImage;
172 memcpy(info->LowMem,(u8*)M.mem_base,sizeof(info->LowMem));
173 }
174
175 /****************************************************************************
176 PARAMETERS:
177 r_seg - Segment for pointer to convert
178 r_off - Offset for pointer to convert
179
180 REMARKS:
181 This function maps a real mode pointer in the emulator memory to a protected
182 mode pointer that can be used to directly access the memory.
183
184 NOTE: The memory is *always* in little endian format, son on non-x86
185 systems you will need to do endian translations to access this
186 memory.
187 ****************************************************************************/
188 void * PMAPI BE_mapRealPointer(
189 uint r_seg,
190 uint r_off)
191 {
192 u32 addr = ((u32)r_seg << 4) + r_off;
193
194 if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
195 return (void*)(_BE_env.biosmem_base + addr - 0xC0000);
196 }
197 else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
198 return (void*)(_BE_env.busmem_base + addr - 0xA0000);
199 }
200 return (void*)(M.mem_base + addr);
201 }
202
203 /****************************************************************************
204 PARAMETERS:
205 len - Return the length of the VESA buffer
206 rseg - Place to store VESA buffer segment
207 roff - Place to store VESA buffer offset
208
209 REMARKS:
210 This function returns the address of the VESA transfer buffer in real
211 mode emulator memory. The VESA transfer buffer is always 1024 bytes long,
212 and located at 15Kb into the start of the real mode memory (16Kb is where
213 we put the real mode code we execute for issuing interrupts).
214
215 NOTE: The memory is *always* in little endian format, son on non-x86
216 systems you will need to do endian translations to access this
217 memory.
218 ****************************************************************************/
219 void * PMAPI BE_getVESABuf(
220 uint *len,
221 uint *rseg,
222 uint *roff)
223 {
224 *len = 1024;
225 *rseg = SEG(0x03C00);
226 *roff = OFF(0x03C00);
227 return (void*)(M.mem_base + ((u32)*rseg << 4) + *roff);
228 }
229
230 /****************************************************************************
231 REMARKS:
232 Cleans up and exits the emulator.
233 ****************************************************************************/
234 void PMAPI BE_exit(void)
235 {
236 free((void*)M.mem_base);
237 PM_freePhysicalAddr((void*)_BE_env.busmem_base,0x5FFFF);
238 }
239
240 /****************************************************************************
241 PARAMETERS:
242 seg - Segment of code to call
243 off - Offset of code to call
244 regs - Real mode registers to load
245 sregs - Real mode segment registers to load
246
247 REMARKS:
248 This functions calls a real mode far function at the specified address,
249 and loads all the x86 registers from the passed in registers structure.
250 On exit the registers returned from the call are returned in the same
251 structures.
252 ****************************************************************************/
253 void PMAPI BE_callRealMode(
254 uint seg,
255 uint off,
256 RMREGS *regs,
257 RMSREGS *sregs)
258 {
259 M.x86.R_EAX = regs->e.eax;
260 M.x86.R_EBX = regs->e.ebx;
261 M.x86.R_ECX = regs->e.ecx;
262 M.x86.R_EDX = regs->e.edx;
263 M.x86.R_ESI = regs->e.esi;
264 M.x86.R_EDI = regs->e.edi;
265 M.x86.R_DS = sregs->ds;
266 M.x86.R_ES = sregs->es;
267 M.x86.R_FS = sregs->fs;
268 M.x86.R_GS = sregs->gs;
269 M.x86.R_CS = (u16)seg;
270 M.x86.R_IP = (u16)off;
271 M.x86.R_SS = SEG(M.mem_size - 1);
272 M.x86.R_SP = OFF(M.mem_size - 1);
273 X86EMU_exec();
274 regs->e.cflag = M.x86.R_EFLG & F_CF;
275 regs->e.eax = M.x86.R_EAX;
276 regs->e.ebx = M.x86.R_EBX;
277 regs->e.ecx = M.x86.R_ECX;
278 regs->e.edx = M.x86.R_EDX;
279 regs->e.esi = M.x86.R_ESI;
280 regs->e.edi = M.x86.R_EDI;
281 sregs->ds = M.x86.R_DS;
282 sregs->es = M.x86.R_ES;
283 sregs->fs = M.x86.R_FS;
284 sregs->gs = M.x86.R_GS;
285 }
286
287 /****************************************************************************
288 PARAMETERS:
289 intno - Interrupt number to execute
290 in - Real mode registers to load
291 out - Place to store resulting real mode registers
292
293 REMARKS:
294 This functions calls a real mode interrupt function at the specified address,
295 and loads all the x86 registers from the passed in registers structure.
296 On exit the registers returned from the call are returned in out stucture.
297 ****************************************************************************/
298 int PMAPI BE_int86(
299 int intno,
300 RMREGS *in,
301 RMREGS *out)
302 {
303 M.x86.R_EAX = in->e.eax;
304 M.x86.R_EBX = in->e.ebx;
305 M.x86.R_ECX = in->e.ecx;
306 M.x86.R_EDX = in->e.edx;
307 M.x86.R_ESI = in->e.esi;
308 M.x86.R_EDI = in->e.edi;
309 ((u8*)M.mem_base)[0x4000] = 0xCD;
310 ((u8*)M.mem_base)[0x4001] = (u8)intno;
311 ((u8*)M.mem_base)[0x4002] = 0xC3;
312 M.x86.R_CS = SEG(0x04000);
313 M.x86.R_IP = OFF(0x04000);
314 M.x86.R_SS = SEG(M.mem_size - 1);
315 M.x86.R_SP = OFF(M.mem_size - 1);
316 X86EMU_exec();
317 out->e.cflag = M.x86.R_EFLG & F_CF;
318 out->e.eax = M.x86.R_EAX;
319 out->e.ebx = M.x86.R_EBX;
320 out->e.ecx = M.x86.R_ECX;
321 out->e.edx = M.x86.R_EDX;
322 out->e.esi = M.x86.R_ESI;
323 out->e.edi = M.x86.R_EDI;
324 return out->x.ax;
325 }
326
327 /****************************************************************************
328 PARAMETERS:
329 intno - Interrupt number to execute
330 in - Real mode registers to load
331 out - Place to store resulting real mode registers
332 sregs - Real mode segment registers to load
333
334 REMARKS:
335 This functions calls a real mode interrupt function at the specified address,
336 and loads all the x86 registers from the passed in registers structure.
337 On exit the registers returned from the call are returned in out stucture.
338 ****************************************************************************/
339 int PMAPI BE_int86x(
340 int intno,
341 RMREGS *in,
342 RMREGS *out,
343 RMSREGS *sregs)
344 {
345 M.x86.R_EAX = in->e.eax;
346 M.x86.R_EBX = in->e.ebx;
347 M.x86.R_ECX = in->e.ecx;
348 M.x86.R_EDX = in->e.edx;
349 M.x86.R_ESI = in->e.esi;
350 M.x86.R_EDI = in->e.edi;
351 M.x86.R_DS = sregs->ds;
352 M.x86.R_ES = sregs->es;
353 M.x86.R_FS = sregs->fs;
354 M.x86.R_GS = sregs->gs;
355 ((u8*)M.mem_base)[0x4000] = 0xCD;
356 ((u8*)M.mem_base)[0x4001] = (u8)intno;
357 ((u8*)M.mem_base)[0x4002] = 0xC3;
358 M.x86.R_CS = SEG(0x04000);
359 M.x86.R_IP = OFF(0x04000);
360 M.x86.R_SS = SEG(M.mem_size - 1);
361 M.x86.R_SP = OFF(M.mem_size - 1);
362 X86EMU_exec();
363 out->e.cflag = M.x86.R_EFLG & F_CF;
364 out->e.eax = M.x86.R_EAX;
365 out->e.ebx = M.x86.R_EBX;
366 out->e.ecx = M.x86.R_ECX;
367 out->e.edx = M.x86.R_EDX;
368 out->e.esi = M.x86.R_ESI;
369 out->e.edi = M.x86.R_EDI;
370 sregs->ds = M.x86.R_DS;
371 sregs->es = M.x86.R_ES;
372 sregs->fs = M.x86.R_FS;
373 sregs->gs = M.x86.R_GS;
374 return out->x.ax;
375 }
376
377 #ifdef __DRIVER__
378
379 /****************************************************************************
380 REMARKS:
381 Empty log function for binary portable DLL. The BPD is compiled without
382 debug information, so very little is logged anyway so it is simpler this
383 way.
384 ****************************************************************************/
385 void printk(const char *msg, ...)
386 {
387 }
388
389 /****************************************************************************
390 REMARKS:
391 Fatal error handler called when a non-imported function is called by the
392 driver. We leave this to a runtime error so that older applications and
393 shell drivers will work with newer bpd drivers provided no newer functions
394 are required by the driver itself. If they are, the application or shell
395 driver needs to be recompiled.
396 ****************************************************************************/
397 static void _PM_fatalErrorHandler(void)
398 {
399 PM_fatalError("Unsupported PM_imports import function called! Please re-compile!\n");
400 }
401
402 /****************************************************************************
403 PARAMETERS:
404 beImp - BE library imports
405 beImp - Generic emulator imports
406
407 RETURNS:
408 Pointer to exported function list
409
410 REMARKS:
411 This function initialises the BIOS emulator library and returns the list of
412 loader library exported functions.
413 {secret}
414 ****************************************************************************/
415 BE_exports * _CEXPORT BE_initLibrary(
416 PM_imports *pmImp)
417 {
418 static BE_exports _BE_exports = {
419 sizeof(BE_exports),
420 BE_init,
421 BE_setVGA,
422 BE_getVGA,
423 BE_mapRealPointer,
424 BE_getVESABuf,
425 BE_callRealMode,
426 BE_int86,
427 BE_int86x,
428 NULL,
429 BE_exit,
430 };
431 int i,max;
432 ulong *p;
433
434 /* Initialize all default imports to point to fatal error handler */
435 /* for upwards compatibility. */
436 max = sizeof(_PM_imports)/sizeof(BE_initLibrary_t);
437 for (i = 0,p = (ulong*)&_PM_imports; i < max; i++)
438 *p++ = (ulong)_PM_fatalErrorHandler;
439
440 /* Now copy all our imported functions */
441 memcpy(&_PM_imports,pmImp,MIN(sizeof(_PM_imports),pmImp->dwSize));
442 return &_BE_exports;
443 }
444
445 #endif /* __DRIVER__ */