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

📄 dual_buffer.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- c-file-style: "img" -*-
<module>
* Name         : dual_buffer.c
* Title        : Dual Space Buffer Management.
* Author       : Marcus Shawcroft
* 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 :  Manages buffers mapped into two virtual memory spaces,
*                cpu and device.
* 
* Platform     : ALL
*
</module>
********************************************************************************/
#include "services_headers.h"
#include "buffer_manager.h"
#include "hash.h"
#include "ra.h"
#include "dual_buffer.h"
#include "dual_page.h"
#include "hash.h"
#include "pool.h"
#include "hw.h"

struct _DB_STATE_
{
	/* Resource allocation arena of dual mapped pages. For devices
       where the hardware imposes different constraints on the valid
       device virtual address range depending on the use of the buffer
       we maintain two allocation arenas, one low address range, the
       other high. For devices without such a constrain we do not
       create the high arena, instead all allocations come from the
       low arena. */
	RA_ARENA *pDualPageArena;
	RA_ARENA *pDualPageHiArena;

	struct device_tag device;
	DP_PAGER *pDualPager;
    HASH_TABLE *pDualPageHash;
	POOL *pMemBufPool;

	HASH_STATE *pHashState;
	RA_STATE *pRAState;
	DP_STATE *pDPState;
};

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

	PURPOSE:    Allocate a buffer mapped into both cpu and device virtual
	            address spaces. 
	            
	PARAMETERS:	In:  pDBState - dual buffer state (from DB_Initialise())
	            In:  size - requested buffer size in bytes.
	            In:  buffer_props - property flags for the buffer.
	            In:  uDevVAddrAlignment - required device virtual address
	                 alignment, or 0.
	            Out: pBuf - receives a pointer to a descriptor of the allocated
	                 buffer.
	RETURNS:	IMG_TRUE - Success
	            IMG_FALSE - Failed.
</function>
-----------------------------------------------------------------------------*/
static IMG_BOOL
AllocMemory (DB_STATE *pDBState,
             IMG_SIZE_T uSize,
             IMG_UINT32 uFlags,
             IMG_UINT32 uDevVAddrAlignment,
             BM_BUF *pBuf)
{
	IMG_DEV_VIRTADDR DevVAddr = {0};
	DP_MAPPING *pMapping;
	IMG_UINTPTR_T uOffset;

	PVR_ASSERT (pDBState != IMG_NULL);
	PVR_ASSERT (pBuf != IMG_NULL);

	PVR_DPF ((PVR_DBG_MESSAGE,
              "dual_buffer:AllocMemory (pDBState=0x%x, uSize=0x%lx, uFlags=0x%x, align=0x%x, pBuf=0x%x)",
              pDBState, uSize, uFlags, uDevVAddrAlignment, pBuf));

	uSize = HOST_PAGEALIGN (uSize);

	/* if there is no pDualPageArena then all allocations are taken
	   from the contiguous memory pool, this happens when there is no
	   hardware MMU support */
	if (pDBState->pDualPageArena == IMG_NULL || (uFlags & BP_CONTIGUOUS))
	{
		IMG_BOOL bResult;
		
		pBuf->pArena = IMG_NULL;
		bResult = DP_Alloc (pDBState->pDualPager,
                            uSize,
                            IMG_NULL, 
                            (void*) &pMapping,
                            uFlags,
                            uDevVAddrAlignment,
                            &(DevVAddr.uiAddr));
		if (!bResult) 
		{
			PVR_DPF((PVR_DBG_ERROR, "AllocMemory: ERROR DP_Alloc FAILED"));
			return bResult;
	}
	}
	else
	{
		if ((uFlags & BP_HI_MEMORY) && DP_HaveHiArena (pDBState->pDualPager))
			pBuf->pArena = pDBState->pDualPageHiArena;
		else
			pBuf->pArena = pDBState->pDualPageArena;
		if (!RA_Alloc (pBuf->pArena,
                       uSize,
                       IMG_NULL,
                       (void*) &pMapping,
                       uFlags,
                       uDevVAddrAlignment,
                       0,
                       &(DevVAddr.uiAddr))) 
		{
			PVR_DPF((PVR_DBG_ERROR, "AllocMemory: ERROR RA_Alloc FAILED"));
			return IMG_FALSE;
		}
	}

	/* determine the offset of this allocation within the underlying
	   dual mapped chunk of memory, we can assume that all three
	   addresses associated with this allocation are placed at the same
	   offset within the underlying chunk. */
	uOffset = DevVAddr.uiAddr - pMapping->DevVAddr.uiAddr;

	pBuf->pRef = pMapping;
	if (pMapping->CpuPAddr.uiAddr==0)
		pBuf->CpuPAddr.uiAddr = 0;
	else
		pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;
	pBuf->CpuVAddr = (void*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + uOffset);
	pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr + uOffset;

	PVR_DPF ((PVR_DBG_MESSAGE,
              "dual_buffer:AllocMemory () = (hv=0x%lx  dv=0x%lx	hp=0x%lx)",
              pBuf->CpuVAddr, pBuf->DevVAddr.uiAddr, pBuf->CpuPAddr.uiAddr));
	return IMG_TRUE;
}

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

	PURPOSE:    Allocate a buffer mapped into both cpu and device virtual
	            address spaces. 
	            
	PARAMETERS:	In:  pDBState - dual buffer state (from DB_Initialise())
	            In:  base - address of memory to wrap
	            In:  uSize - requested buffer size in bytes.
	            In:  uBufferProps - property flags for the buffer.
	            In:  uDevVAddrAlignment - required device virtual address
	                 alignment, or 0.
	            Out: pBuf - receives a pointer to a descriptor of the allocated
	                 buffer.
	RETURNS:	IMG_TRUE - Success
	            IMG_FALSE - Failed.
</function>
-----------------------------------------------------------------------------*/
static IMG_BOOL
WrapMemory (DB_STATE *pDBState,
			IMG_SYS_PHYADDR base,
			IMG_SIZE_T uSize,
			IMG_UINT32 uFlags,
			IMG_UINT32 uDevVAddrAlignment,
			BM_BUF *pBuf)
{
	IMG_DEV_VIRTADDR DevVAddr = {0};
	DP_MAPPING *pMapping;
	IMG_UINTPTR_T uOffset;
	IMG_BOOL bResult;

	PVR_DPF ((PVR_DBG_MESSAGE,
              "dual_buffer:WrapMemory(base=0x%x, uSize=0x%x)", base, uSize));

	PVR_ASSERT (pBuf != IMG_NULL);

#if 0
	IMG_SIZE_T uBaseOffset = 0;
	/* we may have been asked to wrap non page aligned memory, we
	   force the wrap to be page aligned by rounding base down to the
	   nearest page and increasing size by the corresponding
	   amount. The rounding offset will be added back into each of the
	   wrapped buffer addresses. */
	
	uBaseOffset = base.uiAddr & (HOST_PAGE_SIZE - 1);
	base.addr -= uBaseOffset;
	uSize += uBaseOffset;
#endif
	
	uSize = HOST_PAGEALIGN (uSize);

	pBuf->pArena = IMG_NULL;
	bResult = DP_Wrap (pDBState->pDualPager,
					  base,
					  uSize,
					  IMG_NULL,
					  (void*) &pMapping,
					  uFlags,
					  uDevVAddrAlignment,
					  &(DevVAddr.uiAddr));
	if (!bResult) return IMG_FALSE;

	/* determine the offset of this allocation within the underlying
	   dual mapped chunk of memory, we can assume that all three
	   addresses associated with this allocation are placed at the same
	   offset within the underlying chunk. */
	uOffset = DevVAddr.uiAddr - pMapping->DevVAddr.uiAddr;

	pBuf->pRef = pMapping;
	if (pMapping->CpuPAddr.uiAddr==0)
		pBuf->CpuPAddr.uiAddr = 0;
	else
		pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;
	pBuf->CpuVAddr = (void*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + uOffset);
	pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr + uOffset;

	return IMG_TRUE;
}

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

	PURPOSE:    To initialise the dual buffer module, must be called before
	            any other function within dual buffer.
	            
	PARAMETERS:	In:  pRegisters - cpu virtual address for the device registers.
			In:  pSlaveports - cpu virtual address for the device slaveports 
	            Out: ppState - receives the dual buffer state
	RETURNS:	IMG_TRUE - success
	            IMG_FALSE - failed
</function>
-----------------------------------------------------------------------------*/
IMG_BOOL
DB_Initialise (	IMG_CPU_VIRTADDR pRegisters, 
				IMG_CPU_VIRTADDR pSlavePorts,
				IMG_UINT32       ui32CoreConfig,
				DB_STATE **ppState)
{
	DB_STATE *pDBState = IMG_NULL;
	
	PVR_DPF ((PVR_DBG_MESSAGE,
              "DB_Initialise (registers=0x%x)", pRegisters));

	PVR_ASSERT (ppState!=IMG_NULL);

	if (HostAllocMem (PVRSRV_HOST_PAGEABLE_HEAP, 
                      sizeof (*pDBState), 
                      (IMG_VOID **)&pDBState, 
                      0) != PVRSRV_OK)
	{
		goto cleanup;
	}
	
	HostMemSet (pDBState, 0, sizeof (DB_STATE));

	HW_Define (&pDBState->device, pRegisters, pSlavePorts, ui32CoreConfig);

	if (!HASH_Initialise (&pDBState->pHashState)) 
		goto cleanup;
	if (!RA_Initialise (pDBState->pHashState, &pDBState->pRAState)) 
		goto cleanup;
	if (!DP_Initialise (pDBState->pRAState, &pDBState->pDPState)) 
		goto cleanup;

	pDBState->pMemBufPool = POOL_Create ("mem_buf", sizeof (BM_BUF));
	if (pDBState->pMemBufPool==IMG_NULL) goto cleanup;

	pDBState->pDualPageHash = HASH_Create (pDBState->pHashState, 32);
	if (pDBState->pDualPageHash==IMG_NULL) goto cleanup;

	pDBState->pDualPager = DP_Create (pDBState->pDPState, &pDBState->device);
	if (pDBState->pDualPager==IMG_NULL) goto cleanup;

	/* if we have MMU hardware then we create arenas to manage mapped
	 * memory
	 */
	if (pDBState->device.bHaveMMU && (SysMMUMode () == SYS_MMU_NORMAL))
	{
		pDBState->pDualPageArena = RA_Create (pDBState->pRAState, 
                                               "dual page", 0, 0, 
                                               HOST_PAGESIZE(),
                                               DP_AllocMany, 
                                               DP_Free, 
                                               pDBState->pDualPager);

⌨️ 快捷键说明

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