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