blob: 2a8e1a01c1fc948be61fd86f749764e332f748dc [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****************************************************************************/
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200254static u8 VGA_inpb (const int port)
Jason Jinece92f82007-07-06 08:34:56 +0800255{
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200256 u8 val = 0xff;
Jason Jinece92f82007-07-06 08:34:56 +0800257
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200258 switch (port) {
259 case 0x3C0:
260 /* 3C0 has funky characteristics because it can act as either
261 a data register or index register depending on the state
262 of an internal flip flop in the hardware. Hence we have
263 to emulate that functionality in here. */
264 if (_BE_env.flipFlop3C0 == 0) {
265 /* Access 3C0 as index register */
266 val = _BE_env.emu3C0;
267 } else {
268 /* Access 3C0 as data register */
269 if (_BE_env.emu3C0 < ATT_C)
270 val = _BE_env.emu3C1[_BE_env.emu3C0];
271 }
272 _BE_env.flipFlop3C0 ^= 1;
273 break;
274 case 0x3C1:
275 if (_BE_env.emu3C0 < ATT_C)
276 return _BE_env.emu3C1[_BE_env.emu3C0];
277 break;
278 case 0x3CC:
279 return _BE_env.emu3C2;
280 case 0x3C4:
281 return _BE_env.emu3C4;
282 case 0x3C5:
283 if (_BE_env.emu3C4 < ATT_C)
284 return _BE_env.emu3C5[_BE_env.emu3C4];
285 break;
286 case 0x3C6:
287 return _BE_env.emu3C6;
288 case 0x3C7:
289 return _BE_env.emu3C7;
290 case 0x3C8:
291 return _BE_env.emu3C8;
292 case 0x3C9:
293 if (_BE_env.emu3C7 < PAL_C)
294 return _BE_env.emu3C9[_BE_env.emu3C7++];
295 break;
296 case 0x3CE:
297 return _BE_env.emu3CE;
298 case 0x3CF:
299 if (_BE_env.emu3CE < GRA_C)
300 return _BE_env.emu3CF[_BE_env.emu3CE];
301 break;
302 case 0x3D4:
303 if (_BE_env.emu3C2 & 0x1)
304 return _BE_env.emu3D4;
305 break;
306 case 0x3D5:
307 if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C))
308 return _BE_env.emu3D5[_BE_env.emu3D4];
309 break;
310 case 0x3DA:
311 _BE_env.flipFlop3C0 = 0;
312 val = _BE_env.emu3DA;
313 _BE_env.emu3DA ^= 0x9;
314 break;
315 }
316 return val;
Jason Jinece92f82007-07-06 08:34:56 +0800317}
318
319/****************************************************************************
320PARAMETERS:
321port - Port to write to
322type - Type of access to perform
323
324REMARKS:
325Performs an emulated write to one of the 8253 timer registers. For now
326we only emulate timer 0 which is the only timer that the BIOS code appears
327to use.
328****************************************************************************/
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200329static void VGA_outpb (int port, u8 val)
Jason Jinece92f82007-07-06 08:34:56 +0800330{
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200331 switch (port) {
332 case 0x3C0:
333 /* 3C0 has funky characteristics because it can act as either
334 a data register or index register depending on the state
335 of an internal flip flop in the hardware. Hence we have
336 to emulate that functionality in here. */
337 if (_BE_env.flipFlop3C0 == 0) {
338 /* Access 3C0 as index register */
339 _BE_env.emu3C0 = val;
340 } else {
341 /* Access 3C0 as data register */
342 if (_BE_env.emu3C0 < ATT_C)
343 _BE_env.emu3C1[_BE_env.emu3C0] = val;
344 }
345 _BE_env.flipFlop3C0 ^= 1;
346 break;
347 case 0x3C2:
348 _BE_env.emu3C2 = val;
349 break;
350 case 0x3C4:
351 _BE_env.emu3C4 = val;
352 break;
353 case 0x3C5:
354 if (_BE_env.emu3C4 < ATT_C)
355 _BE_env.emu3C5[_BE_env.emu3C4] = val;
356 break;
357 case 0x3C6:
358 _BE_env.emu3C6 = val;
359 break;
360 case 0x3C7:
361 _BE_env.emu3C7 = (int) val *3;
362
363 break;
364 case 0x3C8:
365 _BE_env.emu3C8 = (int) val *3;
366
367 break;
368 case 0x3C9:
369 if (_BE_env.emu3C8 < PAL_C)
370 _BE_env.emu3C9[_BE_env.emu3C8++] = val;
371 break;
372 case 0x3CE:
373 _BE_env.emu3CE = val;
374 break;
375 case 0x3CF:
376 if (_BE_env.emu3CE < GRA_C)
377 _BE_env.emu3CF[_BE_env.emu3CE] = val;
378 break;
379 case 0x3D4:
380 if (_BE_env.emu3C2 & 0x1)
381 _BE_env.emu3D4 = val;
382 break;
383 case 0x3D5:
384 if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C))
385 _BE_env.emu3D5[_BE_env.emu3D4] = val;
386 break;
387 }
Jason Jinece92f82007-07-06 08:34:56 +0800388}
389
390/****************************************************************************
391PARAMETERS:
392regOffset - Offset into register space for non-DWORD accesses
393value - Value to write to register for PCI_WRITE_* operations
394func - Function to perform (PCIAccessRegFlags)
395
396RETURNS:
397Value read from configuration register for PCI_READ_* operations
398
399REMARKS:
400Accesses a PCI configuration space register by decoding the value currently
401stored in the _BE_env.configAddress variable and passing it through to the
402portable PCI_accessReg function.
403****************************************************************************/
404static u32 BE_accessReg(int regOffset, u32 value, int func)
405{
406#ifdef __KERNEL__
407 int function, device, bus;
408 u8 val8;
409 u16 val16;
410 u32 val32;
411
412
413 /* Decode the configuration register values for the register we wish to
414 * access
415 */
416 regOffset += (_BE_env.configAddress & 0xFF);
417 function = (_BE_env.configAddress >> 8) & 0x7;
418 device = (_BE_env.configAddress >> 11) & 0x1F;
419 bus = (_BE_env.configAddress >> 16) & 0xFF;
420
421 /* Ignore accesses to all devices other than the one we're POSTing */
422 if ((function == _BE_env.vgaInfo.function) &&
423 (device == _BE_env.vgaInfo.device) &&
424 (bus == _BE_env.vgaInfo.bus)) {
425 switch (func) {
426 case REG_READ_BYTE:
427 pci_read_config_byte(_BE_env.vgaInfo.pcidev, regOffset,
428 &val8);
429 return val8;
430 case REG_READ_WORD:
431 pci_read_config_word(_BE_env.vgaInfo.pcidev, regOffset,
432 &val16);
433 return val16;
434 case REG_READ_DWORD:
435 pci_read_config_dword(_BE_env.vgaInfo.pcidev, regOffset,
436 &val32);
437 return val32;
438 case REG_WRITE_BYTE:
439 pci_write_config_byte(_BE_env.vgaInfo.pcidev, regOffset,
440 value);
441
442 return 0;
443 case REG_WRITE_WORD:
444 pci_write_config_word(_BE_env.vgaInfo.pcidev, regOffset,
445 value);
446
447 return 0;
448 case REG_WRITE_DWORD:
449 pci_write_config_dword(_BE_env.vgaInfo.pcidev,
450 regOffset, value);
451
452 return 0;
453 }
454 }
455 return 0;
456#else
457 PCIDeviceInfo pciInfo;
458
459 pciInfo.mech1 = 1;
460 pciInfo.slot.i = 0;
461 pciInfo.slot.p.Function = (_BE_env.configAddress >> 8) & 0x7;
462 pciInfo.slot.p.Device = (_BE_env.configAddress >> 11) & 0x1F;
463 pciInfo.slot.p.Bus = (_BE_env.configAddress >> 16) & 0xFF;
464 pciInfo.slot.p.Enable = 1;
465
466 /* Ignore accesses to all devices other than the one we're POSTing */
467 if ((pciInfo.slot.p.Function ==
468 _BE_env.vgaInfo.pciInfo->slot.p.Function)
469 && (pciInfo.slot.p.Device == _BE_env.vgaInfo.pciInfo->slot.p.Device)
470 && (pciInfo.slot.p.Bus == _BE_env.vgaInfo.pciInfo->slot.p.Bus))
471 return PCI_accessReg((_BE_env.configAddress & 0xFF) + regOffset,
472 value, func, &pciInfo);
473 return 0;
474#endif
475}
476
477/****************************************************************************
478PARAMETERS:
479port - Port to read from
480type - Type of access to perform
481
482REMARKS:
483Performs an emulated read from one of the PCI configuration space registers.
484We emulate this using our PCI_accessReg function which will access the PCI
485configuration space registers in a portable fashion.
486****************************************************************************/
487static u32 PCI_inp(int port, int type)
488{
489 switch (type) {
490 case REG_READ_BYTE:
491 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
492 && port <= 0xCFF)
493 return BE_accessReg(port - 0xCFC, 0, REG_READ_BYTE);
494 break;
495 case REG_READ_WORD:
496 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
497 && port <= 0xCFF)
498 return BE_accessReg(port - 0xCFC, 0, REG_READ_WORD);
499 break;
500 case REG_READ_DWORD:
501 if (port == 0xCF8)
502 return _BE_env.configAddress;
503 else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
504 return BE_accessReg(0, 0, REG_READ_DWORD);
505 break;
506 }
507 return 0;
508}
509
510/****************************************************************************
511PARAMETERS:
512port - Port to write to
513type - Type of access to perform
514
515REMARKS:
516Performs an emulated write to one of the PCI control registers.
517****************************************************************************/
518static void PCI_outp(int port, u32 val, int type)
519{
520 switch (type) {
521 case REG_WRITE_BYTE:
522 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
523 && port <= 0xCFF)
524 BE_accessReg(port - 0xCFC, val, REG_WRITE_BYTE);
525 break;
526 case REG_WRITE_WORD:
527 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
528 && port <= 0xCFF)
529 BE_accessReg(port - 0xCFC, val, REG_WRITE_WORD);
530 break;
531 case REG_WRITE_DWORD:
532 if (port == 0xCF8)
533 {
534 _BE_env.configAddress = val & 0x80FFFFFC;
535 }
536 else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
537 BE_accessReg(0, val, REG_WRITE_DWORD);
538 break;
539 }
540}
541
542#endif
543
544/****************************************************************************
545PARAMETERS:
546port - Port to write to
547
548RETURNS:
549Value read from the I/O port
550
551REMARKS:
552Performs an emulated 8-bit read from an I/O port. We handle special cases
553that we need to emulate in here, and fall through to reflecting the write
554through to the real hardware if we don't need to special case it.
555****************************************************************************/
556u8 X86API BE_inb(X86EMU_pioAddr port)
557{
558 u8 val = 0;
559
560#if defined(DEBUG) || !defined(__i386__)
561 if (IS_VGA_PORT(port)){
562 /*seems reading port 0x3c3 return the high 16 bit of io port*/
563 if(port == 0x3c3)
564 val = LOG_inpb(port);
565 else
566 val = VGA_inpb(port);
567 }
568 else if (IS_TIMER_PORT(port))
569 DB(printf("Can not interept TIMER port now!\n");)
570 else if (IS_SPKR_PORT(port))
571 DB(printf("Can not interept SPEAKER port now!\n");)
572 else if (IS_CMOS_PORT(port))
573 DB(printf("Can not interept CMOS port now!\n");)
574 else if (IS_PCI_PORT(port))
575 val = PCI_inp(port, REG_READ_BYTE);
576 else if (port < 0x100) {
577 DB(printf("WARN: INVALID inb.%04X -> %02X\n", (u16) port, val);)
578 val = LOG_inpb(port);
579 } else
580#endif
581 val = LOG_inpb(port);
582 return val;
583}
584
585/****************************************************************************
586PARAMETERS:
587port - Port to write to
588
589RETURNS:
590Value read from the I/O port
591
592REMARKS:
593Performs an emulated 16-bit read from an I/O port. We handle special cases
594that we need to emulate in here, and fall through to reflecting the write
595through to the real hardware if we don't need to special case it.
596****************************************************************************/
597u16 X86API BE_inw(X86EMU_pioAddr port)
598{
599 u16 val = 0;
600
601#if defined(DEBUG) || !defined(__i386__)
602 if (IS_PCI_PORT(port))
603 val = PCI_inp(port, REG_READ_WORD);
604 else if (port < 0x100) {
605 DB(printf("WARN: Maybe INVALID inw.%04X -> %04X\n", (u16) port, val);)
606 val = LOG_inpw(port);
607 } else
608#endif
609 val = LOG_inpw(port);
610 return val;
611}
612
613/****************************************************************************
614PARAMETERS:
615port - Port to write to
616
617RETURNS:
618Value read from the I/O port
619
620REMARKS:
621Performs an emulated 32-bit read from an I/O port. We handle special cases
622that we need to emulate in here, and fall through to reflecting the write
623through to the real hardware if we don't need to special case it.
624****************************************************************************/
625u32 X86API BE_inl(X86EMU_pioAddr port)
626{
627 u32 val = 0;
628
629#if defined(DEBUG) || !defined(__i386__)
630 if (IS_PCI_PORT(port))
631 val = PCI_inp(port, REG_READ_DWORD);
632 else if (port < 0x100) {
633 val = LOG_inpd(port);
634 } else
635#endif
636 val = LOG_inpd(port);
637 return val;
638}
639
640/****************************************************************************
641PARAMETERS:
642port - Port to write to
643val - Value to write to port
644
645REMARKS:
646Performs an emulated 8-bit write to an I/O port. We handle special cases
647that we need to emulate in here, and fall through to reflecting the write
648through to the real hardware if we don't need to special case it.
649****************************************************************************/
650void X86API BE_outb(X86EMU_pioAddr port, u8 val)
651{
652#if defined(DEBUG) || !defined(__i386__)
653 if (IS_VGA_PORT(port))
654 VGA_outpb(port, val);
655 else if (IS_TIMER_PORT(port))
656 DB(printf("Can not interept TIMER port now!\n");)
657 else if (IS_SPKR_PORT(port))
658 DB(printf("Can not interept SPEAKER port now!\n");)
659 else if (IS_CMOS_PORT(port))
660 DB(printf("Can not interept CMOS port now!\n");)
661 else if (IS_PCI_PORT(port))
662 PCI_outp(port, val, REG_WRITE_BYTE);
663 else if (port < 0x100) {
664 DB(printf("WARN:Maybe INVALID outb.%04X <- %02X\n", (u16) port, val);)
665 LOG_outpb(port, val);
666 } else
667#endif
668 LOG_outpb(port, val);
669}
670
671/****************************************************************************
672PARAMETERS:
673port - Port to write to
674val - Value to write to port
675
676REMARKS:
677Performs an emulated 16-bit write to an I/O port. We handle special cases
678that we need to emulate in here, and fall through to reflecting the write
679through to the real hardware if we don't need to special case it.
680****************************************************************************/
681void X86API BE_outw(X86EMU_pioAddr port, u16 val)
682{
683#if defined(DEBUG) || !defined(__i386__)
684 if (IS_VGA_PORT(port)) {
685 VGA_outpb(port, val);
686 VGA_outpb(port + 1, val >> 8);
687 } else if (IS_PCI_PORT(port))
688 PCI_outp(port, val, REG_WRITE_WORD);
689 else if (port < 0x100) {
690 DB(printf("WARN: MAybe INVALID outw.%04X <- %04X\n", (u16) port,
691 val);)
692 LOG_outpw(port, val);
693 } else
694#endif
695 LOG_outpw(port, val);
696}
697
698/****************************************************************************
699PARAMETERS:
700port - Port to write to
701val - Value to write to port
702
703REMARKS:
704Performs an emulated 32-bit write to an I/O port. We handle special cases
705that we need to emulate in here, and fall through to reflecting the write
706through to the real hardware if we don't need to special case it.
707****************************************************************************/
708void X86API BE_outl(X86EMU_pioAddr port, u32 val)
709{
710#if defined(DEBUG) || !defined(__i386__)
711 if (IS_PCI_PORT(port))
712 PCI_outp(port, val, REG_WRITE_DWORD);
713 else if (port < 0x100) {
714 DB(printf("WARN: INVALID outl.%04X <- %08X\n", (u16) port,val);)
715 LOG_outpd(port, val);
716 } else
717#endif
718 LOG_outpd(port, val);
719}