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 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; }
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 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; }
/*! ****************************************************************************** @Function SGXUT_readmem @Description Read memory from ukernel @Input *psSGXDevData : device data for SGX-type device @Input asHeapInfo : heap allocation info @Input ui32SharedHeapCount : heap count (includes per-context heaps) @Input hDevMemContext : device memory context of this app @Return void ******************************************************************************/ static IMG_VOID SGXUT_readmem(PVRSRV_DEV_DATA *psSGXDevData, PVRSRV_HEAP_INFO *asHeapInfo, IMG_UINT32 ui32SharedHeapCount, IMG_HANDLE hDevMemContext) { SGX_MISC_INFO sSGXMiscInfo; PVRSRV_ERROR eResult; PVRSRV_CLIENT_MEM_INFO *psDeviceMemInfo; PVRSRV_CLIENT_MEM_INFO *psDeviceDestMemInfo; IMG_DEV_VIRTADDR sDevVAddr; IMG_PVOID pvLinAddr; IMG_UINT32 ui32ByteOffset = 1; IMG_UINT32 ui32InitMemValue = 0x1234, ui32DeviceValue; IMG_HANDLE hVertexShaderHeap, hKernelDataHeap; IMG_UINT i; /* Find the kernel-video data heap */ for(i=0; i < ui32SharedHeapCount; i++) { switch(HEAP_IDX(asHeapInfo[i].ui32HeapID)) { case SGX_VERTEXSHADER_HEAP_ID: { hVertexShaderHeap = asHeapInfo[i].hDevMemHeap; break; } case SGX_KERNEL_DATA_HEAP_ID: { hKernelDataHeap = asHeapInfo[i].hDevMemHeap; } default: { break; } } } /* * Allocate device-addressable memory and check its value from * within the microkernel */ PVRSRVAllocDeviceMem(psSGXDevData, /* hKernelDataHeap, */ hVertexShaderHeap, PVRSRV_MEM_READ | PVRSRV_MEM_WRITE, 16, 4, &psDeviceMemInfo); /* Apply offset */ sDevVAddr = psDeviceMemInfo->sDevVAddr; pvLinAddr = psDeviceMemInfo->pvLinAddr; sDevVAddr.uiAddr += ui32ByteOffset; pvLinAddr = (IMG_PVOID)((IMG_CHAR*)pvLinAddr + ui32ByteOffset); /* Initialise value in device-addressable memory */ DPF("Writing memory (CPU) at 0x%x: value is %x\n", (IMG_UINTPTR_T)pvLinAddr, ui32InitMemValue); PVRSRVMemCopy(pvLinAddr, (IMG_PVOID)&ui32InitMemValue, sizeof(IMG_UINT32)); /* Configure the address to read and its context in the microkernel */ DPF("\nMisc Info API: Query the SGX device memory buffer\n"); sSGXMiscInfo.eRequest = SGX_MISC_INFO_REQUEST_MEMREAD; sSGXMiscInfo.sDevVAddrSrc = sDevVAddr; sSGXMiscInfo.hDevMemContext = hDevMemContext; eResult = SGXGetMiscInfo(psSGXDevData, &sSGXMiscInfo); ui32DeviceValue = sSGXMiscInfo.uData.sSGXFeatures.ui32DeviceMemValue; DPF("Reading memory (device) at 0x%x: value is %x\n", sSGXMiscInfo.sDevVAddrSrc.uiAddr, ui32DeviceValue); if(ui32DeviceValue != ui32InitMemValue) { DPF("ERROR: Device and CPU values disagree.\n\n"); } { /* Allocate dest buffer for GPU memcopy */ PVRSRVAllocDeviceMem(psSGXDevData, hKernelDataHeap, /* hVertexShaderHeap, */ PVRSRV_MEM_WRITE, 16, 4, &psDeviceDestMemInfo); /* Configure the mem copy */ DPF("\nMisc Info API: Perform a device-->device 4-byte memcopy\n"); sSGXMiscInfo.eRequest = SGX_MISC_INFO_REQUEST_MEMCOPY; sSGXMiscInfo.sDevVAddrSrc = sDevVAddr; sSGXMiscInfo.sDevVAddrDest = psDeviceDestMemInfo->sDevVAddr; eResult = SGXGetMiscInfo(psSGXDevData, &sSGXMiscInfo); ui32DeviceValue = *(IMG_UINT32*)psDeviceDestMemInfo->pvLinAddr; DPF("Reading memory (device) at 0x%x: value is %x\n", sSGXMiscInfo.sDevVAddrDest.uiAddr, ui32DeviceValue); if(ui32DeviceValue != ui32InitMemValue) { DPF("ERROR: Device src and dest values disagree.\n\n"); } } /* Free allocations */ PVRSRVFreeDeviceMem(psSGXDevData, psDeviceMemInfo); PVRSRVFreeDeviceMem(psSGXDevData, psDeviceDestMemInfo); }
int alloc_ramdec_region(unsigned long *base_addr0, unsigned long *base_addr1, unsigned long size0, unsigned long size1) { unsigned long pid = OSGetCurrentProcessIDKM(); unsigned long num = 10; unsigned long heap_count = 0; void *sgx_cookie = NULL; unsigned long heapIndex = 0, generalHeapIndex = 0; PVRSRV_ERROR err; PVRSRV_KERNEL_MEM_INFO *rendec0MemInfo; PVRSRV_KERNEL_MEM_INFO *rendec1MemInfo; int i; printk(KERN_INFO "Calling PVRSRVPerProcessData()\n"); if (PVRSRVPerProcessDataConnect(200) != PVRSRV_OK) { printk(KERN_ERR "msvdx_init: connect to PVR failed\n"); } psPerProc = PVRSRVPerProcessData(200); if (psPerProc == IMG_NULL) { printk(KERN_ERR "msvdx_init: Couldn't find per process data for pid=%lx\n", pid); } printk(KERN_INFO " TEST: pp_data = 0x%p\n", psPerProc); PVRSRVEnumerateDevicesKM(&num, dev_id_list); printk(KERN_INFO "Calling PVRSRVEnumerateDevicesKM()\n"); if (PVRSRVEnumerateDevicesKM(&num, dev_id_list) != PVRSRV_OK) { printk(KERN_ERR "msvdx_init: PVRSRVEnumerateDevice failed\n"); } else { printk(KERN_INFO " PVRSRVEnumerateDevicesKM() found %ld devices\n", num); for (i = 0 ; i < num ; i++) { PVRSRV_DEVICE_IDENTIFIER *id = dev_id_list + i; unsigned long cookie = 0; printk(KERN_INFO " Device %d has type %d, class %d & index %ld\n", i, id->eDeviceType, id->eDeviceClass, id->ui32DeviceIndex); if (PVRSRV_DEVICE_TYPE_EXT != id->eDeviceType) { // Call PVRSRVAcquireDeviceDataKM(): printk(KERN_INFO "Calling PVRSRVAcquireDeviceDataKM()\n"); err = PVRSRVAcquireDeviceDataKM(id->ui32DeviceIndex, PVRSRV_DEVICE_TYPE_UNKNOWN, (void *) &cookie); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] PVRSRVAcquireDeviceDataKM() " "returned %d\n", err); break; } if (PVRSRV_DEVICE_TYPE_SGX == id->eDeviceType) { printk(KERN_INFO " Found cookie = 0x%lx\n", cookie); // Save this away for later: sgx_cookie = (void *) cookie; } } } } // Enumerate the display class devices to be able to find the 3DD: printk(KERN_INFO "Calling PVRSRVEnumerateDCKM()\n"); err = PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS_DISPLAY, &num, dev_ids); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] PVRSRVEnumerateDCKM() returned %d\n", err); } else { // Find the 3DD: printk(KERN_INFO " PVRSRVEnumerateDCKM() found %ld devices\n", num); for (i = 0 ; i < num ; i++) { printk(KERN_INFO " device %d has ID %ld\n", i, dev_ids[i]); } if (0 == dev_ids[0]) { printk(KERN_ERR "[EMGD] Did not find 3rd-party display driver ID\n"); } } // Call PVRSRVCreateDeviceMemContextKM(): printk(KERN_INFO "Calling PVRSRVCreateDeviceMemContextKM()\n"); err = PVRSRVCreateDeviceMemContextKM(sgx_cookie, psPerProc, &dev_mem_context, &heap_count, heap_info, &mem_created, &dummy); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] PVRSRVCreateDeviceMemContextKM() " "returned %d\n", err); } for (heapIndex=0; heapIndex<heap_count; heapIndex++) { if (HEAP_IDX(heap_info[heapIndex].ui32HeapID) == SGX_GENERAL_HEAP_ID) { generalHeapIndex = heapIndex; break; } } if (PVRSRVAllocDeviceMemKM(sgx_cookie, psPerProc, heap_info[generalHeapIndex].hDevMemHeap, PVRSRV_MEM_READ | PVRSRV_MEM_WRITE, size0, 0, &rendec0MemInfo, "") != PVRSRV_OK) { printk(KERN_ERR "msvdx: PVRSRVAllocDeviceMemKM failed\n"); } if (PVRSRVAllocDeviceMemKM(sgx_cookie, psPerProc, heap_info[generalHeapIndex].hDevMemHeap, PVRSRV_MEM_READ | PVRSRV_MEM_WRITE, size1, 0, &rendec1MemInfo, "") != PVRSRV_OK) { printk(KERN_ERR "msvdx: PVRSRVAllocDeviceMemKM failed\n"); } *base_addr0 = rendec0MemInfo->sDevVAddr.uiAddr; *base_addr1 = rendec1MemInfo->sDevVAddr.uiAddr; //printk(KERN_INFO "pvr size0=%lx, size1=%lx, heap=%ld\n", size0, size1, generalHeapIndex); // return PVRSRV_OK; return 0; }
/* * Can't call from module initialization, since PVR services are started when * the Xorg server starts. */ int msvdx_pvr_init(void) { drm_emgd_priv_t *priv; igd_context_t *context; platform_context_plb_t *platform; struct msvdx_pvr_info *pvr; PVRSRV_DEVICE_IDENTIFIER dev_id_list[PVRSRV_MAX_DEVICES]; IMG_UINT32 pid; IMG_UINT32 num_devices; IMG_UINT32 i; IMG_BOOL mem_created; PVRSRV_ERROR err; int ret; priv = gpDrmDevice->dev_private; context = priv->context; platform = (platform_context_plb_t *)context->platform_context; if (platform->msvdx_pvr) { printk(KERN_INFO "[EMGD] MSVDX: PVR services already " "initialized\n"); return 0; } pvr = kzalloc(sizeof(*pvr), GFP_KERNEL); if (!pvr) return -ENOMEM; /* * Create a dummy kernel thread so that a persistent PVR per process * data could be created. */ pvr->kthread = kthread_run(msvdx_pvr_kthread, NULL, "msvdx-pvr"); if (IS_ERR(pvr->kthread)) { ret = PTR_ERR(pvr->kthread); printk(KERN_ERR "[EMGD] MSVDX: failed to create MSVDX PVR " "kernel tread, error=%i\n", ret); pvr->kthread = NULL; goto out_free; } ret = -ENODEV; pid = OSGetCurrentProcessIDKM(); //(IMG_UINT32)pvr->kthread->pid; err = PVRSRVPerProcessDataConnect(pid); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] MSVDX: connect to PVR failed (pid=%u), " "error=%i\n", (unsigned int)err, err); goto out_stop_kthread; } pvr->per_proc = PVRSRVPerProcessData(pid); if (pvr->per_proc == IMG_NULL) { printk(KERN_ERR "[EMGD] MSVDX: Couldn't find per process " "data for pid=%u\n", (unsigned int)pid); goto out_stop_kthread; } err = PVRSRVEnumerateDevicesKM(&num_devices, dev_id_list); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] MSVDX: PVRSRVEnumerateDevice() failed, " "error=%u\n", (unsigned int)err); goto out_stop_kthread; } for (i = 0 ; i < num_devices ; i++) { PVRSRV_DEVICE_IDENTIFIER *id; IMG_HANDLE cookie; cookie = IMG_NULL; id = &dev_id_list[i]; if (id->eDeviceType != PVRSRV_DEVICE_TYPE_EXT) { err = PVRSRVAcquireDeviceDataKM(id->ui32DeviceIndex, PVRSRV_DEVICE_TYPE_UNKNOWN, &cookie); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] MSVDX: " "PVRSRVAcquireDeviceDataKM() failed, " "error=%u\n", err); break; } if (PVRSRV_DEVICE_TYPE_SGX == id->eDeviceType) { pvr->sgx_cookie = cookie; break; } } } if (pvr->sgx_cookie == IMG_NULL) goto out_stop_kthread; err = PVRSRVCreateDeviceMemContextKM(pvr->sgx_cookie, pvr->per_proc, &pvr->dev_mem_context, &pvr->heap_count, pvr->heap_info, &mem_created, pvr->heap_shared); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] MSVDX: PVRSRVCreateDeviceMemContextKM()" " failed, error=%u\n", (unsigned int)err); goto out_stop_kthread; } for (i = 0; i < pvr->heap_count; i++) { if (HEAP_IDX(pvr->heap_info[i].ui32HeapID) == SGX_VIDEO_HEAP_ID) { pvr->mapping_heap_index = i; break; } } platform->msvdx_pvr = pvr; pvr->pid = pid; return 0; out_stop_kthread: kthread_stop(pvr->kthread); out_free: kfree(pvr); return ret; }