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