/* * Memory map * When paddr is NULL, allocate len bytes of memory having contiguous physical address, * and returns the logical address to *laddr. * When paddr is not NULL, map len bytes of physical memory from paddr and returns * the logical address to *laddr. * * N.B. Access to *laddr may cause page fault. */ LOCAL ER _MapMemory( CONST void *paddr, INT len, UINT attr, void **laddr ) { ER ercd; UINT a; if ( len <= 0 ) { ercd = E_PAR; goto err_ret; } a = ( (attr & MM_USER) != 0 )? TA_RNG3: TA_RNG0; if ( (attr & MM_CDIS) != 0 ) { a |= TA_NOCACHE; } if ( paddr == NULL ) { /* Allocate memory automatically */ *laddr = GetSysMemBlk((INT)smPageCount((UW)len), a); if ( *laddr == NULL ) { ercd = E_NOMEM; goto err_ret; } /* Set memory access privilege */ ercd = _SetMemoryAccess(*laddr, len, (attr & (MM_READ|MM_WRITE|MM_EXECUTE))); if ( ercd < E_OK ) { RelSysMemBlk(*laddr); *laddr = NULL; goto err_ret; } } else { /* Logical address conversion */ *laddr = toLogicalAddress(paddr); /* Flush cache */ FlushCache(*laddr, len); if ( (attr & MM_CDIS) != 0 ) { /* Allocate logical addresses for cache off area */ *laddr = toNoCacheLogicalAddress(*laddr); } } return E_OK; err_ret: #ifdef DEBUG TM_DEBUG_PRINT(("_MapMemory ercd = %d\n", ercd)); #endif return ercd; }
/* * Free memory * It may be called during interrupt disable. In this case, need to wait * until interrupt is enabled and until free. */ LOCAL void ifree( void *ptr, IMACB *imacb ) { QUEUE *aq; UW imask; DI(imask); /* Exclusive control by interrupt disable */ SpinLock(&MemLockObj); aq = (QUEUE*)ptr - 1; clrAreaFlag(aq, AREA_USE); if ( !chkAreaFlag(aq->next, AREA_END|AREA_USE) ) { /* Merge with free area in after location */ removeFreeQue(aq->next + 1); removeAreaQue(aq->next); } if ( !chkAreaFlag(aq, AREA_TOP) && !chkAreaFlag(aq->prev, AREA_USE) ) { /* Merge with free area in front location */ aq = aq->prev; removeFreeQue(aq + 1); removeAreaQue(aq->next); } /* If the whole page is free, then free the page. * However, do not free the page if it is called during * interrupt disabled. */ if ( !isDI(imask) && chkAreaFlag(aq, AREA_TOP) && chkAreaFlag(aq->next, AREA_END) ) { /* Free pages */ removeAreaQue(aq->next); removeAreaQue(aq); SpinUnlock(&MemLockObj); EI(imask); RelSysMemBlk(aq); DI(imask); SpinLock(&MemLockObj); } else { /* Register free area to FreeQue */ appendFreeArea(aq, imacb); } SpinUnlock(&MemLockObj); EI(imask); }
/* * Memory unmap */ LOCAL ER _UnmapMemory( VP laddr ) { ER ercd; /* Memory release when memory is allocated automatically by MapMemory() * If the memory is not automatically allocated, RelSysMemBlk() * returns E_PAR. */ ercd = RelSysMemBlk(laddr); if ( ercd < E_OK && ercd != E_PAR ) { goto err_ret; } return E_OK; err_ret: DEBUG_PRINT(("_UnmapMemory ercd = %d\n", ercd)); return ercd; }