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