/* * Get memory */ LOCAL void* imalloc( size_t size, IMACB *imacb ) { QUEUE *q; VP mem; UW imask; /* If it is smaller than the minimum fragment size, allocate the minimum size to it. */ if ( size < MIN_FRAGMENT ) { size = MIN_FRAGMENT; } size = ROUND(size); DI(imask); /* Exclusive control by interrupt disable */ SpinLock(&MemLockObj); /* Search FreeQue */ q = searchFreeArea(size, imacb); if ( q != &imacb->freeque ) { /* There is free area: Split from FreeQue once */ removeFreeQue(q); q = q - 1; } else { /* Reserve new pages because there is no free space */ QUEUE *e; size_t n; /* Reserve pages */ SpinUnlock(&MemLockObj); EI(imask); n = PageCount(size + sizeof(QUEUE) * 2); q = GetSysMemBlk(n, imacb->mematr); if ( q == NULL ) { goto err_ret; /* Insufficient memory */ } DI(imask); SpinLock(&MemLockObj); /* Register on AreaQue */ e = (QUEUE*)((VB*)q + n * pagesz) - 1; insertAreaQue(&imacb->areaque, e); insertAreaQue(&imacb->areaque, q); setAreaFlag(q, AREA_TOP); setAreaFlag(e, AREA_END); } /* Allocate memory */ mem = mem_alloc(q, size, imacb); SpinUnlock(&MemLockObj); EI(imask); return mem; err_ret: BMS_DEBUG_PRINT(("imalloc error\n")); return NULL; }
/* * 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; }
/* * Memory map * Cache control required, but cache control by page cannot be * provided without MMU (except for certain machines), so not implemented. */ LOCAL ER _MapMemory( VP paddr, INT len, UINT attr, VP *laddr ) { ER ercd; if ( len <= 0 ) { ercd = E_PAR; goto err_ret; } if ( paddr == NULL ) { UINT a = ( (attr & MM_USER) != 0 )? TA_RNG3: TA_RNGS; if ( (attr & MM_CDIS) != 0 ) { a |= TA_NOCACHE; } /* Allocate memory automatically */ *laddr = GetSysMemBlk((INT)smPageCount((UW)len), a); if ( *laddr == NULL ) { ercd = E_NOMEM; 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: DEBUG_PRINT(("_MapMemory ercd = %d\n", ercd)); return ercd; }