Example #1
0
static IMG_BOOL
AllocMemory (BM_CONTEXT				*pBMContext,
				BM_HEAP				*psBMHeap,
				IMG_DEV_VIRTADDR	*psDevVAddr,
				IMG_SIZE_T			uSize,
				IMG_UINT32			uFlags,
				IMG_UINT32			uDevVAddrAlignment,
				BM_BUF				*pBuf)
{
	BM_MAPPING			*pMapping;
	IMG_UINTPTR_T		uOffset;
	RA_ARENA			*pArena = IMG_NULL;

	PVR_DPF ((PVR_DBG_MESSAGE,
			  "AllocMemory (uSize=0x%x, uFlags=0x%x, align=0x%x)",
			  uSize, uFlags, uDevVAddrAlignment));

	


	if(uFlags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
	{
		if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
		{
			
			PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: combination of DevVAddr management and RAM backing mode unsupported"));
			return IMG_FALSE;
		}

		

		
		if(psBMHeap->ui32Attribs
		   &	(PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
		   |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
		{
			
			pArena = psBMHeap->pImportArena;
			PVR_ASSERT(psBMHeap->sDevArena.psDeviceMemoryHeapInfo->ui32Attribs & PVRSRV_MEM_RAM_BACKED_ALLOCATION);
		}
		else
		{
			PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: backing store type doesn't match heap"));
			return IMG_FALSE;
		}

		
		if (!RA_Alloc(pArena,
					  uSize,
					  IMG_NULL,
					  (IMG_VOID*) &pMapping,
					  uFlags,
					  uDevVAddrAlignment,
					  0,
					  (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr)))
		{
			PVR_DPF((PVR_DBG_ERROR, "AllocMemory: RA_Alloc(0x%x) FAILED", uSize));
			return IMG_FALSE;
		}

		uOffset = pBuf->DevVAddr.uiAddr - pMapping->DevVAddr.uiAddr;
		if(pMapping->CpuVAddr)
		{
			pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + uOffset);
		}
		else
		{
			pBuf->CpuVAddr = IMG_NULL;
		}

		if(uSize == pMapping->uSize)
		{
			pBuf->hOSMemHandle = pMapping->hOSMemHandle;
		}
		else
		{
			if(OSGetSubMemHandle(pMapping->hOSMemHandle,
								 uOffset,
								 uSize,
								 psBMHeap->ui32Attribs,
								 &pBuf->hOSMemHandle)!=PVRSRV_OK)
			{
				PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSGetSubMemHandle FAILED"));
				return IMG_FALSE;
			}
		}

		
		pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;

		if(uFlags & PVRSRV_MEM_ZERO)
		{
			if(!ZeroBuf(pBuf, pMapping, uSize, psBMHeap->ui32Attribs | uFlags))
			{
				return IMG_FALSE;
			}
		}
	}
	else
	{
		if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
		{
			
			PVR_ASSERT(psDevVAddr != IMG_NULL);

			if (psDevVAddr == IMG_NULL)
			{
				PVR_DPF((PVR_DBG_ERROR, "AllocMemory: invalid parameter - psDevVAddr"));
				return IMG_FALSE;
			}

			
			pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
													uSize,
													IMG_NULL,
													PVRSRV_MEM_USER_SUPPLIED_DEVVADDR,
													uDevVAddrAlignment,
													psDevVAddr);

			
			pBuf->DevVAddr = *psDevVAddr;
		}
		else
		{
			

			
			pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
													uSize,
													IMG_NULL,
													0,
													uDevVAddrAlignment,
													&pBuf->DevVAddr);
		}

		
		if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
							sizeof (struct _BM_MAPPING_),
							(IMG_PVOID *)&pMapping, IMG_NULL,
							"Buffer Manager Mapping") != PVRSRV_OK)
		{
			PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSAllocMem(0x%x) FAILED", sizeof(*pMapping)));
			return IMG_FALSE;
		}

		
		pBuf->CpuVAddr = IMG_NULL;
		pBuf->hOSMemHandle = 0;
		pBuf->CpuPAddr.uiAddr = 0;

		
		pMapping->CpuVAddr = IMG_NULL;
		pMapping->CpuPAddr.uiAddr = 0;
		pMapping->DevVAddr = pBuf->DevVAddr;
		pMapping->psSysAddr = IMG_NULL;
		pMapping->uSize = uSize;
		pMapping->hOSMemHandle = 0;
	}

	
	pMapping->pArena = pArena;

	
	pMapping->pBMHeap = psBMHeap;
	pBuf->pMapping = pMapping;

	
	PVR_DPF ((PVR_DBG_MESSAGE,
				"AllocMemory: pMapping=%08x: DevV=%08X CpuV=%08x CpuP=%08X uSize=0x%x",
				(IMG_UINTPTR_T)pMapping,
				pMapping->DevVAddr.uiAddr,
				(IMG_UINTPTR_T)pMapping->CpuVAddr,
				pMapping->CpuPAddr.uiAddr,
				pMapping->uSize));

	PVR_DPF ((PVR_DBG_MESSAGE,
				"AllocMemory: pBuf=%08x: DevV=%08X CpuV=%08x CpuP=%08X uSize=0x%x",
				(IMG_UINTPTR_T)pBuf,
				pBuf->DevVAddr.uiAddr,
				(IMG_UINTPTR_T)pBuf->CpuVAddr,
				pBuf->CpuPAddr.uiAddr,
				uSize));

	
	PVR_ASSERT(((pBuf->DevVAddr.uiAddr) & (uDevVAddrAlignment - 1)) == 0);

	return IMG_TRUE;
}
static IMG_BOOL AllocMemory(struct BM_CONTEXT *pBMContext,
		struct BM_HEAP *psBMHeap, struct IMG_DEV_VIRTADDR *psDevVAddr,
		size_t uSize, u32 uFlags, u32 uDevVAddrAlignment,
		struct BM_BUF *pBuf)
{
	struct BM_MAPPING *pMapping;
	u32 uOffset;
	struct RA_ARENA *pArena = NULL;

	PVR_DPF(PVR_DBG_MESSAGE, "AllocMemory "
			"(pBMContext=%08X, uSize=0x%x, uFlags=0x%x, "
			"align=0x%x, pBuf=%08X)",
		 pBMContext, uSize, uFlags, uDevVAddrAlignment, pBuf);

	if (uFlags & PVRSRV_MEM_RAM_BACKED_ALLOCATION) {
		if (uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) {
			PVR_DPF(PVR_DBG_ERROR, "AllocMemory: "
				"combination of DevVAddr management and "
				"RAM backing mode unsupported");
			return IMG_FALSE;
		}

		if (psBMHeap->ui32Attribs &
		    (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG |
		     PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)) {
			pArena = psBMHeap->pImportArena;
		} else {
			PVR_DPF(PVR_DBG_ERROR, "AllocMemory: "
				"backing store type doesn't match heap");
			return IMG_FALSE;
		}

		if (!RA_Alloc(pArena, uSize, (void *)&pMapping, uFlags,
			      uDevVAddrAlignment,
			      (u32 *)&(pBuf->DevVAddr.uiAddr))) {
			PVR_DPF(PVR_DBG_ERROR,
				 "AllocMemory: RA_Alloc(0x%x) FAILED", uSize);
			return IMG_FALSE;
		}

		uOffset = pBuf->DevVAddr.uiAddr - pMapping->DevVAddr.uiAddr;
		if (pMapping->CpuVAddr) {
			pBuf->CpuVAddr =
			    (void *)((u32) pMapping->CpuVAddr + uOffset);
		} else {
			pBuf->CpuVAddr = NULL;
		}

		if (uSize == pMapping->uSize) {
			pBuf->hOSMemHandle = pMapping->hOSMemHandle;
		} else {
			if (OSGetSubMemHandle(pMapping->hOSMemHandle, uOffset,
					uSize, psBMHeap->ui32Attribs,
					&pBuf->hOSMemHandle) != PVRSRV_OK) {
				PVR_DPF(PVR_DBG_ERROR, "AllocMemory: "
						"OSGetSubMemHandle FAILED");
				return IMG_FALSE;
			}
		}

		pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;

		if (uFlags & PVRSRV_MEM_ZERO)
			if (!ZeroBuf(pBuf, pMapping, uSize,
				     psBMHeap->ui32Attribs | uFlags))
				return IMG_FALSE;
	} else {
		if (uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) {
			PVR_ASSERT(psDevVAddr != NULL);

			if (psDevVAddr == NULL) {
				PVR_DPF(PVR_DBG_ERROR, "AllocMemory: "
					"invalid parameter - psDevVAddr");
				return IMG_FALSE;
			}

			pBMContext->psDeviceNode->pfnMMUAlloc(
					      psBMHeap->pMMUHeap, uSize,
					      PVRSRV_MEM_USER_SUPPLIED_DEVVADDR,
					      uDevVAddrAlignment, psDevVAddr);
			pBuf->DevVAddr = *psDevVAddr;
		} else {
			pBMContext->psDeviceNode->pfnMMUAlloc(psBMHeap->
							     pMMUHeap, uSize, 0,
							     uDevVAddrAlignment,
							     &pBuf->DevVAddr);
		}

		if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
			       sizeof(struct BM_MAPPING),
			       (void **)&pMapping, NULL) != PVRSRV_OK) {
			PVR_DPF(PVR_DBG_ERROR,
				 "AllocMemory: OSAllocMem(0x%x) FAILED");
			return IMG_FALSE;
		}

		pBuf->CpuVAddr = NULL;
		pBuf->hOSMemHandle = NULL;
		pBuf->CpuPAddr.uiAddr = 0;

		pMapping->CpuVAddr = NULL;
		pMapping->CpuPAddr.uiAddr = 0;
		pMapping->DevVAddr = pBuf->DevVAddr;
		pMapping->psSysAddr = NULL;
		pMapping->uSize = uSize;
		pMapping->hOSMemHandle = NULL;
	}

	pMapping->pArena = pArena;

	pMapping->pBMHeap = psBMHeap;
	pBuf->pMapping = pMapping;

	PVR_DPF(PVR_DBG_MESSAGE, "AllocMemory: "
		"pMapping=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
		 pMapping, pMapping->DevVAddr.uiAddr, pMapping->CpuVAddr,
		 pMapping->CpuPAddr.uiAddr, pMapping->uSize);

	PVR_DPF(PVR_DBG_MESSAGE, "AllocMemory: "
		 "pBuf=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
		 pBuf, pBuf->DevVAddr.uiAddr, pBuf->CpuVAddr,
		 pBuf->CpuPAddr.uiAddr, uSize);

	PVR_ASSERT(((pBuf->DevVAddr.uiAddr) & (uDevVAddrAlignment - 1)) == 0);

	return IMG_TRUE;
}
Example #3
0
static IMG_BOOL
WrapMemory (BM_HEAP *psBMHeap,
			IMG_SIZE_T uSize,
			IMG_SIZE_T ui32BaseOffset,
			IMG_BOOL bPhysContig,
			IMG_SYS_PHYADDR *psAddr,
			IMG_VOID *pvCPUVAddr,
			IMG_UINT32 uFlags,
			BM_BUF *pBuf)
{
	IMG_DEV_VIRTADDR DevVAddr = {0};
	BM_MAPPING *pMapping;
	IMG_BOOL bResult;
	IMG_SIZE_T const ui32PageSize = HOST_PAGESIZE();

	PVR_DPF ((PVR_DBG_MESSAGE,
			  "WrapMemory(psBMHeap=%08X, size=0x%x, offset=0x%x, bPhysContig=0x%x, pvCPUVAddr = 0x%08x, flags=0x%x)",
			  (IMG_UINTPTR_T)psBMHeap, uSize, ui32BaseOffset, bPhysContig, (IMG_UINTPTR_T)pvCPUVAddr, uFlags));

	PVR_ASSERT((psAddr->uiAddr & (ui32PageSize - 1)) == 0);

	PVR_ASSERT(((IMG_UINTPTR_T)pvCPUVAddr & (ui32PageSize - 1)) == 0);

	uSize += ui32BaseOffset;
	uSize = HOST_PAGEALIGN (uSize);

	
	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
						sizeof(*pMapping),
						(IMG_PVOID *)&pMapping, IMG_NULL,
						"Mocked-up mapping") != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSAllocMem(0x%x) FAILED",sizeof(*pMapping)));
		return IMG_FALSE;
	}

	OSMemSet(pMapping, 0, sizeof (*pMapping));

	pMapping->uSize = uSize;
	pMapping->pBMHeap = psBMHeap;

	if(pvCPUVAddr)
	{
		pMapping->CpuVAddr = pvCPUVAddr;

		if (bPhysContig)
		{
			pMapping->eCpuMemoryOrigin = hm_wrapped_virtaddr;
			pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);

			if(OSRegisterMem(pMapping->CpuPAddr,
							pMapping->CpuVAddr,
							pMapping->uSize,
							uFlags,
							&pMapping->hOSMemHandle) != PVRSRV_OK)
			{
				PVR_DPF((PVR_DBG_ERROR,	"WrapMemory: OSRegisterMem Phys=0x%08X, Size=%d) failed",
					pMapping->CpuPAddr.uiAddr, pMapping->uSize));
				goto fail_cleanup;
			}
		}
		else
		{
			pMapping->eCpuMemoryOrigin = hm_wrapped_scatter_virtaddr;
			pMapping->psSysAddr = psAddr;

			if(OSRegisterDiscontigMem(pMapping->psSysAddr,
							pMapping->CpuVAddr,
							pMapping->uSize,
							uFlags,
							&pMapping->hOSMemHandle) != PVRSRV_OK)
			{
				PVR_DPF((PVR_DBG_ERROR,	"WrapMemory: OSRegisterDiscontigMem Size=%d) failed",
					pMapping->uSize));
				goto fail_cleanup;
			}
		}
	}
	else
	{
		if (bPhysContig)
		{
			pMapping->eCpuMemoryOrigin = hm_wrapped;
			pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);

			if(OSReservePhys(pMapping->CpuPAddr,
							 pMapping->uSize,
							 uFlags,
							 &pMapping->CpuVAddr,
							 &pMapping->hOSMemHandle) != PVRSRV_OK)
			{
				PVR_DPF((PVR_DBG_ERROR,	"WrapMemory: OSReservePhys Phys=0x%08X, Size=%d) failed",
					pMapping->CpuPAddr.uiAddr, pMapping->uSize));
				goto fail_cleanup;
			}
		}
		else
		{
			pMapping->eCpuMemoryOrigin = hm_wrapped_scatter;
			pMapping->psSysAddr = psAddr;

			if(OSReserveDiscontigPhys(pMapping->psSysAddr,
							 pMapping->uSize,
							 uFlags,
							 &pMapping->CpuVAddr,
							 &pMapping->hOSMemHandle) != PVRSRV_OK)
			{
				PVR_DPF((PVR_DBG_ERROR,	"WrapMemory: OSReserveDiscontigPhys Size=%d) failed",
					pMapping->uSize));
				goto fail_cleanup;
			}
		}
	}

	
	bResult = DevMemoryAlloc(psBMHeap->pBMContext,
							 pMapping,
							 IMG_NULL,
							 uFlags | PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
							 IMG_CAST_TO_DEVVADDR_UINT(ui32PageSize),
							 &DevVAddr);
	if (!bResult)
	{
		PVR_DPF((PVR_DBG_ERROR,
				"WrapMemory: DevMemoryAlloc(0x%x) failed",
				pMapping->uSize));
		goto fail_cleanup;
	}

	
	pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + ui32BaseOffset;
	if(!ui32BaseOffset)
	{
		pBuf->hOSMemHandle = pMapping->hOSMemHandle;
	}
	else
	{
		if(OSGetSubMemHandle(pMapping->hOSMemHandle,
							 ui32BaseOffset,
							 (pMapping->uSize-ui32BaseOffset),
							 uFlags,
							 &pBuf->hOSMemHandle)!=PVRSRV_OK)
		{
			PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSGetSubMemHandle failed"));
			goto fail_cleanup;
		}
	}
	if(pMapping->CpuVAddr)
	{
		pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + ui32BaseOffset);
	}
	pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr + IMG_CAST_TO_DEVVADDR_UINT(ui32BaseOffset);

	if(uFlags & PVRSRV_MEM_ZERO)
	{
		if(!ZeroBuf(pBuf, pMapping, uSize, uFlags))
		{
			return IMG_FALSE;
		}
	}

	PVR_DPF ((PVR_DBG_MESSAGE, "DevVaddr.uiAddr=%08X", DevVAddr.uiAddr));
	PVR_DPF ((PVR_DBG_MESSAGE,
				"WrapMemory: DevV=%08X CpuP=%08X uSize=0x%x",
				pMapping->DevVAddr.uiAddr, pMapping->CpuPAddr.uiAddr, pMapping->uSize));
	PVR_DPF ((PVR_DBG_MESSAGE,
				"WrapMemory: DevV=%08X CpuP=%08X uSize=0x%x",
				pBuf->DevVAddr.uiAddr, pBuf->CpuPAddr.uiAddr, uSize));

	pBuf->pMapping = pMapping;
	return IMG_TRUE;

fail_cleanup:
	if(ui32BaseOffset && pBuf->hOSMemHandle)
	{
		OSReleaseSubMemHandle(pBuf->hOSMemHandle, uFlags);
	}

	if(pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
	{
		switch(pMapping->eCpuMemoryOrigin)
		{
			case hm_wrapped:
				OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
				break;
			case hm_wrapped_virtaddr:
				OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
				break;
			case hm_wrapped_scatter:
				OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
				break;
			case hm_wrapped_scatter_virtaddr:
				OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
				break;
			default:
				break;
		}

	}

	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
	

	return IMG_FALSE;
}
static IMG_BOOL WrapMemory(struct BM_HEAP *psBMHeap,
	   size_t uSize, u32 ui32BaseOffset, IMG_BOOL bPhysContig,
	   struct IMG_SYS_PHYADDR *psAddr, void *pvCPUVAddr, u32 uFlags,
	   struct BM_BUF *pBuf)
{
	struct IMG_DEV_VIRTADDR DevVAddr = { 0 };
	struct BM_MAPPING *pMapping;
	IMG_BOOL bResult;
	u32 const ui32PageSize = HOST_PAGESIZE();

	PVR_DPF(PVR_DBG_MESSAGE,
		 "WrapMemory(psBMHeap=%08X, size=0x%x, offset=0x%x, "
		 "bPhysContig=0x%x, pvCPUVAddr = 0x%x, flags=0x%x, pBuf=%08X)",
		 psBMHeap, uSize, ui32BaseOffset, bPhysContig, pvCPUVAddr,
		 uFlags, pBuf);

	PVR_ASSERT((psAddr->uiAddr & (ui32PageSize - 1)) == 0);

	PVR_ASSERT(((u32) pvCPUVAddr & (ui32PageSize - 1)) == 0);

	uSize += ui32BaseOffset;
	uSize = HOST_PAGEALIGN(uSize);

	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*pMapping),
		       (void **)&pMapping, NULL) != PVRSRV_OK) {
		PVR_DPF(PVR_DBG_ERROR, "WrapMemory: OSAllocMem(0x%x) FAILED",
			 sizeof(*pMapping));
		return IMG_FALSE;
	}

	OSMemSet(pMapping, 0, sizeof(*pMapping));

	pMapping->uSize = uSize;
	pMapping->pBMHeap = psBMHeap;

	if (pvCPUVAddr) {
		pMapping->CpuVAddr = pvCPUVAddr;

		if (bPhysContig) {
			pMapping->eCpuMemoryOrigin = hm_wrapped_virtaddr;
			pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);

			if (OSRegisterMem(pMapping->CpuPAddr,
					pMapping->CpuVAddr, pMapping->uSize,
					  uFlags, &pMapping->hOSMemHandle) !=
					PVRSRV_OK) {
				PVR_DPF(PVR_DBG_ERROR, "WrapMemory: "
					"OSRegisterMem Phys=0x%08X, "
					"CpuVAddr = 0x%08X, Size=%d) failed",
					 pMapping->CpuPAddr, pMapping->CpuVAddr,
					 pMapping->uSize);
				goto fail_cleanup;
			}
		} else {
			pMapping->eCpuMemoryOrigin =
			    hm_wrapped_scatter_virtaddr;
			pMapping->psSysAddr = psAddr;

			if (OSRegisterDiscontigMem(pMapping->psSysAddr,
						   pMapping->CpuVAddr,
						   pMapping->uSize,
						   uFlags,
						   &pMapping->hOSMemHandle) !=
			    PVRSRV_OK) {
				PVR_DPF(PVR_DBG_ERROR, "WrapMemory: "
					"OSRegisterDiscontigMem CpuVAddr = "
					"0x%08X, Size=%d) failed",
					 pMapping->CpuVAddr, pMapping->uSize);
				goto fail_cleanup;
			}
		}
	} else {
		if (bPhysContig) {
			pMapping->eCpuMemoryOrigin = hm_wrapped;
			pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);

			if (OSReservePhys(pMapping->CpuPAddr, pMapping->uSize,
					uFlags, &pMapping->CpuVAddr,
					&pMapping->hOSMemHandle) != PVRSRV_OK) {
				PVR_DPF(PVR_DBG_ERROR, "WrapMemory: "
					"OSReservePhys Phys=0x%08X, Size=%d) "
					"failed",
					 pMapping->CpuPAddr, pMapping->uSize);
				goto fail_cleanup;
			}
		} else {
			pMapping->eCpuMemoryOrigin = hm_wrapped_scatter;
			pMapping->psSysAddr = psAddr;

			if (OSReserveDiscontigPhys(pMapping->psSysAddr,
						   pMapping->uSize, uFlags,
						   &pMapping->CpuVAddr,
						   &pMapping->hOSMemHandle) !=
			    PVRSRV_OK) {
				PVR_DPF(PVR_DBG_ERROR, "WrapMemory: "
				       "OSReserveDiscontigPhys Size=%d) failed",
					 pMapping->uSize);
				goto fail_cleanup;
			}
		}
	}

	bResult = DevMemoryAlloc(psBMHeap->pBMContext, pMapping,
				 uFlags | PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
				 ui32PageSize, &DevVAddr);
	if (!bResult) {
		PVR_DPF(PVR_DBG_ERROR,
			 "WrapMemory: DevMemoryAlloc(0x%x) failed",
			 pMapping->uSize);
		goto fail_cleanup;
	}

	pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + ui32BaseOffset;
	if (!ui32BaseOffset)
		pBuf->hOSMemHandle = pMapping->hOSMemHandle;
	else
		if (OSGetSubMemHandle(pMapping->hOSMemHandle,
				      ui32BaseOffset,
				      (pMapping->uSize - ui32BaseOffset),
				      uFlags,
				      &pBuf->hOSMemHandle) != PVRSRV_OK) {
			PVR_DPF(PVR_DBG_ERROR,
				 "WrapMemory: OSGetSubMemHandle failed");
			goto fail_cleanup;
		}
	if (pMapping->CpuVAddr)
		pBuf->CpuVAddr = (void *)((u32) pMapping->CpuVAddr +
							     ui32BaseOffset);
	pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr + ui32BaseOffset;

	if (uFlags & PVRSRV_MEM_ZERO)
		if (!ZeroBuf(pBuf, pMapping, uSize, uFlags))
			return IMG_FALSE;

	PVR_DPF(PVR_DBG_MESSAGE, "DevVaddr.uiAddr=%08X", DevVAddr.uiAddr);
	PVR_DPF(PVR_DBG_MESSAGE, "WrapMemory: pMapping=%08X: DevV=%08X "
			"CpuV=%08X CpuP=%08X uSize=0x%x",
		 pMapping, pMapping->DevVAddr.uiAddr, pMapping->CpuVAddr,
		 pMapping->CpuPAddr.uiAddr, pMapping->uSize);
	PVR_DPF(PVR_DBG_MESSAGE, "WrapMemory: pBuf=%08X: DevV=%08X "
				"CpuV=%08X CpuP=%08X uSize=0x%x",
		 pBuf, pBuf->DevVAddr.uiAddr, pBuf->CpuVAddr,
		 pBuf->CpuPAddr.uiAddr, uSize);

	pBuf->pMapping = pMapping;
	return IMG_TRUE;

fail_cleanup:
	if (ui32BaseOffset && pBuf->hOSMemHandle)
		OSReleaseSubMemHandle(pBuf->hOSMemHandle, uFlags);

	if (pMapping->CpuVAddr || pMapping->hOSMemHandle)
		switch (pMapping->eCpuMemoryOrigin) {
		case hm_wrapped:
			OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize,
					uFlags, pMapping->hOSMemHandle);
			break;
		case hm_wrapped_virtaddr:
			OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize,
					uFlags, pMapping->hOSMemHandle);
			break;
		case hm_wrapped_scatter:
			OSUnReserveDiscontigPhys(pMapping->CpuVAddr,
						 pMapping->uSize, uFlags,
						 pMapping->hOSMemHandle);
			break;
		case hm_wrapped_scatter_virtaddr:
			OSUnRegisterDiscontigMem(pMapping->CpuVAddr,
						 pMapping->uSize, uFlags,
						 pMapping->hOSMemHandle);
			break;
		default:
			break;
		}

	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_MAPPING), pMapping,
		  NULL);

	return IMG_FALSE;
}