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