IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData) { SYS_DATA *psSysData = pvSysData; if(!psSysData) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n")); return; } List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, &PVRSRVMISR_ForEachCb); if (PVRSRVProcessQueues(ISR_ID, IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED) { PVRSRVProcessQueues(ISR_ID, IMG_FALSE); } if (psSysData->psGlobalEventObject) { IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM; if(hOSEventKM) { OSEventObjectSignal(hOSEventKM); } } }
PVRSRV_ERROR TLStreamSync(IMG_HANDLE psStream) { PVRSRV_ERROR eError = PVRSRV_OK; PTL_STREAM psTmp; PVR_DPF_ENTERED; if ( IMG_NULL == psStream ) { PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS); } psTmp = (PTL_STREAM)psStream; /* Signal clients only when data is available to read */ if (psTmp->ui32Read != psTmp->ui32Write) { eError = OSEventObjectSignal(psTmp->psNode->hDataEventObj); } PVR_DPF_RETURN_RC(eError); }
/*! ****************************************************************************** @Function PVRSRVSetDevicePowerStateKM @Description Set the Device into a new state @Input ui32DeviceIndex : device index @Input eNewPowerState : New power state @Input bForced : TRUE if the transition should not fail (e.g. OS request) @Return PVRSRV_ERROR ******************************************************************************/ IMG_EXPORT PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex, PVRSRV_DEV_POWER_STATE eNewPowerState, IMG_BOOL bForced) { PVRSRV_DATA* psPVRSRVData = PVRSRVGetPVRSRVData(); PVRSRV_ERROR eError; PVRSRV_DEV_POWER_STATE eOldPowerState; eError = PVRSRVGetDevicePowerState(ui32DeviceIndex, &eOldPowerState); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVSetDevicePowerStateKM: Couldn't read power state.")); eOldPowerState = PVRSRV_DEV_POWER_STATE_DEFAULT; } #if defined(PDUMP) if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) { /* Pdump a power-up regardless of the default state. Then disable pdump and transition to the default power state. This ensures that a power-up is always present in the pdump when necessary. */ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON, bForced); if(eError != PVRSRV_OK) { goto Exit; } eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON, bForced); if (eError != PVRSRV_OK) { goto Exit; } PDUMPPOWCMDSTART(); } #endif /* PDUMP */ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState, bForced); if(eError != PVRSRV_OK) { if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) { PDUMPPOWCMDEND(); } goto Exit; } eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState, bForced); if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) { PDUMPPOWCMDEND(); } /* Signal Device Watchdog Thread about power mode change. */ if (eOldPowerState != eNewPowerState && eNewPowerState == PVRSRV_DEV_POWER_STATE_ON) { psPVRSRVData->ui32DevicesWatchdogPwrTrans++; if (psPVRSRVData->ui32DevicesWatchdogTimeout == DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT) { if (psPVRSRVData->hDevicesWatchdogEvObj) { eError = OSEventObjectSignal(psPVRSRVData->hDevicesWatchdogEvObj); PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal"); } } } Exit: if (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED) { PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSetDevicePowerStateKM : Transition to %d was denied, Forced=%d", eNewPowerState, bForced)); } else if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVSetDevicePowerStateKM : Transition to %d FAILED (%s)", eNewPowerState, PVRSRVGetErrorStringKM(eError))); } return eError; }
PVRSRV_ERROR TLStreamCommit(IMG_HANDLE hStream, IMG_UINT32 ui32ReqSize) { PTL_STREAM psTmp; IMG_UINT32 ui32LRead, ui32OldWrite, ui32LWrite, ui32LPending; PVRSRV_ERROR eError; PVR_DPF_ENTERED; if ( IMG_NULL == hStream ) { PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS); } psTmp = (PTL_STREAM)hStream; /* Get a local copy of the stream buffer parameters */ ui32LRead = psTmp->ui32Read ; ui32LWrite = psTmp->ui32Write ; ui32LPending = psTmp->ui32Pending ; ui32OldWrite = ui32LWrite; // Space in buffer is aligned ui32ReqSize = PVRSRVTL_ALIGN(ui32ReqSize); /* Sanity check. ReqSize + packet header size. */ if ( ui32LPending != ui32ReqSize + sizeof(PVRSRVTL_PACKETHDR) ) { PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_MISUSE); } /* Update pointer to written data. */ ui32LWrite = (ui32LWrite + ui32LPending) % psTmp->ui32Size; /* and reset LPending to 0 since data are now submitted */ ui32LPending = NOTHING_PENDING; /* If we have transitioned from an empty buffer to a non-empty buffer, * signal any consumers that may be waiting. */ if (ui32OldWrite == ui32LRead && !psTmp->bNoSignalOnCommit) { /* Signal consumers that may be waiting */ eError = OSEventObjectSignal(psTmp->psNode->hDataEventObj); if ( eError != PVRSRV_OK) { PVR_DPF_RETURN_RC(eError); } } /* Calculate high water mark for debug purposes */ #if defined(TL_BUFFER_UTILIZATION) { IMG_UINT32 tmp = 0; if (ui32LWrite > ui32LRead) { tmp = (ui32LWrite-ui32LRead); } else if (ui32LWrite < ui32LRead) { tmp = (psTmp->ui32Size-ui32LRead+ui32LWrite); } /* else equal, ignore */ if (tmp > psTmp->ui32BufferUt) { psTmp->ui32BufferUt = tmp; } } #endif /* Update stream buffer parameters to match local copies */ psTmp->ui32Write = ui32LWrite ; psTmp->ui32Pending = ui32LPending ; PVR_DPF_RETURN_OK; }
/******************************************************************************* * 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); }