| /**************************************************************************** |
| * |
| * BIOS emulator and interface |
| * to Realmode X86 Emulator Library |
| * |
| * ======================================================================== |
| * |
| * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. |
| * Jason Jin<Jason.jin@freescale.com> |
| * |
| * Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. |
| * |
| * This file may be distributed and/or modified under the terms of the |
| * GNU General Public License version 2.0 as published by the Free |
| * Software Foundation and appearing in the file LICENSE.GPL included |
| * in the packaging of this file. |
| * |
| * Licensees holding a valid Commercial License for this product from |
| * SciTech Software, Inc. may use this file in accordance with the |
| * Commercial License Agreement provided with the Software. |
| * |
| * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING |
| * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE. |
| * |
| * See http://www.scitechsoft.com/license/ for information about |
| * the licensing options available and how to purchase a Commercial |
| * License Agreement. |
| * |
| * Contact license@scitechsoft.com if any conditions of this licensing |
| * are not clear to you, or you have questions about licensing options. |
| * |
| * ======================================================================== |
| * |
| * Language: ANSI C |
| * Environment: Any |
| * Developer: Kendall Bennett |
| * |
| * Description: This file includes BIOS emulator I/O and memory access |
| * functions. |
| * |
| * Jason ported this file to u-boot to run the ATI video card |
| * BIOS in u-boot. Removed some emulate functions such as the |
| * timer port access. Made all the VGA port except reading 0x3c3 |
| * be emulated. Seems like reading 0x3c3 should return the high |
| * 16 bit of the io port. |
| * |
| ****************************************************************************/ |
| |
| #include <common.h> |
| |
| #if defined(CONFIG_BIOSEMU) |
| |
| #include "biosemui.h" |
| |
| /*------------------------- Global Variables ------------------------------*/ |
| |
| #ifndef __i386__ |
| static char *BE_biosDate = "08/14/99"; |
| static u8 BE_model = 0xFC; |
| static u8 BE_submodel = 0x00; |
| #endif |
| |
| /*----------------------------- Implementation ----------------------------*/ |
| |
| /**************************************************************************** |
| PARAMETERS: |
| addr - Emulator memory address to convert |
| |
| RETURNS: |
| Actual memory address to read or write the data |
| |
| REMARKS: |
| This function converts an emulator memory address in a 32-bit range to |
| a real memory address that we wish to access. It handles splitting up the |
| memory address space appropriately to access the emulator BIOS image, video |
| memory and system BIOS etc. |
| ****************************************************************************/ |
| static u8 *BE_memaddr(u32 addr) |
| { |
| if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) { |
| return (u8*)(_BE_env.biosmem_base + addr - 0xC0000); |
| } else if (addr > _BE_env.biosmem_limit && addr < 0xD0000) { |
| DB(printf("BE_memaddr: address %#lx may be invalid!\n", addr);) |
| return M.mem_base; |
| } else if (addr >= 0xA0000 && addr <= 0xBFFFF) { |
| return (u8*)(_BE_env.busmem_base + addr - 0xA0000); |
| } |
| #ifdef __i386__ |
| else if (addr >= 0xD0000 && addr <= 0xFFFFF) { |
| /* We map the real System BIOS directly on real PC's */ |
| DB(printf("BE_memaddr: System BIOS address %#lx\n", addr);) |
| return _BE_env.busmem_base + addr - 0xA0000; |
| } |
| #else |
| else if (addr >= 0xFFFF5 && addr < 0xFFFFE) { |
| /* Return a faked BIOS date string for non-x86 machines */ |
| DB(printf("BE_memaddr - Returning BIOS date\n");) |
| return (u8 *)(BE_biosDate + addr - 0xFFFF5); |
| } else if (addr == 0xFFFFE) { |
| /* Return system model identifier for non-x86 machines */ |
| DB(printf("BE_memaddr - Returning model\n");) |
| return &BE_model; |
| } else if (addr == 0xFFFFF) { |
| /* Return system submodel identifier for non-x86 machines */ |
| DB(printf("BE_memaddr - Returning submodel\n");) |
| return &BE_submodel; |
| } |
| #endif |
| else if (addr > M.mem_size - 1) { |
| HALT_SYS(); |
| return M.mem_base; |
| } |
| |
| return M.mem_base + addr; |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| addr - Emulator memory address to read |
| |
| RETURNS: |
| Byte value read from emulator memory. |
| |
| REMARKS: |
| Reads a byte value from the emulator memory. We have three distinct memory |
| regions that are handled differently, which this function handles. |
| ****************************************************************************/ |
| u8 X86API BE_rdb(u32 addr) |
| { |
| if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF) |
| return 0; |
| else { |
| u8 val = readb_le(BE_memaddr(addr)); |
| return val; |
| } |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| addr - Emulator memory address to read |
| |
| RETURNS: |
| Word value read from emulator memory. |
| |
| REMARKS: |
| Reads a word value from the emulator memory. We have three distinct memory |
| regions that are handled differently, which this function handles. |
| ****************************************************************************/ |
| u16 X86API BE_rdw(u32 addr) |
| { |
| if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF) |
| return 0; |
| else { |
| u8 *base = BE_memaddr(addr); |
| u16 val = readw_le(base); |
| return val; |
| } |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| addr - Emulator memory address to read |
| |
| RETURNS: |
| Long value read from emulator memory. |
| |
| REMARKS: |
| Reads a 32-bit value from the emulator memory. We have three distinct memory |
| regions that are handled differently, which this function handles. |
| ****************************************************************************/ |
| u32 X86API BE_rdl(u32 addr) |
| { |
| if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF) |
| return 0; |
| else { |
| u8 *base = BE_memaddr(addr); |
| u32 val = readl_le(base); |
| return val; |
| } |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| addr - Emulator memory address to read |
| val - Value to store |
| |
| REMARKS: |
| Writes a byte value to emulator memory. We have three distinct memory |
| regions that are handled differently, which this function handles. |
| ****************************************************************************/ |
| void X86API BE_wrb(u32 addr, u8 val) |
| { |
| if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) { |
| writeb_le(BE_memaddr(addr), val); |
| } |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| addr - Emulator memory address to read |
| val - Value to store |
| |
| REMARKS: |
| Writes a word value to emulator memory. We have three distinct memory |
| regions that are handled differently, which this function handles. |
| ****************************************************************************/ |
| void X86API BE_wrw(u32 addr, u16 val) |
| { |
| if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) { |
| u8 *base = BE_memaddr(addr); |
| writew_le(base, val); |
| |
| } |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| addr - Emulator memory address to read |
| val - Value to store |
| |
| REMARKS: |
| Writes a 32-bit value to emulator memory. We have three distinct memory |
| regions that are handled differently, which this function handles. |
| ****************************************************************************/ |
| void X86API BE_wrl(u32 addr, u32 val) |
| { |
| if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) { |
| u8 *base = BE_memaddr(addr); |
| writel_le(base, val); |
| } |
| } |
| |
| #if defined(DEBUG) || !defined(__i386__) |
| |
| /* For Non-Intel machines we may need to emulate some I/O port accesses that |
| * the BIOS may try to access, such as the PCI config registers. |
| */ |
| |
| #define IS_TIMER_PORT(port) (0x40 <= port && port <= 0x43) |
| #define IS_CMOS_PORT(port) (0x70 <= port && port <= 0x71) |
| /*#define IS_VGA_PORT(port) (_BE_env.emulateVGA && 0x3C0 <= port && port <= 0x3DA)*/ |
| #define IS_VGA_PORT(port) (0x3C0 <= port && port <= 0x3DA) |
| #define IS_PCI_PORT(port) (0xCF8 <= port && port <= 0xCFF) |
| #define IS_SPKR_PORT(port) (port == 0x61) |
| |
| /**************************************************************************** |
| PARAMETERS: |
| port - Port to read from |
| type - Type of access to perform |
| |
| REMARKS: |
| Performs an emulated read from the Standard VGA I/O ports. If the target |
| hardware does not support mapping the VGA I/O and memory (such as some |
| PowerPC systems), we emulate the VGA so that the BIOS will still be able to |
| set NonVGA display modes such as on ATI hardware. |
| ****************************************************************************/ |
| static u8 VGA_inpb (const int port) |
| { |
| u8 val = 0xff; |
| |
| switch (port) { |
| case 0x3C0: |
| /* 3C0 has funky characteristics because it can act as either |
| a data register or index register depending on the state |
| of an internal flip flop in the hardware. Hence we have |
| to emulate that functionality in here. */ |
| if (_BE_env.flipFlop3C0 == 0) { |
| /* Access 3C0 as index register */ |
| val = _BE_env.emu3C0; |
| } else { |
| /* Access 3C0 as data register */ |
| if (_BE_env.emu3C0 < ATT_C) |
| val = _BE_env.emu3C1[_BE_env.emu3C0]; |
| } |
| _BE_env.flipFlop3C0 ^= 1; |
| break; |
| case 0x3C1: |
| if (_BE_env.emu3C0 < ATT_C) |
| return _BE_env.emu3C1[_BE_env.emu3C0]; |
| break; |
| case 0x3CC: |
| return _BE_env.emu3C2; |
| case 0x3C4: |
| return _BE_env.emu3C4; |
| case 0x3C5: |
| if (_BE_env.emu3C4 < ATT_C) |
| return _BE_env.emu3C5[_BE_env.emu3C4]; |
| break; |
| case 0x3C6: |
| return _BE_env.emu3C6; |
| case 0x3C7: |
| return _BE_env.emu3C7; |
| case 0x3C8: |
| return _BE_env.emu3C8; |
| case 0x3C9: |
| if (_BE_env.emu3C7 < PAL_C) |
| return _BE_env.emu3C9[_BE_env.emu3C7++]; |
| break; |
| case 0x3CE: |
| return _BE_env.emu3CE; |
| case 0x3CF: |
| if (_BE_env.emu3CE < GRA_C) |
| return _BE_env.emu3CF[_BE_env.emu3CE]; |
| break; |
| case 0x3D4: |
| if (_BE_env.emu3C2 & 0x1) |
| return _BE_env.emu3D4; |
| break; |
| case 0x3D5: |
| if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C)) |
| return _BE_env.emu3D5[_BE_env.emu3D4]; |
| break; |
| case 0x3DA: |
| _BE_env.flipFlop3C0 = 0; |
| val = _BE_env.emu3DA; |
| _BE_env.emu3DA ^= 0x9; |
| break; |
| } |
| return val; |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| port - Port to write to |
| type - Type of access to perform |
| |
| REMARKS: |
| Performs an emulated write to one of the 8253 timer registers. For now |
| we only emulate timer 0 which is the only timer that the BIOS code appears |
| to use. |
| ****************************************************************************/ |
| static void VGA_outpb (int port, u8 val) |
| { |
| switch (port) { |
| case 0x3C0: |
| /* 3C0 has funky characteristics because it can act as either |
| a data register or index register depending on the state |
| of an internal flip flop in the hardware. Hence we have |
| to emulate that functionality in here. */ |
| if (_BE_env.flipFlop3C0 == 0) { |
| /* Access 3C0 as index register */ |
| _BE_env.emu3C0 = val; |
| } else { |
| /* Access 3C0 as data register */ |
| if (_BE_env.emu3C0 < ATT_C) |
| _BE_env.emu3C1[_BE_env.emu3C0] = val; |
| } |
| _BE_env.flipFlop3C0 ^= 1; |
| break; |
| case 0x3C2: |
| _BE_env.emu3C2 = val; |
| break; |
| case 0x3C4: |
| _BE_env.emu3C4 = val; |
| break; |
| case 0x3C5: |
| if (_BE_env.emu3C4 < ATT_C) |
| _BE_env.emu3C5[_BE_env.emu3C4] = val; |
| break; |
| case 0x3C6: |
| _BE_env.emu3C6 = val; |
| break; |
| case 0x3C7: |
| _BE_env.emu3C7 = (int) val *3; |
| |
| break; |
| case 0x3C8: |
| _BE_env.emu3C8 = (int) val *3; |
| |
| break; |
| case 0x3C9: |
| if (_BE_env.emu3C8 < PAL_C) |
| _BE_env.emu3C9[_BE_env.emu3C8++] = val; |
| break; |
| case 0x3CE: |
| _BE_env.emu3CE = val; |
| break; |
| case 0x3CF: |
| if (_BE_env.emu3CE < GRA_C) |
| _BE_env.emu3CF[_BE_env.emu3CE] = val; |
| break; |
| case 0x3D4: |
| if (_BE_env.emu3C2 & 0x1) |
| _BE_env.emu3D4 = val; |
| break; |
| case 0x3D5: |
| if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C)) |
| _BE_env.emu3D5[_BE_env.emu3D4] = val; |
| break; |
| } |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| regOffset - Offset into register space for non-DWORD accesses |
| value - Value to write to register for PCI_WRITE_* operations |
| func - Function to perform (PCIAccessRegFlags) |
| |
| RETURNS: |
| Value read from configuration register for PCI_READ_* operations |
| |
| REMARKS: |
| Accesses a PCI configuration space register by decoding the value currently |
| stored in the _BE_env.configAddress variable and passing it through to the |
| portable PCI_accessReg function. |
| ****************************************************************************/ |
| static u32 BE_accessReg(int regOffset, u32 value, int func) |
| { |
| #ifdef __KERNEL__ |
| int function, device, bus; |
| u8 val8; |
| u16 val16; |
| u32 val32; |
| |
| |
| /* Decode the configuration register values for the register we wish to |
| * access |
| */ |
| regOffset += (_BE_env.configAddress & 0xFF); |
| function = (_BE_env.configAddress >> 8) & 0x7; |
| device = (_BE_env.configAddress >> 11) & 0x1F; |
| bus = (_BE_env.configAddress >> 16) & 0xFF; |
| |
| /* Ignore accesses to all devices other than the one we're POSTing */ |
| if ((function == _BE_env.vgaInfo.function) && |
| (device == _BE_env.vgaInfo.device) && |
| (bus == _BE_env.vgaInfo.bus)) { |
| switch (func) { |
| case REG_READ_BYTE: |
| pci_read_config_byte(_BE_env.vgaInfo.pcidev, regOffset, |
| &val8); |
| return val8; |
| case REG_READ_WORD: |
| pci_read_config_word(_BE_env.vgaInfo.pcidev, regOffset, |
| &val16); |
| return val16; |
| case REG_READ_DWORD: |
| pci_read_config_dword(_BE_env.vgaInfo.pcidev, regOffset, |
| &val32); |
| return val32; |
| case REG_WRITE_BYTE: |
| pci_write_config_byte(_BE_env.vgaInfo.pcidev, regOffset, |
| value); |
| |
| return 0; |
| case REG_WRITE_WORD: |
| pci_write_config_word(_BE_env.vgaInfo.pcidev, regOffset, |
| value); |
| |
| return 0; |
| case REG_WRITE_DWORD: |
| pci_write_config_dword(_BE_env.vgaInfo.pcidev, |
| regOffset, value); |
| |
| return 0; |
| } |
| } |
| return 0; |
| #else |
| PCIDeviceInfo pciInfo; |
| |
| pciInfo.mech1 = 1; |
| pciInfo.slot.i = 0; |
| pciInfo.slot.p.Function = (_BE_env.configAddress >> 8) & 0x7; |
| pciInfo.slot.p.Device = (_BE_env.configAddress >> 11) & 0x1F; |
| pciInfo.slot.p.Bus = (_BE_env.configAddress >> 16) & 0xFF; |
| pciInfo.slot.p.Enable = 1; |
| |
| /* Ignore accesses to all devices other than the one we're POSTing */ |
| if ((pciInfo.slot.p.Function == |
| _BE_env.vgaInfo.pciInfo->slot.p.Function) |
| && (pciInfo.slot.p.Device == _BE_env.vgaInfo.pciInfo->slot.p.Device) |
| && (pciInfo.slot.p.Bus == _BE_env.vgaInfo.pciInfo->slot.p.Bus)) |
| return PCI_accessReg((_BE_env.configAddress & 0xFF) + regOffset, |
| value, func, &pciInfo); |
| return 0; |
| #endif |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| port - Port to read from |
| type - Type of access to perform |
| |
| REMARKS: |
| Performs an emulated read from one of the PCI configuration space registers. |
| We emulate this using our PCI_accessReg function which will access the PCI |
| configuration space registers in a portable fashion. |
| ****************************************************************************/ |
| static u32 PCI_inp(int port, int type) |
| { |
| switch (type) { |
| case REG_READ_BYTE: |
| if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port |
| && port <= 0xCFF) |
| return BE_accessReg(port - 0xCFC, 0, REG_READ_BYTE); |
| break; |
| case REG_READ_WORD: |
| if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port |
| && port <= 0xCFF) |
| return BE_accessReg(port - 0xCFC, 0, REG_READ_WORD); |
| break; |
| case REG_READ_DWORD: |
| if (port == 0xCF8) |
| return _BE_env.configAddress; |
| else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC) |
| return BE_accessReg(0, 0, REG_READ_DWORD); |
| break; |
| } |
| return 0; |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| port - Port to write to |
| type - Type of access to perform |
| |
| REMARKS: |
| Performs an emulated write to one of the PCI control registers. |
| ****************************************************************************/ |
| static void PCI_outp(int port, u32 val, int type) |
| { |
| switch (type) { |
| case REG_WRITE_BYTE: |
| if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port |
| && port <= 0xCFF) |
| BE_accessReg(port - 0xCFC, val, REG_WRITE_BYTE); |
| break; |
| case REG_WRITE_WORD: |
| if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port |
| && port <= 0xCFF) |
| BE_accessReg(port - 0xCFC, val, REG_WRITE_WORD); |
| break; |
| case REG_WRITE_DWORD: |
| if (port == 0xCF8) |
| { |
| _BE_env.configAddress = val & 0x80FFFFFC; |
| } |
| else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC) |
| BE_accessReg(0, val, REG_WRITE_DWORD); |
| break; |
| } |
| } |
| |
| #endif |
| |
| /**************************************************************************** |
| PARAMETERS: |
| port - Port to write to |
| |
| RETURNS: |
| Value read from the I/O port |
| |
| REMARKS: |
| Performs an emulated 8-bit read from an I/O port. We handle special cases |
| that we need to emulate in here, and fall through to reflecting the write |
| through to the real hardware if we don't need to special case it. |
| ****************************************************************************/ |
| u8 X86API BE_inb(X86EMU_pioAddr port) |
| { |
| u8 val = 0; |
| |
| #if defined(DEBUG) || !defined(__i386__) |
| if (IS_VGA_PORT(port)){ |
| /*seems reading port 0x3c3 return the high 16 bit of io port*/ |
| if(port == 0x3c3) |
| val = LOG_inpb(port); |
| else |
| val = VGA_inpb(port); |
| } |
| else if (IS_TIMER_PORT(port)) |
| DB(printf("Can not interept TIMER port now!\n");) |
| else if (IS_SPKR_PORT(port)) |
| DB(printf("Can not interept SPEAKER port now!\n");) |
| else if (IS_CMOS_PORT(port)) |
| DB(printf("Can not interept CMOS port now!\n");) |
| else if (IS_PCI_PORT(port)) |
| val = PCI_inp(port, REG_READ_BYTE); |
| else if (port < 0x100) { |
| DB(printf("WARN: INVALID inb.%04X -> %02X\n", (u16) port, val);) |
| val = LOG_inpb(port); |
| } else |
| #endif |
| val = LOG_inpb(port); |
| return val; |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| port - Port to write to |
| |
| RETURNS: |
| Value read from the I/O port |
| |
| REMARKS: |
| Performs an emulated 16-bit read from an I/O port. We handle special cases |
| that we need to emulate in here, and fall through to reflecting the write |
| through to the real hardware if we don't need to special case it. |
| ****************************************************************************/ |
| u16 X86API BE_inw(X86EMU_pioAddr port) |
| { |
| u16 val = 0; |
| |
| #if defined(DEBUG) || !defined(__i386__) |
| if (IS_PCI_PORT(port)) |
| val = PCI_inp(port, REG_READ_WORD); |
| else if (port < 0x100) { |
| DB(printf("WARN: Maybe INVALID inw.%04X -> %04X\n", (u16) port, val);) |
| val = LOG_inpw(port); |
| } else |
| #endif |
| val = LOG_inpw(port); |
| return val; |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| port - Port to write to |
| |
| RETURNS: |
| Value read from the I/O port |
| |
| REMARKS: |
| Performs an emulated 32-bit read from an I/O port. We handle special cases |
| that we need to emulate in here, and fall through to reflecting the write |
| through to the real hardware if we don't need to special case it. |
| ****************************************************************************/ |
| u32 X86API BE_inl(X86EMU_pioAddr port) |
| { |
| u32 val = 0; |
| |
| #if defined(DEBUG) || !defined(__i386__) |
| if (IS_PCI_PORT(port)) |
| val = PCI_inp(port, REG_READ_DWORD); |
| else if (port < 0x100) { |
| val = LOG_inpd(port); |
| } else |
| #endif |
| val = LOG_inpd(port); |
| return val; |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| port - Port to write to |
| val - Value to write to port |
| |
| REMARKS: |
| Performs an emulated 8-bit write to an I/O port. We handle special cases |
| that we need to emulate in here, and fall through to reflecting the write |
| through to the real hardware if we don't need to special case it. |
| ****************************************************************************/ |
| void X86API BE_outb(X86EMU_pioAddr port, u8 val) |
| { |
| #if defined(DEBUG) || !defined(__i386__) |
| if (IS_VGA_PORT(port)) |
| VGA_outpb(port, val); |
| else if (IS_TIMER_PORT(port)) |
| DB(printf("Can not interept TIMER port now!\n");) |
| else if (IS_SPKR_PORT(port)) |
| DB(printf("Can not interept SPEAKER port now!\n");) |
| else if (IS_CMOS_PORT(port)) |
| DB(printf("Can not interept CMOS port now!\n");) |
| else if (IS_PCI_PORT(port)) |
| PCI_outp(port, val, REG_WRITE_BYTE); |
| else if (port < 0x100) { |
| DB(printf("WARN:Maybe INVALID outb.%04X <- %02X\n", (u16) port, val);) |
| LOG_outpb(port, val); |
| } else |
| #endif |
| LOG_outpb(port, val); |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| port - Port to write to |
| val - Value to write to port |
| |
| REMARKS: |
| Performs an emulated 16-bit write to an I/O port. We handle special cases |
| that we need to emulate in here, and fall through to reflecting the write |
| through to the real hardware if we don't need to special case it. |
| ****************************************************************************/ |
| void X86API BE_outw(X86EMU_pioAddr port, u16 val) |
| { |
| #if defined(DEBUG) || !defined(__i386__) |
| if (IS_VGA_PORT(port)) { |
| VGA_outpb(port, val); |
| VGA_outpb(port + 1, val >> 8); |
| } else if (IS_PCI_PORT(port)) |
| PCI_outp(port, val, REG_WRITE_WORD); |
| else if (port < 0x100) { |
| DB(printf("WARN: MAybe INVALID outw.%04X <- %04X\n", (u16) port, |
| val);) |
| LOG_outpw(port, val); |
| } else |
| #endif |
| LOG_outpw(port, val); |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| port - Port to write to |
| val - Value to write to port |
| |
| REMARKS: |
| Performs an emulated 32-bit write to an I/O port. We handle special cases |
| that we need to emulate in here, and fall through to reflecting the write |
| through to the real hardware if we don't need to special case it. |
| ****************************************************************************/ |
| void X86API BE_outl(X86EMU_pioAddr port, u32 val) |
| { |
| #if defined(DEBUG) || !defined(__i386__) |
| if (IS_PCI_PORT(port)) |
| PCI_outp(port, val, REG_WRITE_DWORD); |
| else if (port < 0x100) { |
| DB(printf("WARN: INVALID outl.%04X <- %08X\n", (u16) port,val);) |
| LOG_outpd(port, val); |
| } else |
| #endif |
| LOG_outpd(port, val); |
| } |
| #endif |