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