| /********************************************************************** |
| * |
| * Copyright (C) Imagination Technologies Ltd. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms and conditions of the GNU General Public License, |
| * version 2, as published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope it will be useful but, except |
| * as otherwise stated in writing, without any warranty; without even the |
| * implied warranty of merchantability or fitness for a particular purpose. |
| * See the GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License along with |
| * this program; if not, write to the Free Software Foundation, Inc., |
| * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * The full GNU General Public License is included in this distribution in |
| * the file called "COPYING". |
| * |
| * Contact Information: |
| * Imagination Technologies Ltd. <gpl-support@imgtec.com> |
| * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK |
| * |
| ******************************************************************************/ |
| |
| #include "services_headers.h" |
| |
| #include "sysconfig.h" |
| #include "hash.h" |
| #include "ra.h" |
| #include "pdump_km.h" |
| #include "lists.h" |
| |
| static IMG_BOOL |
| ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags); |
| static IMG_VOID |
| BM_FreeMemory (IMG_VOID *pH, IMG_UINTPTR_T base, BM_MAPPING *psMapping); |
| static IMG_BOOL |
| BM_ImportMemory(IMG_VOID *pH, IMG_SIZE_T uSize, |
| IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping, |
| IMG_UINT32 uFlags, IMG_PVOID pvPrivData, |
| IMG_UINT32 ui32PrivDataLength, IMG_UINTPTR_T *pBase); |
| |
| static IMG_BOOL |
| DevMemoryAlloc (BM_CONTEXT *pBMContext, |
| BM_MAPPING *pMapping, |
| IMG_SIZE_T *pActualSize, |
| IMG_UINT32 uFlags, |
| IMG_UINT32 dev_vaddr_alignment, |
| IMG_DEV_VIRTADDR *pDevVAddr); |
| static IMG_VOID |
| DevMemoryFree (BM_MAPPING *pMapping); |
| |
| static IMG_BOOL |
| AllocMemory (BM_CONTEXT *pBMContext, |
| BM_HEAP *psBMHeap, |
| IMG_DEV_VIRTADDR *psDevVAddr, |
| IMG_SIZE_T uSize, |
| IMG_UINT32 uFlags, |
| IMG_UINT32 uDevVAddrAlignment, |
| IMG_PVOID pvPrivData, |
| IMG_UINT32 ui32PrivDataLength, |
| 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, |
| pvPrivData, |
| ui32PrivDataLength, |
| (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 |
| { |
| IMG_BOOL bResult; |
| |
| |
| |
| bResult = pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap, |
| uSize, |
| IMG_NULL, |
| 0, |
| uDevVAddrAlignment, |
| &pBuf->DevVAddr); |
| |
| if(!bResult) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "AllocMemory: MMUAlloc failed")); |
| return IMG_FALSE; |
| } |
| } |
| |
| |
| 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 |
| 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 |
| ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags) |
| { |
| IMG_VOID *pvCpuVAddr; |
| |
| if(pBuf->CpuVAddr) |
| { |
| OSMemSet(pBuf->CpuVAddr, 0, ui32Bytes); |
| } |
| else if(pMapping->eCpuMemoryOrigin == hm_contiguous |
| || pMapping->eCpuMemoryOrigin == hm_wrapped) |
| { |
| pvCpuVAddr = OSMapPhysToLin(pBuf->CpuPAddr, |
| ui32Bytes, |
| PVRSRV_HAP_KERNEL_ONLY |
| | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK), |
| IMG_NULL); |
| if(!pvCpuVAddr) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin for contiguous buffer failed")); |
| return IMG_FALSE; |
| } |
| OSMemSet(pvCpuVAddr, 0, ui32Bytes); |
| OSUnMapPhysToLin(pvCpuVAddr, |
| ui32Bytes, |
| PVRSRV_HAP_KERNEL_ONLY |
| | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK), |
| IMG_NULL); |
| } |
| else |
| { |
| IMG_SIZE_T ui32BytesRemaining = ui32Bytes; |
| IMG_SIZE_T ui32CurrentOffset = 0; |
| IMG_CPU_PHYADDR CpuPAddr; |
| |
| |
| PVR_ASSERT(pBuf->hOSMemHandle); |
| |
| while(ui32BytesRemaining > 0) |
| { |
| IMG_SIZE_T ui32BlockBytes = MIN(ui32BytesRemaining, HOST_PAGESIZE()); |
| CpuPAddr = OSMemHandleToCpuPAddr(pBuf->hOSMemHandle, ui32CurrentOffset); |
| |
| if(CpuPAddr.uiAddr & (HOST_PAGESIZE() -1)) |
| { |
| ui32BlockBytes = |
| MIN(ui32BytesRemaining, (IMG_UINT32)(HOST_PAGEALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr)); |
| } |
| |
| pvCpuVAddr = OSMapPhysToLin(CpuPAddr, |
| ui32BlockBytes, |
| PVRSRV_HAP_KERNEL_ONLY |
| | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK), |
| IMG_NULL); |
| if(!pvCpuVAddr) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin while zeroing non-contiguous memory FAILED")); |
| return IMG_FALSE; |
| } |
| OSMemSet(pvCpuVAddr, 0, ui32BlockBytes); |
| OSUnMapPhysToLin(pvCpuVAddr, |
| ui32BlockBytes, |
| PVRSRV_HAP_KERNEL_ONLY |
| | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK), |
| IMG_NULL); |
| |
| ui32BytesRemaining -= ui32BlockBytes; |
| ui32CurrentOffset += ui32BlockBytes; |
| } |
| } |
| |
| return IMG_TRUE; |
| } |
| |
| static IMG_VOID |
| FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator) |
| { |
| BM_MAPPING *pMapping; |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, |
| "FreeBuf: pBuf=0x%x: DevVAddr=%08X CpuVAddr=0x%x CpuPAddr=%08X", |
| (IMG_UINTPTR_T)pBuf, pBuf->DevVAddr.uiAddr, |
| (IMG_UINTPTR_T)pBuf->CpuVAddr, pBuf->CpuPAddr.uiAddr)); |
| |
| |
| pMapping = pBuf->pMapping; |
| |
| psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode; |
| if (psDeviceNode->pfnCacheInvalidate) |
| { |
| psDeviceNode->pfnCacheInvalidate(psDeviceNode); |
| } |
| |
| if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) |
| { |
| |
| if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0)) |
| { |
| |
| if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION) |
| { |
| |
| PVR_DPF ((PVR_DBG_ERROR, "FreeBuf: combination of DevVAddr management and RAM backing mode unsupported")); |
| } |
| else |
| { |
| |
| OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL); |
| pBuf->pMapping = IMG_NULL; |
| } |
| } |
| } |
| else |
| { |
| |
| if(pBuf->hOSMemHandle != pMapping->hOSMemHandle) |
| { |
| |
| if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0)) |
| { |
| |
| OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Flags); |
| } |
| } |
| if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION) |
| { |
| |
| |
| if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0)) |
| { |
| |
| |
| |
| PVR_ASSERT(pBuf->ui32ExportCount == 0) |
| RA_Free (pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr, IMG_FALSE); |
| } |
| } |
| else |
| { |
| if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0)) |
| { |
| switch (pMapping->eCpuMemoryOrigin) |
| { |
| case hm_wrapped: |
| OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle); |
| break; |
| case hm_wrapped_virtaddr: |
| OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle); |
| break; |
| case hm_wrapped_scatter: |
| OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle); |
| break; |
| case hm_wrapped_scatter_virtaddr: |
| OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle); |
| break; |
| default: |
| break; |
| } |
| } |
| if (bFromAllocator) |
| DevMemoryFree (pMapping); |
| |
| if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0)) |
| { |
| |
| OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL); |
| pBuf->pMapping = IMG_NULL; |
| } |
| } |
| } |
| |
| |
| if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0)) |
| { |
| OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, IMG_NULL); |
| |
| } |
| } |
| |
| static PVRSRV_ERROR BM_DestroyContext_AnyCb(BM_HEAP *psBMHeap) |
| { |
| if(psBMHeap->ui32Attribs |
| & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG |
| |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)) |
| { |
| if (psBMHeap->pImportArena) |
| { |
| IMG_BOOL bTestDelete = RA_TestDelete(psBMHeap->pImportArena); |
| if (!bTestDelete) |
| { |
| PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext_AnyCb: RA_TestDelete failed")); |
| return PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP; |
| } |
| } |
| } |
| return PVRSRV_OK; |
| } |
| |
| |
| PVRSRV_ERROR |
| BM_DestroyContext(IMG_HANDLE hBMContext, |
| IMG_BOOL *pbDestroyed) |
| { |
| PVRSRV_ERROR eError; |
| BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext; |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, "BM_DestroyContext")); |
| |
| if (pbDestroyed != IMG_NULL) |
| { |
| *pbDestroyed = IMG_FALSE; |
| } |
| |
| |
| |
| if (pBMContext == IMG_NULL) |
| { |
| PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Invalid handle")); |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| pBMContext->ui32RefCount--; |
| |
| if (pBMContext->ui32RefCount > 0) |
| { |
| |
| return PVRSRV_OK; |
| } |
| |
| |
| |
| |
| eError = List_BM_HEAP_PVRSRV_ERROR_Any(pBMContext->psBMHeap, &BM_DestroyContext_AnyCb); |
| if(eError != PVRSRV_OK) |
| { |
| PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: List_BM_HEAP_PVRSRV_ERROR_Any failed")); |
| #if 0 |
| |
| |
| |
| |
| PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Cleaning up with ResManFreeSpecial")); |
| if(ResManFreeSpecial() != PVRSRV_OK) |
| { |
| PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeSpecial failed %d",eError)); |
| } |
| |
| #endif |
| return eError; |
| } |
| else |
| { |
| |
| eError = ResManFreeResByPtr(pBMContext->hResItem, CLEANUP_WITH_POLL); |
| if(eError != PVRSRV_OK) |
| { |
| PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeResByPtr failed %d",eError)); |
| return eError; |
| } |
| |
| |
| if (pbDestroyed != IMG_NULL) |
| { |
| *pbDestroyed = IMG_TRUE; |
| } |
| } |
| |
| return PVRSRV_OK; |
| } |
| |
| |
| static PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP *psBMHeap, va_list va) |
| { |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*); |
| |
| |
| if(psBMHeap->ui32Attribs |
| & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG |
| |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)) |
| { |
| if (psBMHeap->pImportArena) |
| { |
| RA_Delete (psBMHeap->pImportArena); |
| } |
| } |
| else |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_DestroyContext: backing store type unsupported")); |
| return PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE; |
| } |
| |
| |
| psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap); |
| |
| |
| OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL); |
| |
| |
| return PVRSRV_OK; |
| } |
| |
| |
| static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam, |
| IMG_UINT32 ui32Param, |
| IMG_BOOL bDummy) |
| { |
| BM_CONTEXT *pBMContext = pvParam; |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| PVRSRV_ERROR eError; |
| PVR_UNREFERENCED_PARAMETER(ui32Param); |
| PVR_UNREFERENCED_PARAMETER(bDummy); |
| |
| |
| |
| psDeviceNode = pBMContext->psDeviceNode; |
| |
| |
| |
| eError = List_BM_HEAP_PVRSRV_ERROR_Any_va(pBMContext->psBMHeap, |
| &BM_DestroyContextCallBack_AnyVaCb, |
| psDeviceNode); |
| if (eError != PVRSRV_OK) |
| { |
| return eError; |
| } |
| |
| |
| if (pBMContext->psMMUContext) |
| { |
| psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext); |
| } |
| |
| |
| |
| if (pBMContext->pBufferHash) |
| { |
| HASH_Delete(pBMContext->pBufferHash); |
| } |
| |
| if (pBMContext == psDeviceNode->sDevMemoryInfo.pBMKernelContext) |
| { |
| |
| psDeviceNode->sDevMemoryInfo.pBMKernelContext = IMG_NULL; |
| } |
| else |
| { |
| if (pBMContext->ppsThis != IMG_NULL) |
| { |
| |
| List_BM_CONTEXT_Remove(pBMContext); |
| } |
| } |
| |
| OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext, IMG_NULL); |
| |
| |
| return PVRSRV_OK; |
| } |
| |
| |
| static IMG_HANDLE BM_CreateContext_IncRefCount_AnyVaCb(BM_CONTEXT *pBMContext, va_list va) |
| { |
| PRESMAN_CONTEXT hResManContext; |
| hResManContext = va_arg(va, PRESMAN_CONTEXT); |
| if(ResManFindResourceByPtr(hResManContext, pBMContext->hResItem) == PVRSRV_OK) |
| { |
| |
| pBMContext->ui32RefCount++; |
| return pBMContext; |
| } |
| return IMG_NULL; |
| } |
| |
| static IMG_VOID BM_CreateContext_InsertHeap_ForEachVaCb(BM_HEAP *psBMHeap, va_list va) |
| { |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| BM_CONTEXT *pBMContext; |
| psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*); |
| pBMContext = va_arg(va, BM_CONTEXT*); |
| switch(psBMHeap->sDevArena.DevMemHeapType) |
| { |
| case DEVICE_MEMORY_HEAP_SHARED: |
| case DEVICE_MEMORY_HEAP_SHARED_EXPORTED: |
| { |
| |
| psDeviceNode->pfnMMUInsertHeap(pBMContext->psMMUContext, psBMHeap->pMMUHeap); |
| break; |
| } |
| } |
| } |
| |
| IMG_HANDLE |
| BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode, |
| IMG_DEV_PHYADDR *psPDDevPAddr, |
| PVRSRV_PER_PROCESS_DATA *psPerProc, |
| IMG_BOOL *pbCreated) |
| { |
| BM_CONTEXT *pBMContext; |
| DEVICE_MEMORY_INFO *psDevMemoryInfo; |
| IMG_BOOL bKernelContext; |
| PRESMAN_CONTEXT hResManContext; |
| |
| PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateContext")); |
| |
| if (psPerProc == IMG_NULL) |
| { |
| bKernelContext = IMG_TRUE; |
| hResManContext = psDeviceNode->hResManContext; |
| } |
| else |
| { |
| bKernelContext = IMG_FALSE; |
| hResManContext = psPerProc->hResManContext; |
| } |
| |
| if (pbCreated != IMG_NULL) |
| { |
| *pbCreated = IMG_FALSE; |
| } |
| |
| |
| psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo; |
| |
| if (bKernelContext == IMG_FALSE) |
| { |
| IMG_HANDLE res = (IMG_HANDLE) List_BM_CONTEXT_Any_va(psDevMemoryInfo->pBMContext, |
| &BM_CreateContext_IncRefCount_AnyVaCb, |
| hResManContext); |
| if (res) |
| { |
| return res; |
| } |
| } |
| |
| |
| if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, |
| sizeof (struct _BM_CONTEXT_), |
| (IMG_PVOID *)&pBMContext, IMG_NULL, |
| "Buffer Manager Context") != PVRSRV_OK) |
| { |
| PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: Alloc failed")); |
| return IMG_NULL; |
| } |
| OSMemSet(pBMContext, 0, sizeof (BM_CONTEXT)); |
| |
| |
| pBMContext->psDeviceNode = psDeviceNode; |
| |
| |
| |
| pBMContext->pBufferHash = HASH_Create(32); |
| if (pBMContext->pBufferHash==IMG_NULL) |
| { |
| PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: HASH_Create failed")); |
| goto cleanup; |
| } |
| |
| if((IMG_NULL == psDeviceNode->pfnMMUInitialise) || (psDeviceNode->pfnMMUInitialise(psDeviceNode, |
| &pBMContext->psMMUContext, |
| psPDDevPAddr) != PVRSRV_OK)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: MMUInitialise failed")); |
| goto cleanup; |
| } |
| |
| if(bKernelContext) |
| { |
| |
| PVR_ASSERT(psDevMemoryInfo->pBMKernelContext == IMG_NULL); |
| psDevMemoryInfo->pBMKernelContext = pBMContext; |
| } |
| else |
| { |
| |
| |
| |
| |
| |
| PVR_ASSERT(psDevMemoryInfo->pBMKernelContext); |
| |
| if (psDevMemoryInfo->pBMKernelContext == IMG_NULL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: psDevMemoryInfo->pBMKernelContext invalid")); |
| goto cleanup; |
| } |
| |
| PVR_ASSERT(psDevMemoryInfo->pBMKernelContext->psBMHeap); |
| |
| |
| |
| |
| |
| pBMContext->psBMSharedHeap = psDevMemoryInfo->pBMKernelContext->psBMHeap; |
| |
| |
| |
| |
| List_BM_HEAP_ForEach_va(pBMContext->psBMSharedHeap, |
| &BM_CreateContext_InsertHeap_ForEachVaCb, |
| psDeviceNode, |
| pBMContext); |
| |
| |
| List_BM_CONTEXT_Insert(&psDevMemoryInfo->pBMContext, pBMContext); |
| } |
| |
| |
| pBMContext->ui32RefCount++; |
| |
| |
| pBMContext->hResItem = ResManRegisterRes(hResManContext, |
| RESMAN_TYPE_DEVICEMEM_CONTEXT, |
| pBMContext, |
| 0, |
| &BM_DestroyContextCallBack); |
| if (pBMContext->hResItem == IMG_NULL) |
| { |
| PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: ResManRegisterRes failed")); |
| goto cleanup; |
| } |
| |
| if (pbCreated != IMG_NULL) |
| { |
| *pbCreated = IMG_TRUE; |
| } |
| return (IMG_HANDLE)pBMContext; |
| |
| cleanup: |
| (IMG_VOID)BM_DestroyContextCallBack(pBMContext, 0, CLEANUP_WITH_POLL); |
| |
| return IMG_NULL; |
| } |
| |
| |
| static IMG_VOID *BM_CreateHeap_AnyVaCb(BM_HEAP *psBMHeap, va_list va) |
| { |
| DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo; |
| psDevMemHeapInfo = va_arg(va, DEVICE_MEMORY_HEAP_INFO*); |
| if (psBMHeap->sDevArena.ui32HeapID == psDevMemHeapInfo->ui32HeapID) |
| { |
| |
| return psBMHeap; |
| } |
| else |
| { |
| return IMG_NULL; |
| } |
| } |
| |
| IMG_HANDLE |
| BM_CreateHeap (IMG_HANDLE hBMContext, |
| DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo) |
| { |
| BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext; |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| BM_HEAP *psBMHeap; |
| |
| PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateHeap")); |
| |
| if(!pBMContext) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: BM_CONTEXT null")); |
| return IMG_NULL; |
| } |
| |
| psDeviceNode = pBMContext->psDeviceNode; |
| |
| |
| |
| PVR_ASSERT((psDevMemHeapInfo->ui32HeapSize & (psDevMemHeapInfo->ui32DataPageSize - 1)) == 0); |
| PVR_ASSERT(psDevMemHeapInfo->ui32HeapSize > 0); |
| |
| |
| |
| |
| |
| |
| if(pBMContext->ui32RefCount > 0) |
| { |
| psBMHeap = (BM_HEAP*)List_BM_HEAP_Any_va(pBMContext->psBMHeap, |
| &BM_CreateHeap_AnyVaCb, |
| psDevMemHeapInfo); |
| |
| if (psBMHeap) |
| { |
| return psBMHeap; |
| } |
| } |
| |
| |
| if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, |
| sizeof (BM_HEAP), |
| (IMG_PVOID *)&psBMHeap, IMG_NULL, |
| "Buffer Manager Heap") != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: Alloc failed")); |
| return IMG_NULL; |
| } |
| |
| OSMemSet (psBMHeap, 0, sizeof (BM_HEAP)); |
| |
| psBMHeap->sDevArena.ui32HeapID = psDevMemHeapInfo->ui32HeapID; |
| psBMHeap->sDevArena.pszName = psDevMemHeapInfo->pszName; |
| psBMHeap->sDevArena.BaseDevVAddr = psDevMemHeapInfo->sDevVAddrBase; |
| psBMHeap->sDevArena.ui32Size = psDevMemHeapInfo->ui32HeapSize; |
| psBMHeap->sDevArena.DevMemHeapType = psDevMemHeapInfo->DevMemHeapType; |
| psBMHeap->sDevArena.ui32DataPageSize = psDevMemHeapInfo->ui32DataPageSize; |
| psBMHeap->sDevArena.psDeviceMemoryHeapInfo = psDevMemHeapInfo; |
| psBMHeap->ui32Attribs = psDevMemHeapInfo->ui32Attribs; |
| #if defined(SUPPORT_MEMORY_TILING) |
| psBMHeap->ui32XTileStride = psDevMemHeapInfo->ui32XTileStride; |
| #endif |
| |
| |
| psBMHeap->pBMContext = pBMContext; |
| |
| psBMHeap->pMMUHeap = psDeviceNode->pfnMMUCreate (pBMContext->psMMUContext, |
| &psBMHeap->sDevArena, |
| &psBMHeap->pVMArena, |
| &psBMHeap->psMMUAttrib); |
| if (!psBMHeap->pMMUHeap) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: MMUCreate failed")); |
| goto ErrorExit; |
| } |
| |
| |
| psBMHeap->pImportArena = RA_Create (psDevMemHeapInfo->pszBSName, |
| 0, 0, IMG_NULL, |
| MAX(HOST_PAGESIZE(), psBMHeap->sDevArena.ui32DataPageSize), |
| &BM_ImportMemory, |
| &BM_FreeMemory, |
| IMG_NULL, |
| psBMHeap); |
| if(psBMHeap->pImportArena == IMG_NULL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: RA_Create failed")); |
| goto ErrorExit; |
| } |
| |
| if(psBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) |
| { |
| |
| |
| |
| |
| psBMHeap->pLocalDevMemArena = psDevMemHeapInfo->psLocalDevMemArena; |
| if(psBMHeap->pLocalDevMemArena == IMG_NULL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: LocalDevMemArena null")); |
| goto ErrorExit; |
| } |
| } |
| |
| |
| List_BM_HEAP_Insert(&pBMContext->psBMHeap, psBMHeap); |
| |
| return (IMG_HANDLE)psBMHeap; |
| |
| |
| ErrorExit: |
| |
| |
| if (psBMHeap->pMMUHeap != IMG_NULL) |
| { |
| psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap); |
| |
| } |
| |
| |
| OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL); |
| |
| |
| return IMG_NULL; |
| } |
| |
| IMG_VOID |
| BM_DestroyHeap (IMG_HANDLE hDevMemHeap) |
| { |
| BM_HEAP* psBMHeap = (BM_HEAP*)hDevMemHeap; |
| PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode; |
| |
| PVR_DPF((PVR_DBG_MESSAGE, "BM_DestroyHeap")); |
| |
| if(psBMHeap) |
| { |
| |
| if(psBMHeap->ui32Attribs |
| & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG |
| |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)) |
| { |
| if (psBMHeap->pImportArena) |
| { |
| RA_Delete (psBMHeap->pImportArena); |
| } |
| } |
| else |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_DestroyHeap: backing store type unsupported")); |
| return; |
| } |
| |
| |
| psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap); |
| |
| |
| List_BM_HEAP_Remove(psBMHeap); |
| |
| OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL); |
| |
| } |
| else |
| { |
| PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyHeap: invalid heap handle")); |
| } |
| } |
| |
| |
| IMG_BOOL |
| BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode) |
| { |
| |
| PVR_DPF((PVR_DBG_MESSAGE, "BM_Reinitialise")); |
| PVR_UNREFERENCED_PARAMETER(psDeviceNode); |
| |
| |
| return IMG_TRUE; |
| } |
| |
| IMG_BOOL |
| BM_Alloc ( IMG_HANDLE hDevMemHeap, |
| IMG_DEV_VIRTADDR *psDevVAddr, |
| IMG_SIZE_T uSize, |
| IMG_UINT32 *pui32Flags, |
| IMG_UINT32 uDevVAddrAlignment, |
| IMG_PVOID pvPrivData, |
| IMG_UINT32 ui32PrivDataLength, |
| BM_HANDLE *phBuf) |
| { |
| BM_BUF *pBuf; |
| BM_CONTEXT *pBMContext; |
| BM_HEAP *psBMHeap; |
| SYS_DATA *psSysData; |
| IMG_UINT32 uFlags; |
| |
| if (pui32Flags == IMG_NULL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: invalid parameter")); |
| PVR_DBG_BREAK; |
| return IMG_FALSE; |
| } |
| |
| uFlags = *pui32Flags; |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, |
| "BM_Alloc (uSize=0x%x, uFlags=0x%x, uDevVAddrAlignment=0x%x)", |
| uSize, uFlags, uDevVAddrAlignment)); |
| |
| SysAcquireData(&psSysData); |
| |
| psBMHeap = (BM_HEAP*)hDevMemHeap; |
| pBMContext = psBMHeap->pBMContext; |
| |
| if(uDevVAddrAlignment == 0) |
| { |
| uDevVAddrAlignment = 1; |
| } |
| |
| |
| if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, |
| sizeof (BM_BUF), |
| (IMG_PVOID *)&pBuf, IMG_NULL, |
| "Buffer Manager buffer") != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: BM_Buf alloc FAILED")); |
| return IMG_FALSE; |
| } |
| OSMemSet(pBuf, 0, sizeof (BM_BUF)); |
| |
| |
| if (AllocMemory(pBMContext, |
| psBMHeap, |
| psDevVAddr, |
| uSize, |
| uFlags, |
| uDevVAddrAlignment, |
| pvPrivData, |
| ui32PrivDataLength, |
| pBuf) != IMG_TRUE) |
| { |
| OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL); |
| |
| PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: AllocMemory FAILED")); |
| return IMG_FALSE; |
| } |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, |
| "BM_Alloc (uSize=0x%x, uFlags=0x%x)", |
| uSize, uFlags)); |
| |
| |
| pBuf->ui32RefCount = 1; |
| *phBuf = (BM_HANDLE)pBuf; |
| *pui32Flags = uFlags | psBMHeap->ui32Attribs; |
| |
| |
| if(uFlags & PVRSRV_HAP_CACHETYPE_MASK) |
| { |
| *pui32Flags &= ~PVRSRV_HAP_CACHETYPE_MASK; |
| *pui32Flags |= (uFlags & PVRSRV_HAP_CACHETYPE_MASK); |
| } |
| |
| return IMG_TRUE; |
| } |
| |
| |
| |
| #if defined(PVR_LMA) |
| static IMG_BOOL |
| ValidSysPAddrArrayForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR *psSysPAddr, IMG_UINT32 ui32PageCount, IMG_SIZE_T ui32PageSize) |
| { |
| IMG_UINT32 i; |
| |
| for (i = 0; i < ui32PageCount; i++) |
| { |
| IMG_SYS_PHYADDR sStartSysPAddr = psSysPAddr[i]; |
| IMG_SYS_PHYADDR sEndSysPAddr; |
| |
| if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr)) |
| { |
| return IMG_FALSE; |
| } |
| |
| sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32PageSize; |
| |
| if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr)) |
| { |
| return IMG_FALSE; |
| } |
| } |
| |
| return IMG_TRUE; |
| } |
| |
| static IMG_BOOL |
| ValidSysPAddrRangeForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR sStartSysPAddr, IMG_SIZE_T ui32Range) |
| { |
| IMG_SYS_PHYADDR sEndSysPAddr; |
| |
| if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr)) |
| { |
| return IMG_FALSE; |
| } |
| |
| sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32Range; |
| |
| if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr)) |
| { |
| return IMG_FALSE; |
| } |
| |
| return IMG_TRUE; |
| } |
| |
| #define WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) HOST_PAGEALIGN((ui32ByteSize) + (ui32PageOffset)) |
| |
| #define WRAP_PAGE_COUNT(ui32ByteSize, ui32PageOffset, ui32HostPageSize) (WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) / (ui32HostPageSize)) |
| |
| #endif |
| |
| |
| IMG_BOOL |
| BM_Wrap ( IMG_HANDLE hDevMemHeap, |
| IMG_SIZE_T ui32Size, |
| IMG_SIZE_T ui32Offset, |
| IMG_BOOL bPhysContig, |
| IMG_SYS_PHYADDR *psSysAddr, |
| IMG_VOID *pvCPUVAddr, |
| IMG_UINT32 *pui32Flags, |
| BM_HANDLE *phBuf) |
| { |
| BM_BUF *pBuf; |
| BM_CONTEXT *psBMContext; |
| BM_HEAP *psBMHeap; |
| SYS_DATA *psSysData; |
| IMG_SYS_PHYADDR sHashAddress; |
| IMG_UINT32 uFlags; |
| |
| psBMHeap = (BM_HEAP*)hDevMemHeap; |
| psBMContext = psBMHeap->pBMContext; |
| |
| uFlags = psBMHeap->ui32Attribs & (PVRSRV_HAP_CACHETYPE_MASK | PVRSRV_HAP_MAPTYPE_MASK); |
| |
| if ((pui32Flags != IMG_NULL) && ((*pui32Flags & PVRSRV_HAP_CACHETYPE_MASK) != 0)) |
| { |
| uFlags &= ~PVRSRV_HAP_CACHETYPE_MASK; |
| uFlags |= *pui32Flags & PVRSRV_HAP_CACHETYPE_MASK; |
| } |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, |
| "BM_Wrap (uSize=0x%x, uOffset=0x%x, bPhysContig=0x%x, pvCPUVAddr=0x%x, uFlags=0x%x)", |
| ui32Size, ui32Offset, bPhysContig, (IMG_UINTPTR_T)pvCPUVAddr, uFlags)); |
| |
| SysAcquireData(&psSysData); |
| |
| #if defined(PVR_LMA) |
| if (bPhysContig) |
| { |
| if (!ValidSysPAddrRangeForDev(psBMContext->psDeviceNode, *psSysAddr, WRAP_MAPPING_SIZE(ui32Size, ui32Offset))) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: System address range invalid for device")); |
| return IMG_FALSE; |
| } |
| } |
| else |
| { |
| IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE(); |
| |
| if (!ValidSysPAddrArrayForDev(psBMContext->psDeviceNode, psSysAddr, WRAP_PAGE_COUNT(ui32Size, ui32Offset, ui32HostPageSize), ui32HostPageSize)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: Array of system addresses invalid for device")); |
| return IMG_FALSE; |
| } |
| } |
| #endif |
| |
| sHashAddress = psSysAddr[0]; |
| |
| |
| sHashAddress.uiAddr += ui32Offset; |
| |
| |
| pBuf = (BM_BUF *)HASH_Retrieve(psBMContext->pBufferHash, sHashAddress.uiAddr); |
| |
| if(pBuf) |
| { |
| IMG_SIZE_T ui32MappingSize = HOST_PAGEALIGN (ui32Size + ui32Offset); |
| |
| |
| if(pBuf->pMapping->uSize == ui32MappingSize && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || |
| pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)) |
| { |
| PVR_DPF((PVR_DBG_MESSAGE, |
| "BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)", |
| ui32Size, ui32Offset, sHashAddress.uiAddr)); |
| |
| PVRSRVBMBufIncRef(pBuf); |
| *phBuf = (BM_HANDLE)pBuf; |
| if(pui32Flags) |
| *pui32Flags = uFlags; |
| |
| return IMG_TRUE; |
| } |
| else |
| { |
| |
| HASH_Remove(psBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddress.uiAddr); |
| } |
| } |
| |
| |
| if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, |
| sizeof (BM_BUF), |
| (IMG_PVOID *)&pBuf, IMG_NULL, |
| "Buffer Manager buffer") != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: BM_Buf alloc FAILED")); |
| return IMG_FALSE; |
| } |
| OSMemSet(pBuf, 0, sizeof (BM_BUF)); |
| |
| |
| if (WrapMemory (psBMHeap, ui32Size, ui32Offset, bPhysContig, psSysAddr, pvCPUVAddr, uFlags, pBuf) != IMG_TRUE) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: WrapMemory FAILED")); |
| OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL); |
| |
| return IMG_FALSE; |
| } |
| |
| |
| if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr) |
| { |
| |
| PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr == pBuf->CpuPAddr.uiAddr); |
| |
| if (!HASH_Insert (psBMContext->pBufferHash, sHashAddress.uiAddr, (IMG_UINTPTR_T)pBuf)) |
| { |
| FreeBuf (pBuf, uFlags, IMG_TRUE); |
| PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: HASH_Insert FAILED")); |
| return IMG_FALSE; |
| } |
| } |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, |
| "BM_Wrap (uSize=0x%x, uFlags=0x%x, devVAddr=%08X)", |
| ui32Size, uFlags, pBuf->DevVAddr.uiAddr)); |
| |
| |
| pBuf->ui32RefCount = 1; |
| *phBuf = (BM_HANDLE)pBuf; |
| if(pui32Flags) |
| { |
| |
| *pui32Flags = (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) | PVRSRV_HAP_MULTI_PROCESS; |
| } |
| |
| return IMG_TRUE; |
| } |
| |
| IMG_VOID |
| BM_Export (BM_HANDLE hBuf) |
| { |
| BM_BUF *pBuf = (BM_BUF *)hBuf; |
| |
| PVRSRVBMBufIncExport(pBuf); |
| } |
| |
| IMG_VOID |
| BM_FreeExport(BM_HANDLE hBuf, |
| IMG_UINT32 ui32Flags) |
| { |
| BM_BUF *pBuf = (BM_BUF *)hBuf; |
| |
| PVRSRVBMBufDecExport(pBuf); |
| FreeBuf (pBuf, ui32Flags, IMG_FALSE); |
| } |
| |
| IMG_VOID |
| BM_Free (BM_HANDLE hBuf, |
| IMG_UINT32 ui32Flags) |
| { |
| BM_BUF *pBuf = (BM_BUF *)hBuf; |
| SYS_DATA *psSysData; |
| IMG_SYS_PHYADDR sHashAddr; |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, "BM_Free (h=0x%x)", (IMG_UINTPTR_T)hBuf)); |
| PVR_ASSERT (pBuf!=IMG_NULL); |
| |
| if (pBuf == IMG_NULL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_Free: invalid parameter")); |
| return; |
| } |
| |
| SysAcquireData(&psSysData); |
| |
| PVRSRVBMBufDecRef(pBuf); |
| if(pBuf->ui32RefCount == 0) |
| { |
| if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr) |
| { |
| sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr); |
| |
| HASH_Remove (pBuf->pMapping->pBMHeap->pBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddr.uiAddr); |
| } |
| FreeBuf (pBuf, ui32Flags, IMG_TRUE); |
| } |
| } |
| |
| |
| IMG_CPU_VIRTADDR |
| BM_HandleToCpuVaddr (BM_HANDLE hBuf) |
| { |
| BM_BUF *pBuf = (BM_BUF *)hBuf; |
| |
| PVR_ASSERT (pBuf != IMG_NULL); |
| if (pBuf == IMG_NULL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_HandleToCpuVaddr: invalid parameter")); |
| return IMG_NULL; |
| } |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, |
| "BM_HandleToCpuVaddr(h=0x%x)=0x%x", |
| (IMG_UINTPTR_T)hBuf, (IMG_UINTPTR_T)pBuf->CpuVAddr)); |
| return pBuf->CpuVAddr; |
| } |
| |
| |
| IMG_DEV_VIRTADDR |
| BM_HandleToDevVaddr (BM_HANDLE hBuf) |
| { |
| BM_BUF *pBuf = (BM_BUF *)hBuf; |
| |
| PVR_ASSERT (pBuf != IMG_NULL); |
| if (pBuf == IMG_NULL) |
| { |
| IMG_DEV_VIRTADDR DevVAddr = {0}; |
| PVR_DPF((PVR_DBG_ERROR, "BM_HandleToDevVaddr: invalid parameter")); |
| return DevVAddr; |
| } |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToDevVaddr(h=0x%x)=%08X", (IMG_UINTPTR_T)hBuf, pBuf->DevVAddr.uiAddr)); |
| return pBuf->DevVAddr; |
| } |
| |
| |
| IMG_SYS_PHYADDR |
| BM_HandleToSysPaddr (BM_HANDLE hBuf) |
| { |
| BM_BUF *pBuf = (BM_BUF *)hBuf; |
| |
| PVR_ASSERT (pBuf != IMG_NULL); |
| |
| if (pBuf == IMG_NULL) |
| { |
| IMG_SYS_PHYADDR PhysAddr = {0}; |
| PVR_DPF((PVR_DBG_ERROR, "BM_HandleToSysPaddr: invalid parameter")); |
| return PhysAddr; |
| } |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToSysPaddr(h=0x%x)=%08X", (IMG_UINTPTR_T)hBuf, pBuf->CpuPAddr.uiAddr)); |
| return SysCpuPAddrToSysPAddr (pBuf->CpuPAddr); |
| } |
| |
| IMG_HANDLE |
| BM_HandleToOSMemHandle(BM_HANDLE hBuf) |
| { |
| BM_BUF *pBuf = (BM_BUF *)hBuf; |
| |
| PVR_ASSERT (pBuf != IMG_NULL); |
| |
| if (pBuf == IMG_NULL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_HandleToOSMemHandle: invalid parameter")); |
| return IMG_NULL; |
| } |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, |
| "BM_HandleToOSMemHandle(h=0x%x)=0x%x", |
| (IMG_UINTPTR_T)hBuf, (IMG_UINTPTR_T)pBuf->hOSMemHandle)); |
| return pBuf->hOSMemHandle; |
| } |
| |
| static IMG_BOOL |
| DevMemoryAlloc (BM_CONTEXT *pBMContext, |
| BM_MAPPING *pMapping, |
| IMG_SIZE_T *pActualSize, |
| IMG_UINT32 uFlags, |
| IMG_UINT32 dev_vaddr_alignment, |
| IMG_DEV_VIRTADDR *pDevVAddr) |
| { |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| #ifdef PDUMP |
| IMG_UINT32 ui32PDumpSize = (IMG_UINT32)pMapping->uSize; |
| #endif |
| |
| psDeviceNode = pBMContext->psDeviceNode; |
| |
| if(uFlags & PVRSRV_MEM_INTERLEAVED) |
| { |
| |
| pMapping->uSize *= 2; |
| } |
| |
| #ifdef PDUMP |
| if(uFlags & PVRSRV_MEM_DUMMY) |
| { |
| |
| ui32PDumpSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize; |
| } |
| #endif |
| |
| |
| if (!psDeviceNode->pfnMMUAlloc (pMapping->pBMHeap->pMMUHeap, |
| pMapping->uSize, |
| pActualSize, |
| 0, |
| dev_vaddr_alignment, |
| &(pMapping->DevVAddr))) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "DevMemoryAlloc ERROR MMU_Alloc")); |
| return IMG_FALSE; |
| } |
| |
| #ifdef SUPPORT_SGX_MMU_BYPASS |
| EnableHostAccess(pBMContext->psMMUContext); |
| #endif |
| |
| #if defined(PDUMP) |
| |
| PDUMPMALLOCPAGES(&psDeviceNode->sDevId, |
| pMapping->DevVAddr.uiAddr, |
| pMapping->CpuVAddr, |
| pMapping->hOSMemHandle, |
| ui32PDumpSize, |
| pMapping->pBMHeap->sDevArena.ui32DataPageSize, |
| #if defined(SUPPORT_PDUMP_MULTI_PROCESS) |
| psDeviceNode->pfnMMUIsHeapShared(pMapping->pBMHeap->pMMUHeap), |
| #else |
| IMG_FALSE, |
| #endif |
| (IMG_HANDLE)pMapping); |
| #endif |
| |
| switch (pMapping->eCpuMemoryOrigin) |
| { |
| case hm_wrapped: |
| case hm_wrapped_virtaddr: |
| case hm_contiguous: |
| { |
| psDeviceNode->pfnMMUMapPages ( pMapping->pBMHeap->pMMUHeap, |
| pMapping->DevVAddr, |
| SysCpuPAddrToSysPAddr (pMapping->CpuPAddr), |
| pMapping->uSize, |
| uFlags, |
| (IMG_HANDLE)pMapping); |
| |
| *pDevVAddr = pMapping->DevVAddr; |
| break; |
| } |
| case hm_env: |
| { |
| psDeviceNode->pfnMMUMapShadow ( pMapping->pBMHeap->pMMUHeap, |
| pMapping->DevVAddr, |
| pMapping->uSize, |
| pMapping->CpuVAddr, |
| pMapping->hOSMemHandle, |
| pDevVAddr, |
| uFlags, |
| (IMG_HANDLE)pMapping); |
| break; |
| } |
| case hm_wrapped_scatter: |
| case hm_wrapped_scatter_virtaddr: |
| { |
| psDeviceNode->pfnMMUMapScatter (pMapping->pBMHeap->pMMUHeap, |
| pMapping->DevVAddr, |
| pMapping->psSysAddr, |
| pMapping->uSize, |
| uFlags, |
| (IMG_HANDLE)pMapping); |
| |
| *pDevVAddr = pMapping->DevVAddr; |
| break; |
| } |
| default: |
| PVR_DPF((PVR_DBG_ERROR, |
| "Illegal value %d for pMapping->eCpuMemoryOrigin", |
| pMapping->eCpuMemoryOrigin)); |
| return IMG_FALSE; |
| } |
| |
| #ifdef SUPPORT_SGX_MMU_BYPASS |
| DisableHostAccess(pBMContext->psMMUContext); |
| #endif |
| |
| return IMG_TRUE; |
| } |
| |
| static IMG_VOID |
| DevMemoryFree (BM_MAPPING *pMapping) |
| { |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| IMG_DEV_PHYADDR sDevPAddr; |
| #ifdef PDUMP |
| IMG_UINT32 ui32PSize; |
| #endif |
| |
| psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode; |
| sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr); |
| |
| if (sDevPAddr.uiAddr != 0) |
| { |
| #ifdef PDUMP |
| |
| if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY) |
| { |
| |
| ui32PSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize; |
| } |
| else |
| { |
| ui32PSize = (IMG_UINT32)pMapping->uSize; |
| } |
| |
| PDUMPFREEPAGES(pMapping->pBMHeap, |
| pMapping->DevVAddr, |
| ui32PSize, |
| pMapping->pBMHeap->sDevArena.ui32DataPageSize, |
| (IMG_HANDLE)pMapping, |
| (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE); |
| #endif |
| } |
| psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSize)); |
| } |
| |
| #ifndef XPROC_WORKAROUND_NUM_SHAREABLES |
| #define XPROC_WORKAROUND_NUM_SHAREABLES 200 |
| #endif |
| |
| #define XPROC_WORKAROUND_BAD_SHAREINDEX 0773407734 |
| |
| #define XPROC_WORKAROUND_UNKNOWN 0 |
| #define XPROC_WORKAROUND_ALLOC 1 |
| #define XPROC_WORKAROUND_MAP 2 |
| |
| static IMG_UINT32 gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX; |
| static IMG_UINT32 gXProcWorkaroundState = XPROC_WORKAROUND_UNKNOWN; |
| |
| |
| static struct { |
| IMG_UINT32 ui32RefCount; |
| IMG_UINT32 ui32AllocFlags; |
| IMG_UINT32 ui32Size; |
| IMG_UINT32 ui32PageSize; |
| RA_ARENA *psArena; |
| IMG_SYS_PHYADDR sSysPAddr; |
| IMG_VOID *pvCpuVAddr; |
| IMG_HANDLE hOSMemHandle; |
| } gXProcWorkaroundShareData[XPROC_WORKAROUND_NUM_SHAREABLES] = {{0}}; |
| |
| PVRSRV_ERROR BM_XProcWorkaroundSetShareIndex(IMG_UINT32 ui32Index) |
| { |
| |
| |
| |
| if (gXProcWorkaroundShareIndex != XPROC_WORKAROUND_BAD_SHAREINDEX) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "No, it's already set!")); |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| gXProcWorkaroundShareIndex = ui32Index; |
| gXProcWorkaroundState = XPROC_WORKAROUND_MAP; |
| |
| return PVRSRV_OK; |
| } |
| |
| PVRSRV_ERROR BM_XProcWorkaroundUnsetShareIndex(IMG_UINT32 ui32Index) |
| { |
| |
| |
| |
| if (gXProcWorkaroundShareIndex == XPROC_WORKAROUND_BAD_SHAREINDEX) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "huh? how can it be bad??")); |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| if (gXProcWorkaroundShareIndex != ui32Index) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "gXProcWorkaroundShareIndex == 0x%08x != 0x%08x == ui32Index", gXProcWorkaroundShareIndex, ui32Index)); |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX; |
| gXProcWorkaroundState = XPROC_WORKAROUND_UNKNOWN; |
| |
| return PVRSRV_OK; |
| } |
| |
| PVRSRV_ERROR BM_XProcWorkaroundFindNewBufferAndSetShareIndex(IMG_UINT32 *pui32Index) |
| { |
| |
| |
| |
| if (gXProcWorkaroundShareIndex != XPROC_WORKAROUND_BAD_SHAREINDEX) |
| { |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| for (*pui32Index = 0; *pui32Index < XPROC_WORKAROUND_NUM_SHAREABLES; (*pui32Index)++) |
| { |
| if (gXProcWorkaroundShareData[*pui32Index].ui32RefCount == 0) |
| { |
| gXProcWorkaroundShareIndex = *pui32Index; |
| gXProcWorkaroundState = XPROC_WORKAROUND_ALLOC; |
| return PVRSRV_OK; |
| } |
| } |
| |
| PVR_DPF((PVR_DBG_ERROR, "ran out of shared buffers")); |
| return PVRSRV_ERROR_OUT_OF_MEMORY; |
| } |
| |
| static PVRSRV_ERROR |
| XProcWorkaroundAllocShareable(RA_ARENA *psArena, |
| IMG_UINT32 ui32AllocFlags, |
| IMG_UINT32 ui32Size, |
| IMG_UINT32 ui32PageSize, |
| IMG_PVOID pvPrivData, |
| IMG_UINT32 ui32PrivDataLength, |
| IMG_VOID **ppvCpuVAddr, |
| IMG_HANDLE *phOSMemHandle) |
| { |
| if ((ui32AllocFlags & PVRSRV_MEM_XPROC) == 0) |
| { |
| PVR_DPF((PVR_DBG_VERBOSE, "XProcWorkaroundAllocShareable: bad flags")); |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| if (gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount > 0) |
| { |
| PVR_DPF((PVR_DBG_VERBOSE, |
| "XProcWorkaroundAllocShareable: re-using previously allocated pages")); |
| |
| ui32AllocFlags &= ~PVRSRV_HAP_MAPTYPE_MASK; |
| ui32AllocFlags |= PVRSRV_HAP_SINGLE_PROCESS; |
| |
| if (ui32AllocFlags != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "Can't! Flags don't match! (I had 0x%08x, you gave 0x%08x)", |
| gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags, |
| ui32AllocFlags)); |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| if (ui32Size != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32Size) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "Can't! Size doesn't match!")); |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| if (ui32PageSize != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32PageSize) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "Can't! Page Size doesn't match!")); |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| *ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr; |
| *phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle; |
| |
| gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount++; |
| |
| return PVRSRV_OK; |
| } |
| else |
| { |
| if (gXProcWorkaroundState != XPROC_WORKAROUND_ALLOC) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "XPROC workaround in bad state! About to allocate memory from non-alloc state! (%d)", |
| gXProcWorkaroundState)); |
| } |
| PVR_ASSERT(gXProcWorkaroundState == XPROC_WORKAROUND_ALLOC); |
| |
| if (psArena != IMG_NULL) |
| { |
| IMG_CPU_PHYADDR sCpuPAddr; |
| IMG_SYS_PHYADDR sSysPAddr; |
| |
| PVR_DPF((PVR_DBG_VERBOSE, |
| "XProcWorkaroundAllocShareable: making a NEW allocation from local mem")); |
| |
| if (!RA_Alloc (psArena, |
| ui32Size, |
| IMG_NULL, |
| IMG_NULL, |
| 0, |
| ui32PageSize, |
| 0, |
| pvPrivData, |
| ui32PrivDataLength, |
| (IMG_UINTPTR_T *)&sSysPAddr.uiAddr)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "XProcWorkaroundAllocShareable: RA_Alloc(0x%x) FAILED", ui32Size)); |
| return PVRSRV_ERROR_OUT_OF_MEMORY; |
| } |
| |
| sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr); |
| if(OSReservePhys(sCpuPAddr, |
| ui32Size, |
| ui32AllocFlags, |
| (IMG_VOID **)&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr, |
| &gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle) != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "XProcWorkaroundAllocShareable: OSReservePhys failed")); |
| return PVRSRV_ERROR_OUT_OF_MEMORY; |
| } |
| gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].sSysPAddr = sSysPAddr; |
| } |
| else |
| { |
| PVR_DPF((PVR_DBG_VERBOSE, |
| "XProcWorkaroundAllocShareable: making a NEW allocation from OS")); |
| |
| ui32AllocFlags &= ~PVRSRV_HAP_MAPTYPE_MASK; |
| ui32AllocFlags |= PVRSRV_HAP_SINGLE_PROCESS; |
| |
| |
| if (OSAllocPages(ui32AllocFlags, |
| ui32Size, |
| ui32PageSize, |
| pvPrivData, |
| ui32PrivDataLength, |
| (IMG_VOID **)&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr, |
| &gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle) != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "XProcWorkaroundAllocShareable: OSAllocPages(0x%x) failed", |
| ui32PageSize)); |
| return PVRSRV_ERROR_OUT_OF_MEMORY; |
| } |
| } |
| |
| gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].psArena = psArena; |
| gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags = ui32AllocFlags; |
| gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32Size = ui32Size; |
| gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32PageSize = ui32PageSize; |
| |
| *ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr; |
| *phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle; |
| |
| gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount++; |
| |
| return PVRSRV_OK; |
| } |
| } |
| |
| static PVRSRV_ERROR XProcWorkaroundHandleToSI(IMG_HANDLE hOSMemHandle, IMG_UINT32 *pui32SI) |
| { |
| |
| IMG_UINT32 ui32SI; |
| IMG_BOOL bFound; |
| IMG_BOOL bErrorDups; |
| |
| bFound = IMG_FALSE; |
| bErrorDups = IMG_FALSE; |
| |
| for (ui32SI = 0; ui32SI < XPROC_WORKAROUND_NUM_SHAREABLES; ui32SI++) |
| { |
| if (gXProcWorkaroundShareData[ui32SI].ui32RefCount>0 && gXProcWorkaroundShareData[ui32SI].hOSMemHandle == hOSMemHandle) |
| { |
| if (bFound) |
| { |
| bErrorDups = IMG_TRUE; |
| } |
| else |
| { |
| *pui32SI = ui32SI; |
| bFound = IMG_TRUE; |
| } |
| } |
| } |
| |
| if (bErrorDups || !bFound) |
| { |
| return PVRSRV_ERROR_BM_BAD_SHAREMEM_HANDLE; |
| } |
| |
| return PVRSRV_OK; |
| } |
| |
| static IMG_VOID XProcWorkaroundFreeShareable(IMG_HANDLE hOSMemHandle) |
| { |
| IMG_UINT32 ui32SI = (IMG_UINT32)((IMG_UINTPTR_T)hOSMemHandle & 0xffffU); |
| PVRSRV_ERROR eError; |
| |
| eError = XProcWorkaroundHandleToSI(hOSMemHandle, &ui32SI); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "bad handle")); |
| return; |
| } |
| |
| gXProcWorkaroundShareData[ui32SI].ui32RefCount--; |
| |
| PVR_DPF((PVR_DBG_VERBOSE, "Reduced refcount of SI[%d] from %d to %d", |
| ui32SI, gXProcWorkaroundShareData[ui32SI].ui32RefCount+1, gXProcWorkaroundShareData[ui32SI].ui32RefCount)); |
| |
| if (gXProcWorkaroundShareData[ui32SI].ui32RefCount == 0) |
| { |
| if (gXProcWorkaroundShareData[ui32SI].psArena != IMG_NULL) |
| { |
| IMG_SYS_PHYADDR sSysPAddr; |
| |
| if (gXProcWorkaroundShareData[ui32SI].pvCpuVAddr != IMG_NULL) |
| { |
| OSUnReservePhys(gXProcWorkaroundShareData[ui32SI].pvCpuVAddr, |
| gXProcWorkaroundShareData[ui32SI].ui32Size, |
| gXProcWorkaroundShareData[ui32SI].ui32AllocFlags, |
| gXProcWorkaroundShareData[ui32SI].hOSMemHandle); |
| } |
| sSysPAddr = gXProcWorkaroundShareData[ui32SI].sSysPAddr; |
| RA_Free (gXProcWorkaroundShareData[ui32SI].psArena, |
| sSysPAddr.uiAddr, |
| IMG_FALSE); |
| } |
| else |
| { |
| PVR_DPF((PVR_DBG_VERBOSE, "freeing OS memory")); |
| OSFreePages(gXProcWorkaroundShareData[ui32SI].ui32AllocFlags, |
| gXProcWorkaroundShareData[ui32SI].ui32PageSize, |
| gXProcWorkaroundShareData[ui32SI].pvCpuVAddr, |
| gXProcWorkaroundShareData[ui32SI].hOSMemHandle); |
| } |
| } |
| } |
| |
| |
| static IMG_BOOL |
| BM_ImportMemory (IMG_VOID *pH, |
| IMG_SIZE_T uRequestSize, |
| IMG_SIZE_T *pActualSize, |
| BM_MAPPING **ppsMapping, |
| IMG_UINT32 uFlags, |
| IMG_PVOID pvPrivData, |
| IMG_UINT32 ui32PrivDataLength, |
| IMG_UINTPTR_T *pBase) |
| { |
| BM_MAPPING *pMapping; |
| BM_HEAP *pBMHeap = pH; |
| BM_CONTEXT *pBMContext = pBMHeap->pBMContext; |
| IMG_BOOL bResult; |
| IMG_SIZE_T uSize; |
| IMG_SIZE_T uPSize; |
| IMG_SIZE_T uDevVAddrAlignment = 0; |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, |
| "BM_ImportMemory (pBMContext=0x%x, uRequestSize=0x%x, uFlags=0x%x, uAlign=0x%x)", |
| (IMG_UINTPTR_T)pBMContext, uRequestSize, uFlags, uDevVAddrAlignment)); |
| |
| PVR_ASSERT (ppsMapping != IMG_NULL); |
| PVR_ASSERT (pBMContext != IMG_NULL); |
| |
| if (ppsMapping == IMG_NULL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: invalid parameter")); |
| goto fail_exit; |
| } |
| |
| uSize = HOST_PAGEALIGN (uRequestSize); |
| PVR_ASSERT (uSize >= uRequestSize); |
| |
| if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, |
| sizeof (BM_MAPPING), |
| (IMG_PVOID *)&pMapping, IMG_NULL, |
| "Buffer Manager Mapping") != PVRSRV_OK) |
| { |
| PVR_DPF ((PVR_DBG_ERROR, "BM_ImportMemory: failed BM_MAPPING alloc")); |
| goto fail_exit; |
| } |
| |
| pMapping->hOSMemHandle = 0; |
| pMapping->CpuVAddr = 0; |
| pMapping->DevVAddr.uiAddr = 0; |
| pMapping->CpuPAddr.uiAddr = 0; |
| pMapping->uSize = uSize; |
| pMapping->pBMHeap = pBMHeap; |
| pMapping->ui32Flags = uFlags; |
| |
| |
| if (pActualSize) |
| { |
| *pActualSize = uSize; |
| } |
| |
| |
| if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY) |
| { |
| uPSize = pBMHeap->sDevArena.ui32DataPageSize; |
| } |
| else |
| { |
| uPSize = pMapping->uSize; |
| } |
| |
| if (uFlags & PVRSRV_MEM_XPROC) |
| { |
| IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs | PVRSRV_MEM_XPROC; |
| IMG_BOOL bBadBackingStoreType; |
| |
| |
| if(uFlags & PVRSRV_MEM_ION) |
| { |
| ui32Attribs |= PVRSRV_MEM_ION; |
| } |
| |
| bBadBackingStoreType = IMG_TRUE; |
| |
| if ((ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) != 0) |
| { |
| #ifndef MAX |
| #define MAX(a,b) ((a) > (b) ? (a) : (b)) |
| #endif |
| uDevVAddrAlignment = MAX(pBMHeap->sDevArena.ui32DataPageSize, HOST_PAGESIZE()); |
| |
| |
| if (uPSize % uDevVAddrAlignment != 0) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "Cannot use use this memory sharing workaround with allocations that might be suballocated")); |
| goto fail_mapping_alloc; |
| } |
| uDevVAddrAlignment = 0; |
| |
| |
| if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) |
| { |
| ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK; |
| ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK); |
| } |
| |
| |
| if (XProcWorkaroundAllocShareable(IMG_NULL, |
| ui32Attribs, |
| (IMG_UINT32)uPSize, |
| pBMHeap->sDevArena.ui32DataPageSize, |
| pvPrivData, |
| ui32PrivDataLength, |
| (IMG_VOID **)&pMapping->CpuVAddr, |
| &pMapping->hOSMemHandle) != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "BM_ImportMemory: XProcWorkaroundAllocShareable(0x%x) failed", |
| uPSize)); |
| goto fail_mapping_alloc; |
| } |
| |
| |
| |
| |
| pMapping->eCpuMemoryOrigin = hm_env; |
| bBadBackingStoreType = IMG_FALSE; |
| } |
| |
| if ((ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) != 0) |
| { |
| uDevVAddrAlignment = pBMHeap->sDevArena.ui32DataPageSize; |
| |
| if (uPSize % uDevVAddrAlignment != 0) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "Cannot use use this memory sharing workaround with allocations that might be suballocated")); |
| goto fail_mapping_alloc; |
| } |
| uDevVAddrAlignment = 0; |
| |
| |
| if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) |
| { |
| ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK; |
| ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK); |
| } |
| |
| |
| if (XProcWorkaroundAllocShareable(pBMHeap->pLocalDevMemArena, |
| ui32Attribs, |
| (IMG_UINT32)uPSize, |
| pBMHeap->sDevArena.ui32DataPageSize, |
| pvPrivData, |
| ui32PrivDataLength, |
| (IMG_VOID **)&pMapping->CpuVAddr, |
| &pMapping->hOSMemHandle) != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "BM_ImportMemory: XProcWorkaroundAllocShareable(0x%x) failed", |
| uPSize)); |
| goto fail_mapping_alloc; |
| } |
| |
| |
| |
| |
| pMapping->eCpuMemoryOrigin = hm_env; |
| bBadBackingStoreType = IMG_FALSE; |
| } |
| |
| if (bBadBackingStoreType) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "Cannot use this memory sharing workaround with this type of backing store")); |
| goto fail_mapping_alloc; |
| } |
| } |
| else |
| |
| |
| |
| if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) |
| { |
| IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs; |
| |
| |
| if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) |
| { |
| ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK; |
| ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK); |
| } |
| |
| if (pMapping->ui32Flags & PVRSRV_MEM_ALLOCATENONCACHEDMEM) |
| { |
| ui32Attribs &= ~PVRSRV_MEM_ALLOCATENONCACHEDMEM; |
| ui32Attribs |= (pMapping->ui32Flags & PVRSRV_MEM_ALLOCATENONCACHEDMEM); |
| } |
| |
| |
| if (OSAllocPages(ui32Attribs, |
| uPSize, |
| pBMHeap->sDevArena.ui32DataPageSize, |
| pvPrivData, |
| ui32PrivDataLength, |
| (IMG_VOID **)&pMapping->CpuVAddr, |
| &pMapping->hOSMemHandle) != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "BM_ImportMemory: OSAllocPages(0x%x) failed", |
| uPSize)); |
| goto fail_mapping_alloc; |
| } |
| |
| |
| pMapping->eCpuMemoryOrigin = hm_env; |
| } |
| else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) |
| { |
| IMG_SYS_PHYADDR sSysPAddr; |
| IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs; |
| |
| |
| PVR_ASSERT(pBMHeap->pLocalDevMemArena != IMG_NULL); |
| |
| |
| if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) |
| { |
| ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK; |
| ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK); |
| } |
| |
| if (!RA_Alloc (pBMHeap->pLocalDevMemArena, |
| uPSize, |
| IMG_NULL, |
| IMG_NULL, |
| 0, |
| pBMHeap->sDevArena.ui32DataPageSize, |
| 0, |
| pvPrivData, |
| ui32PrivDataLength, |
| (IMG_UINTPTR_T *)&sSysPAddr.uiAddr)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: RA_Alloc(0x%x) FAILED", uPSize)); |
| goto fail_mapping_alloc; |
| } |
| |
| |
| pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr); |
| if(OSReservePhys(pMapping->CpuPAddr, |
| uPSize, |
| ui32Attribs, |
| &pMapping->CpuVAddr, |
| &pMapping->hOSMemHandle) != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: OSReservePhys failed")); |
| goto fail_dev_mem_alloc; |
| } |
| |
| |
| pMapping->eCpuMemoryOrigin = hm_contiguous; |
| } |
| else |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: Invalid backing store type")); |
| goto fail_mapping_alloc; |
| } |
| |
| |
| bResult = DevMemoryAlloc (pBMContext, |
| pMapping, |
| IMG_NULL, |
| uFlags, |
| (IMG_UINT32)uDevVAddrAlignment, |
| &pMapping->DevVAddr); |
| if (!bResult) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "BM_ImportMemory: DevMemoryAlloc(0x%x) failed", |
| pMapping->uSize)); |
| goto fail_dev_mem_alloc; |
| } |
| |
| |
| |
| PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1); |
| |
| *pBase = pMapping->DevVAddr.uiAddr; |
| *ppsMapping = pMapping; |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, "BM_ImportMemory: IMG_TRUE")); |
| return IMG_TRUE; |
| |
| fail_dev_mem_alloc: |
| if (pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle)) |
| { |
| |
| if(pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) |
| { |
| pMapping->uSize /= 2; |
| } |
| |
| if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY) |
| { |
| uPSize = pBMHeap->sDevArena.ui32DataPageSize; |
| } |
| else |
| { |
| uPSize = pMapping->uSize; |
| } |
| |
| if (uFlags & PVRSRV_MEM_XPROC) |
| { |
| XProcWorkaroundFreeShareable(pMapping->hOSMemHandle); |
| } |
| else |
| if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) |
| { |
| OSFreePages(pBMHeap->ui32Attribs, |
| uPSize, |
| (IMG_VOID *)pMapping->CpuVAddr, |
| pMapping->hOSMemHandle); |
| } |
| else |
| { |
| IMG_SYS_PHYADDR sSysPAddr; |
| |
| if(pMapping->CpuVAddr) |
| { |
| OSUnReservePhys(pMapping->CpuVAddr, |
| uPSize, |
| pBMHeap->ui32Attribs, |
| pMapping->hOSMemHandle); |
| } |
| sSysPAddr = SysCpuPAddrToSysPAddr(pMapping->CpuPAddr); |
| RA_Free (pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE); |
| } |
| } |
| fail_mapping_alloc: |
| OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL); |
| |
| fail_exit: |
| return IMG_FALSE; |
| } |
| |
| |
| static IMG_VOID |
| BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping) |
| { |
| BM_HEAP *pBMHeap = h; |
| IMG_SIZE_T uPSize; |
| |
| PVR_UNREFERENCED_PARAMETER (_base); |
| |
| PVR_DPF ((PVR_DBG_MESSAGE, |
| "BM_FreeMemory (h=0x%x, base=0x%x, psMapping=0x%x)", |
| (IMG_UINTPTR_T)h, _base, (IMG_UINTPTR_T)psMapping)); |
| |
| PVR_ASSERT (psMapping != IMG_NULL); |
| |
| if (psMapping == IMG_NULL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: invalid parameter")); |
| return; |
| } |
| |
| DevMemoryFree (psMapping); |
| |
| |
| if((psMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) != 0) |
| { |
| psMapping->uSize /= 2; |
| } |
| |
| if(psMapping->ui32Flags & PVRSRV_MEM_DUMMY) |
| { |
| uPSize = psMapping->pBMHeap->sDevArena.ui32DataPageSize; |
| } |
| else |
| { |
| uPSize = psMapping->uSize; |
| } |
| |
| if (psMapping->ui32Flags & PVRSRV_MEM_XPROC) |
| { |
| XProcWorkaroundFreeShareable(psMapping->hOSMemHandle); |
| } |
| else |
| if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) |
| { |
| OSFreePages(pBMHeap->ui32Attribs, |
| uPSize, |
| (IMG_VOID *) psMapping->CpuVAddr, |
| psMapping->hOSMemHandle); |
| } |
| else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) |
| { |
| IMG_SYS_PHYADDR sSysPAddr; |
| |
| OSUnReservePhys(psMapping->CpuVAddr, uPSize, pBMHeap->ui32Attribs, psMapping->hOSMemHandle); |
| |
| sSysPAddr = SysCpuPAddrToSysPAddr(psMapping->CpuPAddr); |
| |
| RA_Free (pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE); |
| } |
| else |
| { |
| PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: Invalid backing store type")); |
| } |
| |
| OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), psMapping, IMG_NULL); |
| |
| |
| PVR_DPF((PVR_DBG_MESSAGE, |
| "..BM_FreeMemory (h=0x%x, base=0x%x)", |
| (IMG_UINTPTR_T)h, _base)); |
| } |
| |
| IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo, |
| IMG_DEV_VIRTADDR sDevVPageAddr, |
| IMG_DEV_PHYADDR *psDevPAddr) |
| { |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| |
| PVR_DPF((PVR_DBG_MESSAGE, "BM_GetPhysPageAddr")); |
| |
| PVR_ASSERT (psMemInfo && psDevPAddr) |
| |
| |
| PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0); |
| |
| |
| psDeviceNode = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pBMContext->psDeviceNode; |
| |
| *psDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pMMUHeap, |
| sDevVPageAddr); |
| } |
| |
| |
| MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap) |
| { |
| BM_HEAP *pBMHeap = (BM_HEAP*)hDevMemHeap; |
| |
| PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUContext")); |
| |
| return pBMHeap->pBMContext->psMMUContext; |
| } |
| |
| MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext) |
| { |
| BM_CONTEXT *pBMContext = (BM_CONTEXT*)hDevMemContext; |
| |
| PVR_DPF ((PVR_DBG_VERBOSE, "BM_GetMMUContextFromMemContext")); |
| |
| return pBMContext->psMMUContext; |
| } |
| |
| IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap) |
| { |
| PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUHeap")); |
| |
| return (IMG_HANDLE)((BM_HEAP*)hDevMemHeap)->pMMUHeap; |
| } |
| |
| |
| PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext) |
| { |
| PVR_DPF((PVR_DBG_VERBOSE, "BM_GetDeviceNode")); |
| |
| return ((BM_CONTEXT*)hDevMemContext)->psDeviceNode; |
| } |
| |
| |
| IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo) |
| { |
| PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMappingHandle")); |
| |
| return ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->hOSMemHandle; |
| } |
| |