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 * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. 7*ece92f85SJason Jin * Jason Jin <Jason.jin@freescale.com> 8*ece92f85SJason Jin * 9*ece92f85SJason Jin * Copyright (C) 1996-1999 SciTech Software, Inc. 10*ece92f85SJason Jin * 11*ece92f85SJason Jin * ======================================================================== 12*ece92f85SJason Jin * 13*ece92f85SJason Jin * Permission to use, copy, modify, distribute, and sell this software and 14*ece92f85SJason Jin * its documentation for any purpose is hereby granted without fee, 15*ece92f85SJason Jin * provided that the above copyright notice appear in all copies and that 16*ece92f85SJason Jin * both that copyright notice and this permission notice appear in 17*ece92f85SJason Jin * supporting documentation, and that the name of the authors not be used 18*ece92f85SJason Jin * in advertising or publicity pertaining to distribution of the software 19*ece92f85SJason Jin * without specific, written prior permission. The authors makes no 20*ece92f85SJason Jin * representations about the suitability of this software for any purpose. 21*ece92f85SJason Jin * It is provided "as is" without express or implied warranty. 22*ece92f85SJason Jin * 23*ece92f85SJason Jin * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 24*ece92f85SJason Jin * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 25*ece92f85SJason Jin * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 26*ece92f85SJason Jin * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 27*ece92f85SJason Jin * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 28*ece92f85SJason Jin * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 29*ece92f85SJason Jin * PERFORMANCE OF THIS SOFTWARE. 30*ece92f85SJason Jin * 31*ece92f85SJason Jin * ======================================================================== 32*ece92f85SJason Jin * 33*ece92f85SJason Jin * Language: ANSI C 34*ece92f85SJason Jin * Environment: Any 35*ece92f85SJason Jin * Developer: Kendall Bennett 36*ece92f85SJason Jin * 37*ece92f85SJason Jin * Description: Module implementing the BIOS specific functions. 38*ece92f85SJason Jin * 39*ece92f85SJason Jin * Jason ported this file to u-boot to run the ATI video card 40*ece92f85SJason Jin * video BIOS. 41*ece92f85SJason Jin * 42*ece92f85SJason Jin ****************************************************************************/ 43*ece92f85SJason Jin 44*ece92f85SJason Jin #include "biosemui.h" 45*ece92f85SJason Jin 46*ece92f85SJason Jin /*----------------------------- Implementation ----------------------------*/ 47*ece92f85SJason Jin 48*ece92f85SJason Jin /**************************************************************************** 49*ece92f85SJason Jin PARAMETERS: 50*ece92f85SJason Jin intno - Interrupt number being serviced 51*ece92f85SJason Jin 52*ece92f85SJason Jin REMARKS: 53*ece92f85SJason Jin Handler for undefined interrupts. 54*ece92f85SJason Jin ****************************************************************************/ 55*ece92f85SJason Jin static void X86API undefined_intr(int intno) 56*ece92f85SJason Jin { 57*ece92f85SJason Jin if (BE_rdw(intno * 4 + 2) == BIOS_SEG) { 58*ece92f85SJason Jin DB(printf("biosEmu: undefined interrupt %xh called!\n", intno);) 59*ece92f85SJason Jin } else 60*ece92f85SJason Jin X86EMU_prepareForInt(intno); 61*ece92f85SJason Jin } 62*ece92f85SJason Jin 63*ece92f85SJason Jin /**************************************************************************** 64*ece92f85SJason Jin PARAMETERS: 65*ece92f85SJason Jin intno - Interrupt number being serviced 66*ece92f85SJason Jin 67*ece92f85SJason Jin REMARKS: 68*ece92f85SJason Jin This function handles the default system BIOS Int 10h (the default is stored 69*ece92f85SJason Jin in the Int 42h vector by the system BIOS at bootup). We only need to handle 70*ece92f85SJason Jin a small number of special functions used by the BIOS during POST time. 71*ece92f85SJason Jin ****************************************************************************/ 72*ece92f85SJason Jin static void X86API int42(int intno) 73*ece92f85SJason Jin { 74*ece92f85SJason Jin if (M.x86.R_AH == 0x12 && M.x86.R_BL == 0x32) { 75*ece92f85SJason Jin if (M.x86.R_AL == 0) { 76*ece92f85SJason Jin /* Enable CPU accesses to video memory */ 77*ece92f85SJason Jin PM_outpb(0x3c2, PM_inpb(0x3cc) | (u8) 0x02); 78*ece92f85SJason Jin return; 79*ece92f85SJason Jin } else if (M.x86.R_AL == 1) { 80*ece92f85SJason Jin /* Disable CPU accesses to video memory */ 81*ece92f85SJason Jin PM_outpb(0x3c2, PM_inpb(0x3cc) & (u8) ~ 0x02); 82*ece92f85SJason Jin return; 83*ece92f85SJason Jin } 84*ece92f85SJason Jin #ifdef DEBUG 85*ece92f85SJason Jin else { 86*ece92f85SJason Jin printf("int42: unknown function AH=0x12, BL=0x32, AL=%#02x\n", 87*ece92f85SJason Jin M.x86.R_AL); 88*ece92f85SJason Jin } 89*ece92f85SJason Jin #endif 90*ece92f85SJason Jin } 91*ece92f85SJason Jin #ifdef DEBUG 92*ece92f85SJason Jin else { 93*ece92f85SJason Jin printf("int42: unknown function AH=%#02x, AL=%#02x, BL=%#02x\n", 94*ece92f85SJason Jin M.x86.R_AH, M.x86.R_AL, M.x86.R_BL); 95*ece92f85SJason Jin } 96*ece92f85SJason Jin #endif 97*ece92f85SJason Jin } 98*ece92f85SJason Jin 99*ece92f85SJason Jin /**************************************************************************** 100*ece92f85SJason Jin PARAMETERS: 101*ece92f85SJason Jin intno - Interrupt number being serviced 102*ece92f85SJason Jin 103*ece92f85SJason Jin REMARKS: 104*ece92f85SJason Jin This function handles the default system BIOS Int 10h. If the POST code 105*ece92f85SJason Jin has not yet re-vectored the Int 10h BIOS interrupt vector, we handle this 106*ece92f85SJason Jin by simply calling the int42 interrupt handler above. Very early in the 107*ece92f85SJason Jin BIOS POST process, the vector gets replaced and we simply let the real 108*ece92f85SJason Jin mode interrupt handler process the interrupt. 109*ece92f85SJason Jin ****************************************************************************/ 110*ece92f85SJason Jin static void X86API int10(int intno) 111*ece92f85SJason Jin { 112*ece92f85SJason Jin if (BE_rdw(intno * 4 + 2) == BIOS_SEG) 113*ece92f85SJason Jin int42(intno); 114*ece92f85SJason Jin else 115*ece92f85SJason Jin X86EMU_prepareForInt(intno); 116*ece92f85SJason Jin } 117*ece92f85SJason Jin 118*ece92f85SJason Jin /* Result codes returned by the PCI BIOS */ 119*ece92f85SJason Jin 120*ece92f85SJason Jin #define SUCCESSFUL 0x00 121*ece92f85SJason Jin #define FUNC_NOT_SUPPORT 0x81 122*ece92f85SJason Jin #define BAD_VENDOR_ID 0x83 123*ece92f85SJason Jin #define DEVICE_NOT_FOUND 0x86 124*ece92f85SJason Jin #define BAD_REGISTER_NUMBER 0x87 125*ece92f85SJason Jin #define SET_FAILED 0x88 126*ece92f85SJason Jin #define BUFFER_TOO_SMALL 0x89 127*ece92f85SJason Jin 128*ece92f85SJason Jin /**************************************************************************** 129*ece92f85SJason Jin PARAMETERS: 130*ece92f85SJason Jin intno - Interrupt number being serviced 131*ece92f85SJason Jin 132*ece92f85SJason Jin REMARKS: 133*ece92f85SJason Jin This function handles the default Int 1Ah interrupt handler for the real 134*ece92f85SJason Jin mode code, which provides support for the PCI BIOS functions. Since we only 135*ece92f85SJason Jin want to allow the real mode BIOS code *only* see the PCI config space for 136*ece92f85SJason Jin its own device, we only return information for the specific PCI config 137*ece92f85SJason Jin space that we have passed in to the init function. This solves problems 138*ece92f85SJason Jin when using the BIOS to warm boot a secondary adapter when there is an 139*ece92f85SJason Jin identical adapter before it on the bus (some BIOS'es get confused in this 140*ece92f85SJason Jin case). 141*ece92f85SJason Jin ****************************************************************************/ 142*ece92f85SJason Jin static void X86API int1A(int unused) 143*ece92f85SJason Jin { 144*ece92f85SJason Jin u16 pciSlot; 145*ece92f85SJason Jin 146*ece92f85SJason Jin #ifdef __KERNEL__ 147*ece92f85SJason Jin u8 interface, subclass, baseclass; 148*ece92f85SJason Jin 149*ece92f85SJason Jin /* Initialise the PCI slot number */ 150*ece92f85SJason Jin pciSlot = ((int)_BE_env.vgaInfo.bus << 8) | 151*ece92f85SJason Jin ((int)_BE_env.vgaInfo.device << 3) | (int)_BE_env.vgaInfo.function; 152*ece92f85SJason Jin #else 153*ece92f85SJason Jin /* Fail if no PCI device information has been registered */ 154*ece92f85SJason Jin if (!_BE_env.vgaInfo.pciInfo) 155*ece92f85SJason Jin return; 156*ece92f85SJason Jin 157*ece92f85SJason Jin pciSlot = (u16) (_BE_env.vgaInfo.pciInfo->slot.i >> 8); 158*ece92f85SJason Jin #endif 159*ece92f85SJason Jin switch (M.x86.R_AX) { 160*ece92f85SJason Jin case 0xB101: /* PCI bios present? */ 161*ece92f85SJason Jin M.x86.R_AL = 0x00; /* no config space/special cycle generation support */ 162*ece92f85SJason Jin M.x86.R_EDX = 0x20494350; /* " ICP" */ 163*ece92f85SJason Jin M.x86.R_BX = 0x0210; /* Version 2.10 */ 164*ece92f85SJason Jin M.x86.R_CL = 0; /* Max bus number in system */ 165*ece92f85SJason Jin CLEAR_FLAG(F_CF); 166*ece92f85SJason Jin break; 167*ece92f85SJason Jin case 0xB102: /* Find PCI device */ 168*ece92f85SJason Jin M.x86.R_AH = DEVICE_NOT_FOUND; 169*ece92f85SJason Jin #ifdef __KERNEL__ 170*ece92f85SJason Jin if (M.x86.R_DX == _BE_env.vgaInfo.VendorID && 171*ece92f85SJason Jin M.x86.R_CX == _BE_env.vgaInfo.DeviceID && M.x86.R_SI == 0) { 172*ece92f85SJason Jin #else 173*ece92f85SJason Jin if (M.x86.R_DX == _BE_env.vgaInfo.pciInfo->VendorID && 174*ece92f85SJason Jin M.x86.R_CX == _BE_env.vgaInfo.pciInfo->DeviceID && 175*ece92f85SJason Jin M.x86.R_SI == 0) { 176*ece92f85SJason Jin #endif 177*ece92f85SJason Jin M.x86.R_AH = SUCCESSFUL; 178*ece92f85SJason Jin M.x86.R_BX = pciSlot; 179*ece92f85SJason Jin } 180*ece92f85SJason Jin CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); 181*ece92f85SJason Jin break; 182*ece92f85SJason Jin case 0xB103: /* Find PCI class code */ 183*ece92f85SJason Jin M.x86.R_AH = DEVICE_NOT_FOUND; 184*ece92f85SJason Jin #ifdef __KERNEL__ 185*ece92f85SJason Jin pci_read_config_byte(_BE_env.vgaInfo.pcidev, PCI_CLASS_PROG, 186*ece92f85SJason Jin &interface); 187*ece92f85SJason Jin pci_read_config_byte(_BE_env.vgaInfo.pcidev, PCI_CLASS_DEVICE, 188*ece92f85SJason Jin &subclass); 189*ece92f85SJason Jin pci_read_config_byte(_BE_env.vgaInfo.pcidev, 190*ece92f85SJason Jin PCI_CLASS_DEVICE + 1, &baseclass); 191*ece92f85SJason Jin if (M.x86.R_CL == interface && M.x86.R_CH == subclass 192*ece92f85SJason Jin && (u8) (M.x86.R_ECX >> 16) == baseclass) { 193*ece92f85SJason Jin #else 194*ece92f85SJason Jin if (M.x86.R_CL == _BE_env.vgaInfo.pciInfo->Interface && 195*ece92f85SJason Jin M.x86.R_CH == _BE_env.vgaInfo.pciInfo->SubClass && 196*ece92f85SJason Jin (u8) (M.x86.R_ECX >> 16) == 197*ece92f85SJason Jin _BE_env.vgaInfo.pciInfo->BaseClass) { 198*ece92f85SJason Jin #endif 199*ece92f85SJason Jin M.x86.R_AH = SUCCESSFUL; 200*ece92f85SJason Jin M.x86.R_BX = pciSlot; 201*ece92f85SJason Jin } 202*ece92f85SJason Jin CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); 203*ece92f85SJason Jin break; 204*ece92f85SJason Jin case 0xB108: /* Read configuration byte */ 205*ece92f85SJason Jin M.x86.R_AH = BAD_REGISTER_NUMBER; 206*ece92f85SJason Jin if (M.x86.R_BX == pciSlot) { 207*ece92f85SJason Jin M.x86.R_AH = SUCCESSFUL; 208*ece92f85SJason Jin #ifdef __KERNEL__ 209*ece92f85SJason Jin pci_read_config_byte(_BE_env.vgaInfo.pcidev, M.x86.R_DI, 210*ece92f85SJason Jin &M.x86.R_CL); 211*ece92f85SJason Jin #else 212*ece92f85SJason Jin M.x86.R_CL = 213*ece92f85SJason Jin (u8) PCI_accessReg(M.x86.R_DI, 0, PCI_READ_BYTE, 214*ece92f85SJason Jin _BE_env.vgaInfo.pciInfo); 215*ece92f85SJason Jin #endif 216*ece92f85SJason Jin } 217*ece92f85SJason Jin CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); 218*ece92f85SJason Jin break; 219*ece92f85SJason Jin case 0xB109: /* Read configuration word */ 220*ece92f85SJason Jin M.x86.R_AH = BAD_REGISTER_NUMBER; 221*ece92f85SJason Jin if (M.x86.R_BX == pciSlot) { 222*ece92f85SJason Jin M.x86.R_AH = SUCCESSFUL; 223*ece92f85SJason Jin #ifdef __KERNEL__ 224*ece92f85SJason Jin pci_read_config_word(_BE_env.vgaInfo.pcidev, M.x86.R_DI, 225*ece92f85SJason Jin &M.x86.R_CX); 226*ece92f85SJason Jin #else 227*ece92f85SJason Jin M.x86.R_CX = 228*ece92f85SJason Jin (u16) PCI_accessReg(M.x86.R_DI, 0, PCI_READ_WORD, 229*ece92f85SJason Jin _BE_env.vgaInfo.pciInfo); 230*ece92f85SJason Jin #endif 231*ece92f85SJason Jin } 232*ece92f85SJason Jin CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); 233*ece92f85SJason Jin break; 234*ece92f85SJason Jin case 0xB10A: /* Read configuration dword */ 235*ece92f85SJason Jin M.x86.R_AH = BAD_REGISTER_NUMBER; 236*ece92f85SJason Jin if (M.x86.R_BX == pciSlot) { 237*ece92f85SJason Jin M.x86.R_AH = SUCCESSFUL; 238*ece92f85SJason Jin #ifdef __KERNEL__ 239*ece92f85SJason Jin pci_read_config_dword(_BE_env.vgaInfo.pcidev, 240*ece92f85SJason Jin M.x86.R_DI, &M.x86.R_ECX); 241*ece92f85SJason Jin #else 242*ece92f85SJason Jin M.x86.R_ECX = 243*ece92f85SJason Jin (u32) PCI_accessReg(M.x86.R_DI, 0, PCI_READ_DWORD, 244*ece92f85SJason Jin _BE_env.vgaInfo.pciInfo); 245*ece92f85SJason Jin #endif 246*ece92f85SJason Jin } 247*ece92f85SJason Jin CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); 248*ece92f85SJason Jin break; 249*ece92f85SJason Jin case 0xB10B: /* Write configuration byte */ 250*ece92f85SJason Jin M.x86.R_AH = BAD_REGISTER_NUMBER; 251*ece92f85SJason Jin if (M.x86.R_BX == pciSlot) { 252*ece92f85SJason Jin M.x86.R_AH = SUCCESSFUL; 253*ece92f85SJason Jin #ifdef __KERNEL__ 254*ece92f85SJason Jin pci_write_config_byte(_BE_env.vgaInfo.pcidev, 255*ece92f85SJason Jin M.x86.R_DI, M.x86.R_CL); 256*ece92f85SJason Jin #else 257*ece92f85SJason Jin PCI_accessReg(M.x86.R_DI, M.x86.R_CL, PCI_WRITE_BYTE, 258*ece92f85SJason Jin _BE_env.vgaInfo.pciInfo); 259*ece92f85SJason Jin #endif 260*ece92f85SJason Jin } 261*ece92f85SJason Jin CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); 262*ece92f85SJason Jin break; 263*ece92f85SJason Jin case 0xB10C: /* Write configuration word */ 264*ece92f85SJason Jin M.x86.R_AH = BAD_REGISTER_NUMBER; 265*ece92f85SJason Jin if (M.x86.R_BX == pciSlot) { 266*ece92f85SJason Jin M.x86.R_AH = SUCCESSFUL; 267*ece92f85SJason Jin #ifdef __KERNEL__ 268*ece92f85SJason Jin pci_write_config_word(_BE_env.vgaInfo.pcidev, 269*ece92f85SJason Jin M.x86.R_DI, M.x86.R_CX); 270*ece92f85SJason Jin #else 271*ece92f85SJason Jin PCI_accessReg(M.x86.R_DI, M.x86.R_CX, PCI_WRITE_WORD, 272*ece92f85SJason Jin _BE_env.vgaInfo.pciInfo); 273*ece92f85SJason Jin #endif 274*ece92f85SJason Jin } 275*ece92f85SJason Jin CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); 276*ece92f85SJason Jin break; 277*ece92f85SJason Jin case 0xB10D: /* Write configuration dword */ 278*ece92f85SJason Jin M.x86.R_AH = BAD_REGISTER_NUMBER; 279*ece92f85SJason Jin if (M.x86.R_BX == pciSlot) { 280*ece92f85SJason Jin M.x86.R_AH = SUCCESSFUL; 281*ece92f85SJason Jin #ifdef __KERNEL__ 282*ece92f85SJason Jin pci_write_config_dword(_BE_env.vgaInfo.pcidev, 283*ece92f85SJason Jin M.x86.R_DI, M.x86.R_ECX); 284*ece92f85SJason Jin #else 285*ece92f85SJason Jin PCI_accessReg(M.x86.R_DI, M.x86.R_ECX, PCI_WRITE_DWORD, 286*ece92f85SJason Jin _BE_env.vgaInfo.pciInfo); 287*ece92f85SJason Jin #endif 288*ece92f85SJason Jin } 289*ece92f85SJason Jin CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); 290*ece92f85SJason Jin break; 291*ece92f85SJason Jin default: 292*ece92f85SJason Jin printf("biosEmu/bios.int1a: unknown function AX=%#04x\n", 293*ece92f85SJason Jin M.x86.R_AX); 294*ece92f85SJason Jin } 295*ece92f85SJason Jin } 296*ece92f85SJason Jin 297*ece92f85SJason Jin /**************************************************************************** 298*ece92f85SJason Jin REMARKS: 299*ece92f85SJason Jin This function initialises the BIOS emulation functions for the specific 300*ece92f85SJason Jin PCI display device. We insulate the real mode BIOS from any other devices 301*ece92f85SJason Jin on the bus, so that it will work correctly thinking that it is the only 302*ece92f85SJason Jin device present on the bus (ie: avoiding any adapters present in from of 303*ece92f85SJason Jin the device we are trying to control). 304*ece92f85SJason Jin ****************************************************************************/ 305*ece92f85SJason Jin #define BE_constLE_32(v) ((((((v)&0xff00)>>8)|(((v)&0xff)<<8))<<16)|(((((v)&0xff000000)>>8)|(((v)&0x00ff0000)<<8))>>16)) 306*ece92f85SJason Jin 307*ece92f85SJason Jin void _BE_bios_init(u32 * intrTab) 308*ece92f85SJason Jin { 309*ece92f85SJason Jin int i; 310*ece92f85SJason Jin X86EMU_intrFuncs bios_intr_tab[256]; 311*ece92f85SJason Jin 312*ece92f85SJason Jin for (i = 0; i < 256; ++i) { 313*ece92f85SJason Jin intrTab[i] = BE_constLE_32(BIOS_SEG << 16); 314*ece92f85SJason Jin bios_intr_tab[i] = undefined_intr; 315*ece92f85SJason Jin } 316*ece92f85SJason Jin bios_intr_tab[0x10] = int10; 317*ece92f85SJason Jin bios_intr_tab[0x1A] = int1A; 318*ece92f85SJason Jin bios_intr_tab[0x42] = int42; 319*ece92f85SJason Jin bios_intr_tab[0x6D] = int10; 320*ece92f85SJason Jin X86EMU_setupIntrFuncs(bios_intr_tab); 321*ece92f85SJason Jin } 322