📄 mmu.c
字号:
{
pMMU->pVmaHiArena = RA_Create ( pRAState,
"mmu vma hi",
MMU_HI_ARENA_BASE, uMmuHiArenaSize, DEV_PAGE_SIZE,
IMG_NULL, IMG_NULL, IMG_NULL);
if (pMMU->pVmaHiArena==IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to RA_Create failed"));
RA_Delete (pMMU->pVmaArena);
_FreePageTables (pMMU);
HostFreeMem (PVRSRV_HOST_PAGEABLE_HEAP, pMMU);
return IMG_NULL;
}
}
bRes = MMUFLUSH_Create (pMMU, &(pMMU->pFlush), pPager);
if (!bRes)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to MMUFLUSH_Create failed"));
if (pMMU->pVmaHiArena)
RA_Delete (pMMU->pVmaHiArena);
RA_Delete (pMMU->pVmaArena);
_FreePageTables (pMMU);
HostFreeMem (PVRSRV_HOST_PAGEABLE_HEAP, pMMU);
return IMG_NULL;
}
return pMMU;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: MMU_Delete
PURPOSE: Delete an MMU device.
PARAMETERS: In: pMMU - The MMU to delete.
RETURNS:
</function>
-----------------------------------------------------------------------------*/
void
MMU_Delete (MMU *pMMU)
{
if (pMMU != IMG_NULL)
{
PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Delete ()"));
MMUFLUSH_Delete (pMMU, &(pMMU->pFlush), pMMU->pPager);
RA_Delete (pMMU->pVmaHiArena);
RA_Delete (pMMU->pVmaArena);
_FreePageTables (pMMU);
HostFreeMem (PVRSRV_HOST_PAGEABLE_HEAP, pMMU);
}
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: MMU_Alloc
PURPOSE: Allocate space in an mmu's virtual address space.
PARAMETERS: In: pMMU - MMU to allocate on.
In: uSize - Size in bytes to allocate.
Out: pActualSize - If non null receives actual size allocated.
In: uFlags - Allocation flags.
In: uDevVAddrAlignment - Required alignment.
Out: DevVAddr - Receives base address of allocation.
RETURNS: IMG_TRUE - Success
IMG_FALSE - Failure
</function>
-----------------------------------------------------------------------------*/
IMG_BOOL
MMU_Alloc (MMU *pMMU,
IMG_SIZE_T uSize,
IMG_SIZE_T *pActualSize,
IMG_UINT32 uFlags,
IMG_UINT32 uDevVAddrAlignment,
IMG_DEV_VIRTADDR *DevVAddr)
{
RA_ARENA *pArena;
PVR_DPF ((PVR_DBG_MESSAGE,
"MMU_Alloc (uSize=0x%x, flags=0x%x, align=0x%x)",
uSize, uFlags, uDevVAddrAlignment));
if ((uFlags & BP_HI_MEMORY) && (MMU_HI_ARENA_SIZE>0))
pArena = pMMU->pVmaHiArena;
else
pArena = pMMU->pVmaArena;
return RA_Alloc (pArena, uSize, pActualSize, IMG_NULL, 0,
uDevVAddrAlignment, 0, &(DevVAddr->uiAddr));
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: MMU_Free
PURPOSE: Free space in an mmu's virtual address space.
PARAMETERS: In: pMMU - MMU to deallocate on.
In: DevVAddr - Base address to deallocate.
RETURNS: None
</function>
-----------------------------------------------------------------------------*/
void
MMU_Free (MMU *pMMU, IMG_DEV_VIRTADDR DevVAddr)
{
PVR_ASSERT (pMMU != IMG_NULL);
PVR_DPF ((PVR_DBG_MESSAGE,
"MMU_Free (mmu=0x%x, dev_vaddr=0x%lx)", pMMU, DevVAddr.uiAddr));
if (MMU_HI_ARENA_SIZE!=0 && DevVAddr.uiAddr>=MMU_HI_ARENA_BASE)
RA_Free (pMMU->pVmaHiArena, DevVAddr.uiAddr, IMG_NULL);
else
RA_Free (pMMU->pVmaArena, DevVAddr.uiAddr, IMG_NULL);
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: MMU_Enable
PURPOSE: Enable an mmu. Establishes pages tables and takes the mmu out
of bypass and waits for the mmu to acknowledge enabled.
PARAMETERS: In: pMMU - the mmu
RETURNS: None
</function>
-----------------------------------------------------------------------------*/
void
MMU_Enable (MMU *pMMU)
{
IMG_UINT32 uStatus;
PVR_ASSERT (pMMU != IMG_NULL);
PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Enable ()"));
uStatus = HW_ReadReg (pMMU->pDev, MBX1_GLOBREG_MMU_ENABLE);
if ((uStatus & MMU_ENABLE_MASK) == MMU_ENABLE_MASK)
{
PVR_DPF ((PVR_DBG_MESSAGE,
"MMU: MMU is *ALREADY* enabled! <<<<<<<<<<<<<<<<<"));
}
HW_ModifyReg (pMMU->pDev, MBX1_GLOBREG_MMU_ENABLE, MMU_ENABLE_MASK, 0);
DisableSpinWait (pMMU->pDev);
HW_ModifyReg (pMMU->pDev, MBX1_GLOBREG_MMU_ENABLE, MMU_ENABLE_MASK, 1);
/* spin, on the status port */
_EnableSpinWait (pMMU->pDev);
pMMU->bEnabled = IMG_TRUE;
PVR_DPF ((PVR_DBG_MESSAGE,
"MMU_Enable () XXXXX MMU IS NOW ENABLED XXXXX"));
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: MMU_Disable
PURPOSE: Disable an mmu, takes the mmu into bypass.
PARAMETERS: In: pMMU - the mmu
RETURNS: None
</function>
-----------------------------------------------------------------------------*/
void
MMU_Disable (MMU *pMMU)
{
PVR_ASSERT (pMMU != IMG_NULL);
PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Disable ()"));
HW_ModifyReg (pMMU->pDev, MBX1_GLOBREG_MMU_ENABLE, MMU_ENABLE_MASK, 0);
DisableSpinWait (pMMU->pDev);
pMMU->bEnabled = IMG_FALSE;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: MMU_MapPages
PURPOSE: Create a linear mapping for a ranege of pages at a specified
virtual address.
PARAMETERS: In: pMMU - the mmu.
In: dev_vaddr - the device virtual address.
In: dev_paddr - the device physical address of the page to
map.
In: uSize - size of memory range in bytes
RETURNS: None
</function>
-----------------------------------------------------------------------------*/
void
MMU_MapPages (MMU *pMMU,
IMG_DEV_VIRTADDR DevVAddr,
IMG_DEV_PHYADDR DevPAddr,
IMG_SIZE_T uSize)
{
IMG_UINT32 uCount;
PVR_ASSERT (pMMU != IMG_NULL);
PVR_DPF ((PVR_DBG_MESSAGE,
"MMU_MapPages (mmu=0x%x,devVAddr=0x%x,devPAddr=0x%x,size=0x%x)",
pMMU, DevVAddr.uiAddr, DevPAddr.uiAddr, uSize));
for (uCount=0; uCount<uSize; uCount+=DEV_PAGE_SIZE)
{
MMU_MapPage (pMMU, DevVAddr, DevPAddr);
DevVAddr.uiAddr += DEV_PAGE_SIZE;
DevPAddr.uiAddr += DEV_PAGE_SIZE;
}
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: MMU_MapPage
PURPOSE: Create a mapping for one page at a specified virtual address.
PARAMETERS: In: pMMU - the mmu.
In: DevVAddr - the device virtual address.
In: DevPAddr - the device physical address of the page to map.
RETURNS: None
</function>
-----------------------------------------------------------------------------*/
void
MMU_MapPage (MMU *pMMU,
IMG_DEV_VIRTADDR DevVAddr,
IMG_DEV_PHYADDR DevPAddr)
{
volatile IMG_UINTPTR_T *pt;
PVR_ASSERT (pMMU != IMG_NULL);
#if 0
/* This trace generates *alot* of output, hence normally it's turned off */
PVR_DPF ((PVR_DBG_MESSAGE,
"MMU_MapPage (dv=0x%lx, dp=0x%lx) ptr=%d pte=%d pt=0x%x",
DevVAddr, DevPAddr.uiAddr,
ptr_offset (DevVAddr),
pte_offset (DevVAddr),
pMMU->page_table[ptr_offset (DevVAddr)]));
#endif
pt = pMMU->aPageTableCpuVAddr [ptr_offset (DevVAddr)];
pt [pte_offset (DevVAddr)] = DevPAddr.uiAddr;
if (pMMU->bEnabled)
{
/* with hardware support for tlb_reload we flush the tlb cache by
* forcing reload of tlbs when an address is mapped
*/
switch (pMMU->eFlushMechanism)
{
case FM_TLB_RELOAD:
/* we have not been told to flush, but it is easier to do it here */
MMUFLUSH_TLBReload (pMMU->pDev, DevVAddr, DevPAddr);
break;
#if defined (FIX_HW_PRN_63)
case FM_2D_FLUSH:
/* handle flushing in the usual way, ie when we are told to flush */
break;
#endif
}
}
#ifdef STUB
env_notify_mmu_map (DevVAddr, DevPAddr);
#endif
}
/* todo: boilerplate */
void
MMU_FlushRange (MMU *pMMU,
IMG_DEV_VIRTADDR DevVAddr,
IMG_SIZE_T uSize)
{
switch (pMMU->eFlushMechanism)
{
case FM_TLB_RELOAD:
/* the cache is flushed during page mapping when using this mechanism */
break;
#if defined (FIX_HW_PRN_63)
case FM_2D_FLUSH:
MMUFLUSH_Range (pMMU->pDev, DevVAddr, uSize, &(pMMU->pFlush));
break;
#endif
}
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: MMU_HaveHiArena
PURPOSE: Query if a high allocation arena is present.
PARAMETERS: In: pMMU - the mmu
RETURNS: IMG_TRUE - Present.
IMG_FALSE - Not present.
</function>
-----------------------------------------------------------------------------*/
IMG_BOOL
MMU_HaveHiArena (MMU *pMMU)
{
PVR_ASSERT (pMMU != IMG_NULL);
PVR_DPF ((PVR_DBG_MESSAGE,
"MMU_HaveHiArena () = %d", MMU_HI_ARENA_SIZE>0));
UNREFERENCED_PARAMETER (pMMU);
if (MMU_HI_ARENA_SIZE > 0)
{
return IMG_TRUE;
}
else
{
return IMG_FALSE;
}
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: MMU_LowArenaVAddrRange
PURPOSE: Query the device virtual address range for the low arena.
PARAMETERS: In: pMMU - the mmu
RETURNS: size in bytes
</function>
-----------------------------------------------------------------------------*/
IMG_SIZE_T
MMU_LowArenaVAddrRange (MMU *pMMU)
{
PVR_ASSERT (pMMU != IMG_NULL);
return MMU_ARENA_SIZE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -