blob: 894012fa898acd0226b077bd47f4c1a0edf19152 [file] [log] [blame]
Jason Jinece92f82007-07-06 08:34:56 +08001/****************************************************************************
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__
55static char *BE_biosDate = "08/14/99";
56static u8 BE_model = 0xFC;
57static u8 BE_submodel = 0x00;
58#endif
59
60/*----------------------------- Implementation ----------------------------*/
61
62/****************************************************************************
63PARAMETERS:
64addr - Emulator memory address to convert
65
66RETURNS:
67Actual memory address to read or write the data
68
69REMARKS:
70This function converts an emulator memory address in a 32-bit range to
71a real memory address that we wish to access. It handles splitting up the
72memory address space appropriately to access the emulator BIOS image, video
73memory and system BIOS etc.
74****************************************************************************/
75static 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/****************************************************************************
115PARAMETERS:
116addr - Emulator memory address to read
117
118RETURNS:
119Byte value read from emulator memory.
120
121REMARKS:
122Reads a byte value from the emulator memory. We have three distinct memory
123regions that are handled differently, which this function handles.
124****************************************************************************/
125u8 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/****************************************************************************
136PARAMETERS:
137addr - Emulator memory address to read
138
139RETURNS:
140Word value read from emulator memory.
141
142REMARKS:
143Reads a word value from the emulator memory. We have three distinct memory
144regions that are handled differently, which this function handles.
145****************************************************************************/
146u16 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/****************************************************************************
158PARAMETERS:
159addr - Emulator memory address to read
160
161RETURNS:
162Long value read from emulator memory.
163
164REMARKS:
165Reads a 32-bit value from the emulator memory. We have three distinct memory
166regions that are handled differently, which this function handles.
167****************************************************************************/
168u32 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/****************************************************************************
180PARAMETERS:
181addr - Emulator memory address to read
182val - Value to store
183
184REMARKS:
185Writes a byte value to emulator memory. We have three distinct memory
186regions that are handled differently, which this function handles.
187****************************************************************************/
188void 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/****************************************************************************
196PARAMETERS:
197addr - Emulator memory address to read
198val - Value to store
199
200REMARKS:
201Writes a word value to emulator memory. We have three distinct memory
202regions that are handled differently, which this function handles.
203****************************************************************************/
204void 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/****************************************************************************
214PARAMETERS:
215addr - Emulator memory address to read
216val - Value to store
217
218REMARKS:
219Writes a 32-bit value to emulator memory. We have three distinct memory
220regions that are handled differently, which this function handles.
221****************************************************************************/
222void 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/****************************************************************************
244PARAMETERS:
245port - Port to read from
246type - Type of access to perform
247
248REMARKS:
249Performs an emulated read from the Standard VGA I/O ports. If the target
250hardware does not support mapping the VGA I/O and memory (such as some
251PowerPC systems), we emulate the VGA so that the BIOS will still be able to
252set NonVGA display modes such as on ATI hardware.
253****************************************************************************/
254static u8 VGA_inpb(
255 const int port)
256{
257 u8 val = 0xff;
258
259 switch (port) {
260 case 0x3C0:
261 /* 3C0 has funky characteristics because it can act as either
262 a data register or index register depending on the state
263 of an internal flip flop in the hardware. Hence we have
264 to emulate that functionality in here. */
265 if (_BE_env.flipFlop3C0 == 0) {
266 /* Access 3C0 as index register*/
267 val = _BE_env.emu3C0;
268 }
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/****************************************************************************
322PARAMETERS:
323port - Port to write to
324type - Type of access to perform
325
326REMARKS:
327Performs an emulated write to one of the 8253 timer registers. For now
328we only emulate timer 0 which is the only timer that the BIOS code appears
329to use.
330****************************************************************************/
331static void VGA_outpb(
332 int port,
333 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 }
345 else {
346 /* Access 3C0 as data register*/
347 if (_BE_env.emu3C0 < ATT_C)
348 _BE_env.emu3C1[_BE_env.emu3C0] = val;
349 }
350 _BE_env.flipFlop3C0 ^= 1;
351 break;
352 case 0x3C2:
353 _BE_env.emu3C2 = val;
354 break;
355 case 0x3C4:
356 _BE_env.emu3C4 = val;
357 break;
358 case 0x3C5:
359 if (_BE_env.emu3C4 < ATT_C)
360 _BE_env.emu3C5[_BE_env.emu3C4] = val;
361 break;
362 case 0x3C6:
363 _BE_env.emu3C6 = val;
364 break;
365 case 0x3C7:
366 _BE_env.emu3C7 = (int)val * 3;
367 break;
368 case 0x3C8:
369 _BE_env.emu3C8 = (int)val * 3;
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/****************************************************************************
394PARAMETERS:
395regOffset - Offset into register space for non-DWORD accesses
396value - Value to write to register for PCI_WRITE_* operations
397func - Function to perform (PCIAccessRegFlags)
398
399RETURNS:
400Value read from configuration register for PCI_READ_* operations
401
402REMARKS:
403Accesses a PCI configuration space register by decoding the value currently
404stored in the _BE_env.configAddress variable and passing it through to the
405portable PCI_accessReg function.
406****************************************************************************/
407static 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/****************************************************************************
481PARAMETERS:
482port - Port to read from
483type - Type of access to perform
484
485REMARKS:
486Performs an emulated read from one of the PCI configuration space registers.
487We emulate this using our PCI_accessReg function which will access the PCI
488configuration space registers in a portable fashion.
489****************************************************************************/
490static 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/****************************************************************************
514PARAMETERS:
515port - Port to write to
516type - Type of access to perform
517
518REMARKS:
519Performs an emulated write to one of the PCI control registers.
520****************************************************************************/
521static 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/****************************************************************************
548PARAMETERS:
549port - Port to write to
550
551RETURNS:
552Value read from the I/O port
553
554REMARKS:
555Performs an emulated 8-bit read from an I/O port. We handle special cases
556that we need to emulate in here, and fall through to reflecting the write
557through to the real hardware if we don't need to special case it.
558****************************************************************************/
559u8 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/****************************************************************************
589PARAMETERS:
590port - Port to write to
591
592RETURNS:
593Value read from the I/O port
594
595REMARKS:
596Performs an emulated 16-bit read from an I/O port. We handle special cases
597that we need to emulate in here, and fall through to reflecting the write
598through to the real hardware if we don't need to special case it.
599****************************************************************************/
600u16 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/****************************************************************************
617PARAMETERS:
618port - Port to write to
619
620RETURNS:
621Value read from the I/O port
622
623REMARKS:
624Performs an emulated 32-bit read from an I/O port. We handle special cases
625that we need to emulate in here, and fall through to reflecting the write
626through to the real hardware if we don't need to special case it.
627****************************************************************************/
628u32 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/****************************************************************************
644PARAMETERS:
645port - Port to write to
646val - Value to write to port
647
648REMARKS:
649Performs an emulated 8-bit write to an I/O port. We handle special cases
650that we need to emulate in here, and fall through to reflecting the write
651through to the real hardware if we don't need to special case it.
652****************************************************************************/
653void 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/****************************************************************************
675PARAMETERS:
676port - Port to write to
677val - Value to write to port
678
679REMARKS:
680Performs an emulated 16-bit write to an I/O port. We handle special cases
681that we need to emulate in here, and fall through to reflecting the write
682through to the real hardware if we don't need to special case it.
683****************************************************************************/
684void 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/****************************************************************************
702PARAMETERS:
703port - Port to write to
704val - Value to write to port
705
706REMARKS:
707Performs an emulated 32-bit write to an I/O port. We handle special cases
708that we need to emulate in here, and fall through to reflecting the write
709through to the real hardware if we don't need to special case it.
710****************************************************************************/
711void 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}