| /********************************************************************** |
| * |
| * Copyright (C) Imagination Technologies Ltd. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms and conditions of the GNU General Public License, |
| * version 2, as published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope it will be useful but, except |
| * as otherwise stated in writing, without any warranty; without even the |
| * implied warranty of merchantability or fitness for a particular purpose. |
| * See the GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License along with |
| * this program; if not, write to the Free Software Foundation, Inc., |
| * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * The full GNU General Public License is included in this distribution in |
| * the file called "COPYING". |
| * |
| * Contact Information: |
| * Imagination Technologies Ltd. <gpl-support@imgtec.com> |
| * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK |
| * |
| ******************************************************************************/ |
| |
| #include "services_headers.h" |
| #include "buffer_manager.h" |
| #include "pvr_bridge_km.h" |
| #include "handle.h" |
| #include "perproc.h" |
| #include "pdump_km.h" |
| #include "deviceid.h" |
| #include "ra.h" |
| #if defined(TTRACE) |
| #include "ttrace.h" |
| #endif |
| #include "perfkm.h" |
| |
| #include "pvrversion.h" |
| |
| #include "lists.h" |
| |
| IMG_UINT32 g_ui32InitFlags; |
| |
| #define INIT_DATA_ENABLE_PDUMPINIT 0x1U |
| #define INIT_DATA_ENABLE_TTARCE 0x2U |
| |
| PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID) |
| { |
| SYS_DEVICE_ID* psDeviceWalker; |
| SYS_DEVICE_ID* psDeviceEnd; |
| |
| psDeviceWalker = &psSysData->sDeviceID[0]; |
| psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices; |
| |
| |
| while (psDeviceWalker < psDeviceEnd) |
| { |
| if (!psDeviceWalker->bInUse) |
| { |
| psDeviceWalker->bInUse = IMG_TRUE; |
| *pui32DevID = psDeviceWalker->uiID; |
| return PVRSRV_OK; |
| } |
| psDeviceWalker++; |
| } |
| |
| PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!")); |
| |
| |
| PVR_ASSERT(psDeviceWalker < psDeviceEnd); |
| |
| return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE; |
| } |
| |
| |
| PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID) |
| { |
| SYS_DEVICE_ID* psDeviceWalker; |
| SYS_DEVICE_ID* psDeviceEnd; |
| |
| psDeviceWalker = &psSysData->sDeviceID[0]; |
| psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices; |
| |
| |
| while (psDeviceWalker < psDeviceEnd) |
| { |
| |
| if ( |
| (psDeviceWalker->uiID == ui32DevID) && |
| (psDeviceWalker->bInUse) |
| ) |
| { |
| psDeviceWalker->bInUse = IMG_FALSE; |
| return PVRSRV_OK; |
| } |
| psDeviceWalker++; |
| } |
| |
| PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!")); |
| |
| |
| PVR_ASSERT(psDeviceWalker < psDeviceEnd); |
| |
| return PVRSRV_ERROR_INVALID_DEVICEID; |
| } |
| |
| |
| #ifndef ReadHWReg |
| IMG_EXPORT |
| IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset) |
| { |
| return *(volatile IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset); |
| } |
| #endif |
| |
| |
| #ifndef WriteHWReg |
| IMG_EXPORT |
| IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value) |
| { |
| PVR_DPF((PVR_DBG_MESSAGE,"WriteHWReg Base:%x, Offset: %x, Value %x", |
| (IMG_UINTPTR_T)pvLinRegBaseAddr,ui32Offset,ui32Value)); |
| |
| *(IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset) = ui32Value; |
| } |
| #endif |
| |
| |
| #ifndef WriteHWRegs |
| IMG_EXPORT |
| IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs) |
| { |
| while (ui32Count) |
| { |
| WriteHWReg (pvLinRegBaseAddr, psHWRegs->ui32RegAddr, psHWRegs->ui32RegVal); |
| psHWRegs++; |
| ui32Count--; |
| } |
| } |
| #endif |
| |
| static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) |
| { |
| IMG_UINT *pui32DevCount; |
| PVRSRV_DEVICE_IDENTIFIER **ppsDevIdList; |
| |
| pui32DevCount = va_arg(va, IMG_UINT*); |
| ppsDevIdList = va_arg(va, PVRSRV_DEVICE_IDENTIFIER**); |
| |
| if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT) |
| { |
| *(*ppsDevIdList) = psDeviceNode->sDevId; |
| (*ppsDevIdList)++; |
| (*pui32DevCount)++; |
| } |
| } |
| |
| |
| |
| IMG_EXPORT |
| PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices, |
| PVRSRV_DEVICE_IDENTIFIER *psDevIdList) |
| { |
| SYS_DATA *psSysData; |
| IMG_UINT32 i; |
| |
| if (!pui32NumDevices || !psDevIdList) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params")); |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| SysAcquireData(&psSysData); |
| |
| |
| |
| for (i=0; i<PVRSRV_MAX_DEVICES; i++) |
| { |
| psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN; |
| } |
| |
| |
| *pui32NumDevices = 0; |
| |
| |
| |
| |
| |
| List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList, |
| &PVRSRVEnumerateDevicesKM_ForEachVaCb, |
| pui32NumDevices, |
| &psDevIdList); |
| |
| |
| return PVRSRV_OK; |
| } |
| |
| |
| PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData) |
| { |
| PVRSRV_ERROR eError; |
| |
| |
| eError = ResManInit(); |
| if (eError != PVRSRV_OK) |
| { |
| goto Error; |
| } |
| |
| eError = PVRSRVPerProcessDataInit(); |
| if(eError != PVRSRV_OK) |
| { |
| goto Error; |
| } |
| |
| |
| eError = PVRSRVHandleInit(); |
| if(eError != PVRSRV_OK) |
| { |
| goto Error; |
| } |
| |
| |
| eError = OSCreateResource(&psSysData->sPowerStateChangeResource); |
| if (eError != PVRSRV_OK) |
| { |
| goto Error; |
| } |
| |
| |
| psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0; |
| psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified; |
| |
| |
| if(OSAllocMem( PVRSRV_PAGEABLE_SELECT, |
| sizeof(PVRSRV_EVENTOBJECT) , |
| (IMG_VOID **)&psSysData->psGlobalEventObject, 0, |
| "Event Object") != PVRSRV_OK) |
| { |
| |
| goto Error; |
| } |
| |
| if(OSEventObjectCreateKM("PVRSRV_GLOBAL_EVENTOBJECT", psSysData->psGlobalEventObject) != PVRSRV_OK) |
| { |
| goto Error; |
| } |
| |
| |
| psSysData->pfnHighResTimerCreate = OSFuncHighResTimerCreate; |
| psSysData->pfnHighResTimerGetus = OSFuncHighResTimerGetus; |
| psSysData->pfnHighResTimerDestroy = OSFuncHighResTimerDestroy; |
| |
| #if defined(TTRACE) |
| eError = PVRSRVTimeTraceInit(); |
| if (eError != PVRSRV_OK) |
| goto Error; |
| g_ui32InitFlags |= INIT_DATA_ENABLE_TTARCE; |
| #endif |
| |
| |
| PDUMPINIT(); |
| g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT; |
| |
| PERFINIT(); |
| return eError; |
| |
| Error: |
| PVRSRVDeInit(psSysData); |
| return eError; |
| } |
| |
| |
| |
| IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData) |
| { |
| PVRSRV_ERROR eError; |
| |
| PVR_UNREFERENCED_PARAMETER(psSysData); |
| |
| if (psSysData == IMG_NULL) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param")); |
| return; |
| } |
| |
| PERFDEINIT(); |
| |
| #if defined(TTRACE) |
| |
| if ((g_ui32InitFlags & INIT_DATA_ENABLE_TTARCE) > 0) |
| { |
| PVRSRVTimeTraceDeinit(); |
| } |
| #endif |
| |
| if( (g_ui32InitFlags & INIT_DATA_ENABLE_PDUMPINIT) > 0) |
| { |
| PDUMPDEINIT(); |
| } |
| |
| |
| if(psSysData->psGlobalEventObject) |
| { |
| OSEventObjectDestroyKM(psSysData->psGlobalEventObject); |
| OSFreeMem( PVRSRV_PAGEABLE_SELECT, |
| sizeof(PVRSRV_EVENTOBJECT), |
| psSysData->psGlobalEventObject, |
| 0); |
| psSysData->psGlobalEventObject = IMG_NULL; |
| } |
| |
| eError = PVRSRVHandleDeInit(); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed")); |
| } |
| |
| eError = PVRSRVPerProcessDataDeInit(); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed")); |
| } |
| |
| ResManDeInit(); |
| } |
| |
| |
| PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData, |
| PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*), |
| IMG_UINT32 ui32SOCInterruptBit, |
| IMG_UINT32 *pui32DeviceIndex) |
| { |
| PVRSRV_ERROR eError; |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| |
| |
| if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP, |
| sizeof(PVRSRV_DEVICE_NODE), |
| (IMG_VOID **)&psDeviceNode, IMG_NULL, |
| "Device Node") != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode")); |
| return (PVRSRV_ERROR_OUT_OF_MEMORY); |
| } |
| OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE)); |
| |
| eError = pfnRegisterDevice(psDeviceNode); |
| if (eError != PVRSRV_OK) |
| { |
| OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, |
| sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL); |
| |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device")); |
| return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED); |
| } |
| |
| |
| |
| |
| |
| |
| psDeviceNode->ui32RefCount = 1; |
| psDeviceNode->psSysData = psSysData; |
| psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit; |
| |
| |
| AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex); |
| |
| |
| List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode); |
| |
| |
| *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex; |
| |
| return PVRSRV_OK; |
| } |
| |
| |
| PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex) |
| { |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| SYS_DATA *psSysData; |
| PVRSRV_ERROR eError; |
| |
| PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice")); |
| |
| SysAcquireData(&psSysData); |
| |
| |
| psDeviceNode = (PVRSRV_DEVICE_NODE*) |
| List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, |
| &MatchDeviceKM_AnyVaCb, |
| ui32DevIndex, |
| IMG_TRUE); |
| if(!psDeviceNode) |
| { |
| |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: requested device is not present")); |
| return PVRSRV_ERROR_INIT_FAILURE; |
| } |
| PVR_ASSERT (psDeviceNode->ui32RefCount > 0); |
| |
| |
| |
| eError = PVRSRVResManConnect(IMG_NULL, &psDeviceNode->hResManContext); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed PVRSRVResManConnect call")); |
| return eError; |
| } |
| |
| |
| if(psDeviceNode->pfnInitDevice != IMG_NULL) |
| { |
| eError = psDeviceNode->pfnInitDevice(psDeviceNode); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed InitDevice call")); |
| return eError; |
| } |
| } |
| |
| return PVRSRV_OK; |
| } |
| |
| |
| static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode) |
| { |
| PVRSRV_ERROR eError; |
| eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex, |
| PVRSRV_DEV_POWER_STATE_DEFAULT, |
| KERNEL_ID, IMG_FALSE); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex)); |
| } |
| return eError; |
| } |
| |
| static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode) |
| { |
| PVRSRV_ERROR eError; |
| eError = PVRSRVDevInitCompatCheck(psDeviceNode); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex)); |
| } |
| return eError; |
| } |
| |
| |
| PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful) |
| { |
| SYS_DATA *psSysData; |
| PVRSRV_ERROR eError; |
| |
| PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem")); |
| |
| SysAcquireData(&psSysData); |
| |
| if (bInitSuccessful) |
| { |
| eError = SysFinalise(); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: SysFinalise failed (%d)", eError)); |
| return eError; |
| } |
| |
| |
| eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList, |
| &PVRSRVFinaliseSystem_SetPowerState_AnyCb); |
| if (eError != PVRSRV_OK) |
| { |
| return eError; |
| } |
| |
| |
| eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList, |
| &PVRSRVFinaliseSystem_CompatCheck_AnyCb); |
| if (eError != PVRSRV_OK) |
| { |
| return eError; |
| } |
| } |
| |
| |
| |
| |
| |
| PDUMPENDINITPHASE(); |
| |
| return PVRSRV_OK; |
| } |
| |
| |
| PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode) |
| { |
| |
| if (psDeviceNode->pfnInitDeviceCompatCheck) |
| return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode); |
| else |
| return PVRSRV_OK; |
| } |
| |
| static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) |
| { |
| PVRSRV_DEVICE_TYPE eDeviceType; |
| IMG_UINT32 ui32DevIndex; |
| |
| eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE); |
| ui32DevIndex = va_arg(va, IMG_UINT32); |
| |
| if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN && |
| psDeviceNode->sDevId.eDeviceType == eDeviceType) || |
| (eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN && |
| psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)) |
| { |
| return psDeviceNode; |
| } |
| else |
| { |
| return IMG_NULL; |
| } |
| } |
| |
| IMG_EXPORT |
| PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex, |
| PVRSRV_DEVICE_TYPE eDeviceType, |
| IMG_HANDLE *phDevCookie) |
| { |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| SYS_DATA *psSysData; |
| |
| PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM")); |
| |
| SysAcquireData(&psSysData); |
| |
| |
| psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, |
| &PVRSRVAcquireDeviceDataKM_Match_AnyVaCb, |
| eDeviceType, |
| ui32DevIndex); |
| |
| |
| if (!psDeviceNode) |
| { |
| |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present")); |
| return PVRSRV_ERROR_INIT_FAILURE; |
| } |
| |
| PVR_ASSERT (psDeviceNode->ui32RefCount > 0); |
| |
| |
| if (phDevCookie) |
| { |
| *phDevCookie = (IMG_HANDLE)psDeviceNode; |
| } |
| |
| return PVRSRV_OK; |
| } |
| |
| |
| PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex) |
| { |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| SYS_DATA *psSysData; |
| PVRSRV_ERROR eError; |
| |
| SysAcquireData(&psSysData); |
| |
| psDeviceNode = (PVRSRV_DEVICE_NODE*) |
| List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, |
| &MatchDeviceKM_AnyVaCb, |
| ui32DevIndex, |
| IMG_TRUE); |
| |
| if (!psDeviceNode) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: requested device %d is not present", ui32DevIndex)); |
| return PVRSRV_ERROR_DEVICEID_NOT_FOUND; |
| } |
| |
| |
| |
| eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex, |
| PVRSRV_DEV_POWER_STATE_OFF, |
| KERNEL_ID, |
| IMG_FALSE); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call")); |
| return eError; |
| } |
| |
| |
| |
| eError = ResManFreeResByCriteria(psDeviceNode->hResManContext, |
| RESMAN_CRITERIA_RESTYPE, |
| RESMAN_TYPE_DEVICEMEM_ALLOCATION, |
| IMG_NULL, 0); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call")); |
| return eError; |
| } |
| |
| |
| |
| if(psDeviceNode->pfnDeInitDevice != IMG_NULL) |
| { |
| eError = psDeviceNode->pfnDeInitDevice(psDeviceNode); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed DeInitDevice call")); |
| return eError; |
| } |
| } |
| |
| |
| |
| PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE); |
| psDeviceNode->hResManContext = IMG_NULL; |
| |
| |
| List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode); |
| |
| |
| (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex); |
| OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, |
| sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL); |
| |
| |
| return (PVRSRV_OK); |
| } |
| |
| |
| IMG_EXPORT |
| PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr, |
| IMG_UINT32 ui32Value, |
| IMG_UINT32 ui32Mask, |
| IMG_UINT32 ui32Timeoutus, |
| IMG_UINT32 ui32PollPeriodus, |
| IMG_BOOL bAllowPreemption) |
| { |
| #if defined (EMULATOR) |
| { |
| PVR_UNREFERENCED_PARAMETER(bAllowPreemption); |
| #if !defined(__linux__) |
| PVR_UNREFERENCED_PARAMETER(ui32PollPeriodus); |
| #endif |
| |
| |
| |
| do |
| { |
| if((*pui32LinMemAddr & ui32Mask) == ui32Value) |
| { |
| return PVRSRV_OK; |
| } |
| |
| #if defined(__linux__) |
| OSWaitus(ui32PollPeriodus); |
| #else |
| OSReleaseThreadQuanta(); |
| #endif |
| |
| } while (ui32Timeoutus); |
| } |
| #else |
| { |
| IMG_UINT32 ui32ActualValue = 0xFFFFFFFFU; |
| |
| if (bAllowPreemption) |
| { |
| PVR_ASSERT(ui32PollPeriodus >= 1000); |
| } |
| |
| |
| LOOP_UNTIL_TIMEOUT(ui32Timeoutus) |
| { |
| ui32ActualValue = (*pui32LinMemAddr & ui32Mask); |
| if(ui32ActualValue == ui32Value) |
| { |
| return PVRSRV_OK; |
| } |
| |
| if (bAllowPreemption) |
| { |
| OSSleepms(ui32PollPeriodus / 1000); |
| } |
| else |
| { |
| OSWaitus(ui32PollPeriodus); |
| } |
| } END_LOOP_UNTIL_TIMEOUT(); |
| |
| PVR_DPF((PVR_DBG_ERROR,"PollForValueKM: Timeout. Expected 0x%x but found 0x%x (mask 0x%x).", |
| ui32Value, ui32ActualValue, ui32Mask)); |
| } |
| #endif |
| |
| return PVRSRV_ERROR_TIMEOUT; |
| } |
| |
| |
| static IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, va_list va) |
| { |
| IMG_CHAR **ppszStr; |
| IMG_UINT32 *pui32StrLen; |
| IMG_UINT32 ui32Mode; |
| PVRSRV_ERROR (*pfnGetStats)(RA_ARENA *, IMG_CHAR **, IMG_UINT32 *); |
| |
| ppszStr = va_arg(va, IMG_CHAR**); |
| pui32StrLen = va_arg(va, IMG_UINT32*); |
| ui32Mode = va_arg(va, IMG_UINT32); |
| |
| |
| switch(ui32Mode) |
| { |
| case PVRSRV_MISC_INFO_MEMSTATS_PRESENT: |
| pfnGetStats = &RA_GetStats; |
| break; |
| case PVRSRV_MISC_INFO_FREEMEM_PRESENT: |
| pfnGetStats = &RA_GetStatsFreeMem; |
| break; |
| default: |
| return; |
| } |
| |
| if(psBMHeap->pImportArena) |
| { |
| pfnGetStats(psBMHeap->pImportArena, |
| ppszStr, |
| pui32StrLen); |
| } |
| |
| if(psBMHeap->pVMArena) |
| { |
| pfnGetStats(psBMHeap->pVMArena, |
| ppszStr, |
| pui32StrLen); |
| } |
| } |
| |
| static PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va) |
| { |
| |
| IMG_UINT32 *pui32StrLen; |
| IMG_INT32 *pi32Count; |
| IMG_CHAR **ppszStr; |
| IMG_UINT32 ui32Mode; |
| |
| pui32StrLen = va_arg(va, IMG_UINT32*); |
| pi32Count = va_arg(va, IMG_INT32*); |
| ppszStr = va_arg(va, IMG_CHAR**); |
| ui32Mode = va_arg(va, IMG_UINT32); |
| |
| CHECK_SPACE(*pui32StrLen); |
| *pi32Count = OSSNPrintf(*ppszStr, 100, "\nApplication Context (hDevMemContext) %p:\n", |
| (IMG_HANDLE)psBMContext); |
| UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen); |
| |
| List_BM_HEAP_ForEach_va(psBMContext->psBMHeap, |
| &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb, |
| ppszStr, |
| pui32StrLen, |
| ui32Mode); |
| return PVRSRV_OK; |
| } |
| |
| |
| static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) |
| { |
| IMG_UINT32 *pui32StrLen; |
| IMG_INT32 *pi32Count; |
| IMG_CHAR **ppszStr; |
| IMG_UINT32 ui32Mode; |
| |
| pui32StrLen = va_arg(va, IMG_UINT32*); |
| pi32Count = va_arg(va, IMG_INT32*); |
| ppszStr = va_arg(va, IMG_CHAR**); |
| ui32Mode = va_arg(va, IMG_UINT32); |
| |
| CHECK_SPACE(*pui32StrLen); |
| *pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType); |
| UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen); |
| |
| |
| if(psDeviceNode->sDevMemoryInfo.pBMKernelContext) |
| { |
| CHECK_SPACE(*pui32StrLen); |
| *pi32Count = OSSNPrintf(*ppszStr, 100, "\nKernel Context:\n"); |
| UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen); |
| |
| List_BM_HEAP_ForEach_va(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psBMHeap, |
| &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb, |
| ppszStr, |
| pui32StrLen, |
| ui32Mode); |
| } |
| |
| |
| return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext, |
| &PVRSRVGetMiscInfoKM_BMContext_AnyVaCb, |
| pui32StrLen, |
| pi32Count, |
| ppszStr, |
| ui32Mode); |
| } |
| |
| |
| IMG_EXPORT |
| #if defined (SUPPORT_SID_INTERFACE) |
| PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO_KM *psMiscInfo) |
| #else |
| PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo) |
| #endif |
| { |
| SYS_DATA *psSysData; |
| |
| if(!psMiscInfo) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters")); |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| psMiscInfo->ui32StatePresent = 0; |
| |
| |
| 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)) |
| { |
| PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags")); |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| SysAcquireData(&psSysData); |
| |
| |
| 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; |
| } |
| |
| |
| 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; |
| } |
| |
| |
| if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) && |
| (psMiscInfo->pszMemoryStr != IMG_NULL)) |
| { |
| RA_ARENA **ppArena; |
| IMG_CHAR *pszStr; |
| IMG_UINT32 ui32StrLen; |
| IMG_INT32 i32Count; |
| |
| pszStr = psMiscInfo->pszMemoryStr; |
| ui32StrLen = psMiscInfo->ui32MemoryStrLen; |
| |
| psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT; |
| |
| |
| 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); |
| |
| ppArena++; |
| } |
| |
| |
| |
| List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, |
| &PVRSRVGetMiscInfoKM_Device_AnyVaCb, |
| &ui32StrLen, |
| &i32Count, |
| &pszStr, |
| PVRSRV_MISC_INFO_MEMSTATS_PRESENT); |
| |
| |
| i32Count = OSSNPrintf(pszStr, 100, "\n"); |
| UPDATE_SPACE(pszStr, i32Count, ui32StrLen); |
| } |
| |
| |
| 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; |
| |
| |
| 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; |
| } |
| |
| |
| |
| 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; |
| IMG_INT32 i32Count; |
| IMG_INT i; |
| psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT; |
| |
| |
| 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) |
| { |
| |
| psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType; |
| } |
| else |
| { |
| #if defined (SUPPORT_SID_INTERFACE) |
| PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = psMiscInfo->sCacheOpCtl.psKernelMemInfo; |
| |
| if(!psMiscInfo->sCacheOpCtl.psKernelMemInfo) |
| #else |
| PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; |
| PVRSRV_PER_PROCESS_DATA *psPerProc; |
| |
| if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo) |
| #endif |
| { |
| 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")); |
| } |
| |
| #if defined (SUPPORT_SID_INTERFACE) |
| PVR_DBG_BREAK |
| #else |
| |
| 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; |
| } |
| #endif |
| |
| if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) |
| { |
| if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, |
| psMiscInfo->sCacheOpCtl.pvBaseVAddr, |
| psMiscInfo->sCacheOpCtl.ui32Length)) |
| { |
| return PVRSRV_ERROR_CACHEOP_FAILED; |
| } |
| } |
| else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) |
| { |
| if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, |
| psMiscInfo->sCacheOpCtl.pvBaseVAddr, |
| psMiscInfo->sCacheOpCtl.ui32Length)) |
| { |
| return PVRSRV_ERROR_CACHEOP_FAILED; |
| } |
| } |
| } |
| } |
| |
| if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT) != 0UL) |
| { |
| #if !defined (SUPPORT_SID_INTERFACE) |
| PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; |
| PVRSRV_PER_PROCESS_DATA *psPerProc; |
| #endif |
| |
| psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT; |
| |
| #if defined (SUPPORT_SID_INTERFACE) |
| PVR_DBG_BREAK |
| #else |
| |
| 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; |
| #endif |
| } |
| |
| #if defined(PVRSRV_RESET_ON_HWTIMEOUT) |
| if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL) |
| { |
| PVR_LOG(("User requested OS reset")); |
| OSPanic(); |
| } |
| #endif |
| |
| return PVRSRV_OK; |
| } |
| |
| |
| IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode) |
| { |
| SYS_DATA *psSysData; |
| IMG_BOOL bStatus = IMG_FALSE; |
| IMG_UINT32 ui32InterruptSource; |
| |
| if(!psDeviceNode) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n")); |
| goto out; |
| } |
| psSysData = psDeviceNode->psSysData; |
| |
| |
| ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode); |
| if(ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit) |
| { |
| if(psDeviceNode->pfnDeviceISR != IMG_NULL) |
| { |
| bStatus = (*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData); |
| } |
| |
| SysClearInterrupts(psSysData, psDeviceNode->ui32SOCInterruptBit); |
| } |
| |
| out: |
| return bStatus; |
| } |
| |
| static IMG_VOID PVRSRVSystemLISR_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) |
| { |
| |
| IMG_BOOL *pbStatus; |
| IMG_UINT32 *pui32InterruptSource; |
| IMG_UINT32 *pui32ClearInterrupts; |
| |
| pbStatus = va_arg(va, IMG_BOOL*); |
| pui32InterruptSource = va_arg(va, IMG_UINT32*); |
| pui32ClearInterrupts = va_arg(va, IMG_UINT32*); |
| |
| |
| if(psDeviceNode->pfnDeviceISR != IMG_NULL) |
| { |
| if(*pui32InterruptSource & psDeviceNode->ui32SOCInterruptBit) |
| { |
| if((*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData)) |
| { |
| |
| *pbStatus = IMG_TRUE; |
| } |
| |
| *pui32ClearInterrupts |= psDeviceNode->ui32SOCInterruptBit; |
| } |
| } |
| } |
| |
| IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData) |
| { |
| SYS_DATA *psSysData = pvSysData; |
| IMG_BOOL bStatus = IMG_FALSE; |
| IMG_UINT32 ui32InterruptSource; |
| IMG_UINT32 ui32ClearInterrupts = 0; |
| if(!psSysData) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n")); |
| } |
| else |
| { |
| |
| ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL); |
| |
| |
| if(ui32InterruptSource) |
| { |
| |
| List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList, |
| &PVRSRVSystemLISR_ForEachVaCb, |
| &bStatus, |
| &ui32InterruptSource, |
| &ui32ClearInterrupts); |
| |
| SysClearInterrupts(psSysData, ui32ClearInterrupts); |
| } |
| } |
| return bStatus; |
| } |
| |
| |
| static IMG_VOID PVRSRVMISR_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode) |
| { |
| if(psDeviceNode->pfnDeviceMISR != IMG_NULL) |
| { |
| (*psDeviceNode->pfnDeviceMISR)(psDeviceNode->pvISRData); |
| } |
| } |
| |
| 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); |
| } |
| } |
| } |
| |
| |
| IMG_EXPORT |
| PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags) |
| { |
| return PVRSRVPerProcessDataConnect(ui32PID, ui32Flags); |
| } |
| |
| |
| IMG_EXPORT |
| IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID) |
| { |
| PVRSRVPerProcessDataDisconnect(ui32PID); |
| } |
| |
| |
| PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer, |
| IMG_SIZE_T *puiBufSize, IMG_BOOL bSave) |
| { |
| IMG_SIZE_T uiBytesSaved = 0; |
| IMG_PVOID pvLocalMemCPUVAddr; |
| RA_SEGMENT_DETAILS sSegDetails; |
| |
| if (hArena == IMG_NULL) |
| { |
| return (PVRSRV_ERROR_INVALID_PARAMS); |
| } |
| |
| sSegDetails.uiSize = 0; |
| sSegDetails.sCpuPhyAddr.uiAddr = 0; |
| sSegDetails.hSegment = 0; |
| |
| |
| while (RA_GetNextLiveSegment(hArena, &sSegDetails)) |
| { |
| if (pbyBuffer == IMG_NULL) |
| { |
| |
| uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize; |
| } |
| else |
| { |
| if ((uiBytesSaved + sizeof(sSegDetails.uiSize) + sSegDetails.uiSize) > *puiBufSize) |
| { |
| return (PVRSRV_ERROR_OUT_OF_MEMORY); |
| } |
| |
| PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSaveRestoreLiveSegments: Base %08x size %08x", sSegDetails.sCpuPhyAddr.uiAddr, sSegDetails.uiSize)); |
| |
| |
| pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr, |
| sSegDetails.uiSize, |
| PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED, |
| IMG_NULL); |
| if (pvLocalMemCPUVAddr == IMG_NULL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Failed to map local memory to host")); |
| return (PVRSRV_ERROR_OUT_OF_MEMORY); |
| } |
| |
| if (bSave) |
| { |
| |
| OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize)); |
| pbyBuffer += sizeof(sSegDetails.uiSize); |
| |
| OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr, sSegDetails.uiSize); |
| pbyBuffer += sSegDetails.uiSize; |
| } |
| else |
| { |
| IMG_UINT32 uiSize; |
| |
| OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize)); |
| |
| if (uiSize != sSegDetails.uiSize) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Segment size error")); |
| } |
| else |
| { |
| pbyBuffer += sizeof(sSegDetails.uiSize); |
| |
| OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer, sSegDetails.uiSize); |
| pbyBuffer += sSegDetails.uiSize; |
| } |
| } |
| |
| |
| uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize; |
| |
| OSUnMapPhysToLin(pvLocalMemCPUVAddr, |
| sSegDetails.uiSize, |
| PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED, |
| IMG_NULL); |
| } |
| } |
| |
| if (pbyBuffer == IMG_NULL) |
| { |
| *puiBufSize = uiBytesSaved; |
| } |
| |
| return (PVRSRV_OK); |
| } |
| |
| |
| IMG_EXPORT |
| const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError) |
| { |
| |
| #include "pvrsrv_errors.h" |
| } |
| |
| static IMG_VOID PVRSRVCommandCompleteCallbacks_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode) |
| { |
| if(psDeviceNode->pfnDeviceCommandComplete != IMG_NULL) |
| { |
| |
| (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode); |
| } |
| } |
| |
| IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID) |
| { |
| SYS_DATA *psSysData; |
| SysAcquireData(&psSysData); |
| |
| |
| List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, |
| &PVRSRVCommandCompleteCallbacks_ForEachCb); |
| } |
| |
| IMG_EXPORT |
| IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID) |
| { |
| PVRSRVScheduleDeviceCallbacks(); |
| } |
| |