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