IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie, PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_HANDLE hDevMemContext, IMG_SIZE_T ui32ByteSize, IMG_SIZE_T ui32PageOffset, IMG_BOOL bPhysContig, IMG_SYS_PHYADDR *psExtSysPAddr, IMG_VOID *pvLinAddr, IMG_UINT32 ui32Flags, PVRSRV_KERNEL_MEM_INFO **ppsMemInfo) { PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL; DEVICE_MEMORY_INFO *psDevMemoryInfo; IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE(); IMG_HANDLE hDevMemHeap = IMG_NULL; PVRSRV_DEVICE_NODE* psDeviceNode; BM_HANDLE hBuffer; PVRSRV_MEMBLK *psMemBlock; IMG_BOOL bBMError; BM_HEAP *psBMHeap; PVRSRV_ERROR eError; IMG_VOID *pvPageAlignedCPUVAddr; IMG_SYS_PHYADDR *psIntSysPAddr = IMG_NULL; IMG_HANDLE hOSWrapMem = IMG_NULL; DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; IMG_UINT32 i; IMG_SIZE_T ui32PageCount = 0; psDeviceNode = (PVRSRV_DEVICE_NODE*)hDevCookie; PVR_ASSERT(psDeviceNode != IMG_NULL); if (psDeviceNode == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: invalid parameter")); return PVRSRV_ERROR_INVALID_PARAMS; } if(pvLinAddr) { ui32PageOffset = (IMG_UINTPTR_T)pvLinAddr & (ui32HostPageSize - 1); ui32PageCount = HOST_PAGEALIGN(ui32ByteSize + ui32PageOffset) / ui32HostPageSize; pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvLinAddr - ui32PageOffset); if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageCount * sizeof(IMG_SYS_PHYADDR), (IMG_VOID **)&psIntSysPAddr, IMG_NULL, "Array of Page Addresses") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block")); return PVRSRV_ERROR_OUT_OF_MEMORY; } eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr, ui32PageCount * ui32HostPageSize, psIntSysPAddr, &hOSWrapMem); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block")); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExitPhase1; } psExtSysPAddr = psIntSysPAddr; bPhysContig = IMG_FALSE; } else { } psDevMemoryInfo = &((BM_CONTEXT*)hDevMemContext)->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,"PVRSRVWrapExtMemoryKM: unable to find mapping heap")); eError = PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP; goto ErrorExitPhase2; } if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), (IMG_VOID **)&psMemInfo, IMG_NULL, "Kernel Memory Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block")); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExitPhase2; } OSMemSet(psMemInfo, 0, sizeof(*psMemInfo)); psMemInfo->ui32Flags = ui32Flags; psMemBlock = &(psMemInfo->sMemBlk); bBMError = BM_Wrap(hDevMemHeap, ui32ByteSize, ui32PageOffset, bPhysContig, psExtSysPAddr, IMG_NULL, &psMemInfo->ui32Flags, &hBuffer); if (!bBMError) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: BM_Wrap Failed")); eError = PVRSRV_ERROR_BAD_MAPPING; goto ErrorExitPhase3; } psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); psMemBlock->hOSWrapMem = hOSWrapMem; psMemBlock->psIntSysPAddr = psIntSysPAddr; psMemBlock->hBuffer = (IMG_HANDLE)hBuffer; psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer); psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = ui32ByteSize; psMemInfo->pvSysBackupBuffer = IMG_NULL; psBMHeap = (BM_HEAP*)hDevMemHeap; hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext; eError = PVRSRVAllocSyncInfoKM(hDevCookie, hDevMemContext, &psMemInfo->psKernelSyncInfo); if(eError != PVRSRV_OK) { goto ErrorExitPhase4; } psMemInfo->psKernelSyncInfo->ui32RefCount++; psMemInfo->ui32RefCount++; psMemInfo->memType = PVRSRV_MEMTYPE_WRAPPED; psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICEMEM_WRAP, psMemInfo, 0, &UnwrapExtMemoryCallBack); *ppsMemInfo = psMemInfo; return PVRSRV_OK; ErrorExitPhase4: if(psMemInfo) { FreeDeviceMem(psMemInfo); psMemInfo = IMG_NULL; } ErrorExitPhase3: if(psMemInfo) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL); } ErrorExitPhase2: if(psIntSysPAddr) { OSReleasePhysPageAddr(hOSWrapMem); } ErrorExitPhase1: if(psIntSysPAddr) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageCount * sizeof(IMG_SYS_PHYADDR), psIntSysPAddr, IMG_NULL); } return eError; }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE hDevCookie, IMG_HANDLE hDevMemContext, IMG_UINT32 *pui32ClientHeapCount, PVRSRV_HEAP_INFO *psHeapInfo, IMG_BOOL *pbShared) { PVRSRV_DEVICE_NODE *psDeviceNode; IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0; DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; IMG_HANDLE hDevMemHeap; IMG_UINT32 i; #if !defined(PVR_SECURE_HANDLES) PVR_UNREFERENCED_PARAMETER(pbShared); #endif if (hDevCookie == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapInfoKM: hDevCookie invalid")); PVR_DBG_BREAK; return PVRSRV_ERROR_INVALID_PARAMS; } psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie; ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount; psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap; PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS); for(i=0; i<ui32HeapCount; i++) { switch(psDeviceMemoryHeap[i].DevMemHeapType) { case DEVICE_MEMORY_HEAP_SHARED_EXPORTED: { psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID; psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap; psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase; psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize; psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs; #if defined(PVR_SECURE_HANDLES) pbShared[ui32ClientHeapCount] = IMG_TRUE; #endif ui32ClientHeapCount++; break; } case DEVICE_MEMORY_HEAP_PERCONTEXT: { hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]); psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID; psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap; psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase; psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize; psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs; #if defined(PVR_SECURE_HANDLES) pbShared[ui32ClientHeapCount] = IMG_FALSE; #endif ui32ClientHeapCount++; break; } } } *pui32ClientHeapCount = ui32ClientHeapCount; return PVRSRV_OK; }
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; }
enum PVRSRV_ERROR PVRSRVWrapExtMemoryKM(void *hDevCookie, struct PVRSRV_PER_PROCESS_DATA *psPerProc, void *hDevMemContext, u32 ui32ByteSize, u32 ui32PageOffset, IMG_BOOL bPhysContig, struct IMG_SYS_PHYADDR *psExtSysPAddr, void *pvLinAddr, struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo) { struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = NULL; struct DEVICE_MEMORY_INFO *psDevMemoryInfo; u32 ui32HostPageSize = HOST_PAGESIZE(); void *hDevMemHeap = NULL; struct PVRSRV_DEVICE_NODE *psDeviceNode; void *hBuffer; struct PVRSRV_MEMBLK *psMemBlock; IMG_BOOL bBMError; struct BM_HEAP *psBMHeap; enum PVRSRV_ERROR eError; void *pvPageAlignedCPUVAddr; struct IMG_SYS_PHYADDR *psIntSysPAddr = NULL; void *hOSWrapMem = NULL; struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; int page_count = 0; u32 i; psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie; PVR_ASSERT(psDeviceNode != NULL); if (!psDeviceNode || (!pvLinAddr && !psExtSysPAddr)) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: invalid parameter"); return PVRSRV_ERROR_INVALID_PARAMS; } if (pvLinAddr) { get_page_details((u32)pvLinAddr, ui32ByteSize, &ui32PageOffset, &page_count); pvPageAlignedCPUVAddr = (void *)((u8 *) pvLinAddr - ui32PageOffset); if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, page_count * sizeof(struct IMG_SYS_PHYADDR), (void **)&psIntSysPAddr, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: " "Failed to alloc memory for block"); return PVRSRV_ERROR_OUT_OF_MEMORY; } eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr, page_count * ui32HostPageSize, psIntSysPAddr, &hOSWrapMem); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM:" " Failed to alloc memory for block"); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExitPhase1; } psExtSysPAddr = psIntSysPAddr; bPhysContig = IMG_FALSE; } psDevMemoryInfo = &((struct BM_CONTEXT *)hDevMemContext)->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 == NULL) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: unable to find mapping heap"); eError = PVRSRV_ERROR_GENERIC; goto ErrorExitPhase2; } if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_KERNEL_MEM_INFO), (void **) &psMemInfo, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: " "Failed to alloc memory for block"); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExitPhase2; } OSMemSet(psMemInfo, 0, sizeof(*psMemInfo)); psMemBlock = &(psMemInfo->sMemBlk); bBMError = BM_Wrap(hDevMemHeap, ui32ByteSize, ui32PageOffset, bPhysContig, psExtSysPAddr, NULL, &psMemInfo->ui32Flags, &hBuffer); if (!bBMError) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: BM_Wrap Failed"); eError = PVRSRV_ERROR_BAD_MAPPING; goto ErrorExitPhase3; } psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); psMemBlock->hOSWrapMem = hOSWrapMem; psMemBlock->psIntSysPAddr = psIntSysPAddr; psMemBlock->hBuffer = (void *) hBuffer; psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer); psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = ui32ByteSize; psMemInfo->pvSysBackupBuffer = NULL; psBMHeap = (struct BM_HEAP *)hDevMemHeap; hDevMemContext = (void *) psBMHeap->pBMContext; eError = alloc_or_reuse_syncinfo(hDevCookie, hDevMemContext, &psMemInfo->psKernelSyncInfo, psExtSysPAddr); if (eError != PVRSRV_OK) goto ErrorExitPhase4; psMemInfo->ui32RefCount++; psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICEMEM_WRAP, psMemInfo, 0, UnwrapExtMemoryCallBack); *ppsMemInfo = psMemInfo; return PVRSRV_OK; ErrorExitPhase4: FreeDeviceMem(psMemInfo); psMemInfo = NULL; ErrorExitPhase3: if (psMemInfo) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_KERNEL_MEM_INFO), psMemInfo, NULL); } ErrorExitPhase2: if (hOSWrapMem) OSReleasePhysPageAddr(hOSWrapMem); ErrorExitPhase1: if (psIntSysPAddr) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, page_count * sizeof(struct IMG_SYS_PHYADDR), psIntSysPAddr, NULL); } return eError; }
enum PVRSRV_ERROR PVRSRVGetDeviceMemHeapInfoKM(void *hDevCookie, void *hDevMemContext, u32 *pui32ClientHeapCount, struct PVRSRV_HEAP_INFO *psHeapInfo, IMG_BOOL *pbShared) { struct PVRSRV_DEVICE_NODE *psDeviceNode; u32 ui32HeapCount, ui32ClientHeapCount = 0; struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; void *hDevMemHeap; u32 i; if (hDevCookie == NULL) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapInfoKM: hDevCookie invalid"); PVR_DBG_BREAK; return PVRSRV_ERROR_INVALID_PARAMS; } psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie; ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount; psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap; PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS); for (i = 0; i < ui32HeapCount; i++) { switch (psDeviceMemoryHeap[i].DevMemHeapType) { case DEVICE_MEMORY_HEAP_SHARED_EXPORTED: psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID; psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap; psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase; psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize; psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs; pbShared[ui32ClientHeapCount] = IMG_TRUE; ui32ClientHeapCount++; break; case DEVICE_MEMORY_HEAP_PERCONTEXT: hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]); psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID; psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap; psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase; psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize; psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs; pbShared[ui32ClientHeapCount] = IMG_FALSE; ui32ClientHeapCount++; break; } } *pui32ClientHeapCount = ui32ClientHeapCount; return PVRSRV_OK; }
enum PVRSRV_ERROR PVRSRVMapDeviceClassMemoryKM( struct PVRSRV_PER_PROCESS_DATA *psPerProc, void *hDevMemContext, void *hDeviceClassBuffer, struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo, void **phOSMapInfo) { enum PVRSRV_ERROR eError; struct PVRSRV_KERNEL_MEM_INFO *psMemInfo; struct PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer; struct IMG_SYS_PHYADDR *psSysPAddr; void *pvCPUVAddr, *pvPageAlignedCPUVAddr; IMG_BOOL bPhysContig; struct BM_CONTEXT *psBMContext; struct DEVICE_MEMORY_INFO *psDevMemoryInfo; struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; void *hDevMemHeap = NULL; u32 ui32ByteSize; u32 ui32Offset; u32 ui32PageSize = HOST_PAGESIZE(); void *hBuffer; struct PVRSRV_MEMBLK *psMemBlock; IMG_BOOL bBMError; u32 i; if (!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo || !hDevMemContext) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceClassMemoryKM: invalid parameters"); return PVRSRV_ERROR_INVALID_PARAMS; } psDeviceClassBuffer = (struct PVRSRV_DEVICECLASS_BUFFER *) hDeviceClassBuffer; eError = psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer-> hExtDevice, psDeviceClassBuffer-> hExtBuffer, &psSysPAddr, &ui32ByteSize, (void __iomem **)&pvCPUVAddr, phOSMapInfo, &bPhysContig); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceClassMemoryKM: " "unable to get buffer address"); return PVRSRV_ERROR_GENERIC; } psBMContext = (struct 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 == NULL) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceClassMemoryKM: " "unable to find mapping heap"); return PVRSRV_ERROR_GENERIC; } ui32Offset = ((u32)pvCPUVAddr) & (ui32PageSize - 1); pvPageAlignedCPUVAddr = (void *)((u8 *)pvCPUVAddr - ui32Offset); if (OSAllocMem(PVRSRV_PAGEABLE_SELECT, sizeof(struct PVRSRV_KERNEL_MEM_INFO), (void **)&psMemInfo, NULL) != 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(struct PVRSRV_KERNEL_MEM_INFO), psMemInfo, NULL); return PVRSRV_ERROR_BAD_MAPPING; } psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); psMemBlock->hBuffer = (void *) hBuffer; psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer); psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = ui32ByteSize; psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo; psMemInfo->pvSysBackupBuffer = NULL; psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, psMemInfo, 0, UnmapDeviceClassMemoryCallBack); *ppsMemInfo = psMemInfo; return PVRSRV_OK; }