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