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