diff options
Diffstat (limited to 'pvr-source/services4/srvkm/common/buffer_manager.c')
-rwxr-xr-x | pvr-source/services4/srvkm/common/buffer_manager.c | 3573 |
1 files changed, 0 insertions, 3573 deletions
diff --git a/pvr-source/services4/srvkm/common/buffer_manager.c b/pvr-source/services4/srvkm/common/buffer_manager.c deleted file mode 100755 index 9ce7a11..0000000 --- a/pvr-source/services4/srvkm/common/buffer_manager.c +++ /dev/null @@ -1,3573 +0,0 @@ -/*************************************************************************/ /*! -@Title Buffer management functions for Linux -@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved -@Description Manages buffers mapped into two memory spaces - cpu and device, - either of which can be virtual or physical. -@License Dual MIT/GPLv2 - -The contents of this file are subject to the MIT license as set out below. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -Alternatively, the contents of this file may be used under the terms of -the GNU General Public License Version 2 ("GPL") in which case the provisions -of GPL are applicable instead of those above. - -If you wish to allow use of your version of this file only under the terms of -GPL, and not to allow others to use your version of this file under the terms -of the MIT license, indicate your decision by deleting the provisions above -and replace them with the notice and other provisions required by GPL as set -out in the file called "GPL-COPYING" included in this distribution. If you do -not delete the provisions above, a recipient may use your version of this file -under the terms of either the MIT license or GPL. - -This License is also included in this distribution in the file called -"MIT-COPYING". - -EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS -PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ /**************************************************************************/ - -#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_INT32 -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_INT32 -DevMemoryFree (BM_MAPPING *pMapping); - -/*! -****************************************************************************** - - @Function AllocMemory - - @Description Allocate a buffer mapped into both cpu and device virtual - address spaces. This is now quite simple: - - 1. Choose whence to get the memory; - 2. Obtain memory from that source; - 3. Work out the actual buffer addresses in other spaces. - - In choosing whence to get the memory we work like this: - - 1. If an import arena exists, use unless BP_CONTIGUOUS is set; - 2. Use a contiguous pool. - - @Input pBMContext - BM context - @Input psBMHeap - BM heap - @Input psDevVAddr - device virtual address (optional) - @Input uSize - requested buffer size in bytes. - @Input uFlags - property flags for the buffer. - @Input uDevVAddrAlignment - required device virtual address - alignment, or 0. - @Input pvPrivData - opaque private data passed through to allocator - @Input ui32PrivDataLength - length of opaque private data - - @Output pBuf - receives a pointer to a descriptor of the allocated - buffer. - @Return IMG_TRUE - Success - IMG_FALSE - Failed. - - *****************************************************************************/ -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, - IMG_UINT32 ui32ChunkSize, - IMG_UINT32 ui32NumVirtChunks, - IMG_UINT32 ui32NumPhysChunks, - IMG_BOOL *pabMapChunk, - 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)); - - /* - what to do depends on combination of DevVaddr generation - and backing RAM requirement - */ - if(uFlags & PVRSRV_MEM_RAM_BACKED_ALLOCATION) - { - if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) - { - /* user supplied DevVAddr, RAM backing */ - PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: combination of DevVAddr management and RAM backing mode unsupported")); - return IMG_FALSE; - } - - /* BM supplied DevVAddr, RAM Backing */ - - /* check heap attributes */ - if(psBMHeap->ui32Attribs - & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG - |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)) - { - /* specify arena (VM+RAM)*/ - 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; - } - - /* Now allocate from the arena we chose above. */ - /* in case of a pageable buffer, we must bypass RA which could - * combine/split individual mappings between buffers: - */ - if (uFlags & (PVRSRV_MEM_SPARSE | PVRSRV_HAP_GPU_PAGEABLE)) - { - IMG_BOOL bSuccess; - IMG_SIZE_T puiActualSize; - IMG_SIZE_T uRequestSize = uSize; - - if(uFlags & PVRSRV_MEM_SPARSE) - { - uRequestSize = ui32ChunkSize * ui32NumPhysChunks; - uSize = ui32ChunkSize * ui32NumVirtChunks; - } - - /* Allocate physical memory */ - if (!BM_ImportMemory(psBMHeap, - uRequestSize, - &puiActualSize, - &pMapping, - uFlags, - pvPrivData, - ui32PrivDataLength, - (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr))) - { - PVR_DPF((PVR_DBG_ERROR, - "BM_ImportMemory: Failed to allocate device memory")); - return IMG_FALSE; - } - pBuf->hOSMemHandle = pMapping->hOSMemHandle; - - /* We allocate VM space for sparse area */ - if(uFlags & PVRSRV_MEM_SPARSE) - { - if (puiActualSize != ui32ChunkSize * ui32NumPhysChunks) - { - /* - * Most likely the chunk size was not host page multiple, - * so return with an error - */ - PVR_DPF((PVR_DBG_ERROR, "AllocMemory: Failed to allocate" - "memory for sparse allocation")); - BM_FreeMemory(pArena, IMG_NULL, pMapping); - return IMG_FALSE; - } - - pMapping->uSizeVM = uSize; - pMapping->ui32ChunkSize = ui32ChunkSize; - pMapping->ui32NumVirtChunks = ui32NumVirtChunks; - pMapping->ui32NumPhysChunks = ui32NumPhysChunks; - pMapping->pabMapChunk = pabMapChunk; - - if (!(uFlags & PVRSRV_HAP_NO_GPU_VIRTUAL_ON_ALLOC)) - { - /* Allocate VA space and map in the physical memory */ - bSuccess = DevMemoryAlloc (pBMContext, - pMapping, - IMG_NULL, - uFlags, - (IMG_UINT32)uDevVAddrAlignment, - &pMapping->DevVAddr); - if (!bSuccess) - { - PVR_DPF((PVR_DBG_ERROR, - "AllocMemory: Failed to allocate device memory")); - BM_FreeMemory(pArena, IMG_NULL, pMapping); - return IMG_FALSE; - } - - /* uDevVAddrAlignment is currently set to zero so QAC - * generates warning which we override */ - /* PRQA S 3356,3358 1 */ - PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1); - pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr; - } - } - } - else - { - 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) hOSMemHandle %p, flags 0x%08x FAILED", - uSize, pMapping->hOSMemHandle, uFlags)); - 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->uSizeVM) - { - 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; - } - } - - /* for hm_contiguous and hm_wrapped memory, the pMapping - * will have a physical address, else 0 */ - 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) - { - /* user supplied DevVAddr, no RAM backing */ - PVR_ASSERT(psDevVAddr != IMG_NULL); - - if (psDevVAddr == IMG_NULL) - { - PVR_DPF((PVR_DBG_ERROR, "AllocMemory: invalid parameter - psDevVAddr")); - return IMG_FALSE; - } - - /* just make space in the pagetables */ - pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap, - uSize, - IMG_NULL, - PVRSRV_MEM_USER_SUPPLIED_DEVVADDR, - uDevVAddrAlignment, - psDevVAddr); - - /* setup buf */ - pBuf->DevVAddr = *psDevVAddr; - } - else - { - IMG_BOOL bResult; - /* BM supplied DevVAddr, no RAM Backing */ - - /* just make space in the pagetables */ - 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; - } - } - - /* allocate a mocked-up mapping */ - 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; - } - - /* setup buf */ - pBuf->CpuVAddr = IMG_NULL; - pBuf->hOSMemHandle = 0; - pBuf->CpuPAddr.uiAddr = 0; - - /* setup mapping */ - pMapping->CpuVAddr = IMG_NULL; - pMapping->CpuPAddr.uiAddr = 0; - pMapping->DevVAddr = pBuf->DevVAddr; - pMapping->ui32MappingCount = 1; - pMapping->psSysAddr = IMG_NULL; - pMapping->uSize = uSize; - pMapping->hOSMemHandle = 0; - } - - /* Record the arena pointer in the mapping. */ - pMapping->pArena = pArena; - pMapping->ui32DevVAddrAlignment = uDevVAddrAlignment; - - /* record the heap */ - pMapping->pBMHeap = psBMHeap; - pBuf->pMapping = pMapping; - - /* output some stats */ - 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)); - - /* Verify virtual device address alignment */ - PVR_ASSERT(((pBuf->DevVAddr.uiAddr) & (uDevVAddrAlignment - 1)) == 0); - - return IMG_TRUE; -} - - -/*! -****************************************************************************** - - @Function WrapMemory - - @Description Allocate a buffer mapped into both cpu and device virtual - address spaces. - - @Input psBMHeap - BM heap - @Input uSize - requested buffer size in bytes. - @Input ui32BaseOffset - Offset from page of wrap. - @Input bPhysContig - Is the wrap physically contiguous. - @Input psAddr - List of pages to wrap. - @Input pvCPUVAddr - Optional CPU Kernel virtual address (page aligned) of memory to wrap - @Input uFlags - property flags for the buffer. - @Output Buf - receives a pointer to a descriptor of the allocated - buffer. - @Return IMG_TRUE - Success - IMG_FALSE - Failed. - - *****************************************************************************/ -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_INT32 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); - /* Only need lower 12 bits of the cpu addr - don't care what size a void* is */ - PVR_ASSERT(((IMG_UINTPTR_T)pvCPUVAddr & (ui32PageSize - 1)) == 0); - - uSize += ui32BaseOffset; - uSize = HOST_PAGEALIGN (uSize); - - /* allocate a mocked-up mapping */ - 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->uSizeVM = 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, - IMG_NULL, - &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; - } - } - } - - /* - * Allocate device memory for this buffer. Map wrapped pages as read/write - */ - bResult = DevMemoryAlloc(psBMHeap->pBMContext, - pMapping, - IMG_NULL, - uFlags | PVRSRV_MEM_READ | PVRSRV_MEM_WRITE, - IMG_CAST_TO_DEVVADDR_UINT(ui32PageSize), - &DevVAddr); - if (bResult <= 0) - { - PVR_DPF((PVR_DBG_ERROR, - "WrapMemory: DevMemoryAlloc(0x%x) failed", - pMapping->uSize)); - goto fail_cleanup; - } - - /* - * 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. - */ - 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); - /*not nulling pointer, out of scope*/ - - 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; - - /* Walk through the pBuf one page at a time and use - * transient mappings to zero the memory */ - - PVR_ASSERT(pBuf->hOSMemHandle); - - while(ui32BytesRemaining > 0) - { - IMG_SIZE_T ui32BlockBytes = MIN(ui32BytesRemaining, HOST_PAGESIZE()); - CpuPAddr = OSMemHandleToCpuPAddr(pBuf->hOSMemHandle, ui32CurrentOffset); - /* If the CpuPAddr isn't page aligned then start by writing up to the next page - * boundary (or ui32BytesRemaining if less), so that subsequent iterations can - * copy full physical pages. */ - 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; -} - -/*! -****************************************************************************** - - @Function FreeBuf - - @Description Free a buffer previously allocated with BM_Alloc() or unwrap - one previous wrapped with BM_Wrap(). - The buffer is identified by the buffer descriptor pBuf - returned at allocation. Note the double indirection when - passing the buffer. - - - @Input pBuf - buffer descriptor to free. - @Input ui32Flags - flags - @Input bFromAllocator - Is this being called by the - allocator? - - @Return None. - - *****************************************************************************/ -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)); - - /* record mapping */ - pMapping = pBuf->pMapping; - - psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode; - if (psDeviceNode->pfnCacheInvalidate) - { - psDeviceNode->pfnCacheInvalidate(psDeviceNode); - } - - if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) - { - /* Submemhandle is required by exported mappings */ - if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0)) - { - /* user supplied Device Virtual Address */ - if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION) - { - /* RAM backed allocation */ - PVR_DPF ((PVR_DBG_ERROR, "FreeBuf: combination of DevVAddr management and RAM backing mode unsupported")); - } - else - { - /* free the mocked-up mapping */ - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL); - pBuf->pMapping = IMG_NULL; /*nulling pointer alias*/ - } - } - } - else - { - /* BM supplied Device Virtual Address */ - if(pBuf->hOSMemHandle != pMapping->hOSMemHandle) - { - /* Submemhandle is required by exported mappings */ - if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0)) - { - OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Flags); - } - } - - if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION) - { - /* Submemhandle is required by exported mappings */ - - if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0)) - { - /* - RAM backed allocation - Note: currently no need to distinguish between hm_env and hm_contiguous - */ - PVR_ASSERT(pBuf->ui32ExportCount == 0); - if (pBuf->pMapping->ui32Flags & (PVRSRV_MEM_SPARSE | PVRSRV_HAP_GPU_PAGEABLE)) - { - IMG_UINT32 ui32FreeSize = 0; - IMG_PVOID pvFreePtr = IMG_NULL; - - if(pBuf->pMapping->ui32Flags & PVRSRV_MEM_SPARSE) - { - ui32FreeSize = sizeof(IMG_BOOL) * pBuf->pMapping->ui32NumVirtChunks; - pvFreePtr = pBuf->pMapping->pabMapChunk; - } - - /* With sparse and page-able allocations we don't go through the sub-alloc RA */ - BM_FreeMemory(pBuf->pMapping->pBMHeap, pBuf->DevVAddr.uiAddr, pBuf->pMapping); - - if(pvFreePtr) - { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, - ui32FreeSize, - pvFreePtr, - IMG_NULL); - } - } - else - { - 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)) - { - /* free the mocked-up mapping */ - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL); - pBuf->pMapping = IMG_NULL; /*nulling pointer alias*/ - } - } - } - - - if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0)) - { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, IMG_NULL); - /*not nulling pointer, copy on stack*/ - } -} - -/*! -****************************************************************************** - - @Function BM_DestroyContext_AnyCb - - @Description Destroy a buffer manager heap. - - @Input psBMHeap - - @Return PVRSRV_ERROR - - *****************************************************************************/ -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; -} - - -/*! -****************************************************************************** - - @Function BM_DestroyContext - - @Description Destroy a buffer manager context. All allocated buffers must be - free'd before calling this function. This function is called - also to perform cleanup during aborted initialisations so it's - fairly careful not to assume any given resource has really been - created/allocated. - - @Return PVRSRV_ERROR - - *****************************************************************************/ -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; - } - - /* - Exit straight away if it's an invalid context handle - */ - if (pBMContext == IMG_NULL) - { - PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Invalid handle")); - return PVRSRV_ERROR_INVALID_PARAMS; - } - - pBMContext->ui32RefCount--; - - if (pBMContext->ui32RefCount > 0) - { - /* Just return if there are more references to this context */ - return PVRSRV_OK; - } - - /* - Check whether there is a bug in the client which brought it here before - all the allocations have been freed. - */ - 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")); - return eError; - } - else - { - /* free the device memory context */ - eError = ResManFreeResByPtr(pBMContext->hResItem, CLEANUP_WITH_POLL); - if(eError != PVRSRV_OK) - { - PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeResByPtr failed %d",eError)); - return eError; - } - - /* mark context as destroyed */ - if (pbDestroyed != IMG_NULL) - { - *pbDestroyed = IMG_TRUE; - } - } - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function BM_DestroyContextCallBack_AnyVaCb - - @Description Destroy Device memory context - - @Input psBMHeap - heap to be freed. - @Input va - list of variable arguments with the following contents: - - psDeviceNode - @Return PVRSRV_ERROR - - *****************************************************************************/ -static PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP *psBMHeap, va_list va) -{ - PVRSRV_DEVICE_NODE *psDeviceNode; - psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*); - - /* Free up the import arenas */ - 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; - } - - /* Free up the MMU Heaps */ - psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap); - - /* Free Heap memory */ - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL); - /*not nulling pointer, copy on stack*/ - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function BM_DestroyContextCallBack - - @Description Destroy Device memory context - - @Input pvParam - opaque void ptr param - @Input ui32Param - opaque unsigned long param - - @Return PVRSRV_ERROR - - *****************************************************************************/ -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; -/* BM_CONTEXT **ppBMContext; - BM_HEAP *psBMHeap, *psTmpBMHeap;*/ - - PVR_UNREFERENCED_PARAMETER(ui32Param); - PVR_UNREFERENCED_PARAMETER(bDummy); - - /* - Get DeviceNode from BMcontext - */ - psDeviceNode = pBMContext->psDeviceNode; - - /* - Free the import arenas and heaps - */ - eError = List_BM_HEAP_PVRSRV_ERROR_Any_va(pBMContext->psBMHeap, - &BM_DestroyContextCallBack_AnyVaCb, - psDeviceNode); - if (eError != PVRSRV_OK) - { - return eError; - } - /* - 'Finalise' the MMU - */ - if (pBMContext->psMMUContext) - { - psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext); - } - - /* - Free up generic, useful resources - if they were allocated. - */ - if (pBMContext->pBufferHash) - { - HASH_Delete(pBMContext->pBufferHash); - } - - if (pBMContext == psDeviceNode->sDevMemoryInfo.pBMKernelContext) - { - /* Freeing the kernel context */ - psDeviceNode->sDevMemoryInfo.pBMKernelContext = IMG_NULL; - } - else - { - if (pBMContext->ppsThis != IMG_NULL) - { - /* - * Remove context from the linked list - */ - List_BM_CONTEXT_Remove(pBMContext); - } - } - - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext, IMG_NULL); - /*not nulling pointer, copy on stack*/ - - 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) - { - /* just increment the refcount and return the memory context found for this process */ - 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: - { - /* insert the heap into the device's MMU page directory/table */ - psDeviceNode->pfnMMUInsertHeap(pBMContext->psMMUContext, psBMHeap->pMMUHeap); - break; - } - } -} - -/*! -****************************************************************************** - - @Function BM_CreateContext - - @Description Creates and initialises a buffer manager context. This function must be called - before any other buffer manager functions. - - @Return valid BM context handle - Success - IMG_NULL - Failed - - *****************************************************************************/ -IMG_HANDLE -BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode, - IMG_DEV_PHYADDR *psPDDevPAddr, - PVRSRV_PER_PROCESS_DATA *psPerProc, - IMG_BOOL *pbCreated) -{ - BM_CONTEXT *pBMContext; -/* BM_HEAP *psBMHeap;*/ - 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; - } - - /* setup the device memory info. */ - 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; - } - } - - /* allocate a BM context */ - 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)); - - /* store the associated devicenode */ - pBMContext->psDeviceNode = psDeviceNode; - - /* This hash table is used to store BM_Wraps in a global way */ - /* INTEGRATION_POINT: 32 is an abitrary limit on the number of hashed BM_wraps */ - 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) - { - /* just save the kernel context */ - PVR_ASSERT(psDevMemoryInfo->pBMKernelContext == IMG_NULL); - psDevMemoryInfo->pBMKernelContext = pBMContext; - } - else - { - /* - On the creation of each new context we must - insert the kernel context's 'shared' and 'shared_exported' - heaps into the new context - - check the kernel context and heaps exist - */ - 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); - - /* - insert the kernel heaps structures into the new context's shared heap list - Note. this will include the kernel only heaps but these will not actually - be imported into the context nor returned to the client - */ - pBMContext->psBMSharedHeap = psDevMemoryInfo->pBMKernelContext->psBMHeap; - - /* - insert the shared heaps into the MMU page directory/table - for the new context - */ - List_BM_HEAP_ForEach_va(pBMContext->psBMSharedHeap, - &BM_CreateContext_InsertHeap_ForEachVaCb, - psDeviceNode, - pBMContext); - - /* Finally, insert the new context into the list of BM contexts */ - List_BM_CONTEXT_Insert(&psDevMemoryInfo->pBMContext, pBMContext); - } - - /* Increment the refcount, as creation is successful */ - pBMContext->ui32RefCount++; - - /* register with resman */ - 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) - { - /* Match - just return already created heap */ - return psBMHeap; - } - else - { - return IMG_NULL; - } -} - -/*! -****************************************************************************** - - @Function BM_CreateHeap - - @Description Creates and initialises a BM heap for a given BM context. - - @Return - valid heap handle - success - IMG_NULL - failure - - - *****************************************************************************/ -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; - - /* - * Ensure that the heap size is a multiple of the data page size. - */ - PVR_ASSERT((psDevMemHeapInfo->ui32HeapSize & (psDevMemHeapInfo->ui32DataPageSize - 1)) == 0); - PVR_ASSERT(psDevMemHeapInfo->ui32HeapSize > 0); - - /* - We may be being asked to create a heap in a context which already has one. - Test for refcount > 0 because PVRSRVGetDeviceMemHeapInfoKM doesn't increment the refcount. - This does mean that the first call to PVRSRVCreateDeviceMemContextKM will first try to find - heaps that we already know don't exist - */ - 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 - - /* tie the heap to the context */ - 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; - } - - /* memory is allocated from the OS as required */ - 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) - { - /* - memory comes from a device memory contiguous allocator (ra) - Note: these arenas are shared across the system so don't delete - as part of heap destroy - */ - psBMHeap->pLocalDevMemArena = psDevMemHeapInfo->psLocalDevMemArena; - if(psBMHeap->pLocalDevMemArena == IMG_NULL) - { - PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: LocalDevMemArena null")); - goto ErrorExit; - } - } - - /* insert heap into head of the heap list */ - List_BM_HEAP_Insert(&pBMContext->psBMHeap, psBMHeap); - - return (IMG_HANDLE)psBMHeap; - - /* handle error case */ -ErrorExit: - - /* Free up the MMU if we created one */ - if (psBMHeap->pMMUHeap != IMG_NULL) - { - psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap); - /* don't finalise psMMUContext as we don't own it */ - } - - /* Free the Heap memory */ - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL); - /*not nulling pointer, out of scope*/ - - return IMG_NULL; -} - -/*! -****************************************************************************** - - @Function BM_DestroyHeap - - @Description Destroys a BM heap - - @Return - valid heap handle - success - IMG_NULL - failure - - - *****************************************************************************/ -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) - { - /* Free up the import arenas */ - 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; - } - - /* Free up the MMU Heap */ - psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap); - - /* remove from the heap list */ - 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")); - } -} - - -/*! -****************************************************************************** - - @Function BM_Reinitialise - - @Description Reinitialise the buffer manager after a power down event. - - @Return IMG_TRUE - Success - IMG_FALSE - Failed - - *****************************************************************************/ -IMG_BOOL -BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode) -{ - - PVR_DPF((PVR_DBG_MESSAGE, "BM_Reinitialise")); - PVR_UNREFERENCED_PARAMETER(psDeviceNode); - - /* FIXME: Need to reenable all contexts - List_BM_CONTEXT_ForEach(psDeviceNode->sDevMemoryInfo.pBMContext, MMU_Enable); - */ - - return IMG_TRUE; -} - -/*! -****************************************************************************** - - @Function BM_Alloc - - @Description Allocate a buffer mapped into both cpu and device virtual - memory maps. - - @Input hDevMemHeap - @Input psDevVAddr - device virtual address specified by caller (optional) - @Input uSize - require size in bytes of the buffer. - @Input pui32Flags - bit mask of buffer property flags. - @Input uDevVAddrAlignment - required alignment in bytes, or 0. - @Input pvPrivData - opaque private data passed through to allocator - @Input ui32PrivDataLength - length of opaque private data - - @Output phBuf - receives buffer handle - @Output pui32Flags - bit mask of heap property flags. - - @Return IMG_TRUE - Success - IMG_FALSE - Failure - - *****************************************************************************/ -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, - IMG_UINT32 ui32ChunkSize, - IMG_UINT32 ui32NumVirtChunks, - IMG_UINT32 ui32NumPhysChunks, - IMG_BOOL *pabMapChunk, - 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; - } - - /* - * Allocate something in which to record the allocation's details. - */ - 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)); - - /* - * Allocate the memory itself now. - */ - if (AllocMemory(pBMContext, - psBMHeap, - psDevVAddr, - uSize, - uFlags, - uDevVAddrAlignment, - pvPrivData, - ui32PrivDataLength, - ui32ChunkSize, - ui32NumVirtChunks, - ui32NumPhysChunks, - pabMapChunk, - pBuf) != IMG_TRUE) - { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL); - /* not nulling pointer, out of scope */ - 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)); - - /* - * Assign the handle and return. - */ - pBuf->ui32RefCount = 1; - *phBuf = (BM_HANDLE)pBuf; - *pui32Flags = uFlags | psBMHeap->ui32Attribs; - - /* - * If the user has specified heap CACHETYPE flags themselves, - * override any CACHETYPE flags inherited from the heap. - */ - if(uFlags & PVRSRV_HAP_CACHETYPE_MASK) - { - *pui32Flags &= ~PVRSRV_HAP_CACHETYPE_MASK; - *pui32Flags |= (uFlags & PVRSRV_HAP_CACHETYPE_MASK); - } - - return IMG_TRUE; -} - - - -#if defined(PVR_LMA) -/*! -****************************************************************************** - - @Function ValidSysPAddrArrayForDev - - @Description Verify the array of system address is accessible - by the given device. - - @Input psDeviceNode - @Input psSysPAddr - system address array - @Input ui32PageSize - size of address array - - @Return IMG_BOOL - - *****************************************************************************/ -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; -} - -/*! -****************************************************************************** - - @Function ValidSysPAddrRangeForDev - - @Description Verify a system address range is accessible - by the given device. - - @Input psDeviceNode - @Input sStartSysPAddr - starting system address - @Input ui32Range - length of address range - - @Return IMG_BOOL - - *****************************************************************************/ -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 - - -/*! -****************************************************************************** - - @Function BM_Wrap - - @Description Create a buffer which wraps user provided system physical - memory. - The wrapped memory must be page aligned. BM_Wrap will - roundup the size to a multiple of cpu pages. - - @Input ui32Size - size of memory to wrap. - @Input ui32Offset - Offset into page of memory to wrap. - @Input bPhysContig - Is the wrap physically contiguous. - @Input psSysAddr - list of system physical page addresses of memory to wrap. - @Input pvCPUVAddr - optional CPU kernel virtual address (Page aligned) of memory to wrap. - @Input uFlags - bit mask of buffer property flags. - @output phBuf - receives the buffer handle. - - @Return IMG_TRUE - Success. - IMG_FALSE - Failed - - *****************************************************************************/ -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 | PVRSRV_HAP_MAPPING_CTRL_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 - /* - * Insert the System Physical Address of the first page into the hash so we can optimise multiple wraps of the - * same memory. - */ - sHashAddress = psSysAddr[0]; - - /* Add the in-page offset to ensure a unique hash */ - sHashAddress.uiAddr += ui32Offset; - - /* See if this address has already been wrapped */ - pBuf = (BM_BUF *)HASH_Retrieve(psBMContext->pBufferHash, sHashAddress.uiAddr); - - if(pBuf) - { - IMG_SIZE_T ui32MappingSize = HOST_PAGEALIGN (ui32Size + ui32Offset); - - /* Check base address, size and contiguity type match */ - 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 - { - /* Otherwise removed that item from the hash table - (a workaround for buffer device class) */ - HASH_Remove(psBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddress.uiAddr); - } - } - - /* - * Allocate something in which to record the allocation's details. - */ - 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)); - - /* - * Actually perform the memory wrap. - */ - 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); - /*not nulling pointer, out of scope*/ - return IMG_FALSE; - } - - /* Only insert the buffer in the hash table if it is contiguous - allows for optimisation of multiple wraps - * of the same contiguous buffer. - */ - if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr) - { - /* Have we calculated the right Hash key ? */ - 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)); - - /* - * Assign the handle and return. - */ - pBuf->ui32RefCount = 1; - *phBuf = (BM_HANDLE)pBuf; - if(pui32Flags) - { - /* need to override the heap attributes SINGLE PROC to MULT_PROC. */ - *pui32Flags = (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) | PVRSRV_HAP_MULTI_PROCESS; - } - - return IMG_TRUE; -} - -/*! -****************************************************************************** - - @Function BM_Export - - @Description Export a buffer previously allocated via BM_Alloc. - - @Input hBuf - buffer handle. - @Input ui32Flags - flags - - @Return None. - - *****************************************************************************/ - -IMG_VOID -BM_Export (BM_HANDLE hBuf) -{ - BM_BUF *pBuf = (BM_BUF *)hBuf; - - PVRSRVBMBufIncExport(pBuf); -} - -/*! -****************************************************************************** - @Function BM_Export - - @Description Export a buffer previously allocated via BM_Alloc. - - @Input hBuf - buffer handle. - - @Return None. -**************************************************************************/ -IMG_VOID -BM_FreeExport(BM_HANDLE hBuf, - IMG_UINT32 ui32Flags) -{ - BM_BUF *pBuf = (BM_BUF *)hBuf; - - PVRSRVBMBufDecExport(pBuf); - FreeBuf (pBuf, ui32Flags, IMG_FALSE); -} - -/*! -****************************************************************************** - @Function BM_FreeExport - - @Description Free a buffer previously exported via BM_Export. - - @Input hBuf - buffer handle. - @Input ui32Flags - flags - - @Return None. -**************************************************************************/ -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); - } -} - - -/*! -****************************************************************************** - - @Function BM_HandleToCpuVaddr - - @Description Retreive the cpu virtual address associated with a buffer. - - @Input buffer handle. - - @Return buffers cpu virtual address, or NULL if none exists - - *****************************************************************************/ -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; -} - - -/*! -****************************************************************************** - - @Function BM_HandleToDevVaddr - - @Description Retreive the device virtual address associated with a buffer. - - @Input hBuf - buffer handle. - - @Return buffers device virtual address. - - *****************************************************************************/ -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; -} - - -/*! -****************************************************************************** - - @Function BM_HandleToSysPaddr - - @Description Retreive the system physical address associated with a buffer. - - @Input hBuf - buffer handle. - - @Return buffers device virtual address. - - *****************************************************************************/ -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); -} - -/*! -****************************************************************************** - - @Function BM_HandleToMemOSHandle - - @Description Retreive the underlying memory handle associated with a buffer. - - @Input hBuf - buffer handle. - - @Return OS Specific memory handle. - - *****************************************************************************/ -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; -} - -/*---------------------------------------------------------------------------- -<function> - FUNCTION: BM_UnmapFromDev - - PURPOSE: Unmaps a buffer from GPU virtual address space, but otherwise - leaves buffer intact (ie. not changing any CPU virtual space - mappings, etc). This in conjunction with BM_RemapToDev() can - be used to migrate buffers in and out of GPU virtual address - space to deal with fragmentation and/or limited size of GPU - MMU. - - PARAMETERS: In: hBuf - buffer handle. - RETURNS: IMG_TRUE - Success - IMG_FALSE - Failure -</function> ------------------------------------------------------------------------------*/ -IMG_INT32 -BM_UnmapFromDev(BM_HANDLE hBuf) -{ - BM_BUF *pBuf = (BM_BUF *)hBuf; - BM_MAPPING *pMapping; - IMG_INT32 result; - - PVR_ASSERT (pBuf != IMG_NULL); - - if (pBuf == IMG_NULL) - { - PVR_DPF((PVR_DBG_ERROR, "BM_UnmapFromDev: invalid parameter")); - return -(PVRSRV_ERROR_INVALID_PARAMS); - } - - pMapping = pBuf->pMapping; - - if ((pMapping->ui32Flags & PVRSRV_HAP_GPU_PAGEABLE) == 0) - { - PVR_DPF((PVR_DBG_ERROR, "BM_UnmapFromDev: cannot unmap non-pageable buffer")); - return -(PVRSRV_ERROR_STILL_MAPPED); - } - - result = DevMemoryFree(pMapping); - - if(result == 0) - pBuf->DevVAddr.uiAddr = PVRSRV_BAD_DEVICE_ADDRESS; - - return result; -} - -/*---------------------------------------------------------------------------- -<function> - FUNCTION: BM_RemapToDev - - PURPOSE: Maps a buffer back into GPU virtual address space, after it - has been BM_UnmapFromDev()'d. After this operation, the GPU - virtual address may have changed, so BM_HandleToDevVaddr() - should be called to get the new address. - - PARAMETERS: In: hBuf - buffer handle. - RETURNS: IMG_TRUE - Success - IMG_FALSE - Failure -</function> ------------------------------------------------------------------------------*/ -IMG_INT32 -BM_RemapToDev(BM_HANDLE hBuf) -{ - BM_BUF *pBuf = (BM_BUF *)hBuf; - BM_MAPPING *pMapping; - IMG_INT32 mapCount; - - PVR_ASSERT (pBuf != IMG_NULL); - - if (pBuf == IMG_NULL) - { - PVR_DPF((PVR_DBG_ERROR, "BM_RemapToDev: invalid parameter")); - return -PVRSRV_ERROR_INVALID_PARAMS; - } - - pMapping = pBuf->pMapping; - - if ((pMapping->ui32Flags & PVRSRV_HAP_GPU_PAGEABLE) == 0) - { - PVR_DPF((PVR_DBG_ERROR, "BM_RemapToDev: cannot remap non-pageable buffer")); - return -PVRSRV_ERROR_BAD_MAPPING; - } - - mapCount = DevMemoryAlloc(pMapping->pBMHeap->pBMContext, pMapping, IMG_NULL, - pMapping->ui32Flags, pMapping->ui32DevVAddrAlignment, &pBuf->DevVAddr); - - if(mapCount <= 0) - { - PVR_DPF((PVR_DBG_WARNING, "BM_RemapToDev: failed to allocate device memory")); - } - - return mapCount; -} - -/*! -****************************************************************************** - - @Function DevMemoryAlloc - - @Description Allocate device memory for a given physical/virtual memory - mapping. We handle the main cases where device MMU mappings - are required - these are the dynamic cases: all wrappings of - host OS memory and host OS imports for SYS_MMU_NORMAL mode. - - If no MMU support is required then we simply map device virtual - space as device physical space. - - @Input pBMContext - the pager to allocate from. - @Output pMapping - the mapping descriptor to be filled in for this - allocation. - @Output pActualSize - the actual size of the block allocated in - bytes. - @Input uFlags - allocation flags - @Input dev_vaddr_alignment - required device virtual address - alignment, or 0. - @Output pDevVAddr - receives the device virtual base address of the - allocated block. - @Return IMG_INT32 - Reference count - -1 - Failed. - - *****************************************************************************/ -static IMG_INT32 -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 - - if(pMapping->ui32MappingCount > 0) - { - pMapping->ui32MappingCount++; - *pDevVAddr = pMapping->DevVAddr; - return pMapping->ui32MappingCount; - } - - psDeviceNode = pBMContext->psDeviceNode; - - pMapping->ui32DevVAddrAlignment = dev_vaddr_alignment; - - if(uFlags & PVRSRV_MEM_INTERLEAVED) - { - /* double the size */ - /* don't continue to alter the size each time a buffer is remapped.. - * we only want to do this the first time - */ - /* TODO: FIXME: There is something wrong with this logic */ - if (pMapping->ui32MappingCount == 0) - pMapping->uSize *= 2; - } - -#ifdef PDUMP - if(uFlags & PVRSRV_MEM_DUMMY) - { - /* only one page behind a dummy allocation */ - ui32PDumpSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize; - } -#endif - - /* Check we haven't fall through a gap */ - PVR_ASSERT(pMapping->uSizeVM != 0); - /* allocate device linear space */ - if (!psDeviceNode->pfnMMUAlloc (pMapping->pBMHeap->pMMUHeap, - pMapping->uSizeVM, - pActualSize, - 0, - dev_vaddr_alignment, - &(pMapping->DevVAddr))) - { - PVR_DPF((PVR_DBG_ERROR, "DevMemoryAlloc ERROR MMU_Alloc")); - pDevVAddr->uiAddr = PVRSRV_BAD_DEVICE_ADDRESS; - return -(PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY); - } - -#ifdef SUPPORT_SGX_MMU_BYPASS - EnableHostAccess(pBMContext->psMMUContext); -#endif - -#if defined(PDUMP) - /* pdump the memory allocate */ - 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, // unused -#endif /* SUPPORT_PDUMP_MULTI_PROCESS */ - (IMG_HANDLE)pMapping); -#endif - - switch (pMapping->eCpuMemoryOrigin) - { - case hm_wrapped: - case hm_wrapped_virtaddr: - case hm_contiguous: - { - if (uFlags & PVRSRV_MEM_SPARSE) - { - /* Check if this device supports sparse mappings */ - PVR_ASSERT(psDeviceNode->pfnMMUMapPagesSparse != IMG_NULL); - psDeviceNode->pfnMMUMapPagesSparse(pMapping->pBMHeap->pMMUHeap, - pMapping->DevVAddr, - SysCpuPAddrToSysPAddr (pMapping->CpuPAddr), - pMapping->ui32ChunkSize, - pMapping->ui32NumVirtChunks, - pMapping->ui32NumPhysChunks, - pMapping->pabMapChunk, - uFlags, - (IMG_HANDLE)pMapping); - } - else - { - psDeviceNode->pfnMMUMapPages ( pMapping->pBMHeap->pMMUHeap, - pMapping->DevVAddr, - SysCpuPAddrToSysPAddr (pMapping->CpuPAddr), - pMapping->uSize, - uFlags, - (IMG_HANDLE)pMapping); - } - *pDevVAddr = pMapping->DevVAddr; - break; - } - case hm_env: - { - if (uFlags & PVRSRV_MEM_SPARSE) - { - /* Check if this device supports sparse mappings */ - PVR_ASSERT(psDeviceNode->pfnMMUMapShadowSparse != IMG_NULL); - psDeviceNode->pfnMMUMapShadowSparse(pMapping->pBMHeap->pMMUHeap, - pMapping->DevVAddr, - pMapping->ui32ChunkSize, - pMapping->ui32NumVirtChunks, - pMapping->ui32NumPhysChunks, - pMapping->pabMapChunk, - pMapping->CpuVAddr, - pMapping->hOSMemHandle, - pDevVAddr, - uFlags, - (IMG_HANDLE)pMapping); - } - else - { - 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 -(PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE); - } - -#ifdef SUPPORT_SGX_MMU_BYPASS - DisableHostAccess(pBMContext->psMMUContext); -#endif - - pMapping->ui32MappingCount = 1; - - return pMapping->ui32MappingCount; -} - -static IMG_INT32 -DevMemoryFree (BM_MAPPING *pMapping) -{ - PVRSRV_DEVICE_NODE *psDeviceNode; - IMG_DEV_PHYADDR sDevPAddr; -#ifdef PDUMP - IMG_UINT32 ui32PSize; -#endif - - if(pMapping->ui32MappingCount > 1) - { - pMapping->ui32MappingCount--; - - /* Nothing else to do for now */ - return pMapping->ui32MappingCount; - } - - if (pMapping->ui32MappingCount == 0) - { - /* already unmapped from GPU.. bail */ - return -(PVRSRV_ERROR_MAPPING_NOT_FOUND); - } - - /* Then pMapping->ui32MappingCount is 1 - * ready to release GPU mapping */ - - psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode; - sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr); - - if (sDevPAddr.uiAddr != 0) - { -#ifdef PDUMP - /* pdump the memory free */ - if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY) - { - /* physical memory size differs in the case of Dummy allocations */ - 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, - (pMapping->ui32Flags & PVRSRV_MEM_SPARSE) ? IMG_TRUE : IMG_FALSE); -#endif - } - PVR_ASSERT(pMapping->uSizeVM != 0); - psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSizeVM)); - - pMapping->ui32MappingCount = 0; - - return pMapping->ui32MappingCount; -} - -/* If this array grows larger, it might be preferable to use a hashtable rather than an array. */ -#ifndef XPROC_WORKAROUND_NUM_SHAREABLES -#define XPROC_WORKAROUND_NUM_SHAREABLES 500 -#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; - -/* PRQA S 0686 10 */ /* force compiler to init structure */ -XPROC_DATA gXProcWorkaroundShareData[XPROC_WORKAROUND_NUM_SHAREABLES] = {{0}}; - -IMG_INT32 BM_XProcGetShareDataRefCount(IMG_UINT32 ui32Index) -{ - if(ui32Index >= XPROC_WORKAROUND_NUM_SHAREABLES) - return -1; - - return gXProcWorkaroundShareData[ui32Index].ui32RefCount; -} - -PVRSRV_ERROR BM_XProcWorkaroundSetShareIndex(IMG_UINT32 ui32Index) -{ - /* if you fail this assertion - did you acquire the mutex? - did you call "set" exactly once? - did you call "unset" exactly once per set? - */ - 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 you fail this assertion - did you acquire the mutex? - did you call "set" exactly once? - did you call "unset" exactly once per set? - */ - 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 you fail this assertion - did you acquire the mutex? - did you call "set" exactly once? - did you call "unset" exactly once per set? - */ - 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, - "%s ERROR: Flags don't match (Shared 0x%08x, Requested 0x%08x)!", - __FUNCTION__, - gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags, - ui32AllocFlags)); - return PVRSRV_ERROR_INVALID_PARAMS; - } - - if (ui32Size != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32Size) - { - PVR_DPF((PVR_DBG_ERROR, - "%s ERROR: Size doesn't match (Shared %d, Requested %d) with flags 0x%08x - 0x%08x!", - __FUNCTION__, - gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32Size, - ui32Size, - gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags, - ui32AllocFlags)); - return PVRSRV_ERROR_INVALID_PARAMS; - } - - if (ui32PageSize != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32PageSize) - { - PVR_DPF((PVR_DBG_ERROR, - "%s ERROR: Page Size doesn't match (Shared %d, Requested %d) with flags 0x%08x - 0x%08x!", - __FUNCTION__, - gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32PageSize, - ui32PageSize, - gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags, - ui32AllocFlags)); - return PVRSRV_ERROR_INVALID_PARAMS; - } - - *ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr; - *phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle; - - BM_XProcIndexAcquire(gXProcWorkaroundShareIndex); - - 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_NULL, - (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; - - /* allocate pages from the OS RAM */ - if (OSAllocPages(ui32AllocFlags, - ui32Size, - ui32PageSize, - pvPrivData, - ui32PrivDataLength, - IMG_NULL, /* FIXME: to support cross process sparse allocations */ - (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; - - BM_XProcIndexAcquire(gXProcWorkaroundShareIndex); - - 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; -} - -#if defined(PVRSRV_REFCOUNT_DEBUG) -IMG_VOID _BM_XProcIndexAcquireDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index) -#else -IMG_VOID _BM_XProcIndexAcquire(IMG_UINT32 ui32Index) -#endif -{ -#if defined(PVRSRV_REFCOUNT_DEBUG) - PVRSRVBMXProcIncRef2(pszFile, iLine, ui32Index); -#else - PVRSRVBMXProcIncRef(ui32Index); -#endif -} - -#if defined(PVRSRV_REFCOUNT_DEBUG) -IMG_VOID _BM_XProcIndexReleaseDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index) -#else -IMG_VOID _BM_XProcIndexRelease(IMG_UINT32 ui32Index) -#endif -{ -#if defined(PVRSRV_REFCOUNT_DEBUG) - PVRSRVBMXProcDecRef2(pszFile, iLine, ui32Index); -#else - PVRSRVBMXProcDecRef(ui32Index); -#endif - - PVR_DPF((PVR_DBG_VERBOSE, "Reduced refcount of SI[%d] from %d to %d", - ui32Index, gXProcWorkaroundShareData[ui32Index].ui32RefCount+1, gXProcWorkaroundShareData[ui32Index].ui32RefCount)); - - if (gXProcWorkaroundShareData[ui32Index].ui32RefCount == 0) - { - if (gXProcWorkaroundShareData[ui32Index].psArena != IMG_NULL) - { - IMG_SYS_PHYADDR sSysPAddr; - - if (gXProcWorkaroundShareData[ui32Index].pvCpuVAddr != IMG_NULL) - { - OSUnReservePhys(gXProcWorkaroundShareData[ui32Index].pvCpuVAddr, - gXProcWorkaroundShareData[ui32Index].ui32Size, - gXProcWorkaroundShareData[ui32Index].ui32AllocFlags, - gXProcWorkaroundShareData[ui32Index].hOSMemHandle); - } - sSysPAddr = gXProcWorkaroundShareData[ui32Index].sSysPAddr; - RA_Free (gXProcWorkaroundShareData[ui32Index].psArena, - sSysPAddr.uiAddr, - IMG_FALSE); - } - else - { - PVR_DPF((PVR_DBG_VERBOSE, "freeing OS memory")); - OSFreePages(gXProcWorkaroundShareData[ui32Index].ui32AllocFlags, - gXProcWorkaroundShareData[ui32Index].ui32PageSize, - gXProcWorkaroundShareData[ui32Index].pvCpuVAddr, - gXProcWorkaroundShareData[ui32Index].hOSMemHandle); - } - } -} - -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; - } - - BM_XProcIndexRelease(ui32SI); -} - - -/*! -****************************************************************************** - - @Function BM_ImportMemory - - @Description Provide a resource allocator with a source of pages of memory - from the Host OS's own allocation. Allocates a block of pages - larger than requested, allowing the resource allocator to - operate a small cache of pre allocated pages. - - @Input pH - buffer manager handle, not the void type is dictated - by the generic nature of the resource allocator interface. - @Input uRequestSize - requested size in bytes - @Output pActualSize - receives the actual size allocated in bytes - which may be >= requested size - @Output ppsMapping - receives the arbitrary user reference - associated with the underlying storage. - @Input uFlags - bit mask of allocation flags - @Input pvPrivData - opaque private data passed through to allocator - @Input ui32PrivDataLength - length of opaque private data - @Output pBase - receives a pointer to the allocated storage. - - @Return IMG_TRUE - success - IMG_FALSE - failed - - *****************************************************************************/ -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_INT32 uResult; - 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->ui32MappingCount = 0; - pMapping->CpuPAddr.uiAddr = 0; - pMapping->uSize = uSize; - if ((uFlags & PVRSRV_MEM_SPARSE) == 0) - { - pMapping->uSizeVM = uSize; - } - pMapping->pBMHeap = pBMHeap; - pMapping->ui32Flags = uFlags; - - /* - * If anyone want's to know, pass back the actual size of our allocation. - * There could be up to an extra page's worth of memory which will be marked - * as free in the RA. - */ - if (pActualSize) - { - *pActualSize = uSize; - } - - /* if it's a dummy allocation only use one physical page */ - 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) - { - 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; /* FIXME: find out why it doesn't work if alignment is specified */ - - /* If the user has specified heap CACHETYPE flags, use them to - * override the flags inherited from the heap. - */ - if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) - { - ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK; - ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK); - } - - /* allocate "shared" pages. */ - 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; - } - - /* specify how page addresses are derived */ - /* it works just like "env" now - no need to record - it as shareable, as we use the actual hOSMemHandle - and only divert to our wrapper layer based on Attribs */ - 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; /* FIXME: find out why it doesn't work if alignment is specified */ - - /* If the user has specified heap CACHETYPE flags, use them to - * override the flags inherited from the heap. - */ - if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) - { - ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK; - ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK); - } - - /* allocate "shared" pages. */ - 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; - } - - /* specify how page addresses are derived */ - /* it works just like "env" now - no need to record - it as shareable, as we use the actual hOSMemHandle - and only divert to our wrapper layer based on Attribs */ - 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 - - /* - What type of backing store do we have? - */ - if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) - { - IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs; - - /* The allocation code needs to know this is a sparse mapping */ - if (pMapping->ui32Flags & PVRSRV_MEM_SPARSE) - { - ui32Attribs |= PVRSRV_MEM_SPARSE; - } - - /* If the user has specified heap CACHETYPE flags, use them to - * override the flags inherited from the heap. - */ - 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); - } - - /* allocate pages from the OS RAM */ - if (OSAllocPages(ui32Attribs, - uPSize, - pBMHeap->sDevArena.ui32DataPageSize, - pvPrivData, - ui32PrivDataLength, - pMapping, - (IMG_VOID **)&pMapping->CpuVAddr, - &pMapping->hOSMemHandle) != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, - "BM_ImportMemory: OSAllocPages(0x%x) failed", - uPSize)); - goto fail_mapping_alloc; - } - - /* specify how page addresses are derived */ - pMapping->eCpuMemoryOrigin = hm_env; - } - else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) - { - IMG_SYS_PHYADDR sSysPAddr; - IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs; - - /* The allocation code needs to know this is a sparse mapping */ - if (pMapping->ui32Flags & PVRSRV_MEM_SPARSE) - { - ui32Attribs |= PVRSRV_MEM_SPARSE; - } - - /* allocate pages from the local device memory allocator */ - PVR_ASSERT(pBMHeap->pLocalDevMemArena != IMG_NULL); - - /* If the user has specified heap CACHETYPE flags, use them to - * override the flags inherited from the heap. - */ - 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; - } - - /* derive the CPU virtual address */ - pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr); - if(OSReservePhys(pMapping->CpuPAddr, - uPSize, - ui32Attribs, - pMapping, - &pMapping->CpuVAddr, - &pMapping->hOSMemHandle) != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: OSReservePhys failed")); - goto fail_dev_mem_alloc; - } - - /* specify how page addresses are derived */ - pMapping->eCpuMemoryOrigin = hm_contiguous; - } - else - { - PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: Invalid backing store type")); - goto fail_mapping_alloc; - } - - if(uFlags & PVRSRV_MEM_ION) - { - IMG_UINT32 ui32AddressOffsets[PVRSRV_MAX_NUMBER_OF_MM_BUFFER_PLANES]; - IMG_UINT32 ui32NumAddrOffsets = PVRSRV_MAX_NUMBER_OF_MM_BUFFER_PLANES; - - IMG_INT32 retSize = OSGetMemMultiPlaneInfo(pMapping->hOSMemHandle, - ui32AddressOffsets, &ui32NumAddrOffsets); - - if(retSize > 0 && pActualSize) - { - *pActualSize = pMapping->uSize = retSize; - } - } - - /* - * Allocate some device memory for what we just allocated. - */ - /* - * Do not allocate GPU mapping if NO_GPU_VIRTUAL_ON_ALLOC is requested. - * In the case where CBI is enabled, this allows for late - * GPU mapping. This flag is, otherwise, used in cases where only - * the memory management feature of the driver is utilized, without - * a need for GPU rendering - */ - if ((uFlags & (PVRSRV_MEM_SPARSE | PVRSRV_HAP_NO_GPU_VIRTUAL_ON_ALLOC)) == 0) - { - uResult = DevMemoryAlloc (pBMContext, - pMapping, - IMG_NULL, - uFlags, - (IMG_UINT32)uDevVAddrAlignment, - &pMapping->DevVAddr); - if (uResult <= 0) - { - PVR_DPF((PVR_DBG_ERROR, - "BM_ImportMemory: DevMemoryAlloc(0x%x) failed", - pMapping->uSize)); - goto fail_dev_mem_alloc; - } - - /* uDevVAddrAlignment is currently set to zero so QAC generates warning which we override */ - /* PRQA S 3356,3358 1 */ - PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1); - PVR_ASSERT(pBase); - } - - if(pBase) - *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)) - { - /* the size is double the actual size for interleaved allocations */ - 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); - /*not nulling pointer, out of scope*/ -fail_exit: - return IMG_FALSE; -} - - -/*! -****************************************************************************** - - @Function BM_FreeMemory - - @Description Free a block of pages previously allocated via - BM_ImportMemory. - - @Input h - buffer manager handle, not the void type as dictated by - the generic nature of the resource allocator interface. - @Input _base - base address of blocks to free. - @Input psMapping - arbitrary user reference associated with the - underlying storage provided by BM_ImportMemory - @Return None - - *****************************************************************************/ -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; - } - - /* - Only free the virtual memory if we got as far a allocating it. - This NULL check should be safe as we always have a guard page - at virtual address 0x00000000 - */ - if (psMapping->DevVAddr.uiAddr) - { - DevMemoryFree (psMapping); - } - - /* the size is double the actual for interleaved */ - 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); - /*not nulling pointer, copy on stack*/ - - PVR_DPF((PVR_DBG_MESSAGE, - "..BM_FreeMemory (h=0x%x, base=0x%x)", - (IMG_UINTPTR_T)h, _base)); -} - -/*! -****************************************************************************** - - @Function BM_GetPhysPageAddr - - @Description - - @Input psMemInfo - - @Input sDevVPageAddr - - @Output psDevPAddr - - @Return IMG_VOID - -******************************************************************************/ - -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); - - /* check it's a page address */ - PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0); - - /* PRQA S 0505 4 */ /* PVR_ASSERT should catch NULL ptrs */ - psDeviceNode = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pBMContext->psDeviceNode; - - *psDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pMMUHeap, - sDevVPageAddr); -} - - -/*! -****************************************************************************** - @Function BM_GetMMUContext - - @Description utility function to return the MMU context - - @Input hDevMemHeap - the Dev mem heap handle - - @Return MMU context, else NULL -**************************************************************************/ -MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap) -{ - BM_HEAP *pBMHeap = (BM_HEAP*)hDevMemHeap; - - PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUContext")); - - return pBMHeap->pBMContext->psMMUContext; -} - -/*! -****************************************************************************** - @Function BM_GetMMUContextFromMemContext - - @Description utility function to return the MMU context - - @Input hDevMemContext - the Dev mem context handle - - @Return MMU context, else NULL -**************************************************************************/ -MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext) -{ - BM_CONTEXT *pBMContext = (BM_CONTEXT*)hDevMemContext; - - PVR_DPF ((PVR_DBG_VERBOSE, "BM_GetMMUContextFromMemContext")); - - return pBMContext->psMMUContext; -} - -/*! -****************************************************************************** - @Function BM_GetMMUHeap - - @Description utility function to return the MMU heap handle - - @Input hDevMemHeap - the Dev mem heap handle - - @Return MMU heap handle, else NULL -**************************************************************************/ -IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap) -{ - PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUHeap")); - - return (IMG_HANDLE)((BM_HEAP*)hDevMemHeap)->pMMUHeap; -} - - -/*! -****************************************************************************** - @Function BM_GetDeviceNode - - @Description utility function to return the devicenode from the BM Context - - @Input hDevMemContext - the Dev Mem Context - - @Return MMU heap handle, else NULL -**************************************************************************/ -PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext) -{ - PVR_DPF((PVR_DBG_VERBOSE, "BM_GetDeviceNode")); - - return ((BM_CONTEXT*)hDevMemContext)->psDeviceNode; -} - - -/*! -****************************************************************************** - @Function BM_GetMappingHandle - - @Description utility function to return the mapping handle from a meminfo - - @Input psMemInfo - kernel meminfo - - @Return mapping handle, else NULL -**************************************************************************/ -IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo) -{ - PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMappingHandle")); - - return ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->hOSMemHandle; -} - -/*! -****************************************************************************** - @Function BM_MappingHandleFromBuffer - - @Description utility function to get the BM mapping handle from a BM buffer - - @Input hBuffer - Handle to BM buffer - - @Return BM mapping handle -**************************************************************************/ -IMG_HANDLE BM_MappingHandleFromBuffer(IMG_HANDLE hBuffer) -{ - BM_BUF *psBuffer; - - PVR_ASSERT(hBuffer != IMG_NULL); - psBuffer = hBuffer; - return psBuffer->pMapping; -} - -/*! -****************************************************************************** - @Function BM_GetVirtualSize - - @Description utility function to get the VM size of a BM mapping - - @Input hBMHandle - Handle to BM mapping - - @Return VM size of mapping -**************************************************************************/ -IMG_UINT32 BM_GetVirtualSize(IMG_HANDLE hBMHandle) -{ - BM_MAPPING *psMapping; - - PVR_ASSERT(hBMHandle != IMG_NULL); - psMapping = hBMHandle; - return psMapping->ui32ChunkSize * psMapping->ui32NumVirtChunks; -} - -/*! -****************************************************************************** - @Function BM_MapPageAtOffset - - @Description utility function check if the specificed offset in a BM mapping - is a page that needs tp be mapped - - @Input hBMHandle - Handle to BM mapping - - @Input ui32Offset - Offset into allocation - - @Return IMG_TRUE if the page should be mapped -**************************************************************************/ -IMG_BOOL BM_MapPageAtOffset(IMG_HANDLE hBMHandle, IMG_UINT32 ui32Offset) -{ - BM_MAPPING *psMapping; - IMG_UINT32 ui32ChunkIndex; - - PVR_ASSERT(hBMHandle != IMG_NULL); - psMapping = hBMHandle; - - ui32ChunkIndex = ui32Offset / psMapping->ui32ChunkSize; - /* Check for overrun */ - PVR_ASSERT(ui32ChunkIndex <= psMapping->ui32NumVirtChunks); - return psMapping->pabMapChunk[ui32ChunkIndex]; -} - -/*! -****************************************************************************** - @Function BM_VirtOffsetToPhyscial - - @Description utility function find of physical offset of a sparse allocation - from it's virtual offset. - - @Input hBMHandle - Handle to BM mapping - - @Input ui32VirtOffset - Virtual offset into allocation - - @Output pui32PhysOffset - Physical offset - - @Return IMG_TRUE if the virtual offset is physically backed -**************************************************************************/ -IMG_BOOL BM_VirtOffsetToPhysical(IMG_HANDLE hBMHandle, - IMG_UINT32 ui32VirtOffset, - IMG_UINT32 *pui32PhysOffset) -{ - BM_MAPPING *psMapping; - IMG_UINT32 ui32ChunkOffset; - IMG_UINT32 ui32PhysOffset = 0; - IMG_UINT32 i; - - PVR_ASSERT(hBMHandle != IMG_NULL); - psMapping = hBMHandle; - - ui32ChunkOffset = ui32VirtOffset / psMapping->ui32ChunkSize; - if (!psMapping->pabMapChunk[ui32ChunkOffset]) - { - return IMG_FALSE; - } - - for (i=0;i<ui32ChunkOffset;i++) - { - if (psMapping->pabMapChunk[i]) - { - ui32PhysOffset += psMapping->ui32ChunkSize; - } - } - *pui32PhysOffset = ui32PhysOffset; - - return IMG_TRUE; -} -/****************************************************************************** - End of file (buffer_manager.c) -******************************************************************************/ |