xref: /openbmc/u-boot/drivers/bios_emulator/besys.c (revision ece92f85053b8df613edcf05b26a416cbc3d629c)
1*ece92f85SJason Jin /****************************************************************************
2*ece92f85SJason Jin *
3*ece92f85SJason Jin *                        BIOS emulator and interface
4*ece92f85SJason Jin *                      to Realmode X86 Emulator Library
5*ece92f85SJason Jin *
6*ece92f85SJason Jin *  ========================================================================
7*ece92f85SJason Jin *
8*ece92f85SJason Jin *   Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
9*ece92f85SJason Jin *   Jason Jin<Jason.jin@freescale.com>
10*ece92f85SJason Jin *
11*ece92f85SJason Jin *   Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
12*ece92f85SJason Jin *
13*ece92f85SJason Jin *   This file may be distributed and/or modified under the terms of the
14*ece92f85SJason Jin *   GNU General Public License version 2.0 as published by the Free
15*ece92f85SJason Jin *   Software Foundation and appearing in the file LICENSE.GPL included
16*ece92f85SJason Jin *   in the packaging of this file.
17*ece92f85SJason Jin *
18*ece92f85SJason Jin *   Licensees holding a valid Commercial License for this product from
19*ece92f85SJason Jin *   SciTech Software, Inc. may use this file in accordance with the
20*ece92f85SJason Jin *   Commercial License Agreement provided with the Software.
21*ece92f85SJason Jin *
22*ece92f85SJason Jin *   This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
23*ece92f85SJason Jin *   THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24*ece92f85SJason Jin *   PURPOSE.
25*ece92f85SJason Jin *
26*ece92f85SJason Jin *   See http://www.scitechsoft.com/license/ for information about
27*ece92f85SJason Jin *   the licensing options available and how to purchase a Commercial
28*ece92f85SJason Jin *   License Agreement.
29*ece92f85SJason Jin *
30*ece92f85SJason Jin *   Contact license@scitechsoft.com if any conditions of this licensing
31*ece92f85SJason Jin *   are not clear to you, or you have questions about licensing options.
32*ece92f85SJason Jin *
33*ece92f85SJason Jin *  ========================================================================
34*ece92f85SJason Jin *
35*ece92f85SJason Jin * Language:     ANSI C
36*ece92f85SJason Jin * Environment:  Any
37*ece92f85SJason Jin * Developer:    Kendall Bennett
38*ece92f85SJason Jin *
39*ece92f85SJason Jin * Description:  This file includes BIOS emulator I/O and memory access
40*ece92f85SJason Jin *               functions.
41*ece92f85SJason Jin *
42*ece92f85SJason Jin *		Jason ported this file to u-boot to run the ATI video card
43*ece92f85SJason Jin *		BIOS in u-boot. Removed some emulate functions such as the
44*ece92f85SJason Jin *		timer port access. Made all the VGA port except reading 0x3c3
45*ece92f85SJason Jin *		be emulated. Seems like reading 0x3c3 should return the high
46*ece92f85SJason Jin *		16 bit of the io port.
47*ece92f85SJason Jin *
48*ece92f85SJason Jin ****************************************************************************/
49*ece92f85SJason Jin 
50*ece92f85SJason Jin #include "biosemui.h"
51*ece92f85SJason Jin 
52*ece92f85SJason Jin /*------------------------- Global Variables ------------------------------*/
53*ece92f85SJason Jin 
54*ece92f85SJason Jin #ifndef __i386__
55*ece92f85SJason Jin static char *BE_biosDate = "08/14/99";
56*ece92f85SJason Jin static u8 BE_model = 0xFC;
57*ece92f85SJason Jin static u8 BE_submodel = 0x00;
58*ece92f85SJason Jin #endif
59*ece92f85SJason Jin 
60*ece92f85SJason Jin /*----------------------------- Implementation ----------------------------*/
61*ece92f85SJason Jin 
62*ece92f85SJason Jin /****************************************************************************
63*ece92f85SJason Jin PARAMETERS:
64*ece92f85SJason Jin addr    - Emulator memory address to convert
65*ece92f85SJason Jin 
66*ece92f85SJason Jin RETURNS:
67*ece92f85SJason Jin Actual memory address to read or write the data
68*ece92f85SJason Jin 
69*ece92f85SJason Jin REMARKS:
70*ece92f85SJason Jin This function converts an emulator memory address in a 32-bit range to
71*ece92f85SJason Jin a real memory address that we wish to access. It handles splitting up the
72*ece92f85SJason Jin memory address space appropriately to access the emulator BIOS image, video
73*ece92f85SJason Jin memory and system BIOS etc.
74*ece92f85SJason Jin ****************************************************************************/
75*ece92f85SJason Jin static u8 *BE_memaddr(u32 addr)
76*ece92f85SJason Jin {
77*ece92f85SJason Jin 	if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
78*ece92f85SJason Jin 		return (u8*)(_BE_env.biosmem_base + addr - 0xC0000);
79*ece92f85SJason Jin 	} else if (addr > _BE_env.biosmem_limit && addr < 0xD0000) {
80*ece92f85SJason Jin 		DB(printf("BE_memaddr: address %#lx may be invalid!\n", addr);)
81*ece92f85SJason Jin 		return M.mem_base;
82*ece92f85SJason Jin 	} else if (addr >= 0xA0000 && addr <= 0xBFFFF) {
83*ece92f85SJason Jin 		return (u8*)(_BE_env.busmem_base + addr - 0xA0000);
84*ece92f85SJason Jin 	}
85*ece92f85SJason Jin #ifdef __i386__
86*ece92f85SJason Jin 	else if (addr >= 0xD0000 && addr <= 0xFFFFF) {
87*ece92f85SJason Jin 		/* We map the real System BIOS directly on real PC's */
88*ece92f85SJason Jin 		DB(printf("BE_memaddr: System BIOS address %#lx\n", addr);)
89*ece92f85SJason Jin 		    return _BE_env.busmem_base + addr - 0xA0000;
90*ece92f85SJason Jin 	}
91*ece92f85SJason Jin #else
92*ece92f85SJason Jin 	else if (addr >= 0xFFFF5 && addr < 0xFFFFE) {
93*ece92f85SJason Jin 		/* Return a faked BIOS date string for non-x86 machines */
94*ece92f85SJason Jin 		DB(printf("BE_memaddr - Returning BIOS date\n");)
95*ece92f85SJason Jin 		return BE_biosDate + addr - 0xFFFF5;
96*ece92f85SJason Jin 	} else if (addr == 0xFFFFE) {
97*ece92f85SJason Jin 		/* Return system model identifier for non-x86 machines */
98*ece92f85SJason Jin 		DB(printf("BE_memaddr - Returning model\n");)
99*ece92f85SJason Jin 		return &BE_model;
100*ece92f85SJason Jin 	} else if (addr == 0xFFFFF) {
101*ece92f85SJason Jin 		/* Return system submodel identifier for non-x86 machines */
102*ece92f85SJason Jin 		DB(printf("BE_memaddr - Returning submodel\n");)
103*ece92f85SJason Jin 		return &BE_submodel;
104*ece92f85SJason Jin 	}
105*ece92f85SJason Jin #endif
106*ece92f85SJason Jin 	else if (addr > M.mem_size - 1) {
107*ece92f85SJason Jin 		HALT_SYS();
108*ece92f85SJason Jin 		return M.mem_base;
109*ece92f85SJason Jin 	}
110*ece92f85SJason Jin 
111*ece92f85SJason Jin 	return M.mem_base + addr;
112*ece92f85SJason Jin }
113*ece92f85SJason Jin 
114*ece92f85SJason Jin /****************************************************************************
115*ece92f85SJason Jin PARAMETERS:
116*ece92f85SJason Jin addr    - Emulator memory address to read
117*ece92f85SJason Jin 
118*ece92f85SJason Jin RETURNS:
119*ece92f85SJason Jin Byte value read from emulator memory.
120*ece92f85SJason Jin 
121*ece92f85SJason Jin REMARKS:
122*ece92f85SJason Jin Reads a byte value from the emulator memory. We have three distinct memory
123*ece92f85SJason Jin regions that are handled differently, which this function handles.
124*ece92f85SJason Jin ****************************************************************************/
125*ece92f85SJason Jin u8 X86API BE_rdb(u32 addr)
126*ece92f85SJason Jin {
127*ece92f85SJason Jin 	if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
128*ece92f85SJason Jin 		return 0;
129*ece92f85SJason Jin 	else {
130*ece92f85SJason Jin 		u8 val = readb_le(BE_memaddr(addr));
131*ece92f85SJason Jin 		return val;
132*ece92f85SJason Jin 	}
133*ece92f85SJason Jin }
134*ece92f85SJason Jin 
135*ece92f85SJason Jin /****************************************************************************
136*ece92f85SJason Jin PARAMETERS:
137*ece92f85SJason Jin addr    - Emulator memory address to read
138*ece92f85SJason Jin 
139*ece92f85SJason Jin RETURNS:
140*ece92f85SJason Jin Word value read from emulator memory.
141*ece92f85SJason Jin 
142*ece92f85SJason Jin REMARKS:
143*ece92f85SJason Jin Reads a word value from the emulator memory. We have three distinct memory
144*ece92f85SJason Jin regions that are handled differently, which this function handles.
145*ece92f85SJason Jin ****************************************************************************/
146*ece92f85SJason Jin u16 X86API BE_rdw(u32 addr)
147*ece92f85SJason Jin {
148*ece92f85SJason Jin 	if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
149*ece92f85SJason Jin 		return 0;
150*ece92f85SJason Jin 	else {
151*ece92f85SJason Jin 		u8 *base = BE_memaddr(addr);
152*ece92f85SJason Jin 		u16 val = readw_le(base);
153*ece92f85SJason Jin 		return val;
154*ece92f85SJason Jin 	}
155*ece92f85SJason Jin }
156*ece92f85SJason Jin 
157*ece92f85SJason Jin /****************************************************************************
158*ece92f85SJason Jin PARAMETERS:
159*ece92f85SJason Jin addr    - Emulator memory address to read
160*ece92f85SJason Jin 
161*ece92f85SJason Jin RETURNS:
162*ece92f85SJason Jin Long value read from emulator memory.
163*ece92f85SJason Jin 
164*ece92f85SJason Jin REMARKS:
165*ece92f85SJason Jin Reads a 32-bit value from the emulator memory. We have three distinct memory
166*ece92f85SJason Jin regions that are handled differently, which this function handles.
167*ece92f85SJason Jin ****************************************************************************/
168*ece92f85SJason Jin u32 X86API BE_rdl(u32 addr)
169*ece92f85SJason Jin {
170*ece92f85SJason Jin 	if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
171*ece92f85SJason Jin 		return 0;
172*ece92f85SJason Jin 	else {
173*ece92f85SJason Jin 		u8 *base = BE_memaddr(addr);
174*ece92f85SJason Jin 		u32 val = readl_le(base);
175*ece92f85SJason Jin 		return val;
176*ece92f85SJason Jin 	}
177*ece92f85SJason Jin }
178*ece92f85SJason Jin 
179*ece92f85SJason Jin /****************************************************************************
180*ece92f85SJason Jin PARAMETERS:
181*ece92f85SJason Jin addr    - Emulator memory address to read
182*ece92f85SJason Jin val     - Value to store
183*ece92f85SJason Jin 
184*ece92f85SJason Jin REMARKS:
185*ece92f85SJason Jin Writes a byte value to emulator memory. We have three distinct memory
186*ece92f85SJason Jin regions that are handled differently, which this function handles.
187*ece92f85SJason Jin ****************************************************************************/
188*ece92f85SJason Jin void X86API BE_wrb(u32 addr, u8 val)
189*ece92f85SJason Jin {
190*ece92f85SJason Jin 	if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
191*ece92f85SJason Jin 		writeb_le(BE_memaddr(addr), val);
192*ece92f85SJason Jin 	}
193*ece92f85SJason Jin }
194*ece92f85SJason Jin 
195*ece92f85SJason Jin /****************************************************************************
196*ece92f85SJason Jin PARAMETERS:
197*ece92f85SJason Jin addr    - Emulator memory address to read
198*ece92f85SJason Jin val     - Value to store
199*ece92f85SJason Jin 
200*ece92f85SJason Jin REMARKS:
201*ece92f85SJason Jin Writes a word value to emulator memory. We have three distinct memory
202*ece92f85SJason Jin regions that are handled differently, which this function handles.
203*ece92f85SJason Jin ****************************************************************************/
204*ece92f85SJason Jin void X86API BE_wrw(u32 addr, u16 val)
205*ece92f85SJason Jin {
206*ece92f85SJason Jin 	if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
207*ece92f85SJason Jin 		u8 *base = BE_memaddr(addr);
208*ece92f85SJason Jin 		writew_le(base, val);
209*ece92f85SJason Jin 
210*ece92f85SJason Jin 	}
211*ece92f85SJason Jin }
212*ece92f85SJason Jin 
213*ece92f85SJason Jin /****************************************************************************
214*ece92f85SJason Jin PARAMETERS:
215*ece92f85SJason Jin addr    - Emulator memory address to read
216*ece92f85SJason Jin val     - Value to store
217*ece92f85SJason Jin 
218*ece92f85SJason Jin REMARKS:
219*ece92f85SJason Jin Writes a 32-bit value to emulator memory. We have three distinct memory
220*ece92f85SJason Jin regions that are handled differently, which this function handles.
221*ece92f85SJason Jin ****************************************************************************/
222*ece92f85SJason Jin void X86API BE_wrl(u32 addr, u32 val)
223*ece92f85SJason Jin {
224*ece92f85SJason Jin 	if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
225*ece92f85SJason Jin 		u8 *base = BE_memaddr(addr);
226*ece92f85SJason Jin 		writel_le(base, val);
227*ece92f85SJason Jin 	}
228*ece92f85SJason Jin }
229*ece92f85SJason Jin 
230*ece92f85SJason Jin #if defined(DEBUG) || !defined(__i386__)
231*ece92f85SJason Jin 
232*ece92f85SJason Jin /* For Non-Intel machines we may need to emulate some I/O port accesses that
233*ece92f85SJason Jin  * the BIOS may try to access, such as the PCI config registers.
234*ece92f85SJason Jin  */
235*ece92f85SJason Jin 
236*ece92f85SJason Jin #define IS_TIMER_PORT(port) (0x40 <= port && port <= 0x43)
237*ece92f85SJason Jin #define IS_CMOS_PORT(port)  (0x70 <= port && port <= 0x71)
238*ece92f85SJason Jin /*#define IS_VGA_PORT(port)   (_BE_env.emulateVGA && 0x3C0 <= port && port <= 0x3DA)*/
239*ece92f85SJason Jin #define IS_VGA_PORT(port)   (0x3C0 <= port && port <= 0x3DA)
240*ece92f85SJason Jin #define IS_PCI_PORT(port)   (0xCF8 <= port && port <= 0xCFF)
241*ece92f85SJason Jin #define IS_SPKR_PORT(port)  (port == 0x61)
242*ece92f85SJason Jin 
243*ece92f85SJason Jin /****************************************************************************
244*ece92f85SJason Jin PARAMETERS:
245*ece92f85SJason Jin port    - Port to read from
246*ece92f85SJason Jin type    - Type of access to perform
247*ece92f85SJason Jin 
248*ece92f85SJason Jin REMARKS:
249*ece92f85SJason Jin Performs an emulated read from the Standard VGA I/O ports. If the target
250*ece92f85SJason Jin hardware does not support mapping the VGA I/O and memory (such as some
251*ece92f85SJason Jin PowerPC systems), we emulate the VGA so that the BIOS will still be able to
252*ece92f85SJason Jin set NonVGA display modes such as on ATI hardware.
253*ece92f85SJason Jin ****************************************************************************/
254*ece92f85SJason Jin static u8 VGA_inpb(
255*ece92f85SJason Jin     const int port)
256*ece92f85SJason Jin {
257*ece92f85SJason Jin     u8 val = 0xff;
258*ece92f85SJason Jin 
259*ece92f85SJason Jin     switch (port) {
260*ece92f85SJason Jin         case 0x3C0:
261*ece92f85SJason Jin             /* 3C0 has funky characteristics because it can act as either
262*ece92f85SJason Jin                a data register or index register depending on the state
263*ece92f85SJason Jin                of an internal flip flop in the hardware. Hence we have
264*ece92f85SJason Jin                to emulate that functionality in here. */
265*ece92f85SJason Jin             if (_BE_env.flipFlop3C0 == 0) {
266*ece92f85SJason Jin                 /* Access 3C0 as index register*/
267*ece92f85SJason Jin                 val = _BE_env.emu3C0;
268*ece92f85SJason Jin                 }
269*ece92f85SJason Jin             else {
270*ece92f85SJason Jin                 /* Access 3C0 as data register*/
271*ece92f85SJason Jin                 if (_BE_env.emu3C0 < ATT_C)
272*ece92f85SJason Jin                     val = _BE_env.emu3C1[_BE_env.emu3C0];
273*ece92f85SJason Jin                 }
274*ece92f85SJason Jin             _BE_env.flipFlop3C0 ^= 1;
275*ece92f85SJason Jin             break;
276*ece92f85SJason Jin         case 0x3C1:
277*ece92f85SJason Jin             if (_BE_env.emu3C0 < ATT_C)
278*ece92f85SJason Jin                 return _BE_env.emu3C1[_BE_env.emu3C0];
279*ece92f85SJason Jin             break;
280*ece92f85SJason Jin         case 0x3CC:
281*ece92f85SJason Jin             return _BE_env.emu3C2;
282*ece92f85SJason Jin         case 0x3C4:
283*ece92f85SJason Jin             return _BE_env.emu3C4;
284*ece92f85SJason Jin         case 0x3C5:
285*ece92f85SJason Jin             if (_BE_env.emu3C4 < ATT_C)
286*ece92f85SJason Jin                 return _BE_env.emu3C5[_BE_env.emu3C4];
287*ece92f85SJason Jin             break;
288*ece92f85SJason Jin         case 0x3C6:
289*ece92f85SJason Jin             return _BE_env.emu3C6;
290*ece92f85SJason Jin         case 0x3C7:
291*ece92f85SJason Jin             return _BE_env.emu3C7;
292*ece92f85SJason Jin         case 0x3C8:
293*ece92f85SJason Jin             return _BE_env.emu3C8;
294*ece92f85SJason Jin         case 0x3C9:
295*ece92f85SJason Jin             if (_BE_env.emu3C7 < PAL_C)
296*ece92f85SJason Jin                 return _BE_env.emu3C9[_BE_env.emu3C7++];
297*ece92f85SJason Jin             break;
298*ece92f85SJason Jin         case 0x3CE:
299*ece92f85SJason Jin             return _BE_env.emu3CE;
300*ece92f85SJason Jin         case 0x3CF:
301*ece92f85SJason Jin             if (_BE_env.emu3CE < GRA_C)
302*ece92f85SJason Jin                 return _BE_env.emu3CF[_BE_env.emu3CE];
303*ece92f85SJason Jin             break;
304*ece92f85SJason Jin         case 0x3D4:
305*ece92f85SJason Jin             if (_BE_env.emu3C2 & 0x1)
306*ece92f85SJason Jin                 return _BE_env.emu3D4;
307*ece92f85SJason Jin             break;
308*ece92f85SJason Jin         case 0x3D5:
309*ece92f85SJason Jin             if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C))
310*ece92f85SJason Jin                 return _BE_env.emu3D5[_BE_env.emu3D4];
311*ece92f85SJason Jin             break;
312*ece92f85SJason Jin         case 0x3DA:
313*ece92f85SJason Jin             _BE_env.flipFlop3C0 = 0;
314*ece92f85SJason Jin             val = _BE_env.emu3DA;
315*ece92f85SJason Jin             _BE_env.emu3DA ^= 0x9;
316*ece92f85SJason Jin             break;
317*ece92f85SJason Jin         }
318*ece92f85SJason Jin     return val;
319*ece92f85SJason Jin }
320*ece92f85SJason Jin 
321*ece92f85SJason Jin /****************************************************************************
322*ece92f85SJason Jin PARAMETERS:
323*ece92f85SJason Jin port    - Port to write to
324*ece92f85SJason Jin type    - Type of access to perform
325*ece92f85SJason Jin 
326*ece92f85SJason Jin REMARKS:
327*ece92f85SJason Jin Performs an emulated write to one of the 8253 timer registers. For now
328*ece92f85SJason Jin we only emulate timer 0 which is the only timer that the BIOS code appears
329*ece92f85SJason Jin to use.
330*ece92f85SJason Jin ****************************************************************************/
331*ece92f85SJason Jin static void VGA_outpb(
332*ece92f85SJason Jin     int port,
333*ece92f85SJason Jin     u8 val)
334*ece92f85SJason Jin {
335*ece92f85SJason Jin     switch (port) {
336*ece92f85SJason Jin         case 0x3C0:
337*ece92f85SJason Jin             /* 3C0 has funky characteristics because it can act as either
338*ece92f85SJason Jin              a data register or index register depending on the state
339*ece92f85SJason Jin              of an internal flip flop in the hardware. Hence we have
340*ece92f85SJason Jin              to emulate that functionality in here.*/
341*ece92f85SJason Jin             if (_BE_env.flipFlop3C0 == 0) {
342*ece92f85SJason Jin                 /* Access 3C0 as index register*/
343*ece92f85SJason Jin                 _BE_env.emu3C0 = val;
344*ece92f85SJason Jin                 }
345*ece92f85SJason Jin             else {
346*ece92f85SJason Jin                 /* Access 3C0 as data register*/
347*ece92f85SJason Jin                 if (_BE_env.emu3C0 < ATT_C)
348*ece92f85SJason Jin                     _BE_env.emu3C1[_BE_env.emu3C0] = val;
349*ece92f85SJason Jin                 }
350*ece92f85SJason Jin             _BE_env.flipFlop3C0 ^= 1;
351*ece92f85SJason Jin             break;
352*ece92f85SJason Jin         case 0x3C2:
353*ece92f85SJason Jin             _BE_env.emu3C2 = val;
354*ece92f85SJason Jin             break;
355*ece92f85SJason Jin         case 0x3C4:
356*ece92f85SJason Jin             _BE_env.emu3C4 = val;
357*ece92f85SJason Jin             break;
358*ece92f85SJason Jin         case 0x3C5:
359*ece92f85SJason Jin             if (_BE_env.emu3C4 < ATT_C)
360*ece92f85SJason Jin                 _BE_env.emu3C5[_BE_env.emu3C4] = val;
361*ece92f85SJason Jin             break;
362*ece92f85SJason Jin         case 0x3C6:
363*ece92f85SJason Jin             _BE_env.emu3C6 = val;
364*ece92f85SJason Jin             break;
365*ece92f85SJason Jin         case 0x3C7:
366*ece92f85SJason Jin             _BE_env.emu3C7 = (int)val * 3;
367*ece92f85SJason Jin             break;
368*ece92f85SJason Jin         case 0x3C8:
369*ece92f85SJason Jin             _BE_env.emu3C8 = (int)val * 3;
370*ece92f85SJason Jin             break;
371*ece92f85SJason Jin         case 0x3C9:
372*ece92f85SJason Jin             if (_BE_env.emu3C8 < PAL_C)
373*ece92f85SJason Jin                 _BE_env.emu3C9[_BE_env.emu3C8++] = val;
374*ece92f85SJason Jin             break;
375*ece92f85SJason Jin         case 0x3CE:
376*ece92f85SJason Jin             _BE_env.emu3CE = val;
377*ece92f85SJason Jin             break;
378*ece92f85SJason Jin         case 0x3CF:
379*ece92f85SJason Jin             if (_BE_env.emu3CE < GRA_C)
380*ece92f85SJason Jin                 _BE_env.emu3CF[_BE_env.emu3CE] = val;
381*ece92f85SJason Jin             break;
382*ece92f85SJason Jin         case 0x3D4:
383*ece92f85SJason Jin             if (_BE_env.emu3C2 & 0x1)
384*ece92f85SJason Jin                 _BE_env.emu3D4 = val;
385*ece92f85SJason Jin             break;
386*ece92f85SJason Jin         case 0x3D5:
387*ece92f85SJason Jin             if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C))
388*ece92f85SJason Jin                 _BE_env.emu3D5[_BE_env.emu3D4] = val;
389*ece92f85SJason Jin             break;
390*ece92f85SJason Jin         }
391*ece92f85SJason Jin }
392*ece92f85SJason Jin 
393*ece92f85SJason Jin /****************************************************************************
394*ece92f85SJason Jin PARAMETERS:
395*ece92f85SJason Jin regOffset   - Offset into register space for non-DWORD accesses
396*ece92f85SJason Jin value       - Value to write to register for PCI_WRITE_* operations
397*ece92f85SJason Jin func        - Function to perform (PCIAccessRegFlags)
398*ece92f85SJason Jin 
399*ece92f85SJason Jin RETURNS:
400*ece92f85SJason Jin Value read from configuration register for PCI_READ_* operations
401*ece92f85SJason Jin 
402*ece92f85SJason Jin REMARKS:
403*ece92f85SJason Jin Accesses a PCI configuration space register by decoding the value currently
404*ece92f85SJason Jin stored in the _BE_env.configAddress variable and passing it through to the
405*ece92f85SJason Jin portable PCI_accessReg function.
406*ece92f85SJason Jin ****************************************************************************/
407*ece92f85SJason Jin static u32 BE_accessReg(int regOffset, u32 value, int func)
408*ece92f85SJason Jin {
409*ece92f85SJason Jin #ifdef __KERNEL__
410*ece92f85SJason Jin 	int function, device, bus;
411*ece92f85SJason Jin 	u8 val8;
412*ece92f85SJason Jin 	u16 val16;
413*ece92f85SJason Jin 	u32 val32;
414*ece92f85SJason Jin 
415*ece92f85SJason Jin 
416*ece92f85SJason Jin 	/* Decode the configuration register values for the register we wish to
417*ece92f85SJason Jin 	 * access
418*ece92f85SJason Jin 	 */
419*ece92f85SJason Jin 	regOffset += (_BE_env.configAddress & 0xFF);
420*ece92f85SJason Jin 	function = (_BE_env.configAddress >> 8) & 0x7;
421*ece92f85SJason Jin 	device = (_BE_env.configAddress >> 11) & 0x1F;
422*ece92f85SJason Jin 	bus = (_BE_env.configAddress >> 16) & 0xFF;
423*ece92f85SJason Jin 
424*ece92f85SJason Jin 	/* Ignore accesses to all devices other than the one we're POSTing */
425*ece92f85SJason Jin 	if ((function == _BE_env.vgaInfo.function) &&
426*ece92f85SJason Jin 	    (device == _BE_env.vgaInfo.device) &&
427*ece92f85SJason Jin 	    (bus == _BE_env.vgaInfo.bus)) {
428*ece92f85SJason Jin 		switch (func) {
429*ece92f85SJason Jin 		case REG_READ_BYTE:
430*ece92f85SJason Jin 			pci_read_config_byte(_BE_env.vgaInfo.pcidev, regOffset,
431*ece92f85SJason Jin 					     &val8);
432*ece92f85SJason Jin 			return val8;
433*ece92f85SJason Jin 		case REG_READ_WORD:
434*ece92f85SJason Jin 			pci_read_config_word(_BE_env.vgaInfo.pcidev, regOffset,
435*ece92f85SJason Jin 					     &val16);
436*ece92f85SJason Jin 			return val16;
437*ece92f85SJason Jin 		case REG_READ_DWORD:
438*ece92f85SJason Jin 			pci_read_config_dword(_BE_env.vgaInfo.pcidev, regOffset,
439*ece92f85SJason Jin 					      &val32);
440*ece92f85SJason Jin 			return val32;
441*ece92f85SJason Jin 		case REG_WRITE_BYTE:
442*ece92f85SJason Jin 			pci_write_config_byte(_BE_env.vgaInfo.pcidev, regOffset,
443*ece92f85SJason Jin 					      value);
444*ece92f85SJason Jin 
445*ece92f85SJason Jin 			return 0;
446*ece92f85SJason Jin 		case REG_WRITE_WORD:
447*ece92f85SJason Jin 			pci_write_config_word(_BE_env.vgaInfo.pcidev, regOffset,
448*ece92f85SJason Jin 					      value);
449*ece92f85SJason Jin 
450*ece92f85SJason Jin 			return 0;
451*ece92f85SJason Jin 		case REG_WRITE_DWORD:
452*ece92f85SJason Jin 			pci_write_config_dword(_BE_env.vgaInfo.pcidev,
453*ece92f85SJason Jin 					       regOffset, value);
454*ece92f85SJason Jin 
455*ece92f85SJason Jin 			return 0;
456*ece92f85SJason Jin 		}
457*ece92f85SJason Jin 	}
458*ece92f85SJason Jin 	return 0;
459*ece92f85SJason Jin #else
460*ece92f85SJason Jin 	PCIDeviceInfo pciInfo;
461*ece92f85SJason Jin 
462*ece92f85SJason Jin 	pciInfo.mech1 = 1;
463*ece92f85SJason Jin 	pciInfo.slot.i = 0;
464*ece92f85SJason Jin 	pciInfo.slot.p.Function = (_BE_env.configAddress >> 8) & 0x7;
465*ece92f85SJason Jin 	pciInfo.slot.p.Device = (_BE_env.configAddress >> 11) & 0x1F;
466*ece92f85SJason Jin 	pciInfo.slot.p.Bus = (_BE_env.configAddress >> 16) & 0xFF;
467*ece92f85SJason Jin 	pciInfo.slot.p.Enable = 1;
468*ece92f85SJason Jin 
469*ece92f85SJason Jin 	/* Ignore accesses to all devices other than the one we're POSTing */
470*ece92f85SJason Jin 	if ((pciInfo.slot.p.Function ==
471*ece92f85SJason Jin 	     _BE_env.vgaInfo.pciInfo->slot.p.Function)
472*ece92f85SJason Jin 	    && (pciInfo.slot.p.Device == _BE_env.vgaInfo.pciInfo->slot.p.Device)
473*ece92f85SJason Jin 	    && (pciInfo.slot.p.Bus == _BE_env.vgaInfo.pciInfo->slot.p.Bus))
474*ece92f85SJason Jin 		return PCI_accessReg((_BE_env.configAddress & 0xFF) + regOffset,
475*ece92f85SJason Jin 				     value, func, &pciInfo);
476*ece92f85SJason Jin 	return 0;
477*ece92f85SJason Jin #endif
478*ece92f85SJason Jin }
479*ece92f85SJason Jin 
480*ece92f85SJason Jin /****************************************************************************
481*ece92f85SJason Jin PARAMETERS:
482*ece92f85SJason Jin port    - Port to read from
483*ece92f85SJason Jin type    - Type of access to perform
484*ece92f85SJason Jin 
485*ece92f85SJason Jin REMARKS:
486*ece92f85SJason Jin Performs an emulated read from one of the PCI configuration space registers.
487*ece92f85SJason Jin We emulate this using our PCI_accessReg function which will access the PCI
488*ece92f85SJason Jin configuration space registers in a portable fashion.
489*ece92f85SJason Jin ****************************************************************************/
490*ece92f85SJason Jin static u32 PCI_inp(int port, int type)
491*ece92f85SJason Jin {
492*ece92f85SJason Jin 	switch (type) {
493*ece92f85SJason Jin 	case REG_READ_BYTE:
494*ece92f85SJason Jin 		if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
495*ece92f85SJason Jin 		    && port <= 0xCFF)
496*ece92f85SJason Jin 			return BE_accessReg(port - 0xCFC, 0, REG_READ_BYTE);
497*ece92f85SJason Jin 		break;
498*ece92f85SJason Jin 	case REG_READ_WORD:
499*ece92f85SJason Jin 		if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
500*ece92f85SJason Jin 		    && port <= 0xCFF)
501*ece92f85SJason Jin 			return BE_accessReg(port - 0xCFC, 0, REG_READ_WORD);
502*ece92f85SJason Jin 		break;
503*ece92f85SJason Jin 	case REG_READ_DWORD:
504*ece92f85SJason Jin 		if (port == 0xCF8)
505*ece92f85SJason Jin 			return _BE_env.configAddress;
506*ece92f85SJason Jin 		else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
507*ece92f85SJason Jin 			return BE_accessReg(0, 0, REG_READ_DWORD);
508*ece92f85SJason Jin 		break;
509*ece92f85SJason Jin 	}
510*ece92f85SJason Jin 	return 0;
511*ece92f85SJason Jin }
512*ece92f85SJason Jin 
513*ece92f85SJason Jin /****************************************************************************
514*ece92f85SJason Jin PARAMETERS:
515*ece92f85SJason Jin port    - Port to write to
516*ece92f85SJason Jin type    - Type of access to perform
517*ece92f85SJason Jin 
518*ece92f85SJason Jin REMARKS:
519*ece92f85SJason Jin Performs an emulated write to one of the PCI control registers.
520*ece92f85SJason Jin ****************************************************************************/
521*ece92f85SJason Jin static void PCI_outp(int port, u32 val, int type)
522*ece92f85SJason Jin {
523*ece92f85SJason Jin 	switch (type) {
524*ece92f85SJason Jin 	case REG_WRITE_BYTE:
525*ece92f85SJason Jin 		if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
526*ece92f85SJason Jin 		    && port <= 0xCFF)
527*ece92f85SJason Jin 			BE_accessReg(port - 0xCFC, val, REG_WRITE_BYTE);
528*ece92f85SJason Jin 		break;
529*ece92f85SJason Jin 	case REG_WRITE_WORD:
530*ece92f85SJason Jin 		if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
531*ece92f85SJason Jin 		    && port <= 0xCFF)
532*ece92f85SJason Jin 			BE_accessReg(port - 0xCFC, val, REG_WRITE_WORD);
533*ece92f85SJason Jin 		break;
534*ece92f85SJason Jin 	case REG_WRITE_DWORD:
535*ece92f85SJason Jin 		if (port == 0xCF8)
536*ece92f85SJason Jin 		{
537*ece92f85SJason Jin 			_BE_env.configAddress = val & 0x80FFFFFC;
538*ece92f85SJason Jin 		}
539*ece92f85SJason Jin 		else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
540*ece92f85SJason Jin 			BE_accessReg(0, val, REG_WRITE_DWORD);
541*ece92f85SJason Jin 		break;
542*ece92f85SJason Jin 	}
543*ece92f85SJason Jin }
544*ece92f85SJason Jin 
545*ece92f85SJason Jin #endif
546*ece92f85SJason Jin 
547*ece92f85SJason Jin /****************************************************************************
548*ece92f85SJason Jin PARAMETERS:
549*ece92f85SJason Jin port    - Port to write to
550*ece92f85SJason Jin 
551*ece92f85SJason Jin RETURNS:
552*ece92f85SJason Jin Value read from the I/O port
553*ece92f85SJason Jin 
554*ece92f85SJason Jin REMARKS:
555*ece92f85SJason Jin Performs an emulated 8-bit read from an I/O port. We handle special cases
556*ece92f85SJason Jin that we need to emulate in here, and fall through to reflecting the write
557*ece92f85SJason Jin through to the real hardware if we don't need to special case it.
558*ece92f85SJason Jin ****************************************************************************/
559*ece92f85SJason Jin u8 X86API BE_inb(X86EMU_pioAddr port)
560*ece92f85SJason Jin {
561*ece92f85SJason Jin 	u8 val = 0;
562*ece92f85SJason Jin 
563*ece92f85SJason Jin #if defined(DEBUG) || !defined(__i386__)
564*ece92f85SJason Jin 	if (IS_VGA_PORT(port)){
565*ece92f85SJason Jin 		/*seems reading port 0x3c3 return the high 16 bit of io port*/
566*ece92f85SJason Jin 		if(port == 0x3c3)
567*ece92f85SJason Jin 			val = LOG_inpb(port);
568*ece92f85SJason Jin 		else
569*ece92f85SJason Jin 			val = VGA_inpb(port);
570*ece92f85SJason Jin 	}
571*ece92f85SJason Jin 	else if (IS_TIMER_PORT(port))
572*ece92f85SJason Jin 		DB(printf("Can not interept TIMER port now!\n");)
573*ece92f85SJason Jin 	else if (IS_SPKR_PORT(port))
574*ece92f85SJason Jin 		DB(printf("Can not interept SPEAKER port now!\n");)
575*ece92f85SJason Jin 	else if (IS_CMOS_PORT(port))
576*ece92f85SJason Jin 		DB(printf("Can not interept CMOS port now!\n");)
577*ece92f85SJason Jin 	else if (IS_PCI_PORT(port))
578*ece92f85SJason Jin 		val = PCI_inp(port, REG_READ_BYTE);
579*ece92f85SJason Jin 	else if (port < 0x100) {
580*ece92f85SJason Jin 		DB(printf("WARN: INVALID inb.%04X -> %02X\n", (u16) port, val);)
581*ece92f85SJason Jin 		val = LOG_inpb(port);
582*ece92f85SJason Jin 	} else
583*ece92f85SJason Jin #endif
584*ece92f85SJason Jin 		val = LOG_inpb(port);
585*ece92f85SJason Jin 	return val;
586*ece92f85SJason Jin }
587*ece92f85SJason Jin 
588*ece92f85SJason Jin /****************************************************************************
589*ece92f85SJason Jin PARAMETERS:
590*ece92f85SJason Jin port    - Port to write to
591*ece92f85SJason Jin 
592*ece92f85SJason Jin RETURNS:
593*ece92f85SJason Jin Value read from the I/O port
594*ece92f85SJason Jin 
595*ece92f85SJason Jin REMARKS:
596*ece92f85SJason Jin Performs an emulated 16-bit read from an I/O port. We handle special cases
597*ece92f85SJason Jin that we need to emulate in here, and fall through to reflecting the write
598*ece92f85SJason Jin through to the real hardware if we don't need to special case it.
599*ece92f85SJason Jin ****************************************************************************/
600*ece92f85SJason Jin u16 X86API BE_inw(X86EMU_pioAddr port)
601*ece92f85SJason Jin {
602*ece92f85SJason Jin 	u16 val = 0;
603*ece92f85SJason Jin 
604*ece92f85SJason Jin #if defined(DEBUG) || !defined(__i386__)
605*ece92f85SJason Jin 	if (IS_PCI_PORT(port))
606*ece92f85SJason Jin 		val = PCI_inp(port, REG_READ_WORD);
607*ece92f85SJason Jin 	else if (port < 0x100) {
608*ece92f85SJason Jin 		DB(printf("WARN: Maybe INVALID inw.%04X -> %04X\n", (u16) port, val);)
609*ece92f85SJason Jin 		val = LOG_inpw(port);
610*ece92f85SJason Jin 	} else
611*ece92f85SJason Jin #endif
612*ece92f85SJason Jin 		val = LOG_inpw(port);
613*ece92f85SJason Jin 	return val;
614*ece92f85SJason Jin }
615*ece92f85SJason Jin 
616*ece92f85SJason Jin /****************************************************************************
617*ece92f85SJason Jin PARAMETERS:
618*ece92f85SJason Jin port    - Port to write to
619*ece92f85SJason Jin 
620*ece92f85SJason Jin RETURNS:
621*ece92f85SJason Jin Value read from the I/O port
622*ece92f85SJason Jin 
623*ece92f85SJason Jin REMARKS:
624*ece92f85SJason Jin Performs an emulated 32-bit read from an I/O port. We handle special cases
625*ece92f85SJason Jin that we need to emulate in here, and fall through to reflecting the write
626*ece92f85SJason Jin through to the real hardware if we don't need to special case it.
627*ece92f85SJason Jin ****************************************************************************/
628*ece92f85SJason Jin u32 X86API BE_inl(X86EMU_pioAddr port)
629*ece92f85SJason Jin {
630*ece92f85SJason Jin 	u32 val = 0;
631*ece92f85SJason Jin 
632*ece92f85SJason Jin #if defined(DEBUG) || !defined(__i386__)
633*ece92f85SJason Jin 	if (IS_PCI_PORT(port))
634*ece92f85SJason Jin 		val = PCI_inp(port, REG_READ_DWORD);
635*ece92f85SJason Jin 	else if (port < 0x100) {
636*ece92f85SJason Jin 		val = LOG_inpd(port);
637*ece92f85SJason Jin 	} else
638*ece92f85SJason Jin #endif
639*ece92f85SJason Jin 		val = LOG_inpd(port);
640*ece92f85SJason Jin 	return val;
641*ece92f85SJason Jin }
642*ece92f85SJason Jin 
643*ece92f85SJason Jin /****************************************************************************
644*ece92f85SJason Jin PARAMETERS:
645*ece92f85SJason Jin port    - Port to write to
646*ece92f85SJason Jin val     - Value to write to port
647*ece92f85SJason Jin 
648*ece92f85SJason Jin REMARKS:
649*ece92f85SJason Jin Performs an emulated 8-bit write to an I/O port. We handle special cases
650*ece92f85SJason Jin that we need to emulate in here, and fall through to reflecting the write
651*ece92f85SJason Jin through to the real hardware if we don't need to special case it.
652*ece92f85SJason Jin ****************************************************************************/
653*ece92f85SJason Jin void X86API BE_outb(X86EMU_pioAddr port, u8 val)
654*ece92f85SJason Jin {
655*ece92f85SJason Jin #if defined(DEBUG) || !defined(__i386__)
656*ece92f85SJason Jin 	if (IS_VGA_PORT(port))
657*ece92f85SJason Jin 		VGA_outpb(port, val);
658*ece92f85SJason Jin 	else if (IS_TIMER_PORT(port))
659*ece92f85SJason Jin 		DB(printf("Can not interept TIMER port now!\n");)
660*ece92f85SJason Jin 	else if (IS_SPKR_PORT(port))
661*ece92f85SJason Jin 		DB(printf("Can not interept SPEAKER port now!\n");)
662*ece92f85SJason Jin 	else if (IS_CMOS_PORT(port))
663*ece92f85SJason Jin 		DB(printf("Can not interept CMOS port now!\n");)
664*ece92f85SJason Jin 	else if (IS_PCI_PORT(port))
665*ece92f85SJason Jin 		PCI_outp(port, val, REG_WRITE_BYTE);
666*ece92f85SJason Jin 	else if (port < 0x100) {
667*ece92f85SJason Jin 		DB(printf("WARN:Maybe INVALID outb.%04X <- %02X\n", (u16) port, val);)
668*ece92f85SJason Jin 		LOG_outpb(port, val);
669*ece92f85SJason Jin 	} else
670*ece92f85SJason Jin #endif
671*ece92f85SJason Jin 		LOG_outpb(port, val);
672*ece92f85SJason Jin }
673*ece92f85SJason Jin 
674*ece92f85SJason Jin /****************************************************************************
675*ece92f85SJason Jin PARAMETERS:
676*ece92f85SJason Jin port    - Port to write to
677*ece92f85SJason Jin val     - Value to write to port
678*ece92f85SJason Jin 
679*ece92f85SJason Jin REMARKS:
680*ece92f85SJason Jin Performs an emulated 16-bit write to an I/O port. We handle special cases
681*ece92f85SJason Jin that we need to emulate in here, and fall through to reflecting the write
682*ece92f85SJason Jin through to the real hardware if we don't need to special case it.
683*ece92f85SJason Jin ****************************************************************************/
684*ece92f85SJason Jin void X86API BE_outw(X86EMU_pioAddr port, u16 val)
685*ece92f85SJason Jin {
686*ece92f85SJason Jin #if defined(DEBUG) || !defined(__i386__)
687*ece92f85SJason Jin 		if (IS_VGA_PORT(port)) {
688*ece92f85SJason Jin 			VGA_outpb(port, val);
689*ece92f85SJason Jin 			VGA_outpb(port + 1, val >> 8);
690*ece92f85SJason Jin 		} else if (IS_PCI_PORT(port))
691*ece92f85SJason Jin 			PCI_outp(port, val, REG_WRITE_WORD);
692*ece92f85SJason Jin 		else if (port < 0x100) {
693*ece92f85SJason Jin 			DB(printf("WARN: MAybe INVALID outw.%04X <- %04X\n", (u16) port,
694*ece92f85SJason Jin 			       val);)
695*ece92f85SJason Jin 			LOG_outpw(port, val);
696*ece92f85SJason Jin 		} else
697*ece92f85SJason Jin #endif
698*ece92f85SJason Jin 			LOG_outpw(port, val);
699*ece92f85SJason Jin }
700*ece92f85SJason Jin 
701*ece92f85SJason Jin /****************************************************************************
702*ece92f85SJason Jin PARAMETERS:
703*ece92f85SJason Jin port    - Port to write to
704*ece92f85SJason Jin val     - Value to write to port
705*ece92f85SJason Jin 
706*ece92f85SJason Jin REMARKS:
707*ece92f85SJason Jin Performs an emulated 32-bit write to an I/O port. We handle special cases
708*ece92f85SJason Jin that we need to emulate in here, and fall through to reflecting the write
709*ece92f85SJason Jin through to the real hardware if we don't need to special case it.
710*ece92f85SJason Jin ****************************************************************************/
711*ece92f85SJason Jin void X86API BE_outl(X86EMU_pioAddr port, u32 val)
712*ece92f85SJason Jin {
713*ece92f85SJason Jin #if defined(DEBUG) || !defined(__i386__)
714*ece92f85SJason Jin 	if (IS_PCI_PORT(port))
715*ece92f85SJason Jin 		PCI_outp(port, val, REG_WRITE_DWORD);
716*ece92f85SJason Jin 	else if (port < 0x100) {
717*ece92f85SJason Jin 		DB(printf("WARN: INVALID outl.%04X <- %08X\n", (u16) port,val);)
718*ece92f85SJason Jin 		LOG_outpd(port, val);
719*ece92f85SJason Jin 	} else
720*ece92f85SJason Jin #endif
721*ece92f85SJason Jin 		LOG_outpd(port, val);
722*ece92f85SJason Jin }
723