⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmu.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
<module>
 * Name         : mmu.c
 * Title        : MMU Management
 * Author(s)    : Imagination Technologies
 * Created      : 14 May 2003
 *
 * Copyright    : 2003 by Imagination Technologies Limited.
 *                All rights reserved.  No part of this software, either
 *                material or conceptual may be copied or distributed,
 *                transmitted, transcribed, stored in a retrieval system
 *                or translated into any human or computer language in any
 *                form by any means, electronic, mechanical, manual or
 *                other-wise, or disclosed to third parties without the
 *                express written permission of Imagination Technologies
 *                Limited, Unit 8, HomePark Industrial Estate,
 *                King's Langley, Hertfordshire, WD4 8LZ, U.K.
 *
 * Description  : Implements basic low level control of MMU.
 *
 * Platform     : ALL
 *
</module>
*/

#include "services_headers.h"
#include "buffer_manager.h"
#include "dual_page.h"
#include "hash.h"
#include "ra.h"
#include "hw.h"
#include "mmu.h"
#include "mmu_flush.h"
#include "pool.h"
#include "env.h"

/* determine the page table register offset */
#define ptr_offset(dev_vaddr) \
  ((dev_vaddr.uiAddr>>(DEV_PAGE_SHIFT+MBX_MMU_TT_SHIFT))&((1<<MBX_MMU_PTR_SHIFT)-1))

/* determine the page table entry */
#define pte_offset(dev_vaddr) \
  ((dev_vaddr.uiAddr >> DEV_PAGE_SHIFT) & ((1<<MBX_MMU_TT_SHIFT)-1))

struct _MMU_
{
    IMG_CPU_VIRTADDR aPageTableCpuVAddr [MBX_MMU_PTRS];
    IMG_CPU_PHYADDR aPageTableCpuPAddr [MBX_MMU_PTRS];
    
    struct device_tag *pDev;

    /* Resource allocation arenas for address ranges in the device virtual
     * address space. For devices which impose different
     * address range criteria depending on the use of the buffer, we
     * maintain two allocation arenas, one for low addresses, the other
     * for high addresses, selection between the two is controlled by the
     * presence of the BP_HI_MEMORY allocation flags.
     */

    RA_ARENA *pVmaArena;
    RA_ARENA *pVmaHiArena;
    MMU_FLUSH pFlush;
    enum _MMU_FLUSH_MECHANISM_
    {
        FM_TLB_RELOAD,
#if defined (FIX_HW_PRN_63)
        FM_2D_FLUSH
#endif
    } eFlushMechanism;

    /* Dummy page referenced by unused page table entries */
    IMG_CPU_VIRTADDR DummyPageCpuVAddr;
    IMG_CPU_PHYADDR DummyPageCpuPAddr;

    /* dual page pager for allocating contrigous working memory */
    DP_PAGER *pPager;

    /* The MMU is currently enabled or disabled */
    IMG_BOOL bEnabled;
};

static IMG_UINT32
aPageRegisterOffset [] =
{
    MBX1_GLOBREG_MMU_PAGE0_ADDR,
    MBX1_GLOBREG_MMU_PAGE1_ADDR,
    MBX1_GLOBREG_MMU_PAGE2_ADDR,
    MBX1_GLOBREG_MMU_PAGE3_ADDR,
    MBX1_GLOBREG_MMU_PAGE4_ADDR,
    MBX1_GLOBREG_MMU_PAGE5_ADDR,
    MBX1_GLOBREG_MMU_PAGE6_ADDR,
    MBX1_GLOBREG_MMU_PAGE7_ADDR
};

/* todo: boilerplate */
static void
_EnableSpinWait (struct device_tag *pDev)
{
    IMG_UINT32 uIterations = 0;
    while ((HW_ReadReg (pDev, MBX1_GLOBREG_MMU_ENABLE) & MMU_READY_MASK) == 0)
        uIterations++;
    PVR_DPF ((PVR_DBG_MESSAGE,
	      "_EnableSpinWait() iterations=%u", uIterations));
}

/* todo: boilerplate */
static void
DisableSpinWait (struct device_tag *pDev)
{
    IMG_UINT32 uIterations = 0;
    while ((HW_ReadReg (pDev, MBX1_GLOBREG_MMU_ENABLE) & MMU_READY_MASK) != 0)
        uIterations++;
    PVR_DPF ((PVR_DBG_MESSAGE,
	      "DisableSpinWait() iterations=%d", uIterations));
}

/*----------------------------------------------------------------------------
<function>
    FUNCTION:   _FreePageTables

    PURPOSE:    Free the page tables associated with an MMU.

    PARAMETERS: In:  pMMU - the mmu
    RETURNS:    None
</function>
-----------------------------------------------------------------------------*/
static void
_FreePageTables (MMU *pMMU)
{
    IMG_UINT32 uPtn;
    for (uPtn=0; uPtn<MBX_MMU_PTRS; uPtn++)
    {
        if (pMMU->aPageTableCpuVAddr[uPtn] != IMG_NULL)
            DP_FreeContiguous (pMMU->pPager,
                               0,
                               pMMU->aPageTableCpuPAddr [uPtn]);
    }
    DP_FreeContiguous (pMMU->pPager, 0, pMMU->DummyPageCpuPAddr);
}

/*----------------------------------------------------------------------------
<function>
    FUNCTION:   _AllocPageTables

    PURPOSE:    Allocate page tables for an MMU.

    PARAMETERS: In:  pMMU - the mmu
    RETURNS:    IMG_TRUE - Success
                IMG_FALSE - Failed
</function>
-----------------------------------------------------------------------------*/
static IMG_BOOL
_AllocPageTables (MMU *pMMU)
{
    IMG_UINT32 uPtn;
    IMG_DEV_PHYADDR DummyPageDevPAddr;

    PVR_DPF ((PVR_DBG_MESSAGE, "_AllocPageTables()"));

    PVR_ASSERT (pMMU!=IMG_NULL);
    PVR_ASSERT (HOST_PAGESIZE() == DEV_PAGE_SIZE);
    
    for (uPtn=0; uPtn<MBX_MMU_PTRS; uPtn++)
   	{
        pMMU->aPageTableCpuVAddr[uPtn] = IMG_NULL;
	}
	
    if (!DP_AllocContiguous (pMMU->pPager,
                             0,
                             DEV_PAGE_SIZE,
                             IMG_NULL,
                             DEV_PAGE_SIZE,
                             &pMMU->DummyPageCpuVAddr,
                             &pMMU->DummyPageCpuPAddr))
    {
    	PVR_DPF((PVR_DBG_ERROR, "_AllocPageTables: ERROR call to DP_AllocContiguous failed"));	
    	return IMG_FALSE;
    }
       
    PVR_DPF ((PVR_DBG_MESSAGE, "mmu: dummy page cpu_paddr = 0x%x",
            pMMU->DummyPageCpuPAddr.uiAddr));
    
    DummyPageDevPAddr = ENV_CpuPAddrToDevPAddr (pMMU->DummyPageCpuPAddr);
    
    for (uPtn=0; uPtn<MBX_MMU_PTRS; uPtn++)
    {
        IMG_DEV_PHYADDR DevPAddr;
        IMG_CPU_PHYADDR CpuPAddr;
        IMG_UINT32 uOffset;

        if (!DP_AllocContiguous (pMMU->pPager,
                                 0,
                                 MBX_MMU_TT_ENTRIES << 2,
                                 IMG_NULL,
                                 DEV_PAGE_SIZE,
                                 &pMMU->aPageTableCpuVAddr[uPtn],
                                 &pMMU->aPageTableCpuPAddr[uPtn]))
      	{      		
      		PVR_DPF((PVR_DBG_ERROR, "_AllocPageTables: ERROR call to DP_AllocContiguous failed"));
      		_FreePageTables(pMMU);   /* This will also cleanup pMMU->DummyPageCpuVAddr */
      		return IMG_FALSE;
       	}	
            
        CpuPAddr = pMMU->aPageTableCpuPAddr[uPtn];
        DevPAddr = ENV_CpuPAddrToDevPAddr (CpuPAddr);
        PVR_DPF ((PVR_DBG_MESSAGE, "  ptn=%d  dp=0x%x cp=0x%x",
                uPtn, DevPAddr.uiAddr, CpuPAddr.uiAddr));
        HW_WriteReg (pMMU->pDev, aPageRegisterOffset[uPtn], DevPAddr.uiAddr);

        /* TODO: pdump missing */
        /* Point all entries at the dummy page */
        for (uOffset=0; uOffset<MBX_MMU_TT_ENTRIES; uOffset++)
        {
            volatile IMG_UINTPTR_T *pt = pMMU->aPageTableCpuVAddr[uPtn];
            pt[uOffset] = DummyPageDevPAddr.uiAddr;
        }
    }

    return IMG_TRUE;
}


/*----------------------------------------------------------------------------
<function>
    FUNCTION:   MMU_Initialise

    PURPOSE:    Initialise the mmu module.

    PARAMETERS: None
    RETURNS:    IMG_TRUE Success
                IMG_FALSE Failed
</function>
-----------------------------------------------------------------------------*/
IMG_BOOL
MMU_Initialise (void)
{
    PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Initialise ()"));
    return IMG_TRUE;
}

/*----------------------------------------------------------------------------
<function>
    FUNCTION:   MMU_Finalise

    PURPOSE:    Finalise the mmu module, deallocate all resources.

    PARAMETERS: None.
    RETURNS:    None.
</function>
-----------------------------------------------------------------------------*/
void
MMU_Finalise (void)
{
    PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Finalise ()"));
}

/*----------------------------------------------------------------------------
<function>
    FUNCTION:   MMU_Create

    PURPOSE:    Create an mmu device.

    PARAMETERS: In: pDev -
                In: pRAState - 
                In: pPager - dual pager pager for working space allocation.
    RETURNS:
</function>
-----------------------------------------------------------------------------*/
MMU *
MMU_Create (struct device_tag *pDev,
            RA_STATE *pRAState,
            DP_PAGER *pPager)
{
    MMU *pMMU;
    IMG_BOOL bRes;
    IMG_SIZE_T uMmuHiArenaSize;

    PVR_ASSERT (pDev!=IMG_NULL);
    PVR_ASSERT (pRAState!=IMG_NULL);

    PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Create (0x%x)", pDev));
    HostAllocMem( PVRSRV_HOST_PAGEABLE_HEAP, 
                  sizeof (*pMMU), 
                  (IMG_VOID **)&pMMU,  0);                      
    if (pMMU == IMG_NULL)
    {
    	PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to HostAllocMem failed"));
    	return IMG_NULL;
    }
     
    pMMU->bEnabled = IMG_FALSE;
    pMMU->pDev = pDev;
    pMMU->pPager = pPager;
    pMMU->eFlushMechanism = FM_TLB_RELOAD;
    
#if defined (FIX_HW_PRN_63)
    /* For some broken hardware we should be using the 2d flush mechanism, but
       fpga images omit the 2D core, in this situation we resort to
       the standard flush mechanism and an optimistic outlook */
        pMMU->eFlushMechanism = FM_2D_FLUSH;
#endif

    bRes = _AllocPageTables (pMMU);
    if (!bRes)
    {
    	PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to _AllocPageTables failed"));
    	HostFreeMem (PVRSRV_HOST_PAGEABLE_HEAP, pMMU);	
    	return IMG_NULL;
	}

	/* Create the arena */	
    pMMU->pVmaArena = RA_Create (pRAState,
                                 "mmu vma",
                                 MMU_ARENA_BASE,
                                 MMU_ARENA_SIZE,
                                 DEV_PAGE_SIZE,
                                 IMG_NULL,
                                 IMG_NULL,
                                 IMG_NULL);
    if (pMMU->pVmaArena == IMG_NULL)
    {
    	PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to RA_Create failed"));
	    _FreePageTables (pMMU);
	    HostFreeMem (PVRSRV_HOST_PAGEABLE_HEAP, pMMU);
	    return IMG_NULL;
    }

    uMmuHiArenaSize = MMU_HI_ARENA_SIZE;
    pMMU->pVmaHiArena = IMG_NULL;
    if (uMmuHiArenaSize>0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -