/*! ****************************************************************************** @Function PVRSRVAllocHandleBase @Description Allocate a handle base structure for a process @Input ppsBase - pointer to handle base structure pointer @Output ppsBase - points to handle base structure pointer @Return Error code or PVRSRV_OK ******************************************************************************/ PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase) { PVRSRV_HANDLE_BASE *psBase; PVRSRV_ERROR eError; if (gpsHandleFuncs == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Handle management not initialised")); return PVRSRV_ERROR_NOT_READY; } if (ppsBase == IMG_NULL) { eError = PVRSRV_ERROR_INVALID_PARAMS; goto err; } psBase = OSAllocZMem(sizeof(*psBase)); if (psBase == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't allocate handle base")); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto err; } eError = gpsHandleFuncs->pfnCreateHandleBase(&psBase->psImplBase); if (eError != PVRSRV_OK) { goto ErrorFreeHandleBase; } psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY), HASH_Func_Default, HASH_Key_Comp_Default); if (psBase->psHashTab == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't create data pointer hash table")); eError = PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE; goto ErrorDestroyHandleBase; } *ppsBase = psBase; return PVRSRV_OK; ErrorDestroyHandleBase: (IMG_VOID)gpsHandleFuncs->pfnDestroyHandleBase(psBase->psImplBase); ErrorFreeHandleBase: OSFreeMem(psBase); err: return eError; }
/* * Make functions */ PTL_STREAM_DESC TLMakeStreamDesc(PTL_SNODE f1, IMG_UINT32 f2, IMG_HANDLE f3) { PTL_STREAM_DESC ps = OSAllocZMem(sizeof(TL_STREAM_DESC)); if (ps == IMG_NULL) { return IMG_NULL; } ps->psNode = f1; ps->ui32Flags = f2; ps->hDataEvent = f3; return ps; }
PTL_SNODE TLMakeSNode(IMG_HANDLE f2, TL_STREAM *f3, TL_STREAM_DESC *f4) { PTL_SNODE ps = OSAllocZMem(sizeof(TL_SNODE)); if (ps == IMG_NULL) { return IMG_NULL; } ps->hDataEventObj = f2; ps->psStream = f3; ps->psRDesc = f4; f3->psNode = ps; return ps; }
PVRSRV_ERROR SysCreateConfigData(PVRSRV_SYSTEM_CONFIG **ppsSysConfig, void *hDevice) { PLAT_DATA *psPlatData; PVRSRV_ERROR eError; PVR_UNREFERENCED_PARAMETER(hDevice); psPlatData = OSAllocZMem(sizeof(*psPlatData)); /* Query the Emu for reg and IRQ information */ eError = PCIInitDev(psPlatData); if (eError != PVRSRV_OK) { goto e0; } /* Save data for this device */ sSysConfig.pasDevices[0].hSysData = (IMG_HANDLE) psPlatData; /* Save private data for the physical memory heap */ gsPhysHeapConfig[0].hPrivData = (IMG_HANDLE) psPlatData; #if defined(TDMETACODE) #error "Not supported services/3rdparty/intel_drm/sysconfig.c" gsPhysHeapConfig[1].hPrivData = IMG_NULL; #endif *ppsSysConfig = &sSysConfig; gpsPlatData = psPlatData; /* Setup other system specific stuff */ #if defined(SUPPORT_ION) IonInit(NULL); #endif return PVRSRV_OK; e0: return eError; }
/*! ****************************************************************************** @Function CreateHandleBase @Description Create a handle base structure @Input ppsBase - pointer to handle base structure pointer @Output ppsBase - points to handle base structure pointer @Return Error code or PVRSRV_OK ******************************************************************************/ static PVRSRV_ERROR CreateHandleBase(HANDLE_IMPL_BASE **ppsBase) { HANDLE_IMPL_BASE *psBase; PVR_ASSERT(ppsBase); psBase = OSAllocZMem(sizeof(*psBase)); if (psBase == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't allocate generic handle base", __FUNCTION__)); return PVRSRV_ERROR_OUT_OF_MEMORY; } psBase->psHandleBlockArray = IMG_NULL; psBase->ui32MaxHandleValue = HANDLE_VALUE_MAX; psBase->bPurgingEnabled = IMG_FALSE; *ppsBase = psBase; return PVRSRV_OK; }
/*! ****************************************************************************** @Function AllocHandle @Description Allocate a new handle @Input phHandle - location for new handle pvData - pointer to resource to be associated with the handle eType - the type of resource hParent - parent handle or IMG_NULL @Output phHandle - points to new handle @Return Error code or PVRSRV_OK ******************************************************************************/ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent) { HANDLE_DATA *psNewHandleData; IMG_HANDLE hHandle; PVRSRV_ERROR eError; /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); PVR_ASSERT(psBase != IMG_NULL && psBase->psHashTab != IMG_NULL); PVR_ASSERT(gpsHandleFuncs); if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) { /* Handle must not already exist */ PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL); } psNewHandleData = OSAllocZMem(sizeof(*psNewHandleData)); if (psNewHandleData == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't allocate handle data")); return PVRSRV_ERROR_OUT_OF_MEMORY; } eError = gpsHandleFuncs->pfnAcquireHandle(psBase->psImplBase, &hHandle, psNewHandleData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Failed to acquire a handle")); goto ErrorFreeHandleData; } /* * If a data pointer can be associated with multiple handles, we * don't put the handle in the hash table, as the data pointer * may not map to a unique handle */ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) { HAND_KEY aKey; /* Initialise hash key */ InitKey(aKey, psBase, pvData, eType, hParent); /* Put the new handle in the hash table */ if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle)) { PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table")); eError = PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE; goto ErrorReleaseHandle; } } psNewHandleData->hHandle = hHandle; psNewHandleData->eType = eType; psNewHandleData->eFlag = eFlag; psNewHandleData->pvData = pvData; psNewHandleData->ui32Refs = 1; InitParentList(psNewHandleData); #if defined(DEBUG) PVR_ASSERT(NoChildren(psNewHandleData)); #endif InitChildEntry(psNewHandleData); #if defined(DEBUG) PVR_ASSERT(NoParent(psNewHandleData)); #endif /* Return the new handle to the client */ *phHandle = psNewHandleData->hHandle; return PVRSRV_OK; ErrorReleaseHandle: (IMG_VOID)gpsHandleFuncs->pfnReleaseHandle(psBase->psImplBase, hHandle, IMG_NULL); ErrorFreeHandleData: OSFreeMem(psNewHandleData); return eError; }
IMG_INTERNAL PVRSRV_ERROR TLClientOpenStream(IMG_HANDLE hSrvHandle, IMG_PCHAR pszName, IMG_UINT32 ui32Mode, IMG_HANDLE* phSD) { PVRSRV_ERROR eError = PVRSRV_OK; TL_STREAM_DESC* psSD = 0; DEVMEM_SERVER_EXPORTCOOKIE hServerExportCookie; PVR_ASSERT(hSrvHandle); PVR_ASSERT(pszName); PVR_ASSERT(phSD); *phSD = NULL; /* Allocate memory for the stream descriptor object, initialise with * "no data read" yet. */ psSD = OSAllocZMem(sizeof(TL_STREAM_DESC)); if (psSD == NULL) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; PVR_DPF((PVR_DBG_ERROR, "BridgeTLOpenStream: KM returned %d", eError)); goto e0; } psSD->uiReadLen = psSD->uiReadOffset = NO_ACQUIRE; /* Send open stream request to kernel server to get stream handle and * buffer cookie so we can get access to the buffer in this process. */ eError = BridgeTLOpenStream(hSrvHandle, pszName, ui32Mode, &psSD->hServerSD, &hServerExportCookie); if (eError != PVRSRV_OK) { if ((ui32Mode & PVRSRV_STREAM_FLAG_OPEN_WAIT) && (eError == PVRSRV_ERROR_TIMEOUT)) { goto e1; } PVR_LOGG_IF_ERROR(eError, "BridgeTLOpenStream", e1); } /* Convert server export cookie into a cookie for use by this client */ eError = DevmemMakeServerExportClientExport(hSrvHandle, hServerExportCookie, &psSD->sExportCookie); PVR_LOGG_IF_ERROR(eError, "DevmemMakeServerExportClientExport", e2); /* Now convert client cookie into a client handle on the buffer's * physical memory region */ eError = DevmemImport(hSrvHandle, &psSD->sExportCookie, PVRSRV_MEMALLOCFLAG_CPU_READABLE, "TLClientCookie", &psSD->psUMmemDesc); PVR_LOGG_IF_ERROR(eError, "DevmemImport", e3); /* Now map the memory into the virtual address space of this process. */ eError = DevmemAcquireCpuVirtAddr(psSD->psUMmemDesc, (IMG_PVOID *) &psSD->pBaseAddr); PVR_LOGG_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", e4); /* Return client descriptor handle to caller */ *phSD = psSD; return PVRSRV_OK; /* Clean up post buffer setup */ e4: DevmemFree(psSD->psUMmemDesc); e3: (void) DevmemUnmakeServerExportClientExport(hSrvHandle, &psSD->sExportCookie); /* Clean up post stream open */ e2: BridgeTLCloseStream(hSrvHandle, psSD->hServerSD); /* Cleanup post allocation of the descriptor object */ e1: OSFreeMem(psSD); e0: return eError; }
/******************************************************************************* * TL Server public API implementation. ******************************************************************************/ PVRSRV_ERROR TLStreamCreate(IMG_HANDLE *phStream, IMG_CHAR *szStreamName, IMG_UINT32 ui32Size, IMG_UINT32 ui32StreamFlags, TL_STREAM_SOURCECB pfProducerCB, IMG_PVOID pvProducerUD) { PTL_STREAM psTmp; PVRSRV_ERROR eError; IMG_HANDLE hEventList; PTL_SNODE psn = 0; IMG_CHAR pszBufferLabel[PRVSRVTL_MAX_STREAM_NAME_SIZE+20]; DEVMEM_FLAGS_T uiMemFlags = PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_GPU_READABLE | PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_UNCACHED | /* GPU & CPU */ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE; PVR_DPF_ENTERED; /* Sanity checks: */ /* non NULL handler required */ if ( NULL == phStream ) { PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS); } if (OSStringLength(szStreamName) >= PRVSRVTL_MAX_STREAM_NAME_SIZE) { PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS); } /* Check if there already exists a stream with this name. */ psn = TLFindStreamNodeByName( szStreamName ); if ( IMG_NULL != psn ) { PVR_DPF_RETURN_RC(PVRSRV_ERROR_ALREADY_EXISTS); } /* Allocate stream structure container (stream struct) for the new stream */ psTmp = OSAllocZMem(sizeof(TL_STREAM)) ; if ( NULL == psTmp ) { PVR_DPF_RETURN_RC(PVRSRV_ERROR_OUT_OF_MEMORY); } OSStringCopy(psTmp->szName, szStreamName); if ( ui32StreamFlags & TL_FLAG_FORCE_FLUSH ) { psTmp->bWaitForEmptyOnDestroy = IMG_TRUE; } psTmp->bNoSignalOnCommit = (ui32StreamFlags&TL_FLAG_NO_SIGNAL_ON_COMMIT) ? IMG_TRUE : IMG_FALSE; if ( ui32StreamFlags & TL_FLAG_DROP_DATA ) { if ( ui32StreamFlags & TL_FLAG_BLOCKING_RESERVE ) { eError = PVRSRV_ERROR_INVALID_PARAMS; goto e0; } psTmp->bDrop = IMG_TRUE; } else if ( ui32StreamFlags & TL_FLAG_BLOCKING_RESERVE ) { /* Additional synchronization object required for this kind of stream */ psTmp->bBlock = IMG_TRUE; eError = OSEventObjectCreate(NULL, &psTmp->hProducerEventObj); if (eError != PVRSRV_OK) { goto e0; } /* Create an event handle for this kind of stream */ eError = OSEventObjectOpen(psTmp->hProducerEventObj, &psTmp->hProducerEvent); if (eError != PVRSRV_OK) { goto e1; } } /* Remember producer supplied CB and data for later */ psTmp->pfProducerCallback = (IMG_VOID(*)(IMG_VOID))pfProducerCB; psTmp->pvProducerUserData = pvProducerUD; /* Round the requested bytes to a multiple of array elements' size, eg round 3 to 4 */ psTmp->ui32Size = PVRSRVTL_ALIGN(ui32Size); psTmp->ui32Read = 0; psTmp->ui32Write = 0; psTmp->ui32Pending = NOTHING_PENDING; OSSNPrintf(pszBufferLabel, sizeof(pszBufferLabel), "TLStreamBuf-%s", szStreamName); /* Allocate memory for the circular buffer and export it to user space. */ eError = DevmemAllocateExportable( IMG_NULL, (IMG_HANDLE) TLGetGlobalRgxDevice(), (IMG_DEVMEM_SIZE_T)psTmp->ui32Size, (IMG_DEVMEM_ALIGN_T) OSGetPageSize(), uiMemFlags | PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE, pszBufferLabel, &psTmp->psStreamMemDesc); PVR_LOGG_IF_ERROR(eError, "DevmemAllocateExportable", e2); eError = DevmemAcquireCpuVirtAddr( psTmp->psStreamMemDesc, (IMG_VOID**) &psTmp->pbyBuffer ); PVR_LOGG_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", e3); eError = DevmemExport(psTmp->psStreamMemDesc, &(psTmp->sExportCookie)); PVR_LOGG_IF_ERROR(eError, "DevmemExport", e4); /* Synchronization object to synchronize with user side data transfers. */ eError = OSEventObjectCreate(psTmp->szName, &hEventList); if (eError != PVRSRV_OK) { goto e5; } /* Stream created, now reset the reference count to 1 */ psTmp->uiRefCount = 1; //Thread Safety: Not yet implemented eError = OSLockCreate(&psTmp->hLock, LOCK_TYPE_PASSIVE); //Thread Safety: Not yet implemented if (eError != PVRSRV_OK) //Thread Safety: Not yet implemented { //Thread Safety: Not yet implemented goto e6; //Thread Safety: Not yet implemented } /* Now remember the stream in the global TL structures */ psn = TLMakeSNode(hEventList, (TL_STREAM *)psTmp, 0); if (psn == NULL) { eError=PVRSRV_ERROR_OUT_OF_MEMORY; goto e7; } TLAddStreamNode(psn); /* Best effort signal, client wait timeout will ultimately let it find the * new stream if this fails, acceptable to avoid cleanup as it is tricky * at this point */ (void) OSEventObjectSignal(TLGGD()->hTLEventObj); /* Pass the newly created stream handle back to caller */ *phStream = (IMG_HANDLE)psTmp; PVR_DPF_RETURN_OK; e7: //Thread Safety: Not yet implemented OSLockDestroy(psTmp->hLock); //Thread Safety: Not yet implemented e6: OSEventObjectDestroy(hEventList); e5: DevmemUnexport(psTmp->psStreamMemDesc, &(psTmp->sExportCookie)); e4: DevmemReleaseCpuVirtAddr( psTmp->psStreamMemDesc ); e3: DevmemFree(psTmp->psStreamMemDesc); e2: OSEventObjectClose(psTmp->hProducerEvent); e1: OSEventObjectDestroy(psTmp->hProducerEventObj); e0: OSFREEMEM(psTmp); PVR_DPF_RETURN_RC(eError); }