IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_HANDLE hDevMemContext, IMG_HANDLE hDeviceClassBuffer, PVRSRV_KERNEL_MEM_INFO **ppsMemInfo, IMG_HANDLE *phOSMapInfo) { PVRSRV_ERROR eError; PVRSRV_DEVICE_NODE* psDeviceNode; PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL; PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer; IMG_SYS_PHYADDR *psSysPAddr; IMG_VOID *pvCPUVAddr, *pvPageAlignedCPUVAddr; IMG_BOOL bPhysContig; BM_CONTEXT *psBMContext; DEVICE_MEMORY_INFO *psDevMemoryInfo; DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; IMG_HANDLE hDevMemHeap = IMG_NULL; IMG_SIZE_T ui32ByteSize; IMG_SIZE_T ui32Offset; IMG_SIZE_T ui32PageSize = HOST_PAGESIZE(); BM_HANDLE hBuffer; PVRSRV_MEMBLK *psMemBlock; IMG_BOOL bBMError; IMG_UINT32 i; PVRSRV_DC_MAPINFO *psDCMapInfo = IMG_NULL; if(!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo || !hDevMemContext) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_MAPINFO), (IMG_VOID **)&psDCMapInfo, IMG_NULL, "PVRSRV_DC_MAPINFO") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for psDCMapInfo")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psDCMapInfo, 0, sizeof(PVRSRV_DC_MAPINFO)); psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER*)hDeviceClassBuffer; eError = psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->hExtDevice, psDeviceClassBuffer->hExtBuffer, &psSysPAddr, &ui32ByteSize, &pvCPUVAddr, phOSMapInfo, &bPhysContig, &psDCMapInfo->ui32TilingStride); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to get buffer address")); goto ErrorExitPhase1; } psBMContext = (BM_CONTEXT*)psDeviceClassBuffer->hDevMemContext; psDeviceNode = psBMContext->psDeviceNode; psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo; psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap; for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++) { if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID) { if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT) { hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]); } else { hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap; } break; } } if(hDevMemHeap == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to find mapping heap")); eError = PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE; goto ErrorExitPhase1; } ui32Offset = ((IMG_UINTPTR_T)pvCPUVAddr) & (ui32PageSize - 1); pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvCPUVAddr - ui32Offset); eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), (IMG_VOID **)&psMemInfo, IMG_NULL, "Kernel Memory Info"); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for block")); goto ErrorExitPhase1; } OSMemSet(psMemInfo, 0, sizeof(*psMemInfo)); psMemBlock = &(psMemInfo->sMemBlk); bBMError = BM_Wrap(hDevMemHeap, ui32ByteSize, ui32Offset, bPhysContig, psSysPAddr, pvPageAlignedCPUVAddr, &psMemInfo->ui32Flags, &hBuffer); if (!bBMError) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed")); eError = PVRSRV_ERROR_BAD_MAPPING; goto ErrorExitPhase2; } psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); psMemBlock->hBuffer = (IMG_HANDLE)hBuffer; psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer); psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = ui32ByteSize; psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo; psMemInfo->pvSysBackupBuffer = IMG_NULL; psDCMapInfo->psMemInfo = psMemInfo; #if defined(SUPPORT_MEMORY_TILING) psDCMapInfo->psDeviceNode = psDeviceNode; if(psDCMapInfo->ui32TilingStride > 0) { eError = psDeviceNode->pfnAllocMemTilingRange(psDeviceNode, psMemInfo, psDCMapInfo->ui32TilingStride, &psDCMapInfo->ui32RangeIndex); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: AllocMemTilingRange failed")); goto ErrorExitPhase3; } } #endif psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, psDCMapInfo, 0, &UnmapDeviceClassMemoryCallBack); psMemInfo->ui32RefCount++; psMemInfo->memType = PVRSRV_MEMTYPE_DEVICECLASS; *ppsMemInfo = psMemInfo; #if defined(SUPPORT_PDUMP_MULTI_PROCESS) PDUMPCOMMENT("Dump display surface"); PDUMPMEM(IMG_NULL, psMemInfo, ui32Offset, psMemInfo->ui32AllocSize, PDUMP_FLAGS_CONTINUOUS, ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping); #endif return PVRSRV_OK; #if defined(SUPPORT_MEMORY_TILING) ErrorExitPhase3: if(psMemInfo) { FreeDeviceMem(psMemInfo); psMemInfo = IMG_NULL; } #endif ErrorExitPhase2: if(psMemInfo) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL); } ErrorExitPhase1: if(psDCMapInfo) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psDCMapInfo, IMG_NULL); } return eError; }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_HANDLE hDevMemContext, IMG_HANDLE hDeviceClassBuffer, PVRSRV_KERNEL_MEM_INFO **ppsMemInfo, IMG_HANDLE *phOSMapInfo) { PVRSRV_ERROR eError; PVRSRV_KERNEL_MEM_INFO *psMemInfo; PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer; IMG_SYS_PHYADDR *psSysPAddr; IMG_VOID *pvCPUVAddr, *pvPageAlignedCPUVAddr; IMG_BOOL bPhysContig; BM_CONTEXT *psBMContext; DEVICE_MEMORY_INFO *psDevMemoryInfo; DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; IMG_HANDLE hDevMemHeap = IMG_NULL; IMG_SIZE_T ui32ByteSize; IMG_SIZE_T ui32Offset; IMG_SIZE_T ui32PageSize = HOST_PAGESIZE(); BM_HANDLE hBuffer; PVRSRV_MEMBLK *psMemBlock; IMG_BOOL bBMError; IMG_UINT32 i; if(!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo || !hDevMemContext) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER*)hDeviceClassBuffer; eError = psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->hExtDevice, psDeviceClassBuffer->hExtBuffer, &psSysPAddr, &ui32ByteSize, &pvCPUVAddr, phOSMapInfo, &bPhysContig); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to get buffer address")); return PVRSRV_ERROR_GENERIC; } psBMContext = (BM_CONTEXT*)psDeviceClassBuffer->hDevMemContext; psDevMemoryInfo = &psBMContext->psDeviceNode->sDevMemoryInfo; psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap; for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++) { if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID) { if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT) { hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]); } else { hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap; } break; } } if(hDevMemHeap == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to find mapping heap")); return PVRSRV_ERROR_GENERIC; } ui32Offset = ((IMG_UINTPTR_T)pvCPUVAddr) & (ui32PageSize - 1); pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvCPUVAddr - ui32Offset); if(OSAllocMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), (IMG_VOID **)&psMemInfo, IMG_NULL, "Kernel Memory Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for block")); return (PVRSRV_ERROR_OUT_OF_MEMORY); } OSMemSet(psMemInfo, 0, sizeof(*psMemInfo)); psMemBlock = &(psMemInfo->sMemBlk); bBMError = BM_Wrap(hDevMemHeap, ui32ByteSize, ui32Offset, bPhysContig, psSysPAddr, pvPageAlignedCPUVAddr, &psMemInfo->ui32Flags, &hBuffer); if (!bBMError) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed")); OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL); return PVRSRV_ERROR_BAD_MAPPING; } psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); psMemBlock->hBuffer = (IMG_HANDLE)hBuffer; psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer); psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = ui32ByteSize; psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo; psMemInfo->pvSysBackupBuffer = IMG_NULL; psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, psMemInfo, 0, UnmapDeviceClassMemoryCallBack); *ppsMemInfo = psMemInfo; return PVRSRV_OK; }