📄 cachesh7729lib.c
字号:
*/LOCAL STATUS cacheSh7729Invalidate ( CACHE_TYPE cache, void * from, size_t bytes ) { if (bytes == ENTIRE_CACHE) { UINT32 ccr = cacheSh7729CCRGet (); if ((ccr & (CCR_WRITE_BACK_P1 | CCR_WRITE_THRU)) == CCR_WRITE_THRU) { cacheSh7729CFlush (); return OK; } } return cacheSh7729Clear (cache, from, bytes); }/******************************************************************************** cacheSh7729Clear - clear all or some entries from a SH7729 cache** This routine flushes and invalidates all or some entries of the specified* SH7729 cache.** RETURNS: OK, or ERROR if the cache type is invalid or the cache control* is not supported.** NOMANUAL*/LOCAL STATUS cacheSh7729Clear ( CACHE_TYPE cache, void * from, /* address to clear */ size_t bytes ) { UINT32 p = (UINT32)from; UINT32 ix; UINT32 c_size; /* cache size */ int way, lastway; if (p >= SH7700_P2_BASE && p <= (SH7700_P2_BASE | SH7700_PHYS_MASK)) return ERROR; /* P2 non-cacheable */ else if (p >= SH7700_P4_BASE) return ERROR; /* P4 non-cacheable */ c_size = CAC_DATA_SIZE; lastway = 3; if (bytes == 0) { return OK; } else if (bytes == ENTIRE_CACHE) { for (way = 0; way <= lastway; way++) { if ((way == 2 && (ccr2 & CCR2_LOCK_WAY2)) || (way == 3 && (ccr2 & CCR2_LOCK_WAY3))) { continue; /* skip locked way */ } for (ix = 0; ix <= 0xff0; ix += CAC_LINE_SIZE) { UINT32 *pt = (UINT32 *)(CAC_ADRS_ARRAY | (way << 12) | ix); cacheSh7729MFlush (pt, -1, 0, 0); } } } else { UINT32 ca_begin = p & ~(CAC_LINE_SIZE - 1); UINT32 ca_end = p + bytes - 1; if (bytes < c_size) /* do associative purge */ { cacheSh7729AFlush (ca_begin, ca_end); } else /* check every cache tag */ { for (way = 0; way <= lastway; way++) { for (ix = 0; ix <= 0xff0; ix += CAC_LINE_SIZE) { UINT32 *pt = (UINT32 *)(CAC_ADRS_ARRAY | (way << 12) | ix); cacheSh7729MFlush (pt, ix, ca_begin, ca_end); } } } } return OK; }/******************************************************************************** cacheSh7729DmaMalloc - allocate a cache-safe buffer** This routine attempts to return a pointer to a section of memory that will* not experience cache coherency problems. This routine is only called when* MMU support is available for cache control.** INTERNAL* We check if the cache is actually on before allocating the memory. It is* possible that the user wants Memory Management Unit (MMU) support but does* not need caching.** RETURNS: A pointer to a cache-safe buffer, or NULL.** NOMANUAL*/LOCAL void *cacheSh7729DmaMalloc ( size_t bytes ) { void *pBuf; int pageSize; if (cacheDataEnabled == FALSE) return malloc (bytes); /* cache is off just allocate buffer */ if ((pageSize = VM_PAGE_SIZE_GET ()) == ERROR) return NULL; /* make sure bytes is a multiple of pageSize */ bytes = bytes / pageSize * pageSize + pageSize; if (_func_valloc == NULL || (pBuf = (void *)(*_func_valloc)(bytes)) == NULL) return NULL; VM_STATE_SET (NULL, pBuf, bytes, VM_STATE_MASK_CACHEABLE, VM_STATE_CACHEABLE_NOT); return pBuf; }/******************************************************************************** cacheSh7729DmaFree - free the buffer acquired by cacheSh7729DmaMalloc()** This routine returns to the free memory pool a block of memory previously* allocated with cacheSh7729DmaMalloc(). The buffer is marked cacheable.** RETURNS: OK, or ERROR if cacheSh7729DmaMalloc() cannot be undone.** NOMANUAL*/LOCAL STATUS cacheSh7729DmaFree ( void *pBuf ) { STATUS status = OK; if (cacheDataEnabled) { BLOCK_HDR *pHdr = BLOCK_TO_HDR (pBuf); status = VM_STATE_SET (NULL, pBuf, (pHdr->nWords * 2) - sizeof(BLOCK_HDR), VM_STATE_MASK_CACHEABLE, VM_STATE_CACHEABLE); } free (pBuf); return status; }/******************************************************************************** cacheSh7729P2DmaMalloc - allocate a cache-safe buffer from P2 region** This routine attempts to return a pointer to a section of memory that will* not experience cache coherency problems. This routine may be called when* MMU support is NOT available for cache control.** RETURNS: A pointer to a cache-safe buffer, or NULL.** NOMANUAL*/LOCAL void *cacheSh7729P2DmaMalloc ( size_t bytes ) { void *pBuf; int alignment = VM_PAGE_SIZE_GET (); if (alignment != ERROR && _func_valloc != NULL) { /* adjust bytes to a multiple of MMU page size */ bytes = bytes / alignment * alignment + alignment; /* get a page aligned memory */ if ((pBuf = (void *)(*_func_valloc)(bytes)) == NULL) return NULL; /* mark it as non-cacheable, non-writable on virtual space */ VM_STATE_SET (NULL, pBuf, bytes, VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE, VM_STATE_WRITABLE_NOT | VM_STATE_CACHEABLE_NOT); } else { /* adjust bytes to a multiple of cache line length */ alignment = _CACHE_ALIGN_SIZE; bytes = bytes / alignment * alignment + alignment; /* use memalign() to avoid sharing a cache-line with other buffers */ if ((pBuf = memalign (alignment, bytes)) == NULL) return NULL; } /* make sure nothing in pBuf is cached on cacheable region */ if (cacheLib.flushRtn != NULL) cacheLib.flushRtn (DATA_CACHE, pBuf, bytes); /* relocate the buffer to P2 (mmu-bypass, non-cacheable) region */ return (void *)(((UINT32)pBuf & SH7700_PHYS_MASK) | SH7700_P2_BASE); }/******************************************************************************** cacheSh7729P2DmaFree - free the buffer acquired by cacheSh7729P2DmaMalloc()** This routine returns to the free memory pool a block of memory previously* allocated with cacheSh7729P2DmaMalloc().** RETURNS: OK, or ERROR if cacheSh7729DmaMalloc() cannot be undone.** NOMANUAL*/LOCAL STATUS cacheSh7729P2DmaFree ( void *pBuf ) { STATUS status = OK; UINT32 p = (UINT32)pBuf; if (p < SH7700_P2_BASE || p > (SH7700_P2_BASE | SH7700_PHYS_MASK)) return ERROR; if (cacheDataMode & CACHE_DMA_BYPASS_P0) p = p & SH7700_PHYS_MASK; /* relocate to P0 */ else if (cacheDataMode & CACHE_DMA_BYPASS_P1) p = (p & SH7700_PHYS_MASK) | SH7700_P1_BASE; /* relocate to P1 */ else if (cacheDataMode & CACHE_DMA_BYPASS_P3) p = (p & SH7700_PHYS_MASK) | SH7700_P3_BASE; /* relocate to P3 */ else return ERROR; if (VM_PAGE_SIZE_GET () != ERROR && _func_valloc != NULL) { BLOCK_HDR *pHdr = BLOCK_TO_HDR ((void *)p); status = VM_STATE_SET (NULL, (void *)p, (pHdr->nWords * 2) - sizeof(BLOCK_HDR), VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE, VM_STATE_WRITABLE | VM_STATE_CACHEABLE); } free ((void *)p); return status; }#undef CACHE_DEBUG#ifdef CACHE_DEBUG#include "stdio.h"LOCAL UINT32 va[1024][5]; /* (256-entry * 4-way) * (tag[1] + data[4]) *//******************************************************************************** cacheSh7729Dump - dump SH7729 cache** NOMANUAL*/LOCAL int partition (UINT32 a[][5], int l, int r) { int i, j, pivot; UINT32 t; i = l - 1; j = r; pivot = a[r][0]; for (;;) { while (a[++i][0] < pivot) ; while (i < --j && pivot < a[j][0]) ; if (i >= j) break; t = a[i][0]; a[i][0] = a[j][0]; a[j][0] = t; t = a[i][1]; a[i][1] = a[j][1]; a[j][1] = t; t = a[i][2]; a[i][2] = a[j][2]; a[j][2] = t; t = a[i][3]; a[i][3] = a[j][3]; a[j][3] = t; t = a[i][4]; a[i][4] = a[j][4]; a[j][4] = t; } t = a[i][0]; a[i][0] = a[r][0]; a[r][0] = t; t = a[i][1]; a[i][1] = a[r][1]; a[r][1] = t; t = a[i][2]; a[i][2] = a[r][2]; a[r][2] = t; t = a[i][3]; a[i][3] = a[r][3]; a[r][3] = t; t = a[i][4]; a[i][4] = a[r][4]; a[r][4] = t; return i; }LOCAL void quick_sort_1 (UINT32 a[][5], int l, int r) { int v; if (l >= r) return; v = partition (a, l, r); quick_sort_1 (a, l, v - 1); /* sort left partial array */ quick_sort_1 (a, v + 1, r); /* sort right partial array */ }LOCAL void quick_sort (UINT32 a[][5], int n) { quick_sort_1 (a, 0, n - 1); }LOCAL void cacheSh7729DumpOp (UINT32 a[][5], UINT32 ccr) { int ent, i; for (ent = 0; ent < 256; ent++) { int way; int lastway = 3; for (way = 0; way <= lastway; way++) { UINT32 tag = *(UINT32 *)(CAC_ADRS_ARRAY | (way << 12) | (ent << 4)); i = ent * 4 + way; a[i][0] = (tag & 0xfffffc03) |((ent & 0x3f)<<4) |((ent & 0xc0)>>4); a[i][1] = *(UINT32 *)(0xf1000000 | (way << 12) | (ent << 4)); a[i][2] = *(UINT32 *)(0xf1000004 | (way << 12) | (ent << 4)); a[i][3] = *(UINT32 *)(0xf1000008 | (way << 12) | (ent << 4)); a[i][4] = *(UINT32 *)(0xf100000c | (way << 12) | (ent << 4)); } } }LOCAL void cacheSh7729Disp (UINT32 a[][5], UINT32 ccr) { int i; int lines = 1024; /* cache lines */ quick_sort (a, lines); for (i = 0; i < lines; i++) { UINT32 b10 = (a[i][0] & 0xc) << 8; /* MSB of entry selector */ printf ("0x%08x: %08x %08x %08x %08x %s %s %s\n", a[i][0] & 0xfffffff0, a[i][1], a[i][2], a[i][3], a[i][4], (a[i][0] & 0xc00) ^ b10 ? "!" : " ", a[i][0] & 0x2 ? "U+" : "U-", a[i][0] & 0x1 ? "V+" : "V-"); } }void cacheSh7729ClearTest (int addr, int bytes) { UINT32 ccr = cacheSh7729CCRGet (); int key = intLock (); /* LOCK INTERRUPTS */ if ((ccr & (CCR_WRITE_BACK_P1 | CCR_WRITE_THRU)) == CCR_WRITE_THRU) { cacheSh7729CCRSet (ccr & ~CCR_CACHE_ENABLE); /* disable caching */ cacheSh7729Clear (INSTRUCTION_CACHE, (void *)addr, bytes); cacheSh7729DumpOp (va, ccr); cacheSh7729CCRSet (ccr); /* restore ccr */ intUnlock (key); /* UNLOCK INTERRUPTS */ cacheSh7729Disp (va, ccr); } else { UINT32 pDumpRtn = ((UINT32)cacheSh7729DumpOp & SH7700_PHYS_MASK) | SH7700_P2_BASE; UINT32 (*a)[1024][5] = (UINT32(*)[1024][5])(((UINT32)va & SH7700_PHYS_MASK)| SH7700_P2_BASE); cacheSh7729Clear (INSTRUCTION_CACHE, (void *)addr, bytes); (* (VOIDFUNCPTR)pDumpRtn)(*a, ccr); intUnlock (key); /* UNLOCK INTERRUPTS */ cacheSh7729Disp (*a, ccr); } }void cacheSh7729ClearTestAll () { cacheSh7729ClearTest (0, ENTIRE_CACHE); }void cacheSh7729Dump () { cacheSh7729ClearTest (0, 0); }STATUS cacheSh7729LockTest (int way, int from, int bytes) { STATUS status = ERROR; switch (way) { case 2: status = cacheSh7729Lock (WAY2_CACHE, (void *)from, bytes); break; case 3: status = cacheSh7729Lock (WAY3_CACHE, (void *)from, bytes); break; } return status; }STATUS cacheSh7729UnlockTest (int way) { STATUS status = ERROR; switch (way) { case 2: status = cacheSh7729Unlock (WAY2_CACHE, NULL, 0); break; case 3: status = cacheSh7729Unlock (WAY3_CACHE, NULL, 0); break; } return status; }#endif /* CACHE_DEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -