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