⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mtrr.c

📁 BIOS emulator and interface to Realmode X86 Emulator Library Can emulate a PCI Graphic Controller V
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************					SciTech OS Portability Manager Library**  ========================================================================**    The contents of this file are subject to the SciTech MGL Public*    License Version 1.0 (the "License"); you may not use this file*    except in compliance with the License. You may obtain a copy of*    the License at http://www.scitechsoft.com/mgl-license.txt**    Software distributed under the License is distributed on an*    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or*    implied. See the License for the specific language governing*    rights and limitations under the License.**    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.**    The Initial Developer of the Original Code is SciTech Software, Inc.*    All Rights Reserved.**  ========================================================================**				Heavily based on code copyright (C) Richard Gooch** Language:		ANSI C* Environment:	32-bit Ring 0 device driver** Description:	Generic Memory Type Range Register (MTRR) functions to*				manipulate the MTRR registers on supported CPU's. This code*				*must* run at ring 0, so you can't normally include this*				code directly in normal applications (the except is DOS4GW*				apps which run at ring 0 under real DOS). Thus this code*				will normally be compiled into a ring 0 device driver for*				the target operating system.*****************************************************************************/#include "pmapi.h"#include "ztimerc.h"#include "mtrr.h"#ifndef REALMODE/*--------------------------- Global variables ----------------------------*//* Intel pre-defined MTRR registers */#define NUM_FIXED_RANGES 		88#define INTEL_cap_MSR     		0x0FE#define INTEL_defType_MSR 		0x2FF#define INTEL_fix64K_00000_MSR 	0x250#define INTEL_fix16K_80000_MSR 	0x258#define INTEL_fix16K_A0000_MSR 	0x259#define INTEL_fix4K_C0000_MSR 	0x268#define INTEL_fix4K_C8000_MSR 	0x269#define INTEL_fix4K_D0000_MSR 	0x26A#define INTEL_fix4K_D8000_MSR 	0x26B#define INTEL_fix4K_E0000_MSR 	0x26C#define INTEL_fix4K_E8000_MSR 	0x26D#define INTEL_fix4K_F0000_MSR 	0x26E#define INTEL_fix4K_F8000_MSR 	0x26F/* Macros to find the address of a paricular MSR register */#define INTEL_physBase_MSR(reg)	(0x200 + 2 * (reg))#define INTEL_physMask_MSR(reg)	(0x200 + 2 * (reg) + 1)/* Cyrix CPU configuration register indexes */#define CX86_CCR0 0xC0#define CX86_CCR1 0xC1#define CX86_CCR2 0xC2#define CX86_CCR3 0xC3#define CX86_CCR4 0xE8#define CX86_CCR5 0xE9#define CX86_CCR6 0xEA#define CX86_DIR0 0xFE#define CX86_DIR1 0xFF#define CX86_ARR_BASE 0xC4#define CX86_RCR_BASE 0xDC/* Structure to maintain machine state while updating MTRR registers */typedef struct {	ulong	flags;	ulong 	defTypeLo;	ulong 	defTypeHi;	ulong 	cr4Val;	ulong 	ccr3;	} MTRRContext;static int		numMTRR = -1;static int		cpuType,cpuFamily;static void 	(*getMTRR)(uint reg,ulong *base,ulong *size,int *type) = NULL;static void 	(*setMTRR)(uint reg,ulong base,ulong size,int type) = NULL;static int 		(*getFreeRegion)(ulong base,ulong size) = NULL;/*----------------------------- Implementation ----------------------------*//****************************************************************************RETURNS:Returns non-zero if we have the write-combining memory type****************************************************************************/static int MTRR_haveWriteCombine(void){	ulong	config,dummy;	switch (cpuFamily) {		case CPU_AMD:			if (cpuType < CPU_AMDAthlon) {				/* AMD K6-2 and later support the MTRR registers */				if (cpuType < CPU_AMDK6_2)					return 0;				return 1;				}			/* Fall through for AMD Athlon which uses P6 style MTRR's */		case CPU_Intel:			_MTRR_readMSR(INTEL_cap_MSR,&config,&dummy);			return (config & (1 << 10));		case CPU_Cyrix:			/* Cyrix 6x86 and later support the MTRR registers */			if (cpuType < CPU_Cyrix6x86)				return 0;			return 1;		}	return 0;}/****************************************************************************PARAMETERS:base	- The starting physical base address of the regionsize	- The size in bytes of the regionRETURNS:The index of the region on success, else -1 on error.REMARKS:Generic function to find the location of a free MTRR register to be usedfor creating a new mapping.****************************************************************************/static int GENERIC_getFreeRegion(	ulong base,	ulong size){	int		i,ltype;	ulong 	lbase,lsize;	for (i = 0; i < numMTRR; i++) {		getMTRR(i,&lbase,&lsize,&ltype);		if (lsize < 1)			return i;		}	(void)base;	(void)size;	return -1;}/****************************************************************************PARAMETERS:base	- The starting physical base address of the regionsize	- The size in bytes of the regionRETURNS:The index of the region on success, else -1 on error.REMARKS:Cyrix specific function to find the location of a free MTRR register to beused for creating a new mapping.****************************************************************************/static int CYRIX_getFreeRegion(	ulong base,	ulong size){	int 	i,ltype;	ulong	lbase, lsize;	if (size > 0x2000000UL) {		/* If we are to set up a region >32M then look at ARR7 immediately */		getMTRR(7,&lbase,&lsize,&ltype);		if (lsize < 1)			return 7;		}	else {		/* Check ARR0-6 registers */		for (i = 0; i < 7; i++) {			getMTRR(i,&lbase,&lsize,&ltype);			if (lsize < 1)				return i;			}		/* Try ARR7 but its size must be at least 256K */		getMTRR(7,&lbase,&lsize,&ltype);		if ((lsize < 1) && (size >= 0x40000))			return i;		}	(void)base;	return -1;}/****************************************************************************PARAMETERS:c	- Place to store the machine context across the callREMARKS:Puts the processor into a state where MTRRs can be safely updated****************************************************************************/static void MTRR_beginUpdate(	MTRRContext *c){	c->flags = _MTRR_disableInt();	if (cpuFamily != CPU_AMD || (cpuFamily == CPU_AMD && cpuType >= CPU_AMDAthlon)) {		c->cr4Val = _MTRR_saveCR4();		switch (cpuFamily) {			case CPU_Intel:			case CPU_AMD:				/* Disable MTRRs, and set the default type to uncached */				_MTRR_readMSR(INTEL_defType_MSR,&c->defTypeLo,&c->defTypeHi);				_MTRR_writeMSR(INTEL_defType_MSR,c->defTypeLo & 0xF300UL,c->defTypeHi);				break;			case CPU_Cyrix:				c->ccr3 = _MTRR_getCx86(CX86_CCR3);				_MTRR_setCx86(CX86_CCR3, (c->ccr3 & 0x0F) | 0x10);				break;			}		}}/****************************************************************************PARAMETERS:c	- Place to restore the machine context fromREMARKS:Restores the processor after updating any of the registers****************************************************************************/static void MTRR_endUpdate(	MTRRContext *c){	if (cpuFamily != CPU_AMD || (cpuFamily == CPU_AMD && cpuType >= CPU_AMDAthlon)) {		_MTRR_flushTLB();		switch (cpuFamily) {			case CPU_Intel:				_MTRR_writeMSR(INTEL_defType_MSR,c->defTypeLo,c->defTypeHi);				break;			case CPU_Cyrix:				_MTRR_setCx86(CX86_CCR3,c->ccr3);				break;			}		_MTRR_restoreCR4(c->cr4Val);		}	/* Re-enable interrupts (if enabled previously) */	_MTRR_restoreInt(c->flags);}/****************************************************************************PARAMETERS:reg		- MTRR register to readbase	- Place to store the starting physical base address of the regionsize	- Place to store the size in bytes of the regiontype	- Place to store the type of the MTRR registerREMARKS:Intel specific function to read the value of a specific MTRR register.****************************************************************************/static void INTEL_getMTRR(	uint reg,	ulong *base,	ulong *size,	int *type){	ulong hi,maskLo,baseLo;	_MTRR_readMSR(INTEL_physMask_MSR(reg),&maskLo,&hi);	if ((maskLo & 0x800) == 0) {		/* MTRR is disabled, so it is free */		*base = 0;		*size = 0;		*type = 0;		return;		}	_MTRR_readMSR(INTEL_physBase_MSR(reg),&baseLo,&hi);	maskLo = (maskLo & 0xFFFFF000UL);	*size = ~(maskLo - 1);	*base = (baseLo & 0xFFFFF000UL);	*type = (baseLo & 0xFF);}/****************************************************************************PARAMETERS:reg		- MTRR register to setbase	- The starting physical base address of the regionsize	- The size in bytes of the regiontype	- Type to place into the MTRR registerREMARKS:Intel specific function to set the value of a specific MTRR register tothe passed in base, size and type.****************************************************************************/static void INTEL_setMTRR(	uint reg,	ulong base,	ulong size,	int type){	MTRRContext	c;	MTRR_beginUpdate(&c);	if (size == 0) {		/* The invalid bit is kept in the mask, so we simply clear the		 * relevant mask register to disable a range.		 */		_MTRR_writeMSR(INTEL_physMask_MSR(reg),0,0);		}	else {		_MTRR_writeMSR(INTEL_physBase_MSR(reg),base | type,0);		_MTRR_writeMSR(INTEL_physMask_MSR(reg),~(size - 1) | 0x800,0);		}	MTRR_endUpdate(&c);}/****************************************************************************PARAMETERS:reg		- MTRR register to setbase	- The starting physical base address of the regionsize	- The size in bytes of the regiontype	- Type to place into the MTRR registerREMARKS:Intel specific function to set the value of a specific MTRR register tothe passed in base, size and type.****************************************************************************/static void AMD_getMTRR(	uint reg,	ulong *base,	ulong *size,	int *type){	ulong	low,high;	/*  Upper dword is region 1, lower is region 0  */	_MTRR_readMSR(0xC0000085, &low, &high);	if (reg == 1)		low = high;	/* Find the base and type for the region */	*base = low & 0xFFFE0000;	*type = 0;	if (low & 1)		*type = PM_MTRR_UNCACHABLE;	if (low & 2)		*type = PM_MTRR_WRCOMB;	if ((low & 3) == 0) {		*size = 0;		return;		}	/* This needs a little explaining. The size is stored as an	 * inverted mask of bits of 128K granularity 15 bits long offset	 * 2 bits	 *	 * So to get a size we do invert the mask and add 1 to the lowest	 * mask bit (4 as its 2 bits in). This gives us a size we then shift	 * to turn into 128K blocks	 *     *  eg              111 1111 1111 1100      is 512K     *     *  invert          000 0000 0000 0011     *  +1              000 0000 0000 0100     *  *128K   ...     */    low = (~low) & 0x1FFFC;	*size = (low + 4) << 15;}/****************************************************************************PARAMETERS:reg		- MTRR register to setbase	- The starting physical base address of the regionsize	- The size in bytes of the regiontype	- Type to place into the MTRR registerREMARKS:Intel specific function to set the value of a specific MTRR register tothe passed in base, size and type.****************************************************************************/static void AMD_setMTRR(	uint reg,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -