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

📄 mtrr.c

📁 自己修改的U-boot1.1.4For AT91RM9200DK. 请用armgcc3.3.2编译。
💻 C
📖 第 1 页 / 共 2 页
字号:
    ulong size,    int type){    ulong       low,high,newVal;    MTRRContext c;    MTRR_beginUpdate(&c);    _MTRR_readMSR(0xC0000085, &low, &high);    if (size == 0) {	/* Clear register to disable */	if (reg)	    high = 0;	else	    low = 0;	}    else {	/* Set the register to the base (already shifted for us), the	 * type (off by one) and an inverted bitmask of the size	 * The size is the only odd bit. We are fed say 512K	 * We invert this and we get 111 1111 1111 1011 but	 * if you subtract one and invert you get the desired	 * 111 1111 1111 1100 mask	 */	newVal = (((~(size-1)) >> 15) & 0x0001FFFC) | base | (type+1);	if (reg)	    high = newVal;	else	    low = newVal;	}    /* The writeback rule is quite specific. See the manual. Its     * disable local interrupts, write back the cache, set the MTRR     */    PM_flushTLB();    _MTRR_writeMSR(0xC0000085, low, high);    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 CYRIX_getMTRR(    uint reg,    ulong *base,    ulong *size,    int *type){    MTRRContext c;    uchar       arr = CX86_ARR_BASE + reg*3;    uchar       rcr,shift;    /* Save flags and disable interrupts */    MTRR_beginUpdate(&c);    ((uchar*)base)[3]  = _MTRR_getCx86(arr);    ((uchar*)base)[2]  = _MTRR_getCx86((uchar)(arr+1));    ((uchar*)base)[1]  = _MTRR_getCx86((uchar)(arr+2));    rcr = _MTRR_getCx86((uchar)(CX86_RCR_BASE + reg));    MTRR_endUpdate(&c);    /* Enable interrupts if it was enabled previously */    shift = ((uchar*)base)[1] & 0x0f;    *base &= 0xFFFFF000UL;    /* Power of two, at least 4K on ARR0-ARR6, 256K on ARR7     * Note: shift==0xF means 4G, this is unsupported.     */    if (shift)	*size = (reg < 7 ? 0x800UL : 0x20000UL) << shift;    else	*size = 0;    /* Bit 0 is Cache Enable on ARR7, Cache Disable on ARR0-ARR6 */    if (reg < 7) {	switch (rcr) {	    case  1: *type = PM_MTRR_UNCACHABLE; break;	    case  8: *type = PM_MTRR_WRBACK;     break;	    case  9: *type = PM_MTRR_WRCOMB;     break;	    case 24:	    default: *type = PM_MTRR_WRTHROUGH;  break;	    }	}    else {	switch (rcr) {	    case  0: *type = PM_MTRR_UNCACHABLE; break;	    case  8: *type = PM_MTRR_WRCOMB;     break;	    case  9: *type = PM_MTRR_WRBACK;     break;	    case 25:	    default: *type = PM_MTRR_WRTHROUGH;  break;	    }	}}/****************************************************************************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 CYRIX_setMTRR(    uint reg,    ulong base,    ulong size,    int type){    MTRRContext c;    uchar       arr = CX86_ARR_BASE + reg*3;    uchar       arr_type,arr_size;    /* Count down from 32M (ARR0-ARR6) or from 2G (ARR7) */    size >>= (reg < 7 ? 12 : 18);    size &= 0x7FFF; /* Make sure arr_size <= 14 */    for (arr_size = 0; size; arr_size++, size >>= 1)	;    if (reg < 7) {	switch (type) {	    case PM_MTRR_UNCACHABLE:    arr_type =  1; break;	    case PM_MTRR_WRCOMB:        arr_type =  9; break;	    case PM_MTRR_WRTHROUGH:     arr_type = 24; break;	    default:                    arr_type =  8; break;	    }	}    else {	switch (type) {	    case PM_MTRR_UNCACHABLE:    arr_type =  0; break;	    case PM_MTRR_WRCOMB:        arr_type =  8; break;	    case PM_MTRR_WRTHROUGH:     arr_type = 25; break;	    default:                    arr_type =  9; break;	    }	}    MTRR_beginUpdate(&c);    _MTRR_setCx86((uchar)arr,     ((uchar*)&base)[3]);    _MTRR_setCx86((uchar)(arr+1), ((uchar*)&base)[2]);    _MTRR_setCx86((uchar)(arr+2), (uchar)((((uchar*)&base)[1]) | arr_size));    _MTRR_setCx86((uchar)(CX86_RCR_BASE + reg), (uchar)arr_type);    MTRR_endUpdate(&c);}/****************************************************************************REMARKS:On Cyrix 6x86(MX) and MII the ARR3 is special: it has connectionwith the SMM (System Management Mode) mode. So we need the following:Check whether SMI_LOCK (CCR3 bit 0) is set  if it is set, ARR3 cannot be changed  (it cannot be changed until the    next processor reset)  if it is reset, then we can change it, set all the needed bits:   - disable access to SMM memory through ARR3 range (CCR1 bit 7 reset)   - disable access to SMM memory (CCR1 bit 2 reset)   - disable SMM mode (CCR1 bit 1 reset)   - disable write protection of ARR3 (CCR6 bit 1 reset)   - (maybe) disable ARR3Just to be sure, we enable ARR usage by the processor (CCR5 bit 5 set)****************************************************************************/static void CYRIX_initARR(void){    MTRRContext c;    uchar       ccr[7];    int         ccrc[7] = { 0, 0, 0, 0, 0, 0, 0 };    /* Begin updating */    MTRR_beginUpdate(&c);    /* Save all CCRs locally */    ccr[0] = _MTRR_getCx86(CX86_CCR0);    ccr[1] = _MTRR_getCx86(CX86_CCR1);    ccr[2] = _MTRR_getCx86(CX86_CCR2);    ccr[3] = (uchar)c.ccr3;    ccr[4] = _MTRR_getCx86(CX86_CCR4);    ccr[5] = _MTRR_getCx86(CX86_CCR5);    ccr[6] = _MTRR_getCx86(CX86_CCR6);    if (ccr[3] & 1)	ccrc[3] = 1;    else {	/* Disable SMM mode (bit 1), access to SMM memory (bit 2) and	 * access to SMM memory through ARR3 (bit 7).	 */	if (ccr[6] & 0x02) {	    ccr[6] &= 0xFD;	    ccrc[6] = 1;        /* Disable write protection of ARR3. */	    _MTRR_setCx86(CX86_CCR6,ccr[6]);	    }	}    /* If we changed CCR1 in memory, change it in the processor, too. */    if (ccrc[1])	_MTRR_setCx86(CX86_CCR1,ccr[1]);    /* Enable ARR usage by the processor */    if (!(ccr[5] & 0x20)) {	ccr[5] |= 0x20;	ccrc[5] = 1;	_MTRR_setCx86(CX86_CCR5,ccr[5]);	}    /* We are finished updating */    MTRR_endUpdate(&c);}/****************************************************************************REMARKS:Initialise the MTRR module, by detecting the processor type and determiningif the processor supports the MTRR functionality.****************************************************************************/void MTRR_init(void){    int     i,cpu,ltype;    ulong   eax,edx,lbase,lsize;    /* Check that we have a compatible CPU */    if (numMTRR == -1) {	numMTRR = 0;	if (!_MTRR_isRing0())	    return;	cpu = CPU_getProcessorType();	cpuFamily = cpu & CPU_familyMask;	cpuType = cpu & CPU_mask;	cpuStepping = (cpu & CPU_steppingMask) >> CPU_steppingShift;	switch (cpuFamily) {	    case CPU_Intel:		/* Intel Pentium Pro and later support the MTRR registers */		if (cpuType < CPU_PentiumPro)		    return;		_MTRR_readMSR(INTEL_cap_MSR,&eax,&edx);		numMTRR = eax & 0xFF;		getMTRR = INTEL_getMTRR;		setMTRR = INTEL_setMTRR;		getFreeRegion = GENERIC_getFreeRegion;		INTEL_disableBankedWriteCombine();		break;	    case CPU_AMD:		/* AMD K6-2 and later support the MTRR registers */		if ((cpuType < CPU_AMDK6_2) || (cpuType == CPU_AMDK6_2 && cpuStepping < 8))		    return;		if (cpuType < CPU_AMDAthlon) {		    numMTRR = 2;        /* AMD CPU's have 2 MTRR's */		    getMTRR = AMD_getMTRR;		    setMTRR = AMD_setMTRR;		    getFreeRegion = AMDK6_getFreeRegion;		    /* For some reason some IBM systems with K6-2 processors		     * have write combined enabled for the system BIOS		     * region from 0xE0000 to 0xFFFFFF. We need *both* MTRR's		     * for our own graphics drivers, so if we detect any		     * regions below the 1Meg boundary, we remove them		     * so we can use this MTRR register ourselves.		     */		    for (i = 0; i < numMTRR; i++) {			getMTRR(i,&lbase,&lsize,&ltype);			if (lbase < 0x100000)			    setMTRR(i,0,0,0);			}		    }		else {		    /* AMD Athlon uses P6 style MTRR's */		    _MTRR_readMSR(INTEL_cap_MSR,&eax,&edx);		    numMTRR = eax & 0xFF;		    getMTRR = INTEL_getMTRR;		    setMTRR = INTEL_setMTRR;		    getFreeRegion = GENERIC_getFreeRegion;		    INTEL_disableBankedWriteCombine();		    }		break;	    case CPU_Cyrix:		/* Cyrix 6x86 and later support the MTRR registers */		if (cpuType < CPU_Cyrix6x86 || cpuType >= CPU_CyrixMediaGX)		    return;		numMTRR = 8;        /* Cyrix CPU's have 8 ARR's */		getMTRR = CYRIX_getMTRR;		setMTRR = CYRIX_setMTRR;		getFreeRegion = CYRIX_getFreeRegion;		CYRIX_initARR();		break;	    default:		return;	    }	}}/****************************************************************************PARAMETERS:base    - The starting physical base address of the regionsize    - The size in bytes of the regiontype    - Type to place into the MTRR registerRETURNS:Error code describing the result.REMARKS:Function to enable write combining for the specified region of memory.****************************************************************************/int MTRR_enableWriteCombine(    ulong base,    ulong size,    uint type){    int     i;    int     ltype;    ulong   lbase,lsize,last;    /* Check that we have a CPU that supports MTRR's and type is valid */    if (numMTRR <= 0) {	if (!_MTRR_isRing0())	    return PM_MTRR_ERR_NO_OS_SUPPORT;	return PM_MTRR_NOT_SUPPORTED;	}    if (type >= PM_MTRR_MAX)	return PM_MTRR_ERR_PARAMS;    /* If the type is WC, check that this processor supports it */    if (!MTRR_haveWriteCombine())	return PM_MTRR_ERR_NOWRCOMB;    /* Adjust the boundaries depending on the CPU type */    switch (cpuFamily) {	case CPU_AMD:	    if (cpuType < CPU_AMDAthlon) {		/* Apply the K6 block alignment and size rules. In order:		 *  o Uncached or gathering only		 *  o 128K or bigger block		 *  o Power of 2 block		 *  o base suitably aligned to the power		 */		if (type > PM_MTRR_WRCOMB && (size < (1 << 17) || (size & ~(size-1))-size || (base & (size-1))))		    return PM_MTRR_ERR_NOT_ALIGNED;		break;		}	    /* Fall through for AMD Athlon which uses P6 style MTRR's */	case CPU_Intel:	case CPU_Cyrix:	    if ((base & 0xFFF) || (size & 0xFFF)) {		/* Base and size must be multiples of 4Kb */		return PM_MTRR_ERR_NOT_4KB_ALIGNED;		}	    if (base < 0x100000) {		/* Base must be >= 1Mb */		return PM_MTRR_ERR_BELOW_1MB;		}	    /* Check upper bits of base and last are equal and lower bits	     * are 0 for base and 1 for last	     */	    last = base + size - 1;	    for (lbase = base; !(lbase & 1) && (last & 1); lbase = lbase >> 1, last = last >> 1)		;	    if (lbase != last) {		/* Base is not aligned on the correct boundary */		return PM_MTRR_ERR_NOT_ALIGNED;		}	    break;	default:	    return PM_MTRR_NOT_SUPPORTED;	}    /* Search for existing MTRR */    for (i = 0; i < numMTRR; ++i) {	getMTRR(i,&lbase,&lsize,&ltype);	if (lbase == 0 && lsize == 0)	    continue;	if (base > lbase + (lsize-1))	    continue;	if ((base < lbase) && (base+size-1 < lbase))	    continue;	/* Check that we don't overlap an existing region */	if (type != PM_MTRR_UNCACHABLE) {	    if ((base < lbase) || (base+size-1 > lbase+lsize-1))		return PM_MTRR_ERR_OVERLAP;	    }	else if (base == lbase && size == lsize) {	    /* The region already exists so leave it alone */	    return PM_MTRR_ERR_OK;	    }	/* New region is enclosed by an existing region, so only allow	 * a new type to be created if we are setting a region to be	 * uncacheable (such as MMIO registers within a framebuffer).	 */	if (ltype != (int)type) {	    if (type == PM_MTRR_UNCACHABLE)		continue;	    return PM_MTRR_ERR_TYPE_MISMATCH;	    }	return PM_MTRR_ERR_OK;	}    /* Search for an empty MTRR */    if ((i = getFreeRegion(base,size)) < 0)	return PM_MTRR_ERR_NONE_FREE;    setMTRR(i,base,size,type);    return PM_MTRR_ERR_OK;}/****************************************************************************PARAMETERS:callback    - Function to callback with write combine informationREMARKS:Function to enumerate all write combine regions currently enabled for theprocessor.****************************************************************************/int PMAPI PM_enumWriteCombine(    PM_enumWriteCombine_t callback){    int     i,ltype;    ulong   lbase,lsize;    /* Check that we have a CPU that supports MTRR's and type is valid */    if (numMTRR <= 0) {	if (!_MTRR_isRing0())	    return PM_MTRR_ERR_NO_OS_SUPPORT;	return PM_MTRR_NOT_SUPPORTED;	}    /* Enumerate all existing MTRR's */    for (i = 0; i < numMTRR; ++i) {	getMTRR(i,&lbase,&lsize,&ltype);	callback(lbase,lsize,ltype);	}    return PM_MTRR_ERR_OK;}#endif

⌨️ 快捷键说明

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