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