/*! ****************************************************************************** @Function PVRSRVMISR @Input pvSysData @Description OS-independent Medium-level Interrupt Service Routine ******************************************************************************/ IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData) { SYS_DATA *psSysData = pvSysData; /* PVRSRV_DEVICE_NODE *psDeviceNode; */ if(!psSysData) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n")); return; } /* Traverse the devices' MISR handlers. */ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, &PVRSRVMISR_ForEachCb); #if defined(SUPPORT_PVRSRV_DEVICE_CLASS) /* Process the queues. */ if (PVRSRVProcessQueues(IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED) { PVRSRVProcessQueues(IMG_FALSE); } #endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */ /* signal global event object */ if (psSysData->psGlobalEventObject) { IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM; if(hOSEventKM) { OSEventObjectSignalKM(hOSEventKM); } } }
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(IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED) { PVRSRVProcessQueues(IMG_FALSE); } if (psSysData->psGlobalEventObject) { IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM; if(hOSEventKM) { OSEventObjectSignalKM(hOSEventKM); } } }
void PVRSRVMISR(void *pvSysData) { struct SYS_DATA *psSysData = pvSysData; struct PVRSRV_DEVICE_NODE *psDeviceNode; if (!psSysData) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n"); return; } psDeviceNode = psSysData->psDeviceNodeList; while (psDeviceNode != NULL) { if (psDeviceNode->pfnDeviceMISR != NULL) (*psDeviceNode->pfnDeviceMISR)(psDeviceNode-> pvISRData); psDeviceNode = psDeviceNode->psNext; } if (PVRSRVProcessQueues(ISR_ID, IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED) PVRSRVProcessQueues(ISR_ID, IMG_FALSE); if (psSysData->psGlobalEventObject) { void *hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM; if (hOSEventKM) OSEventObjectSignal(hOSEventKM); } }
enum PVRSRV_ERROR PVRSRVSwapToDCBufferKM(void *hDeviceKM, void *hBuffer, u32 ui32SwapInterval, void *hPrivateTag, u32 ui32ClipRectCount, struct IMG_RECT *psClipRect) { enum PVRSRV_ERROR eError; struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo; struct PVRSRV_DC_BUFFER *psBuffer; struct PVRSRV_QUEUE_INFO *psQueue; struct DISPLAYCLASS_FLIP_COMMAND *psFlipCmd; u32 i; u32 ui32NumSrcSyncs = 1; struct PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2]; struct PVRSRV_COMMAND *psCommand; if (!hDeviceKM || !hBuffer || !psClipRect) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVSwapToDCBufferKM: Invalid parameters"); return PVRSRV_ERROR_INVALID_PARAMS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); psBuffer = (struct PVRSRV_DC_BUFFER *)hBuffer; psQueue = psBuffer->psSwapChain->psQueue; apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo; if (psBuffer->psSwapChain->psLastFlipBuffer && psBuffer != psBuffer->psSwapChain->psLastFlipBuffer) { apsSrcSync[1] = psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer. psKernelSyncInfo; ui32NumSrcSyncs++; } eError = PVRSRVInsertCommandKM(psQueue, &psCommand, psDCInfo->ui32DeviceID, DC_FLIP_COMMAND, 0, NULL, ui32NumSrcSyncs, apsSrcSync, sizeof(struct DISPLAYCLASS_FLIP_COMMAND) + (sizeof(struct IMG_RECT) * ui32ClipRectCount)); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVSwapToDCBufferKM: Failed to get space in queue"); goto Exit; } psFlipCmd = (struct DISPLAYCLASS_FLIP_COMMAND *)psCommand->pvData; psFlipCmd->hExtDevice = psDCInfo->hExtDevice; psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain; psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer; psFlipCmd->hPrivateTag = hPrivateTag; psFlipCmd->ui32ClipRectCount = ui32ClipRectCount; psFlipCmd->psClipRect = (struct IMG_RECT *)((u8 *) psFlipCmd + sizeof(struct DISPLAYCLASS_FLIP_COMMAND)); for (i = 0; i < ui32ClipRectCount; i++) psFlipCmd->psClipRect[i] = psClipRect[i]; psFlipCmd->ui32SwapInterval = ui32SwapInterval; eError = PVRSRVSubmitCommandKM(psQueue, psCommand); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVSwapToDCBufferKM: Failed to submit command"); goto Exit; } LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) { if (PVRSRVProcessQueues(IMG_FALSE) != PVRSRV_ERROR_PROCESSING_BLOCKED) { goto ProcessedQueues; } OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT); } END_LOOP_UNTIL_TIMEOUT(); PVR_DPF(PVR_DBG_ERROR, "PVRSRVSwapToDCBufferKM: Failed to process queues"); eError = PVRSRV_ERROR_GENERIC; goto Exit; ProcessedQueues: psBuffer->psSwapChain->psLastFlipBuffer = psBuffer; Exit: return eError; }
enum PVRSRV_ERROR PVRSRVSwapToDCSystemKM(void *hDeviceKM, void *hSwapChain) { enum PVRSRV_ERROR eError; struct PVRSRV_QUEUE_INFO *psQueue; struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo; struct PVRSRV_DC_SWAPCHAIN *psSwapChain; struct DISPLAYCLASS_FLIP_COMMAND *psFlipCmd; IMG_BOOL bStart = IMG_FALSE; u32 uiStart = 0; u32 ui32NumSrcSyncs = 1; struct PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2]; struct PVRSRV_COMMAND *psCommand; if (!hDeviceKM || !hSwapChain) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVSwapToDCSystemKM: Invalid parameters"); return PVRSRV_ERROR_INVALID_PARAMS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain; psQueue = psSwapChain->psQueue; apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo; if (psSwapChain->psLastFlipBuffer) { apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer. psKernelSyncInfo; ui32NumSrcSyncs++; } eError = PVRSRVInsertCommandKM(psQueue, &psCommand, psDCInfo->ui32DeviceID, DC_FLIP_COMMAND, 0, NULL, ui32NumSrcSyncs, apsSrcSync, sizeof(struct DISPLAYCLASS_FLIP_COMMAND)); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVSwapToDCSystemKM: " "Failed to get space in queue"); goto Exit; } psFlipCmd = (struct DISPLAYCLASS_FLIP_COMMAND *)psCommand->pvData; psFlipCmd->hExtDevice = psDCInfo->hExtDevice; psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain; psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer; psFlipCmd->hPrivateTag = NULL; psFlipCmd->ui32ClipRectCount = 0; psFlipCmd->ui32SwapInterval = 1; eError = PVRSRVSubmitCommandKM(psQueue, psCommand); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVSwapToDCSystemKM: Failed to submit command"); goto Exit; } do { if (PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) != PVRSRV_ERROR_PROCESSING_BLOCKED) goto ProcessedQueues; if (bStart == IMG_FALSE) { uiStart = OSClockus(); bStart = IMG_TRUE; } OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT); } while ((OSClockus() - uiStart) < MAX_HW_TIME_US); PVR_DPF(PVR_DBG_ERROR, "PVRSRVSwapToDCSystemKM: Failed to process queues"); eError = PVRSRV_ERROR_GENERIC; goto Exit; ProcessedQueues: psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer; eError = PVRSRV_OK; Exit: return eError; }
/*! ****************************************************************************** @Function PVRSRVGetMiscInfoKM @Description Retrieves misc. info. @Output PVRSRV_MISC_INFO @Return PVRSRV_ERROR : ******************************************************************************/ IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo) { SYS_DATA *psSysData; if(!psMiscInfo) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psMiscInfo->ui32StatePresent = 0; /* do a basic check for uninitialised request flag */ if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT |PVRSRV_MISC_INFO_MEMSTATS_PRESENT |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT |PVRSRV_MISC_INFO_DDKVERSION_PRESENT |PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT |PVRSRV_MISC_INFO_RESET_PRESENT |PVRSRV_MISC_INFO_FREEMEM_PRESENT |PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT |PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT |PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT)) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags")); return PVRSRV_ERROR_INVALID_PARAMS; } SysAcquireData(&psSysData); /* return SOC Timer registers */ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) && (psSysData->pvSOCTimerRegisterKM != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT; psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM; psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle; } else { psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL; psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL; } /* return SOC Clock Gating registers */ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) && (psSysData->pvSOCClockGateRegsBase != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT; psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase; psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize; } /* memory stats */ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { RA_ARENA **ppArena; /* BM_HEAP *psBMHeap; BM_CONTEXT *psBMContext; PVRSRV_DEVICE_NODE *psDeviceNode;*/ IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT; /* Local backing stores */ ppArena = &psSysData->apsLocalDevMemArena[0]; while(*ppArena) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); RA_GetStats(*ppArena, &pszStr, &ui32StrLen); /* advance through the array */ ppArena++; } /* per device */ /* psDeviceNode = psSysData->psDeviceNodeList;*/ /*triple loop; devices:contexts:heaps*/ List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, &PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr, PVRSRV_MISC_INFO_MEMSTATS_PRESENT); /* attach a new line and string terminate */ i32Count = OSSNPrintf(pszStr, 100, "\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } /* Lean version of mem stats: only show free mem on each RA */ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0) && psMiscInfo->pszMemoryStr) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT; /* triple loop over devices:contexts:heaps */ List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, &PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr, PVRSRV_MISC_INFO_FREEMEM_PRESENT); i32Count = OSSNPrintf(pszStr, 100, "\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) && (psSysData->psGlobalEventObject != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT; psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject; } /* DDK version and memstats not supported in same call to GetMiscInfo */ if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL) && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_UINT32 ui32LenStrPerNum = 12; /* string length per UI32: 10 digits + '.' + '\0' = 12 bytes */ IMG_INT32 i32Count; IMG_INT i; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT; /* construct DDK string */ psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ; psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN; psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BUILD_HI; psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD_LO; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; for (i=0; i<4; i++) { if (ui32StrLen < ui32LenStrPerNum) { return PVRSRV_ERROR_INVALID_PARAMS; } i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); if (i != 3) { i32Count = OSSNPrintf(pszStr, 2, "."); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } } } if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT; if(psMiscInfo->sCacheOpCtl.bDeferOp) { /* For now, assume deferred ops are "full" cache ops, * and we don't need (or expect) a meminfo. */ psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType; } else { PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; PVRSRV_PER_PROCESS_DATA *psPerProc; if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " "Ignoring non-deferred cache op with no meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " "Deferred cache op is pending. It is unlikely you want " "to combine deferred cache ops with immediate ones")); } psPerProc = PVRSRVFindPerProcessData(); if(PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo, psMiscInfo->sCacheOpCtl.u.psKernelMemInfo, PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: " "Can't find kernel meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) { if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, 0, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) { return PVRSRV_ERROR_CACHEOP_FAILED; } } else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) { if(psMiscInfo->sCacheOpCtl.ui32Length!=0) { if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, 0, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) { return PVRSRV_ERROR_CACHEOP_FAILED; } } } } } if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT) != 0UL) { PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; PVRSRV_PER_PROCESS_DATA *psPerProc; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT; psPerProc = PVRSRVFindPerProcessData(); if(PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo, psMiscInfo->sGetRefCountCtl.u.psKernelMemInfo, PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: " "Can't find kernel meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } psMiscInfo->sGetRefCountCtl.ui32RefCount = psKernelMemInfo->ui32RefCount; } if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT) != 0UL) { psMiscInfo->ui32PageSize = HOST_PAGESIZE(); psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT; } #if defined(PVRSRV_RESET_ON_HWTIMEOUT) if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL) { PVR_LOG(("User requested OS reset")); OSPanic(); } #endif /* #if defined(PVRSRV_RESET_ON_HWTIMEOUT) */ #if defined(SUPPORT_PVRSRV_DEVICE_CLASS) if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT) != 0UL) { PVRSRVProcessQueues(IMG_TRUE); psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT; } #endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */ return PVRSRV_OK; }
IMG_EXPORT PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM, IMG_HANDLE hSwapChain) { PVRSRV_ERROR eError; PVRSRV_QUEUE_INFO *psQueue; PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DC_SWAPCHAIN *psSwapChain; DISPLAYCLASS_FLIP_COMMAND *psFlipCmd; IMG_UINT32 ui32NumSrcSyncs = 1; PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2]; PVRSRV_COMMAND *psCommand; if(!hDeviceKM || !hSwapChain) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } #if defined(SUPPORT_LMA) eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE); if(eError != PVRSRV_OK) { return eError; } #endif psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); psSwapChain = (PVRSRV_DC_SWAPCHAIN*)hSwapChain; psQueue = psSwapChain->psQueue; apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo; if(psSwapChain->psLastFlipBuffer) { if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo) { apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo; ui32NumSrcSyncs++; } } eError = PVRSRVInsertCommandKM (psQueue, &psCommand, psDCInfo->ui32DeviceID, DC_FLIP_COMMAND, 0, IMG_NULL, ui32NumSrcSyncs, apsSrcSync, sizeof(DISPLAYCLASS_FLIP_COMMAND)); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue")); goto Exit; } psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData; psFlipCmd->hExtDevice = psDCInfo->hExtDevice; psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain; psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer; psFlipCmd->hPrivateTag = IMG_NULL; psFlipCmd->ui32ClipRectCount = 0; psFlipCmd->ui32SwapInterval = 1; eError = PVRSRVSubmitCommandKM (psQueue, psCommand); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to submit command")); goto Exit; } LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) { if(PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) != PVRSRV_ERROR_PROCESSING_BLOCKED) { goto ProcessedQueues; } OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT); } END_LOOP_UNTIL_TIMEOUT(); PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to process queues")); eError = PVRSRV_ERROR_GENERIC; goto Exit; ProcessedQueues: psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer; eError = PVRSRV_OK; Exit: #if defined(SUPPORT_LMA) PVRSRVPowerUnlock(KERNEL_ID); #endif return eError; }