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