diff options
| author | Stefan Roese <sr@denx.de> | 2007-08-14 16:36:29 +0200 | 
|---|---|---|
| committer | Stefan Roese <sr@denx.de> | 2007-08-14 16:36:29 +0200 | 
| commit | 3b3bff4cbf2cb14f9a3e7d03f26ebab900efe4ae (patch) | |
| tree | fb66bf8861d9f78765160d734a438856f5317cdb /drivers/bios_emulator/bios.c | |
| parent | 4ce846ec59f36b85d6644a769690ad3feb667575 (diff) | |
| parent | 4ef35e53c693556c54b0c22d6f873de87bade253 (diff) | |
| download | olio-uboot-2014.01-3b3bff4cbf2cb14f9a3e7d03f26ebab900efe4ae.tar.xz olio-uboot-2014.01-3b3bff4cbf2cb14f9a3e7d03f26ebab900efe4ae.zip | |
Merge with git://www.denx.de/git/u-boot.git
Diffstat (limited to 'drivers/bios_emulator/bios.c')
| -rw-r--r-- | drivers/bios_emulator/bios.c | 323 | 
1 files changed, 323 insertions, 0 deletions
| diff --git a/drivers/bios_emulator/bios.c b/drivers/bios_emulator/bios.c new file mode 100644 index 000000000..7aa1bfb2e --- /dev/null +++ b/drivers/bios_emulator/bios.c @@ -0,0 +1,323 @@ +/**************************************************************************** +* +*                        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 "biosemui.h" + +#if defined(CONFIG_BIOSEMU) +/*----------------------------- 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); +} +#endif |