enum PVRSRV_ERROR PVRSRVAllocDeviceMemKM(void *hDevCookie, struct PVRSRV_PER_PROCESS_DATA *psPerProc, void *hDevMemHeap, u32 ui32Flags, u32 ui32Size, u32 ui32Alignment, struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo) { struct PVRSRV_KERNEL_MEM_INFO *psMemInfo; enum PVRSRV_ERROR eError; struct BM_HEAP *psBMHeap; void *hDevMemContext; if (!hDevMemHeap || (ui32Size == 0)) return PVRSRV_ERROR_INVALID_PARAMS; eError = AllocDeviceMem(hDevCookie, hDevMemHeap, ui32Flags, ui32Size, ui32Alignment, &psMemInfo); if (eError != PVRSRV_OK) return eError; if (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ) { psMemInfo->psKernelSyncInfo = NULL; } else { psBMHeap = (struct BM_HEAP *)hDevMemHeap; hDevMemContext = (void *) psBMHeap->pBMContext; eError = PVRSRVAllocSyncInfoKM(hDevCookie, hDevMemContext, &psMemInfo->psKernelSyncInfo); if (eError != PVRSRV_OK) goto free_mainalloc; } *ppsMemInfo = psMemInfo; if (ui32Flags & PVRSRV_MEM_NO_RESMAN) { psMemInfo->sMemBlk.hResItem = NULL; } else { psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICEMEM_ALLOCATION, psMemInfo, 0, FreeDeviceMemCallBack); if (psMemInfo->sMemBlk.hResItem == NULL) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto free_mainalloc; } } psMemInfo->ui32RefCount++; return PVRSRV_OK; free_mainalloc: FreeDeviceMem(psMemInfo); return eError; }
IMG_EXPORT PVRSRV_ERROR PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_UINT32 ui32Flags, IMG_SIZE_T uSize, PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo) { PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), (IMG_VOID **)&psKernelMemInfo, IMG_NULL, "Kernel Memory Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for meminfo")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psKernelMemInfo, 0, sizeof(*psKernelMemInfo)); ui32Flags &= ~PVRSRV_HAP_MAPTYPE_MASK; ui32Flags |= PVRSRV_HAP_MULTI_PROCESS; psKernelMemInfo->ui32Flags = ui32Flags; psKernelMemInfo->uAllocSize = uSize; if(OSAllocPages(psKernelMemInfo->ui32Flags, psKernelMemInfo->uAllocSize, (IMG_UINT32)HOST_PAGESIZE(), IMG_NULL, 0, IMG_NULL, &psKernelMemInfo->pvLinAddrKM, &psKernelMemInfo->sMemBlk.hOSMemHandle) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for block")); OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psKernelMemInfo, 0); return PVRSRV_ERROR_OUT_OF_MEMORY; } /* register with the resman */ psKernelMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_MEM_INFO, psKernelMemInfo, 0, &FreeSharedSysMemCallBack); *ppsKernelMemInfo = psKernelMemInfo; return PVRSRV_OK; }
static IMG_INT PVRSRVBridgePMRSecureImportPMR(IMG_UINT32 ui32BridgeID, PVRSRV_BRIDGE_IN_PMRSECUREIMPORTPMR *psPMRSecureImportPMRIN, PVRSRV_BRIDGE_OUT_PMRSECUREIMPORTPMR *psPMRSecureImportPMROUT, CONNECTION_DATA *psConnection) { PMR * psPMRInt; IMG_HANDLE hPMRInt2; PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SMM_PMRSECUREIMPORTPMR); NEW_HANDLE_BATCH_OR_ERROR(psPMRSecureImportPMROUT->eError, psConnection, 1); psPMRSecureImportPMROUT->eError = PMRSecureImportPMR( psPMRSecureImportPMRIN->Export, &psPMRInt, &psPMRSecureImportPMROUT->uiSize, &psPMRSecureImportPMROUT->sAlign); /* Exit early if bridged call fails */ if(psPMRSecureImportPMROUT->eError != PVRSRV_OK) { goto PMRSecureImportPMR_exit; } /* Create a resman item and overwrite the handle with it */ hPMRInt2 = ResManRegisterRes(psConnection->hResManContext, RESMAN_TYPE_PMR, psPMRInt, /* FIXME: how can we avoid this cast? */ (RESMAN_FREE_FN)&PMRUnrefPMR); if (hPMRInt2 == IMG_NULL) { psPMRSecureImportPMROUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE; goto PMRSecureImportPMR_exit; } PVRSRVAllocHandleNR(psConnection->psHandleBase, &psPMRSecureImportPMROUT->hPMR, (IMG_HANDLE) hPMRInt2, PVRSRV_HANDLE_TYPE_PHYSMEM_PMR, PVRSRV_HANDLE_ALLOC_FLAG_NONE ); COMMIT_HANDLE_BATCH_OR_ERROR(psPMRSecureImportPMROUT->eError, psConnection); PMRSecureImportPMR_exit: return 0; }
/*! ****************************************************************************** @Function LinuxEventObjectAdd @Description Linux wait object addition @Input hOSEventObjectList : Event object list handle @Output phOSEventObject : Pointer to the event object handle @Return PVRSRV_ERROR : Error code ******************************************************************************/ PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject) { PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject; PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList; IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); PVRSRV_PER_PROCESS_DATA *psPerProc; unsigned long ulLockFlags; psPerProc = PVRSRVPerProcessData(ui32PID); if (psPerProc == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: Couldn't find per-process data")); return PVRSRV_ERROR_OUT_OF_MEMORY; } /* allocate completion variable */ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), (IMG_VOID **)&psLinuxEventObject, IMG_NULL, "Linux Event Object") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory ")); return PVRSRV_ERROR_OUT_OF_MEMORY; } INIT_LIST_HEAD(&psLinuxEventObject->sList); atomic_set(&psLinuxEventObject->sTimeStamp, 0); psLinuxEventObject->ui32TimeStampPrevious = 0; #if defined(DEBUG) psLinuxEventObject->ui32Stats = 0; #endif init_waitqueue_head(&psLinuxEventObject->sWait); psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList; psLinuxEventObject->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_EVENT_OBJECT, psLinuxEventObject, 0, &LinuxEventObjectDeleteCallback); write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags); list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList); write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags); *phOSEventObject = psLinuxEventObject; return PVRSRV_OK; }
enum PVRSRV_ERROR PVRSRVAllocSharedSysMemoryKM( struct PVRSRV_PER_PROCESS_DATA *psPerProc, u32 ui32Flags, u32 ui32Size, struct PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo) { struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_KERNEL_MEM_INFO), (void **) &psKernelMemInfo, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: " "Failed to alloc memory for meminfo"); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psKernelMemInfo, 0, sizeof(*psKernelMemInfo)); ui32Flags &= ~PVRSRV_HAP_MAPTYPE_MASK; ui32Flags |= PVRSRV_HAP_MULTI_PROCESS; psKernelMemInfo->ui32Flags = ui32Flags; psKernelMemInfo->ui32AllocSize = ui32Size; if (OSAllocPages(psKernelMemInfo->ui32Flags, psKernelMemInfo->ui32AllocSize, HOST_PAGESIZE(), &psKernelMemInfo->pvLinAddrKM, &psKernelMemInfo->sMemBlk.hOSMemHandle) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: " "Failed to alloc memory for block"); OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_KERNEL_MEM_INFO), psKernelMemInfo, NULL); return PVRSRV_ERROR_OUT_OF_MEMORY; } psKernelMemInfo->sMemBlk.hResItem = ResManRegisterRes( psPerProc->hResManContext, RESMAN_TYPE_SHARED_MEM_INFO, psKernelMemInfo, 0, FreeSharedSysMemCallBack); *ppsKernelMemInfo = psKernelMemInfo; return PVRSRV_OK; }
static IMG_INT PVRSRVBridgeAllocSyncPrimitiveBlock(IMG_UINT32 ui32BridgeID, PVRSRV_BRIDGE_IN_ALLOCSYNCPRIMITIVEBLOCK *psAllocSyncPrimitiveBlockIN, PVRSRV_BRIDGE_OUT_ALLOCSYNCPRIMITIVEBLOCK *psAllocSyncPrimitiveBlockOUT, CONNECTION_DATA *psConnection) { IMG_HANDLE hDevNodeInt = IMG_NULL; SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = IMG_NULL; IMG_HANDLE hSyncHandleInt2 = IMG_NULL; DEVMEM_EXPORTCOOKIE * psExportCookieInt = IMG_NULL; PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_ALLOCSYNCPRIMITIVEBLOCK); psAllocSyncPrimitiveBlockOUT->hSyncHandle = IMG_NULL; { /* Look up the address from the handle */ psAllocSyncPrimitiveBlockOUT->eError = PVRSRVLookupHandle(psConnection->psHandleBase, (IMG_HANDLE *) &hDevNodeInt, psAllocSyncPrimitiveBlockIN->hDevNode, PVRSRV_HANDLE_TYPE_DEV_NODE); if(psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK) { goto AllocSyncPrimitiveBlock_exit; } } psAllocSyncPrimitiveBlockOUT->eError = PVRSRVAllocSyncPrimitiveBlockKM(psConnection, hDevNodeInt, &psSyncHandleInt, &psAllocSyncPrimitiveBlockOUT->ui32SyncPrimVAddr, &psAllocSyncPrimitiveBlockOUT->ui32SyncPrimBlockSize, &psExportCookieInt); /* Exit early if bridged call fails */ if(psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK) { goto AllocSyncPrimitiveBlock_exit; } /* Create a resman item and overwrite the handle with it */ hSyncHandleInt2 = ResManRegisterRes(psConnection->hResManContext, RESMAN_TYPE_SYNC_PRIMITIVE_BLOCK, psSyncHandleInt, /* FIXME: how can we avoid this cast? */ (RESMAN_FREE_FN)&PVRSRVFreeSyncPrimitiveBlockKM); if (hSyncHandleInt2 == IMG_NULL) { psAllocSyncPrimitiveBlockOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE; goto AllocSyncPrimitiveBlock_exit; } psAllocSyncPrimitiveBlockOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase, &psAllocSyncPrimitiveBlockOUT->hSyncHandle, (IMG_HANDLE) hSyncHandleInt2, PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK, PVRSRV_HANDLE_ALLOC_FLAG_NONE ); if (psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK) { goto AllocSyncPrimitiveBlock_exit; } psAllocSyncPrimitiveBlockOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase, &psAllocSyncPrimitiveBlockOUT->hExportCookie, (IMG_HANDLE) psExportCookieInt, PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE, PVRSRV_HANDLE_ALLOC_FLAG_NONE ,psAllocSyncPrimitiveBlockOUT->hSyncHandle); if (psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK) { goto AllocSyncPrimitiveBlock_exit; } AllocSyncPrimitiveBlock_exit: if (psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK) { if (psAllocSyncPrimitiveBlockOUT->hSyncHandle) { PVRSRVReleaseHandle(psConnection->psHandleBase, (IMG_HANDLE) psAllocSyncPrimitiveBlockOUT->hSyncHandle, PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK); } /* If we have a valid resman item we should undo the bridge function by freeing the resman item */ if (hSyncHandleInt2) { PVRSRV_ERROR eError = ResManFreeResByPtr(hSyncHandleInt2); /* Freeing a resource should never fail... */ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY)); } else if (psSyncHandleInt) { PVRSRVFreeSyncPrimitiveBlockKM(psSyncHandleInt); } } return 0; }
enum PVRSRV_ERROR SGXFindSharedPBDescKM( struct PVRSRV_PER_PROCESS_DATA *psPerProc, void *hDevCookie, IMG_BOOL bLockOnFailure, u32 ui32TotalPBSize, void **phSharedPBDesc, struct PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo, struct PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo, struct PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo, struct PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos, u32 *ui32SharedPBDescSubKernelMemInfosCount) { struct PVRSRV_STUB_PBDESC *psStubPBDesc; struct PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos = NULL; struct PVRSRV_SGXDEV_INFO *psSGXDevInfo; enum PVRSRV_ERROR eError; psSGXDevInfo = ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice; psStubPBDesc = psSGXDevInfo->psStubPBDescListKM; if (psStubPBDesc != NULL) { u32 i; struct RESMAN_ITEM *psResItem; if (psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize) { PVR_DPF(PVR_DBG_WARNING, "SGXFindSharedPBDescKM: " "Shared PB requested with different size " "(0x%x) from existing shared PB (0x%x) - " "requested size ignored", ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize); } if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount, (void **) &ppsSharedPBDescSubKernelMemInfos, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "SGXFindSharedPBDescKM: OSAllocMem failed"); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ExitNotFound; } psResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_PB_DESC, psStubPBDesc, 0, &SGXCleanupSharedPBDescCallback); if (psResItem == NULL) { OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(struct PVRSRV_KERNEL_MEM_INFO *)* psStubPBDesc->ui32SubKernelMemInfosCount, ppsSharedPBDescSubKernelMemInfos, NULL); PVR_DPF(PVR_DBG_ERROR, "SGXFindSharedPBDescKM: " "ResManRegisterRes failed"); eError = PVRSRV_ERROR_GENERIC; goto ExitNotFound; } *ppsSharedPBDescKernelMemInfo = psStubPBDesc->psSharedPBDescKernelMemInfo; *ppsHWPBDescKernelMemInfo = psStubPBDesc->psHWPBDescKernelMemInfo; *ppsBlockKernelMemInfo = psStubPBDesc->psBlockKernelMemInfo; *ui32SharedPBDescSubKernelMemInfosCount = psStubPBDesc->ui32SubKernelMemInfosCount; *pppsSharedPBDescSubKernelMemInfos = ppsSharedPBDescSubKernelMemInfos; for (i = 0; i < psStubPBDesc->ui32SubKernelMemInfosCount; i++) { ppsSharedPBDescSubKernelMemInfos[i] = psStubPBDesc->ppsSubKernelMemInfos[i]; } psStubPBDesc->ui32RefCount++; *phSharedPBDesc = (void *) psResItem; return PVRSRV_OK; } eError = PVRSRV_OK; if (bLockOnFailure) { if (psResItemCreateSharedPB == NULL) { psResItemCreateSharedPB = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, psPerProc, 0, &SGXCleanupSharedPBDescCreateLockCallback); if (psResItemCreateSharedPB == NULL) { PVR_DPF(PVR_DBG_ERROR, "SGXFindSharedPBDescKM: " "ResManRegisterRes failed"); eError = PVRSRV_ERROR_GENERIC; goto ExitNotFound; } PVR_ASSERT(psPerProcCreateSharedPB == NULL); psPerProcCreateSharedPB = psPerProc; } else { eError = PVRSRV_ERROR_PROCESSING_BLOCKED; } } ExitNotFound: *phSharedPBDesc = NULL; return eError; }
IMG_EXPORT PVRSRV_ERROR SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_HANDLE hDevCookie, PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo, PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo, PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo, PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo, IMG_UINT32 ui32TotalPBSize, IMG_HANDLE *phSharedPBDesc, PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos, IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount, IMG_DEV_VIRTADDR sHWPBDescDevVAddr) { PVRSRV_STUB_PBDESC *psStubPBDesc=IMG_NULL; PVRSRV_ERROR eRet = PVRSRV_ERROR_INVALID_PERPROC; IMG_UINT32 i; PVRSRV_SGXDEV_INFO *psSGXDevInfo; PRESMAN_ITEM psResItem; if (psPerProcCreateSharedPB != psPerProc) { goto NoAdd; } else { PVR_ASSERT(psResItemCreateSharedPB != IMG_NULL); ResManFreeResByPtr(psResItemCreateSharedPB, CLEANUP_WITH_POLL); PVR_ASSERT(psResItemCreateSharedPB == IMG_NULL); PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL); } psSGXDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice; psStubPBDesc = psSGXDevInfo->psStubPBDescListKM; if (psStubPBDesc != IMG_NULL) { if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize) { PVR_DPF((PVR_DBG_WARNING, "SGXAddSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored", ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize)); } psResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_PB_DESC, psStubPBDesc, 0, &SGXCleanupSharedPBDescCallback); if (psResItem == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: " "Failed to register existing shared " "PBDesc with the resource manager")); goto NoAddKeepPB; } psStubPBDesc->ui32RefCount++; *phSharedPBDesc = (IMG_HANDLE)psResItem; eRet = PVRSRV_OK; goto NoAddKeepPB; } if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_STUB_PBDESC), (IMG_VOID **)&psStubPBDesc, 0, "Stub Parameter Buffer Description") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc " "StubPBDesc")); eRet = PVRSRV_ERROR_OUT_OF_MEMORY; goto NoAdd; } psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL; if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount, (IMG_VOID **)&psStubPBDesc->ppsSubKernelMemInfos, 0, "Array of Kernel Memory Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: " "Failed to alloc " "StubPBDesc->ppsSubKernelMemInfos")); eRet = PVRSRV_ERROR_OUT_OF_MEMORY; goto NoAdd; } if(PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo) != PVRSRV_OK) { goto NoAdd; } if(PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo) != PVRSRV_OK) { goto NoAdd; } if(PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo) != PVRSRV_OK) { goto NoAdd; } if(PVRSRVDissociateMemFromResmanKM(psHWBlockKernelMemInfo) != PVRSRV_OK) { goto NoAdd; } psStubPBDesc->ui32RefCount = 1; psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize; psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo; psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo; psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo; psStubPBDesc->psHWBlockKernelMemInfo = psHWBlockKernelMemInfo; psStubPBDesc->ui32SubKernelMemInfosCount = ui32SharedPBDescSubKernelMemInfosCount; for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++) { psStubPBDesc->ppsSubKernelMemInfos[i] = ppsSharedPBDescSubKernelMemInfos[i]; if(PVRSRVDissociateMemFromResmanKM(ppsSharedPBDescSubKernelMemInfos[i]) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: " "Failed to dissociate shared PBDesc " "from process")); goto NoAdd; } } psStubPBDesc->sHWPBDescDevVAddr = sHWPBDescDevVAddr; psResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_PB_DESC, psStubPBDesc, 0, &SGXCleanupSharedPBDescCallback); if (psResItem == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: " "Failed to register shared PBDesc " " with the resource manager")); goto NoAdd; } psStubPBDesc->hDevCookie = hDevCookie; List_PVRSRV_STUB_PBDESC_Insert(&(psSGXDevInfo->psStubPBDescListKM), psStubPBDesc); *phSharedPBDesc = (IMG_HANDLE)psResItem; return PVRSRV_OK; NoAdd: if(psStubPBDesc) { if(psStubPBDesc->ppsSubKernelMemInfos) { OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount, psStubPBDesc->ppsSubKernelMemInfos, 0); psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL; } OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_STUB_PBDESC), psStubPBDesc, 0); } NoAddKeepPB: for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++) { PVRSRVFreeDeviceMemKM(hDevCookie, ppsSharedPBDescSubKernelMemInfos[i]); } PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo); PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo); PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo); PVRSRVFreeDeviceMemKM(hDevCookie, psHWBlockKernelMemInfo); return eRet; }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie, PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_HANDLE hDevMemHeap, IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_SIZE_T ui32Alignment, PVRSRV_KERNEL_MEM_INFO **ppsMemInfo) { PVRSRV_KERNEL_MEM_INFO *psMemInfo; PVRSRV_ERROR eError; BM_HEAP *psBMHeap; IMG_HANDLE hDevMemContext; if (!hDevMemHeap || (ui32Size == 0)) { return PVRSRV_ERROR_INVALID_PARAMS; } if (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) { if (((ui32Size % HOST_PAGESIZE()) != 0) || ((ui32Alignment % HOST_PAGESIZE()) != 0)) { return PVRSRV_ERROR_INVALID_PARAMS; } } eError = AllocDeviceMem(hDevCookie, hDevMemHeap, ui32Flags, ui32Size, ui32Alignment, &psMemInfo); if (eError != PVRSRV_OK) { return eError; } #if defined(PVRSRV_RESOURCE_PROFILING) psBMHeap = (BM_HEAP*)hDevMemHeap; if (psBMHeap->pBMContext->psDeviceNode->pfnResProfCB) psBMHeap->pBMContext->psDeviceNode->pfnResProfCB(hDevCookie, psMemInfo->ui32AllocSize, IMG_TRUE); #endif if (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ) { psMemInfo->psKernelSyncInfo = IMG_NULL; } else { psBMHeap = (BM_HEAP*)hDevMemHeap; hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext; eError = PVRSRVAllocSyncInfoKM(hDevCookie, hDevMemContext, &psMemInfo->psKernelSyncInfo); if(eError != PVRSRV_OK) { goto free_mainalloc; } psMemInfo->psKernelSyncInfo->ui32RefCount++; #if defined(PVRSRV_RESOURCE_PROFILING) if (psBMHeap->pBMContext->psDeviceNode->pfnResProfCB) psBMHeap->pBMContext->psDeviceNode->pfnResProfCB(hDevCookie, psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize, IMG_TRUE); #endif } *ppsMemInfo = psMemInfo; if (ui32Flags & PVRSRV_MEM_NO_RESMAN) { psMemInfo->sMemBlk.hResItem = IMG_NULL; } else { psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICEMEM_ALLOCATION, psMemInfo, 0, &FreeDeviceMemCallBack); if (psMemInfo->sMemBlk.hResItem == IMG_NULL) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto free_mainalloc; } } psMemInfo->ui32RefCount++; psMemInfo->memType = PVRSRV_MEMTYPE_DEVICE; return (PVRSRV_OK); free_mainalloc: #if defined(PVRSRV_RESOURCE_PROFILING) if (psBMHeap->pBMContext->psDeviceNode->pfnResProfCB) psBMHeap->pBMContext->psDeviceNode->pfnResProfCB(hDevCookie, psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize, IMG_FALSE); #endif FreeDeviceMem(psMemInfo); return eError; }
IMG_EXPORT PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_UINT32 ui32DeviceID, IMG_HANDLE hDevCookie, IMG_HANDLE *phDeviceKM) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo; PVRSRV_DEVICE_NODE *psDeviceNode; SYS_DATA *psSysData; PVRSRV_ERROR eError; if(!phDeviceKM || !hDevCookie) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Invalid params")); return PVRSRV_ERROR_GENERIC; } SysAcquireData(&psSysData); psDeviceNode = (PVRSRV_DEVICE_NODE*) List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, MatchDeviceKM_AnyVaCb, ui32DeviceID, IMG_FALSE, PVRSRV_DEVICE_CLASS_DISPLAY); if (!psDeviceNode) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID)); return PVRSRV_ERROR_GENERIC; } psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice; if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psDCPerContextInfo), (IMG_VOID **)&psDCPerContextInfo, IMG_NULL, "Display Class per Context Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed psDCPerContextInfo alloc")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo)); if(psDCInfo->ui32RefCount++ == 0) { psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie; psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext; eError = PVRSRVAllocSyncInfoKM(IMG_NULL, (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext, &psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed sync info alloc")); psDCInfo->ui32RefCount--; return eError; } eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID, &psDCInfo->hExtDevice, (PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device")); psDCInfo->ui32RefCount--; PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo); return eError; } } psDCPerContextInfo->psDCInfo = psDCInfo; psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DISPLAYCLASS_DEVICE, psDCPerContextInfo, 0, CloseDCDeviceCallBack); *phDeviceKM = (IMG_HANDLE)psDCPerContextInfo; 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; }
static IMG_INT PVRSRVBridgeTLOpenStream(IMG_UINT32 ui32BridgeID, PVRSRV_BRIDGE_IN_TLOPENSTREAM *psTLOpenStreamIN, PVRSRV_BRIDGE_OUT_TLOPENSTREAM *psTLOpenStreamOUT, CONNECTION_DATA *psConnection) { IMG_CHAR *uiNameInt = IMG_NULL; TL_STREAM_DESC * psSDInt = IMG_NULL; IMG_HANDLE hSDInt2 = IMG_NULL; DEVMEM_EXPORTCOOKIE * psClientBUFExportCookieInt = IMG_NULL; PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PVRTL_TLOPENSTREAM); psTLOpenStreamOUT->hSD = IMG_NULL; { uiNameInt = OSAllocMem(PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)); if (!uiNameInt) { psTLOpenStreamOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto TLOpenStream_exit; } } /* Copy the data over */ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psTLOpenStreamIN->puiName, PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) || (OSCopyFromUser(NULL, uiNameInt, psTLOpenStreamIN->puiName, PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK) ) { psTLOpenStreamOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; goto TLOpenStream_exit; } psTLOpenStreamOUT->eError = TLServerOpenStreamKM( uiNameInt, psTLOpenStreamIN->ui32Mode, &psSDInt, &psClientBUFExportCookieInt); /* Exit early if bridged call fails */ if(psTLOpenStreamOUT->eError != PVRSRV_OK) { goto TLOpenStream_exit; } /* Create a resman item and overwrite the handle with it */ hSDInt2 = ResManRegisterRes(psConnection->hResManContext, RESMAN_TYPE_TL_STREAM_DESC, psSDInt, /* FIXME: how can we avoid this cast? */ (RESMAN_FREE_FN)&TLServerCloseStreamKM); if (hSDInt2 == IMG_NULL) { psTLOpenStreamOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE; goto TLOpenStream_exit; } psTLOpenStreamOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase, &psTLOpenStreamOUT->hSD, (IMG_HANDLE) hSDInt2, PVRSRV_HANDLE_TYPE_PVR_TL_SD, PVRSRV_HANDLE_ALLOC_FLAG_NONE ); if (psTLOpenStreamOUT->eError != PVRSRV_OK) { goto TLOpenStream_exit; } psTLOpenStreamOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase, &psTLOpenStreamOUT->hClientBUFExportCookie, (IMG_HANDLE) psClientBUFExportCookieInt, PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE, PVRSRV_HANDLE_ALLOC_FLAG_NONE ,psTLOpenStreamOUT->hSD); if (psTLOpenStreamOUT->eError != PVRSRV_OK) { goto TLOpenStream_exit; } TLOpenStream_exit: if (psTLOpenStreamOUT->eError != PVRSRV_OK) { if (psTLOpenStreamOUT->hSD) { PVRSRVReleaseHandle(psConnection->psHandleBase, (IMG_HANDLE) psTLOpenStreamOUT->hSD, PVRSRV_HANDLE_TYPE_PVR_TL_SD); } /* If we have a valid resman item we should undo the bridge function by freeing the resman item */ if (hSDInt2) { PVRSRV_ERROR eError = ResManFreeResByPtr(hSDInt2); /* Freeing a resource should never fail... */ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY)); } else if (psSDInt) { TLServerCloseStreamKM(psSDInt); } } if (uiNameInt) OSFreeMem(uiNameInt); return 0; }
static IMG_INT PVRSRVBridgeRGXCreateComputeContext(IMG_UINT32 ui32BridgeID, PVRSRV_BRIDGE_IN_RGXCREATECOMPUTECONTEXT *psRGXCreateComputeContextIN, PVRSRV_BRIDGE_OUT_RGXCREATECOMPUTECONTEXT *psRGXCreateComputeContextOUT, CONNECTION_DATA *psConnection) { IMG_HANDLE hDevNodeInt = IMG_NULL; IMG_BYTE *psFrameworkCmdInt = IMG_NULL; IMG_HANDLE hPrivDataInt = IMG_NULL; RGX_SERVER_COMPUTE_CONTEXT * psComputeContextInt = IMG_NULL; IMG_HANDLE hComputeContextInt2 = IMG_NULL; PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXCMP_RGXCREATECOMPUTECONTEXT); if (psRGXCreateComputeContextIN->ui32FrameworkCmdize != 0) { psFrameworkCmdInt = OSAllocMem(psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)); if (!psFrameworkCmdInt) { psRGXCreateComputeContextOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto RGXCreateComputeContext_exit; } } /* Copy the data over */ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXCreateComputeContextIN->psFrameworkCmd, psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) || (OSCopyFromUser(NULL, psFrameworkCmdInt, psRGXCreateComputeContextIN->psFrameworkCmd, psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) != PVRSRV_OK) ) { psRGXCreateComputeContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; goto RGXCreateComputeContext_exit; } { /* Look up the address from the handle */ psRGXCreateComputeContextOUT->eError = PVRSRVLookupHandle(psConnection->psHandleBase, (IMG_HANDLE *) &hDevNodeInt, psRGXCreateComputeContextIN->hDevNode, PVRSRV_HANDLE_TYPE_DEV_NODE); if(psRGXCreateComputeContextOUT->eError != PVRSRV_OK) { goto RGXCreateComputeContext_exit; } } { /* Look up the address from the handle */ psRGXCreateComputeContextOUT->eError = PVRSRVLookupHandle(psConnection->psHandleBase, (IMG_HANDLE *) &hPrivDataInt, psRGXCreateComputeContextIN->hPrivData, PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA); if(psRGXCreateComputeContextOUT->eError != PVRSRV_OK) { goto RGXCreateComputeContext_exit; } } psRGXCreateComputeContextOUT->eError = PVRSRVRGXCreateComputeContextKM(psConnection, hDevNodeInt, psRGXCreateComputeContextIN->ui32Priority, psRGXCreateComputeContextIN->sMCUFenceAddr, psRGXCreateComputeContextIN->ui32FrameworkCmdize, psFrameworkCmdInt, hPrivDataInt, &psComputeContextInt); /* Exit early if bridged call fails */ if(psRGXCreateComputeContextOUT->eError != PVRSRV_OK) { goto RGXCreateComputeContext_exit; } /* Create a resman item and overwrite the handle with it */ hComputeContextInt2 = ResManRegisterRes(psConnection->hResManContext, RESMAN_TYPE_RGX_SERVER_COMPUTE_CONTEXT, psComputeContextInt, (RESMAN_FREE_FN)&PVRSRVRGXDestroyComputeContextKM); if (hComputeContextInt2 == IMG_NULL) { psRGXCreateComputeContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE; goto RGXCreateComputeContext_exit; } psRGXCreateComputeContextOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase, &psRGXCreateComputeContextOUT->hComputeContext, (IMG_HANDLE) hComputeContextInt2, PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT, PVRSRV_HANDLE_ALLOC_FLAG_NONE ); if (psRGXCreateComputeContextOUT->eError != PVRSRV_OK) { goto RGXCreateComputeContext_exit; } RGXCreateComputeContext_exit: if (psRGXCreateComputeContextOUT->eError != PVRSRV_OK) { /* If we have a valid resman item we should undo the bridge function by freeing the resman item */ if (hComputeContextInt2) { PVRSRV_ERROR eError = ResManFreeResByPtr(hComputeContextInt2); /* Freeing a resource should never fail... */ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY)); } else if (psComputeContextInt) { PVRSRVRGXDestroyComputeContextKM(psComputeContextInt); } } if (psFrameworkCmdInt) OSFreeMem(psFrameworkCmdInt); return 0; }
static IMG_INT PVRSRVBridgeEventObjectOpen(IMG_UINT32 ui32BridgeID, PVRSRV_BRIDGE_IN_EVENTOBJECTOPEN *psEventObjectOpenIN, PVRSRV_BRIDGE_OUT_EVENTOBJECTOPEN *psEventObjectOpenOUT, CONNECTION_DATA *psConnection) { IMG_HANDLE hEventObjectInt = IMG_NULL; IMG_HANDLE hEventObjectInt2 = IMG_NULL; IMG_HANDLE hOSEventInt = IMG_NULL; IMG_HANDLE hOSEventInt2 = IMG_NULL; PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTOPEN); { /* Look up the address from the handle */ psEventObjectOpenOUT->eError = PVRSRVLookupHandle(psConnection->psHandleBase, (IMG_HANDLE *) &hEventObjectInt2, psEventObjectOpenIN->hEventObject, PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT); if(psEventObjectOpenOUT->eError != PVRSRV_OK) { goto EventObjectOpen_exit; } /* Look up the data from the resman address */ psEventObjectOpenOUT->eError = ResManFindPrivateDataByPtr(hEventObjectInt2, (IMG_VOID **) &hEventObjectInt); if(psEventObjectOpenOUT->eError != PVRSRV_OK) { goto EventObjectOpen_exit; } } psEventObjectOpenOUT->eError = OSEventObjectOpen( hEventObjectInt, &hOSEventInt); /* Exit early if bridged call fails */ if(psEventObjectOpenOUT->eError != PVRSRV_OK) { goto EventObjectOpen_exit; } /* Create a resman item and overwrite the handle with it */ hOSEventInt2 = ResManRegisterRes(psConnection->hResManContext, RESMAN_TYPE_EVENT_OBJECT, hOSEventInt, /* FIXME: how can we avoid this cast? */ (RESMAN_FREE_FN)&OSEventObjectClose); if (hOSEventInt2 == IMG_NULL) { psEventObjectOpenOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE; goto EventObjectOpen_exit; } psEventObjectOpenOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase, &psEventObjectOpenOUT->hOSEvent, (IMG_HANDLE) hOSEventInt2, PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT, PVRSRV_HANDLE_ALLOC_FLAG_MULTI ); if (psEventObjectOpenOUT->eError != PVRSRV_OK) { goto EventObjectOpen_exit; } EventObjectOpen_exit: if (psEventObjectOpenOUT->eError != PVRSRV_OK) { /* If we have a valid resman item we should undo the bridge function by freeing the resman item */ if (hOSEventInt2) { PVRSRV_ERROR eError = ResManFreeResByPtr(hOSEventInt2); /* Freeing a resource should never fail... */ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY)); } else if (hOSEventInt) { OSEventObjectClose(hOSEventInt); } } return 0; }
static IMG_INT PVRSRVBridgeAcquireGlobalEventObject(IMG_UINT32 ui32BridgeID, PVRSRV_BRIDGE_IN_ACQUIREGLOBALEVENTOBJECT *psAcquireGlobalEventObjectIN, PVRSRV_BRIDGE_OUT_ACQUIREGLOBALEVENTOBJECT *psAcquireGlobalEventObjectOUT, CONNECTION_DATA *psConnection) { IMG_HANDLE hGlobalEventObjectInt = IMG_NULL; IMG_HANDLE hGlobalEventObjectInt2 = IMG_NULL; PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_ACQUIREGLOBALEVENTOBJECT); PVR_UNREFERENCED_PARAMETER(psAcquireGlobalEventObjectIN); psAcquireGlobalEventObjectOUT->eError = AcquireGlobalEventObjectServer( &hGlobalEventObjectInt); /* Exit early if bridged call fails */ if(psAcquireGlobalEventObjectOUT->eError != PVRSRV_OK) { goto AcquireGlobalEventObject_exit; } /* Create a resman item and overwrite the handle with it */ hGlobalEventObjectInt2 = ResManRegisterRes(psConnection->hResManContext, RESMAN_TYPE_SHARED_EVENT_OBJECT, hGlobalEventObjectInt, /* FIXME: how can we avoid this cast? */ (RESMAN_FREE_FN)&ReleaseGlobalEventObjectServer); if (hGlobalEventObjectInt2 == IMG_NULL) { psAcquireGlobalEventObjectOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE; goto AcquireGlobalEventObject_exit; } psAcquireGlobalEventObjectOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase, &psAcquireGlobalEventObjectOUT->hGlobalEventObject, (IMG_HANDLE) hGlobalEventObjectInt2, PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT, PVRSRV_HANDLE_ALLOC_FLAG_SHARED ); if (psAcquireGlobalEventObjectOUT->eError != PVRSRV_OK) { goto AcquireGlobalEventObject_exit; } AcquireGlobalEventObject_exit: if (psAcquireGlobalEventObjectOUT->eError != PVRSRV_OK) { /* If we have a valid resman item we should undo the bridge function by freeing the resman item */ if (hGlobalEventObjectInt2) { PVRSRV_ERROR eError = ResManFreeResByPtr(hGlobalEventObjectInt2); /* Freeing a resource should never fail... */ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY)); } else if (hGlobalEventObjectInt) { ReleaseGlobalEventObjectServer(hGlobalEventObjectInt); } } return 0; }
static IMG_INT PVRSRVBridgePMRSecureExportPMR(IMG_UINT32 ui32BridgeID, PVRSRV_BRIDGE_IN_PMRSECUREEXPORTPMR *psPMRSecureExportPMRIN, PVRSRV_BRIDGE_OUT_PMRSECUREEXPORTPMR *psPMRSecureExportPMROUT, CONNECTION_DATA *psConnection) { PMR * psPMRInt = IMG_NULL; IMG_HANDLE hPMRInt2 = IMG_NULL; PMR * psPMROutInt = IMG_NULL; IMG_HANDLE hPMROutInt2 = IMG_NULL; CONNECTION_DATA *psSecureConnection; PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SMM_PMRSECUREEXPORTPMR); { /* Look up the address from the handle */ psPMRSecureExportPMROUT->eError = PVRSRVLookupHandle(psConnection->psHandleBase, (IMG_HANDLE *) &hPMRInt2, psPMRSecureExportPMRIN->hPMR, PVRSRV_HANDLE_TYPE_PHYSMEM_PMR); if(psPMRSecureExportPMROUT->eError != PVRSRV_OK) { goto PMRSecureExportPMR_exit; } /* Look up the data from the resman address */ psPMRSecureExportPMROUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt); if(psPMRSecureExportPMROUT->eError != PVRSRV_OK) { goto PMRSecureExportPMR_exit; } } psPMRSecureExportPMROUT->eError = PMRSecureExportPMR(psConnection, psPMRInt, &psPMRSecureExportPMROUT->Export, &psPMROutInt, &psSecureConnection); /* Exit early if bridged call fails */ if(psPMRSecureExportPMROUT->eError != PVRSRV_OK) { goto PMRSecureExportPMR_exit; } /* Create a resman item and overwrite the handle with it */ hPMROutInt2 = ResManRegisterRes(psSecureConnection->hResManContext, RESMAN_TYPE_PMR, psPMROutInt, /* FIXME: how can we avoid this cast? */ (RESMAN_FREE_FN)&PMRSecureUnexportPMR); if (hPMROutInt2 == IMG_NULL) { psPMRSecureExportPMROUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE; goto PMRSecureExportPMR_exit; } PMRSecureExportPMR_exit: if (psPMRSecureExportPMROUT->eError != PVRSRV_OK) { /* If we have a valid resman item we should undo the bridge function by freeing the resman item */ if (hPMROutInt2) { PVRSRV_ERROR eError = ResManFreeResByPtr(hPMROutInt2); /* Freeing a resource should never fail... */ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY)); } else if (psPMROutInt) { PMRSecureUnexportPMR(psPMROutInt); } } return 0; }
static IMG_INT PVRSRVBridgePMRSecureImportPMR(IMG_UINT32 ui32BridgeID, PVRSRV_BRIDGE_IN_PMRSECUREIMPORTPMR *psPMRSecureImportPMRIN, PVRSRV_BRIDGE_OUT_PMRSECUREIMPORTPMR *psPMRSecureImportPMROUT, CONNECTION_DATA *psConnection) { PMR * psPMRInt = IMG_NULL; IMG_HANDLE hPMRInt2 = IMG_NULL; PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SMM_PMRSECUREIMPORTPMR); psPMRSecureImportPMROUT->eError = PMRSecureImportPMR( psPMRSecureImportPMRIN->Export, &psPMRInt, &psPMRSecureImportPMROUT->uiSize, &psPMRSecureImportPMROUT->sAlign); /* Exit early if bridged call fails */ if(psPMRSecureImportPMROUT->eError != PVRSRV_OK) { goto PMRSecureImportPMR_exit; } /* Create a resman item and overwrite the handle with it */ hPMRInt2 = ResManRegisterRes(psConnection->hResManContext, RESMAN_TYPE_PMR, psPMRInt, /* FIXME: how can we avoid this cast? */ (RESMAN_FREE_FN)&PMRUnrefPMR); if (hPMRInt2 == IMG_NULL) { psPMRSecureImportPMROUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE; goto PMRSecureImportPMR_exit; } psPMRSecureImportPMROUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase, &psPMRSecureImportPMROUT->hPMR, (IMG_HANDLE) hPMRInt2, PVRSRV_HANDLE_TYPE_PHYSMEM_PMR, PVRSRV_HANDLE_ALLOC_FLAG_NONE ); if (psPMRSecureImportPMROUT->eError != PVRSRV_OK) { goto PMRSecureImportPMR_exit; } PMRSecureImportPMR_exit: if (psPMRSecureImportPMROUT->eError != PVRSRV_OK) { /* If we have a valid resman item we should undo the bridge function by freeing the resman item */ if (hPMRInt2) { PVRSRV_ERROR eError = ResManFreeResByPtr(hPMRInt2); /* Freeing a resource should never fail... */ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY)); } else if (psPMRInt) { PMRUnrefPMR(psPMRInt); } } return 0; }
static IMG_INT PVRSRVBridgeServerSyncAlloc(IMG_UINT32 ui32BridgeID, PVRSRV_BRIDGE_IN_SERVERSYNCALLOC *psServerSyncAllocIN, PVRSRV_BRIDGE_OUT_SERVERSYNCALLOC *psServerSyncAllocOUT, CONNECTION_DATA *psConnection) { IMG_HANDLE hDevNodeInt = IMG_NULL; SERVER_SYNC_PRIMITIVE * psSyncHandleInt = IMG_NULL; IMG_HANDLE hSyncHandleInt2 = IMG_NULL; PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SERVERSYNCALLOC); { /* Look up the address from the handle */ psServerSyncAllocOUT->eError = PVRSRVLookupHandle(psConnection->psHandleBase, (IMG_HANDLE *) &hDevNodeInt, psServerSyncAllocIN->hDevNode, PVRSRV_HANDLE_TYPE_DEV_NODE); if(psServerSyncAllocOUT->eError != PVRSRV_OK) { goto ServerSyncAlloc_exit; } } psServerSyncAllocOUT->eError = PVRSRVServerSyncAllocKM( hDevNodeInt, &psSyncHandleInt, &psServerSyncAllocOUT->ui32SyncPrimVAddr); /* Exit early if bridged call fails */ if(psServerSyncAllocOUT->eError != PVRSRV_OK) { goto ServerSyncAlloc_exit; } /* Create a resman item and overwrite the handle with it */ hSyncHandleInt2 = ResManRegisterRes(psConnection->hResManContext, RESMAN_TYPE_SERVER_SYNC_PRIMITIVE, psSyncHandleInt, /* FIXME: how can we avoid this cast? */ (RESMAN_FREE_FN)&PVRSRVServerSyncFreeKM); if (hSyncHandleInt2 == IMG_NULL) { psServerSyncAllocOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE; goto ServerSyncAlloc_exit; } psServerSyncAllocOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase, &psServerSyncAllocOUT->hSyncHandle, (IMG_HANDLE) hSyncHandleInt2, PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE, PVRSRV_HANDLE_ALLOC_FLAG_NONE ); if (psServerSyncAllocOUT->eError != PVRSRV_OK) { goto ServerSyncAlloc_exit; } ServerSyncAlloc_exit: if (psServerSyncAllocOUT->eError != PVRSRV_OK) { /* If we have a valid resman item we should undo the bridge function by freeing the resman item */ if (hSyncHandleInt2) { PVRSRV_ERROR eError = ResManFreeResByPtr(hSyncHandleInt2); /* Freeing a resource should never fail... */ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY)); } else if (psSyncHandleInt) { PVRSRVServerSyncFreeKM(psSyncHandleInt); } } return 0; }
static IMG_INT PVRSRVBridgeSyncPrimOpCreate(IMG_UINT32 ui32BridgeID, PVRSRV_BRIDGE_IN_SYNCPRIMOPCREATE *psSyncPrimOpCreateIN, PVRSRV_BRIDGE_OUT_SYNCPRIMOPCREATE *psSyncPrimOpCreateOUT, CONNECTION_DATA *psConnection) { SYNC_PRIMITIVE_BLOCK * *psBlockListInt = IMG_NULL; IMG_HANDLE *hBlockListInt2 = IMG_NULL; IMG_UINT32 *ui32SyncBlockIndexInt = IMG_NULL; IMG_UINT32 *ui32IndexInt = IMG_NULL; SERVER_SYNC_PRIMITIVE * *psServerSyncInt = IMG_NULL; IMG_HANDLE *hServerSyncInt2 = IMG_NULL; SERVER_OP_COOKIE * psServerCookieInt = IMG_NULL; IMG_HANDLE hServerCookieInt2 = IMG_NULL; PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCPRIMOPCREATE); if (psSyncPrimOpCreateIN->ui32SyncBlockCount != 0) { psBlockListInt = OSAllocMem(psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(SYNC_PRIMITIVE_BLOCK *)); if (!psBlockListInt) { psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto SyncPrimOpCreate_exit; } hBlockListInt2 = OSAllocMem(psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE)); if (!hBlockListInt2) { psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto SyncPrimOpCreate_exit; } } /* Copy the data over */ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncPrimOpCreateIN->phBlockList, psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE)) || (OSCopyFromUser(NULL, hBlockListInt2, psSyncPrimOpCreateIN->phBlockList, psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) ) { psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; goto SyncPrimOpCreate_exit; } if (psSyncPrimOpCreateIN->ui32ClientSyncCount != 0) { ui32SyncBlockIndexInt = OSAllocMem(psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)); if (!ui32SyncBlockIndexInt) { psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto SyncPrimOpCreate_exit; } } /* Copy the data over */ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncPrimOpCreateIN->pui32SyncBlockIndex, psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) || (OSCopyFromUser(NULL, ui32SyncBlockIndexInt, psSyncPrimOpCreateIN->pui32SyncBlockIndex, psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) ) { psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; goto SyncPrimOpCreate_exit; } if (psSyncPrimOpCreateIN->ui32ClientSyncCount != 0) { ui32IndexInt = OSAllocMem(psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)); if (!ui32IndexInt) { psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto SyncPrimOpCreate_exit; } } /* Copy the data over */ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncPrimOpCreateIN->pui32Index, psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) || (OSCopyFromUser(NULL, ui32IndexInt, psSyncPrimOpCreateIN->pui32Index, psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) ) { psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; goto SyncPrimOpCreate_exit; } if (psSyncPrimOpCreateIN->ui32ServerSyncCount != 0) { psServerSyncInt = OSAllocMem(psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *)); if (!psServerSyncInt) { psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto SyncPrimOpCreate_exit; } hServerSyncInt2 = OSAllocMem(psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)); if (!hServerSyncInt2) { psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto SyncPrimOpCreate_exit; } } /* Copy the data over */ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncPrimOpCreateIN->phServerSync, psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) || (OSCopyFromUser(NULL, hServerSyncInt2, psSyncPrimOpCreateIN->phServerSync, psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) ) { psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; goto SyncPrimOpCreate_exit; } { IMG_UINT32 i; for (i=0;i<psSyncPrimOpCreateIN->ui32SyncBlockCount;i++) { { /* Look up the address from the handle */ psSyncPrimOpCreateOUT->eError = PVRSRVLookupHandle(psConnection->psHandleBase, (IMG_HANDLE *) &hBlockListInt2[i], psSyncPrimOpCreateIN->phBlockList[i], PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK); if(psSyncPrimOpCreateOUT->eError != PVRSRV_OK) { goto SyncPrimOpCreate_exit; } /* Look up the data from the resman address */ psSyncPrimOpCreateOUT->eError = ResManFindPrivateDataByPtr(hBlockListInt2[i], (IMG_VOID **) &psBlockListInt[i]); if(psSyncPrimOpCreateOUT->eError != PVRSRV_OK) { goto SyncPrimOpCreate_exit; } } } } { IMG_UINT32 i; for (i=0;i<psSyncPrimOpCreateIN->ui32ServerSyncCount;i++) { { /* Look up the address from the handle */ psSyncPrimOpCreateOUT->eError = PVRSRVLookupHandle(psConnection->psHandleBase, (IMG_HANDLE *) &hServerSyncInt2[i], psSyncPrimOpCreateIN->phServerSync[i], PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE); if(psSyncPrimOpCreateOUT->eError != PVRSRV_OK) { goto SyncPrimOpCreate_exit; } /* Look up the data from the resman address */ psSyncPrimOpCreateOUT->eError = ResManFindPrivateDataByPtr(hServerSyncInt2[i], (IMG_VOID **) &psServerSyncInt[i]); if(psSyncPrimOpCreateOUT->eError != PVRSRV_OK) { goto SyncPrimOpCreate_exit; } } } } psSyncPrimOpCreateOUT->eError = PVRSRVSyncPrimOpCreateKM( psSyncPrimOpCreateIN->ui32SyncBlockCount, psBlockListInt, psSyncPrimOpCreateIN->ui32ClientSyncCount, ui32SyncBlockIndexInt, ui32IndexInt, psSyncPrimOpCreateIN->ui32ServerSyncCount, psServerSyncInt, &psServerCookieInt); /* Exit early if bridged call fails */ if(psSyncPrimOpCreateOUT->eError != PVRSRV_OK) { goto SyncPrimOpCreate_exit; } /* Create a resman item and overwrite the handle with it */ hServerCookieInt2 = ResManRegisterRes(psConnection->hResManContext, RESMAN_TYPE_SERVER_OP_COOKIE, psServerCookieInt, /* FIXME: how can we avoid this cast? */ (RESMAN_FREE_FN)&PVRSRVSyncPrimOpDestroyKM); if (hServerCookieInt2 == IMG_NULL) { psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE; goto SyncPrimOpCreate_exit; } psSyncPrimOpCreateOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase, &psSyncPrimOpCreateOUT->hServerCookie, (IMG_HANDLE) hServerCookieInt2, PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE, PVRSRV_HANDLE_ALLOC_FLAG_NONE ); if (psSyncPrimOpCreateOUT->eError != PVRSRV_OK) { goto SyncPrimOpCreate_exit; } SyncPrimOpCreate_exit: if (psSyncPrimOpCreateOUT->eError != PVRSRV_OK) { /* If we have a valid resman item we should undo the bridge function by freeing the resman item */ if (hServerCookieInt2) { PVRSRV_ERROR eError = ResManFreeResByPtr(hServerCookieInt2); /* Freeing a resource should never fail... */ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY)); } else if (psServerCookieInt) { PVRSRVSyncPrimOpDestroyKM(psServerCookieInt); } } if (psBlockListInt) OSFreeMem(psBlockListInt); if (hBlockListInt2) OSFreeMem(hBlockListInt2); if (ui32SyncBlockIndexInt) OSFreeMem(ui32SyncBlockIndexInt); if (ui32IndexInt) OSFreeMem(ui32IndexInt); if (psServerSyncInt) OSFreeMem(psServerSyncInt); if (hServerSyncInt2) OSFreeMem(hServerSyncInt2); return 0; }
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; }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc, PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo, IMG_HANDLE hDstDevMemHeap, PVRSRV_KERNEL_MEM_INFO **ppsDstMemInfo) { PVRSRV_ERROR eError; IMG_UINT32 i; IMG_SIZE_T ui32PageCount, ui32PageOffset; IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE(); IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL; IMG_DEV_PHYADDR sDevPAddr; BM_BUF *psBuf; IMG_DEV_VIRTADDR sDevVAddr; PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL; BM_HANDLE hBuffer; PVRSRV_MEMBLK *psMemBlock; IMG_BOOL bBMError; PVRSRV_DEVICE_NODE *psDeviceNode; IMG_VOID *pvPageAlignedCPUVAddr; RESMAN_MAP_DEVICE_MEM_DATA *psMapData = IMG_NULL; if(!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } *ppsDstMemInfo = IMG_NULL; ui32PageOffset = psSrcMemInfo->sDevVAddr.uiAddr & (ui32HostPageSize - 1); ui32PageCount = HOST_PAGEALIGN(psSrcMemInfo->ui32AllocSize + ui32PageOffset) / ui32HostPageSize; pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)psSrcMemInfo->pvLinAddrKM - ui32PageOffset); if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageCount*sizeof(IMG_SYS_PHYADDR), (IMG_VOID **)&psSysPAddr, IMG_NULL, "Array of Page Addresses") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block")); return PVRSRV_ERROR_OUT_OF_MEMORY; } psBuf = psSrcMemInfo->sMemBlk.hBuffer; psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode; sDevVAddr.uiAddr = psSrcMemInfo->sDevVAddr.uiAddr - IMG_CAST_TO_DEVVADDR_UINT(ui32PageOffset); for(i=0; i<ui32PageCount; i++) { BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr); psSysPAddr[i] = SysDevPAddrToSysPAddr (psDeviceNode->sDevId.eDeviceType, sDevPAddr); sDevVAddr.uiAddr += IMG_CAST_TO_DEVVADDR_UINT(ui32HostPageSize); } if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), (IMG_VOID **)&psMapData, IMG_NULL, "Resource Manager Map Data") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc resman map data")); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExit; } 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,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block")); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExit; } OSMemSet(psMemInfo, 0, sizeof(*psMemInfo)); psMemInfo->ui32Flags = psSrcMemInfo->ui32Flags; psMemBlock = &(psMemInfo->sMemBlk); bBMError = BM_Wrap(hDstDevMemHeap, psSrcMemInfo->ui32AllocSize, ui32PageOffset, IMG_FALSE, psSysPAddr, pvPageAlignedCPUVAddr, &psMemInfo->ui32Flags, &hBuffer); if (!bBMError) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: BM_Wrap Failed")); eError = PVRSRV_ERROR_BAD_MAPPING; goto ErrorExit; } psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); psMemBlock->hBuffer = (IMG_HANDLE)hBuffer; psMemBlock->psIntSysPAddr = psSysPAddr; psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM; psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = psSrcMemInfo->ui32AllocSize; psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo; if( psMemInfo->psKernelSyncInfo ) psMemInfo->psKernelSyncInfo->ui32RefCount++; psMemInfo->pvSysBackupBuffer = IMG_NULL; psMemInfo->ui32RefCount++; psSrcMemInfo->ui32RefCount++; BM_Export(psSrcMemInfo->sMemBlk.hBuffer); psMemInfo->memType = PVRSRV_MEMTYPE_MAPPED; psMapData->psMemInfo = psMemInfo; psMapData->psSrcMemInfo = psSrcMemInfo; psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICEMEM_MAPPING, psMapData, 0, &UnmapDeviceMemoryCallBack); *ppsDstMemInfo = psMemInfo; return PVRSRV_OK; ErrorExit: if(psSysPAddr) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psSysPAddr, IMG_NULL); } if(psMemInfo) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL); } if(psMapData) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL); } return eError; }
IMG_EXPORT PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_UINT32 ui32DeviceID, IMG_HANDLE hDevCookie, IMG_HANDLE *phDeviceKM) { PVRSRV_BUFFERCLASS_INFO *psBCInfo; PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo; PVRSRV_DEVICE_NODE *psDeviceNode; SYS_DATA *psSysData; IMG_UINT32 i; PVRSRV_ERROR eError; if(!phDeviceKM || !hDevCookie) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Invalid params")); return PVRSRV_ERROR_GENERIC; } SysAcquireData(&psSysData); psDeviceNode = (PVRSRV_DEVICE_NODE*) List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, MatchDeviceKM_AnyVaCb, ui32DeviceID, IMG_FALSE, PVRSRV_DEVICE_CLASS_BUFFER); if (!psDeviceNode) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID)); return PVRSRV_ERROR_GENERIC; } psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice; if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psBCPerContextInfo), (IMG_VOID **)&psBCPerContextInfo, IMG_NULL, "Buffer Class per Context Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed psBCPerContextInfo alloc")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo)); if(psBCInfo->ui32RefCount++ == 0) { BUFFER_INFO sBufferInfo; psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie; psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext; eError = psBCInfo->psFuncTable->pfnOpenBCDevice(&psBCInfo->hExtDevice); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to open external BC device")); return eError; } eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM : Failed to get BC Info")); return eError; } psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount; eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount, (IMG_VOID **)&psBCInfo->psBuffer, IMG_NULL, "Array of Buffer Class Buffer"); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to allocate BC buffers")); return eError; } OSMemSet (psBCInfo->psBuffer, 0, sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount); for(i=0; i<psBCInfo->ui32BufferCount; i++) { eError = PVRSRVAllocSyncInfoKM(IMG_NULL, psBCInfo->hDevMemContext, &psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc")); goto ErrorExit; } eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice, i, psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData, &psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtBuffer); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to get BC buffers")); goto ErrorExit; } psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr; psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext; psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice; } } psBCPerContextInfo->psBCInfo = psBCInfo; psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_BUFFERCLASS_DEVICE, psBCPerContextInfo, 0, CloseBCDeviceCallBack); *phDeviceKM = (IMG_HANDLE)psBCPerContextInfo; return PVRSRV_OK; ErrorExit: for(i=0; i<psBCInfo->ui32BufferCount; i++) { if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) { PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); } } if(psBCInfo->psBuffer) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL); psBCInfo->psBuffer = IMG_NULL; } return eError; }
enum PVRSRV_ERROR PVRSRVMapDeviceMemoryKM( struct PVRSRV_PER_PROCESS_DATA *psPerProc, struct PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo, void *hDstDevMemHeap, struct PVRSRV_KERNEL_MEM_INFO **ppsDstMemInfo) { enum PVRSRV_ERROR eError; u32 ui32PageOffset; u32 ui32HostPageSize = HOST_PAGESIZE(); int page_count; int i; struct IMG_SYS_PHYADDR *psSysPAddr = NULL; struct IMG_DEV_PHYADDR sDevPAddr; struct BM_BUF *psBuf; struct IMG_DEV_VIRTADDR sDevVAddr; struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = NULL; void *hBuffer; struct PVRSRV_MEMBLK *psMemBlock; IMG_BOOL bBMError; struct PVRSRV_DEVICE_NODE *psDeviceNode; void *pvPageAlignedCPUVAddr; struct RESMAN_MAP_DEVICE_MEM_DATA *psMapData = NULL; if (!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryKM: invalid parameters"); return PVRSRV_ERROR_INVALID_PARAMS; } *ppsDstMemInfo = NULL; get_page_details((u32)psSrcMemInfo->pvLinAddrKM, psSrcMemInfo->ui32AllocSize, &ui32PageOffset, &page_count); pvPageAlignedCPUVAddr = (void *) ((u8 *) psSrcMemInfo->pvLinAddrKM - ui32PageOffset); if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, page_count * sizeof(struct IMG_SYS_PHYADDR), (void **) &psSysPAddr, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryKM: " "Failed to alloc memory for block"); return PVRSRV_ERROR_OUT_OF_MEMORY; } psBuf = psSrcMemInfo->sMemBlk.hBuffer; psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode; sDevVAddr.uiAddr = psSrcMemInfo->sDevVAddr.uiAddr - ui32PageOffset; for (i = 0; i < page_count; i++) { eError = BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryKM: " "Failed to retrieve page list from device"); goto ErrorExit; } psSysPAddr[i] = SysDevPAddrToSysPAddr(psDeviceNode->sDevId.eDeviceType, sDevPAddr); sDevVAddr.uiAddr += ui32HostPageSize; } if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct RESMAN_MAP_DEVICE_MEM_DATA), (void **)&psMapData, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryKM: " "Failed to alloc resman map data"); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExit; } if (OSAllocMem(PVRSRV_PAGEABLE_SELECT, sizeof(struct PVRSRV_KERNEL_MEM_INFO), (void **)&psMemInfo, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryKM: " "Failed to alloc memory for block"); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExit; } OSMemSet(psMemInfo, 0, sizeof(*psMemInfo)); psMemBlock = &(psMemInfo->sMemBlk); bBMError = BM_Wrap(hDstDevMemHeap, psSrcMemInfo->ui32AllocSize, ui32PageOffset, bm_is_continuous(psBuf), psSysPAddr, pvPageAlignedCPUVAddr, &psMemInfo->ui32Flags, &hBuffer); if (!bBMError) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryKM: BM_Wrap Failed"); eError = PVRSRV_ERROR_BAD_MAPPING; goto ErrorExit; } psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); psMemBlock->hBuffer = (void *) hBuffer; psMemBlock->psIntSysPAddr = psSysPAddr; psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM; psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = psSrcMemInfo->ui32AllocSize; psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo; psMemInfo->pvSysBackupBuffer = NULL; psSrcMemInfo->ui32RefCount++; psMapData->psMemInfo = psMemInfo; psMapData->psSrcMemInfo = psSrcMemInfo; psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICEMEM_MAPPING, psMapData, 0, UnmapDeviceMemoryCallBack); *ppsDstMemInfo = psMemInfo; return PVRSRV_OK; ErrorExit: if (psSysPAddr) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct IMG_SYS_PHYADDR), psSysPAddr, NULL); } if (psMemInfo) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(struct PVRSRV_KERNEL_MEM_INFO), psMemInfo, NULL); } if (psMapData) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(struct RESMAN_MAP_DEVICE_MEM_DATA), psMapData, NULL); } return eError; }
enum PVRSRV_ERROR PVRSRVOpenBCDeviceKM( struct PVRSRV_PER_PROCESS_DATA *psPerProc, u32 ui32DeviceID, void *hDevCookie, void **phDeviceKM) { struct PVRSRV_BUFFERCLASS_INFO *psBCInfo; struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo; struct PVRSRV_DEVICE_NODE *psDeviceNode; struct SYS_DATA *psSysData; u32 i; enum PVRSRV_ERROR eError; if (!phDeviceKM || !hDevCookie) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: Invalid params"); return PVRSRV_ERROR_GENERIC; } if (SysAcquireData(&psSysData) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: Failed to get SysData"); return PVRSRV_ERROR_GENERIC; } psDeviceNode = psSysData->psDeviceNodeList; while (psDeviceNode) { if ((psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_BUFFER) && (psDeviceNode->sDevId.ui32DeviceIndex == ui32DeviceID)) { psBCInfo = (struct PVRSRV_BUFFERCLASS_INFO *) psDeviceNode->pvDevice; goto FoundDevice; } psDeviceNode = psDeviceNode->psNext; } PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID); return PVRSRV_ERROR_GENERIC; FoundDevice: if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psBCPerContextInfo), (void **)&psBCPerContextInfo, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: " "Failed psBCPerContextInfo alloc"); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo)); if (psBCInfo->ui32RefCount++ == 0) { struct BUFFER_INFO sBufferInfo; psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie; psBCInfo->hDevMemContext = (void *) psDeviceNode->sDevMemoryInfo.pBMKernelContext; eError = psBCInfo->psFuncTable->pfnOpenBCDevice(&psBCInfo-> hExtDevice); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: " "Failed to open external BC device"); return eError; } eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM : Failed to get BC Info"); return eError; } psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount; eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount, (void **) &psBCInfo->psBuffer, NULL); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: " "Failed to allocate BC buffers"); return eError; } OSMemSet(psBCInfo->psBuffer, 0, sizeof(struct PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount); for (i = 0; i < psBCInfo->ui32BufferCount; i++) { eError = PVRSRVAllocSyncInfoKM(NULL, psBCInfo->hDevMemContext, &psBCInfo->psBuffer[i].sDeviceClassBuffer. psKernelSyncInfo); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: " "Failed sync info alloc"); goto ErrorExit; } eError = psBCInfo->psFuncTable->pfnGetBCBuffer( psBCInfo->hExtDevice, i, psBCInfo->psBuffer[i].sDeviceClassBuffer. psKernelSyncInfo-> psSyncData, &psBCInfo->psBuffer[i].sDeviceClassBuffer. hExtBuffer); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: " "Failed to get BC buffers"); goto ErrorExit; } psBCInfo->psBuffer[i].sDeviceClassBuffer. pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr; psBCInfo->psBuffer[i].sDeviceClassBuffer. hDevMemContext = psBCInfo->hDevMemContext; psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice; } } psBCPerContextInfo->psBCInfo = psBCInfo; psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_BUFFERCLASS_DEVICE, psBCPerContextInfo, 0, CloseBCDeviceCallBack); *phDeviceKM = (void *)psBCPerContextInfo; return PVRSRV_OK; ErrorExit: for (i = 0; i < psBCInfo->ui32BufferCount; i++) { if (psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) { PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i]. sDeviceClassBuffer. psKernelSyncInfo); } } if (psBCInfo->psBuffer) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_BC_BUFFER), psBCInfo->psBuffer, 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_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 PVRSRVOpenDCDeviceKM( struct PVRSRV_PER_PROCESS_DATA *psPerProc, u32 ui32DeviceID, void *hDevCookie, void **phDeviceKM) { struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo; struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo; struct PVRSRV_DEVICE_NODE *psDeviceNode; struct SYS_DATA *psSysData; if (!phDeviceKM || !hDevCookie) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: Invalid params"); return PVRSRV_ERROR_GENERIC; } if (SysAcquireData(&psSysData) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: Failed to get SysData"); return PVRSRV_ERROR_GENERIC; } psDeviceNode = psSysData->psDeviceNodeList; while (psDeviceNode) { if ((psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY) && (psDeviceNode->sDevId.ui32DeviceIndex == ui32DeviceID)) { psDCInfo = (struct PVRSRV_DISPLAYCLASS_INFO *) psDeviceNode->pvDevice; goto FoundDevice; } psDeviceNode = psDeviceNode->psNext; } PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID); return PVRSRV_ERROR_GENERIC; FoundDevice: if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psDCPerContextInfo), (void **)&psDCPerContextInfo, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: " "Failed psDCPerContextInfo alloc"); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo)); if (psDCInfo->ui32RefCount++ == 0) { enum PVRSRV_ERROR eError; struct PVRSRV_DC_SRV2DISP_KMJTABLE *jtbl; psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie; jtbl = psDCInfo->psFuncTable; if (!try_module_get(jtbl->owner)) { PVR_DPF(PVR_DBG_ERROR, "%s: can't get DC module"); return PVRSRV_ERROR_INVALID_DEVICE; } psDCInfo->hDevMemContext = (void *) psDeviceNode->sDevMemoryInfo.pBMKernelContext; eError = PVRSRVAllocSyncInfoKM(NULL, (void *)psDeviceNode-> sDevMemoryInfo.pBMKernelContext, &psDCInfo->sSystemBuffer. sDeviceClassBuffer. psKernelSyncInfo); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: Failed sync info alloc"); psDCInfo->ui32RefCount--; module_put(jtbl->owner); return eError; } eError = jtbl->pfnOpenDCDevice(ui32DeviceID, &psDCInfo->hExtDevice, (struct PVRSRV_SYNC_DATA *)psDCInfo->sSystemBuffer. sDeviceClassBuffer.psKernelSyncInfo-> psSyncDataMemInfoKM->pvLinAddrKM); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: " "Failed to open external DC device"); psDCInfo->ui32RefCount--; module_put(jtbl->owner); PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer. sDeviceClassBuffer.psKernelSyncInfo); return eError; } } psDCPerContextInfo->psDCInfo = psDCInfo; psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DISPLAYCLASS_DEVICE, psDCPerContextInfo, 0, CloseDCDeviceCallBack); *phDeviceKM = (void *) psDCPerContextInfo; return PVRSRV_OK; }
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 PVRSRVCreateDCSwapChainKM( struct PVRSRV_PER_PROCESS_DATA *psPerProc, void *hDeviceKM, u32 ui32Flags, struct DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib, struct DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib, u32 ui32BufferCount, u32 ui32OEMFlags, void **phSwapChain, u32 *pui32SwapChainID) { struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo; struct PVRSRV_DC_SWAPCHAIN *psSwapChain = NULL; struct PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS]; struct PVRSRV_QUEUE_INFO *psQueue = NULL; enum PVRSRV_ERROR eError; u32 i; if (!hDeviceKM || !psDstSurfAttrib || !psSrcSurfAttrib || !phSwapChain || !pui32SwapChainID) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: Invalid parameters"); return PVRSRV_ERROR_INVALID_PARAMS; } if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: Too many buffers"); return PVRSRV_ERROR_TOOMANYBUFFERS; } if (ui32BufferCount < 2) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: Too few buffers"); return PVRSRV_ERROR_TOO_FEW_BUFFERS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_DC_SWAPCHAIN), (void **) &psSwapChain, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc"); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExit; } OSMemSet(psSwapChain, 0, sizeof(struct PVRSRV_DC_SWAPCHAIN)); eError = PVRSRVCreateCommandQueueKM(1024, &psQueue); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue"); goto ErrorExit; } psSwapChain->psQueue = psQueue; for (i = 0; i < ui32BufferCount; i++) { eError = PVRSRVAllocSyncInfoKM(NULL, psDCInfo->hDevMemContext, &psSwapChain->asBuffer[i]. sDeviceClassBuffer. psKernelSyncInfo); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: " "Failed to alloc syninfo for psSwapChain"); goto ErrorExit; } psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr; psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext; psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice; psSwapChain->asBuffer[i].psDCInfo = psDCInfo; psSwapChain->asBuffer[i].psSwapChain = psSwapChain; apsSyncData[i] = (struct PVRSRV_SYNC_DATA *)psSwapChain->asBuffer[i]. sDeviceClassBuffer.psKernelSyncInfo-> psSyncDataMemInfoKM->pvLinAddrKM; } psSwapChain->ui32BufferCount = ui32BufferCount; psSwapChain->psDCInfo = psDCInfo; eError = psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice, ui32Flags, psDstSurfAttrib, psSrcSurfAttrib, ui32BufferCount, apsSyncData, ui32OEMFlags, &psSwapChain->hExtSwapChain, pui32SwapChainID); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: " "Failed to create 3rd party SwapChain"); goto ErrorExit; } *phSwapChain = (void *) psSwapChain; psSwapChain->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN, psSwapChain, 0, DestroyDCSwapChainCallBack); return eError; ErrorExit: for (i = 0; i < ui32BufferCount; i++) { if (psSwapChain->asBuffer[i].sDeviceClassBuffer. psKernelSyncInfo) { PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i]. sDeviceClassBuffer. psKernelSyncInfo); } } if (psQueue) PVRSRVDestroyCommandQueueKM(psQueue); if (psSwapChain) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_DC_SWAPCHAIN), psSwapChain, NULL); } return eError; }
IMG_EXPORT PVRSRV_ERROR SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_HANDLE hDevCookie, IMG_BOOL bLockOnFailure, IMG_UINT32 ui32TotalPBSize, IMG_HANDLE *phSharedPBDesc, PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo, PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo, PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo, PVRSRV_KERNEL_MEM_INFO **ppsHWBlockKernelMemInfo, PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos, IMG_UINT32 *ui32SharedPBDescSubKernelMemInfosCount) { PVRSRV_STUB_PBDESC *psStubPBDesc; PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos=IMG_NULL; PVRSRV_SGXDEV_INFO *psSGXDevInfo; PVRSRV_ERROR eError; psSGXDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice; psStubPBDesc = psSGXDevInfo->psStubPBDescListKM; if (psStubPBDesc != IMG_NULL) { IMG_UINT32 i; PRESMAN_ITEM psResItem; if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize) { PVR_DPF((PVR_DBG_WARNING, "SGXFindSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored", ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize)); } if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount, (IMG_VOID **)&ppsSharedPBDescSubKernelMemInfos, IMG_NULL, "Array of Kernel Memory Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: OSAllocMem failed")); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ExitNotFound; } psResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_PB_DESC, psStubPBDesc, 0, &SGXCleanupSharedPBDescCallback); if (psResItem == IMG_NULL) { OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount, ppsSharedPBDescSubKernelMemInfos, 0); PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed")); eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE; goto ExitNotFound; } *ppsSharedPBDescKernelMemInfo = psStubPBDesc->psSharedPBDescKernelMemInfo; *ppsHWPBDescKernelMemInfo = psStubPBDesc->psHWPBDescKernelMemInfo; *ppsBlockKernelMemInfo = psStubPBDesc->psBlockKernelMemInfo; *ppsHWBlockKernelMemInfo = psStubPBDesc->psHWBlockKernelMemInfo; *ui32SharedPBDescSubKernelMemInfosCount = psStubPBDesc->ui32SubKernelMemInfosCount; *pppsSharedPBDescSubKernelMemInfos = ppsSharedPBDescSubKernelMemInfos; for(i=0; i<psStubPBDesc->ui32SubKernelMemInfosCount; i++) { ppsSharedPBDescSubKernelMemInfos[i] = psStubPBDesc->ppsSubKernelMemInfos[i]; } psStubPBDesc->ui32RefCount++; *phSharedPBDesc = (IMG_HANDLE)psResItem; return PVRSRV_OK; } eError = PVRSRV_OK; if (bLockOnFailure) { if (psResItemCreateSharedPB == IMG_NULL) { psResItemCreateSharedPB = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, psPerProc, 0, &SGXCleanupSharedPBDescCreateLockCallback); if (psResItemCreateSharedPB == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed")); eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE; goto ExitNotFound; } PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL); psPerProcCreateSharedPB = psPerProc; } else { eError = PVRSRV_ERROR_PROCESSING_BLOCKED; } } ExitNotFound: *phSharedPBDesc = IMG_NULL; return eError; }
enum PVRSRV_ERROR SGXAddSharedPBDescKM( struct PVRSRV_PER_PROCESS_DATA *psPerProc, void *hDevCookie, struct PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo, struct PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo, struct PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo, u32 ui32TotalPBSize, void **phSharedPBDesc, struct PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos, u32 ui32SharedPBDescSubKernelMemInfosCount) { struct PVRSRV_STUB_PBDESC *psStubPBDesc = NULL; enum PVRSRV_ERROR eRet = PVRSRV_ERROR_GENERIC; u32 i; struct PVRSRV_SGXDEV_INFO *psSGXDevInfo; struct RESMAN_ITEM *psResItem; if (psPerProcCreateSharedPB != psPerProc) { goto NoAdd; } else { PVR_ASSERT(psResItemCreateSharedPB != NULL); ResManFreeResByPtr(psResItemCreateSharedPB); PVR_ASSERT(psResItemCreateSharedPB == NULL); PVR_ASSERT(psPerProcCreateSharedPB == NULL); } psSGXDevInfo = (struct PVRSRV_SGXDEV_INFO *) ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice; psStubPBDesc = psSGXDevInfo->psStubPBDescListKM; if (psStubPBDesc != NULL) { if (psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize) { PVR_DPF(PVR_DBG_WARNING, "SGXAddSharedPBDescKM: " "Shared PB requested with different size " "(0x%x) from existing shared PB (0x%x) - " "requested size ignored", ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize); } psResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_PB_DESC, psStubPBDesc, 0, &SGXCleanupSharedPBDescCallback); if (psResItem == NULL) { PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: " "Failed to register existing shared " "PBDesc with the resource manager"); goto NoAddKeepPB; } psStubPBDesc->ui32RefCount++; *phSharedPBDesc = (void *) psResItem; eRet = PVRSRV_OK; goto NoAddKeepPB; } if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(struct PVRSRV_STUB_PBDESC), (void **)&psStubPBDesc, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc " "StubPBDesc"); eRet = PVRSRV_ERROR_OUT_OF_MEMORY; goto NoAdd; } psStubPBDesc->ppsSubKernelMemInfos = NULL; if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(struct PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount, (void **)&psStubPBDesc->ppsSubKernelMemInfos, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: " "Failed to alloc " "StubPBDesc->ppsSubKernelMemInfos"); eRet = PVRSRV_ERROR_OUT_OF_MEMORY; goto NoAdd; } if (PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo) != PVRSRV_OK) goto NoAdd; if (PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo) != PVRSRV_OK) goto NoAdd; if (PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo) != PVRSRV_OK) goto NoAdd; psStubPBDesc->ui32RefCount = 1; psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize; psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo; psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo; psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo; psStubPBDesc->ui32SubKernelMemInfosCount = ui32SharedPBDescSubKernelMemInfosCount; for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++) { psStubPBDesc->ppsSubKernelMemInfos[i] = ppsSharedPBDescSubKernelMemInfos[i]; if (PVRSRVDissociateMemFromResmanKM (ppsSharedPBDescSubKernelMemInfos[i]) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: " "Failed to dissociate shared PBDesc " "from process"); goto NoAdd; } } psResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_PB_DESC, psStubPBDesc, 0, &SGXCleanupSharedPBDescCallback); if (psResItem == NULL) { PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: " "Failed to register shared PBDesc " " with the resource manager"); goto NoAdd; } psStubPBDesc->hDevCookie = hDevCookie; psStubPBDesc->psNext = psSGXDevInfo->psStubPBDescListKM; psSGXDevInfo->psStubPBDescListKM = psStubPBDesc; *phSharedPBDesc = (void *) psResItem; return PVRSRV_OK; NoAdd: if (psStubPBDesc) { if (psStubPBDesc->ppsSubKernelMemInfos) { OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(struct PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount, psStubPBDesc->ppsSubKernelMemInfos, NULL); } OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(struct PVRSRV_STUB_PBDESC), psStubPBDesc, NULL); } NoAddKeepPB: for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++) PVRSRVFreeDeviceMemKM(hDevCookie, ppsSharedPBDescSubKernelMemInfos[i]); PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo); PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo); PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo); return eRet; }