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