123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- /****************************************************************************
- *
- * BIOS emulator and interface
- * to Realmode X86 Emulator Library
- *
- * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
- * Jason Jin <Jason.jin@freescale.com>
- *
- * Copyright (C) 1996-1999 SciTech Software, Inc.
- *
- * ========================================================================
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of the authors not be used
- * in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission. The authors makes no
- * representations about the suitability of this software for any purpose.
- * It is provided "as is" without express or implied warranty.
- *
- * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
- * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- * ========================================================================
- *
- * Language: ANSI C
- * Environment: Any
- * Developer: Kendall Bennett
- *
- * Description: Module implementing the BIOS specific functions.
- *
- * Jason ported this file to u-boot to run the ATI video card
- * video BIOS.
- *
- ****************************************************************************/
- #include <common.h>
- #include "biosemui.h"
- /*----------------------------- Implementation ----------------------------*/
- /****************************************************************************
- PARAMETERS:
- intno - Interrupt number being serviced
- REMARKS:
- Handler for undefined interrupts.
- ****************************************************************************/
- static void X86API undefined_intr(int intno)
- {
- if (BE_rdw(intno * 4 + 2) == BIOS_SEG) {
- DB(printf("biosEmu: undefined interrupt %xh called!\n", intno);)
- } else
- X86EMU_prepareForInt(intno);
- }
- /****************************************************************************
- PARAMETERS:
- intno - Interrupt number being serviced
- REMARKS:
- This function handles the default system BIOS Int 10h (the default is stored
- in the Int 42h vector by the system BIOS at bootup). We only need to handle
- a small number of special functions used by the BIOS during POST time.
- ****************************************************************************/
- static void X86API int42(int intno)
- {
- if (M.x86.R_AH == 0x12 && M.x86.R_BL == 0x32) {
- if (M.x86.R_AL == 0) {
- /* Enable CPU accesses to video memory */
- PM_outpb(0x3c2, PM_inpb(0x3cc) | (u8) 0x02);
- return;
- } else if (M.x86.R_AL == 1) {
- /* Disable CPU accesses to video memory */
- PM_outpb(0x3c2, PM_inpb(0x3cc) & (u8) ~ 0x02);
- return;
- }
- #ifdef DEBUG
- else {
- printf("int42: unknown function AH=0x12, BL=0x32, AL=%#02x\n",
- M.x86.R_AL);
- }
- #endif
- }
- #ifdef DEBUG
- else {
- printf("int42: unknown function AH=%#02x, AL=%#02x, BL=%#02x\n",
- M.x86.R_AH, M.x86.R_AL, M.x86.R_BL);
- }
- #endif
- }
- /****************************************************************************
- PARAMETERS:
- intno - Interrupt number being serviced
- REMARKS:
- This function handles the default system BIOS Int 10h. If the POST code
- has not yet re-vectored the Int 10h BIOS interrupt vector, we handle this
- by simply calling the int42 interrupt handler above. Very early in the
- BIOS POST process, the vector gets replaced and we simply let the real
- mode interrupt handler process the interrupt.
- ****************************************************************************/
- static void X86API int10(int intno)
- {
- if (BE_rdw(intno * 4 + 2) == BIOS_SEG)
- int42(intno);
- else
- X86EMU_prepareForInt(intno);
- }
- /* Result codes returned by the PCI BIOS */
- #define SUCCESSFUL 0x00
- #define FUNC_NOT_SUPPORT 0x81
- #define BAD_VENDOR_ID 0x83
- #define DEVICE_NOT_FOUND 0x86
- #define BAD_REGISTER_NUMBER 0x87
- #define SET_FAILED 0x88
- #define BUFFER_TOO_SMALL 0x89
- /****************************************************************************
- PARAMETERS:
- intno - Interrupt number being serviced
- REMARKS:
- This function handles the default Int 1Ah interrupt handler for the real
- mode code, which provides support for the PCI BIOS functions. Since we only
- want to allow the real mode BIOS code *only* see the PCI config space for
- its own device, we only return information for the specific PCI config
- space that we have passed in to the init function. This solves problems
- when using the BIOS to warm boot a secondary adapter when there is an
- identical adapter before it on the bus (some BIOS'es get confused in this
- case).
- ****************************************************************************/
- static void X86API int1A(int unused)
- {
- u16 pciSlot;
- #ifdef __KERNEL__
- u8 interface, subclass, baseclass;
- /* Initialise the PCI slot number */
- pciSlot = ((int)_BE_env.vgaInfo.bus << 8) |
- ((int)_BE_env.vgaInfo.device << 3) | (int)_BE_env.vgaInfo.function;
- #else
- /* Fail if no PCI device information has been registered */
- if (!_BE_env.vgaInfo.pciInfo)
- return;
- pciSlot = (u16) (_BE_env.vgaInfo.pciInfo->slot.i >> 8);
- #endif
- switch (M.x86.R_AX) {
- case 0xB101: /* PCI bios present? */
- M.x86.R_AL = 0x00; /* no config space/special cycle generation support */
- M.x86.R_EDX = 0x20494350; /* " ICP" */
- M.x86.R_BX = 0x0210; /* Version 2.10 */
- M.x86.R_CL = 0; /* Max bus number in system */
- CLEAR_FLAG(F_CF);
- break;
- case 0xB102: /* Find PCI device */
- M.x86.R_AH = DEVICE_NOT_FOUND;
- #ifdef __KERNEL__
- if (M.x86.R_DX == _BE_env.vgaInfo.VendorID &&
- M.x86.R_CX == _BE_env.vgaInfo.DeviceID && M.x86.R_SI == 0) {
- #else
- if (M.x86.R_DX == _BE_env.vgaInfo.pciInfo->VendorID &&
- M.x86.R_CX == _BE_env.vgaInfo.pciInfo->DeviceID &&
- M.x86.R_SI == 0) {
- #endif
- M.x86.R_AH = SUCCESSFUL;
- M.x86.R_BX = pciSlot;
- }
- CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
- break;
- case 0xB103: /* Find PCI class code */
- M.x86.R_AH = DEVICE_NOT_FOUND;
- #ifdef __KERNEL__
- pci_read_config_byte(_BE_env.vgaInfo.pcidev, PCI_CLASS_PROG,
- &interface);
- pci_read_config_byte(_BE_env.vgaInfo.pcidev, PCI_CLASS_DEVICE,
- &subclass);
- pci_read_config_byte(_BE_env.vgaInfo.pcidev,
- PCI_CLASS_DEVICE + 1, &baseclass);
- if (M.x86.R_CL == interface && M.x86.R_CH == subclass
- && (u8) (M.x86.R_ECX >> 16) == baseclass) {
- #else
- if (M.x86.R_CL == _BE_env.vgaInfo.pciInfo->Interface &&
- M.x86.R_CH == _BE_env.vgaInfo.pciInfo->SubClass &&
- (u8) (M.x86.R_ECX >> 16) ==
- _BE_env.vgaInfo.pciInfo->BaseClass) {
- #endif
- M.x86.R_AH = SUCCESSFUL;
- M.x86.R_BX = pciSlot;
- }
- CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
- break;
- case 0xB108: /* Read configuration byte */
- M.x86.R_AH = BAD_REGISTER_NUMBER;
- if (M.x86.R_BX == pciSlot) {
- M.x86.R_AH = SUCCESSFUL;
- #ifdef __KERNEL__
- pci_read_config_byte(_BE_env.vgaInfo.pcidev, M.x86.R_DI,
- &M.x86.R_CL);
- #else
- M.x86.R_CL =
- (u8) PCI_accessReg(M.x86.R_DI, 0, PCI_READ_BYTE,
- _BE_env.vgaInfo.pciInfo);
- #endif
- }
- CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
- break;
- case 0xB109: /* Read configuration word */
- M.x86.R_AH = BAD_REGISTER_NUMBER;
- if (M.x86.R_BX == pciSlot) {
- M.x86.R_AH = SUCCESSFUL;
- #ifdef __KERNEL__
- pci_read_config_word(_BE_env.vgaInfo.pcidev, M.x86.R_DI,
- &M.x86.R_CX);
- #else
- M.x86.R_CX =
- (u16) PCI_accessReg(M.x86.R_DI, 0, PCI_READ_WORD,
- _BE_env.vgaInfo.pciInfo);
- #endif
- }
- CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
- break;
- case 0xB10A: /* Read configuration dword */
- M.x86.R_AH = BAD_REGISTER_NUMBER;
- if (M.x86.R_BX == pciSlot) {
- M.x86.R_AH = SUCCESSFUL;
- #ifdef __KERNEL__
- pci_read_config_dword(_BE_env.vgaInfo.pcidev,
- M.x86.R_DI, &M.x86.R_ECX);
- #else
- M.x86.R_ECX =
- (u32) PCI_accessReg(M.x86.R_DI, 0, PCI_READ_DWORD,
- _BE_env.vgaInfo.pciInfo);
- #endif
- }
- CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
- break;
- case 0xB10B: /* Write configuration byte */
- M.x86.R_AH = BAD_REGISTER_NUMBER;
- if (M.x86.R_BX == pciSlot) {
- M.x86.R_AH = SUCCESSFUL;
- #ifdef __KERNEL__
- pci_write_config_byte(_BE_env.vgaInfo.pcidev,
- M.x86.R_DI, M.x86.R_CL);
- #else
- PCI_accessReg(M.x86.R_DI, M.x86.R_CL, PCI_WRITE_BYTE,
- _BE_env.vgaInfo.pciInfo);
- #endif
- }
- CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
- break;
- case 0xB10C: /* Write configuration word */
- M.x86.R_AH = BAD_REGISTER_NUMBER;
- if (M.x86.R_BX == pciSlot) {
- M.x86.R_AH = SUCCESSFUL;
- #ifdef __KERNEL__
- pci_write_config_word(_BE_env.vgaInfo.pcidev,
- M.x86.R_DI, M.x86.R_CX);
- #else
- PCI_accessReg(M.x86.R_DI, M.x86.R_CX, PCI_WRITE_WORD,
- _BE_env.vgaInfo.pciInfo);
- #endif
- }
- CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
- break;
- case 0xB10D: /* Write configuration dword */
- M.x86.R_AH = BAD_REGISTER_NUMBER;
- if (M.x86.R_BX == pciSlot) {
- M.x86.R_AH = SUCCESSFUL;
- #ifdef __KERNEL__
- pci_write_config_dword(_BE_env.vgaInfo.pcidev,
- M.x86.R_DI, M.x86.R_ECX);
- #else
- PCI_accessReg(M.x86.R_DI, M.x86.R_ECX, PCI_WRITE_DWORD,
- _BE_env.vgaInfo.pciInfo);
- #endif
- }
- CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
- break;
- default:
- printf("biosEmu/bios.int1a: unknown function AX=%#04x\n",
- M.x86.R_AX);
- }
- }
- /****************************************************************************
- REMARKS:
- This function initialises the BIOS emulation functions for the specific
- PCI display device. We insulate the real mode BIOS from any other devices
- on the bus, so that it will work correctly thinking that it is the only
- device present on the bus (ie: avoiding any adapters present in from of
- the device we are trying to control).
- ****************************************************************************/
- #define BE_constLE_32(v) ((((((v)&0xff00)>>8)|(((v)&0xff)<<8))<<16)|(((((v)&0xff000000)>>8)|(((v)&0x00ff0000)<<8))>>16))
- void _BE_bios_init(u32 * intrTab)
- {
- int i;
- X86EMU_intrFuncs bios_intr_tab[256];
- for (i = 0; i < 256; ++i) {
- intrTab[i] = BE_constLE_32(BIOS_SEG << 16);
- bios_intr_tab[i] = undefined_intr;
- }
- bios_intr_tab[0x10] = int10;
- bios_intr_tab[0x1A] = int1A;
- bios_intr_tab[0x42] = int42;
- bios_intr_tab[0x6D] = int10;
- X86EMU_setupIntrFuncs(bios_intr_tab);
- }
|