xref: /OK3568_Linux_fs/u-boot/drivers/bios_emulator/biosemu.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /****************************************************************************
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun *			 BIOS emulator and interface
4*4882a593Smuzhiyun *		       to Realmode X86 Emulator Library
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun *  Copyright (C) 2007 Freescale Semiconductor, Inc.
7*4882a593Smuzhiyun *  Jason Jin <Jason.jin@freescale.com>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun *		Copyright (C) 1996-1999 SciTech Software, Inc.
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun *  ========================================================================
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun *  Permission to use, copy, modify, distribute, and sell this software and
14*4882a593Smuzhiyun *  its documentation for any purpose is hereby granted without fee,
15*4882a593Smuzhiyun *  provided that the above copyright notice appear in all copies and that
16*4882a593Smuzhiyun *  both that copyright notice and this permission notice appear in
17*4882a593Smuzhiyun *  supporting documentation, and that the name of the authors not be used
18*4882a593Smuzhiyun *  in advertising or publicity pertaining to distribution of the software
19*4882a593Smuzhiyun *  without specific, written prior permission.	The authors makes no
20*4882a593Smuzhiyun *  representations about the suitability of this software for any purpose.
21*4882a593Smuzhiyun *  It is provided "as is" without express or implied warranty.
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun *  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24*4882a593Smuzhiyun *  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
25*4882a593Smuzhiyun *  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
26*4882a593Smuzhiyun *  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
27*4882a593Smuzhiyun *  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
28*4882a593Smuzhiyun *  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29*4882a593Smuzhiyun *  PERFORMANCE OF THIS SOFTWARE.
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun *  ========================================================================
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun * Language:	ANSI C
34*4882a593Smuzhiyun * Environment:	Any
35*4882a593Smuzhiyun * Developer:	Kendall Bennett
36*4882a593Smuzhiyun *
37*4882a593Smuzhiyun * Description:	Module implementing the system specific functions. This
38*4882a593Smuzhiyun *		module is always compiled and linked in the OS depedent
39*4882a593Smuzhiyun *		libraries, and never in a binary portable driver.
40*4882a593Smuzhiyun *
41*4882a593Smuzhiyun *		Jason ported this file to u-boot to run the ATI video card BIOS
42*4882a593Smuzhiyun *		in u-boot. Made all the video memory be emulated during the
43*4882a593Smuzhiyun *		BIOS runing process which may affect the VGA function but the
44*4882a593Smuzhiyun *		frambuffer function can work after run the BIOS.
45*4882a593Smuzhiyun *
46*4882a593Smuzhiyun ****************************************************************************/
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #include <malloc.h>
49*4882a593Smuzhiyun #include <common.h>
50*4882a593Smuzhiyun #include "biosemui.h"
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun BE_sysEnv _BE_env = {{0}};
53*4882a593Smuzhiyun static X86EMU_memFuncs _BE_mem __attribute__((section(GOT2_TYPE))) = {
54*4882a593Smuzhiyun 	BE_rdb,
55*4882a593Smuzhiyun 	BE_rdw,
56*4882a593Smuzhiyun 	BE_rdl,
57*4882a593Smuzhiyun 	BE_wrb,
58*4882a593Smuzhiyun 	BE_wrw,
59*4882a593Smuzhiyun 	BE_wrl,
60*4882a593Smuzhiyun 	};
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun static X86EMU_pioFuncs _BE_pio __attribute__((section(GOT2_TYPE))) = {
63*4882a593Smuzhiyun 	BE_inb,
64*4882a593Smuzhiyun 	BE_inw,
65*4882a593Smuzhiyun 	BE_inl,
66*4882a593Smuzhiyun 	BE_outb,
67*4882a593Smuzhiyun 	BE_outw,
68*4882a593Smuzhiyun 	BE_outl,
69*4882a593Smuzhiyun 	};
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun #define OFF(addr)	(u16)(((addr) >> 0) & 0xffff)
72*4882a593Smuzhiyun #define SEG(addr)	(u16)(((addr) >> 4) & 0xf000)
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun /****************************************************************************
75*4882a593Smuzhiyun PARAMETERS:
76*4882a593Smuzhiyun debugFlags  - Flags to enable debugging options (debug builds only)
77*4882a593Smuzhiyun memSize	    - Amount of memory to allocate for real mode machine
78*4882a593Smuzhiyun info	    - Pointer to default VGA device information
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun REMARKS:
81*4882a593Smuzhiyun This functions initialises the BElib, and uses the passed in
82*4882a593Smuzhiyun BIOS image as the BIOS that is used and emulated at 0xC0000.
83*4882a593Smuzhiyun ****************************************************************************/
BE_init(u32 debugFlags,int memSize,BE_VGAInfo * info,int shared)84*4882a593Smuzhiyun int X86API BE_init(u32 debugFlags, int memSize, BE_VGAInfo * info, int shared)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun #if !defined(__DRIVER__)  && !defined(__KERNEL__)
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	PM_init();
89*4882a593Smuzhiyun #endif
90*4882a593Smuzhiyun 	memset(&M, 0, sizeof(M));
91*4882a593Smuzhiyun 	if (memSize < 20480){
92*4882a593Smuzhiyun 		printf("Emulator requires at least 20Kb of memory!\n");
93*4882a593Smuzhiyun 		return 0;
94*4882a593Smuzhiyun 	}
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	M.mem_base = malloc(memSize);
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	if (M.mem_base == NULL){
99*4882a593Smuzhiyun 		printf("Biosemu:Out of memory!");
100*4882a593Smuzhiyun 		return 0;
101*4882a593Smuzhiyun 	}
102*4882a593Smuzhiyun 	M.mem_size = memSize;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	_BE_env.emulateVGA = 0;
105*4882a593Smuzhiyun 	_BE_env.busmem_base = (unsigned long)malloc(128 * 1024);
106*4882a593Smuzhiyun 	if ((void *)_BE_env.busmem_base == NULL){
107*4882a593Smuzhiyun 		printf("Biosemu:Out of memory!");
108*4882a593Smuzhiyun 		return 0;
109*4882a593Smuzhiyun 	}
110*4882a593Smuzhiyun 	M.x86.debug = debugFlags;
111*4882a593Smuzhiyun 	_BE_bios_init((u32*)info->LowMem);
112*4882a593Smuzhiyun 	X86EMU_setupMemFuncs(&_BE_mem);
113*4882a593Smuzhiyun 	X86EMU_setupPioFuncs(&_BE_pio);
114*4882a593Smuzhiyun 	BE_setVGA(info);
115*4882a593Smuzhiyun 	return 1;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun /****************************************************************************
119*4882a593Smuzhiyun PARAMETERS:
120*4882a593Smuzhiyun info	    - Pointer to VGA device information to make current
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun REMARKS:
123*4882a593Smuzhiyun This function sets the VGA BIOS functions in the emulator to point to the
124*4882a593Smuzhiyun specific VGA BIOS in use. This includes swapping the BIOS interrupt
125*4882a593Smuzhiyun vectors, BIOS image and BIOS data area to the new BIOS. This allows the
126*4882a593Smuzhiyun real mode BIOS to be swapped without resetting the entire emulator.
127*4882a593Smuzhiyun ****************************************************************************/
BE_setVGA(BE_VGAInfo * info)128*4882a593Smuzhiyun void X86API BE_setVGA(BE_VGAInfo * info)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun #ifdef __KERNEL__
132*4882a593Smuzhiyun 	_BE_env.vgaInfo.function = info->function;
133*4882a593Smuzhiyun 	_BE_env.vgaInfo.device = info->device;
134*4882a593Smuzhiyun 	_BE_env.vgaInfo.bus = info->bus;
135*4882a593Smuzhiyun 	_BE_env.vgaInfo.pcidev = info->pcidev;
136*4882a593Smuzhiyun #else
137*4882a593Smuzhiyun 	_BE_env.vgaInfo.pciInfo = info->pciInfo;
138*4882a593Smuzhiyun #endif
139*4882a593Smuzhiyun 	_BE_env.vgaInfo.BIOSImage = info->BIOSImage;
140*4882a593Smuzhiyun 	if (info->BIOSImage) {
141*4882a593Smuzhiyun 		_BE_env.biosmem_base = (ulong) info->BIOSImage;
142*4882a593Smuzhiyun 		_BE_env.biosmem_limit = 0xC0000 + info->BIOSImageLen - 1;
143*4882a593Smuzhiyun 	} else {
144*4882a593Smuzhiyun 		_BE_env.biosmem_base = _BE_env.busmem_base + 0x20000;
145*4882a593Smuzhiyun 		_BE_env.biosmem_limit = 0xC7FFF;
146*4882a593Smuzhiyun 	}
147*4882a593Smuzhiyun 	if ((info->LowMem[0] == 0) && (info->LowMem[1] == 0) &&
148*4882a593Smuzhiyun 	    (info->LowMem[2] == 0) && (info->LowMem[3] == 0))
149*4882a593Smuzhiyun 		_BE_bios_init((u32 *) info->LowMem);
150*4882a593Smuzhiyun 	memcpy((u8 *) M.mem_base, info->LowMem, sizeof(info->LowMem));
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun /****************************************************************************
154*4882a593Smuzhiyun PARAMETERS:
155*4882a593Smuzhiyun info	    - Pointer to VGA device information to retrieve current
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun REMARKS:
158*4882a593Smuzhiyun This function returns the VGA BIOS functions currently active in the
159*4882a593Smuzhiyun emulator, so they can be restored at a later date.
160*4882a593Smuzhiyun ****************************************************************************/
BE_getVGA(BE_VGAInfo * info)161*4882a593Smuzhiyun void X86API BE_getVGA(BE_VGAInfo * info)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun #ifdef __KERNEL__
164*4882a593Smuzhiyun 	info->function = _BE_env.vgaInfo.function;
165*4882a593Smuzhiyun 	info->device = _BE_env.vgaInfo.device;
166*4882a593Smuzhiyun 	info->bus = _BE_env.vgaInfo.bus;
167*4882a593Smuzhiyun 	info->pcidev = _BE_env.vgaInfo.pcidev;
168*4882a593Smuzhiyun #else
169*4882a593Smuzhiyun 	info->pciInfo = _BE_env.vgaInfo.pciInfo;
170*4882a593Smuzhiyun #endif
171*4882a593Smuzhiyun 	info->BIOSImage = _BE_env.vgaInfo.BIOSImage;
172*4882a593Smuzhiyun 	memcpy(info->LowMem, (u8 *) M.mem_base, sizeof(info->LowMem));
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun /****************************************************************************
176*4882a593Smuzhiyun PARAMETERS:
177*4882a593Smuzhiyun r_seg	- Segment for pointer to convert
178*4882a593Smuzhiyun r_off	- Offset for pointer to convert
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun REMARKS:
181*4882a593Smuzhiyun This function maps a real mode pointer in the emulator memory to a protected
182*4882a593Smuzhiyun mode pointer that can be used to directly access the memory.
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun NOTE:	The memory is *always* in little endian format, son on non-x86
185*4882a593Smuzhiyun 	systems you will need to do endian translations to access this
186*4882a593Smuzhiyun 	memory.
187*4882a593Smuzhiyun ****************************************************************************/
BE_mapRealPointer(uint r_seg,uint r_off)188*4882a593Smuzhiyun void *X86API BE_mapRealPointer(uint r_seg, uint r_off)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun 	u32 addr = ((u32) r_seg << 4) + r_off;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
193*4882a593Smuzhiyun 		return (void *)(_BE_env.biosmem_base + addr - 0xC0000);
194*4882a593Smuzhiyun 	} else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
195*4882a593Smuzhiyun 		return (void *)(_BE_env.busmem_base + addr - 0xA0000);
196*4882a593Smuzhiyun 	}
197*4882a593Smuzhiyun 	return (void *)(M.mem_base + addr);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun /****************************************************************************
201*4882a593Smuzhiyun PARAMETERS:
202*4882a593Smuzhiyun len	- Return the length of the VESA buffer
203*4882a593Smuzhiyun rseg	- Place to store VESA buffer segment
204*4882a593Smuzhiyun roff	- Place to store VESA buffer offset
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun REMARKS:
207*4882a593Smuzhiyun This function returns the address of the VESA transfer buffer in real
208*4882a593Smuzhiyun _BE_piomode emulator memory. The VESA transfer buffer is always 1024 bytes long,
209*4882a593Smuzhiyun and located at 15Kb into the start of the real mode memory (16Kb is where
210*4882a593Smuzhiyun we put the real mode code we execute for issuing interrupts).
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun NOTE:	The memory is *always* in little endian format, son on non-x86
213*4882a593Smuzhiyun 	systems you will need to do endian translations to access this
214*4882a593Smuzhiyun 	memory.
215*4882a593Smuzhiyun ****************************************************************************/
BE_getVESABuf(uint * len,uint * rseg,uint * roff)216*4882a593Smuzhiyun void *X86API BE_getVESABuf(uint * len, uint * rseg, uint * roff)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	*len = 1024;
219*4882a593Smuzhiyun 	*rseg = SEG(0x03C00);
220*4882a593Smuzhiyun 	*roff = OFF(0x03C00);
221*4882a593Smuzhiyun 	return (void *)(M.mem_base + ((u32) * rseg << 4) + *roff);
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun /****************************************************************************
225*4882a593Smuzhiyun REMARKS:
226*4882a593Smuzhiyun Cleans up and exits the emulator.
227*4882a593Smuzhiyun ****************************************************************************/
BE_exit(void)228*4882a593Smuzhiyun void X86API BE_exit(void)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun 	free(M.mem_base);
231*4882a593Smuzhiyun 	free((void *)_BE_env.busmem_base);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun /****************************************************************************
235*4882a593Smuzhiyun PARAMETERS:
236*4882a593Smuzhiyun seg	- Segment of code to call
237*4882a593Smuzhiyun off	- Offset of code to call
238*4882a593Smuzhiyun regs	- Real mode registers to load
239*4882a593Smuzhiyun sregs	- Real mode segment registers to load
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun REMARKS:
242*4882a593Smuzhiyun This functions calls a real mode far function at the specified address,
243*4882a593Smuzhiyun and loads all the x86 registers from the passed in registers structure.
244*4882a593Smuzhiyun On exit the registers returned from the call are returned in the same
245*4882a593Smuzhiyun structures.
246*4882a593Smuzhiyun ****************************************************************************/
BE_callRealMode(uint seg,uint off,RMREGS * regs,RMSREGS * sregs)247*4882a593Smuzhiyun void X86API BE_callRealMode(uint seg, uint off, RMREGS * regs, RMSREGS * sregs)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun 	M.x86.R_EAX = regs->e.eax;
250*4882a593Smuzhiyun 	M.x86.R_EBX = regs->e.ebx;
251*4882a593Smuzhiyun 	M.x86.R_ECX = regs->e.ecx;
252*4882a593Smuzhiyun 	M.x86.R_EDX = regs->e.edx;
253*4882a593Smuzhiyun 	M.x86.R_ESI = regs->e.esi;
254*4882a593Smuzhiyun 	M.x86.R_EDI = regs->e.edi;
255*4882a593Smuzhiyun 	M.x86.R_DS = sregs->ds;
256*4882a593Smuzhiyun 	M.x86.R_ES = sregs->es;
257*4882a593Smuzhiyun 	M.x86.R_FS = sregs->fs;
258*4882a593Smuzhiyun 	M.x86.R_GS = sregs->gs;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	((u8 *) M.mem_base)[0x4000] = 0x9A;
261*4882a593Smuzhiyun 	((u8 *) M.mem_base)[0x4001] = (u8) off;
262*4882a593Smuzhiyun 	((u8 *) M.mem_base)[0x4002] = (u8) (off >> 8);
263*4882a593Smuzhiyun 	((u8 *) M.mem_base)[0x4003] = (u8) seg;
264*4882a593Smuzhiyun 	((u8 *) M.mem_base)[0x4004] = (u8) (seg >> 8);
265*4882a593Smuzhiyun 	((u8 *) M.mem_base)[0x4005] = 0xF1;	/* Illegal op-code */
266*4882a593Smuzhiyun 	M.x86.R_CS = SEG(0x04000);
267*4882a593Smuzhiyun 	M.x86.R_IP = OFF(0x04000);
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	M.x86.R_SS = SEG(M.mem_size - 2);
270*4882a593Smuzhiyun 	M.x86.R_SP = OFF(M.mem_size - 2) + 2;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	X86EMU_exec();
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	regs->e.cflag = M.x86.R_EFLG & F_CF;
275*4882a593Smuzhiyun 	regs->e.eax = M.x86.R_EAX;
276*4882a593Smuzhiyun 	regs->e.ebx = M.x86.R_EBX;
277*4882a593Smuzhiyun 	regs->e.ecx = M.x86.R_ECX;
278*4882a593Smuzhiyun 	regs->e.edx = M.x86.R_EDX;
279*4882a593Smuzhiyun 	regs->e.esi = M.x86.R_ESI;
280*4882a593Smuzhiyun 	regs->e.edi = M.x86.R_EDI;
281*4882a593Smuzhiyun 	sregs->ds = M.x86.R_DS;
282*4882a593Smuzhiyun 	sregs->es = M.x86.R_ES;
283*4882a593Smuzhiyun 	sregs->fs = M.x86.R_FS;
284*4882a593Smuzhiyun 	sregs->gs = M.x86.R_GS;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun /****************************************************************************
288*4882a593Smuzhiyun PARAMETERS:
289*4882a593Smuzhiyun intno	- Interrupt number to execute
290*4882a593Smuzhiyun in	- Real mode registers to load
291*4882a593Smuzhiyun out	- Place to store resulting real mode registers
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun REMARKS:
294*4882a593Smuzhiyun This functions calls a real mode interrupt function at the specified address,
295*4882a593Smuzhiyun and loads all the x86 registers from the passed in registers structure.
296*4882a593Smuzhiyun On exit the registers returned from the call are returned in out stucture.
297*4882a593Smuzhiyun ****************************************************************************/
BE_int86(int intno,RMREGS * in,RMREGS * out)298*4882a593Smuzhiyun int X86API BE_int86(int intno, RMREGS * in, RMREGS * out)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun 	M.x86.R_EAX = in->e.eax;
301*4882a593Smuzhiyun 	M.x86.R_EBX = in->e.ebx;
302*4882a593Smuzhiyun 	M.x86.R_ECX = in->e.ecx;
303*4882a593Smuzhiyun 	M.x86.R_EDX = in->e.edx;
304*4882a593Smuzhiyun 	M.x86.R_ESI = in->e.esi;
305*4882a593Smuzhiyun 	M.x86.R_EDI = in->e.edi;
306*4882a593Smuzhiyun 	((u8 *) M.mem_base)[0x4000] = 0xCD;
307*4882a593Smuzhiyun 	((u8 *) M.mem_base)[0x4001] = (u8) intno;
308*4882a593Smuzhiyun 	((u8 *) M.mem_base)[0x4002] = 0xF1;
309*4882a593Smuzhiyun 	M.x86.R_CS = SEG(0x04000);
310*4882a593Smuzhiyun 	M.x86.R_IP = OFF(0x04000);
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	M.x86.R_SS = SEG(M.mem_size - 1);
313*4882a593Smuzhiyun 	M.x86.R_SP = OFF(M.mem_size - 1) - 1;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	X86EMU_exec();
316*4882a593Smuzhiyun 	out->e.cflag = M.x86.R_EFLG & F_CF;
317*4882a593Smuzhiyun 	out->e.eax = M.x86.R_EAX;
318*4882a593Smuzhiyun 	out->e.ebx = M.x86.R_EBX;
319*4882a593Smuzhiyun 	out->e.ecx = M.x86.R_ECX;
320*4882a593Smuzhiyun 	out->e.edx = M.x86.R_EDX;
321*4882a593Smuzhiyun 	out->e.esi = M.x86.R_ESI;
322*4882a593Smuzhiyun 	out->e.edi = M.x86.R_EDI;
323*4882a593Smuzhiyun 	return out->x.ax;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun /****************************************************************************
327*4882a593Smuzhiyun PARAMETERS:
328*4882a593Smuzhiyun intno	- Interrupt number to execute
329*4882a593Smuzhiyun in	- Real mode registers to load
330*4882a593Smuzhiyun out	- Place to store resulting real mode registers
331*4882a593Smuzhiyun sregs	- Real mode segment registers to load
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun REMARKS:
334*4882a593Smuzhiyun This functions calls a real mode interrupt function at the specified address,
335*4882a593Smuzhiyun and loads all the x86 registers from the passed in registers structure.
336*4882a593Smuzhiyun On exit the registers returned from the call are returned in out stucture.
337*4882a593Smuzhiyun ****************************************************************************/
BE_int86x(int intno,RMREGS * in,RMREGS * out,RMSREGS * sregs)338*4882a593Smuzhiyun int X86API BE_int86x(int intno, RMREGS * in, RMREGS * out, RMSREGS * sregs)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun 	M.x86.R_EAX = in->e.eax;
341*4882a593Smuzhiyun 	M.x86.R_EBX = in->e.ebx;
342*4882a593Smuzhiyun 	M.x86.R_ECX = in->e.ecx;
343*4882a593Smuzhiyun 	M.x86.R_EDX = in->e.edx;
344*4882a593Smuzhiyun 	M.x86.R_ESI = in->e.esi;
345*4882a593Smuzhiyun 	M.x86.R_EDI = in->e.edi;
346*4882a593Smuzhiyun 	M.x86.R_DS = sregs->ds;
347*4882a593Smuzhiyun 	M.x86.R_ES = sregs->es;
348*4882a593Smuzhiyun 	M.x86.R_FS = sregs->fs;
349*4882a593Smuzhiyun 	M.x86.R_GS = sregs->gs;
350*4882a593Smuzhiyun 	((u8 *) M.mem_base)[0x4000] = 0xCD;
351*4882a593Smuzhiyun 	((u8 *) M.mem_base)[0x4001] = (u8) intno;
352*4882a593Smuzhiyun 	((u8 *) M.mem_base)[0x4002] = 0xF1;
353*4882a593Smuzhiyun 	M.x86.R_CS = SEG(0x04000);
354*4882a593Smuzhiyun 	M.x86.R_IP = OFF(0x04000);
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	M.x86.R_SS = SEG(M.mem_size - 1);
357*4882a593Smuzhiyun 	M.x86.R_SP = OFF(M.mem_size - 1) - 1;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	X86EMU_exec();
360*4882a593Smuzhiyun 	out->e.cflag = M.x86.R_EFLG & F_CF;
361*4882a593Smuzhiyun 	out->e.eax = M.x86.R_EAX;
362*4882a593Smuzhiyun 	out->e.ebx = M.x86.R_EBX;
363*4882a593Smuzhiyun 	out->e.ecx = M.x86.R_ECX;
364*4882a593Smuzhiyun 	out->e.edx = M.x86.R_EDX;
365*4882a593Smuzhiyun 	out->e.esi = M.x86.R_ESI;
366*4882a593Smuzhiyun 	out->e.edi = M.x86.R_EDI;
367*4882a593Smuzhiyun 	sregs->ds = M.x86.R_DS;
368*4882a593Smuzhiyun 	sregs->es = M.x86.R_ES;
369*4882a593Smuzhiyun 	sregs->fs = M.x86.R_FS;
370*4882a593Smuzhiyun 	sregs->gs = M.x86.R_GS;
371*4882a593Smuzhiyun 	return out->x.ax;
372*4882a593Smuzhiyun }
373