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