📄 cachecw4011lib.c
字号:
/* cacheCW4011Lib.c - LSI CW4011 cache management library *//* Copyright 1997-2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * This file has been developed or significantly modified by the * MIPS Center of Excellence Dedicated Engineering Staff. * This notice is as per the MIPS Center of Excellence Master Partner * Agreement, do not remove this notice without checking first with * WR/Platforms MIPS Center of Excellence engineering management. *//*modification history--------------------01h,17may02,pes Before aborting cacheTextUpdate() on null pointer, check for ENTIRE_CACHE.01g,08may02,pes Add protection against null pointers, zero counts, and requests involving kseg1 in cacheXXXTextUpdate().01f,16jul01,ros add CofE comment01e,08jan98,dra Rewritten to support cacheEnable and cacheDisable.01d,07may97,dra Substantially rewritten (separate flush & invalidate).01c,22apr97,dra Now sets instMode and dataMode cache modes correctly.01b,25mar97,dra Updates to match CW4011 hardware.01a,21feb97,dra created, based on cacheCW4kLib.c*//*DESCRIPTIONThis library contains architecture-specific cache library functionsfor the LSI MIPS CW4011 architecture. ARCHITECTURE NOTESGeneral:The CW4011 cache is optional. If present, both the I and D caches canbe from 1K to 16K in size; each cache can be composed of one or twosets. With a single set, the cache is direct mapped. With two sets,the cache becomes two-way set associative. Each set can be 1K, 2K,4K, or 8K in size, however for two-way set associative cache layouts,both sets must be the same size.The data cache can operate in either writethrough or copyback mode,so support for flushing the cache is provided.For general information about caching, see the manual entry for cacheLib.INCLUDE FILES: cacheLib.hSEE ALSO: cacheCW4011ALib, cacheLib.I "LSI MiniRISC CW4011 Superscalar Microprocessor Core Technical Manual" *//* includes */#include "vxWorks.h"#include "cacheLib.h"#include "errnoLib.h"#include "intLib.h"#include "memLib.h"#include "stdlib.h"#include "errno.h"/* defines */#define CACHE_LINE_SIZE CACHE_CW4011_LINE_SIZE/* externals */IMPORT void _cw4011InvalidateAll (CACHE_TYPE cacheType, ULONG configBits);IMPORT void _cw4011Invalidate (ULONG configBits, ULONG cacheLineMask, ULONG startLine, ULONG numLines, ULONG startAdr, ULONG endAdr);IMPORT void _cw4011Flush (ULONG configBits, ULONG cacheLineMask, ULONG startLine, ULONG numLines);IMPORT void _cw4011FlushAndDisable (ULONG configBits);IMPORT ULONG _cw4011ConfigGet (void);IMPORT void _cw4011ConfigSet (ULONG);IMPORT ULONG cacheCW4011icacheSet0Size; /* BSP-specified */IMPORT ULONG cacheCW4011icacheSet1; /* BSP-specified */IMPORT ULONG cacheCW4011dcacheSet0Size; /* BSP-specified */IMPORT ULONG cacheCW4011dcacheSet1; /* BSP-specified *//* forward declarations */LOCAL STATUS cacheCW4011Enable (CACHE_TYPE cache);LOCAL STATUS cacheCW4011Disable (CACHE_TYPE cache);LOCAL void *cacheCW4011Malloc (size_t bytes);LOCAL STATUS cacheCW4011Free (void *pBuf);LOCAL STATUS cacheCW4011Clear (CACHE_TYPE cache, void *pVirtAdrs, size_t bytes);LOCAL STATUS cacheCW4011Flush (CACHE_TYPE cache, void *pVirtAdrs, size_t bytes);LOCAL STATUS cacheCW4011WriteBufferFlush (void);LOCAL STATUS cacheCW4011Invalidate (CACHE_TYPE cache, void *pVirtAdrs, size_t bytes);LOCAL void *cacheCW4011PhysToVirt (void *address);LOCAL void *cacheCW4011VirtToPhys (void *address);LOCAL STATUS cacheCW4011TextUpdate (void *address, size_t bytes);LOCAL ULONG cacheLineMaskGet (ULONG cacheSize);LOCAL ULONG cacheSizeDescGet (ULONG cacheSize);LOCAL void cacheAttributesGet (CACHE_TYPE cache, ULONG *pCacheSize, ULONG *pCacheLineMask, ULONG *pCacheEnableSetMask);/* locals */LOCAL ULONG icacheSize = 0; /* computed during init */LOCAL ULONG icacheLineMask = 0; /* " " " */LOCAL ULONG icacheEnableSetMask = 0; /* " " " */LOCAL ULONG dcacheSize = 0; /* " " " */LOCAL ULONG dcacheLineMask = 0; /* " " " */LOCAL ULONG dcacheEnableSetMask = 0; /* " " " *//**************************************************************************** cacheCW4011LibInit - initialize the LSI CW4011 cache library** This routine initializes the function pointers for the CW4011 cache* library. The board support package can select this cache library * by calling this routine. The caches are assumed to be disabled * when this routine is called, and are left disabled. cacheCW4011Enable* is used to actually enable the caches.** RETURNS: OK, or errors if the requested cache configuration is invalid.*/STATUS cacheCW4011LibInit ( CACHE_MODE instMode, /* instruction cache mode */ CACHE_MODE dataMode /* data cache mode */ ) { ULONG config; cacheLib.enableRtn = cacheCW4011Enable; /* cacheEnable() */ cacheLib.disableRtn = cacheCW4011Disable; /* cacheDisable() */ cacheLib.lockRtn = NULL; /* cacheLock */ cacheLib.unlockRtn = NULL; /* cacheUnlock */ cacheLib.flushRtn = cacheCW4011Flush; /* cacheFlush() */ cacheLib.pipeFlushRtn = cacheCW4011WriteBufferFlush;/*cachePipeFlush()*/ cacheLib.textUpdateRtn = cacheCW4011TextUpdate; /* cacheTextUpdate() */ cacheLib.invalidateRtn = cacheCW4011Invalidate; /* cacheInvalidate() */ cacheLib.clearRtn = cacheCW4011Clear; /* cacheClear() */ cacheLib.dmaMallocRtn = (FUNCPTR) cacheCW4011Malloc;/*cacheDmaMalloc()*/ cacheLib.dmaFreeRtn = cacheCW4011Free; /* cacheDmaFree() */ cacheLib.dmaVirtToPhysRtn = (FUNCPTR) cacheCW4011VirtToPhys; cacheLib.dmaPhysToVirtRtn = (FUNCPTR) cacheCW4011PhysToVirt; cacheDataMode = dataMode; /* save dataMode for enable */ cacheMmuAvailable = TRUE; /* mmu support is provided */ /* validate icache size and set request */ if ((cacheCW4011icacheSet0Size == 0) && cacheCW4011icacheSet1) { errno = S_cacheLib_CACHE_SET_SIZE_MISMATCH; return (ERROR); } icacheSize = cacheCW4011icacheSet0Size; icacheLineMask = cacheLineMaskGet (icacheSize); if (icacheSize && (icacheLineMask == 0)) { errno = S_cacheLib_INVALID_CACHE_LINE_SIZE; return (ERROR); } /* enable the icache only if requested */ if (instMode != CACHE_DISABLED) { icacheEnableSetMask = (cacheCW4011icacheSet0Size ? CCC_IE0 : 0) | (cacheCW4011icacheSet1 ? CCC_IE1 : 0); } /* validate provided dcache sizes, and compute useful constants */ if ((cacheCW4011dcacheSet0Size == 0) && cacheCW4011dcacheSet1) { errno = S_cacheLib_CACHE_SET_SIZE_MISMATCH; return (ERROR); } dcacheSize = cacheCW4011dcacheSet0Size; dcacheLineMask = cacheLineMaskGet (dcacheSize); if (dcacheSize && (dcacheLineMask == 0)) { errno = S_cacheLib_INVALID_CACHE_LINE_SIZE; return (ERROR); } /* enable the dcache only if requested */ if (dataMode != CACHE_DISABLED) { dcacheEnableSetMask = (cacheCW4011dcacheSet0Size ? CCC_DE0 : 0) | (cacheCW4011dcacheSet1 ? CCC_DE1 : 0); } /* set cacheDataEnabled TRUE in all cases, since this sets up the * appropriate pointers for the cache DMA malloc routines. */ cacheDataEnabled = TRUE; cacheFuncsSet (); /* set the cache configuration, leaving the caches disabled */ config = _cw4011ConfigGet (); config &= ~(CCC_ISIZE_MASK | CCC_DSIZE_MASK | CCC_WB); if (dcacheSize) config |= cacheSizeDescGet(dcacheSize) << CCC_DSIZE_LSHIFT; if (icacheSize) config |= cacheSizeDescGet(icacheSize) << CCC_ISIZE_LSHIFT; if (dataMode == CACHE_COPYBACK) config |= CCC_WB; _cw4011ConfigSet (config); /* invalidate the cache entries */ if (dcacheSize) _cw4011InvalidateAll (DATA_CACHE, dcacheEnableSetMask); if (icacheSize) _cw4011InvalidateAll (INSTRUCTION_CACHE, icacheEnableSetMask); return (OK); }/**************************************************************************** cacheCW4011Enable - enable the specificed cache.** cacheCW4011Enable is used to enable the instruction and data caches.** RETURNS: OK, or ERROR if the cache type is invalid.*/LOCAL STATUS cacheCW4011Enable ( CACHE_TYPE cache /* Cache to enable */ ) { int oldLevel; ULONG config; switch (cache) { case DATA_CACHE: oldLevel = intLock (); config = _cw4011ConfigGet (); if ((dcacheEnableSetMask == 0) || /* skip if nothing to enable */ (config & dcacheEnableSetMask)) /* skip if already enabled */ { intUnlock (oldLevel); return (OK); } /* cache disabled and known to be invalid; just enable it */ _cw4011ConfigSet (config | dcacheEnableSetMask); cacheDataEnabled = TRUE; /* d-cache is currently on */ cacheFuncsSet (); /* update cache func ptrs */ intUnlock (oldLevel); break; case INSTRUCTION_CACHE: oldLevel = intLock (); config = _cw4011ConfigGet (); if ((icacheEnableSetMask == 0) || /* skip if nothing to enable */ (config & icacheEnableSetMask)) /* skip if already enabled */ { intUnlock (oldLevel); return (OK); } /* cache disabled and known to be invalid; just enable it */ _cw4011ConfigSet (config | icacheEnableSetMask); intUnlock (oldLevel); break; default: errno = S_cacheLib_INVALID_CACHE; return (ERROR); } return (OK); }/**************************************************************************** cacheCW4011Disable - disable the specificed cache.** cacheCW4011Disable is used to disable the instruction and data caches.** RETURNS: OK, or ERROR if the cache type is invalid.*/LOCAL STATUS cacheCW4011Disable ( CACHE_TYPE cache /* Cache to disable */ ) { int oldLevel; ULONG config; ULONG dcacheDisableSetMask = CCC_DE0 | CCC_DE1; ULONG icacheDisableSetMask = CCC_IE0 | CCC_IE1; /* * Note that the xcacheEnableSetMask variables are not used for * disabling the caches. This is because while the caches may not * be enabled in the BSP, they still need to be disabled here. */ switch (cache) { case DATA_CACHE: oldLevel = intLock (); config = _cw4011ConfigGet (); if ((config & dcacheDisableSetMask) == 0) /* skip if disabled */ { intUnlock (oldLevel); return (OK); } /* atomically flush and disable cache if copyback is enabled */ if (config & CCC_WB) _cw4011FlushAndDisable (dcacheSize / CACHE_LINE_SIZE); else _cw4011ConfigSet (config & ~dcacheDisableSetMask); _cw4011InvalidateAll (DATA_CACHE, dcacheEnableSetMask); /* * At this point we would normally set cacheDataEnabled false, * and then call cacheFuncsSet() to update the cache pointers, * but problems have been observed with some ethernet drivers * if the cache "DMA malloc" routines are not used to allocate * buffers for MIPS. */ intUnlock (oldLevel); break; case INSTRUCTION_CACHE: oldLevel = intLock (); config = _cw4011ConfigGet (); if ((config & icacheDisableSetMask) == 0) /* skip if disabled */ { intUnlock (oldLevel); return (OK); } _cw4011ConfigSet (config & ~icacheDisableSetMask); _cw4011InvalidateAll (INSTRUCTION_CACHE, icacheEnableSetMask); intUnlock (oldLevel); break; default: errno = S_cacheLib_INVALID_CACHE; return (ERROR); } return (OK); }/**************************************************************************** cacheCW4011Clear - flush and invalidate all or some entries in a cache** This routine flushes and invalidates all or some of the entries in the* specified cache.** RETURNS: OK, or ERROR if an error occurs during the clear operation.*/LOCAL STATUS cacheCW4011Clear ( CACHE_TYPE cache, /* Cache to clear */ void * address, /* Virtual Address */ size_t bytes /* Number of Bytes to clear */ ) { ULONG oldLevel; STATUS status = OK; if (cache == INSTRUCTION_CACHE) status = cacheCW4011Invalidate (cache, address, bytes); else if (cache == DATA_CACHE) { if (bytes == ENTIRE_CACHE) { /* disable atomically flushes and invalidates the cache */ (void) cacheCW4011Disable (DATA_CACHE); (void) cacheCW4011Enable (DATA_CACHE); status = OK; } else { oldLevel = intLock(); status = cacheCW4011Flush (cache, address, bytes); if (status == OK) status = cacheCW4011Invalidate (cache, address, bytes); intUnlock (oldLevel); } } return (status); }/**************************************************************************** cacheCW4011Invalidate - invalidate all or some entries in a cache** This routine invalidates all or some of the entries in the* specified cache.** RETURNS: OK. Unsupported requests are silently ignored.**/LOCAL STATUS cacheCW4011Invalidate ( CACHE_TYPE cache, /* Cache to Invalidate */ void * address, /* Virtual Address */ size_t bytes /* Number of Bytes to Invalidate */ ) { ULONG line; ULONG end; ULONG numLines; ULONG firstByte; ULONG lastByte; ULONG cacheSize; ULONG cacheLineMask; ULONG cacheEnableSetMask; /* silently ignore regions which aren't cacheable or are empty */ if (IS_KSEG1(address) || (bytes == 0)) return (OK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -