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