diff options
Diffstat (limited to 'drivers/gpu/pvr/sgx')
-rw-r--r-- | drivers/gpu/pvr/sgx/bridged_sgx_bridge.c | 2670 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/bridged_sgx_bridge.h | 42 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/mmu.c | 3023 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/mmu.h | 146 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/pb.c | 459 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/sgx_bridge_km.h | 134 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/sgxconfig.h | 227 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/sgxinfokm.h | 369 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/sgxinit.c | 2557 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/sgxkick.c | 713 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/sgxpower.c | 477 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/sgxreset.c | 509 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/sgxtransfer.c | 582 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/sgxutils.c | 1010 | ||||
-rw-r--r-- | drivers/gpu/pvr/sgx/sgxutils.h | 100 |
15 files changed, 13018 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/sgx/bridged_sgx_bridge.c b/drivers/gpu/pvr/sgx/bridged_sgx_bridge.c new file mode 100644 index 0000000..e1b7320 --- /dev/null +++ b/drivers/gpu/pvr/sgx/bridged_sgx_bridge.c @@ -0,0 +1,2670 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 <stddef.h> + +#include "img_defs.h" + +#if defined(SUPPORT_SGX) + +#include "services.h" +#include "pvr_debug.h" +#include "pvr_bridge.h" +#include "sgx_bridge.h" +#include "perproc.h" +#include "power.h" +#include "pvr_bridge_km.h" +#include "sgx_bridge_km.h" + +#if defined(SUPPORT_MSVDX) + #include "msvdx_bridge.h" +#endif + +#include "bridged_pvr_bridge.h" +#include "bridged_sgx_bridge.h" +#include "sgxutils.h" +#include "pdump_km.h" + +static IMG_INT +SGXGetClientInfoBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_GETCLIENTINFO *psGetClientInfoIN, + PVRSRV_BRIDGE_OUT_GETCLIENTINFO *psGetClientInfoOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETCLIENTINFO); + + psGetClientInfoOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt, + psGetClientInfoIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psGetClientInfoOUT->eError != PVRSRV_OK) + { + return 0; + } + + psGetClientInfoOUT->eError = + SGXGetClientInfoKM(hDevCookieInt, + &psGetClientInfoOUT->sClientInfo); + return 0; +} + +static IMG_INT +SGXReleaseClientInfoBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_RELEASECLIENTINFO *psReleaseClientInfoIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + PVRSRV_SGXDEV_INFO *psDevInfo; + IMG_HANDLE hDevCookieInt; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO); + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt, + psReleaseClientInfoIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice; + + PVR_ASSERT(psDevInfo->ui32ClientRefCount > 0); + + psDevInfo->ui32ClientRefCount--; + + psRetOUT->eError = PVRSRV_OK; + + return 0; +} + + +static IMG_INT +SGXGetInternalDevInfoBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO *psSGXGetInternalDevInfoIN, + PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO *psSGXGetInternalDevInfoOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO); + + psSGXGetInternalDevInfoOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt, + psSGXGetInternalDevInfoIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psSGXGetInternalDevInfoOUT->eError != PVRSRV_OK) + { + return 0; + } + + psSGXGetInternalDevInfoOUT->eError = + SGXGetInternalDevInfoKM(hDevCookieInt, + &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo); + + + psSGXGetInternalDevInfoOUT->eError = + PVRSRVAllocHandle(psPerProc->psHandleBase, + &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle, + psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle, + PVRSRV_HANDLE_TYPE_MEM_INFO, + PVRSRV_HANDLE_ALLOC_FLAG_SHARED); + + return 0; +} + + +static IMG_INT +SGXDoKickBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_DOKICK *psDoKickIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + IMG_UINT32 i; + IMG_INT ret = 0; + IMG_UINT32 ui32NumDstSyncs; + IMG_HANDLE *phKernelSyncInfoHandles = IMG_NULL; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DOKICK); + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psDoKickIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.hCCBKernelMemInfo, + psDoKickIN->sCCBKick.hCCBKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + if(psDoKickIN->sCCBKick.hTA3DSyncInfo != IMG_NULL) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.hTA3DSyncInfo, + psDoKickIN->sCCBKick.hTA3DSyncInfo, + PVRSRV_HANDLE_TYPE_SYNC_INFO); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + if(psDoKickIN->sCCBKick.hTASyncInfo != IMG_NULL) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.hTASyncInfo, + psDoKickIN->sCCBKick.hTASyncInfo, + PVRSRV_HANDLE_TYPE_SYNC_INFO); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + if(psDoKickIN->sCCBKick.h3DSyncInfo != IMG_NULL) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.h3DSyncInfo, + psDoKickIN->sCCBKick.h3DSyncInfo, + PVRSRV_HANDLE_TYPE_SYNC_INFO); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + +#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS) + + if (psDoKickIN->sCCBKick.ui32NumTASrcSyncs > SGX_MAX_TA_SRC_SYNCS) + { + psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; + return 0; + } + + for(i=0; i<psDoKickIN->sCCBKick.ui32NumTASrcSyncs; i++) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i], + psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i], + PVRSRV_HANDLE_TYPE_SYNC_INFO); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + if (psDoKickIN->sCCBKick.ui32NumTADstSyncs > SGX_MAX_TA_DST_SYNCS) + { + psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; + return 0; + } + + for(i=0; i<psDoKickIN->sCCBKick.ui32NumTADstSyncs; i++) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i], + psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i], + PVRSRV_HANDLE_TYPE_SYNC_INFO); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + if (psDoKickIN->sCCBKick.ui32Num3DSrcSyncs > SGX_MAX_3D_SRC_SYNCS) + { + psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; + return 0; + } + + for(i=0; i<psDoKickIN->sCCBKick.ui32Num3DSrcSyncs; i++) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i], + psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i], + PVRSRV_HANDLE_TYPE_SYNC_INFO); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } +#else + + if (psDoKickIN->sCCBKick.ui32NumSrcSyncs > SGX_MAX_SRC_SYNCS) + { + psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; + return 0; + } + for(i=0; i<psDoKickIN->sCCBKick.ui32NumSrcSyncs; i++) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i], + psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i], + PVRSRV_HANDLE_TYPE_SYNC_INFO); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } +#endif + + if (psDoKickIN->sCCBKick.ui32NumTAStatusVals > SGX_MAX_TA_STATUS_VALS) + { + psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; + return 0; + } + for (i = 0; i < psDoKickIN->sCCBKick.ui32NumTAStatusVals; i++) + { + psRetOUT->eError = +#if defined(SUPPORT_SGX_NEW_STATUS_VALS) + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo, + psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); +#else + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i], + psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i], + PVRSRV_HANDLE_TYPE_SYNC_INFO); +#endif + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + if (psDoKickIN->sCCBKick.ui32Num3DStatusVals > SGX_MAX_3D_STATUS_VALS) + { + psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; + return 0; + } + for(i = 0; i < psDoKickIN->sCCBKick.ui32Num3DStatusVals; i++) + { + psRetOUT->eError = +#if defined(SUPPORT_SGX_NEW_STATUS_VALS) + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo, + psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); +#else + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i], + psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i], + PVRSRV_HANDLE_TYPE_SYNC_INFO); +#endif + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + ui32NumDstSyncs = psDoKickIN->sCCBKick.ui32NumDstSyncObjects; + + if(ui32NumDstSyncs > 0) + { + if(!OSAccessOK(PVR_VERIFY_READ, + psDoKickIN->sCCBKick.pahDstSyncHandles, + ui32NumDstSyncs * sizeof(IMG_HANDLE))) + { + PVR_DPF((PVR_DBG_ERROR, "%s: SGXDoKickBW:" + " Invalid pasDstSyncHandles pointer", __FUNCTION__)); + return -EFAULT; + } + + psRetOUT->eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32NumDstSyncs * sizeof(IMG_HANDLE), + (IMG_VOID **)&phKernelSyncInfoHandles, + 0, + "Array of Synchronization Info Handles"); + if (psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + if(CopyFromUserWrapper(psPerProc, + ui32BridgeID, + phKernelSyncInfoHandles, + psDoKickIN->sCCBKick.pahDstSyncHandles, + ui32NumDstSyncs * sizeof(IMG_HANDLE)) != PVRSRV_OK) + { + ret = -EFAULT; + goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT; + } + + + psDoKickIN->sCCBKick.pahDstSyncHandles = phKernelSyncInfoHandles; + + for( i = 0; i < ui32NumDstSyncs; i++) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.pahDstSyncHandles[i], + psDoKickIN->sCCBKick.pahDstSyncHandles[i], + PVRSRV_HANDLE_TYPE_SYNC_INFO); + + if(psRetOUT->eError != PVRSRV_OK) + { + goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT; + } + + } + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo, + psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + + if(psRetOUT->eError != PVRSRV_OK) + { + goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT; + } + } + + psRetOUT->eError = + SGXDoKickKM(hDevCookieInt, + &psDoKickIN->sCCBKick); + +PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT: + + if(phKernelSyncInfoHandles) + { + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32NumDstSyncs * sizeof(IMG_HANDLE), + (IMG_VOID *)phKernelSyncInfoHandles, + 0); + + } + return ret; +} + + +static IMG_INT +SGXScheduleProcessQueuesBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES *psScheduleProcQIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES); + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psScheduleProcQIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psRetOUT->eError = SGXScheduleProcessQueuesKM(hDevCookieInt); + + return 0; +} + + +#if defined(TRANSFER_QUEUE) +static IMG_INT +SGXSubmitTransferBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SUBMITTRANSFER *psSubmitTransferIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + PVRSRV_TRANSFER_SGX_KICK *psKick; + IMG_UINT32 i; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMITTRANSFER); + PVR_UNREFERENCED_PARAMETER(ui32BridgeID); + + psKick = &psSubmitTransferIN->sKick; + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psSubmitTransferIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psKick->hCCBMemInfo, + psKick->hCCBMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + if (psKick->hTASyncInfo != IMG_NULL) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psKick->hTASyncInfo, + psKick->hTASyncInfo, + PVRSRV_HANDLE_TYPE_SYNC_INFO); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + if (psKick->h3DSyncInfo != IMG_NULL) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psKick->h3DSyncInfo, + psKick->h3DSyncInfo, + PVRSRV_HANDLE_TYPE_SYNC_INFO); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + if (psKick->ui32NumSrcSync > SGX_MAX_TRANSFER_SYNC_OPS) + { + psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; + return 0; + } + for (i = 0; i < psKick->ui32NumSrcSync; i++) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psKick->ahSrcSyncInfo[i], + psKick->ahSrcSyncInfo[i], + PVRSRV_HANDLE_TYPE_SYNC_INFO); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + if (psKick->ui32NumDstSync > SGX_MAX_TRANSFER_SYNC_OPS) + { + psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; + return 0; + } + for (i = 0; i < psKick->ui32NumDstSync; i++) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psKick->ahDstSyncInfo[i], + psKick->ahDstSyncInfo[i], + PVRSRV_HANDLE_TYPE_SYNC_INFO); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + psRetOUT->eError = SGXSubmitTransferKM(hDevCookieInt, psKick); + + return 0; +} + + +#if defined(SGX_FEATURE_2D_HARDWARE) +static IMG_INT +SGXSubmit2DBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SUBMIT2D *psSubmit2DIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + PVRSRV_2D_SGX_KICK *psKick; + IMG_UINT32 i; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMIT2D); + PVR_UNREFERENCED_PARAMETER(ui32BridgeID); + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psSubmit2DIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psKick = &psSubmit2DIN->sKick; + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psKick->hCCBMemInfo, + psKick->hCCBMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + if (psKick->hTASyncInfo != IMG_NULL) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psKick->hTASyncInfo, + psKick->hTASyncInfo, + PVRSRV_HANDLE_TYPE_SYNC_INFO); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + if (psKick->h3DSyncInfo != IMG_NULL) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psKick->h3DSyncInfo, + psKick->h3DSyncInfo, + PVRSRV_HANDLE_TYPE_SYNC_INFO); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + if (psKick->ui32NumSrcSync > SGX_MAX_2D_SRC_SYNC_OPS) + { + psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; + return 0; + } + for (i = 0; i < psKick->ui32NumSrcSync; i++) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psKick->ahSrcSyncInfo[i], + psKick->ahSrcSyncInfo[i], + PVRSRV_HANDLE_TYPE_SYNC_INFO); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + if (psKick->hDstSyncInfo != IMG_NULL) + { + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &psKick->hDstSyncInfo, + psKick->hDstSyncInfo, + PVRSRV_HANDLE_TYPE_SYNC_INFO); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + psRetOUT->eError = + SGXSubmit2DKM(hDevCookieInt, psKick); + + return 0; +} +#endif +#endif + + +static IMG_INT +SGXGetMiscInfoBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGXGETMISCINFO *psSGXGetMiscInfoIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + IMG_HANDLE hDevMemContextInt = 0; + PVRSRV_SGXDEV_INFO *psDevInfo; + SGX_MISC_INFO sMiscInfo; + PVRSRV_DEVICE_NODE *psDeviceNode; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, + PVRSRV_BRIDGE_SGX_GETMISCINFO); + + psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psSGXGetMiscInfoIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + +#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG) + + if (psSGXGetMiscInfoIN->psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMREAD) + { + psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevMemContextInt, + psSGXGetMiscInfoIN->psMiscInfo->hDevMemContext, + PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT); + + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } +#endif + + psDeviceNode = hDevCookieInt; + PVR_ASSERT(psDeviceNode != IMG_NULL); + if (psDeviceNode == IMG_NULL) + { + return -EFAULT; + } + + psDevInfo = psDeviceNode->pvDevice; + + + psRetOUT->eError = CopyFromUserWrapper(psPerProc, + ui32BridgeID, + &sMiscInfo, + psSGXGetMiscInfoIN->psMiscInfo, + sizeof(SGX_MISC_INFO)); + if (psRetOUT->eError != PVRSRV_OK) + { + return -EFAULT; + } + + { + psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, hDevMemContextInt); + + if (psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + } + + + psRetOUT->eError = CopyToUserWrapper(psPerProc, + ui32BridgeID, + psSGXGetMiscInfoIN->psMiscInfo, + &sMiscInfo, + sizeof(SGX_MISC_INFO)); + if (psRetOUT->eError != PVRSRV_OK) + { + return -EFAULT; + } + return 0; +} + + +static IMG_INT +SGXReadHWPerfCBBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBIN, + PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + PVRSRV_SGX_HWPERF_CB_ENTRY *psAllocated; + IMG_HANDLE hAllocatedHandle; + IMG_UINT32 ui32AllocatedSize; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_READ_HWPERF_CB); + + psSGXReadHWPerfCBOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psSGXReadHWPerfCBIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + + if(psSGXReadHWPerfCBOUT->eError != PVRSRV_OK) + { + return 0; + } + + ui32AllocatedSize = psSGXReadHWPerfCBIN->ui32ArraySize * + sizeof(psSGXReadHWPerfCBIN->psHWPerfCBData[0]); + ASSIGN_AND_EXIT_ON_ERROR(psSGXReadHWPerfCBOUT->eError, + OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32AllocatedSize, + (IMG_VOID **)&psAllocated, + &hAllocatedHandle, + "Array of Hardware Performance Circular Buffer Data")); + + psSGXReadHWPerfCBOUT->eError = SGXReadHWPerfCBKM(hDevCookieInt, + psSGXReadHWPerfCBIN->ui32ArraySize, + psAllocated, + &psSGXReadHWPerfCBOUT->ui32DataCount, + &psSGXReadHWPerfCBOUT->ui32ClockSpeed, + &psSGXReadHWPerfCBOUT->ui32HostTimeStamp); + if (psSGXReadHWPerfCBOUT->eError == PVRSRV_OK) + { + psSGXReadHWPerfCBOUT->eError = CopyToUserWrapper(psPerProc, + ui32BridgeID, + psSGXReadHWPerfCBIN->psHWPerfCBData, + psAllocated, + ui32AllocatedSize); + } + + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32AllocatedSize, + psAllocated, + hAllocatedHandle); + + + return 0; +} + + +static IMG_INT +SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + PVRSRV_ERROR eError; + IMG_BOOL bDissociateFailed = IMG_FALSE; + IMG_BOOL bLookupFailed = IMG_FALSE; + IMG_BOOL bReleaseFailed = IMG_FALSE; + IMG_HANDLE hDummy; + IMG_UINT32 i; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DEVINITPART2); + + if(!psPerProc->bInitProcess) + { + psRetOUT->eError = PVRSRV_ERROR_PROCESS_NOT_INITIALISED; + return 0; + } + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psSGXDevInitPart2IN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } + + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } + +#if defined(SGX_SUPPORT_HWPROFILING) + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } +#endif + +#if defined(SUPPORT_SGX_HWPERF) + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } +#endif + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } + +#if defined(FIX_HW_BRN_29702) + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } +#endif + +#if defined(FIX_HW_BRN_29823) + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } +#endif + +#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } +#endif + +#if defined(SGX_FEATURE_SPM_MODE_0) + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } +#endif + + for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++) + { + IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i]; + + if (hHandle == IMG_NULL) + { + continue; + } + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDummy, + hHandle, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } + } + + if (bLookupFailed) + { + PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle lookup failed")); + psRetOUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED; + return 0; + } + + + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } + + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } + + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } + + + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } + + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } + + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } + + + #if defined(SGX_SUPPORT_HWPROFILING) + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } +#endif + +#if defined(SUPPORT_SGX_HWPERF) + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } +#endif + + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } + + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } + +#if defined(FIX_HW_BRN_29702) + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bLookupFailed = IMG_TRUE; + } +#endif + +#if defined(FIX_HW_BRN_29823) + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } +#endif + +#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } +#endif + +#if defined(SGX_FEATURE_SPM_MODE_0) + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + &psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo, + psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } +#endif + + + for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++) + { + IMG_HANDLE *phHandle = &psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i]; + + if (*phHandle == IMG_NULL) + continue; + + eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase, + phHandle, + *phHandle, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if (eError != PVRSRV_OK) + { + bReleaseFailed = IMG_TRUE; + } + } + + if (bReleaseFailed) + { + PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle release failed")); + psRetOUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED; + + PVR_DBG_BREAK; + return 0; + } + + + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo); + if (eError != PVRSRV_OK) + { + bDissociateFailed = IMG_TRUE; + } + + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo); + if (eError != PVRSRV_OK) + { + bDissociateFailed = IMG_TRUE; + } + + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo); + if (eError != PVRSRV_OK) + { + bDissociateFailed = IMG_TRUE; + } + + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo); + if (eError != PVRSRV_OK) + { + bDissociateFailed = IMG_TRUE; + } + + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo); + if (eError != PVRSRV_OK) + { + bDissociateFailed = IMG_TRUE; + } + + + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo); + if (eError != PVRSRV_OK) + { + bDissociateFailed = IMG_TRUE; + } + + +#if defined(SGX_SUPPORT_HWPROFILING) + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo); + bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK); +#endif + +#if defined(SUPPORT_SGX_HWPERF) + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo); + if (eError != PVRSRV_OK) + { + bDissociateFailed = IMG_TRUE; + } +#endif + + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo); + if (eError != PVRSRV_OK) + { + bDissociateFailed = IMG_TRUE; + } + + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo); + if (eError != PVRSRV_OK) + { + bDissociateFailed = IMG_TRUE; + } + +#if defined(FIX_HW_BRN_29702) + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo); + bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK); +#endif + +#if defined(FIX_HW_BRN_29823) + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo); + bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK); +#endif + +#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo); + bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK); +#endif + +#if defined(SGX_FEATURE_SPM_MODE_0) + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo); + if (eError != PVRSRV_OK) + { + bDissociateFailed = IMG_TRUE; + } +#endif + + for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++) + { + IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i]; + + if (hHandle == IMG_NULL) + continue; + + eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, hHandle); + if (eError != PVRSRV_OK) + { + bDissociateFailed = IMG_TRUE; + } + } + + + if(bDissociateFailed) + { + PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo); + PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo); + PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo); + PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo); + PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo); + + for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++) + { + IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i]; + + if (hHandle == IMG_NULL) + continue; + + PVRSRVFreeDeviceMemKM(hDevCookieInt, (PVRSRV_KERNEL_MEM_INFO *)hHandle); + + } + + PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A dissociate failed")); + + psRetOUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED; + + + PVR_DBG_BREAK; + return 0; + } + + psRetOUT->eError = + DevInitSGXPart2KM(psPerProc, + hDevCookieInt, + &psSGXDevInitPart2IN->sInitInfo); + + return 0; +} + + +static IMG_INT +SGXRegisterHWRenderContextBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextIN, + PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + IMG_HANDLE hHWRenderContextInt; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT); + + NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc, 1); + + psSGXRegHWRenderContextOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psSGXRegHWRenderContextIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psSGXRegHWRenderContextOUT->eError != PVRSRV_OK) + { + return 0; + } + + hHWRenderContextInt = + SGXRegisterHWRenderContextKM(hDevCookieInt, + &psSGXRegHWRenderContextIN->sHWRenderContextDevVAddr, + psPerProc); + + if (hHWRenderContextInt == IMG_NULL) + { + psSGXRegHWRenderContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT; + return 0; + } + + PVRSRVAllocHandleNR(psPerProc->psHandleBase, + &psSGXRegHWRenderContextOUT->hHWRenderContext, + hHWRenderContextInt, + PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT, + PVRSRV_HANDLE_ALLOC_FLAG_NONE); + + COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc); + + return 0; +} + + +static IMG_INT +SGXUnregisterHWRenderContextBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT *psSGXUnregHWRenderContextIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hHWRenderContextInt; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT); + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hHWRenderContextInt, + psSGXUnregHWRenderContextIN->hHWRenderContext, + PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psRetOUT->eError = SGXUnregisterHWRenderContextKM(hHWRenderContextInt); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psRetOUT->eError = + PVRSRVReleaseHandle(psPerProc->psHandleBase, + psSGXUnregHWRenderContextIN->hHWRenderContext, + PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT); + + return 0; +} + + +static IMG_INT +SGXRegisterHWTransferContextBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextIN, + PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + IMG_HANDLE hHWTransferContextInt; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT); + + NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc, 1); + + psSGXRegHWTransferContextOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psSGXRegHWTransferContextIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psSGXRegHWTransferContextOUT->eError != PVRSRV_OK) + { + return 0; + } + + hHWTransferContextInt = + SGXRegisterHWTransferContextKM(hDevCookieInt, + &psSGXRegHWTransferContextIN->sHWTransferContextDevVAddr, + psPerProc); + + if (hHWTransferContextInt == IMG_NULL) + { + psSGXRegHWTransferContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT; + return 0; + } + + PVRSRVAllocHandleNR(psPerProc->psHandleBase, + &psSGXRegHWTransferContextOUT->hHWTransferContext, + hHWTransferContextInt, + PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT, + PVRSRV_HANDLE_ALLOC_FLAG_NONE); + + COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc); + + return 0; +} + + +static IMG_INT +SGXUnregisterHWTransferContextBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT *psSGXUnregHWTransferContextIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hHWTransferContextInt; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT); + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hHWTransferContextInt, + psSGXUnregHWTransferContextIN->hHWTransferContext, + PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psRetOUT->eError = SGXUnregisterHWTransferContextKM(hHWTransferContextInt); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psRetOUT->eError = + PVRSRVReleaseHandle(psPerProc->psHandleBase, + psSGXUnregHWTransferContextIN->hHWTransferContext, + PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT); + + return 0; +} + + +#if defined(SGX_FEATURE_2D_HARDWARE) +static IMG_INT +SGXRegisterHW2DContextBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextIN, + PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + IMG_HANDLE hHW2DContextInt; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT); + + NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc, 1); + + psSGXRegHW2DContextOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psSGXRegHW2DContextIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psSGXRegHW2DContextOUT->eError != PVRSRV_OK) + { + return 0; + } + + hHW2DContextInt = + SGXRegisterHW2DContextKM(hDevCookieInt, + &psSGXRegHW2DContextIN->sHW2DContextDevVAddr, + psPerProc); + + if (hHW2DContextInt == IMG_NULL) + { + psSGXRegHW2DContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT; + return 0; + } + + PVRSRVAllocHandleNR(psPerProc->psHandleBase, + &psSGXRegHW2DContextOUT->hHW2DContext, + hHW2DContextInt, + PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT, + PVRSRV_HANDLE_ALLOC_FLAG_NONE); + + COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc); + + return 0; +} + + +static IMG_INT +SGXUnregisterHW2DContextBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT *psSGXUnregHW2DContextIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hHW2DContextInt; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT); + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hHW2DContextInt, + psSGXUnregHW2DContextIN->hHW2DContext, + PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psRetOUT->eError = SGXUnregisterHW2DContextKM(hHW2DContextInt); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psRetOUT->eError = + PVRSRVReleaseHandle(psPerProc->psHandleBase, + psSGXUnregHW2DContextIN->hHW2DContext, + PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT); + + return 0; +} +#endif + +static IMG_INT +SGXFlushHWRenderTargetBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET *psSGXFlushHWRenderTargetIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET); + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psSGXFlushHWRenderTargetIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + SGXFlushHWRenderTargetKM(hDevCookieInt, psSGXFlushHWRenderTargetIN->sHWRTDataSetDevVAddr); + + return 0; +} + + +static IMG_INT +SGX2DQueryBlitsCompleteBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE *ps2DQueryBltsCompleteIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + IMG_VOID *pvSyncInfo; + PVRSRV_SGXDEV_INFO *psDevInfo; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE); + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt, + ps2DQueryBltsCompleteIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo, + ps2DQueryBltsCompleteIN->hKernSyncInfo, + PVRSRV_HANDLE_TYPE_SYNC_INFO); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice; + + psRetOUT->eError = + SGX2DQueryBlitsCompleteKM(psDevInfo, + (PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo, + ps2DQueryBltsCompleteIN->bWaitForComplete); + + return 0; +} + + +static IMG_INT +SGXFindSharedPBDescBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescIN, + PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo; + PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo; + PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo; + PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo; + PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos = IMG_NULL; + IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount = 0; + IMG_UINT32 i; + IMG_HANDLE hSharedPBDesc = IMG_NULL; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC); + + NEW_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc, PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS + 4); + + psSGXFindSharedPBDescOUT->hSharedPBDesc = IMG_NULL; + + psSGXFindSharedPBDescOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psSGXFindSharedPBDescIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK) + goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT; + + psSGXFindSharedPBDescOUT->eError = + SGXFindSharedPBDescKM(psPerProc, hDevCookieInt, + psSGXFindSharedPBDescIN->bLockOnFailure, + psSGXFindSharedPBDescIN->ui32TotalPBSize, + &hSharedPBDesc, + &psSharedPBDescKernelMemInfo, + &psHWPBDescKernelMemInfo, + &psBlockKernelMemInfo, + &psHWBlockKernelMemInfo, + &ppsSharedPBDescSubKernelMemInfos, + &ui32SharedPBDescSubKernelMemInfosCount); + if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK) + goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT; + + PVR_ASSERT(ui32SharedPBDescSubKernelMemInfosCount + <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS); + + psSGXFindSharedPBDescOUT->ui32SharedPBDescSubKernelMemInfoHandlesCount = + ui32SharedPBDescSubKernelMemInfosCount; + + if(hSharedPBDesc == IMG_NULL) + { + psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle = 0; + + goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT; + } + + PVRSRVAllocHandleNR(psPerProc->psHandleBase, + &psSGXFindSharedPBDescOUT->hSharedPBDesc, + hSharedPBDesc, + PVRSRV_HANDLE_TYPE_SHARED_PB_DESC, + PVRSRV_HANDLE_ALLOC_FLAG_NONE); + + + PVRSRVAllocSubHandleNR(psPerProc->psHandleBase, + &psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle, + psSharedPBDescKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO_REF, + PVRSRV_HANDLE_ALLOC_FLAG_MULTI, + psSGXFindSharedPBDescOUT->hSharedPBDesc); + + PVRSRVAllocSubHandleNR(psPerProc->psHandleBase, + &psSGXFindSharedPBDescOUT->hHWPBDescKernelMemInfoHandle, + psHWPBDescKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO_REF, + PVRSRV_HANDLE_ALLOC_FLAG_MULTI, + psSGXFindSharedPBDescOUT->hSharedPBDesc); + + PVRSRVAllocSubHandleNR(psPerProc->psHandleBase, + &psSGXFindSharedPBDescOUT->hBlockKernelMemInfoHandle, + psBlockKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO_REF, + PVRSRV_HANDLE_ALLOC_FLAG_MULTI, + psSGXFindSharedPBDescOUT->hSharedPBDesc); + + PVRSRVAllocSubHandleNR(psPerProc->psHandleBase, + &psSGXFindSharedPBDescOUT->hHWBlockKernelMemInfoHandle, + psHWBlockKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO_REF, + PVRSRV_HANDLE_ALLOC_FLAG_MULTI, + psSGXFindSharedPBDescOUT->hSharedPBDesc); + + + for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++) + { + PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOut = + psSGXFindSharedPBDescOUT; + + PVRSRVAllocSubHandleNR(psPerProc->psHandleBase, + &psSGXFindSharedPBDescOut->ahSharedPBDescSubKernelMemInfoHandles[i], + ppsSharedPBDescSubKernelMemInfos[i], + PVRSRV_HANDLE_TYPE_MEM_INFO_REF, + PVRSRV_HANDLE_ALLOC_FLAG_MULTI, + psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle); + } + +PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT: + if (ppsSharedPBDescSubKernelMemInfos != IMG_NULL) + { + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount, + ppsSharedPBDescSubKernelMemInfos, + IMG_NULL); + } + + if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK) + { + if(hSharedPBDesc != IMG_NULL) + { + SGXUnrefSharedPBDescKM(hSharedPBDesc); + } + } + else + { + COMMIT_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc); + } + + return 0; +} + + +static IMG_INT +SGXUnrefSharedPBDescBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescIN, + PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hSharedPBDesc; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC); + + psSGXUnrefSharedPBDescOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, + &hSharedPBDesc, + psSGXUnrefSharedPBDescIN->hSharedPBDesc, + PVRSRV_HANDLE_TYPE_SHARED_PB_DESC); + if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK) + { + return 0; + } + + psSGXUnrefSharedPBDescOUT->eError = + SGXUnrefSharedPBDescKM(hSharedPBDesc); + + if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK) + { + return 0; + } + + psSGXUnrefSharedPBDescOUT->eError = + PVRSRVReleaseHandle(psPerProc->psHandleBase, + psSGXUnrefSharedPBDescIN->hSharedPBDesc, + PVRSRV_HANDLE_TYPE_SHARED_PB_DESC); + + return 0; +} + + +static IMG_INT +SGXAddSharedPBDescBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescIN, + PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo; + PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo; + PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo; + PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo; + IMG_UINT32 ui32KernelMemInfoHandlesCount = + psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount; + IMG_INT ret = 0; + IMG_HANDLE *phKernelMemInfoHandles = IMG_NULL; + PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfos = IMG_NULL; + IMG_UINT32 i; + PVRSRV_ERROR eError; + IMG_HANDLE hSharedPBDesc = IMG_NULL; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC); + + NEW_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc, 1); + + psSGXAddSharedPBDescOUT->hSharedPBDesc = IMG_NULL; + + PVR_ASSERT(ui32KernelMemInfoHandlesCount + <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS); + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &hDevCookieInt, + psSGXAddSharedPBDescIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(eError != PVRSRV_OK) + { + goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT; + } + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + (IMG_VOID **)&psSharedPBDescKernelMemInfo, + psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo, + PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO); + if(eError != PVRSRV_OK) + { + goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT; + } + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + (IMG_VOID **)&psHWPBDescKernelMemInfo, + psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if(eError != PVRSRV_OK) + { + goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT; + } + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + (IMG_VOID **)&psBlockKernelMemInfo, + psSGXAddSharedPBDescIN->hBlockKernelMemInfo, + PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO); + if(eError != PVRSRV_OK) + { + goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT; + } + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + (IMG_VOID **)&psHWBlockKernelMemInfo, + psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + if(eError != PVRSRV_OK) + { + goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT; + } + + + if(!OSAccessOK(PVR_VERIFY_READ, + psSGXAddSharedPBDescIN->phKernelMemInfoHandles, + ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE))) + { + PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC:" + " Invalid phKernelMemInfos pointer", __FUNCTION__)); + ret = -EFAULT; + goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT; + } + + eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE), + (IMG_VOID **)&phKernelMemInfoHandles, + 0, + "Array of Handles"); + if (eError != PVRSRV_OK) + { + goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT; + } + + if(CopyFromUserWrapper(psPerProc, + ui32BridgeID, + phKernelMemInfoHandles, + psSGXAddSharedPBDescIN->phKernelMemInfoHandles, + ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE)) + != PVRSRV_OK) + { + ret = -EFAULT; + goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT; + } + + eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *), + (IMG_VOID **)&ppsKernelMemInfos, + 0, + "Array of pointers to Kernel Memory Info"); + if (eError != PVRSRV_OK) + { + goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT; + } + + for(i=0; i<ui32KernelMemInfoHandlesCount; i++) + { + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + (IMG_VOID **)&ppsKernelMemInfos[i], + phKernelMemInfoHandles[i], + PVRSRV_HANDLE_TYPE_MEM_INFO); + if(eError != PVRSRV_OK) + { + goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT; + } + } + + + + eError = PVRSRVReleaseHandle(psPerProc->psHandleBase, + psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo, + PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO); + PVR_ASSERT(eError == PVRSRV_OK); + + + eError = PVRSRVReleaseHandle(psPerProc->psHandleBase, + psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + PVR_ASSERT(eError == PVRSRV_OK); + + + eError = PVRSRVReleaseHandle(psPerProc->psHandleBase, + psSGXAddSharedPBDescIN->hBlockKernelMemInfo, + PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO); + PVR_ASSERT(eError == PVRSRV_OK); + + + eError = PVRSRVReleaseHandle(psPerProc->psHandleBase, + psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + PVR_ASSERT(eError == PVRSRV_OK); + + for(i=0; i<ui32KernelMemInfoHandlesCount; i++) + { + + eError = PVRSRVReleaseHandle(psPerProc->psHandleBase, + phKernelMemInfoHandles[i], + PVRSRV_HANDLE_TYPE_MEM_INFO); + PVR_ASSERT(eError == PVRSRV_OK); + } + + eError = SGXAddSharedPBDescKM(psPerProc, hDevCookieInt, + psSharedPBDescKernelMemInfo, + psHWPBDescKernelMemInfo, + psBlockKernelMemInfo, + psHWBlockKernelMemInfo, + psSGXAddSharedPBDescIN->ui32TotalPBSize, + &hSharedPBDesc, + ppsKernelMemInfos, + ui32KernelMemInfoHandlesCount); + + + if (eError != PVRSRV_OK) + { + goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT; + } + + PVRSRVAllocHandleNR(psPerProc->psHandleBase, + &psSGXAddSharedPBDescOUT->hSharedPBDesc, + hSharedPBDesc, + PVRSRV_HANDLE_TYPE_SHARED_PB_DESC, + PVRSRV_HANDLE_ALLOC_FLAG_NONE); + +PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT: + + if(phKernelMemInfoHandles) + { + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE), + (IMG_VOID *)phKernelMemInfoHandles, + 0); + } + if(ppsKernelMemInfos) + { + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *), + (IMG_VOID *)ppsKernelMemInfos, + 0); + } + + if(ret == 0 && eError == PVRSRV_OK) + { + COMMIT_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc); + } + + psSGXAddSharedPBDescOUT->eError = eError; + + return ret; +} + +static IMG_INT +SGXGetInfoForSrvinitBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitIN, + PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_HANDLE hDevCookieInt; + IMG_UINT32 i; + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT); + + NEW_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS); + + if(!psPerProc->bInitProcess) + { + psSGXInfoForSrvinitOUT->eError = PVRSRV_ERROR_PROCESS_NOT_INITIALISED; + return 0; + } + + psSGXInfoForSrvinitOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt, + psSGXInfoForSrvinitIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + + if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK) + { + return 0; + } + + psSGXInfoForSrvinitOUT->eError = + SGXGetInfoForSrvinitKM(hDevCookieInt, + &psSGXInfoForSrvinitOUT->sInitInfo); + + if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK) + { + return 0; + } + + for(i = 0; i < PVRSRV_MAX_CLIENT_HEAPS; i++) + { + PVRSRV_HEAP_INFO *psHeapInfo; + + psHeapInfo = &psSGXInfoForSrvinitOUT->sInitInfo.asHeapInfo[i]; + + if (psHeapInfo->ui32HeapID != (IMG_UINT32)SGX_UNDEFINED_HEAP_ID) + { + IMG_HANDLE hDevMemHeapExt; + + if (psHeapInfo->hDevMemHeap != IMG_NULL) + { + + PVRSRVAllocHandleNR(psPerProc->psHandleBase, + &hDevMemHeapExt, + psHeapInfo->hDevMemHeap, + PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP, + PVRSRV_HANDLE_ALLOC_FLAG_SHARED); + psHeapInfo->hDevMemHeap = hDevMemHeapExt; + } + } + } + + COMMIT_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc); + + return 0; +} + +#if defined(PDUMP) +static IMG_VOID +DumpBufferArray(PVRSRV_PER_PROCESS_DATA *psPerProc, + PSGX_KICKTA_DUMP_BUFFER psBufferArray, + IMG_UINT32 ui32BufferArrayLength, + IMG_BOOL bDumpPolls) +{ + IMG_UINT32 i; + + for (i=0; i<ui32BufferArrayLength; i++) + { + PSGX_KICKTA_DUMP_BUFFER psBuffer; + PVRSRV_KERNEL_MEM_INFO *psCtrlMemInfoKM; + IMG_CHAR * pszName; + IMG_HANDLE hUniqueTag; + IMG_UINT32 ui32Offset; + + psBuffer = &psBufferArray[i]; + pszName = psBuffer->pszName; + if (!pszName) + { + pszName = "Nameless buffer"; + } + + hUniqueTag = MAKEUNIQUETAG((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo); + + #if defined(SUPPORT_SGX_NEW_STATUS_VALS) + psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hCtrlKernelMemInfo); + ui32Offset = psBuffer->sCtrlDevVAddr.uiAddr - psCtrlMemInfoKM->sDevVAddr.uiAddr; + #else + psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo)->psKernelSyncInfo->psSyncDataMemInfoKM; + ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete); + #endif + + if (psBuffer->ui32Start <= psBuffer->ui32End) + { + if (bDumpPolls) + { + PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName); + PDUMPCBP(psCtrlMemInfoKM, + ui32Offset, + psBuffer->ui32Start, + psBuffer->ui32SpaceUsed, + psBuffer->ui32BufferSize, + 0, + MAKEUNIQUETAG(psCtrlMemInfoKM)); + } + + PDUMPCOMMENTWITHFLAGS(0, "%s\r\n", pszName); + PDUMPMEMUM(psPerProc, + IMG_NULL, + psBuffer->pvLinAddr, + (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo, + psBuffer->ui32Start, + psBuffer->ui32End - psBuffer->ui32Start, + 0, + hUniqueTag); + } + else + { + + + if (bDumpPolls) + { + PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName); + PDUMPCBP(psCtrlMemInfoKM, + ui32Offset, + psBuffer->ui32Start, + psBuffer->ui32BackEndLength, + psBuffer->ui32BufferSize, + 0, + MAKEUNIQUETAG(psCtrlMemInfoKM)); + } + PDUMPCOMMENTWITHFLAGS(0, "%s (part 1)\r\n", pszName); + PDUMPMEMUM(psPerProc, + IMG_NULL, + psBuffer->pvLinAddr, + (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo, + psBuffer->ui32Start, + psBuffer->ui32BackEndLength, + 0, + hUniqueTag); + + if (bDumpPolls) + { + PDUMPMEMPOL(psCtrlMemInfoKM, + ui32Offset, + 0, + 0xFFFFFFFF, + PDUMP_POLL_OPERATOR_NOTEQUAL, + 0, + MAKEUNIQUETAG(psCtrlMemInfoKM)); + + PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName); + PDUMPCBP(psCtrlMemInfoKM, + ui32Offset, + 0, + psBuffer->ui32End, + psBuffer->ui32BufferSize, + 0, + MAKEUNIQUETAG(psCtrlMemInfoKM)); + } + PDUMPCOMMENTWITHFLAGS(0, "%s (part 2)\r\n", pszName); + PDUMPMEMUM(psPerProc, + IMG_NULL, + psBuffer->pvLinAddr, + (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo, + 0, + psBuffer->ui32End, + 0, + hUniqueTag); + } + } +} +static IMG_INT +SGXPDumpBufferArrayBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY *psPDumpBufferArrayIN, + IMG_VOID *psBridgeOut, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_UINT32 i; + SGX_KICKTA_DUMP_BUFFER *psKickTADumpBuffer; + IMG_UINT32 ui32BufferArrayLength = + psPDumpBufferArrayIN->ui32BufferArrayLength; + IMG_UINT32 ui32BufferArraySize = + ui32BufferArrayLength * sizeof(SGX_KICKTA_DUMP_BUFFER); + PVRSRV_ERROR eError = PVRSRV_ERROR_TOO_FEW_BUFFERS; + + PVR_UNREFERENCED_PARAMETER(psBridgeOut); + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY); + + if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32BufferArraySize, + (IMG_PVOID *)&psKickTADumpBuffer, 0, + "Array of Kick Tile Accelerator Dump Buffer") != PVRSRV_OK) + { + return -ENOMEM; + } + + if(CopyFromUserWrapper(psPerProc, + ui32BridgeID, + psKickTADumpBuffer, + psPDumpBufferArrayIN->psBufferArray, + ui32BufferArraySize) != PVRSRV_OK) + { + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0); + + return -EFAULT; + } + + for(i = 0; i < ui32BufferArrayLength; i++) + { + IMG_VOID *pvMemInfo; + + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &pvMemInfo, + psKickTADumpBuffer[i].hKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + + if(eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: " + "PVRSRVLookupHandle failed (%d)", eError)); + break; + } + psKickTADumpBuffer[i].hKernelMemInfo = pvMemInfo; + +#if defined(SUPPORT_SGX_NEW_STATUS_VALS) + eError = PVRSRVLookupHandle(psPerProc->psHandleBase, + &pvMemInfo, + psKickTADumpBuffer[i].hCtrlKernelMemInfo, + PVRSRV_HANDLE_TYPE_MEM_INFO); + + if(eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: " + "PVRSRVLookupHandle failed (%d)", eError)); + break; + } + psKickTADumpBuffer[i].hCtrlKernelMemInfo = pvMemInfo; +#endif + } + + if(eError == PVRSRV_OK) + { + DumpBufferArray(psPerProc, + psKickTADumpBuffer, + ui32BufferArrayLength, + psPDumpBufferArrayIN->bDumpPolls); + } + + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0); + + + return 0; +} + +static IMG_INT +SGXPDump3DSignatureRegistersBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS *psPDump3DSignatureRegistersIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_UINT32 ui32RegisterArraySize = psPDump3DSignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32); + IMG_UINT32 *pui32Registers = IMG_NULL; + PVRSRV_SGXDEV_INFO *psDevInfo = IMG_NULL; +#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270) + IMG_UINT32 ui32RegVal = 0; +#endif + PVRSRV_DEVICE_NODE *psDeviceNode; + IMG_INT ret = -EFAULT; + + PVR_UNREFERENCED_PARAMETER(psRetOUT); + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS); + + if (ui32RegisterArraySize == 0) + { + goto ExitNoError; + } + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode, + psPDump3DSignatureRegistersIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psRetOUT->eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed")); + goto Exit; + } + + psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice; + +#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270) + + ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT); +#if defined(PDUMP) + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT, + psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0); +#endif +#endif + + if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32RegisterArraySize, + (IMG_PVOID *)&pui32Registers, 0, + "Array of Registers") != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: OSAllocMem failed")); + goto Exit; + } + + if(CopyFromUserWrapper(psPerProc, + ui32BridgeID, + pui32Registers, + psPDump3DSignatureRegistersIN->pui32Registers, + ui32RegisterArraySize) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: CopyFromUserWrapper failed")); + goto Exit; + } + + PDump3DSignatureRegisters(&psDeviceNode->sDevId, + psPDump3DSignatureRegistersIN->ui32DumpFrameNum, + psPDump3DSignatureRegistersIN->bLastFrame, + pui32Registers, + psPDump3DSignatureRegistersIN->ui32NumRegisters); + + PDumpSignatureBuffer(&psDeviceNode->sDevId, + "out.tasig", "TA", 0, + psDevInfo->psKernelTASigBufferMemInfo->sDevVAddr, + psDevInfo->psKernelTASigBufferMemInfo->ui32AllocSize, + 0 ); + PDumpSignatureBuffer(&psDeviceNode->sDevId, + "out.3dsig", "3D", 0, + psDevInfo->psKernel3DSigBufferMemInfo->sDevVAddr, + psDevInfo->psKernel3DSigBufferMemInfo->ui32AllocSize, + 0 ); + +ExitNoError: + psRetOUT->eError = PVRSRV_OK; + ret = 0; +Exit: + if (pui32Registers != IMG_NULL) + { + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0); + } + +#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270) + if (psDevInfo != IMG_NULL) + { + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal); +#if defined(PDUMP) + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, ui32RegVal, + psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0); +#endif + } +#endif + + return ret; +} + +static IMG_INT +SGXPDumpCounterRegistersBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS *psPDumpCounterRegistersIN, + IMG_VOID *psBridgeOut, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_UINT32 ui32RegisterArraySize = psPDumpCounterRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32); + IMG_UINT32 *pui32Registers = IMG_NULL; + PVRSRV_DEVICE_NODE *psDeviceNode; + IMG_INT ret = -EFAULT; + + PVR_UNREFERENCED_PARAMETER(psBridgeOut); + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS); + + if (ui32RegisterArraySize == 0) + { + goto ExitNoError; + } + + if(PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode, + psPDumpCounterRegistersIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "SGXPDumpCounterRegistersBW: hDevCookie lookup failed")); + ret = -ENOMEM; + goto Exit; + } + + if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32RegisterArraySize, + (IMG_PVOID *)&pui32Registers, 0, + "Array of Registers") != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: OSAllocMem failed")); + ret = -ENOMEM; + goto Exit; + } + + if(CopyFromUserWrapper(psPerProc, + ui32BridgeID, + pui32Registers, + psPDumpCounterRegistersIN->pui32Registers, + ui32RegisterArraySize) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: CopyFromUserWrapper failed")); + goto Exit; + } + + PDumpCounterRegisters(&psDeviceNode->sDevId, + psPDumpCounterRegistersIN->ui32DumpFrameNum, + psPDumpCounterRegistersIN->bLastFrame, + pui32Registers, + psPDumpCounterRegistersIN->ui32NumRegisters); + +ExitNoError: + ret = 0; +Exit: + if (pui32Registers != IMG_NULL) + { + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0); + } + + return ret; +} + +static IMG_INT +SGXPDumpTASignatureRegistersBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS *psPDumpTASignatureRegistersIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + IMG_UINT32 ui32RegisterArraySize = psPDumpTASignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32); + IMG_UINT32 *pui32Registers = IMG_NULL; +#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270) + PVRSRV_SGXDEV_INFO *psDevInfo = IMG_NULL; + IMG_UINT32 ui32RegVal = 0; +#endif + PVRSRV_DEVICE_NODE *psDeviceNode; + IMG_INT ret = -EFAULT; + + PVR_UNREFERENCED_PARAMETER(psRetOUT); + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS); + + if (ui32RegisterArraySize == 0) + { + goto ExitNoError; + } + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode, + psPDumpTASignatureRegistersIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psRetOUT->eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed")); + goto Exit; + } + +#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270) + + psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice; + + + ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT); +#if defined(PDUMP) + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT, + psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0); +#endif +#endif + + if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32RegisterArraySize, + (IMG_PVOID *)&pui32Registers, 0, + "Array of Registers") != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: OSAllocMem failed")); + ret = -ENOMEM; + goto Exit; + } + + if(CopyFromUserWrapper(psPerProc, + ui32BridgeID, + pui32Registers, + psPDumpTASignatureRegistersIN->pui32Registers, + ui32RegisterArraySize) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: CopyFromUserWrapper failed")); + goto Exit; + } + + PDumpTASignatureRegisters(&psDeviceNode->sDevId, + psPDumpTASignatureRegistersIN->ui32DumpFrameNum, + psPDumpTASignatureRegistersIN->ui32TAKickCount, + psPDumpTASignatureRegistersIN->bLastFrame, + pui32Registers, + psPDumpTASignatureRegistersIN->ui32NumRegisters); + +ExitNoError: + psRetOUT->eError = PVRSRV_OK; + ret = 0; +Exit: + if (pui32Registers != IMG_NULL) + { + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0); + } + +#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270) + if (psDevInfo != IMG_NULL) + { + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal); +#if defined(PDUMP) + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, ui32RegVal, + psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0); +#endif + } +#endif + + return ret; +} +static IMG_INT +SGXPDumpHWPerfCBBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB *psPDumpHWPerfCBIN, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ +#if defined(SUPPORT_SGX_HWPERF) +#if defined(__linux__) + PVRSRV_SGXDEV_INFO *psDevInfo; + PVRSRV_DEVICE_NODE *psDeviceNode; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB); + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode, + psPDumpHWPerfCBIN->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + psDevInfo = psDeviceNode->pvDevice; + + PDumpHWPerfCBKM(&psDeviceNode->sDevId, + &psPDumpHWPerfCBIN->szFileName[0], + psPDumpHWPerfCBIN->ui32FileOffset, + psDevInfo->psKernelHWPerfCBMemInfo->sDevVAddr, + psDevInfo->psKernelHWPerfCBMemInfo->ui32AllocSize, + psPDumpHWPerfCBIN->ui32PDumpFlags); + + return 0; +#else + PVR_UNREFERENCED_PARAMETER(ui32BridgeID); + PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN); + PVR_UNREFERENCED_PARAMETER(psRetOUT); + PVR_UNREFERENCED_PARAMETER(psPerProc); + return 0; +#endif +#else + PVR_UNREFERENCED_PARAMETER(ui32BridgeID); + PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN); + PVR_UNREFERENCED_PARAMETER(psRetOUT); + PVR_UNREFERENCED_PARAMETER(psPerProc); + return -EFAULT; +#endif +} + + +static IMG_INT +SGXPDumpSaveMemBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM *psPDumpSaveMem, + PVRSRV_BRIDGE_RETURN *psRetOUT, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + PVRSRV_DEVICE_NODE *psDeviceNode; + + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM); + + psRetOUT->eError = + PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode, + psPDumpSaveMem->hDevCookie, + PVRSRV_HANDLE_TYPE_DEV_NODE); + if(psRetOUT->eError != PVRSRV_OK) + { + return 0; + } + + PDumpSaveMemKM(&psDeviceNode->sDevId, + &psPDumpSaveMem->szFileName[0], + psPDumpSaveMem->ui32FileOffset, + psPDumpSaveMem->sDevVAddr, + psPDumpSaveMem->ui32Size, + psPDumpSaveMem->ui32DataMaster, + psPDumpSaveMem->ui32PDumpFlags); + return 0; +} + +#endif + + + +IMG_VOID SetSGXDispatchTableEntry(IMG_VOID) +{ + + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETCLIENTINFO, SGXGetClientInfoBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO, SGXReleaseClientInfoBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO, SGXGetInternalDevInfoBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DOKICK, SGXDoKickBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR, DummyBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READREGISTRYDWORD, DummyBW); + + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE, SGX2DQueryBlitsCompleteBW); + + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMMUPDADDR, DummyBW); + +#if defined(TRANSFER_QUEUE) + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMITTRANSFER, SGXSubmitTransferBW); +#endif + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMISCINFO, SGXGetMiscInfoBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT , SGXGetInfoForSrvinitBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DEVINITPART2, SGXDevInitPart2BW); + + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC, SGXFindSharedPBDescBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC, SGXUnrefSharedPBDescBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC, SGXAddSharedPBDescBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT, SGXRegisterHWRenderContextBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET, SGXFlushHWRenderTargetBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT, SGXUnregisterHWRenderContextBW); +#if defined(SGX_FEATURE_2D_HARDWARE) + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMIT2D, SGXSubmit2DBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT, SGXRegisterHW2DContextBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT, SGXUnregisterHW2DContextBW); +#endif + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT, SGXRegisterHWTransferContextBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT, SGXUnregisterHWTransferContextBW); + + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES, SGXScheduleProcessQueuesBW); + + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READ_HWPERF_CB, SGXReadHWPerfCBBW); + +#if defined(PDUMP) + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY, SGXPDumpBufferArrayBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS, SGXPDump3DSignatureRegistersBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS, SGXPDumpCounterRegistersBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS, SGXPDumpTASignatureRegistersBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB, SGXPDumpHWPerfCBBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM, SGXPDumpSaveMemBW); +#endif +} + + +#endif diff --git a/drivers/gpu/pvr/sgx/bridged_sgx_bridge.h b/drivers/gpu/pvr/sgx/bridged_sgx_bridge.h new file mode 100644 index 0000000..de6cfd1 --- /dev/null +++ b/drivers/gpu/pvr/sgx/bridged_sgx_bridge.h @@ -0,0 +1,42 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 + * + ******************************************************************************/ + +#ifndef __BRIDGED_SGX_BRIDGE_H__ +#define __BRIDGED_SGX_BRIDGE_H__ + +#if defined (__cplusplus) +extern "C" { +#endif + + +IMG_VOID SetSGXDispatchTableEntry(IMG_VOID); + +#if defined (__cplusplus) +} +#endif + +#endif + diff --git a/drivers/gpu/pvr/sgx/mmu.c b/drivers/gpu/pvr/sgx/mmu.c new file mode 100644 index 0000000..e7d19fe --- /dev/null +++ b/drivers/gpu/pvr/sgx/mmu.c @@ -0,0 +1,3023 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 "sgxdefs.h" +#include "sgxmmu.h" +#include "services_headers.h" +#include "buffer_manager.h" +#include "hash.h" +#include "ra.h" +#include "pdump_km.h" +#include "sgxapi_km.h" +#include "sgxinfo.h" +#include "sgxinfokm.h" +#include "mmu.h" +#include "sgxconfig.h" +#include "sgx_bridge_km.h" + +#define UINT32_MAX_VALUE 0xFFFFFFFFUL + +#define SGX_MAX_PD_ENTRIES (1<<(SGX_FEATURE_ADDRESS_SPACE_SIZE - SGX_MMU_PT_SHIFT - SGX_MMU_PAGE_SHIFT)) + +typedef struct _MMU_PT_INFO_ +{ + + IMG_VOID *hPTPageOSMemHandle; + IMG_CPU_VIRTADDR PTPageCpuVAddr; + IMG_UINT32 ui32ValidPTECount; +} MMU_PT_INFO; + +struct _MMU_CONTEXT_ +{ + + PVRSRV_DEVICE_NODE *psDeviceNode; + + + IMG_CPU_VIRTADDR pvPDCpuVAddr; + IMG_DEV_PHYADDR sPDDevPAddr; + + IMG_VOID *hPDOSMemHandle; + + + MMU_PT_INFO *apsPTInfoList[SGX_MAX_PD_ENTRIES]; + + PVRSRV_SGXDEV_INFO *psDevInfo; + +#if defined(PDUMP) + IMG_UINT32 ui32PDumpMMUContextID; +#if defined(SUPPORT_PDUMP_MULTI_PROCESS) + IMG_BOOL bPDumpActive; +#endif +#endif + + struct _MMU_CONTEXT_ *psNext; +}; + +struct _MMU_HEAP_ +{ + + MMU_CONTEXT *psMMUContext; + + + + + IMG_UINT32 ui32PDBaseIndex; + + IMG_UINT32 ui32PageTableCount; + + IMG_UINT32 ui32PTETotal; + + IMG_UINT32 ui32PDEPageSizeCtrl; + + + + + IMG_UINT32 ui32DataPageSize; + + IMG_UINT32 ui32DataPageBitWidth; + + IMG_UINT32 ui32DataPageMask; + + + + + IMG_UINT32 ui32PTShift; + + IMG_UINT32 ui32PTBitWidth; + + IMG_UINT32 ui32PTMask; + + IMG_UINT32 ui32PTSize; + + IMG_UINT32 ui32PTECount; + + + + + IMG_UINT32 ui32PDShift; + + IMG_UINT32 ui32PDBitWidth; + + IMG_UINT32 ui32PDMask; + + + + RA_ARENA *psVMArena; + DEV_ARENA_DESCRIPTOR *psDevArena; +#if defined(PDUMP) + PDUMP_MMU_ATTRIB sMMUAttrib; +#endif +}; + + + +#if defined (SUPPORT_SGX_MMU_DUMMY_PAGE) +#define DUMMY_DATA_PAGE_SIGNATURE 0xDEADBEEF +#endif + +#if defined(PDUMP) +static IMG_VOID +MMU_PDumpPageTables (MMU_HEAP *pMMUHeap, + IMG_DEV_VIRTADDR DevVAddr, + IMG_SIZE_T uSize, + IMG_BOOL bForUnmap, + IMG_HANDLE hUniqueTag); +#endif + +#define PAGE_TEST 0 +#if PAGE_TEST +static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr); +#endif + +#define PT_DEBUG 0 +#if PT_DEBUG +static IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList) +{ + IMG_UINT32 *p = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr; + IMG_UINT32 i; + + + for(i = 0; i < 1024; i += 8) + { + PVR_DPF((PVR_DBG_WARNING, + "%08X %08X %08X %08X %08X %08X %08X %08X\n", + p[i + 0], p[i + 1], p[i + 2], p[i + 3], + p[i + 4], p[i + 5], p[i + 6], p[i + 7])); + } +} + +static IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList) +{ + IMG_UINT32 *p = (IMG_UINT32*) psPTInfoList->PTPageCpuVAddr; + IMG_UINT32 i, ui32Count = 0; + + + for(i = 0; i < 1024; i++) + if(p[i] & SGX_MMU_PTE_VALID) + ui32Count++; + + if(psPTInfoList->ui32ValidPTECount != ui32Count) + { + PVR_DPF((PVR_DBG_WARNING, "ui32ValidPTECount: %u ui32Count: %u\n", + psPTInfoList->ui32ValidPTECount, ui32Count)); + DumpPT(psPTInfoList); + BUG(); + } +} +#else +static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList) +{ + PVR_UNREFERENCED_PARAMETER(psPTInfoList); +} + +static INLINE IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList) +{ + PVR_UNREFERENCED_PARAMETER(psPTInfoList); +} +#endif + + +IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMUHeap) +{ + switch(pMMUHeap->psDevArena->DevMemHeapType) + { + case DEVICE_MEMORY_HEAP_SHARED : + case DEVICE_MEMORY_HEAP_SHARED_EXPORTED : + return IMG_TRUE; + case DEVICE_MEMORY_HEAP_PERCONTEXT : + case DEVICE_MEMORY_HEAP_KERNEL : + return IMG_FALSE; + default: + { + PVR_DPF((PVR_DBG_ERROR, "MMU_IsHeapShared: ERROR invalid heap type")); + return IMG_FALSE; + } + } +} + +#ifdef SUPPORT_SGX_MMU_BYPASS +IMG_VOID +EnableHostAccess (MMU_CONTEXT *psMMUContext) +{ + IMG_UINT32 ui32RegVal; + IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM; + + + + + ui32RegVal = OSReadHWReg(pvRegsBaseKM, EUR_CR_BIF_CTRL); + + OSWriteHWReg(pvRegsBaseKM, + EUR_CR_BIF_CTRL, + ui32RegVal | EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK); + + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK); +} + +IMG_VOID +DisableHostAccess (MMU_CONTEXT *psMMUContext) +{ + IMG_UINT32 ui32RegVal; + IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM; + + + + + + OSWriteHWReg(pvRegsBaseKM, + EUR_CR_BIF_CTRL, + ui32RegVal & ~EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK); + + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, 0); +} +#endif + + +#if defined(SGX_FEATURE_SYSTEM_CACHE) +static IMG_VOID MMU_InvalidateSystemLevelCache(PVRSRV_SGXDEV_INFO *psDevInfo) +{ + #if defined(SGX_FEATURE_MP) + psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL; + #else + + PVR_UNREFERENCED_PARAMETER(psDevInfo); + #endif +} +#endif + +IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo) +{ + psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD; + #if defined(SGX_FEATURE_SYSTEM_CACHE) + MMU_InvalidateSystemLevelCache(psDevInfo); + #endif +} + + +static IMG_VOID MMU_InvalidatePageTableCache(PVRSRV_SGXDEV_INFO *psDevInfo) +{ + psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PT; + #if defined(SGX_FEATURE_SYSTEM_CACHE) + MMU_InvalidateSystemLevelCache(psDevInfo); + #endif +} + + +static IMG_BOOL +_AllocPageTableMemory (MMU_HEAP *pMMUHeap, + MMU_PT_INFO *psPTInfoList, + IMG_DEV_PHYADDR *psDevPAddr) +{ + IMG_DEV_PHYADDR sDevPAddr; + IMG_CPU_PHYADDR sCpuPAddr; + + + + + if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL) + { + + if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + pMMUHeap->ui32PTSize, + SGX_MMU_PAGE_SIZE, + (IMG_VOID **)&psPTInfoList->PTPageCpuVAddr, + &psPTInfoList->hPTPageOSMemHandle) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to OSAllocPages failed")); + return IMG_FALSE; + } + + + if(psPTInfoList->PTPageCpuVAddr) + { + sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle, + psPTInfoList->PTPageCpuVAddr); + } + else + { + + sCpuPAddr = OSMemHandleToCpuPAddr(psPTInfoList->hPTPageOSMemHandle, 0); + } + + sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); + } + else + { + IMG_SYS_PHYADDR sSysPAddr; + + + + + + if(RA_Alloc(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena, + SGX_MMU_PAGE_SIZE, + IMG_NULL, + IMG_NULL, + 0, + SGX_MMU_PAGE_SIZE, + 0, + &(sSysPAddr.uiAddr))!= IMG_TRUE) + { + PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to RA_Alloc failed")); + return IMG_FALSE; + } + + + sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr); + + psPTInfoList->PTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr, + SGX_MMU_PAGE_SIZE, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + &psPTInfoList->hPTPageOSMemHandle); + if(!psPTInfoList->PTPageCpuVAddr) + { + PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR failed to map page tables")); + return IMG_FALSE; + } + + + sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); + + #if PAGE_TEST + PageTest(psPTInfoList->PTPageCpuVAddr, sDevPAddr); + #endif + } + +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + { + IMG_UINT32 *pui32Tmp; + IMG_UINT32 i; + + pui32Tmp = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr; + + for(i=0; i<pMMUHeap->ui32PTECount; i++) + { + pui32Tmp[i] = (pMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT) + | SGX_MMU_PTE_VALID; + } + } +#else + + OSMemSet(psPTInfoList->PTPageCpuVAddr, 0, pMMUHeap->ui32PTSize); +#endif + +#if defined(PDUMP) + { + IMG_UINT32 ui32Flags = 0; +#if defined(SUPPORT_PDUMP_MULTI_PROCESS) + + ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0; +#endif + + PDUMPMALLOCPAGETABLE(&pMMUHeap->psMMUContext->psDeviceNode->sDevId, psPTInfoList->hPTPageOSMemHandle, 0, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, PDUMP_PT_UNIQUETAG); + + PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfoList->hPTPageOSMemHandle, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG); + } +#endif + + + *psDevPAddr = sDevPAddr; + + return IMG_TRUE; +} + + +static IMG_VOID +_FreePageTableMemory (MMU_HEAP *pMMUHeap, MMU_PT_INFO *psPTInfoList) +{ + + + + + if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL) + { + + OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + pMMUHeap->ui32PTSize, + psPTInfoList->PTPageCpuVAddr, + psPTInfoList->hPTPageOSMemHandle); + } + else + { + IMG_SYS_PHYADDR sSysPAddr; + IMG_CPU_PHYADDR sCpuPAddr; + + + sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle, + psPTInfoList->PTPageCpuVAddr); + sSysPAddr = SysCpuPAddrToSysPAddr (sCpuPAddr); + + + + OSUnMapPhysToLin(psPTInfoList->PTPageCpuVAddr, + SGX_MMU_PAGE_SIZE, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + psPTInfoList->hPTPageOSMemHandle); + + + + + RA_Free (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE); + } +} + + + +static IMG_VOID +_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT) +{ + IMG_UINT32 *pui32PDEntry; + IMG_UINT32 i; + IMG_UINT32 ui32PDIndex; + SYS_DATA *psSysData; + MMU_PT_INFO **ppsPTInfoList; + + SysAcquireData(&psSysData); + + + ui32PDIndex = pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> pMMUHeap->ui32PDShift; + + + ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex]; + + { +#if PT_DEBUG + if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount > 0) + { + DumpPT(ppsPTInfoList[ui32PTIndex]); + + } +#endif + + + PVR_ASSERT(ppsPTInfoList[ui32PTIndex] == IMG_NULL || ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount == 0); + } + +#if defined(PDUMP) + { + IMG_UINT32 ui32Flags = 0; +#if defined(SUPPORT_PDUMP_MULTI_PROCESS) + ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0; +#endif + + PDUMPCOMMENT("Free page table (page count == %08X)", pMMUHeap->ui32PageTableCount); + if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr) + { + PDUMPFREEPAGETABLE(&pMMUHeap->psMMUContext->psDeviceNode->sDevId, ppsPTInfoList[ui32PTIndex]->hPTPageOSMemHandle, ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, PDUMP_PT_UNIQUETAG); + } + } +#endif + + switch(pMMUHeap->psDevArena->DevMemHeapType) + { + case DEVICE_MEMORY_HEAP_SHARED : + case DEVICE_MEMORY_HEAP_SHARED_EXPORTED : + { + + MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList; + + while(psMMUContext) + { + + pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr; + pui32PDEntry += ui32PDIndex; + +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + + pui32PDEntry[ui32PTIndex] = (psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr + >>SGX_MMU_PDE_ADDR_ALIGNSHIFT) + | SGX_MMU_PDE_PAGE_SIZE_4K + | SGX_MMU_PDE_VALID; +#else + + if(bOSFreePT) + { + pui32PDEntry[ui32PTIndex] = 0; + } +#endif + #if defined(PDUMP) + + #if defined(SUPPORT_PDUMP_MULTI_PROCESS) + if(psMMUContext->bPDumpActive) + #endif + { + PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG); + } + #endif + + psMMUContext = psMMUContext->psNext; + } + break; + } + case DEVICE_MEMORY_HEAP_PERCONTEXT : + case DEVICE_MEMORY_HEAP_KERNEL : + { + + pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr; + pui32PDEntry += ui32PDIndex; + +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + + pui32PDEntry[ui32PTIndex] = (pMMUHeap->psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr + >>SGX_MMU_PDE_ADDR_ALIGNSHIFT) + | SGX_MMU_PDE_PAGE_SIZE_4K + | SGX_MMU_PDE_VALID; +#else + + if(bOSFreePT) + { + pui32PDEntry[ui32PTIndex] = 0; + } +#endif + + + PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); + break; + } + default: + { + PVR_DPF((PVR_DBG_ERROR, "_DeferredFreePagetable: ERROR invalid heap type")); + return; + } + } + + + if(ppsPTInfoList[ui32PTIndex] != IMG_NULL) + { + if(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr != IMG_NULL) + { + IMG_PUINT32 pui32Tmp; + + pui32Tmp = (IMG_UINT32*)ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr; + + + for(i=0; + (i<pMMUHeap->ui32PTETotal) && (i<pMMUHeap->ui32PTECount); + i++) + { + pui32Tmp[i] = 0; + } + + + + if(bOSFreePT) + { + _FreePageTableMemory(pMMUHeap, ppsPTInfoList[ui32PTIndex]); + } + + + + + pMMUHeap->ui32PTETotal -= i; + } + else + { + + pMMUHeap->ui32PTETotal -= pMMUHeap->ui32PTECount; + } + + if(bOSFreePT) + { + + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(MMU_PT_INFO), + ppsPTInfoList[ui32PTIndex], + IMG_NULL); + ppsPTInfoList[ui32PTIndex] = IMG_NULL; + } + } + else + { + + pMMUHeap->ui32PTETotal -= pMMUHeap->ui32PTECount; + } + + PDUMPCOMMENT("Finished free page table (page count == %08X)", pMMUHeap->ui32PageTableCount); +} + +static IMG_VOID +_DeferredFreePageTables (MMU_HEAP *pMMUHeap) +{ + IMG_UINT32 i; +#if defined(PDUMP) + PDUMPCOMMENT("Free PTs (MMU Context ID == %u, PDBaseIndex == %u, PT count == 0x%x)", + pMMUHeap->psMMUContext->ui32PDumpMMUContextID, + pMMUHeap->ui32PDBaseIndex, + pMMUHeap->ui32PageTableCount); +#endif + for(i=0; i<pMMUHeap->ui32PageTableCount; i++) + { + _DeferredFreePageTable(pMMUHeap, i, IMG_TRUE); + } + MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo); +} + + +static IMG_BOOL +_DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size) +{ + IMG_UINT32 ui32PageTableCount; + IMG_UINT32 ui32PDIndex; + IMG_UINT32 i; + IMG_UINT32 *pui32PDEntry; + MMU_PT_INFO **ppsPTInfoList; + SYS_DATA *psSysData; + IMG_DEV_VIRTADDR sHighDevVAddr; + + +#if SGX_FEATURE_ADDRESS_SPACE_SIZE < 32 + PVR_ASSERT(DevVAddr.uiAddr < (1<<SGX_FEATURE_ADDRESS_SPACE_SIZE)); +#endif + + + SysAcquireData(&psSysData); + + + ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift; + + + + if((UINT32_MAX_VALUE - DevVAddr.uiAddr) + < (ui32Size + pMMUHeap->ui32DataPageMask + pMMUHeap->ui32PTMask)) + { + + sHighDevVAddr.uiAddr = UINT32_MAX_VALUE; + } + else + { + sHighDevVAddr.uiAddr = DevVAddr.uiAddr + + ui32Size + + pMMUHeap->ui32DataPageMask + + pMMUHeap->ui32PTMask; + } + + ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift; + + ui32PageTableCount -= ui32PDIndex; + + + pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr; + pui32PDEntry += ui32PDIndex; + + + ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex]; + +#if defined(PDUMP) + PDUMPCOMMENT("Alloc PTs (MMU Context ID == %u, PDBaseIndex == %u, Size == 0x%x)", + pMMUHeap->psMMUContext->ui32PDumpMMUContextID, + pMMUHeap->ui32PDBaseIndex, + ui32Size); + PDUMPCOMMENT("Alloc page table (page count == %08X)", ui32PageTableCount); + PDUMPCOMMENT("Page directory mods (page count == %08X)", ui32PageTableCount); +#endif + + for(i=0; i<ui32PageTableCount; i++) + { + if(ppsPTInfoList[i] == IMG_NULL) + { + OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof (MMU_PT_INFO), + (IMG_VOID **)&ppsPTInfoList[i], IMG_NULL, + "MMU Page Table Info"); + if (ppsPTInfoList[i] == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to OSAllocMem failed")); + return IMG_FALSE; + } + OSMemSet (ppsPTInfoList[i], 0, sizeof(MMU_PT_INFO)); + } + + if(ppsPTInfoList[i]->hPTPageOSMemHandle == IMG_NULL + && ppsPTInfoList[i]->PTPageCpuVAddr == IMG_NULL) + { + IMG_DEV_PHYADDR sDevPAddr; +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + IMG_UINT32 *pui32Tmp; + IMG_UINT32 j; +#else + + PVR_ASSERT(pui32PDEntry[i] == 0); +#endif + + if(_AllocPageTableMemory (pMMUHeap, ppsPTInfoList[i], &sDevPAddr) != IMG_TRUE) + { + PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to _AllocPageTableMemory failed")); + return IMG_FALSE; + } + + switch(pMMUHeap->psDevArena->DevMemHeapType) + { + case DEVICE_MEMORY_HEAP_SHARED : + case DEVICE_MEMORY_HEAP_SHARED_EXPORTED : + { + + MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList; + + while(psMMUContext) + { + + pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr; + pui32PDEntry += ui32PDIndex; + + + pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT) + | pMMUHeap->ui32PDEPageSizeCtrl + | SGX_MMU_PDE_VALID; + + #if defined(PDUMP) + + #if defined(SUPPORT_PDUMP_MULTI_PROCESS) + if(psMMUContext->bPDumpActive) + #endif + { + + PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); + } + #endif + + + psMMUContext = psMMUContext->psNext; + } + break; + } + case DEVICE_MEMORY_HEAP_PERCONTEXT : + case DEVICE_MEMORY_HEAP_KERNEL : + { + + pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT) + | pMMUHeap->ui32PDEPageSizeCtrl + | SGX_MMU_PDE_VALID; + + + PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); + break; + } + default: + { + PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR invalid heap type")); + return IMG_FALSE; + } + } + +#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) + + + + + MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo); +#endif + } + else + { + + PVR_ASSERT(pui32PDEntry[i] != 0); + } + } + + #if defined(SGX_FEATURE_SYSTEM_CACHE) + MMU_InvalidateSystemLevelCache(pMMUHeap->psMMUContext->psDevInfo); + #endif + + return IMG_TRUE; +} + + +#if defined(PDUMP) +IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext) +{ + BM_CONTEXT *pBMContext = hDevMemContext; + PVR_ASSERT(pBMContext); + return pBMContext->psMMUContext->ui32PDumpMMUContextID; +} + +static IMG_VOID MMU_SetPDumpAttribs(PDUMP_MMU_ATTRIB *psMMUAttrib, + PVRSRV_DEVICE_NODE *psDeviceNode, + IMG_UINT32 ui32DataPageMask, + IMG_UINT32 ui32PTSize) +{ + + psMMUAttrib->sDevId = psDeviceNode->sDevId; + + psMMUAttrib->pszPDRegRegion = IMG_NULL; + psMMUAttrib->ui32DataPageMask = ui32DataPageMask; + + psMMUAttrib->ui32PTEValid = SGX_MMU_PTE_VALID; + psMMUAttrib->ui32PTSize = ui32PTSize; + psMMUAttrib->ui32PTEAlignShift = SGX_MMU_PTE_ADDR_ALIGNSHIFT; + + psMMUAttrib->ui32PDEMask = SGX_MMU_PDE_ADDR_MASK; + psMMUAttrib->ui32PDEAlignShift = SGX_MMU_PDE_ADDR_ALIGNSHIFT; +} +#endif + +PVRSRV_ERROR +MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr) +{ + IMG_UINT32 *pui32Tmp; + IMG_UINT32 i; + IMG_CPU_VIRTADDR pvPDCpuVAddr; + IMG_DEV_PHYADDR sPDDevPAddr; + IMG_CPU_PHYADDR sCpuPAddr; + MMU_CONTEXT *psMMUContext; + IMG_HANDLE hPDOSMemHandle; + SYS_DATA *psSysData; + PVRSRV_SGXDEV_INFO *psDevInfo; +#if defined(PDUMP) + PDUMP_MMU_ATTRIB sMMUAttrib; +#endif + PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Initialise")); + + SysAcquireData(&psSysData); +#if defined(PDUMP) + + + MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode, + SGX_MMU_PAGE_MASK, + SGX_MMU_PT_SIZE * sizeof(IMG_UINT32)); +#endif + + OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof (MMU_CONTEXT), + (IMG_VOID **)&psMMUContext, IMG_NULL, + "MMU Context"); + if (psMMUContext == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocMem failed")); + return PVRSRV_ERROR_OUT_OF_MEMORY; + } + OSMemSet (psMMUContext, 0, sizeof(MMU_CONTEXT)); + + + psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice; + psMMUContext->psDevInfo = psDevInfo; + + + psMMUContext->psDeviceNode = psDeviceNode; + + + if(psDeviceNode->psLocalDevMemArena == IMG_NULL) + { + if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + SGX_MMU_PAGE_SIZE, + SGX_MMU_PAGE_SIZE, + &pvPDCpuVAddr, + &hPDOSMemHandle) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed")); + return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES; + } + + if(pvPDCpuVAddr) + { + sCpuPAddr = OSMapLinToCPUPhys(hPDOSMemHandle, + pvPDCpuVAddr); + } + else + { + + sCpuPAddr = OSMemHandleToCpuPAddr(hPDOSMemHandle, 0); + } + sPDDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); + + #if PAGE_TEST + PageTest(pvPDCpuVAddr, sPDDevPAddr); + #endif + +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + + if(!psDevInfo->pvMMUContextList) + { + + if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + SGX_MMU_PAGE_SIZE, + SGX_MMU_PAGE_SIZE, + &psDevInfo->pvDummyPTPageCpuVAddr, + &psDevInfo->hDummyPTPageOSMemHandle) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed")); + return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES; + } + + if(psDevInfo->pvDummyPTPageCpuVAddr) + { + sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle, + psDevInfo->pvDummyPTPageCpuVAddr); + } + else + { + + sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyPTPageOSMemHandle, 0); + } + psDevInfo->sDummyPTDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); + + + if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + SGX_MMU_PAGE_SIZE, + SGX_MMU_PAGE_SIZE, + &psDevInfo->pvDummyDataPageCpuVAddr, + &psDevInfo->hDummyDataPageOSMemHandle) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed")); + return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES; + } + + if(psDevInfo->pvDummyDataPageCpuVAddr) + { + sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle, + psDevInfo->pvDummyDataPageCpuVAddr); + } + else + { + sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyDataPageOSMemHandle, 0); + } + psDevInfo->sDummyDataDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); + } +#endif + } + else + { + IMG_SYS_PHYADDR sSysPAddr; + + + if(RA_Alloc(psDeviceNode->psLocalDevMemArena, + SGX_MMU_PAGE_SIZE, + IMG_NULL, + IMG_NULL, + 0, + SGX_MMU_PAGE_SIZE, + 0, + &(sSysPAddr.uiAddr))!= IMG_TRUE) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed")); + return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY; + } + + + sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr); + sPDDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr); + pvPDCpuVAddr = OSMapPhysToLin(sCpuPAddr, + SGX_MMU_PAGE_SIZE, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + &hPDOSMemHandle); + if(!pvPDCpuVAddr) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables")); + return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE; + } + + #if PAGE_TEST + PageTest(pvPDCpuVAddr, sPDDevPAddr); + #endif + +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + + if(!psDevInfo->pvMMUContextList) + { + + if(RA_Alloc(psDeviceNode->psLocalDevMemArena, + SGX_MMU_PAGE_SIZE, + IMG_NULL, + IMG_NULL, + 0, + SGX_MMU_PAGE_SIZE, + 0, + &(sSysPAddr.uiAddr))!= IMG_TRUE) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed")); + return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY; + } + + + sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr); + psDevInfo->sDummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr); + psDevInfo->pvDummyPTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr, + SGX_MMU_PAGE_SIZE, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + &psDevInfo->hDummyPTPageOSMemHandle); + if(!psDevInfo->pvDummyPTPageCpuVAddr) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables")); + return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE; + } + + + if(RA_Alloc(psDeviceNode->psLocalDevMemArena, + SGX_MMU_PAGE_SIZE, + IMG_NULL, + IMG_NULL, + 0, + SGX_MMU_PAGE_SIZE, + 0, + &(sSysPAddr.uiAddr))!= IMG_TRUE) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed")); + return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY; + } + + + sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr); + psDevInfo->sDummyDataDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr); + psDevInfo->pvDummyDataPageCpuVAddr = OSMapPhysToLin(sCpuPAddr, + SGX_MMU_PAGE_SIZE, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + &psDevInfo->hDummyDataPageOSMemHandle); + if(!psDevInfo->pvDummyDataPageCpuVAddr) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables")); + return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE; + } + } +#endif + } + +#if defined(PDUMP) +#if defined(SUPPORT_PDUMP_MULTI_PROCESS) + + { + PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData(); + if(psPerProc == IMG_NULL) + { + + psMMUContext->bPDumpActive = IMG_TRUE; + } + else + { + psMMUContext->bPDumpActive = psPerProc->bPDumpActive; + } + } +#endif + +#if IMG_ADDRSPACE_PHYSADDR_BITS == 32 + PDUMPCOMMENT("Alloc page directory for new MMU context (PDDevPAddr == 0x%08x)", + sPDDevPAddr.uiAddr); +#else + PDUMPCOMMENT("Alloc page directory for new MMU context, 64-bit arch detected (PDDevPAddr == 0x%08x%08x)", + sPDDevPAddr.uiHighAddr, sPDDevPAddr.uiAddr); +#endif + PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDOSMemHandle, 0, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG); +#endif +#ifdef SUPPORT_SGX_MMU_BYPASS + EnableHostAccess(psMMUContext); +#endif + + if (pvPDCpuVAddr) + { + pui32Tmp = (IMG_UINT32 *)pvPDCpuVAddr; + } + else + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: pvPDCpuVAddr invalid")); + return PVRSRV_ERROR_INVALID_CPU_ADDR; + } + +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + + for(i=0; i<SGX_MMU_PD_SIZE; i++) + { + pui32Tmp[i] = (psDevInfo->sDummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT) + | SGX_MMU_PDE_PAGE_SIZE_4K + | SGX_MMU_PDE_VALID; + } + + if(!psDevInfo->pvMMUContextList) + { + + + + pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyPTPageCpuVAddr; + for(i=0; i<SGX_MMU_PT_SIZE; i++) + { + pui32Tmp[i] = (psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT) + | SGX_MMU_PTE_VALID; + } + + PDUMPCOMMENT("Dummy Page table contents"); + PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hDummyPTOSMemHandle, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); + + + + pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyDataPageCpuVAddr; + for(i=0; i<(SGX_MMU_PAGE_SIZE/4); i++) + { + pui32Tmp[i] = DUMMY_DATA_PAGE_SIGNATURE; + } + + PDUMPCOMMENT("Dummy Data Page contents"); + PDUMPMEMPTENTRIES(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->hDummyDataPageOSMemHandle, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); + } +#else + + for(i=0; i<SGX_MMU_PD_SIZE; i++) + { + + pui32Tmp[i] = 0; + } +#endif + +#if defined(PDUMP) +#if defined(SUPPORT_PDUMP_MULTI_PROCESS) + if(psMMUContext->bPDumpActive) +#endif + { + + PDUMPCOMMENT("Page directory contents"); + PDUMPPDENTRIES(&sMMUAttrib, hPDOSMemHandle, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); + } + + + { + PVRSRV_ERROR eError; + + IMG_UINT32 ui32MMUType = 1; + + #if defined(SGX_FEATURE_36BIT_MMU) + ui32MMUType = 3; + #else + #if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE) + ui32MMUType = 2; + #endif + #endif + + eError = PDumpSetMMUContext(PVRSRV_DEVICE_TYPE_SGX, + psDeviceNode->sDevId.pszPDumpDevName, + &psMMUContext->ui32PDumpMMUContextID, + ui32MMUType, + PDUMP_PT_UNIQUETAG, + hPDOSMemHandle, + pvPDCpuVAddr); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to PDumpSetMMUContext failed")); + return eError; + } + } + + + PDUMPCOMMENT("Set MMU context complete (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID); +#endif + + + psMMUContext->pvPDCpuVAddr = pvPDCpuVAddr; + psMMUContext->sPDDevPAddr = sPDDevPAddr; + psMMUContext->hPDOSMemHandle = hPDOSMemHandle; + + + *ppsMMUContext = psMMUContext; + + + *psPDDevPAddr = sPDDevPAddr; + + + psMMUContext->psNext = (MMU_CONTEXT*)psDevInfo->pvMMUContextList; + psDevInfo->pvMMUContextList = (IMG_VOID*)psMMUContext; + +#ifdef SUPPORT_SGX_MMU_BYPASS + DisableHostAccess(psMMUContext); +#endif + + return PVRSRV_OK; +} + +IMG_VOID +MMU_Finalise (MMU_CONTEXT *psMMUContext) +{ + IMG_UINT32 *pui32Tmp, i; + SYS_DATA *psSysData; + MMU_CONTEXT **ppsMMUContext; +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psMMUContext->psDevInfo; + MMU_CONTEXT *psMMUContextList = (MMU_CONTEXT*)psDevInfo->pvMMUContextList; +#endif + + SysAcquireData(&psSysData); + +#if defined(PDUMP) + + PDUMPCOMMENT("Clear MMU context (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID); + PDUMPCLEARMMUCONTEXT(PVRSRV_DEVICE_TYPE_SGX, psMMUContext->psDeviceNode->sDevId.pszPDumpDevName, psMMUContext->ui32PDumpMMUContextID, 2); + + +#if IMG_ADDRSPACE_PHYSADDR_BITS == 32 + PDUMPCOMMENT("Free page directory (PDDevPAddr == 0x%08x)", + psMMUContext->sPDDevPAddr.uiAddr); +#else + PDUMPCOMMENT("Free page directory, 64-bit arch detected (PDDevPAddr == 0x%08x%08x)", + psMMUContext->sPDDevPAddr.uiHighAddr, psMMUContext->sPDDevPAddr.uiAddr); +#endif +#endif + + PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psMMUContext->hPDOSMemHandle, psMMUContext->pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG); +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hDummyPTPageOSMemHandle, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG); + PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hDummyDataPageOSMemHandle, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG); +#endif + + pui32Tmp = (IMG_UINT32 *)psMMUContext->pvPDCpuVAddr; + + + for(i=0; i<SGX_MMU_PD_SIZE; i++) + { + + pui32Tmp[i] = 0; + } + + + + + + if(psMMUContext->psDeviceNode->psLocalDevMemArena == IMG_NULL) + { + OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + SGX_MMU_PAGE_SIZE, + psMMUContext->pvPDCpuVAddr, + psMMUContext->hPDOSMemHandle); + +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + + if(!psMMUContextList->psNext) + { + OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + SGX_MMU_PAGE_SIZE, + psDevInfo->pvDummyPTPageCpuVAddr, + psDevInfo->hDummyPTPageOSMemHandle); + OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + SGX_MMU_PAGE_SIZE, + psDevInfo->pvDummyDataPageCpuVAddr, + psDevInfo->hDummyDataPageOSMemHandle); + } +#endif + } + else + { + IMG_SYS_PHYADDR sSysPAddr; + IMG_CPU_PHYADDR sCpuPAddr; + + + sCpuPAddr = OSMapLinToCPUPhys(psMMUContext->hPDOSMemHandle, + psMMUContext->pvPDCpuVAddr); + sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr); + + + OSUnMapPhysToLin(psMMUContext->pvPDCpuVAddr, + SGX_MMU_PAGE_SIZE, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + psMMUContext->hPDOSMemHandle); + + RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE); + +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + + if(!psMMUContextList->psNext) + { + + sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle, + psDevInfo->pvDummyPTPageCpuVAddr); + sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr); + + + OSUnMapPhysToLin(psDevInfo->pvDummyPTPageCpuVAddr, + SGX_MMU_PAGE_SIZE, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + psDevInfo->hDummyPTPageOSMemHandle); + + RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE); + + + sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyDataPageOSMemHandle, + psDevInfo->pvDummyDataPageCpuVAddr); + sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr); + + + OSUnMapPhysToLin(psDevInfo->pvDummyDataPageCpuVAddr, + SGX_MMU_PAGE_SIZE, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + psDevInfo->hDummyDataPageOSMemHandle); + + RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE); + } +#endif + } + + PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Finalise")); + + + ppsMMUContext = (MMU_CONTEXT**)&psMMUContext->psDevInfo->pvMMUContextList; + while(*ppsMMUContext) + { + if(*ppsMMUContext == psMMUContext) + { + + *ppsMMUContext = psMMUContext->psNext; + break; + } + + + ppsMMUContext = &((*ppsMMUContext)->psNext); + } + + + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_CONTEXT), psMMUContext, IMG_NULL); + +} + + +IMG_VOID +MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap) +{ + IMG_UINT32 *pui32PDCpuVAddr = (IMG_UINT32 *) psMMUContext->pvPDCpuVAddr; + IMG_UINT32 *pui32KernelPDCpuVAddr = (IMG_UINT32 *) psMMUHeap->psMMUContext->pvPDCpuVAddr; + IMG_UINT32 ui32PDEntry; +#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) + IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE; +#endif + + + pui32PDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift; + pui32KernelPDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift; + + + + +#if defined(PDUMP) + PDUMPCOMMENT("Page directory shared heap range copy"); + PDUMPCOMMENT(" (Source heap MMU Context ID == %u, PT count == 0x%x)", + psMMUHeap->psMMUContext->ui32PDumpMMUContextID, + psMMUHeap->ui32PageTableCount); + PDUMPCOMMENT(" (Destination MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID); +#endif +#ifdef SUPPORT_SGX_MMU_BYPASS + EnableHostAccess(psMMUContext); +#endif + + for (ui32PDEntry = 0; ui32PDEntry < psMMUHeap->ui32PageTableCount; ui32PDEntry++) + { +#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + + PVR_ASSERT(pui32PDCpuVAddr[ui32PDEntry] == 0); +#endif + + + pui32PDCpuVAddr[ui32PDEntry] = pui32KernelPDCpuVAddr[ui32PDEntry]; + if (pui32PDCpuVAddr[ui32PDEntry]) + { + + #if defined(PDUMP) + + #if defined(SUPPORT_PDUMP_MULTI_PROCESS) + if(psMMUContext->bPDumpActive) + #endif + { + PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID *) &pui32PDCpuVAddr[ui32PDEntry], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); + } + #endif +#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) + bInvalidateDirectoryCache = IMG_TRUE; +#endif + } + } + +#ifdef SUPPORT_SGX_MMU_BYPASS + DisableHostAccess(psMMUContext); +#endif + +#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) + if (bInvalidateDirectoryCache) + { + + + + + MMU_InvalidateDirectoryCache(psMMUContext->psDevInfo); + } +#endif +} + + +static IMG_VOID +MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap, + IMG_DEV_VIRTADDR sDevVAddr, + IMG_UINT32 ui32PageCount, + IMG_HANDLE hUniqueTag) +{ + IMG_DEV_VIRTADDR sTmpDevVAddr; + IMG_UINT32 i; + IMG_UINT32 ui32PDIndex; + IMG_UINT32 ui32PTIndex; + IMG_UINT32 *pui32Tmp; + IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE; + +#if !defined (PDUMP) + PVR_UNREFERENCED_PARAMETER(hUniqueTag); +#endif + + sTmpDevVAddr = sDevVAddr; + + for(i=0; i<ui32PageCount; i++) + { + MMU_PT_INFO **ppsPTInfoList; + + + ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift; + + + ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex]; + + { + + ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift; + + + if (!ppsPTInfoList[0]) + { + PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex )); + + + sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize; + + + continue; + } + + + pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr; + + + if (!pui32Tmp) + { + continue; + } + + CheckPT(ppsPTInfoList[0]); + + + if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID) + { + ppsPTInfoList[0]->ui32ValidPTECount--; + } + else + { + PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex )); + } + + + PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0); + +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + + pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT) + | SGX_MMU_PTE_VALID; +#else + + pui32Tmp[ui32PTIndex] = 0; +#endif + + CheckPT(ppsPTInfoList[0]); + } + + + + if (ppsPTInfoList[0] && ppsPTInfoList[0]->ui32ValidPTECount == 0) + { + _DeferredFreePageTable(psMMUHeap, ui32PDIndex - psMMUHeap->ui32PDBaseIndex, IMG_TRUE); + bInvalidateDirectoryCache = IMG_TRUE; + } + + + sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize; + } + + if(bInvalidateDirectoryCache) + { + MMU_InvalidateDirectoryCache(psMMUHeap->psMMUContext->psDevInfo); + } + else + { + MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo); + } + +#if defined(PDUMP) + MMU_PDumpPageTables(psMMUHeap, + sDevVAddr, + psMMUHeap->ui32DataPageSize * ui32PageCount, + IMG_TRUE, + hUniqueTag); +#endif +} + + +static IMG_VOID MMU_FreePageTables(IMG_PVOID pvMMUHeap, + IMG_SIZE_T ui32Start, + IMG_SIZE_T ui32End, + IMG_HANDLE hUniqueTag) +{ + MMU_HEAP *pMMUHeap = (MMU_HEAP*)pvMMUHeap; + IMG_DEV_VIRTADDR Start; + + Start.uiAddr = ui32Start; + + MMU_UnmapPagesAndFreePTs(pMMUHeap, Start, (ui32End - ui32Start) >> pMMUHeap->ui32PTShift, hUniqueTag); +} + +MMU_HEAP * +MMU_Create (MMU_CONTEXT *psMMUContext, + DEV_ARENA_DESCRIPTOR *psDevArena, + RA_ARENA **ppsVMArena, + PDUMP_MMU_ATTRIB **ppsMMUAttrib) +{ + MMU_HEAP *pMMUHeap; + IMG_UINT32 ui32ScaleSize; + + PVR_UNREFERENCED_PARAMETER(ppsMMUAttrib); + + PVR_ASSERT (psDevArena != IMG_NULL); + + if (psDevArena == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid parameter")); + return IMG_NULL; + } + + OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof (MMU_HEAP), + (IMG_VOID **)&pMMUHeap, IMG_NULL, + "MMU Heap"); + if (pMMUHeap == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to OSAllocMem failed")); + return IMG_NULL; + } + + pMMUHeap->psMMUContext = psMMUContext; + pMMUHeap->psDevArena = psDevArena; + + + + + switch(pMMUHeap->psDevArena->ui32DataPageSize) + { + case 0x1000: + ui32ScaleSize = 0; + pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4K; + break; +#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE) + case 0x4000: + ui32ScaleSize = 2; + pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_16K; + break; + case 0x10000: + ui32ScaleSize = 4; + pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_64K; + break; + case 0x40000: + ui32ScaleSize = 6; + pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_256K; + break; + case 0x100000: + ui32ScaleSize = 8; + pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_1M; + break; + case 0x400000: + ui32ScaleSize = 10; + pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4M; + break; +#endif + default: + PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid data page size")); + goto ErrorFreeHeap; + } + + + pMMUHeap->ui32DataPageSize = psDevArena->ui32DataPageSize; + pMMUHeap->ui32DataPageBitWidth = SGX_MMU_PAGE_SHIFT + ui32ScaleSize; + pMMUHeap->ui32DataPageMask = pMMUHeap->ui32DataPageSize - 1; + + pMMUHeap->ui32PTShift = pMMUHeap->ui32DataPageBitWidth; + pMMUHeap->ui32PTBitWidth = SGX_MMU_PT_SHIFT - ui32ScaleSize; + pMMUHeap->ui32PTMask = SGX_MMU_PT_MASK & (SGX_MMU_PT_MASK<<ui32ScaleSize); + pMMUHeap->ui32PTSize = (IMG_UINT32)(1UL<<pMMUHeap->ui32PTBitWidth) * sizeof(IMG_UINT32); + + if(pMMUHeap->ui32PTSize < 4 * sizeof(IMG_UINT32)) + { + pMMUHeap->ui32PTSize = 4 * sizeof(IMG_UINT32); + } + pMMUHeap->ui32PTECount = pMMUHeap->ui32PTSize >> 2; + + + pMMUHeap->ui32PDShift = pMMUHeap->ui32PTBitWidth + pMMUHeap->ui32PTShift; + pMMUHeap->ui32PDBitWidth = SGX_FEATURE_ADDRESS_SPACE_SIZE - pMMUHeap->ui32PTBitWidth - pMMUHeap->ui32DataPageBitWidth; + pMMUHeap->ui32PDMask = SGX_MMU_PD_MASK & (SGX_MMU_PD_MASK>>(32-SGX_FEATURE_ADDRESS_SPACE_SIZE)); + + + + + + if(psDevArena->BaseDevVAddr.uiAddr > (pMMUHeap->ui32DataPageMask | pMMUHeap->ui32PTMask)) + { + + + + PVR_ASSERT ((psDevArena->BaseDevVAddr.uiAddr + & (pMMUHeap->ui32DataPageMask + | pMMUHeap->ui32PTMask)) == 0); + } + + + pMMUHeap->ui32PTETotal = pMMUHeap->psDevArena->ui32Size >> pMMUHeap->ui32PTShift; + + + pMMUHeap->ui32PDBaseIndex = (pMMUHeap->psDevArena->BaseDevVAddr.uiAddr & pMMUHeap->ui32PDMask) >> pMMUHeap->ui32PDShift; + + + + + pMMUHeap->ui32PageTableCount = (pMMUHeap->ui32PTETotal + pMMUHeap->ui32PTECount - 1) + >> pMMUHeap->ui32PTBitWidth; + + + pMMUHeap->psVMArena = RA_Create(psDevArena->pszName, + psDevArena->BaseDevVAddr.uiAddr, + psDevArena->ui32Size, + IMG_NULL, + MAX(HOST_PAGESIZE(), pMMUHeap->ui32DataPageSize), + IMG_NULL, + IMG_NULL, + &MMU_FreePageTables, + pMMUHeap); + + if (pMMUHeap->psVMArena == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to RA_Create failed")); + goto ErrorFreePagetables; + } + +#if defined(PDUMP) + + MMU_SetPDumpAttribs(&pMMUHeap->sMMUAttrib, + psMMUContext->psDeviceNode, + pMMUHeap->ui32DataPageMask, + pMMUHeap->ui32PTSize); + *ppsMMUAttrib = &pMMUHeap->sMMUAttrib; + + PDUMPCOMMENT("Create MMU device from arena %s (Size == 0x%x, DataPageSize == 0x%x, BaseDevVAddr == 0x%x)", + psDevArena->pszName, + psDevArena->ui32Size, + pMMUHeap->ui32DataPageSize, + psDevArena->BaseDevVAddr.uiAddr); +#endif + +#if 0 + + if(psDevArena->ui32HeapID == SGX_TILED_HEAP_ID) + { + IMG_UINT32 ui32RegVal; + IMG_UINT32 ui32XTileStride; + + + + + + + ui32XTileStride = 2; + + ui32RegVal = (EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK + & ((psDevArena->BaseDevVAddr.uiAddr>>20) + << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT)) + |(EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK + & (((psDevArena->BaseDevVAddr.uiAddr+psDevArena->ui32Size)>>20) + << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT)) + |(EUR_CR_BIF_TILE0_CFG_MASK + & (((ui32XTileStride<<1)|8) << EUR_CR_BIF_TILE0_CFG_SHIFT)); + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_TILE0, ui32RegVal); + } +#endif + + + + *ppsVMArena = pMMUHeap->psVMArena; + + return pMMUHeap; + + +ErrorFreePagetables: + _DeferredFreePageTables (pMMUHeap); + +ErrorFreeHeap: + OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL); + + + return IMG_NULL; +} + +IMG_VOID +MMU_Delete (MMU_HEAP *pMMUHeap) +{ + if (pMMUHeap != IMG_NULL) + { + PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Delete")); + + if(pMMUHeap->psVMArena) + { + RA_Delete (pMMUHeap->psVMArena); + } + +#if defined(PDUMP) + PDUMPCOMMENT("Delete MMU device from arena %s (BaseDevVAddr == 0x%x, PT count for deferred free == 0x%x)", + pMMUHeap->psDevArena->pszName, + pMMUHeap->psDevArena->BaseDevVAddr.uiAddr, + pMMUHeap->ui32PageTableCount); +#endif + +#ifdef SUPPORT_SGX_MMU_BYPASS + EnableHostAccess(pMMUHeap->psMMUContext); +#endif + _DeferredFreePageTables (pMMUHeap); +#ifdef SUPPORT_SGX_MMU_BYPASS + DisableHostAccess(pMMUHeap->psMMUContext); +#endif + + OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL); + + } +} + +IMG_BOOL +MMU_Alloc (MMU_HEAP *pMMUHeap, + IMG_SIZE_T uSize, + IMG_SIZE_T *pActualSize, + IMG_UINT32 uFlags, + IMG_UINT32 uDevVAddrAlignment, + IMG_DEV_VIRTADDR *psDevVAddr) +{ + IMG_BOOL bStatus; + + PVR_DPF ((PVR_DBG_MESSAGE, + "MMU_Alloc: uSize=0x%x, flags=0x%x, align=0x%x", + uSize, uFlags, uDevVAddrAlignment)); + + + + if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0) + { + IMG_UINTPTR_T uiAddr; + + bStatus = RA_Alloc (pMMUHeap->psVMArena, + uSize, + pActualSize, + IMG_NULL, + 0, + uDevVAddrAlignment, + 0, + &uiAddr); + if(!bStatus) + { + PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: RA_Alloc of VMArena failed")); + PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: Alloc of DevVAddr failed from heap %s ID%d", + pMMUHeap->psDevArena->pszName, + pMMUHeap->psDevArena->ui32HeapID)); + return bStatus; + } + + psDevVAddr->uiAddr = IMG_CAST_TO_DEVVADDR_UINT(uiAddr); + } + + #ifdef SUPPORT_SGX_MMU_BYPASS + EnableHostAccess(pMMUHeap->psMMUContext); + #endif + + + bStatus = _DeferredAllocPagetables(pMMUHeap, *psDevVAddr, uSize); + + #ifdef SUPPORT_SGX_MMU_BYPASS + DisableHostAccess(pMMUHeap->psMMUContext); + #endif + + if (!bStatus) + { + PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: _DeferredAllocPagetables failed")); + PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: Failed to alloc pagetable(s) for DevVAddr 0x%8.8x from heap %s ID%d", + psDevVAddr->uiAddr, + pMMUHeap->psDevArena->pszName, + pMMUHeap->psDevArena->ui32HeapID)); + if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0) + { + + RA_Free (pMMUHeap->psVMArena, psDevVAddr->uiAddr, IMG_FALSE); + } + } + + return bStatus; +} + +IMG_VOID +MMU_Free (MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size) +{ + PVR_ASSERT (pMMUHeap != IMG_NULL); + + if (pMMUHeap == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_Free: invalid parameter")); + return; + } + + PVR_DPF((PVR_DBG_MESSAGE, "MMU_Free: Freeing DevVAddr 0x%08X from heap %s ID%d", + DevVAddr.uiAddr, + pMMUHeap->psDevArena->pszName, + pMMUHeap->psDevArena->ui32HeapID)); + + if((DevVAddr.uiAddr >= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr) && + (DevVAddr.uiAddr + ui32Size <= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr + pMMUHeap->psDevArena->ui32Size)) + { + RA_Free (pMMUHeap->psVMArena, DevVAddr.uiAddr, IMG_TRUE); + return; + } + + PVR_DPF((PVR_DBG_ERROR,"MMU_Free: Couldn't free DevVAddr %08X from heap %s ID%d (not in range of heap))", + DevVAddr.uiAddr, + pMMUHeap->psDevArena->pszName, + pMMUHeap->psDevArena->ui32HeapID)); +} + +IMG_VOID +MMU_Enable (MMU_HEAP *pMMUHeap) +{ + PVR_UNREFERENCED_PARAMETER(pMMUHeap); + +} + +IMG_VOID +MMU_Disable (MMU_HEAP *pMMUHeap) +{ + PVR_UNREFERENCED_PARAMETER(pMMUHeap); + +} + +#if defined(PDUMP) +static IMG_VOID +MMU_PDumpPageTables (MMU_HEAP *pMMUHeap, + IMG_DEV_VIRTADDR DevVAddr, + IMG_SIZE_T uSize, + IMG_BOOL bForUnmap, + IMG_HANDLE hUniqueTag) +{ + IMG_UINT32 ui32NumPTEntries; + IMG_UINT32 ui32PTIndex; + IMG_UINT32 *pui32PTEntry; + + MMU_PT_INFO **ppsPTInfoList; + IMG_UINT32 ui32PDIndex; + IMG_UINT32 ui32PTDumpCount; + + + ui32NumPTEntries = (uSize + pMMUHeap->ui32DataPageMask) >> pMMUHeap->ui32PTShift; + + + ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift; + + + ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex]; + + + ui32PTIndex = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift; + + + PDUMPCOMMENT("Page table mods (num entries == %08X) %s", ui32NumPTEntries, bForUnmap ? "(for unmap)" : ""); + + + while(ui32NumPTEntries > 0) + { + MMU_PT_INFO* psPTInfo = *ppsPTInfoList++; + + if(ui32NumPTEntries <= pMMUHeap->ui32PTECount - ui32PTIndex) + { + ui32PTDumpCount = ui32NumPTEntries; + } + else + { + ui32PTDumpCount = pMMUHeap->ui32PTECount - ui32PTIndex; + } + + if (psPTInfo) + { + IMG_UINT32 ui32Flags = 0; +#if defined(SUPPORT_PDUMP_MULTI_PROCESS) + ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0; +#endif + pui32PTEntry = (IMG_UINT32*)psPTInfo->PTPageCpuVAddr; + PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[ui32PTIndex], ui32PTDumpCount * sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag); + } + + + ui32NumPTEntries -= ui32PTDumpCount; + + + ui32PTIndex = 0; + } + + PDUMPCOMMENT("Finished page table mods %s", bForUnmap ? "(for unmap)" : ""); +} +#endif + + +static IMG_VOID +MMU_MapPage (MMU_HEAP *pMMUHeap, + IMG_DEV_VIRTADDR DevVAddr, + IMG_DEV_PHYADDR DevPAddr, + IMG_UINT32 ui32MemFlags) +{ + IMG_UINT32 ui32Index; + IMG_UINT32 *pui32Tmp; + IMG_UINT32 ui32MMUFlags = 0; + MMU_PT_INFO **ppsPTInfoList; + + + PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0); + + + + if(((PVRSRV_MEM_READ|PVRSRV_MEM_WRITE) & ui32MemFlags) == (PVRSRV_MEM_READ|PVRSRV_MEM_WRITE)) + { + + ui32MMUFlags = 0; + } + else if(PVRSRV_MEM_READ & ui32MemFlags) + { + + ui32MMUFlags |= SGX_MMU_PTE_READONLY; + } + else if(PVRSRV_MEM_WRITE & ui32MemFlags) + { + + ui32MMUFlags |= SGX_MMU_PTE_WRITEONLY; + } + + + if(PVRSRV_MEM_CACHE_CONSISTENT & ui32MemFlags) + { + ui32MMUFlags |= SGX_MMU_PTE_CACHECONSISTENT; + } + +#if !defined(FIX_HW_BRN_25503) + + if(PVRSRV_MEM_EDM_PROTECT & ui32MemFlags) + { + ui32MMUFlags |= SGX_MMU_PTE_EDMPROTECT; + } +#endif + + + + + + ui32Index = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift; + + + ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index]; + + CheckPT(ppsPTInfoList[0]); + + + ui32Index = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift; + + + pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr; + +#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + { + IMG_UINT32 uTmp = pui32Tmp[ui32Index]; + + + if (uTmp & SGX_MMU_PTE_VALID) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page is already valid for alloc at VAddr:0x%08X PDIdx:%u PTIdx:%u", + DevVAddr.uiAddr, + DevVAddr.uiAddr >> pMMUHeap->ui32PDShift, + ui32Index )); + PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page table entry value: 0x%08X", uTmp)); + PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Physical page to map: 0x%08X", DevPAddr.uiAddr)); + } + + PVR_ASSERT((uTmp & SGX_MMU_PTE_VALID) == 0); + } +#endif + + + ppsPTInfoList[0]->ui32ValidPTECount++; + + + pui32Tmp[ui32Index] = ((DevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT) + & ((~pMMUHeap->ui32DataPageMask)>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)) + | SGX_MMU_PTE_VALID + | ui32MMUFlags; + + CheckPT(ppsPTInfoList[0]); +} + + +IMG_VOID +MMU_MapScatter (MMU_HEAP *pMMUHeap, + IMG_DEV_VIRTADDR DevVAddr, + IMG_SYS_PHYADDR *psSysAddr, + IMG_SIZE_T uSize, + IMG_UINT32 ui32MemFlags, + IMG_HANDLE hUniqueTag) +{ +#if defined(PDUMP) + IMG_DEV_VIRTADDR MapBaseDevVAddr; +#endif + IMG_UINT32 uCount, i; + IMG_DEV_PHYADDR DevPAddr; + + PVR_ASSERT (pMMUHeap != IMG_NULL); + +#if defined(PDUMP) + MapBaseDevVAddr = DevVAddr; +#else + PVR_UNREFERENCED_PARAMETER(hUniqueTag); +#endif + + for (i=0, uCount=0; uCount<uSize; i++, uCount+=pMMUHeap->ui32DataPageSize) + { + IMG_SYS_PHYADDR sSysAddr; + + sSysAddr = psSysAddr[i]; + + + + PVR_ASSERT((sSysAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0); + + DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysAddr); + + MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags); + DevVAddr.uiAddr += pMMUHeap->ui32DataPageSize; + + PVR_DPF ((PVR_DBG_MESSAGE, + "MMU_MapScatter: devVAddr=%08X, SysAddr=%08X, size=0x%x/0x%x", + DevVAddr.uiAddr, sSysAddr.uiAddr, uCount, uSize)); + } + +#if defined(PDUMP) + MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag); +#endif +} + +IMG_VOID +MMU_MapPages (MMU_HEAP *pMMUHeap, + IMG_DEV_VIRTADDR DevVAddr, + IMG_SYS_PHYADDR SysPAddr, + IMG_SIZE_T uSize, + IMG_UINT32 ui32MemFlags, + IMG_HANDLE hUniqueTag) +{ + IMG_DEV_PHYADDR DevPAddr; +#if defined(PDUMP) + IMG_DEV_VIRTADDR MapBaseDevVAddr; +#endif + IMG_UINT32 uCount; + IMG_UINT32 ui32VAdvance; + IMG_UINT32 ui32PAdvance; + + PVR_ASSERT (pMMUHeap != IMG_NULL); + + PVR_DPF ((PVR_DBG_MESSAGE, "MMU_MapPages: heap:%s, heap_id:%d devVAddr=%08X, SysPAddr=%08X, size=0x%x", + pMMUHeap->psDevArena->pszName, + pMMUHeap->psDevArena->ui32HeapID, + DevVAddr.uiAddr, + SysPAddr.uiAddr, + uSize)); + + + ui32VAdvance = pMMUHeap->ui32DataPageSize; + ui32PAdvance = pMMUHeap->ui32DataPageSize; + +#if defined(PDUMP) + MapBaseDevVAddr = DevVAddr; +#else + PVR_UNREFERENCED_PARAMETER(hUniqueTag); +#endif + + DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr); + + + PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0); + +#if defined(FIX_HW_BRN_23281) + if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED) + { + ui32VAdvance *= 2; + } +#endif + + + + + if(ui32MemFlags & PVRSRV_MEM_DUMMY) + { + ui32PAdvance = 0; + } + + for (uCount=0; uCount<uSize; uCount+=ui32VAdvance) + { + MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags); + DevVAddr.uiAddr += ui32VAdvance; + DevPAddr.uiAddr += ui32PAdvance; + } + +#if defined(PDUMP) + MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag); +#endif +} + +IMG_VOID +MMU_MapShadow (MMU_HEAP *pMMUHeap, + IMG_DEV_VIRTADDR MapBaseDevVAddr, + IMG_SIZE_T uByteSize, + IMG_CPU_VIRTADDR CpuVAddr, + IMG_HANDLE hOSMemHandle, + IMG_DEV_VIRTADDR *pDevVAddr, + IMG_UINT32 ui32MemFlags, + IMG_HANDLE hUniqueTag) +{ + IMG_UINT32 i; + IMG_UINT32 uOffset = 0; + IMG_DEV_VIRTADDR MapDevVAddr; + IMG_UINT32 ui32VAdvance; + IMG_UINT32 ui32PAdvance; + +#if !defined (PDUMP) + PVR_UNREFERENCED_PARAMETER(hUniqueTag); +#endif + + PVR_DPF ((PVR_DBG_MESSAGE, + "MMU_MapShadow: DevVAddr:%08X, Bytes:0x%x, CPUVAddr:%08X", + MapBaseDevVAddr.uiAddr, + uByteSize, + (IMG_UINTPTR_T)CpuVAddr)); + + + ui32VAdvance = pMMUHeap->ui32DataPageSize; + ui32PAdvance = pMMUHeap->ui32DataPageSize; + + + PVR_ASSERT(((IMG_UINTPTR_T)CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0); + PVR_ASSERT(((IMG_UINT32)uByteSize & pMMUHeap->ui32DataPageMask) == 0); + pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr; + +#if defined(FIX_HW_BRN_23281) + if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED) + { + ui32VAdvance *= 2; + } +#endif + + + + + if(ui32MemFlags & PVRSRV_MEM_DUMMY) + { + ui32PAdvance = 0; + } + + + MapDevVAddr = MapBaseDevVAddr; + for (i=0; i<uByteSize; i+=ui32VAdvance) + { + IMG_CPU_PHYADDR CpuPAddr; + IMG_DEV_PHYADDR DevPAddr; + + if(CpuVAddr) + { + CpuPAddr = OSMapLinToCPUPhys (hOSMemHandle, + (IMG_VOID *)((IMG_UINTPTR_T)CpuVAddr + uOffset)); + } + else + { + CpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, uOffset); + } + DevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, CpuPAddr); + + + PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0); + + PVR_DPF ((PVR_DBG_MESSAGE, + "Offset=0x%x: CpuVAddr=%08X, CpuPAddr=%08X, DevVAddr=%08X, DevPAddr=%08X", + uOffset, + (IMG_UINTPTR_T)CpuVAddr + uOffset, + CpuPAddr.uiAddr, + MapDevVAddr.uiAddr, + DevPAddr.uiAddr)); + + MMU_MapPage (pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags); + + + MapDevVAddr.uiAddr += ui32VAdvance; + uOffset += ui32PAdvance; + } + +#if defined(PDUMP) + MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uByteSize, IMG_FALSE, hUniqueTag); +#endif +} + + +IMG_VOID +MMU_UnmapPages (MMU_HEAP *psMMUHeap, + IMG_DEV_VIRTADDR sDevVAddr, + IMG_UINT32 ui32PageCount, + IMG_HANDLE hUniqueTag) +{ + IMG_UINT32 uPageSize = psMMUHeap->ui32DataPageSize; + IMG_DEV_VIRTADDR sTmpDevVAddr; + IMG_UINT32 i; + IMG_UINT32 ui32PDIndex; + IMG_UINT32 ui32PTIndex; + IMG_UINT32 *pui32Tmp; + +#if !defined (PDUMP) + PVR_UNREFERENCED_PARAMETER(hUniqueTag); +#endif + + + sTmpDevVAddr = sDevVAddr; + + for(i=0; i<ui32PageCount; i++) + { + MMU_PT_INFO **ppsPTInfoList; + + + ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift; + + + ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex]; + + + ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift; + + + if (!ppsPTInfoList[0]) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: ERROR Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u", + sTmpDevVAddr.uiAddr, + sDevVAddr.uiAddr, + i, + ui32PDIndex, + ui32PTIndex)); + + + sTmpDevVAddr.uiAddr += uPageSize; + + + continue; + } + + CheckPT(ppsPTInfoList[0]); + + + pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr; + + + if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID) + { + ppsPTInfoList[0]->ui32ValidPTECount--; + } + else + { + PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u", + sTmpDevVAddr.uiAddr, + sDevVAddr.uiAddr, + i, + ui32PDIndex, + ui32PTIndex)); + PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page table entry value: 0x%08X", pui32Tmp[ui32PTIndex])); + } + + + PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0); + +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + + pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT) + | SGX_MMU_PTE_VALID; +#else + + pui32Tmp[ui32PTIndex] = 0; +#endif + + CheckPT(ppsPTInfoList[0]); + + + sTmpDevVAddr.uiAddr += uPageSize; + } + + MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo); + +#if defined(PDUMP) + MMU_PDumpPageTables (psMMUHeap, sDevVAddr, uPageSize*ui32PageCount, IMG_TRUE, hUniqueTag); +#endif +} + + +IMG_DEV_PHYADDR +MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr) +{ + IMG_UINT32 *pui32PageTable; + IMG_UINT32 ui32Index; + IMG_DEV_PHYADDR sDevPAddr; + MMU_PT_INFO **ppsPTInfoList; + + + ui32Index = sDevVPageAddr.uiAddr >> pMMUHeap->ui32PDShift; + + + ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index]; + if (!ppsPTInfoList[0]) + { + PVR_DPF((PVR_DBG_ERROR,"MMU_GetPhysPageAddr: Not mapped in at 0x%08x", sDevVPageAddr.uiAddr)); + sDevPAddr.uiAddr = 0; + return sDevPAddr; + } + + + ui32Index = (sDevVPageAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift; + + + pui32PageTable = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr; + + + sDevPAddr.uiAddr = pui32PageTable[ui32Index]; + + + sDevPAddr.uiAddr &= ~(pMMUHeap->ui32DataPageMask>>SGX_MMU_PTE_ADDR_ALIGNSHIFT); + + + sDevPAddr.uiAddr <<= SGX_MMU_PTE_ADDR_ALIGNSHIFT; + + return sDevPAddr; +} + + +IMG_DEV_PHYADDR MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext) +{ + return (pMMUContext->sPDDevPAddr); +} + + +IMG_EXPORT +PVRSRV_ERROR SGXGetPhysPageAddrKM (IMG_HANDLE hDevMemHeap, + IMG_DEV_VIRTADDR sDevVAddr, + IMG_DEV_PHYADDR *pDevPAddr, + IMG_CPU_PHYADDR *pCpuPAddr) +{ + MMU_HEAP *pMMUHeap; + IMG_DEV_PHYADDR DevPAddr; + + + + pMMUHeap = (MMU_HEAP*)BM_GetMMUHeap(hDevMemHeap); + + DevPAddr = MMU_GetPhysPageAddr(pMMUHeap, sDevVAddr); + pCpuPAddr->uiAddr = DevPAddr.uiAddr; + pDevPAddr->uiAddr = DevPAddr.uiAddr; + + return (pDevPAddr->uiAddr != 0) ? PVRSRV_OK : PVRSRV_ERROR_INVALID_PARAMS; +} + + +PVRSRV_ERROR SGXGetMMUPDAddrKM(IMG_HANDLE hDevCookie, + IMG_HANDLE hDevMemContext, + IMG_DEV_PHYADDR *psPDDevPAddr) +{ + if (!hDevCookie || !hDevMemContext || !psPDDevPAddr) + { + return PVRSRV_ERROR_INVALID_PARAMS; + } + + + *psPDDevPAddr = ((BM_CONTEXT*)hDevMemContext)->psMMUContext->sPDDevPAddr; + + return PVRSRV_OK; +} + +PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo) +{ + PVRSRV_ERROR eError; + SYS_DATA *psSysData; + RA_ARENA *psLocalDevMemArena; + IMG_HANDLE hOSMemHandle = IMG_NULL; + IMG_BYTE *pui8MemBlock = IMG_NULL; + IMG_SYS_PHYADDR sMemBlockSysPAddr; + IMG_CPU_PHYADDR sMemBlockCpuPAddr; + + SysAcquireData(&psSysData); + + psLocalDevMemArena = psSysData->apsLocalDevMemArena[0]; + + + if(psLocalDevMemArena == IMG_NULL) + { + + eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + 3 * SGX_MMU_PAGE_SIZE, + SGX_MMU_PAGE_SIZE, + (IMG_VOID **)&pui8MemBlock, + &hOSMemHandle); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to OSAllocPages failed")); + return eError; + } + + + if(pui8MemBlock) + { + sMemBlockCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, + pui8MemBlock); + } + else + { + + sMemBlockCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, 0); + } + } + else + { + + + if(RA_Alloc(psLocalDevMemArena, + 3 * SGX_MMU_PAGE_SIZE, + IMG_NULL, + IMG_NULL, + 0, + SGX_MMU_PAGE_SIZE, + 0, + &(sMemBlockSysPAddr.uiAddr)) != IMG_TRUE) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to RA_Alloc failed")); + return PVRSRV_ERROR_OUT_OF_MEMORY; + } + + + sMemBlockCpuPAddr = SysSysPAddrToCpuPAddr(sMemBlockSysPAddr); + pui8MemBlock = OSMapPhysToLin(sMemBlockCpuPAddr, + SGX_MMU_PAGE_SIZE * 3, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + &hOSMemHandle); + if(!pui8MemBlock) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR failed to map page tables")); + return PVRSRV_ERROR_BAD_MAPPING; + } + } + + psDevInfo->hBIFResetPDOSMemHandle = hOSMemHandle; + psDevInfo->sBIFResetPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sMemBlockCpuPAddr); + psDevInfo->sBIFResetPTDevPAddr.uiAddr = psDevInfo->sBIFResetPDDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE; + psDevInfo->sBIFResetPageDevPAddr.uiAddr = psDevInfo->sBIFResetPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE; + + + psDevInfo->pui32BIFResetPD = (IMG_UINT32 *)pui8MemBlock; + psDevInfo->pui32BIFResetPT = (IMG_UINT32 *)(pui8MemBlock + SGX_MMU_PAGE_SIZE); + + + OSMemSet(psDevInfo->pui32BIFResetPD, 0, SGX_MMU_PAGE_SIZE); + OSMemSet(psDevInfo->pui32BIFResetPT, 0, SGX_MMU_PAGE_SIZE); + + OSMemSet(pui8MemBlock + (2 * SGX_MMU_PAGE_SIZE), 0xDB, SGX_MMU_PAGE_SIZE); + + return PVRSRV_OK; +} + +IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo) +{ + SYS_DATA *psSysData; + RA_ARENA *psLocalDevMemArena; + IMG_SYS_PHYADDR sPDSysPAddr; + + SysAcquireData(&psSysData); + + psLocalDevMemArena = psSysData->apsLocalDevMemArena[0]; + + + if(psLocalDevMemArena == IMG_NULL) + { + OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + 3 * SGX_MMU_PAGE_SIZE, + psDevInfo->pui32BIFResetPD, + psDevInfo->hBIFResetPDOSMemHandle); + } + else + { + OSUnMapPhysToLin(psDevInfo->pui32BIFResetPD, + 3 * SGX_MMU_PAGE_SIZE, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + psDevInfo->hBIFResetPDOSMemHandle); + + sPDSysPAddr = SysDevPAddrToSysPAddr(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->sBIFResetPDDevPAddr); + RA_Free(psLocalDevMemArena, sPDSysPAddr.uiAddr, IMG_FALSE); + } +} + + +#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT) +PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_DEVICE_NODE *psDeviceNode) +{ + PVRSRV_ERROR eError; + SYS_DATA *psSysData; + RA_ARENA *psLocalDevMemArena; + IMG_HANDLE hPTPageOSMemHandle = IMG_NULL; + IMG_HANDLE hPDPageOSMemHandle = IMG_NULL; + IMG_UINT32 *pui32PD = IMG_NULL; + IMG_UINT32 *pui32PT = IMG_NULL; + IMG_CPU_PHYADDR sCpuPAddr; + IMG_DEV_PHYADDR sPTDevPAddr; + IMG_DEV_PHYADDR sPDDevPAddr; + PVRSRV_SGXDEV_INFO *psDevInfo; + IMG_UINT32 ui32PDOffset; + IMG_UINT32 ui32PTOffset; + + psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice; + + SysAcquireData(&psSysData); + + psLocalDevMemArena = psSysData->apsLocalDevMemArena[0]; + + + if(psLocalDevMemArena == IMG_NULL) + { + + eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + SGX_MMU_PAGE_SIZE, + SGX_MMU_PAGE_SIZE, + (IMG_VOID **)&pui32PT, + &hPTPageOSMemHandle); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed")); + return eError; + } + ui32PTOffset = 0; + + eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + SGX_MMU_PAGE_SIZE, + SGX_MMU_PAGE_SIZE, + (IMG_VOID **)&pui32PD, + &hPDPageOSMemHandle); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed")); + return eError; + } + ui32PDOffset = 0; + + + if(pui32PT) + { + sCpuPAddr = OSMapLinToCPUPhys(hPTPageOSMemHandle, + pui32PT); + } + else + { + + sCpuPAddr = OSMemHandleToCpuPAddr(hPTPageOSMemHandle, 0); + } + sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); + + if(pui32PD) + { + sCpuPAddr = OSMapLinToCPUPhys(hPDPageOSMemHandle, + pui32PD); + } + else + { + + sCpuPAddr = OSMemHandleToCpuPAddr(hPDPageOSMemHandle, 0); + } + sPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); + + } + else + { + + + if(RA_Alloc(psLocalDevMemArena, + SGX_MMU_PAGE_SIZE * 2, + IMG_NULL, + IMG_NULL, + 0, + SGX_MMU_PAGE_SIZE, + 0, + &(psDevInfo->sBRN22997SysPAddr.uiAddr))!= IMG_TRUE) + { + PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to RA_Alloc failed")); + return PVRSRV_ERROR_OUT_OF_MEMORY; + } + + + sCpuPAddr = SysSysPAddrToCpuPAddr(psDevInfo->sBRN22997SysPAddr); + pui32PT = OSMapPhysToLin(sCpuPAddr, + SGX_MMU_PAGE_SIZE * 2, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + &hPTPageOSMemHandle); + if(!pui32PT) + { + PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR failed to map page tables")); + return PVRSRV_ERROR_BAD_MAPPING; + } + ui32PTOffset = 0; + + + sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); + + pui32PD = pui32PT + SGX_MMU_PAGE_SIZE/sizeof(IMG_UINT32); + ui32PDOffset = SGX_MMU_PAGE_SIZE; + hPDPageOSMemHandle = hPTPageOSMemHandle; + sPDDevPAddr.uiAddr = sPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE; + } + + OSMemSet(pui32PD, 0, SGX_MMU_PAGE_SIZE); + OSMemSet(pui32PT, 0, SGX_MMU_PAGE_SIZE); + + + PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDPageOSMemHandle, ui32PDOffset, pui32PD, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG); + PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPTPageOSMemHandle, ui32PTOffset, pui32PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG); + PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, hPDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); + PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, hPTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG); + + psDevInfo->hBRN22997PTPageOSMemHandle = hPTPageOSMemHandle; + psDevInfo->hBRN22997PDPageOSMemHandle = hPDPageOSMemHandle; + psDevInfo->sBRN22997PTDevPAddr = sPTDevPAddr; + psDevInfo->sBRN22997PDDevPAddr = sPDDevPAddr; + psDevInfo->pui32BRN22997PD = pui32PD; + psDevInfo->pui32BRN22997PT = pui32PT; + + return PVRSRV_OK; +} + + +IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo) +{ + IMG_UINT32 *pui32PD = psDevInfo->pui32BRN22997PD; + IMG_UINT32 *pui32PT = psDevInfo->pui32BRN22997PT; + IMG_UINT32 ui32PDIndex; + IMG_UINT32 ui32PTIndex; + IMG_DEV_VIRTADDR sDevVAddr; + volatile IMG_UINT32 *pui32HostPort; + IMG_UINT32 ui32BIFCtrl; + + + + + pui32HostPort = (volatile IMG_UINT32*)(((IMG_UINT8*)psDevInfo->pvHostPortBaseKM) + SYS_SGX_HOSTPORT_BRN23030_OFFSET); + + + sDevVAddr.uiAddr = SYS_SGX_HOSTPORT_BASE_DEVVADDR + SYS_SGX_HOSTPORT_BRN23030_OFFSET; + + ui32PDIndex = (sDevVAddr.uiAddr & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT); + ui32PTIndex = (sDevVAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT; + + + pui32PD[ui32PDIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT) + | SGX_MMU_PDE_VALID; + + pui32PT[ui32PTIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT) + | SGX_MMU_PTE_VALID; + + PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); + PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG); + + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, + psDevInfo->sBRN22997PDDevPAddr.uiAddr); + PDUMPPDREG(&psDevInfo->sMMUAttrib, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sBRN22997PDDevPAddr.uiAddr, PDUMP_PD_UNIQUETAG); + + + ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK); + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl); + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl); + + + if (pui32HostPort) + { + + IMG_UINT32 ui32Tmp; + ui32Tmp = *pui32HostPort; + } + else + { + PVR_DPF((PVR_DBG_ERROR,"Host Port not present for BRN22997 workaround")); + } + + + + + + + + PDUMPCOMMENT("RDW :SGXMEM:v4:%08X\r\n", sDevVAddr.uiAddr); + + PDUMPCOMMENT("SAB :SGXMEM:v4:%08X 4 0 hostport.bin", sDevVAddr.uiAddr); + + + pui32PD[ui32PDIndex] = 0; + pui32PT[ui32PTIndex] = 0; + + + PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); + PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG); + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK); + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl); + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl); +} + + +IMG_VOID WorkaroundBRN22997Free(PVRSRV_DEVICE_NODE *psDeviceNode) +{ + SYS_DATA *psSysData; + RA_ARENA *psLocalDevMemArena; + PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice; + + + SysAcquireData(&psSysData); + + psLocalDevMemArena = psSysData->apsLocalDevMemArena[0]; + + PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN22997PDPageOSMemHandle, psDevInfo->pui32BRN22997PD, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG); + PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN22997PTPageOSMemHandle, psDevInfo->pui32BRN22997PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG); + + + if(psLocalDevMemArena == IMG_NULL) + { + if (psDevInfo->pui32BRN22997PD != IMG_NULL) + { + OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + SGX_MMU_PAGE_SIZE, + psDevInfo->pui32BRN22997PD, + psDevInfo->hBRN22997PDPageOSMemHandle); + } + + if (psDevInfo->pui32BRN22997PT != IMG_NULL) + { + OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + SGX_MMU_PAGE_SIZE, + psDevInfo->pui32BRN22997PT, + psDevInfo->hBRN22997PTPageOSMemHandle); + } + } + else + { + if (psDevInfo->pui32BRN22997PT != IMG_NULL) + { + OSUnMapPhysToLin(psDevInfo->pui32BRN22997PT, + SGX_MMU_PAGE_SIZE * 2, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + psDevInfo->hBRN22997PTPageOSMemHandle); + + + RA_Free(psLocalDevMemArena, psDevInfo->sBRN22997SysPAddr.uiAddr, IMG_FALSE); + } + } +} +#endif + + +#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE) +PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode) +{ + PVRSRV_ERROR eError; + SYS_DATA *psSysData; + RA_ARENA *psLocalDevMemArena; + IMG_HANDLE hPTPageOSMemHandle = IMG_NULL; + IMG_UINT32 *pui32PD; + IMG_UINT32 *pui32PT = IMG_NULL; + IMG_CPU_PHYADDR sCpuPAddr; + IMG_DEV_PHYADDR sPTDevPAddr; + PVRSRV_SGXDEV_INFO *psDevInfo; + IMG_UINT32 ui32PDIndex; + IMG_UINT32 ui32PTIndex; + + psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice; + pui32PD = (IMG_UINT32*)psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->pvPDCpuVAddr; + + SysAcquireData(&psSysData); + + psLocalDevMemArena = psSysData->apsLocalDevMemArena[0]; + + + if(psLocalDevMemArena == IMG_NULL) + { + + eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + SGX_MMU_PAGE_SIZE, + SGX_MMU_PAGE_SIZE, + (IMG_VOID **)&pui32PT, + &hPTPageOSMemHandle); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_MapExtSystemCacheRegs: ERROR call to OSAllocPages failed")); + return eError; + } + + + if(pui32PT) + { + sCpuPAddr = OSMapLinToCPUPhys(hPTPageOSMemHandle, + pui32PT); + } + else + { + + sCpuPAddr = OSMemHandleToCpuPAddr(hPTPageOSMemHandle, 0); + } + sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); + } + else + { + IMG_SYS_PHYADDR sSysPAddr; + + + if(RA_Alloc(psLocalDevMemArena, + SGX_MMU_PAGE_SIZE, + IMG_NULL, + IMG_NULL, + 0, + SGX_MMU_PAGE_SIZE, + 0, + &(sSysPAddr.uiAddr))!= IMG_TRUE) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_MapExtSystemCacheRegs: ERROR call to RA_Alloc failed")); + return PVRSRV_ERROR_OUT_OF_MEMORY; + } + + + sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr); + pui32PT = OSMapPhysToLin(sCpuPAddr, + SGX_MMU_PAGE_SIZE, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + &hPTPageOSMemHandle); + if(!pui32PT) + { + PVR_DPF((PVR_DBG_ERROR, "MMU_MapExtSystemCacheRegs: ERROR failed to map page tables")); + return PVRSRV_ERROR_BAD_MAPPING; + } + + + sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); + + + psDevInfo->sExtSystemCacheRegsPTSysPAddr = sSysPAddr; + } + + OSMemSet(pui32PT, 0, SGX_MMU_PAGE_SIZE); + + ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT); + ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT; + + + pui32PD[ui32PDIndex] = (sPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT) + | SGX_MMU_PDE_VALID; + + pui32PT[ui32PTIndex] = (psDevInfo->sExtSysCacheRegsDevPBase.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT) + | SGX_MMU_PTE_VALID; + + + PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevID, hPTPageOSMemHandle, 0, pui32PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG); + PDUMPMEMPTENTRIES(PVRSRV_DEVICE_TYPE_SGX, hPDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); + PDUMPMEMPTENTRIES(PVRSRV_DEVICE_TYPE_SGX, hPTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG); + + + psDevInfo->pui32ExtSystemCacheRegsPT = pui32PT; + psDevInfo->hExtSystemCacheRegsPTPageOSMemHandle = hPTPageOSMemHandle; + + return PVRSRV_OK; +} + + +PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode) +{ + SYS_DATA *psSysData; + RA_ARENA *psLocalDevMemArena; + PVRSRV_SGXDEV_INFO *psDevInfo; + IMG_UINT32 ui32PDIndex; + IMG_UINT32 *pui32PD; + + psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice; + pui32PD = (IMG_UINT32*)psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->pvPDCpuVAddr; + + SysAcquireData(&psSysData); + + psLocalDevMemArena = psSysData->apsLocalDevMemArena[0]; + + + ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT); + pui32PD[ui32PDIndex] = 0; + + PDUMPMEMPTENTRIES(PVRSRV_DEVICE_TYPE_SGX, psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->hPDOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); + PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hExtSystemCacheRegsPTPageOSMemHandle, psDevInfo->pui32ExtSystemCacheRegsPT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG); + + + if(psLocalDevMemArena == IMG_NULL) + { + if (psDevInfo->pui32ExtSystemCacheRegsPT != IMG_NULL) + { + OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, + SGX_MMU_PAGE_SIZE, + psDevInfo->pui32ExtSystemCacheRegsPT, + psDevInfo->hExtSystemCacheRegsPTPageOSMemHandle); + } + } + else + { + if (psDevInfo->pui32ExtSystemCacheRegsPT != IMG_NULL) + { + OSUnMapPhysToLin(psDevInfo->pui32ExtSystemCacheRegsPT, + SGX_MMU_PAGE_SIZE, + PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY, + psDevInfo->hExtSystemCacheRegsPTPageOSMemHandle); + + RA_Free(psLocalDevMemArena, psDevInfo->sExtSystemCacheRegsPTSysPAddr.uiAddr, IMG_FALSE); + } + } + + return PVRSRV_OK; +} +#endif + + +#if PAGE_TEST +static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr) +{ + volatile IMG_UINT32 ui32WriteData; + volatile IMG_UINT32 ui32ReadData; + volatile IMG_UINT32 *pMem32 = (volatile IMG_UINT32 *)pMem; + IMG_INT n; + IMG_BOOL bOK=IMG_TRUE; + + ui32WriteData = 0xffffffff; + + for (n=0; n<1024; n++) + { + pMem32[n] = ui32WriteData; + ui32ReadData = pMem32[n]; + + if (ui32WriteData != ui32ReadData) + { + + PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) )); + PVR_DBG_BREAK; + bOK = IMG_FALSE; + } + } + + ui32WriteData = 0; + + for (n=0; n<1024; n++) + { + pMem32[n] = ui32WriteData; + ui32ReadData = pMem32[n]; + + if (ui32WriteData != ui32ReadData) + { + + PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) )); + PVR_DBG_BREAK; + bOK = IMG_FALSE; + } + } + + if (bOK) + { + PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x%08X is OK", sDevPAddr.uiAddr)); + } + else + { + PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x%08X *** FAILED ***", sDevPAddr.uiAddr)); + } +} +#endif + diff --git a/drivers/gpu/pvr/sgx/mmu.h b/drivers/gpu/pvr/sgx/mmu.h new file mode 100644 index 0000000..e92b4e0 --- /dev/null +++ b/drivers/gpu/pvr/sgx/mmu.h @@ -0,0 +1,146 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 + * + ******************************************************************************/ + +#ifndef _MMU_H_ +#define _MMU_H_ + +#include "sgxinfokm.h" + +PVRSRV_ERROR +MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr); + +IMG_VOID +MMU_Finalise (MMU_CONTEXT *psMMUContext); + + +IMG_VOID +MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap); + +MMU_HEAP * +MMU_Create (MMU_CONTEXT *psMMUContext, + DEV_ARENA_DESCRIPTOR *psDevArena, + RA_ARENA **ppsVMArena, + PDUMP_MMU_ATTRIB **ppsMMUAttrib); + +IMG_VOID +MMU_Delete (MMU_HEAP *pMMUHeap); + +IMG_BOOL +MMU_Alloc (MMU_HEAP *pMMUHeap, + IMG_SIZE_T uSize, + IMG_SIZE_T *pActualSize, + IMG_UINT32 uFlags, + IMG_UINT32 uDevVAddrAlignment, + IMG_DEV_VIRTADDR *pDevVAddr); + +IMG_VOID +MMU_Free (MMU_HEAP *pMMUHeap, + IMG_DEV_VIRTADDR DevVAddr, + IMG_UINT32 ui32Size); + +IMG_VOID +MMU_Enable (MMU_HEAP *pMMUHeap); + +IMG_VOID +MMU_Disable (MMU_HEAP *pMMUHeap); + +IMG_VOID +MMU_MapPages (MMU_HEAP *pMMUHeap, + IMG_DEV_VIRTADDR DevVAddr, + IMG_SYS_PHYADDR SysPAddr, + IMG_SIZE_T uSize, + IMG_UINT32 ui32MemFlags, + IMG_HANDLE hUniqueTag); + +IMG_VOID +MMU_MapShadow (MMU_HEAP * pMMUHeap, + IMG_DEV_VIRTADDR MapBaseDevVAddr, + IMG_SIZE_T uByteSize, + IMG_CPU_VIRTADDR CpuVAddr, + IMG_HANDLE hOSMemHandle, + IMG_DEV_VIRTADDR * pDevVAddr, + IMG_UINT32 ui32MemFlags, + IMG_HANDLE hUniqueTag); + +IMG_VOID +MMU_UnmapPages (MMU_HEAP *psMMUHeap, + IMG_DEV_VIRTADDR sDevVAddr, + IMG_UINT32 ui32PageCount, + IMG_HANDLE hUniqueTag); + +IMG_VOID +MMU_MapScatter (MMU_HEAP *pMMUHeap, + IMG_DEV_VIRTADDR DevVAddr, + IMG_SYS_PHYADDR *psSysAddr, + IMG_SIZE_T uSize, + IMG_UINT32 ui32MemFlags, + IMG_HANDLE hUniqueTag); + + +IMG_DEV_PHYADDR +MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr); + + +IMG_DEV_PHYADDR +MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext); + + +#ifdef SUPPORT_SGX_MMU_BYPASS +IMG_VOID +EnableHostAccess (MMU_CONTEXT *psMMUContext); + + +IMG_VOID +DisableHostAccess (MMU_CONTEXT *psMMUContext); +#endif + +IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo); + +PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo); + +IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo); + +#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT) +PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_DEVICE_NODE *psDeviceNode); + +IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo); + +IMG_VOID WorkaroundBRN22997Free(PVRSRV_DEVICE_NODE *psDeviceNode); +#endif + +#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE) +PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode); + +PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode); +#endif + +IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMU_Heap); + +#if defined(PDUMP) +IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext); +#endif + +#endif diff --git a/drivers/gpu/pvr/sgx/pb.c b/drivers/gpu/pvr/sgx/pb.c new file mode 100644 index 0000000..f9e8b19 --- /dev/null +++ b/drivers/gpu/pvr/sgx/pb.c @@ -0,0 +1,459 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 <stddef.h> + +#include "services_headers.h" +#include "sgx_bridge_km.h" +#include "sgxapi_km.h" +#include "sgxinfo.h" +#include "sgxinfokm.h" +#include "pvr_bridge_km.h" +#include "pdump_km.h" +#include "sgxutils.h" + +#ifndef __linux__ +#pragma message("TODO: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE") +#endif + +#include "lists.h" + +static IMPLEMENT_LIST_INSERT(PVRSRV_STUB_PBDESC) +static IMPLEMENT_LIST_REMOVE(PVRSRV_STUB_PBDESC) + +static PRESMAN_ITEM psResItemCreateSharedPB = IMG_NULL; +static PVRSRV_PER_PROCESS_DATA *psPerProcCreateSharedPB = IMG_NULL; + +static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param); +static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param); + +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; +} + + +static PVRSRV_ERROR +SGXCleanupSharedPBDescKM(PVRSRV_STUB_PBDESC *psStubPBDescIn) +{ + + IMG_UINT32 i; + PVRSRV_DEVICE_NODE *psDeviceNode; + + psDeviceNode = (PVRSRV_DEVICE_NODE*)psStubPBDescIn->hDevCookie; + + + + + psStubPBDescIn->ui32RefCount--; + if (psStubPBDescIn->ui32RefCount == 0) + { + List_PVRSRV_STUB_PBDESC_Remove(psStubPBDescIn); + for(i=0 ; i<psStubPBDescIn->ui32SubKernelMemInfosCount; i++) + { + + PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, + psStubPBDescIn->ppsSubKernelMemInfos[i]); + } + + OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, + sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDescIn->ui32SubKernelMemInfosCount, + psStubPBDescIn->ppsSubKernelMemInfos, + 0); + psStubPBDescIn->ppsSubKernelMemInfos = IMG_NULL; + + PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psBlockKernelMemInfo); + + PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWBlockKernelMemInfo); + + PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWPBDescKernelMemInfo); + + PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psSharedPBDescKernelMemInfo); + + OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, + sizeof(PVRSRV_STUB_PBDESC), + psStubPBDescIn, + 0); + + + + SGXCleanupRequest(psDeviceNode, + IMG_NULL, + PVRSRV_CLEANUPCMD_PB); + } + return PVRSRV_OK; + +} + +static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param) +{ + PVRSRV_STUB_PBDESC *psStubPBDesc = (PVRSRV_STUB_PBDESC *)pvParam; + + PVR_UNREFERENCED_PARAMETER(ui32Param); + + return SGXCleanupSharedPBDescKM(psStubPBDesc); +} + +static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param) +{ +#ifdef DEBUG + PVRSRV_PER_PROCESS_DATA *psPerProc = (PVRSRV_PER_PROCESS_DATA *)pvParam; + PVR_ASSERT(psPerProc == psPerProcCreateSharedPB); +#else + PVR_UNREFERENCED_PARAMETER(pvParam); +#endif + + PVR_UNREFERENCED_PARAMETER(ui32Param); + + psPerProcCreateSharedPB = IMG_NULL; + psResItemCreateSharedPB = IMG_NULL; + + return PVRSRV_OK; +} + + +IMG_EXPORT PVRSRV_ERROR +SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc) +{ + PVR_ASSERT(hSharedPBDesc != IMG_NULL); + + return ResManFreeResByPtr(hSharedPBDesc); +} + + +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) +{ + 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); + + 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; + } + } + + 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; +} + diff --git a/drivers/gpu/pvr/sgx/sgx_bridge_km.h b/drivers/gpu/pvr/sgx/sgx_bridge_km.h new file mode 100644 index 0000000..7738be1 --- /dev/null +++ b/drivers/gpu/pvr/sgx/sgx_bridge_km.h @@ -0,0 +1,134 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 + * + ******************************************************************************/ + +#if !defined(__SGX_BRIDGE_KM_H__) +#define __SGX_BRIDGE_KM_H__ + +#include "sgxapi_km.h" +#include "sgxinfo.h" +#include "sgxinfokm.h" +#include "sgx_bridge.h" +#include "pvr_bridge.h" +#include "perproc.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +IMG_IMPORT +PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick); + +#if defined(SGX_FEATURE_2D_HARDWARE) +IMG_IMPORT +PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick); +#endif + +IMG_IMPORT +PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, + SGX_CCB_KICK *psCCBKick); + +IMG_IMPORT +PVRSRV_ERROR SGXGetPhysPageAddrKM(IMG_HANDLE hDevMemHeap, + IMG_DEV_VIRTADDR sDevVAddr, + IMG_DEV_PHYADDR *pDevPAddr, + IMG_CPU_PHYADDR *pCpuPAddr); + +IMG_IMPORT +PVRSRV_ERROR IMG_CALLCONV SGXGetMMUPDAddrKM(IMG_HANDLE hDevCookie, + IMG_HANDLE hDevMemContext, + IMG_DEV_PHYADDR *psPDDevPAddr); + +IMG_IMPORT +PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie, + SGX_CLIENT_INFO* psClientInfo); + +IMG_IMPORT +PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo, + SGX_MISC_INFO *psMiscInfo, + PVRSRV_DEVICE_NODE *psDeviceNode, + IMG_HANDLE hDevMemContext); + +IMG_IMPORT +PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE hDevHandle, + IMG_UINT32 ui32ArraySize, + PVRSRV_SGX_HWPERF_CB_ENTRY *psHWPerfCBData, + IMG_UINT32 *pui32DataCount, + IMG_UINT32 *pui32ClockSpeed, + IMG_UINT32 *pui32HostTimeStamp); + +IMG_IMPORT +PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo, + PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, + IMG_BOOL bWaitForComplete); + +IMG_IMPORT +PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, + SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo); + +IMG_IMPORT +PVRSRV_ERROR DevInitSGXPart2KM(PVRSRV_PER_PROCESS_DATA *psPerProc, + IMG_HANDLE hDevHandle, + SGX_BRIDGE_INIT_INFO *psInitInfo); + +IMG_IMPORT 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); + +IMG_IMPORT PVRSRV_ERROR +SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc); + +IMG_IMPORT 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 **psSharedPBDescSubKernelMemInfos, + IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount); + + +IMG_IMPORT PVRSRV_ERROR +SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie, + SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo); + +#if defined (__cplusplus) +} +#endif + +#endif + diff --git a/drivers/gpu/pvr/sgx/sgxconfig.h b/drivers/gpu/pvr/sgx/sgxconfig.h new file mode 100644 index 0000000..a0ca3e9 --- /dev/null +++ b/drivers/gpu/pvr/sgx/sgxconfig.h @@ -0,0 +1,227 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 + * + ******************************************************************************/ + +#ifndef __SGXCONFIG_H__ +#define __SGXCONFIG_H__ + +#include "sgxdefs.h" + +#define DEV_DEVICE_TYPE PVRSRV_DEVICE_TYPE_SGX +#define DEV_DEVICE_CLASS PVRSRV_DEVICE_CLASS_3D + +#define DEV_MAJOR_VERSION 1 +#define DEV_MINOR_VERSION 0 + +#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 32 + #if defined(SGX_FEATURE_2D_HARDWARE) + #define SGX_2D_HEAP_BASE 0x00100000 + #define SGX_2D_HEAP_SIZE (0x08000000-0x00100000-0x00001000) + #else + #if defined(FIX_HW_BRN_26915) + #define SGX_CGBUFFER_HEAP_BASE 0x00100000 + #define SGX_CGBUFFER_HEAP_SIZE (0x08000000-0x00100000-0x00001000) + #endif + #endif + + #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) + #define SGX_GENERAL_MAPPING_HEAP_BASE 0x08000000 + #define SGX_GENERAL_MAPPING_HEAP_SIZE (0x08000000-0x00001000) + #endif + + #define SGX_GENERAL_HEAP_BASE 0x10000000 + #define SGX_GENERAL_HEAP_SIZE (0xC2000000-0x00001000) + + #define SGX_3DPARAMETERS_HEAP_BASE 0xD2000000 + #define SGX_3DPARAMETERS_HEAP_SIZE (0x10000000-0x00001000) + + #define SGX_TADATA_HEAP_BASE 0xE2000000 + #define SGX_TADATA_HEAP_SIZE (0x0D000000-0x00001000) + + #define SGX_SYNCINFO_HEAP_BASE 0xEF000000 + #define SGX_SYNCINFO_HEAP_SIZE (0x01000000-0x00001000) + + #define SGX_PDSPIXEL_CODEDATA_HEAP_BASE 0xF0000000 + #define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE (0x02000000-0x00001000) + + #define SGX_KERNEL_CODE_HEAP_BASE 0xF2000000 + #define SGX_KERNEL_CODE_HEAP_SIZE (0x00080000-0x00001000) + + #define SGX_PDSVERTEX_CODEDATA_HEAP_BASE 0xF2400000 + #define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE (0x01C00000-0x00001000) + + #define SGX_KERNEL_DATA_HEAP_BASE 0xF4000000 + #define SGX_KERNEL_DATA_HEAP_SIZE (0x05000000-0x00001000) + + + #define SGX_PIXELSHADER_HEAP_BASE 0xF9000000 + #define SGX_PIXELSHADER_HEAP_SIZE (0x05000000-0x00001000) + + #define SGX_VERTEXSHADER_HEAP_BASE 0xFE000000 + #define SGX_VERTEXSHADER_HEAP_SIZE (0x02000000-0x00001000) + + + #define SGX_CORE_IDENTIFIED +#endif + +#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28 + #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) + #define SGX_GENERAL_MAPPING_HEAP_BASE 0x00001000 + #define SGX_GENERAL_MAPPING_HEAP_SIZE (0x01800000-0x00001000-0x00001000) + #endif + + #define SGX_GENERAL_HEAP_BASE 0x01800000 + #define SGX_GENERAL_HEAP_SIZE (0x07000000-0x00001000) + + #define SGX_3DPARAMETERS_HEAP_BASE 0x08800000 + #define SGX_3DPARAMETERS_HEAP_SIZE (0x04000000-0x00001000) + + #define SGX_TADATA_HEAP_BASE 0x0C800000 + #define SGX_TADATA_HEAP_SIZE (0x01000000-0x00001000) + + #define SGX_SYNCINFO_HEAP_BASE 0x0D800000 + #define SGX_SYNCINFO_HEAP_SIZE (0x00400000-0x00001000) + + #define SGX_PDSPIXEL_CODEDATA_HEAP_BASE 0x0DC00000 + #define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE (0x00800000-0x00001000) + + #define SGX_KERNEL_CODE_HEAP_BASE 0x0E400000 + #define SGX_KERNEL_CODE_HEAP_SIZE (0x00080000-0x00001000) + + #define SGX_PDSVERTEX_CODEDATA_HEAP_BASE 0x0E800000 + #define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE (0x00800000-0x00001000) + + #define SGX_KERNEL_DATA_HEAP_BASE 0x0F000000 + #define SGX_KERNEL_DATA_HEAP_SIZE (0x00400000-0x00001000) + + #define SGX_PIXELSHADER_HEAP_BASE 0x0F400000 + #define SGX_PIXELSHADER_HEAP_SIZE (0x00500000-0x00001000) + + #define SGX_VERTEXSHADER_HEAP_BASE 0x0FC00000 + #define SGX_VERTEXSHADER_HEAP_SIZE (0x00200000-0x00001000) + + + #define SGX_CORE_IDENTIFIED + +#endif + +#if !defined(SGX_CORE_IDENTIFIED) + #error "sgxconfig.h: ERROR: unspecified SGX Core version" +#endif + +#if !defined (SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE) + #if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) > 0x4000000) + #error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE" + #endif + + #if ((SGX_PDSVERTEX_CODEDATA_HEAP_BASE + SGX_PDSVERTEX_CODEDATA_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) > 0x4000000) + #error "sgxconfig.h: ERROR: SGX_PDSVERTEX_CODEDATA_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE" + #endif +#endif + +#if defined(SGX_FEATURE_2D_HARDWARE) && defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) + #if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE - SGX_2D_HEAP_BASE) >= EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK) + #error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP inaccessable by 2D requestor" + #endif +#endif + +#if defined (EURASIA_USE_CODE_PAGE_SIZE) + #if ((SGX_KERNEL_CODE_HEAP_BASE & (EURASIA_USE_CODE_PAGE_SIZE - 1)) != 0) + #error "sgxconfig.h: ERROR: Kernel code heap base misalignment" + #endif +#endif + +#if defined(SGX_FEATURE_2D_HARDWARE) + #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) + #if ((SGX_2D_HEAP_BASE + SGX_2D_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_2D_HEAP overlaps SGX_GENERAL_MAPPING_HEAP" + #endif + #else + #if ((SGX_2D_HEAP_BASE + SGX_2D_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_2D_HEAP overlaps SGX_GENERAL_HEAP_BASE" + #endif + #endif +#else + #if defined(FIX_HW_BRN_26915) + #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) + #if ((SGX_CGBUFFER_HEAP_BASE + SGX_CGBUFFER_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_CGBUFFER_HEAP overlaps SGX_GENERAL_MAPPING_HEAP" + #endif + #else + #if ((SGX_CGBUFFER_HEAP_BASE + SGX_CGBUFFER_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_CGBUFFER_HEAP overlaps SGX_GENERAL_HEAP_BASE" + #endif + #endif + #endif +#endif + +#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) + #if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP overlaps SGX_GENERAL_HEAP" + #endif +#endif + +#if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_3DPARAMETERS_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_3DPARAMETERS_HEAP" +#endif + +#if ((SGX_3DPARAMETERS_HEAP_BASE + SGX_3DPARAMETERS_HEAP_SIZE) >= SGX_TADATA_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_3DPARAMETERS_HEAP overlaps SGX_TADATA_HEAP" +#endif + +#if ((SGX_TADATA_HEAP_BASE + SGX_TADATA_HEAP_SIZE) >= SGX_SYNCINFO_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_TADATA_HEAP overlaps SGX_SYNCINFO_HEAP" +#endif + +#if ((SGX_SYNCINFO_HEAP_BASE + SGX_SYNCINFO_HEAP_SIZE) >= SGX_PDSPIXEL_CODEDATA_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_SYNCINFO_HEAP overlaps SGX_PDSPIXEL_CODEDATA_HEAP" +#endif + +#if ((SGX_PDSPIXEL_CODEDATA_HEAP_BASE + SGX_PDSPIXEL_CODEDATA_HEAP_SIZE) >= SGX_KERNEL_CODE_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_PDSPIXEL_CODEDATA_HEAP overlaps SGX_KERNEL_CODE_HEAP" +#endif + +#if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE) >= SGX_PDSVERTEX_CODEDATA_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP overlaps SGX_PDSVERTEX_CODEDATA_HEAP" +#endif + +#if ((SGX_PDSVERTEX_CODEDATA_HEAP_BASE + SGX_PDSVERTEX_CODEDATA_HEAP_SIZE) >= SGX_KERNEL_DATA_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_PDSVERTEX_CODEDATA_HEAP overlaps SGX_KERNEL_DATA_HEAP" +#endif + +#if ((SGX_KERNEL_DATA_HEAP_BASE + SGX_KERNEL_DATA_HEAP_SIZE) >= SGX_PIXELSHADER_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_KERNEL_DATA_HEAP overlaps SGX_PIXELSHADER_HEAP" +#endif + +#if ((SGX_PIXELSHADER_HEAP_BASE + SGX_PIXELSHADER_HEAP_SIZE) >= SGX_VERTEXSHADER_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_PIXELSHADER_HEAP overlaps SGX_VERTEXSHADER_HEAP" +#endif + +#if ((SGX_VERTEXSHADER_HEAP_BASE + SGX_VERTEXSHADER_HEAP_SIZE) < SGX_VERTEXSHADER_HEAP_BASE) + #error "sgxconfig.h: ERROR: SGX_VERTEXSHADER_HEAP_BASE size cause wraparound" +#endif + +#endif + diff --git a/drivers/gpu/pvr/sgx/sgxinfokm.h b/drivers/gpu/pvr/sgx/sgxinfokm.h new file mode 100644 index 0000000..056db35 --- /dev/null +++ b/drivers/gpu/pvr/sgx/sgxinfokm.h @@ -0,0 +1,369 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 + * + ******************************************************************************/ + +#ifndef __SGXINFOKM_H__ +#define __SGXINFOKM_H__ + +#include "sgxdefs.h" +#include "device.h" +#include "power.h" +#include "sysconfig.h" +#include "sgxscript.h" +#include "sgxinfo.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +#define SGX_HOSTPORT_PRESENT 0x00000001UL + + +#define SGX_PDUMPREG_NAME "SGXREG" + +typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC; + + +typedef struct _PVRSRV_SGX_CCB_INFO_ *PPVRSRV_SGX_CCB_INFO; + +typedef struct _PVRSRV_SGXDEV_INFO_ +{ + PVRSRV_DEVICE_TYPE eDeviceType; + PVRSRV_DEVICE_CLASS eDeviceClass; + + IMG_UINT8 ui8VersionMajor; + IMG_UINT8 ui8VersionMinor; + IMG_UINT32 ui32CoreConfig; + IMG_UINT32 ui32CoreFlags; + + + IMG_PVOID pvRegsBaseKM; + +#if defined(SGX_FEATURE_HOST_PORT) + + IMG_PVOID pvHostPortBaseKM; + + IMG_UINT32 ui32HPSize; + + IMG_SYS_PHYADDR sHPSysPAddr; +#endif + + + IMG_HANDLE hRegMapping; + + + IMG_SYS_PHYADDR sRegsPhysBase; + + IMG_UINT32 ui32RegSize; + +#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE) + + IMG_UINT32 ui32ExtSysCacheRegsSize; + + IMG_DEV_PHYADDR sExtSysCacheRegsDevPBase; + + IMG_UINT32 *pui32ExtSystemCacheRegsPT; + + IMG_HANDLE hExtSystemCacheRegsPTPageOSMemHandle; + + IMG_SYS_PHYADDR sExtSystemCacheRegsPTSysPAddr; +#endif + + + IMG_UINT32 ui32CoreClockSpeed; + IMG_UINT32 ui32uKernelTimerClock; + + PVRSRV_STUB_PBDESC *psStubPBDescListKM; + + + + IMG_DEV_PHYADDR sKernelPDDevPAddr; + + IMG_VOID *pvDeviceMemoryHeap; + PPVRSRV_KERNEL_MEM_INFO psKernelCCBMemInfo; + PVRSRV_SGX_KERNEL_CCB *psKernelCCB; + PPVRSRV_SGX_CCB_INFO psKernelCCBInfo; + PPVRSRV_KERNEL_MEM_INFO psKernelCCBCtlMemInfo; + PVRSRV_SGX_CCB_CTL *psKernelCCBCtl; + PPVRSRV_KERNEL_MEM_INFO psKernelCCBEventKickerMemInfo; + IMG_UINT32 *pui32KernelCCBEventKicker; +#if defined(PDUMP) + IMG_UINT32 ui32KernelCCBEventKickerDumpVal; +#endif + PVRSRV_KERNEL_MEM_INFO *psKernelSGXMiscMemInfo; + IMG_UINT32 aui32HostKickAddr[SGXMKIF_CMD_MAX]; +#if defined(SGX_SUPPORT_HWPROFILING) + PPVRSRV_KERNEL_MEM_INFO psKernelHWProfilingMemInfo; +#endif + PPVRSRV_KERNEL_MEM_INFO psKernelHWPerfCBMemInfo; + PPVRSRV_KERNEL_MEM_INFO psKernelTASigBufferMemInfo; + PPVRSRV_KERNEL_MEM_INFO psKernel3DSigBufferMemInfo; +#if defined(FIX_HW_BRN_29702) + PPVRSRV_KERNEL_MEM_INFO psKernelCFIMemInfo; +#endif +#if defined(FIX_HW_BRN_29823) + PPVRSRV_KERNEL_MEM_INFO psKernelDummyTermStreamMemInfo; +#endif +#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) + PPVRSRV_KERNEL_MEM_INFO psKernelEDMStatusBufferMemInfo; +#endif +#if defined(SGX_FEATURE_OVERLAPPED_SPM) + PPVRSRV_KERNEL_MEM_INFO psKernelTmpRgnHeaderMemInfo; +#endif +#if defined(SGX_FEATURE_SPM_MODE_0) + PPVRSRV_KERNEL_MEM_INFO psKernelTmpDPMStateMemInfo; +#endif + + + IMG_UINT32 ui32ClientRefCount; + + + IMG_UINT32 ui32CacheControl; + + + IMG_UINT32 ui32ClientBuildOptions; + + + SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes; + + + + + IMG_VOID *pvMMUContextList; + + + IMG_BOOL bForcePTOff; + + IMG_UINT32 ui32EDMTaskReg0; + IMG_UINT32 ui32EDMTaskReg1; + + IMG_UINT32 ui32ClkGateStatusReg; + IMG_UINT32 ui32ClkGateStatusMask; +#if defined(SGX_FEATURE_MP) + IMG_UINT32 ui32MasterClkGateStatusReg; + IMG_UINT32 ui32MasterClkGateStatusMask; + IMG_UINT32 ui32MasterClkGateStatus2Reg; + IMG_UINT32 ui32MasterClkGateStatus2Mask; +#endif + SGX_INIT_SCRIPTS sScripts; + + + IMG_HANDLE hBIFResetPDOSMemHandle; + IMG_DEV_PHYADDR sBIFResetPDDevPAddr; + IMG_DEV_PHYADDR sBIFResetPTDevPAddr; + IMG_DEV_PHYADDR sBIFResetPageDevPAddr; + IMG_UINT32 *pui32BIFResetPD; + IMG_UINT32 *pui32BIFResetPT; + +#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT) + + IMG_HANDLE hBRN22997PTPageOSMemHandle; + IMG_HANDLE hBRN22997PDPageOSMemHandle; + IMG_DEV_PHYADDR sBRN22997PTDevPAddr; + IMG_DEV_PHYADDR sBRN22997PDDevPAddr; + IMG_UINT32 *pui32BRN22997PT; + IMG_UINT32 *pui32BRN22997PD; + IMG_SYS_PHYADDR sBRN22997SysPAddr; +#endif + +#if defined(SUPPORT_HW_RECOVERY) + + IMG_HANDLE hTimer; + + IMG_UINT32 ui32TimeStamp; +#endif + + + IMG_UINT32 ui32NumResets; + + + PVRSRV_KERNEL_MEM_INFO *psKernelSGXHostCtlMemInfo; + SGXMKIF_HOST_CTL *psSGXHostCtl; + + + PVRSRV_KERNEL_MEM_INFO *psKernelSGXTA3DCtlMemInfo; + + IMG_UINT32 ui32Flags; + + + IMG_UINT32 ui32MemTilingUsage; + + #if defined(PDUMP) + PVRSRV_SGX_PDUMP_CONTEXT sPDContext; + #endif + +#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) + + IMG_VOID *pvDummyPTPageCpuVAddr; + IMG_DEV_PHYADDR sDummyPTDevPAddr; + IMG_HANDLE hDummyPTPageOSMemHandle; + IMG_VOID *pvDummyDataPageCpuVAddr; + IMG_DEV_PHYADDR sDummyDataDevPAddr; + IMG_HANDLE hDummyDataPageOSMemHandle; +#endif +#if defined(PDUMP) + PDUMP_MMU_ATTRIB sMMUAttrib; +#endif + IMG_UINT32 asSGXDevData[SGX_MAX_DEV_DATA]; + +} PVRSRV_SGXDEV_INFO; + + +typedef struct _SGX_TIMING_INFORMATION_ +{ + IMG_UINT32 ui32CoreClockSpeed; + IMG_UINT32 ui32HWRecoveryFreq; + IMG_BOOL bEnableActivePM; + IMG_UINT32 ui32ActivePowManLatencyms; + IMG_UINT32 ui32uKernelFreq; +} SGX_TIMING_INFORMATION; + +typedef struct _SGX_DEVICE_MAP_ +{ + IMG_UINT32 ui32Flags; + + + IMG_SYS_PHYADDR sRegsSysPBase; + IMG_CPU_PHYADDR sRegsCpuPBase; + IMG_CPU_VIRTADDR pvRegsCpuVBase; + IMG_UINT32 ui32RegsSize; + +#if defined(SGX_FEATURE_HOST_PORT) + IMG_SYS_PHYADDR sHPSysPBase; + IMG_CPU_PHYADDR sHPCpuPBase; + IMG_UINT32 ui32HPSize; +#endif + + + IMG_SYS_PHYADDR sLocalMemSysPBase; + IMG_DEV_PHYADDR sLocalMemDevPBase; + IMG_CPU_PHYADDR sLocalMemCpuPBase; + IMG_UINT32 ui32LocalMemSize; + +#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE) + IMG_UINT32 ui32ExtSysCacheRegsSize; + IMG_DEV_PHYADDR sExtSysCacheRegsDevPBase; +#endif + + + IMG_UINT32 ui32IRQ; + +#if !defined(SGX_DYNAMIC_TIMING_INFO) + + SGX_TIMING_INFORMATION sTimingInfo; +#endif +#if defined(PDUMP) + + IMG_CHAR *pszPDumpDevName; +#endif +} SGX_DEVICE_MAP; + + +struct _PVRSRV_STUB_PBDESC_ +{ + IMG_UINT32 ui32RefCount; + IMG_UINT32 ui32TotalPBSize; + PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo; + PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo; + PVRSRV_KERNEL_MEM_INFO **ppsSubKernelMemInfos; + IMG_UINT32 ui32SubKernelMemInfosCount; + IMG_HANDLE hDevCookie; + PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo; + PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo; + PVRSRV_STUB_PBDESC *psNext; + PVRSRV_STUB_PBDESC **ppsThis; +}; + +typedef struct _PVRSRV_SGX_CCB_INFO_ +{ + PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo; + PVRSRV_KERNEL_MEM_INFO *psCCBCtlMemInfo; + SGXMKIF_COMMAND *psCommands; + IMG_UINT32 *pui32WriteOffset; + volatile IMG_UINT32 *pui32ReadOffset; +#if defined(PDUMP) + IMG_UINT32 ui32CCBDumpWOff; +#endif +} PVRSRV_SGX_CCB_INFO; + +PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode); + +IMG_VOID SGXOSTimer(IMG_VOID *pvData); + +IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_BOOL bHardwareRecovery, + IMG_UINT32 ui32PDUMPFlags); + +PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_BOOL bHardwareRecovery); +PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie); + +PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE hDevHandle, + PVRSRV_DEV_POWER_STATE eNewPowerState, + PVRSRV_DEV_POWER_STATE eCurrentPowerState); + +PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE hDevHandle, + PVRSRV_DEV_POWER_STATE eNewPowerState, + PVRSRV_DEV_POWER_STATE eCurrentPowerState); + +PVRSRV_ERROR SGXPreClockSpeedChange(IMG_HANDLE hDevHandle, + IMG_BOOL bIdleDevice, + PVRSRV_DEV_POWER_STATE eCurrentPowerState); + +PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE hDevHandle, + IMG_BOOL bIdleDevice, + PVRSRV_DEV_POWER_STATE eCurrentPowerState); + +IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo); + +PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode); + +#if defined(SGX_DYNAMIC_TIMING_INFO) +IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psSGXTimingInfo); +#endif + +#if defined(NO_HARDWARE) +static INLINE IMG_VOID NoHardwareGenerateEvent(PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_UINT32 ui32StatusRegister, + IMG_UINT32 ui32StatusValue, + IMG_UINT32 ui32StatusMask) +{ + IMG_UINT32 ui32RegVal; + + ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister); + + ui32RegVal &= ~ui32StatusMask; + ui32RegVal |= (ui32StatusValue & ui32StatusMask); + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister, ui32RegVal); +} +#endif + +#if defined(__cplusplus) +} +#endif + +#endif + diff --git a/drivers/gpu/pvr/sgx/sgxinit.c b/drivers/gpu/pvr/sgx/sgxinit.c new file mode 100644 index 0000000..1e60cf2 --- /dev/null +++ b/drivers/gpu/pvr/sgx/sgxinit.c @@ -0,0 +1,2557 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 <stddef.h> + +#include "sgxdefs.h" +#include "sgxmmu.h" +#include "services_headers.h" +#include "buffer_manager.h" +#include "sgxapi_km.h" +#include "sgxinfo.h" +#include "sgx_mkif_km.h" +#include "sgxconfig.h" +#include "sysconfig.h" +#include "pvr_bridge_km.h" + +#include "sgx_bridge_km.h" + +#include "pdump_km.h" +#include "ra.h" +#include "mmu.h" +#include "handle.h" +#include "perproc.h" + +#include "sgxutils.h" +#include "pvrversion.h" +#include "sgx_options.h" + +#include "lists.h" +#include "srvkm.h" + +#define VAR(x) #x + + +#define CHECK_SIZE(NAME) \ +{ \ + if (psSGXStructSizes->ui32Sizeof_##NAME != psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME) \ + { \ + PVR_DPF((PVR_DBG_ERROR, "SGXDevInitCompatCheck: Size check failed for SGXMKIF_%s (client) = %d bytes, (ukernel) = %d bytes\n", \ + VAR(NAME), \ + psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME, \ + psSGXStructSizes->ui32Sizeof_##NAME )); \ + bStructSizesFailed = IMG_TRUE; \ + } \ +} + +#if defined (SYS_USING_INTERRUPTS) +IMG_BOOL SGX_ISRHandler(IMG_VOID *pvData); +#endif + + +static +PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo, + PVRSRV_DEVICE_NODE *psDeviceNode); +#if defined(PDUMP) +static +PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode); +#endif + +static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE *psDeviceNode) +{ +#if defined(OS_SUPPORTS_IN_LISR) + if (OSInLISR(psDeviceNode->psSysData)) + { + + psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE; + } + else + { + SGXScheduleProcessQueuesKM(psDeviceNode); + } +#else + SGXScheduleProcessQueuesKM(psDeviceNode); +#endif +} + +static IMG_UINT32 DeinitDevInfo(PVRSRV_SGXDEV_INFO *psDevInfo) +{ + if (psDevInfo->psKernelCCBInfo != IMG_NULL) + { + + + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SGX_CCB_INFO), psDevInfo->psKernelCCBInfo, IMG_NULL); + } + + return PVRSRV_OK; +} + +static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc, + PVRSRV_DEVICE_NODE *psDeviceNode, + SGX_BRIDGE_INIT_INFO *psInitInfo) +{ + PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice; + PVRSRV_ERROR eError; + + PVRSRV_SGX_CCB_INFO *psKernelCCBInfo = IMG_NULL; + + PVR_UNREFERENCED_PARAMETER(psPerProc); + psDevInfo->sScripts = psInitInfo->sScripts; + + psDevInfo->psKernelCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBMemInfo; + psDevInfo->psKernelCCB = (PVRSRV_SGX_KERNEL_CCB *) psDevInfo->psKernelCCBMemInfo->pvLinAddrKM; + + psDevInfo->psKernelCCBCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBCtlMemInfo; + psDevInfo->psKernelCCBCtl = (PVRSRV_SGX_CCB_CTL *) psDevInfo->psKernelCCBCtlMemInfo->pvLinAddrKM; + + psDevInfo->psKernelCCBEventKickerMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBEventKickerMemInfo; + psDevInfo->pui32KernelCCBEventKicker = (IMG_UINT32 *)psDevInfo->psKernelCCBEventKickerMemInfo->pvLinAddrKM; + + psDevInfo->psKernelSGXHostCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXHostCtlMemInfo; + psDevInfo->psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM; + + psDevInfo->psKernelSGXTA3DCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXTA3DCtlMemInfo; + + psDevInfo->psKernelSGXMiscMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXMiscMemInfo; + +#if defined(SGX_SUPPORT_HWPROFILING) + psDevInfo->psKernelHWProfilingMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWProfilingMemInfo; +#endif +#if defined(SUPPORT_SGX_HWPERF) + psDevInfo->psKernelHWPerfCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWPerfCBMemInfo; +#endif + psDevInfo->psKernelTASigBufferMemInfo = psInitInfo->hKernelTASigBufferMemInfo; + psDevInfo->psKernel3DSigBufferMemInfo = psInitInfo->hKernel3DSigBufferMemInfo; +#if defined(FIX_HW_BRN_29702) + psDevInfo->psKernelCFIMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCFIMemInfo; +#endif +#if defined(FIX_HW_BRN_29823) + psDevInfo->psKernelDummyTermStreamMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelDummyTermStreamMemInfo; +#endif +#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) + psDevInfo->psKernelEDMStatusBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelEDMStatusBufferMemInfo; +#endif +#if defined(SGX_FEATURE_OVERLAPPED_SPM) + psDevInfo->psKernelTmpRgnHeaderMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpRgnHeaderMemInfo; +#endif +#if defined(SGX_FEATURE_SPM_MODE_0) + psDevInfo->psKernelTmpDPMStateMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpDPMStateMemInfo; +#endif + + psDevInfo->ui32ClientBuildOptions = psInitInfo->ui32ClientBuildOptions; + + + psDevInfo->sSGXStructSizes = psInitInfo->sSGXStructSizes; + + + + eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_SGX_CCB_INFO), + (IMG_VOID **)&psKernelCCBInfo, 0, + "SGX Circular Command Buffer Info"); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"InitDevInfo: Failed to alloc memory")); + goto failed_allockernelccb; + } + + + OSMemSet(psKernelCCBInfo, 0, sizeof(PVRSRV_SGX_CCB_INFO)); + psKernelCCBInfo->psCCBMemInfo = psDevInfo->psKernelCCBMemInfo; + psKernelCCBInfo->psCCBCtlMemInfo = psDevInfo->psKernelCCBCtlMemInfo; + psKernelCCBInfo->psCommands = psDevInfo->psKernelCCB->asCommands; + psKernelCCBInfo->pui32WriteOffset = &psDevInfo->psKernelCCBCtl->ui32WriteOffset; + psKernelCCBInfo->pui32ReadOffset = &psDevInfo->psKernelCCBCtl->ui32ReadOffset; + psDevInfo->psKernelCCBInfo = psKernelCCBInfo; + + + + OSMemCopy(psDevInfo->aui32HostKickAddr, psInitInfo->aui32HostKickAddr, + SGXMKIF_CMD_MAX * sizeof(psDevInfo->aui32HostKickAddr[0])); + + psDevInfo->bForcePTOff = IMG_FALSE; + + psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl; + + psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0; + psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1; + psDevInfo->ui32ClkGateStatusReg = psInitInfo->ui32ClkGateStatusReg; + psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask; +#if defined(SGX_FEATURE_MP) + psDevInfo->ui32MasterClkGateStatusReg = psInitInfo->ui32MasterClkGateStatusReg; + psDevInfo->ui32MasterClkGateStatusMask = psInitInfo->ui32MasterClkGateStatusMask; + psDevInfo->ui32MasterClkGateStatus2Reg = psInitInfo->ui32MasterClkGateStatus2Reg; + psDevInfo->ui32MasterClkGateStatus2Mask = psInitInfo->ui32MasterClkGateStatus2Mask; +#endif + + + + OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData, sizeof(psDevInfo->asSGXDevData)); + + return PVRSRV_OK; + +failed_allockernelccb: + DeinitDevInfo(psDevInfo); + + return eError; +} + + + + +static PVRSRV_ERROR SGXRunScript(PVRSRV_SGXDEV_INFO *psDevInfo, SGX_INIT_COMMAND *psScript, IMG_UINT32 ui32NumInitCommands) +{ + IMG_UINT32 ui32PC; + SGX_INIT_COMMAND *psComm; + + for (ui32PC = 0, psComm = psScript; + ui32PC < ui32NumInitCommands; + ui32PC++, psComm++) + { + switch (psComm->eOp) + { + case SGX_INIT_OP_WRITE_HW_REG: + { + OSWriteHWReg(psDevInfo->pvRegsBaseKM, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value); + PDUMPCOMMENT("SGXRunScript: Write HW reg operation"); + PDUMPREG(SGX_PDUMPREG_NAME, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value); + break; + } +#if defined(PDUMP) + case SGX_INIT_OP_PDUMP_HW_REG: + { + PDUMPCOMMENT("SGXRunScript: Dump HW reg operation"); + PDUMPREG(SGX_PDUMPREG_NAME, psComm->sPDumpHWReg.ui32Offset, psComm->sPDumpHWReg.ui32Value); + break; + } +#endif + case SGX_INIT_OP_HALT: + { + return PVRSRV_OK; + } + case SGX_INIT_OP_ILLEGAL: + + default: + { + PVR_DPF((PVR_DBG_ERROR,"SGXRunScript: PC %d: Illegal command: %d", ui32PC, psComm->eOp)); + return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION; + } + } + + } + + return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION; +} + +PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_BOOL bHardwareRecovery) +{ + PVRSRV_ERROR eError; + PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo; + SGXMKIF_HOST_CTL *psSGXHostCtl = psSGXHostCtlMemInfo->pvLinAddrKM; + static IMG_BOOL bFirstTime = IMG_TRUE; +#if defined(PDUMP) + IMG_BOOL bPDumpIsSuspended = PDumpIsSuspended(); +#endif + + + + PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 1\n"); + eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1, SGX_MAX_INIT_COMMANDS); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 1) failed (%d)", eError)); + return eError; + } + PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 1\n"); + + + SGXReset(psDevInfo, bFirstTime || bHardwareRecovery, PDUMP_FLAGS_CONTINUOUS); + +#if defined(EUR_CR_POWER) +#if defined(SGX531) + + + + + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 1); + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 1); +#else + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 0); + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 0); +#endif +#endif + + + *psDevInfo->pui32KernelCCBEventKicker = 0; +#if defined(PDUMP) + if (!bPDumpIsSuspended) + { + psDevInfo->ui32KernelCCBEventKickerDumpVal = 0; + PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal, + psDevInfo->psKernelCCBEventKickerMemInfo, 0, + sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo)); + } +#endif + + + + PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 2\n"); + eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2, SGX_MAX_INIT_COMMANDS); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 2) failed (%d)", eError)); + return eError; + } + PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 2\n"); + + + psSGXHostCtl->ui32HostClock = OSClockus(); + + psSGXHostCtl->ui32InitStatus = 0; +#if defined(PDUMP) + PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, + "Reset the SGX microkernel initialisation status\n"); + PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32InitStatus), + sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psSGXHostCtlMemInfo)); + PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, + "Initialise the microkernel\n"); +#endif + +#if defined(SGX_FEATURE_MULTI_EVENT_KICK) + OSWriteMemoryBarrier(); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, + SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), + EUR_CR_EVENT_KICK2_NOW_MASK); +#else + *psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF; + OSWriteMemoryBarrier(); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, + SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), + EUR_CR_EVENT_KICK_NOW_MASK); +#endif + + OSMemoryBarrier(); + +#if defined(PDUMP) + + + if (!bPDumpIsSuspended) + { +#if defined(SGX_FEATURE_MULTI_EVENT_KICK) + PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK); +#else + psDevInfo->ui32KernelCCBEventKickerDumpVal = 1; + PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, + "First increment of the SGX event kicker value\n"); + PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal, + psDevInfo->psKernelCCBEventKickerMemInfo, + 0, + sizeof(IMG_UINT32), + PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo)); + PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK); +#endif + } +#endif + +#if !defined(NO_HARDWARE) + + + if (PollForValueKM(&psSGXHostCtl->ui32InitStatus, + PVRSRV_USSE_EDM_INIT_COMPLETE, + PVRSRV_USSE_EDM_INIT_COMPLETE, + MAX_HW_TIME_US/WAIT_TRY_COUNT, + WAIT_TRY_COUNT) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "SGXInitialise: Wait for uKernel initialisation failed")); + #if !defined(FIX_HW_BRN_23281) + PVR_DBG_BREAK; + #endif + return PVRSRV_ERROR_RETRY; + } +#endif + +#if defined(PDUMP) + PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, + "Wait for the SGX microkernel initialisation to complete"); + PDUMPMEMPOL(psSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32InitStatus), + PVRSRV_USSE_EDM_INIT_COMPLETE, + PVRSRV_USSE_EDM_INIT_COMPLETE, + PDUMP_POLL_OPERATOR_EQUAL, + PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psSGXHostCtlMemInfo)); +#endif + +#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT) + + + + WorkaroundBRN22997ReadHostPort(psDevInfo); +#endif + + PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset == psDevInfo->psKernelCCBCtl->ui32WriteOffset); + + bFirstTime = IMG_FALSE; + + return PVRSRV_OK; +} + +PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie) + +{ + PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *) hDevCookie; + PVRSRV_ERROR eError; + + + if (psDevInfo->pvRegsBaseKM == IMG_NULL) + { + return PVRSRV_OK; + } + + eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands, SGX_MAX_DEINIT_COMMANDS); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXDeinitialise: SGXRunScript failed (%d)", eError)); + return eError; + } + + return PVRSRV_OK; +} + + +static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode) +{ + IMG_HANDLE hDevMemHeap = IMG_NULL; + PVRSRV_SGXDEV_INFO *psDevInfo; + IMG_HANDLE hKernelDevMemContext; + IMG_DEV_PHYADDR sPDDevPAddr; + IMG_UINT32 i; + PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode; + DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap; + PVRSRV_ERROR eError; + + + PDUMPCOMMENT("SGX Core Version Information: %s", SGX_CORE_FRIENDLY_NAME); + + #if defined(SGX_FEATURE_MP) + PDUMPCOMMENT("SGX Multi-processor: %d cores", SGX_FEATURE_MP_CORE_COUNT); + #endif + +#if (SGX_CORE_REV == 0) + PDUMPCOMMENT("SGX Core Revision Information: head RTL"); +#else + PDUMPCOMMENT("SGX Core Revision Information: %d", SGX_CORE_REV); +#endif + + #if defined(SGX_FEATURE_SYSTEM_CACHE) + PDUMPCOMMENT("SGX System Level Cache is present\r\n"); + #if defined(SGX_BYPASS_SYSTEM_CACHE) + PDUMPCOMMENT("SGX System Level Cache is bypassed\r\n"); + #endif + #endif + + PDUMPCOMMENT("SGX Initialisation Part 1"); + + + if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP, + sizeof(PVRSRV_SGXDEV_INFO), + (IMG_VOID **)&psDevInfo, IMG_NULL, + "SGX Device Info") != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1 : Failed to alloc memory for DevInfo")); + return (PVRSRV_ERROR_OUT_OF_MEMORY); + } + OSMemSet (psDevInfo, 0, sizeof(PVRSRV_SGXDEV_INFO)); + + + psDevInfo->eDeviceType = DEV_DEVICE_TYPE; + psDevInfo->eDeviceClass = DEV_DEVICE_CLASS; + + + psDeviceNode->pvDevice = (IMG_PVOID)psDevInfo; + + + psDevInfo->pvDeviceMemoryHeap = (IMG_VOID*)psDeviceMemoryHeap; + + + hKernelDevMemContext = BM_CreateContext(psDeviceNode, + &sPDDevPAddr, + IMG_NULL, + IMG_NULL); + if (hKernelDevMemContext == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1: Failed BM_CreateContext")); + return PVRSRV_ERROR_OUT_OF_MEMORY; + } + + psDevInfo->sKernelPDDevPAddr = sPDDevPAddr; + + + for(i=0; i<psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++) + { + switch(psDeviceMemoryHeap[i].DevMemHeapType) + { + case DEVICE_MEMORY_HEAP_KERNEL: + case DEVICE_MEMORY_HEAP_SHARED: + case DEVICE_MEMORY_HEAP_SHARED_EXPORTED: + { + hDevMemHeap = BM_CreateHeap (hKernelDevMemContext, + &psDeviceMemoryHeap[i]); + + + + psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap; + break; + } + } + } +#if defined(PDUMP) + if(hDevMemHeap) + { + + psDevInfo->sMMUAttrib = *((BM_HEAP*)hDevMemHeap)->psMMUAttrib; + } +#endif + eError = MMU_BIFResetPDAlloc(psDevInfo); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"DevInitSGX : Failed to alloc memory for BIF reset")); + return eError; + } + + return PVRSRV_OK; +} + +IMG_EXPORT +PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo) +{ + PVRSRV_DEVICE_NODE *psDeviceNode; + PVRSRV_SGXDEV_INFO *psDevInfo; + PVRSRV_ERROR eError; + + PDUMPCOMMENT("SGXGetInfoForSrvinit"); + + psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle; + psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice; + + psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr; + + eError = PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXGetInfoForSrvinit: PVRSRVGetDeviceMemHeapsKM failed (%d)", eError)); + return eError; + } + + return eError; +} + +IMG_EXPORT +PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc, + IMG_HANDLE hDevHandle, + SGX_BRIDGE_INIT_INFO *psInitInfo) +{ + PVRSRV_DEVICE_NODE *psDeviceNode; + PVRSRV_SGXDEV_INFO *psDevInfo; + PVRSRV_ERROR eError; + SGX_DEVICE_MAP *psSGXDeviceMap; + PVRSRV_DEV_POWER_STATE eDefaultPowerState; + + PDUMPCOMMENT("SGX Initialisation Part 2"); + + psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle; + psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice; + + + + eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to load EDM program")); + goto failed_init_dev_info; + } + + + eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX, + (IMG_VOID**)&psSGXDeviceMap); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to get device memory map!")); + return PVRSRV_ERROR_INIT_FAILURE; + } + + + if (psSGXDeviceMap->pvRegsCpuVBase) + { + psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase; + } + else + { + + psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase, + psSGXDeviceMap->ui32RegsSize, + PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED, + IMG_NULL); + if (!psDevInfo->pvRegsBaseKM) + { + PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in regs\n")); + return PVRSRV_ERROR_BAD_MAPPING; + } + } + psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize; + psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase; + + +#if defined(SGX_FEATURE_HOST_PORT) + if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT) + { + + psDevInfo->pvHostPortBaseKM = OSMapPhysToLin(psSGXDeviceMap->sHPCpuPBase, + psSGXDeviceMap->ui32HPSize, + PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED, + IMG_NULL); + if (!psDevInfo->pvHostPortBaseKM) + { + PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in host port\n")); + return PVRSRV_ERROR_BAD_MAPPING; + } + psDevInfo->ui32HPSize = psSGXDeviceMap->ui32HPSize; + psDevInfo->sHPSysPAddr = psSGXDeviceMap->sHPSysPBase; + } +#endif + +#if defined (SYS_USING_INTERRUPTS) + + + psDeviceNode->pvISRData = psDeviceNode; + + PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler); + +#endif + + + psDevInfo->psSGXHostCtl->ui32PowerStatus |= PVRSRV_USSE_EDM_POWMAN_NO_WORK; + eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF; + + eError = PVRSRVRegisterPowerDevice (psDeviceNode->sDevId.ui32DeviceIndex, + &SGXPrePowerState, &SGXPostPowerState, + &SGXPreClockSpeedChange, &SGXPostClockSpeedChange, + (IMG_HANDLE)psDeviceNode, + PVRSRV_DEV_POWER_STATE_OFF, + eDefaultPowerState); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: failed to register device with power manager")); + return eError; + } + +#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT) + eError = WorkaroundBRN22997Alloc(psDeviceNode); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to alloc memory for BRN22997 workaround")); + return eError; + } +#endif + +#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE) + + psDevInfo->ui32ExtSysCacheRegsSize = psSGXDeviceMap->ui32ExtSysCacheRegsSize; + psDevInfo->sExtSysCacheRegsDevPBase = psSGXDeviceMap->sExtSysCacheRegsDevPBase; + eError = MMU_MapExtSystemCacheRegs(psDeviceNode); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to map external system cache registers")); + return eError; + } +#endif + + + + OSMemSet(psDevInfo->psKernelCCB, 0, sizeof(PVRSRV_SGX_KERNEL_CCB)); + OSMemSet(psDevInfo->psKernelCCBCtl, 0, sizeof(PVRSRV_SGX_CCB_CTL)); + OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker)); + PDUMPCOMMENT("Initialise Kernel CCB"); + PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBMemInfo, 0, sizeof(PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo)); + PDUMPCOMMENT("Initialise Kernel CCB Control"); + PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBCtlMemInfo, 0, sizeof(PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo)); + PDUMPCOMMENT("Initialise Kernel CCB Event Kicker"); + PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo)); + + return PVRSRV_OK; + +failed_init_dev_info: + return eError; +} + +static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode) +{ + PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode; + PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice; + PVRSRV_ERROR eError; + IMG_UINT32 ui32Heap; + DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; + SGX_DEVICE_MAP *psSGXDeviceMap; + + if (!psDevInfo) + { + + PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Null DevInfo")); + return PVRSRV_OK; + } + +#if defined(SUPPORT_HW_RECOVERY) + if (psDevInfo->hTimer) + { + eError = OSRemoveTimer(psDevInfo->hTimer); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to remove timer")); + return eError; + } + psDevInfo->hTimer = IMG_NULL; + } +#endif + +#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE) + + eError = MMU_UnmapExtSystemCacheRegs(psDeviceNode); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to unmap ext system cache registers")); + return eError; + } +#endif + +#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT) + WorkaroundBRN22997Free(psDeviceNode); +#endif + + MMU_BIFResetPDFree(psDevInfo); + + + + DeinitDevInfo(psDevInfo); + + + psDeviceMemoryHeap = (DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap; + for(ui32Heap=0; ui32Heap<psDeviceNode->sDevMemoryInfo.ui32HeapCount; ui32Heap++) + { + switch(psDeviceMemoryHeap[ui32Heap].DevMemHeapType) + { + case DEVICE_MEMORY_HEAP_KERNEL: + case DEVICE_MEMORY_HEAP_SHARED: + case DEVICE_MEMORY_HEAP_SHARED_EXPORTED: + { + if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap != IMG_NULL) + { + BM_DestroyHeap(psDeviceMemoryHeap[ui32Heap].hDevMemHeap); + } + break; + } + } + } + + + eError = BM_DestroyContext(psDeviceNode->sDevMemoryInfo.pBMKernelContext, IMG_NULL); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX : Failed to destroy kernel context")); + return eError; + } + + + eError = PVRSRVRemovePowerDevice (((PVRSRV_DEVICE_NODE*)pvDeviceNode)->sDevId.ui32DeviceIndex); + if (eError != PVRSRV_OK) + { + return eError; + } + + eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX, + (IMG_VOID**)&psSGXDeviceMap); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to get device memory map!")); + return eError; + } + + + if (!psSGXDeviceMap->pvRegsCpuVBase) + { + + if (psDevInfo->pvRegsBaseKM != IMG_NULL) + { + OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM, + psDevInfo->ui32RegSize, + PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED, + IMG_NULL); + } + } + +#if defined(SGX_FEATURE_HOST_PORT) + if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT) + { + + if (psDevInfo->pvHostPortBaseKM != IMG_NULL) + { + OSUnMapPhysToLin(psDevInfo->pvHostPortBaseKM, + psDevInfo->ui32HPSize, + PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED, + IMG_NULL); + } + } +#endif + + + + OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, + sizeof(PVRSRV_SGXDEV_INFO), + psDevInfo, + 0); + + psDeviceNode->pvDevice = IMG_NULL; + + if (psDeviceMemoryHeap != IMG_NULL) + { + + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID, + psDeviceMemoryHeap, + 0); + } + + return PVRSRV_OK; +} + + +static IMG_VOID SGXDumpDebugReg (PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_UINT32 ui32CoreNum, + IMG_CHAR *pszName, + IMG_UINT32 ui32RegAddr) +{ + IMG_UINT32 ui32RegVal; + ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(ui32RegAddr, ui32CoreNum)); + PVR_LOG(("(P%u) %s%08X", ui32CoreNum, pszName, ui32RegVal)); +} + +static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_BOOL bDumpSGXRegs) +{ + IMG_UINT32 ui32CoreNum; + + PVR_LOG(("SGX debug (%s)", PVRVERSION_STRING)); + + if (bDumpSGXRegs) + { + PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Linear): 0x%08X", (IMG_UINTPTR_T)psDevInfo->pvRegsBaseKM)); + PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Physical): 0x%08X", psDevInfo->sRegsPhysBase.uiAddr)); + + for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT; ui32CoreNum++) + { + + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS: ", EUR_CR_EVENT_STATUS); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS2: ", EUR_CR_EVENT_STATUS2); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_CTRL: ", EUR_CR_BIF_CTRL); + #if defined(EUR_CR_BIF_BANK0) + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_BANK0: ", EUR_CR_BIF_BANK0); + #endif + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_INT_STAT: ", EUR_CR_BIF_INT_STAT); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_FAULT: ", EUR_CR_BIF_FAULT); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_MEM_REQ_STAT: ", EUR_CR_BIF_MEM_REQ_STAT); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_CLKGATECTL: ", EUR_CR_CLKGATECTL); + #if defined(EUR_CR_PDS_PC_BASE) + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_PDS_PC_BASE: ", EUR_CR_PDS_PC_BASE); + #endif + } + } + + + + QueueDumpDebugInfo(); + + { + + + IMG_UINT32 *pui32HostCtlBuffer = (IMG_UINT32 *)psDevInfo->psSGXHostCtl; + IMG_UINT32 ui32LoopCounter; + + PVR_LOG(("SGX Host control:")); + + for (ui32LoopCounter = 0; + ui32LoopCounter < sizeof(*psDevInfo->psSGXHostCtl) / sizeof(*pui32HostCtlBuffer); + ui32LoopCounter += 4) + { + PVR_LOG(("\t(HC-%X) 0x%08X 0x%08X 0x%08X 0x%08X", ui32LoopCounter * sizeof(*pui32HostCtlBuffer), + pui32HostCtlBuffer[ui32LoopCounter + 0], pui32HostCtlBuffer[ui32LoopCounter + 1], + pui32HostCtlBuffer[ui32LoopCounter + 2], pui32HostCtlBuffer[ui32LoopCounter + 3])); + } + } + + { + + + IMG_UINT32 *pui32TA3DCtlBuffer = psDevInfo->psKernelSGXTA3DCtlMemInfo->pvLinAddrKM; + IMG_UINT32 ui32LoopCounter; + + PVR_LOG(("SGX TA/3D control:")); + + for (ui32LoopCounter = 0; + ui32LoopCounter < psDevInfo->psKernelSGXTA3DCtlMemInfo->ui32AllocSize / sizeof(*pui32TA3DCtlBuffer); + ui32LoopCounter += 4) + { + PVR_LOG(("\t(T3C-%X) 0x%08X 0x%08X 0x%08X 0x%08X", ui32LoopCounter * sizeof(*pui32TA3DCtlBuffer), + pui32TA3DCtlBuffer[ui32LoopCounter + 0], pui32TA3DCtlBuffer[ui32LoopCounter + 1], + pui32TA3DCtlBuffer[ui32LoopCounter + 2], pui32TA3DCtlBuffer[ui32LoopCounter + 3])); + } + } + + #if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) + { + IMG_UINT32 *pui32MKTraceBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM; + IMG_UINT32 ui32LastStatusCode, ui32WriteOffset; + + ui32LastStatusCode = *pui32MKTraceBuffer; + pui32MKTraceBuffer++; + ui32WriteOffset = *pui32MKTraceBuffer; + pui32MKTraceBuffer++; + + PVR_LOG(("Last SGX microkernel status code: %08X", ui32LastStatusCode)); + + #if defined(PVRSRV_DUMP_MK_TRACE) + + + { + IMG_UINT32 ui32LoopCounter; + + for (ui32LoopCounter = 0; + ui32LoopCounter < SGXMK_TRACE_BUFFER_SIZE; + ui32LoopCounter++) + { + IMG_UINT32 *pui32BufPtr; + pui32BufPtr = pui32MKTraceBuffer + + (((ui32WriteOffset + ui32LoopCounter) % SGXMK_TRACE_BUFFER_SIZE) * 4); + PVR_LOG(("\t(MKT-%X) %08X %08X %08X %08X", ui32LoopCounter, + pui32BufPtr[2], pui32BufPtr[3], pui32BufPtr[1], pui32BufPtr[0])); + } + } + #endif + } + #endif + + { + + + PVR_LOG(("SGX Kernel CCB WO:0x%X RO:0x%X", + psDevInfo->psKernelCCBCtl->ui32WriteOffset, + psDevInfo->psKernelCCBCtl->ui32ReadOffset)); + + #if defined(PVRSRV_DUMP_KERNEL_CCB) + { + IMG_UINT32 ui32LoopCounter; + + for (ui32LoopCounter = 0; + ui32LoopCounter < sizeof(psDevInfo->psKernelCCB->asCommands) / + sizeof(psDevInfo->psKernelCCB->asCommands[0]); + ui32LoopCounter++) + { + SGXMKIF_COMMAND *psCommand = &psDevInfo->psKernelCCB->asCommands[ui32LoopCounter]; + + PVR_LOG(("\t(KCCB-%X) %08X %08X - %08X %08X %08X %08X", ui32LoopCounter, + psCommand->ui32ServiceAddress, psCommand->ui32CacheControl, + psCommand->ui32Data[0], psCommand->ui32Data[1], + psCommand->ui32Data[2], psCommand->ui32Data[3])); + } + } + #endif + } +} + + +#if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY) +static +IMG_VOID HWRecoveryResetSGX (PVRSRV_DEVICE_NODE *psDeviceNode, + IMG_UINT32 ui32Component, + IMG_UINT32 ui32CallerID) +{ + PVRSRV_ERROR eError; + PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice; + SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl; + + PVR_UNREFERENCED_PARAMETER(ui32Component); + + + + eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE); + if(eError != PVRSRV_OK) + { + + + + PVR_DPF((PVR_DBG_WARNING,"HWRecoveryResetSGX: Power transition in progress")); + return; + } + + psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_HWR; + + PVR_LOG(("HWRecoveryResetSGX: SGX Hardware Recovery triggered")); + + SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE); + + + PDUMPSUSPEND(); + + +#if defined(FIX_HW_BRN_23281) + + for (eError = PVRSRV_ERROR_RETRY; eError == PVRSRV_ERROR_RETRY;) +#endif + { + eError = SGXInitialise(psDevInfo, IMG_TRUE); + } + + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"HWRecoveryResetSGX: SGXInitialise failed (%d)", eError)); + } + + + PDUMPRESUME(); + + PVRSRVPowerUnlock(ui32CallerID); + + + SGXScheduleProcessQueuesKM(psDeviceNode); + + + + PVRSRVProcessQueues(ui32CallerID, IMG_TRUE); +} +#endif + + +#if defined(SUPPORT_HW_RECOVERY) +IMG_VOID SGXOSTimer(IMG_VOID *pvData) +{ + PVRSRV_DEVICE_NODE *psDeviceNode = pvData; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + static IMG_UINT32 ui32EDMTasks = 0; + static IMG_UINT32 ui32LockupCounter = 0; + static IMG_UINT32 ui32NumResets = 0; +#if defined(FIX_HW_BRN_31093) + static IMG_BOOL bBRN31093Inval = IMG_FALSE; +#endif + IMG_UINT32 ui32CurrentEDMTasks; + IMG_BOOL bLockup = IMG_FALSE; + IMG_BOOL bPoweredDown; + + + psDevInfo->ui32TimeStamp++; + +#if defined(NO_HARDWARE) + bPoweredDown = IMG_TRUE; +#else + bPoweredDown = (SGXIsDevicePowered(psDeviceNode)) ? IMG_FALSE : IMG_TRUE; +#endif + + + + if (bPoweredDown) + { + ui32LockupCounter = 0; + #if defined(FIX_HW_BRN_31093) + bBRN31093Inval = IMG_FALSE; + #endif + } + else + { + + ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg0); + if (psDevInfo->ui32EDMTaskReg1 != 0) + { + ui32CurrentEDMTasks ^= OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg1); + } + if ((ui32CurrentEDMTasks == ui32EDMTasks) && + (psDevInfo->ui32NumResets == ui32NumResets)) + { + ui32LockupCounter++; + if (ui32LockupCounter == 3) + { + ui32LockupCounter = 0; + + #if defined(FIX_HW_BRN_31093) + if (bBRN31093Inval == IMG_FALSE) + { + + #if defined(FIX_HW_BRN_29997) + IMG_UINT32 ui32BIFCtrl; + + ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_PAUSE_MASK); + + OSWaitus(200 * 1000000 / psDevInfo->ui32CoreClockSpeed); + #endif + + bBRN31093Inval = IMG_TRUE; + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, EUR_CR_BIF_CTRL_INVAL_PTE_MASK); + + OSWaitus(200 * 1000000 / psDevInfo->ui32CoreClockSpeed); + + #if defined(FIX_HW_BRN_29997) + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl); + #endif + } + else + #endif + { + PVR_DPF((PVR_DBG_ERROR, "SGXOSTimer() detected SGX lockup (0x%x tasks)", ui32EDMTasks)); + + bLockup = IMG_TRUE; + } + } + } + else + { + #if defined(FIX_HW_BRN_31093) + bBRN31093Inval = IMG_FALSE; + #endif + ui32LockupCounter = 0; + ui32EDMTasks = ui32CurrentEDMTasks; + ui32NumResets = psDevInfo->ui32NumResets; + } + } + + if (bLockup) + { + SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl; + + + psSGXHostCtl->ui32HostDetectedLockups ++; + + + HWRecoveryResetSGX(psDeviceNode, 0, KERNEL_ID); + } +} +#endif + + +#if defined(SYS_USING_INTERRUPTS) + +IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData) +{ + IMG_BOOL bInterruptProcessed = IMG_FALSE; + + + + { + IMG_UINT32 ui32EventStatus, ui32EventEnable; + IMG_UINT32 ui32EventClear = 0; +#if defined(SGX_FEATURE_DATA_BREAKPOINTS) + IMG_UINT32 ui32EventStatus2, ui32EventEnable2; +#endif + IMG_UINT32 ui32EventClear2 = 0; + PVRSRV_DEVICE_NODE *psDeviceNode; + PVRSRV_SGXDEV_INFO *psDevInfo; + + + if(pvData == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "SGX_ISRHandler: Invalid params\n")); + return bInterruptProcessed; + } + + psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData; + psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice; + + ui32EventStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS); + ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE); + + + ui32EventStatus &= ui32EventEnable; + +#if defined(SGX_FEATURE_DATA_BREAKPOINTS) + ui32EventStatus2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2); + ui32EventEnable2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE2); + + + ui32EventStatus2 &= ui32EventEnable2; +#endif + + + + if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK) + { + ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK; + } + +#if defined(SGX_FEATURE_DATA_BREAKPOINTS) + if (ui32EventStatus2 & EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_MASK) + { + ui32EventClear2 |= EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_MASK; + } + + if (ui32EventStatus2 & EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK) + { + ui32EventClear2 |= EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK; + } +#endif + + if (ui32EventClear || ui32EventClear2) + { + bInterruptProcessed = IMG_TRUE; + + + ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK; + + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32EventClear); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32EventClear2); + } + } + + return bInterruptProcessed; +} + + +static IMG_VOID SGX_MISRHandler (IMG_VOID *pvData) +{ + PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData; + PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice; + SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl; + + if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) != 0UL) && + ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) == 0UL)) + { + HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID); + } + +#if defined(OS_SUPPORTS_IN_LISR) + if (psDeviceNode->bReProcessDeviceCommandComplete) + { + SGXScheduleProcessQueuesKM(psDeviceNode); + } +#endif + + SGXTestActivePowerEvent(psDeviceNode, ISR_ID); +} +#endif + + + +#if defined(SUPPORT_MEMORY_TILING) +PVRSRV_ERROR SGX_AllocMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode, + PVRSRV_KERNEL_MEM_INFO *psMemInfo, + IMG_UINT32 ui32TilingStride, + IMG_UINT32 *pui32RangeIndex) +{ +#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS) + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + IMG_UINT32 i; + IMG_UINT32 ui32Start; + IMG_UINT32 ui32End; + IMG_UINT32 ui32Offset; + IMG_UINT32 ui32Val; + + + for(i=0; i<10; i++) + { + if((psDevInfo->ui32MemTilingUsage & (1U << i)) == 0) + { + + psDevInfo->ui32MemTilingUsage |= 1U << i; + + *pui32RangeIndex = i; + goto RangeAllocated; + } + } + + PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: all tiling ranges in use")); + return PVRSRV_ERROR_EXCEEDED_HW_LIMITS; + +RangeAllocated: + ui32Offset = EUR_CR_BIF_TILE0 + (i<<2); + + ui32Start = psMemInfo->sDevVAddr.uiAddr; + ui32End = ui32Start + psMemInfo->ui32AllocSize + SGX_MMU_PAGE_SIZE - 1; + + ui32Val = ((ui32TilingStride << EUR_CR_BIF_TILE0_CFG_SHIFT) & EUR_CR_BIF_TILE0_CFG_MASK) + | (((ui32End>>20) << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK) + | (((ui32Start>>20) << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK) + | (0x8 << EUR_CR_BIF_TILE0_CFG_SHIFT); + + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val); + PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val); + + ui32Offset = EUR_CR_BIF_TILE0_ADDR_EXT + (i<<2); + + ui32Val = (((ui32End>>12) << EUR_CR_BIF_TILE0_ADDR_EXT_MAX_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MAX_MASK) + | (((ui32Start>>12) << EUR_CR_BIF_TILE0_ADDR_EXT_MIN_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MIN_MASK); + + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val); + PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val); + + return PVRSRV_OK; +#else + PVR_UNREFERENCED_PARAMETER(psDeviceNode); + PVR_UNREFERENCED_PARAMETER(psMemInfo); + PVR_UNREFERENCED_PARAMETER(ui32TilingStride); + PVR_UNREFERENCED_PARAMETER(pui32RangeIndex); + + PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: device does not support memory tiling")); + return PVRSRV_ERROR_NOT_SUPPORTED; +#endif +} + +PVRSRV_ERROR SGX_FreeMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode, + IMG_UINT32 ui32RangeIndex) +{ +#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS) + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + IMG_UINT32 ui32Offset; + IMG_UINT32 ui32Val; + + if(ui32RangeIndex >= 10) + { + PVR_DPF((PVR_DBG_ERROR,"SGX_FreeMemTilingRange: invalid Range index ")); + return PVRSRV_ERROR_INVALID_PARAMS; + } + + + psDevInfo->ui32MemTilingUsage &= ~(1<<ui32RangeIndex); + + + ui32Offset = EUR_CR_BIF_TILE0 + (ui32RangeIndex<<2); + ui32Val = 0; + + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val); + PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val); + + return PVRSRV_OK; +#else + PVR_UNREFERENCED_PARAMETER(psDeviceNode); + PVR_UNREFERENCED_PARAMETER(ui32RangeIndex); + + PVR_DPF((PVR_DBG_ERROR,"SGX_FreeMemTilingRange: device does not support memory tiling")); + return PVRSRV_ERROR_NOT_SUPPORTED; +#endif +} +#endif + + +PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode) +{ + DEVICE_MEMORY_INFO *psDevMemoryInfo; + DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; + + + psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE; + psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS; +#if defined(PDUMP) + { + + SGX_DEVICE_MAP *psSGXDeviceMemMap; + SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX, + (IMG_VOID**)&psSGXDeviceMemMap); + + psDeviceNode->sDevId.pszPDumpDevName = psSGXDeviceMemMap->pszPDumpDevName; + PVR_ASSERT(psDeviceNode->sDevId.pszPDumpDevName != IMG_NULL); + } + + psDeviceNode->sDevId.pszPDumpRegName = SGX_PDUMPREG_NAME; +#endif + + psDeviceNode->pfnInitDevice = &DevInitSGXPart1; + psDeviceNode->pfnDeInitDevice = &DevDeInitSGX; + + psDeviceNode->pfnInitDeviceCompatCheck = &SGXDevInitCompatCheck; +#if defined(PDUMP) + psDeviceNode->pfnPDumpInitDevice = &SGXResetPDump; + psDeviceNode->pfnMMUGetContextID = &MMU_GetPDumpContextID; +#endif + + + psDeviceNode->pfnMMUInitialise = &MMU_Initialise; + psDeviceNode->pfnMMUFinalise = &MMU_Finalise; + psDeviceNode->pfnMMUInsertHeap = &MMU_InsertHeap; + psDeviceNode->pfnMMUCreate = &MMU_Create; + psDeviceNode->pfnMMUDelete = &MMU_Delete; + psDeviceNode->pfnMMUAlloc = &MMU_Alloc; + psDeviceNode->pfnMMUFree = &MMU_Free; + psDeviceNode->pfnMMUMapPages = &MMU_MapPages; + psDeviceNode->pfnMMUMapShadow = &MMU_MapShadow; + psDeviceNode->pfnMMUUnmapPages = &MMU_UnmapPages; + psDeviceNode->pfnMMUMapScatter = &MMU_MapScatter; + psDeviceNode->pfnMMUGetPhysPageAddr = &MMU_GetPhysPageAddr; + psDeviceNode->pfnMMUGetPDDevPAddr = &MMU_GetPDDevPAddr; +#if defined(SUPPORT_PDUMP_MULTI_PROCESS) + psDeviceNode->pfnMMUIsHeapShared = &MMU_IsHeapShared; +#endif + +#if defined (SYS_USING_INTERRUPTS) + + + psDeviceNode->pfnDeviceISR = SGX_ISRHandler; + psDeviceNode->pfnDeviceMISR = SGX_MISRHandler; +#endif + +#if defined(SUPPORT_MEMORY_TILING) + psDeviceNode->pfnAllocMemTilingRange = SGX_AllocMemTilingRange; + psDeviceNode->pfnFreeMemTilingRange = SGX_FreeMemTilingRange; +#endif + + + + psDeviceNode->pfnDeviceCommandComplete = &SGXCommandComplete; + + + + psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo; + + psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_FEATURE_ADDRESS_SPACE_SIZE; + + + psDevMemoryInfo->ui32Flags = 0; + + + if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, + sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID, + (IMG_VOID **)&psDevMemoryInfo->psDeviceMemoryHeap, 0, + "Array of Device Memory Heap Info") != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXRegisterDevice : Failed to alloc memory for DEVICE_MEMORY_HEAP_INFO")); + return (PVRSRV_ERROR_OUT_OF_MEMORY); + } + OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0, sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID); + + psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap; + + + + + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_HEAP_BASE; + psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_HEAP_SIZE; + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_SINGLE_PROCESS; + psDeviceMemoryHeap->pszName = "General"; + psDeviceMemoryHeap->pszBSName = "General BS"; + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; +#if !defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) + + psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap); +#endif + psDeviceMemoryHeap++; + + + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_TADATA_HEAP_BASE; + psDeviceMemoryHeap->ui32HeapSize = SGX_TADATA_HEAP_SIZE; + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_MULTI_PROCESS; + psDeviceMemoryHeap->pszName = "TA Data"; + psDeviceMemoryHeap->pszBSName = "TA Data BS"; + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++; + + + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_CODE_HEAP_BASE; + psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_CODE_HEAP_SIZE; + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_MULTI_PROCESS; + psDeviceMemoryHeap->pszName = "Kernel Code"; + psDeviceMemoryHeap->pszBSName = "Kernel Code BS"; + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED; + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++; + + + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_DATA_HEAP_BASE; + psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_DATA_HEAP_SIZE; + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_MULTI_PROCESS; + psDeviceMemoryHeap->pszName = "KernelData"; + psDeviceMemoryHeap->pszBSName = "KernelData BS"; + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED; + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++; + + + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PIXELSHADER_HEAP_BASE; + + + + + + + psDeviceMemoryHeap->ui32HeapSize = ((10 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000); + PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_PIXELSHADER_HEAP_SIZE); + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_SINGLE_PROCESS; + psDeviceMemoryHeap->pszName = "PixelShaderUSSE"; + psDeviceMemoryHeap->pszBSName = "PixelShaderUSSE BS"; + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++; + + + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VERTEXSHADER_HEAP_BASE; + + psDeviceMemoryHeap->ui32HeapSize = ((4 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000); + PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_VERTEXSHADER_HEAP_SIZE); + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_SINGLE_PROCESS; + psDeviceMemoryHeap->pszName = "VertexShaderUSSE"; + psDeviceMemoryHeap->pszBSName = "VertexShaderUSSE BS"; + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++; + + + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSPIXEL_CODEDATA_HEAP_BASE; + psDeviceMemoryHeap->ui32HeapSize = SGX_PDSPIXEL_CODEDATA_HEAP_SIZE; + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_SINGLE_PROCESS; + psDeviceMemoryHeap->pszName = "PDSPixelCodeData"; + psDeviceMemoryHeap->pszBSName = "PDSPixelCodeData BS"; + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++; + + + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE; + psDeviceMemoryHeap->ui32HeapSize = SGX_PDSVERTEX_CODEDATA_HEAP_SIZE; + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_SINGLE_PROCESS; + psDeviceMemoryHeap->pszName = "PDSVertexCodeData"; + psDeviceMemoryHeap->pszBSName = "PDSVertexCodeData BS"; + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++; + + + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SYNCINFO_HEAP_BASE; + psDeviceMemoryHeap->ui32HeapSize = SGX_SYNCINFO_HEAP_SIZE; + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_MULTI_PROCESS; + psDeviceMemoryHeap->pszName = "CacheCoherent"; + psDeviceMemoryHeap->pszBSName = "CacheCoherent BS"; + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED; + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + + psDevMemoryInfo->ui32SyncHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap); + psDeviceMemoryHeap++; + + + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_3DPARAMETERS_HEAP_BASE; + psDeviceMemoryHeap->ui32HeapSize = SGX_3DPARAMETERS_HEAP_SIZE; + psDeviceMemoryHeap->pszName = "3DParameters"; + psDeviceMemoryHeap->pszBSName = "3DParameters BS"; +#if defined(SUPPORT_PERCONTEXT_PB) + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_SINGLE_PROCESS; + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; +#else + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_MULTI_PROCESS; + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED; +#endif + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++; + + +#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_MAPPING_HEAP_BASE; + psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_MAPPING_HEAP_SIZE; + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_MULTI_PROCESS; + psDeviceMemoryHeap->pszName = "GeneralMapping"; + psDeviceMemoryHeap->pszBSName = "GeneralMapping BS"; + #if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410) + + + + + + + + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED; + #else + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; + #endif + + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + + psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap); + psDeviceMemoryHeap++; +#endif + + +#if defined(SGX_FEATURE_2D_HARDWARE) + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_2D_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_2D_HEAP_BASE; + psDeviceMemoryHeap->ui32HeapSize = SGX_2D_HEAP_SIZE; + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_SINGLE_PROCESS; + psDeviceMemoryHeap->pszName = "2D"; + psDeviceMemoryHeap->pszBSName = "2D BS"; + + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED; + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++; +#endif + + +#if defined(FIX_HW_BRN_26915) + + + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_CGBUFFER_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_CGBUFFER_HEAP_BASE; + psDeviceMemoryHeap->ui32HeapSize = SGX_CGBUFFER_HEAP_SIZE; + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_MEM_RAM_BACKED_ALLOCATION + | PVRSRV_HAP_SINGLE_PROCESS; + psDeviceMemoryHeap->pszName = "CGBuffer"; + psDeviceMemoryHeap->pszBSName = "CGBuffer BS"; + + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; + + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++; +#endif + + + psDevMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap); + + return PVRSRV_OK; +} + +#if defined(PDUMP) +static +PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode) +{ + PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)(psDeviceNode->pvDevice); + psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0; + PVR_DPF((PVR_DBG_MESSAGE, "Reset pdump CCB write offset.")); + + return PVRSRV_OK; +} +#endif + + +IMG_EXPORT +PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie, + SGX_CLIENT_INFO* psClientInfo) +{ + PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice; + + + + psDevInfo->ui32ClientRefCount++; + + + + psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM(); + + + + OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData, sizeof(psClientInfo->asDevData)); + + + return PVRSRV_OK; +} + + +IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo) +{ + PVR_LOG(("SGX panic")); + SGXDumpDebugInfo(psDevInfo, IMG_FALSE); + OSPanic(); +} + + +PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode) +{ + PVRSRV_ERROR eError; + PVRSRV_SGXDEV_INFO *psDevInfo; + IMG_UINT32 ui32BuildOptions, ui32BuildOptionsMismatch; +#if !defined(NO_HARDWARE) + PPVRSRV_KERNEL_MEM_INFO psMemInfo; + PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt; + PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures; + SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes; + IMG_BOOL bStructSizesFailed; + + + IMG_BOOL bCheckCoreRev; + const IMG_UINT32 aui32CoreRevExceptions[] = + { + 0x10100, 0x10101 + }; + const IMG_UINT32 ui32NumCoreExceptions = sizeof(aui32CoreRevExceptions) / (2*sizeof(IMG_UINT32)); + IMG_UINT i; +#endif + + + if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX) + { + PVR_LOG(("(FAIL) SGXInit: Device not of type SGX")); + eError = PVRSRV_ERROR_INVALID_PARAMS; + goto chk_exit; + } + + psDevInfo = psDeviceNode->pvDevice; + + + + ui32BuildOptions = (SGX_BUILD_OPTIONS); + if (ui32BuildOptions != psDevInfo->ui32ClientBuildOptions) + { + ui32BuildOptionsMismatch = ui32BuildOptions ^ psDevInfo->ui32ClientBuildOptions; + if ( (psDevInfo->ui32ClientBuildOptions & ui32BuildOptionsMismatch) != 0) + { + PVR_LOG(("(FAIL) SGXInit: Mismatch in client-side and KM driver build options; " + "extra options present in client-side driver: (0x%x). Please check sgx_options.h", + psDevInfo->ui32ClientBuildOptions & ui32BuildOptionsMismatch )); + } + + if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0) + { + PVR_LOG(("(FAIL) SGXInit: Mismatch in client-side and KM driver build options; " + "extra options present in KM: (0x%x). Please check sgx_options.h", + ui32BuildOptions & ui32BuildOptionsMismatch )); + } + eError = PVRSRV_ERROR_BUILD_MISMATCH; + goto chk_exit; + } + else + { + PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: Client-side and KM driver build options match. [ OK ]")); + } + +#if !defined (NO_HARDWARE) + psMemInfo = psDevInfo->psKernelSGXMiscMemInfo; + + + psSGXMiscInfoInt = psMemInfo->pvLinAddrKM; + psSGXMiscInfoInt->ui32MiscInfoFlags = 0; + psSGXMiscInfoInt->ui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES; + eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode); + + + if(eError != PVRSRV_OK) + { + PVR_LOG(("(FAIL) SGXInit: Unable to validate device DDK version")); + goto chk_exit; + } + psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures; + if( (psSGXFeatures->ui32DDKVersion != + ((PVRVERSION_MAJ << 16) | + (PVRVERSION_MIN << 8) | + PVRVERSION_BRANCH) ) || + (psSGXFeatures->ui32DDKBuild != PVRVERSION_BUILD) ) + { + PVR_LOG(("(FAIL) SGXInit: Incompatible driver DDK revision (%d)/device DDK revision (%d).", + PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild)); + eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH; + PVR_DBG_BREAK; + goto chk_exit; + } + else + { + PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: driver DDK (%d) and device DDK (%d) match. [ OK ]", + PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild)); + } + + + if (psSGXFeatures->ui32CoreRevSW == 0) + { + + + PVR_LOG(("SGXInit: HW core rev (%x) check skipped.", + psSGXFeatures->ui32CoreRev)); + } + else + { + + bCheckCoreRev = IMG_TRUE; + for(i=0; i<ui32NumCoreExceptions; i+=2) + { + if( (psSGXFeatures->ui32CoreRev==aui32CoreRevExceptions[i]) && + (psSGXFeatures->ui32CoreRevSW==aui32CoreRevExceptions[i+1]) ) + { + PVR_LOG(("SGXInit: HW core rev (%x), SW core rev (%x) check skipped.", + psSGXFeatures->ui32CoreRev, + psSGXFeatures->ui32CoreRevSW)); + bCheckCoreRev = IMG_FALSE; + } + } + + if (bCheckCoreRev) + { + if (psSGXFeatures->ui32CoreRev != psSGXFeatures->ui32CoreRevSW) + { + PVR_LOG(("(FAIL) SGXInit: Incompatible HW core rev (%x) and SW core rev (%x).", + psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW)); + eError = PVRSRV_ERROR_BUILD_MISMATCH; + goto chk_exit; + } + else + { + PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: HW core rev (%x) and SW core rev (%x) match. [ OK ]", + psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW)); + } + } + } + + + psSGXStructSizes = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXStructSizes; + + bStructSizesFailed = IMG_FALSE; + + CHECK_SIZE(HOST_CTL); + CHECK_SIZE(COMMAND); +#if defined(SGX_FEATURE_2D_HARDWARE) + CHECK_SIZE(2DCMD); + CHECK_SIZE(2DCMD_SHARED); +#endif + CHECK_SIZE(CMDTA); + CHECK_SIZE(CMDTA_SHARED); + CHECK_SIZE(TRANSFERCMD); + CHECK_SIZE(TRANSFERCMD_SHARED); + + CHECK_SIZE(3DREGISTERS); + CHECK_SIZE(HWPBDESC); + CHECK_SIZE(HWRENDERCONTEXT); + CHECK_SIZE(HWRENDERDETAILS); + CHECK_SIZE(HWRTDATA); + CHECK_SIZE(HWRTDATASET); + CHECK_SIZE(HWTRANSFERCONTEXT); + + if (bStructSizesFailed == IMG_TRUE) + { + PVR_LOG(("(FAIL) SGXInit: Mismatch in SGXMKIF structure sizes.")); + eError = PVRSRV_ERROR_BUILD_MISMATCH; + goto chk_exit; + } + else + { + PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: SGXMKIF structure sizes match. [ OK ]")); + } + + + ui32BuildOptions = psSGXFeatures->ui32BuildOptions; + if (ui32BuildOptions != (SGX_BUILD_OPTIONS)) + { + ui32BuildOptionsMismatch = ui32BuildOptions ^ (SGX_BUILD_OPTIONS); + if ( ((SGX_BUILD_OPTIONS) & ui32BuildOptionsMismatch) != 0) + { + PVR_LOG(("(FAIL) SGXInit: Mismatch in driver and microkernel build options; " + "extra options present in driver: (0x%x). Please check sgx_options.h", + (SGX_BUILD_OPTIONS) & ui32BuildOptionsMismatch )); + } + + if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0) + { + PVR_LOG(("(FAIL) SGXInit: Mismatch in driver and microkernel build options; " + "extra options present in microkernel: (0x%x). Please check sgx_options.h", + ui32BuildOptions & ui32BuildOptionsMismatch )); + } + eError = PVRSRV_ERROR_BUILD_MISMATCH; + goto chk_exit; + } + else + { + PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: Driver and microkernel build options match. [ OK ]")); + } +#endif + + eError = PVRSRV_OK; +chk_exit: +#if defined(IGNORE_SGX_INIT_COMPATIBILITY_CHECK) + return PVRSRV_OK; +#else + return eError; +#endif +} + +static +PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo, + PVRSRV_DEVICE_NODE *psDeviceNode) +{ + PVRSRV_ERROR eError; + SGXMKIF_COMMAND sCommandData; + PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt; + PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures; + SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes; + + PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo; + + if (! psMemInfo->pvLinAddrKM) + { + PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Invalid address.")); + return PVRSRV_ERROR_INVALID_PARAMS; + } + psSGXMiscInfoInt = psMemInfo->pvLinAddrKM; + psSGXFeatures = &psSGXMiscInfoInt->sSGXFeatures; + psSGXStructSizes = &psSGXMiscInfoInt->sSGXStructSizes; + + psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY; + + + OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures)); + OSMemSet(psSGXStructSizes, 0, sizeof(*psSGXStructSizes)); + + + sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr; + + PDUMPCOMMENT("Microkernel kick for SGXGetMiscInfo"); + eError = SGXScheduleCCBCommandKM(psDeviceNode, + SGXMKIF_CMD_GETMISCINFO, + &sCommandData, + KERNEL_ID, + 0); + + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: SGXScheduleCCBCommandKM failed.")); + return eError; + } + + +#if !defined(NO_HARDWARE) + { + IMG_BOOL bExit; + + bExit = IMG_FALSE; + LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) + { + if ((psSGXMiscInfoInt->ui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_READY) != 0) + { + bExit = IMG_TRUE; + break; + } + } END_LOOP_UNTIL_TIMEOUT(); + + + if (!bExit) + { + PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Timeout occurred waiting for misc info.")); + return PVRSRV_ERROR_TIMEOUT; + } + } +#endif + + return PVRSRV_OK; +} + + + +IMG_EXPORT +PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo, + SGX_MISC_INFO *psMiscInfo, + PVRSRV_DEVICE_NODE *psDeviceNode, + IMG_HANDLE hDevMemContext) +{ + PVRSRV_ERROR eError; + PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo; + IMG_UINT32 *pui32MiscInfoFlags = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->ui32MiscInfoFlags; + + + *pui32MiscInfoFlags = 0; + +#if !defined(SUPPORT_SGX_EDM_MEMORY_DEBUG) + PVR_UNREFERENCED_PARAMETER(hDevMemContext); +#endif + + switch(psMiscInfo->eRequest) + { +#if defined(SGX_FEATURE_DATA_BREAKPOINTS) + case SGX_MISC_INFO_REQUEST_SET_BREAKPOINT: + { + IMG_UINT32 ui32MaskDM; + IMG_UINT32 ui32CtrlWEnable; + IMG_UINT32 ui32CtrlREnable; + IMG_UINT32 ui32CtrlTrapEnable; + IMG_UINT32 ui32RegVal; + IMG_UINT32 ui32StartRegVal; + IMG_UINT32 ui32EndRegVal; + SGXMKIF_COMMAND sCommandData; + + + if(psMiscInfo->uData.sSGXBreakpointInfo.bBPEnable) + { + + IMG_DEV_VIRTADDR sBPDevVAddr = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddr; + IMG_DEV_VIRTADDR sBPDevVAddrEnd = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddrEnd; + + + ui32StartRegVal = sBPDevVAddr.uiAddr & EUR_CR_BREAKPOINT0_START_ADDRESS_MASK; + ui32EndRegVal = sBPDevVAddrEnd.uiAddr & EUR_CR_BREAKPOINT0_END_ADDRESS_MASK; + + ui32MaskDM = psMiscInfo->uData.sSGXBreakpointInfo.ui32DataMasterMask; + ui32CtrlWEnable = psMiscInfo->uData.sSGXBreakpointInfo.bWrite; + ui32CtrlREnable = psMiscInfo->uData.sSGXBreakpointInfo.bRead; + ui32CtrlTrapEnable = psMiscInfo->uData.sSGXBreakpointInfo.bTrapped; + + + ui32RegVal = ((ui32MaskDM<<EUR_CR_BREAKPOINT0_MASK_DM_SHIFT) & EUR_CR_BREAKPOINT0_MASK_DM_MASK) | + ((ui32CtrlWEnable<<EUR_CR_BREAKPOINT0_CTRL_WENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK) | + ((ui32CtrlREnable<<EUR_CR_BREAKPOINT0_CTRL_RENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_RENABLE_MASK) | + ((ui32CtrlTrapEnable<<EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_MASK); + } + else + { + + ui32RegVal = ui32StartRegVal = ui32EndRegVal = 0; + } + + + sCommandData.ui32Data[0] = psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex; + sCommandData.ui32Data[1] = ui32StartRegVal; + sCommandData.ui32Data[2] = ui32EndRegVal; + sCommandData.ui32Data[3] = ui32RegVal; + + + psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0; + + PDUMPCOMMENT("Microkernel kick for setting a data breakpoint"); + eError = SGXScheduleCCBCommandKM(psDeviceNode, + SGXMKIF_CMD_DATABREAKPOINT, + &sCommandData, + KERNEL_ID, + 0); + + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: SGXScheduleCCBCommandKM failed.")); + return eError; + } + +#if defined(NO_HARDWARE) + + psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0; +#else + { + IMG_BOOL bExit; + + bExit = IMG_FALSE; + LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) + { + if (psDevInfo->psSGXHostCtl->ui32BPSetClearSignal != 0) + { + bExit = IMG_TRUE; + + psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0; + break; + } + } END_LOOP_UNTIL_TIMEOUT(); + + + if (!bExit) + { + PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: Timeout occurred waiting BP set/clear")); + return PVRSRV_ERROR_TIMEOUT; + } + } +#endif + + return PVRSRV_OK; + } + + case SGX_MISC_INFO_REQUEST_WAIT_FOR_BREAKPOINT: + { + + + PDUMPCOMMENT("Wait for data breakpoint hit"); + +#if defined(NO_HARDWARE) && defined(PDUMP) + { + PDUMPREGPOL(SGX_PDUMPREG_NAME, + EUR_CR_EVENT_STATUS2, + EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK, + EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK); + + PDUMPREG(SGX_PDUMPREG_NAME, + EUR_CR_EVENT_HOST_CLEAR2, + EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK); + + PDUMPCOMMENT("Breakpoint detected. Wait a bit to show that pipeline stops in simulation"); + PDUMPIDL(2000); + + PDUMPCOMMENT("Now we can resume"); + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BREAKPOINT_TRAP, EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_BREAKPOINT_TRAP_CONTINUE_MASK); + } +#else + { + + } +#endif + return PVRSRV_OK; + } + + case SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT: + { + + + + + + + +#if !defined(NO_HARDWARE) + IMG_BOOL bTrappedBPMaster; + IMG_BOOL abTrappedBPPerCore[SGX_FEATURE_MP_CORE_COUNT]; + IMG_UINT32 ui32CoreNum, ui32TrappedBPCoreNum; + IMG_BOOL bTrappedBPAny; + + ui32TrappedBPCoreNum = 0; + bTrappedBPMaster = !!(EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT)); + bTrappedBPAny = bTrappedBPMaster; + for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT; ui32CoreNum++) + { + abTrappedBPPerCore[ui32CoreNum] = !!(EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum))); + if (abTrappedBPPerCore[ui32CoreNum]) + { + bTrappedBPAny = IMG_TRUE; + ui32TrappedBPCoreNum = ui32CoreNum; + } + } + + psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = bTrappedBPAny; + + if (psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP) + { + IMG_UINT32 ui32Info0, ui32Info1; + + ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO0, ui32TrappedBPCoreNum)); + ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO1, ui32TrappedBPCoreNum)); + + psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT; + psMiscInfo->uData.sSGXBreakpointInfo.sTrappedBPDevVAddr.uiAddr = ui32Info0 & EUR_CR_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK; + psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPBurstLength = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT; + psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBPRead = !!(ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_RNW_MASK); + psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPDataMaster = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT; + psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPTag = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_SHIFT; + psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:ui32TrappedBPCoreNum; + } +#endif + return PVRSRV_OK; + } + + case SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT: + { + + + +#if !defined(NO_HARDWARE) + IMG_UINT32 ui32CoreNum; + IMG_BOOL bMaster; + IMG_UINT32 ui32OldSeqNum, ui32NewSeqNum; + + ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum; + bMaster = ui32CoreNum > SGX_FEATURE_MP_CORE_COUNT; + if (bMaster) + { + + + ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT_TRAP, EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_MASK); + do + { + ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT); + } + while (ui32OldSeqNum == ui32NewSeqNum); + } + else + { + + ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum)); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP, ui32CoreNum), EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_BREAKPOINT_TRAP_CONTINUE_MASK); + do + { + ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum)); + } + while (ui32OldSeqNum == ui32NewSeqNum); + } +#endif + return PVRSRV_OK; + } +#endif + + case SGX_MISC_INFO_REQUEST_CLOCKSPEED: + { + psMiscInfo->uData.ui32SGXClockSpeed = psDevInfo->ui32CoreClockSpeed; + return PVRSRV_OK; + } + + case SGX_MISC_INFO_REQUEST_ACTIVEPOWER: + { + psMiscInfo->uData.sActivePower.ui32NumActivePowerEvents = psDevInfo->psSGXHostCtl->ui32NumActivePowerEvents; + return PVRSRV_OK; + } + + case SGX_MISC_INFO_REQUEST_LOCKUPS: + { +#if defined(SUPPORT_HW_RECOVERY) + psMiscInfo->uData.sLockups.ui32uKernelDetectedLockups = psDevInfo->psSGXHostCtl->ui32uKernelDetectedLockups; + psMiscInfo->uData.sLockups.ui32HostDetectedLockups = psDevInfo->psSGXHostCtl->ui32HostDetectedLockups; +#else + psMiscInfo->uData.sLockups.ui32uKernelDetectedLockups = 0; + psMiscInfo->uData.sLockups.ui32HostDetectedLockups = 0; +#endif + return PVRSRV_OK; + } + + case SGX_MISC_INFO_REQUEST_SPM: + { + + return PVRSRV_OK; + } + + case SGX_MISC_INFO_REQUEST_SGXREV: + { + PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures; + eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode); + if(eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n", + eError)); + return eError; + } + psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures; + + + psMiscInfo->uData.sSGXFeatures = *psSGXFeatures; + + + PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: Core 0x%x, sw ID 0x%x, sw Rev 0x%x\n", + psSGXFeatures->ui32CoreRev, + psSGXFeatures->ui32CoreIdSW, + psSGXFeatures->ui32CoreRevSW)); + PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: DDK version 0x%x, DDK build 0x%x\n", + psSGXFeatures->ui32DDKVersion, + psSGXFeatures->ui32DDKBuild)); + + + return PVRSRV_OK; + } + + case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV: + { + PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures; + + psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures; + + + OSMemSet(psMemInfo->pvLinAddrKM, 0, + sizeof(PVRSRV_SGX_MISCINFO_INFO)); + + psSGXFeatures->ui32DDKVersion = + (PVRVERSION_MAJ << 16) | + (PVRVERSION_MIN << 8) | + PVRVERSION_BRANCH; + psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD; + + + psSGXFeatures->ui32BuildOptions = (SGX_BUILD_OPTIONS); + +#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) + + psSGXFeatures->sDevVAEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->sDevVAddr; + psSGXFeatures->pvEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM; +#endif + + + psMiscInfo->uData.sSGXFeatures = *psSGXFeatures; + return PVRSRV_OK; + } + +#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG) + case SGX_MISC_INFO_REQUEST_MEMREAD: + case SGX_MISC_INFO_REQUEST_MEMCOPY: + { + PVRSRV_ERROR eError; + PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures; + PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemSrc; + PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemDest; + + { + + *pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMREAD; + psSGXMemSrc = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessSrc; + + if(psMiscInfo->sDevVAddrSrc.uiAddr != 0) + { + psSGXMemSrc->sDevVAddr = psMiscInfo->sDevVAddrSrc; + } + else + { + return PVRSRV_ERROR_INVALID_PARAMS; + } + } + + if( psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMCOPY) + { + + *pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMWRITE; + psSGXMemDest = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessDest; + + if(psMiscInfo->sDevVAddrDest.uiAddr != 0) + { + psSGXMemDest->sDevVAddr = psMiscInfo->sDevVAddrDest; + } + else + { + return PVRSRV_ERROR_INVALID_PARAMS; + } + } + + + if(psMiscInfo->hDevMemContext != IMG_NULL) + { + SGXGetMMUPDAddrKM( (IMG_HANDLE)psDeviceNode, hDevMemContext, &psSGXMemSrc->sPDDevPAddr); + + + psSGXMemDest->sPDDevPAddr = psSGXMemSrc->sPDDevPAddr; + } + else + { + return PVRSRV_ERROR_INVALID_PARAMS; + } + + + eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode); + if(eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n", + eError)); + return eError; + } + psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures; + +#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) + if(*pui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_MEMREAD_FAIL) + { + return PVRSRV_ERROR_INVALID_MISCINFO; + } +#endif + + psMiscInfo->uData.sSGXFeatures = *psSGXFeatures; + return PVRSRV_OK; + } +#endif + +#if defined(SUPPORT_SGX_HWPERF) + case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS: + { + PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS *psSetHWPerfStatus = &psMiscInfo->uData.sSetHWPerfStatus; + const IMG_UINT32 ui32ValidFlags = PVRSRV_SGX_HWPERF_STATUS_RESET_COUNTERS | + PVRSRV_SGX_HWPERF_STATUS_GRAPHICS_ON | + PVRSRV_SGX_HWPERF_STATUS_PERIODIC_ON | + PVRSRV_SGX_HWPERF_STATUS_MK_EXECUTION_ON; + SGXMKIF_COMMAND sCommandData = {0}; + + + if ((psSetHWPerfStatus->ui32NewHWPerfStatus & ~ui32ValidFlags) != 0) + { + return PVRSRV_ERROR_INVALID_PARAMS; + } + + #if defined(PDUMP) + PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, + "SGX ukernel HWPerf status %u\n", + psSetHWPerfStatus->ui32NewHWPerfStatus); + #endif + + + #if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS) + OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfGroup[0], + &psSetHWPerfStatus->aui32PerfGroup[0], + sizeof(psDevInfo->psSGXHostCtl->aui32PerfGroup)); + OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfBit[0], + &psSetHWPerfStatus->aui32PerfBit[0], + sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit)); + #if defined(PDUMP) + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, aui32PerfGroup), + sizeof(psDevInfo->psSGXHostCtl->aui32PerfGroup), + PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, aui32PerfBit), + sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit), + PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); + #endif + #else + psDevInfo->psSGXHostCtl->ui32PerfGroup = psSetHWPerfStatus->ui32PerfGroup; + #if defined(PDUMP) + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32PerfGroup), + sizeof(psDevInfo->psSGXHostCtl->ui32PerfGroup), + PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); + #endif + #endif + + + sCommandData.ui32Data[0] = psSetHWPerfStatus->ui32NewHWPerfStatus; + eError = SGXScheduleCCBCommandKM(psDeviceNode, + SGXMKIF_CMD_SETHWPERFSTATUS, + &sCommandData, + KERNEL_ID, + 0); + return eError; + } +#endif + + case SGX_MISC_INFO_DUMP_DEBUG_INFO: + { + PVR_LOG(("User requested SGX debug info")); + + + SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_FALSE); + + return PVRSRV_OK; + } + + case SGX_MISC_INFO_PANIC: + { + PVR_LOG(("User requested SGX panic")); + + SGXPanic(psDeviceNode->pvDevice); + + return PVRSRV_OK; + } + + default: + { + + return PVRSRV_ERROR_INVALID_PARAMS; + } + } +} + + +IMG_EXPORT +PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE hDevHandle, + IMG_UINT32 ui32ArraySize, + PVRSRV_SGX_HWPERF_CB_ENTRY *psClientHWPerfEntry, + IMG_UINT32 *pui32DataCount, + IMG_UINT32 *pui32ClockSpeed, + IMG_UINT32 *pui32HostTimeStamp) +{ + PVRSRV_ERROR eError = PVRSRV_OK; + PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + SGXMKIF_HWPERF_CB *psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM; + IMG_UINT i; + + for (i = 0; + psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < ui32ArraySize; + i++) + { + SGXMKIF_HWPERF_CB_ENTRY *psMKPerfEntry = &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff]; + + psClientHWPerfEntry[i].ui32FrameNo = psMKPerfEntry->ui32FrameNo; + psClientHWPerfEntry[i].ui32Type = psMKPerfEntry->ui32Type; + psClientHWPerfEntry[i].ui32Ordinal = psMKPerfEntry->ui32Ordinal; + psClientHWPerfEntry[i].ui32Info = psMKPerfEntry->ui32Info; + psClientHWPerfEntry[i].ui32Clocksx16 = SGXConvertTimeStamp(psDevInfo, + psMKPerfEntry->ui32TimeWraps, + psMKPerfEntry->ui32Time); + OSMemCopy(&psClientHWPerfEntry[i].ui32Counters[0][0], + &psMKPerfEntry->ui32Counters[0][0], + sizeof(psMKPerfEntry->ui32Counters)); + + psHWPerfCB->ui32Roff = (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1); + } + + *pui32DataCount = i; + *pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed; + *pui32HostTimeStamp = OSClockus(); + + return eError; +} + + diff --git a/drivers/gpu/pvr/sgx/sgxkick.c b/drivers/gpu/pvr/sgx/sgxkick.c new file mode 100644 index 0000000..8a229c9 --- /dev/null +++ b/drivers/gpu/pvr/sgx/sgxkick.c @@ -0,0 +1,713 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 <stddef.h> +#include "services_headers.h" +#include "sgxinfo.h" +#include "sgxinfokm.h" +#if defined (PDUMP) +#include "sgxapi_km.h" +#include "pdump_km.h" +#endif +#include "sgx_bridge_km.h" +#include "osfunc.h" +#include "pvr_debug.h" +#include "sgxutils.h" + +IMG_EXPORT +PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick) +{ + PVRSRV_ERROR eError; + PVRSRV_KERNEL_SYNC_INFO *psSyncInfo; + PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *) psCCBKick->hCCBKernelMemInfo; + SGXMKIF_CMDTA_SHARED *psTACmd; + IMG_UINT32 i; + + if (!CCB_OFFSET_IS_VALID(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset)) + { + PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: Invalid CCB offset")); + return PVRSRV_ERROR_INVALID_PARAMS; + } + + + psTACmd = CCB_DATA_FROM_OFFSET(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset); + + + if (psCCBKick->hTA3DSyncInfo) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo; + psTACmd->sTA3DDependency.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + + psTACmd->sTA3DDependency.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; + + if (psCCBKick->bTADependency) + { + psSyncInfo->psSyncData->ui32WriteOpsPending++; + } + } + + if (psCCBKick->hTASyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo; + + psTACmd->sTATQSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + psTACmd->sTATQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + + psTACmd->ui32TATQSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++; + psTACmd->ui32TATQSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; + } + + if (psCCBKick->h3DSyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo; + + psTACmd->s3DTQSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + psTACmd->s3DTQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + + psTACmd->ui323DTQSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++; + psTACmd->ui323DTQSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; + } + + psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals; + if (psCCBKick->ui32NumTAStatusVals != 0) + { + + for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) + { +#if defined(SUPPORT_SGX_NEW_STATUS_VALS) + psTACmd->sCtlTAStatusInfo[i] = psCCBKick->asTAStatusUpdate[i].sCtlStatus; +#else + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i]; + psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + psTACmd->sCtlTAStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending; +#endif + } + } + + psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals; + if (psCCBKick->ui32Num3DStatusVals != 0) + { + + for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) + { +#if defined(SUPPORT_SGX_NEW_STATUS_VALS) + psTACmd->sCtl3DStatusInfo[i] = psCCBKick->as3DStatusUpdate[i].sCtlStatus; +#else + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i]; + psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + psTACmd->sCtl3DStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending; +#endif + } + } + + +#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS) + + psTACmd->ui32NumTASrcSyncs = psCCBKick->ui32NumTASrcSyncs; + for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i]; + + psTACmd->asTASrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + psTACmd->asTASrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + + + psTACmd->asTASrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++; + + psTACmd->asTASrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; + } + + psTACmd->ui32NumTADstSyncs = psCCBKick->ui32NumTADstSyncs; + for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i]; + + psTACmd->asTADstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + psTACmd->asTADstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + + + psTACmd->asTADstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; + + psTACmd->asTADstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++; + } + + psTACmd->ui32Num3DSrcSyncs = psCCBKick->ui32Num3DSrcSyncs; + for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i]; + + psTACmd->as3DSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + psTACmd->as3DSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + + + psTACmd->as3DSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++; + + psTACmd->as3DSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; + } +#else + + psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs; + for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i]; + + psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + + + psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++; + + psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; + } +#endif + + if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0) + { + PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo = + (PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo; + SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM; + IMG_UINT32 ui32NumDstSyncs = psCCBKick->ui32NumDstSyncObjects; + + PVR_ASSERT(((PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo)->ui32AllocSize >= (sizeof(SGXMKIF_HWDEVICE_SYNC_LIST) + + (sizeof(PVRSRV_DEVICE_SYNC_OBJECT) * ui32NumDstSyncs))); + + psHWDeviceSyncList->ui32NumSyncObjects = ui32NumDstSyncs; +#if defined(PDUMP) + if (PDumpIsCaptureFrameKM()) + { + PDUMPCOMMENT("HWDeviceSyncList for TACmd\r\n"); + PDUMPMEM(IMG_NULL, + psHWDstSyncListMemInfo, + 0, + sizeof(SGXMKIF_HWDEVICE_SYNC_LIST), + 0, + MAKEUNIQUETAG(psHWDstSyncListMemInfo)); + } +#endif + + for (i=0; i<ui32NumDstSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i]; + + if (psSyncInfo) + { + psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + + psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; + psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++; + + #if defined(PDUMP) + if (PDumpIsCaptureFrameKM()) + { + IMG_UINT32 ui32ModifiedValue; + IMG_UINT32 ui32SyncOffset = offsetof(SGXMKIF_HWDEVICE_SYNC_LIST, asSyncData) + + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)); + IMG_UINT32 ui32WOpsOffset = ui32SyncOffset + + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal); + IMG_UINT32 ui32ROpsOffset = ui32SyncOffset + + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal); + + PDUMPCOMMENT("HWDeviceSyncObject for RT: %i\r\n", i); + + PDUMPMEM(IMG_NULL, + psHWDstSyncListMemInfo, + ui32SyncOffset, + sizeof(PVRSRV_DEVICE_SYNC_OBJECT), + 0, + MAKEUNIQUETAG(psHWDstSyncListMemInfo)); + + if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) && + (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0)) + { + + PDUMPCOMMENT("Init RT ROpsComplete\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psSyncInfo->psSyncDataMemInfoKM, + offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete), + sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete), + 0, + MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM)); + + PDUMPCOMMENT("Init RT WOpsComplete\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psSyncInfo->psSyncDataMemInfoKM, + offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete), + sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete), + 0, + MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM)); + } + + psSyncInfo->psSyncData->ui32LastOpDumpVal++; + + ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1; + + PDUMPCOMMENT("Modify RT %d WOpPendingVal in HWDevSyncList\r\n", i); + + PDUMPMEM(&ui32ModifiedValue, + psHWDstSyncListMemInfo, + ui32WOpsOffset, + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psHWDstSyncListMemInfo)); + + ui32ModifiedValue = 0; + PDUMPCOMMENT("Modify RT %d ROpsPendingVal in HWDevSyncList\r\n", i); + + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psHWDstSyncListMemInfo, + ui32ROpsOffset, + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psHWDstSyncListMemInfo)); + } + #endif + } + else + { + psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr.uiAddr = 0; + psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr.uiAddr = 0; + + psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = 0; + psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = 0; + } + } + } + + + + + psTACmd->ui32CtrlFlags |= SGXMKIF_CMDTA_CTRLFLAGS_READY; + +#if defined(PDUMP) + if (PDumpIsCaptureFrameKM()) + { + PDUMPCOMMENT("Shared part of TA command\r\n"); + + PDUMPMEM(psTACmd, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff, + sizeof(SGXMKIF_CMDTA_SHARED), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); + +#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS) + for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++) + { + IMG_UINT32 ui32ModifiedValue; + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i]; + + if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) && + (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0)) + { + + PDUMPCOMMENT("Init RT TA-SRC ROpsComplete\r\n", i); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psSyncInfo->psSyncDataMemInfoKM, + offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete), + sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete), + 0, + MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM)); + + PDUMPCOMMENT("Init RT TA-SRC WOpsComplete\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psSyncInfo->psSyncDataMemInfoKM, + offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete), + sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete), + 0, + MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM)); + } + + psSyncInfo->psSyncData->ui32LastReadOpDumpVal++; + + ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1; + + PDUMPCOMMENT("Modify TA SrcSync %d ROpsPendingVal\r\n", i); + + PDUMPMEM(&ui32ModifiedValue, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTASrcSyncs) + + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal), + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); + + PDUMPCOMMENT("Modify TA SrcSync %d WOpPendingVal\r\n", i); + + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTASrcSyncs) + + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal), + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); + } + + for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++) + { + IMG_UINT32 ui32ModifiedValue; + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i]; + + if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) && + (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0)) + { + + PDUMPCOMMENT("Init RT TA-DST ROpsComplete\r\n", i); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psSyncInfo->psSyncDataMemInfoKM, + offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete), + sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete), + 0, + MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM)); + + PDUMPCOMMENT("Init RT TA-DST WOpsComplete\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psSyncInfo->psSyncDataMemInfoKM, + offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete), + sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete), + 0, + MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM)); + } + + psSyncInfo->psSyncData->ui32LastOpDumpVal++; + + ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1; + + PDUMPCOMMENT("Modify TA DstSync %d WOpPendingVal\r\n", i); + + PDUMPMEM(&ui32ModifiedValue, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTADstSyncs) + + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal), + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); + + PDUMPCOMMENT("Modify TA DstSync %d ROpsPendingVal\r\n", i); + + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTADstSyncs) + + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal), + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); + } + + for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++) + { + IMG_UINT32 ui32ModifiedValue; + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i]; + + if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) && + (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0)) + { + + PDUMPCOMMENT("Init RT 3D-SRC ROpsComplete\r\n", i); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psSyncInfo->psSyncDataMemInfoKM, + offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete), + sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete), + 0, + MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM)); + + PDUMPCOMMENT("Init RT 3D-SRC WOpsComplete\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psSyncInfo->psSyncDataMemInfoKM, + offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete), + sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete), + 0, + MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM)); + } + + psSyncInfo->psSyncData->ui32LastReadOpDumpVal++; + + ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1; + + PDUMPCOMMENT("Modify 3D SrcSync %d ROpsPendingVal\r\n", i); + + PDUMPMEM(&ui32ModifiedValue, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, as3DSrcSyncs) + + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal), + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); + + PDUMPCOMMENT("Modify 3D SrcSync %d WOpPendingVal\r\n", i); + + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, as3DSrcSyncs) + + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal), + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); + } +#else + for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++) + { + IMG_UINT32 ui32ModifiedValue; + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i]; + + if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) && + (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0)) + { + + PDUMPCOMMENT("Init RT ROpsComplete\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psSyncInfo->psSyncDataMemInfoKM, + offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete), + sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete), + 0, + MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM)); + + PDUMPCOMMENT("Init RT WOpsComplete\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psSyncInfo->psSyncDataMemInfoKM, + offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete), + sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete), + 0, + MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM)); + } + + psSyncInfo->psSyncData->ui32LastReadOpDumpVal++; + + ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1; + + PDUMPCOMMENT("Modify SrcSync %d ROpsPendingVal\r\n", i); + + PDUMPMEM(&ui32ModifiedValue, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) + + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal), + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); + + PDUMPCOMMENT("Modify SrcSync %d WOpPendingVal\r\n", i); + + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) + + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal), + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); + } +#endif + + for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) + { +#if !defined(SUPPORT_SGX_NEW_STATUS_VALS) + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i]; + PDUMPCOMMENT("Modify TA status value in TA cmd\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_CMDTA_SHARED, sCtlTAStatusInfo[i].ui32StatusValue), + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); +#endif + } + + for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) + { +#if !defined(SUPPORT_SGX_NEW_STATUS_VALS) + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i]; + PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_CMDTA_SHARED, sCtl3DStatusInfo[i].ui32StatusValue), + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); +#endif + } + } +#endif + + eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TA, &psCCBKick->sCommand, KERNEL_ID, 0); + if (eError == PVRSRV_ERROR_RETRY) + { + if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0) + { + for (i=0; i < psCCBKick->ui32NumDstSyncObjects; i++) + { + + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i]; + + if (psSyncInfo) + { + psSyncInfo->psSyncData->ui32WriteOpsPending--; +#if defined(PDUMP) + if (PDumpIsCaptureFrameKM()) + { + psSyncInfo->psSyncData->ui32LastOpDumpVal--; + } +#endif + } + } + } + +#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS) + for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i]; + psSyncInfo->psSyncData->ui32ReadOpsPending--; + } + for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i]; + psSyncInfo->psSyncData->ui32WriteOpsPending--; + } + for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i]; + psSyncInfo->psSyncData->ui32ReadOpsPending--; + } +#else + for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i]; + psSyncInfo->psSyncData->ui32ReadOpsPending--; + } +#endif + + return eError; + } + else if (PVRSRV_OK != eError) + { + PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: SGXScheduleCCBCommandKM failed.")); + return eError; + } + + +#if defined(NO_HARDWARE) + + + + if (psCCBKick->hTA3DSyncInfo) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo; + + if (psCCBKick->bTADependency) + { + psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; + } + } + + if (psCCBKick->hTASyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo; + + psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending; + } + + if (psCCBKick->h3DSyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo; + + psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending; + } + + + for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) + { +#if defined(SUPPORT_SGX_NEW_STATUS_VALS) + PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->asTAStatusUpdate[i].hKernelMemInfo; + + *(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM + + (psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr.uiAddr + - psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue; +#else + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i]; + psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue; +#endif + } + +#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS) + + for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i]; + psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending; + } + for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i]; + psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; + } + for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i]; + psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending; + } +#else + + for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i]; + psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending; + } +#endif + + if (psCCBKick->bTerminateOrAbort) + { + if (psCCBKick->ui32NumDstSyncObjects > 0) + { + PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo = + (PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo; + SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM; + + for (i=0; i<psCCBKick->ui32NumDstSyncObjects; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i]; + if (psSyncInfo) + psSyncInfo->psSyncData->ui32WriteOpsComplete = psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal+1; + } + } + + + for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) + { +#if defined(SUPPORT_SGX_NEW_STATUS_VALS) + PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->as3DStatusUpdate[i].hKernelMemInfo; + + *(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM + + (psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr.uiAddr + - psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue; +#else + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i]; + psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue; +#endif + } + } +#endif + + return eError; +} + diff --git a/drivers/gpu/pvr/sgx/sgxpower.c b/drivers/gpu/pvr/sgx/sgxpower.c new file mode 100644 index 0000000..cc55f62 --- /dev/null +++ b/drivers/gpu/pvr/sgx/sgxpower.c @@ -0,0 +1,477 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 <stddef.h> + +#include "sgxdefs.h" +#include "services_headers.h" +#include "sgxapi_km.h" +#include "sgx_mkif_km.h" +#include "sgxutils.h" +#include "pdump_km.h" + + +#if defined(SUPPORT_HW_RECOVERY) +static PVRSRV_ERROR SGXAddTimer(PVRSRV_DEVICE_NODE *psDeviceNode, + SGX_TIMING_INFORMATION *psSGXTimingInfo, + IMG_HANDLE *phTimer) +{ + + + + *phTimer = OSAddTimer(SGXOSTimer, psDeviceNode, + 1000 * 50 / psSGXTimingInfo->ui32uKernelFreq); + if(*phTimer == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR,"SGXAddTimer : Failed to register timer callback function")); + return PVRSRV_ERROR_OUT_OF_MEMORY; + } + + return PVRSRV_OK; +} +#endif + + +static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE *psDeviceNode) +{ + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; +#if defined(SGX_DYNAMIC_TIMING_INFO) + SGX_TIMING_INFORMATION sSGXTimingInfo = {0}; +#else + SGX_DEVICE_MAP *psSGXDeviceMap; +#endif + IMG_UINT32 ui32ActivePowManSampleRate; + SGX_TIMING_INFORMATION *psSGXTimingInfo; + + +#if defined(SGX_DYNAMIC_TIMING_INFO) + psSGXTimingInfo = &sSGXTimingInfo; + SysGetSGXTimingInformation(psSGXTimingInfo); +#else + SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX, + (IMG_VOID**)&psSGXDeviceMap); + psSGXTimingInfo = &psSGXDeviceMap->sTimingInfo; +#endif + +#if defined(SUPPORT_HW_RECOVERY) + { + PVRSRV_ERROR eError; + IMG_UINT32 ui32OlduKernelFreq; + + if (psDevInfo->hTimer != IMG_NULL) + { + ui32OlduKernelFreq = psDevInfo->ui32CoreClockSpeed / psDevInfo->ui32uKernelTimerClock; + if (ui32OlduKernelFreq != psSGXTimingInfo->ui32uKernelFreq) + { + + + IMG_HANDLE hNewTimer; + + eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &hNewTimer); + if (eError == PVRSRV_OK) + { + eError = OSRemoveTimer(psDevInfo->hTimer); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXUpdateTimingInfo: Failed to remove timer")); + } + psDevInfo->hTimer = hNewTimer; + } + else + { + + } + } + } + else + { + eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &psDevInfo->hTimer); + if (eError != PVRSRV_OK) + { + return eError; + } + } + + psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate = + psSGXTimingInfo->ui32uKernelFreq / psSGXTimingInfo->ui32HWRecoveryFreq; + } +#endif + + + psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed; + psDevInfo->ui32uKernelTimerClock = psSGXTimingInfo->ui32CoreClockSpeed / psSGXTimingInfo->ui32uKernelFreq; + + + psDevInfo->psSGXHostCtl->ui32uKernelTimerClock = psDevInfo->ui32uKernelTimerClock; +#if defined(PDUMP) + PDUMPCOMMENT("Host Control - Microkernel clock"); + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32uKernelTimerClock), + sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); +#endif + + if (psSGXTimingInfo->bEnableActivePM) + { + ui32ActivePowManSampleRate = + psSGXTimingInfo->ui32uKernelFreq * psSGXTimingInfo->ui32ActivePowManLatencyms / 1000; + + + + + + + + ui32ActivePowManSampleRate += 1; + } + else + { + ui32ActivePowManSampleRate = 0; + } + + psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate = ui32ActivePowManSampleRate; +#if defined(PDUMP) + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32ActivePowManSampleRate), + sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); +#endif + + return PVRSRV_OK; +} + + +static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO *psDevInfo) +{ + #if defined(SUPPORT_HW_RECOVERY) + PVRSRV_ERROR eError; + + eError = OSEnableTimer(psDevInfo->hTimer); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXStartTimer : Failed to enable host timer")); + } + #else + PVR_UNREFERENCED_PARAMETER(psDevInfo); + #endif +} + + +static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_UINT32 ui32Register, + IMG_UINT32 ui32RegisterValue, + IMG_CHAR *pszComment) +{ + PVR_UNREFERENCED_PARAMETER(psDevInfo); + PVR_UNREFERENCED_PARAMETER(ui32Register); + PVR_UNREFERENCED_PARAMETER(ui32RegisterValue); + PVR_UNREFERENCED_PARAMETER(pszComment); + + #if !defined(NO_HARDWARE) + PVR_ASSERT(psDevInfo != IMG_NULL); + /* + if (PollForValueKM((IMG_UINT32 *)psDevInfo->pvRegsBaseKM + (ui32Register >> 2), + 0, + ui32RegisterValue, + MAX_HW_TIME_US/WAIT_TRY_COUNT, + WAIT_TRY_COUNT) != PVRSRV_OK) + */ + if (PollForValueKM((IMG_UINT32 *)psDevInfo->pvRegsBaseKM + (ui32Register >> 2), + 0, + ui32RegisterValue, + 1000, + 500) != PVRSRV_OK) // for using msleep + { + PVR_DPF((PVR_DBG_ERROR,"SGXPollForClockGating: %s failed.", pszComment)); + PVR_DBG_BREAK; + } + #endif + + PDUMPCOMMENT("%s", pszComment); + PDUMPREGPOL(SGX_PDUMPREG_NAME, ui32Register, 0, ui32RegisterValue); +} + + +PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle, + PVRSRV_DEV_POWER_STATE eNewPowerState, + PVRSRV_DEV_POWER_STATE eCurrentPowerState) +{ + if ((eNewPowerState != eCurrentPowerState) && + (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON)) + { + PVRSRV_ERROR eError; + PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + IMG_UINT32 ui32PowerCmd, ui32CompleteStatus; + SGXMKIF_COMMAND sCommand = {0}; + IMG_UINT32 ui32Core; + + #if defined(SUPPORT_HW_RECOVERY) + + eError = OSDisableTimer(psDevInfo->hTimer); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to disable timer")); + return eError; + } + #endif + + if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF) + { + + ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF; + ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE; + PDUMPCOMMENT("SGX power off request"); + } + else + { + + ui32PowerCmd = PVRSRV_POWERCMD_IDLE; + ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE; + PDUMPCOMMENT("SGX idle request"); + } + + sCommand.ui32Data[1] = ui32PowerCmd; + + eError = SGXScheduleCCBCommand(psDevInfo, SGXMKIF_CMD_POWER, &sCommand, KERNEL_ID, 0); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to submit power down command")); + return eError; + } + + + #if !defined(NO_HARDWARE) + if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus, + ui32CompleteStatus, + ui32CompleteStatus, + MAX_HW_TIME_US/WAIT_TRY_COUNT, + WAIT_TRY_COUNT) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Wait for SGX ukernel power transition failed.")); + PVR_DBG_BREAK; + } + #endif + + #if defined(PDUMP) + PDUMPCOMMENT("TA/3D CCB Control - Wait for power event on uKernel."); + PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus), + ui32CompleteStatus, + ui32CompleteStatus, + PDUMP_POLL_OPERATOR_EQUAL, + 0, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); + #endif + + for (ui32Core = 0; ui32Core < SGX_FEATURE_MP_CORE_COUNT; ui32Core++) + { + + SGXPollForClockGating(psDevInfo, + SGX_MP_CORE_SELECT(psDevInfo->ui32ClkGateStatusReg, ui32Core), + psDevInfo->ui32ClkGateStatusMask, + "Wait for SGX clock gating"); + } + + #if defined(SGX_FEATURE_MP) + + SGXPollForClockGating(psDevInfo, + psDevInfo->ui32MasterClkGateStatusReg, + psDevInfo->ui32MasterClkGateStatusMask, + "Wait for SGX master clock gating"); + + SGXPollForClockGating(psDevInfo, + psDevInfo->ui32MasterClkGateStatus2Reg, + psDevInfo->ui32MasterClkGateStatus2Mask, + "Wait for SGX master clock gating (2)"); + #endif + + if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF) + { + + eError = SGXDeinitialise(psDevInfo); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: SGXDeinitialise failed: %u", eError)); + return eError; + } + } + } + + return PVRSRV_OK; +} + + +PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE hDevHandle, + PVRSRV_DEV_POWER_STATE eNewPowerState, + PVRSRV_DEV_POWER_STATE eCurrentPowerState) +{ + if ((eNewPowerState != eCurrentPowerState) && + (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON)) + { + PVRSRV_ERROR eError; + PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl; + + + psSGXHostCtl->ui32PowerStatus = 0; + #if defined(PDUMP) + PDUMPCOMMENT("Host Control - Reset power status"); + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus), + sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); + #endif + + if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF) + { + + + + + eError = SGXUpdateTimingInfo(psDeviceNode); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed")); + return eError; + } + + + + eError = SGXInitialise(psDevInfo, IMG_FALSE); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXInitialise failed")); + return eError; + } + } + else + { + + + SGXMKIF_COMMAND sCommand = {0}; + + sCommand.ui32Data[1] = PVRSRV_POWERCMD_RESUME; + eError = SGXScheduleCCBCommand(psDevInfo, SGXMKIF_CMD_POWER, &sCommand, ISR_ID, 0); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState failed to schedule CCB command: %u", eError)); + return eError; + } + } + + SGXStartTimer(psDevInfo); + } + + return PVRSRV_OK; +} + + +PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE hDevHandle, + IMG_BOOL bIdleDevice, + PVRSRV_DEV_POWER_STATE eCurrentPowerState) +{ + PVRSRV_ERROR eError; + PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + + PVR_UNREFERENCED_PARAMETER(psDevInfo); + + if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON) + { + if (bIdleDevice) + { + + PDUMPSUSPEND(); + + eError = SGXPrePowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_IDLE, + PVRSRV_DEV_POWER_STATE_ON); + + if (eError != PVRSRV_OK) + { + PDUMPRESUME(); + return eError; + } + } + } + + PVR_DPF((PVR_DBG_MESSAGE,"SGXPreClockSpeedChange: SGX clock speed was %uHz", + psDevInfo->ui32CoreClockSpeed)); + + return PVRSRV_OK; +} + + +PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE hDevHandle, + IMG_BOOL bIdleDevice, + PVRSRV_DEV_POWER_STATE eCurrentPowerState) +{ + PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + IMG_UINT32 ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed; + + PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed); + + if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON) + { + PVRSRV_ERROR eError; + + + + eError = SGXUpdateTimingInfo(psDeviceNode); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed")); + return eError; + } + + if (bIdleDevice) + { + + eError = SGXPostPowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_ON, + PVRSRV_DEV_POWER_STATE_IDLE); + + PDUMPRESUME(); + + if (eError != PVRSRV_OK) + { + return eError; + } + } + else + { + SGXStartTimer(psDevInfo); + } + } + + PVR_DPF((PVR_DBG_MESSAGE,"SGXPostClockSpeedChange: SGX clock speed changed from %uHz to %uHz", + ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed)); + + return PVRSRV_OK; +} + + diff --git a/drivers/gpu/pvr/sgx/sgxreset.c b/drivers/gpu/pvr/sgx/sgxreset.c new file mode 100644 index 0000000..68d0e79 --- /dev/null +++ b/drivers/gpu/pvr/sgx/sgxreset.c @@ -0,0 +1,509 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 "sgxdefs.h" +#include "sgxmmu.h" +#include "services_headers.h" +#include "sgxinfokm.h" +#include "sgxconfig.h" + +#include "pdump_km.h" + + +static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_BOOL bResetBIF, + IMG_UINT32 ui32PDUMPFlags, + IMG_BOOL bPDump) +{ + IMG_UINT32 ui32SoftResetRegVal; + +#if defined(SGX_FEATURE_MP) + ui32SoftResetRegVal = + EUR_CR_MASTER_SOFT_RESET_IPF_RESET_MASK | + EUR_CR_MASTER_SOFT_RESET_DPM_RESET_MASK | + EUR_CR_MASTER_SOFT_RESET_VDM_RESET_MASK; + +#if defined(SGX_FEATURE_PTLA) + ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_MASK; +#endif +#if defined(SGX_FEATURE_SYSTEM_CACHE) + ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_SLC_RESET_MASK; +#endif + + if (bResetBIF) + { + ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_BIF_RESET_MASK; + } + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32SoftResetRegVal); + if (bPDump) + { + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SOFT_RESET, ui32SoftResetRegVal, ui32PDUMPFlags); + } +#endif + + ui32SoftResetRegVal = + + EUR_CR_SOFT_RESET_DPM_RESET_MASK | + EUR_CR_SOFT_RESET_TA_RESET_MASK | + EUR_CR_SOFT_RESET_USE_RESET_MASK | + EUR_CR_SOFT_RESET_ISP_RESET_MASK | + EUR_CR_SOFT_RESET_TSP_RESET_MASK; + +#ifdef EUR_CR_SOFT_RESET_TWOD_RESET_MASK + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TWOD_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_TE_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TE_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_MTE_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MTE_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_ISP2_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ISP2_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_PDS_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PDS_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_PBE_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PBE_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_MADD_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MADD_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_ITR_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ITR_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_TEX_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TEX_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_VDM_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_VDM_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK; +#endif +#if defined(EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK) + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK; +#endif + +#if !defined(PDUMP) + PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags); +#endif + + if (bResetBIF) + { + ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_BIF_RESET_MASK; + } + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32SoftResetRegVal); + if (bPDump) + { + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32SoftResetRegVal, ui32PDUMPFlags); + } +} + + +static IMG_VOID SGXResetSleep(PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_UINT32 ui32PDUMPFlags, + IMG_BOOL bPDump) +{ +#if !defined(PDUMP) + PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags); +#endif + + + OSWaitus(100 * 1000000 / psDevInfo->ui32CoreClockSpeed); + if (bPDump) + { + PDUMPIDLWITHFLAGS(30, ui32PDUMPFlags); +#if defined(PDUMP) + PDumpRegRead(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32PDUMPFlags); +#endif + } + +} + + +static IMG_VOID SGXResetInvalDC(PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_UINT32 ui32PDUMPFlags, + IMG_BOOL bPDump) +{ + IMG_UINT32 ui32RegVal; + + +#if defined(EUR_CR_BIF_CTRL_INVAL) + ui32RegVal = EUR_CR_BIF_CTRL_INVAL_ALL_MASK; + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, ui32RegVal); + if (bPDump) + { + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL_INVAL, ui32RegVal, ui32PDUMPFlags); + } +#else + ui32RegVal = EUR_CR_BIF_CTRL_INVALDC_MASK; + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal); + if (bPDump) + { + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags); + } + + ui32RegVal = 0; + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal); + if (bPDump) + { + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags); + } +#endif + SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump); + +#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) + { + + + + if (PollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT), + 0, + EUR_CR_BIF_MEM_REQ_STAT_READS_MASK, + MAX_HW_TIME_US/WAIT_TRY_COUNT, + WAIT_TRY_COUNT) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"Wait for DC invalidate failed.")); + PVR_DBG_BREAK; + } + + if (bPDump) + { + PDUMPREGPOLWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_REQ_STAT, 0, EUR_CR_BIF_MEM_REQ_STAT_READS_MASK, ui32PDUMPFlags); + } + } +#endif +} + + +IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_BOOL bHardwareRecovery, + IMG_UINT32 ui32PDUMPFlags) +{ + IMG_UINT32 ui32RegVal; +#if defined(EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK) + const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK; +#else + const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_MASK; +#endif + +#ifndef PDUMP + PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags); +#endif + + psDevInfo->ui32NumResets++; + + PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX reset sequence\r\n"); + +#if defined(FIX_HW_BRN_23944) + + ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK; + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags); + + SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE); + + ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT); + if (ui32RegVal & ui32BifFaultMask) + { + + ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK | EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK; + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags); + + SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE); + + ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK; + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags); + + SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE); + } +#endif + + + SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_TRUE); + + SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE); + + + +#if defined(SGX_FEATURE_36BIT_MMU) + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK, ui32PDUMPFlags); +#endif + + ui32RegVal = 0; + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags); +#if defined(SGX_FEATURE_MP) + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_CTRL, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_BIF_CTRL, ui32RegVal, ui32PDUMPFlags); +#endif +#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK_SET, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK_SET, ui32RegVal, ui32PDUMPFlags); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags); +#endif + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal, ui32PDUMPFlags); + +#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) + { + IMG_UINT32 ui32DirList, ui32DirListReg; + + for (ui32DirList = 1; + ui32DirList < SGX_FEATURE_BIF_NUM_DIRLISTS; + ui32DirList++) + { + ui32DirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (ui32DirList - 1); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32DirListReg, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, ui32DirListReg, ui32RegVal, ui32PDUMPFlags); + } + } +#endif + +#if defined(EUR_CR_BIF_MEM_ARB_CONFIG) + + + ui32RegVal = (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT) | + (7UL << EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT) | + (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal, ui32PDUMPFlags); +#endif + +#if defined(SGX_FEATURE_SYSTEM_CACHE) +#if defined(SGX_FEATURE_MP) + #if defined(SGX_BYPASS_SYSTEM_CACHE) + #error SGX_BYPASS_SYSTEM_CACHE not supported + #else + ui32RegVal = EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ0_MASK | + #if defined(FIX_HW_BRN_30954) + EUR_CR_MASTER_SLC_CTRL_DISABLE_REORDERING_MASK | + #endif + (0xC << EUR_CR_MASTER_SLC_CTRL_ARB_PAGE_SIZE_SHIFT); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL, ui32RegVal); + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SLC_CTRL, ui32RegVal); + + ui32RegVal = EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_MASK; + #if defined(FIX_HW_BRN_31195) + ui32RegVal |= EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE0_MASK | + EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE1_MASK | + EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE2_MASK | + EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE3_MASK | + EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TA_MASK; + #endif + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal); + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal); + #endif +#else + #if defined(SGX_BYPASS_SYSTEM_CACHE) + + ui32RegVal = MNE_CR_CTRL_BYPASS_ALL_MASK; + #else + #if defined(FIX_HW_BRN_26620) + ui32RegVal = 0; + #else + + ui32RegVal = MNE_CR_CTRL_BYP_CC_MASK; + #endif + #endif + OSWriteHWReg(psDevInfo->pvRegsBaseKM, MNE_CR_CTRL, ui32RegVal); + PDUMPREG(SGX_PDUMPREG_NAME, MNE_CR_CTRL, ui32RegVal); +#endif +#endif + + if (bHardwareRecovery) + { + + + + + + + + ui32RegVal = (IMG_UINT32)psDevInfo->sBIFResetPDDevPAddr.uiAddr; + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal); + + SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE); + + + SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE); + SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE); + + SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE); + + + + for (;;) + { + IMG_UINT32 ui32BifIntStat = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT); + IMG_DEV_VIRTADDR sBifFault; + IMG_UINT32 ui32PDIndex, ui32PTIndex; + + if ((ui32BifIntStat & ui32BifFaultMask) == 0) + { + break; + } + + + + + sBifFault.uiAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT); + PVR_DPF((PVR_DBG_WARNING, "SGXReset: Page fault 0x%x/0x%x", ui32BifIntStat, sBifFault.uiAddr)); + ui32PDIndex = sBifFault.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT); + ui32PTIndex = (sBifFault.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT; + + + SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_FALSE); + + + psDevInfo->pui32BIFResetPD[ui32PDIndex] = (psDevInfo->sBIFResetPTDevPAddr.uiAddr + >>SGX_MMU_PDE_ADDR_ALIGNSHIFT) + | SGX_MMU_PDE_PAGE_SIZE_4K + | SGX_MMU_PDE_VALID; + psDevInfo->pui32BIFResetPT[ui32PTIndex] = (psDevInfo->sBIFResetPageDevPAddr.uiAddr + >>SGX_MMU_PTE_ADDR_ALIGNSHIFT) + | SGX_MMU_PTE_VALID; + + + ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32RegVal); + ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32RegVal); + + SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE); + + + SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_FALSE); + SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE); + + + SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE); + + + psDevInfo->pui32BIFResetPD[ui32PDIndex] = 0; + psDevInfo->pui32BIFResetPT[ui32PTIndex] = 0; + } + } + else + { + + SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE); + SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE); + } + + + + #if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) + + ui32RegVal = (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT); + + #if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA) + + ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_2D_SHIFT); + #endif + + #if defined(FIX_HW_BRN_23410) + + ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_TA_SHIFT); + #endif + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags); + #endif + + { + IMG_UINT32 ui32EDMDirListReg; + + + #if (SGX_BIF_DIR_LIST_INDEX_EDM == 0) + ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE0; + #else + + ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (SGX_BIF_DIR_LIST_INDEX_EDM - 1); + #endif + +#if defined(FIX_HW_BRN_28011) + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT); + PDUMPPDREGWITHFLAGS(&psDevInfo->sMMUAttrib, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG); +#endif + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32EDMDirListReg, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT); + PDUMPPDREGWITHFLAGS(&psDevInfo->sMMUAttrib, ui32EDMDirListReg, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG); + } + +#if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA) + + #if ((SGX_2D_HEAP_BASE & ~EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK) != 0) + #error "SGXReset: SGX_2D_HEAP_BASE doesn't match EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK alignment" + #endif + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE, ui32PDUMPFlags); +#endif + + + SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_TRUE); + + PVR_DPF((PVR_DBG_MESSAGE,"Soft Reset of SGX")); + + + ui32RegVal = 0; +#if defined(SGX_FEATURE_MP) + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SOFT_RESET, ui32RegVal, ui32PDUMPFlags); +#endif + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32RegVal); + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32RegVal, ui32PDUMPFlags); + + + SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE); + + PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX reset sequence\r\n"); +} + + diff --git a/drivers/gpu/pvr/sgx/sgxtransfer.c b/drivers/gpu/pvr/sgx/sgxtransfer.c new file mode 100644 index 0000000..0e9fe81 --- /dev/null +++ b/drivers/gpu/pvr/sgx/sgxtransfer.c @@ -0,0 +1,582 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 + * + ******************************************************************************/ + +#if defined(TRANSFER_QUEUE) + +#include <stddef.h> + +#include "sgxdefs.h" +#include "services_headers.h" +#include "buffer_manager.h" +#include "sgxinfo.h" +#include "sysconfig.h" +#include "regpaths.h" +#include "pdump_km.h" +#include "mmu.h" +#include "pvr_bridge.h" +#include "sgx_bridge_km.h" +#include "sgxinfokm.h" +#include "osfunc.h" +#include "pvr_debug.h" +#include "sgxutils.h" + +IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick) +{ + PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo; + SGXMKIF_COMMAND sCommand = {0}; + SGXMKIF_TRANSFERCMD_SHARED *psSharedTransferCmd; + PVRSRV_KERNEL_SYNC_INFO *psSyncInfo; + PVRSRV_ERROR eError; + IMG_UINT32 loop; +#if defined(PDUMP) + IMG_BOOL bPersistentProcess = IMG_FALSE; + + { + PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData(); + if(psPerProc != IMG_NULL) + { + bPersistentProcess = psPerProc->bPDumpPersistent; + } + } +#endif + + if (!CCB_OFFSET_IS_VALID(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset)) + { + PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: Invalid CCB offset")); + return PVRSRV_ERROR_INVALID_PARAMS; + } + + + psSharedTransferCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset); + + if (psKick->hTASyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo; + + psSharedTransferCmd->ui32TASyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++; + psSharedTransferCmd->ui32TASyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; + + psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + } + else + { + psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0; + psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0; + } + + if (psKick->h3DSyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo; + + psSharedTransferCmd->ui323DSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++; + psSharedTransferCmd->ui323DSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; + + psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + } + else + { + psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0; + psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0; + } + + psSharedTransferCmd->ui32NumSrcSyncs = psKick->ui32NumSrcSync; + psSharedTransferCmd->ui32NumDstSyncs = psKick->ui32NumDstSync; + if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL) + { + for (loop=0; loop<psKick->ui32NumSrcSync; loop++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop]; + + psSharedTransferCmd->asSrcSyncs[loop].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; + psSharedTransferCmd->asSrcSyncs[loop].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; + + psSharedTransferCmd->asSrcSyncs[loop].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + psSharedTransferCmd->asSrcSyncs[loop].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + + } + for (loop=0; loop<psKick->ui32NumDstSync; loop++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop]; + + psSharedTransferCmd->asDstSyncs[loop].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; + psSharedTransferCmd->asDstSyncs[loop].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; + + psSharedTransferCmd->asDstSyncs[loop].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + psSharedTransferCmd->asDstSyncs[loop].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + + } + + + for (loop=0; loop<psKick->ui32NumSrcSync; loop++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop]; + psSyncInfo->psSyncData->ui32ReadOpsPending++; + } + for (loop=0; loop<psKick->ui32NumDstSync; loop++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop]; + psSyncInfo->psSyncData->ui32WriteOpsPending++; + } + } + +#if defined(PDUMP) + if ((PDumpIsCaptureFrameKM() + || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) + && (bPersistentProcess == IMG_FALSE) ) + { + PDUMPCOMMENT("Shared part of transfer command\r\n"); + PDUMPMEM(psSharedTransferCmd, + psCCBMemInfo, + psKick->ui32CCBDumpWOff, + sizeof(SGXMKIF_TRANSFERCMD_SHARED), + psKick->ui32PDumpFlags, + MAKEUNIQUETAG(psCCBMemInfo)); + + if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL) + { + for (loop=0; loop<psKick->ui32NumSrcSync ; loop++) + { + psSyncInfo = psKick->ahSrcSyncInfo[loop]; + + PDUMPCOMMENT("Hack src surface write op in transfer cmd\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psCCBMemInfo, + psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + loop * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal), + sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal), + psKick->ui32PDumpFlags, + MAKEUNIQUETAG(psCCBMemInfo)); + + PDUMPCOMMENT("Hack src surface read op in transfer cmd\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psCCBMemInfo, + psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + loop * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal), + sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal), + psKick->ui32PDumpFlags, + MAKEUNIQUETAG(psCCBMemInfo)); + + } + } + if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL) + { + for (loop=0; loop< psKick->ui32NumDstSync; loop++) + { + psSyncInfo = psKick->ahDstSyncInfo[loop]; + + PDUMPCOMMENT("Hack dest surface write op in transfer cmd\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psCCBMemInfo, + psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + loop * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal) , + sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal), + psKick->ui32PDumpFlags, + MAKEUNIQUETAG(psCCBMemInfo)); + + PDUMPCOMMENT("Hack dest surface read op in transfer cmd\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psCCBMemInfo, + psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + loop * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal), + sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal), + psKick->ui32PDumpFlags, + MAKEUNIQUETAG(psCCBMemInfo)); + + } + } + + + if((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING)== 0UL) + { + for (loop=0; loop<(psKick->ui32NumSrcSync); loop++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop]; + psSyncInfo->psSyncData->ui32LastReadOpDumpVal++; + } + } + + if((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL) + { + for (loop=0; loop<(psKick->ui32NumDstSync); loop++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0]; + psSyncInfo->psSyncData->ui32LastOpDumpVal++; + } + } + } +#endif + + sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr; + + eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TRANSFER, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags); + + if (eError == PVRSRV_ERROR_RETRY) + { + + if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL) + { + if (psKick->ui32NumSrcSync > 0) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0]; + psSyncInfo->psSyncData->ui32ReadOpsPending--; + } + if (psKick->ui32NumDstSync > 0) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0]; + psSyncInfo->psSyncData->ui32WriteOpsPending--; + } +#if defined(PDUMP) + if (PDumpIsCaptureFrameKM() + || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) + { + if (psKick->ui32NumSrcSync > 0) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0]; + psSyncInfo->psSyncData->ui32LastReadOpDumpVal--; + } + if (psKick->ui32NumDstSync > 0) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0]; + psSyncInfo->psSyncData->ui32LastOpDumpVal--; + } + } +#endif + } + + + if (psKick->hTASyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo; + psSyncInfo->psSyncData->ui32WriteOpsPending--; + } + + + if (psKick->h3DSyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo; + psSyncInfo->psSyncData->ui32WriteOpsPending--; + } + } + + else if (PVRSRV_OK != eError) + { + PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: SGXScheduleCCBCommandKM failed.")); + return eError; + } + + +#if defined(NO_HARDWARE) + if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE) == 0) + { + IMG_UINT32 i; + + + for(i = 0; i < psKick->ui32NumSrcSync; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i]; + psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending; + } + + for(i = 0; i < psKick->ui32NumDstSync; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[i]; + psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; + + } + + if (psKick->hTASyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo; + + psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; + } + + if (psKick->h3DSyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo; + + psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; + } + } +#endif + + return eError; +} + +#if defined(SGX_FEATURE_2D_HARDWARE) +IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick) + +{ + PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo; + SGXMKIF_COMMAND sCommand = {0}; + SGXMKIF_2DCMD_SHARED *ps2DCmd; + PVRSRV_KERNEL_SYNC_INFO *psSyncInfo; + PVRSRV_ERROR eError; + IMG_UINT32 i; +#if defined(PDUMP) + IMG_BOOL bPersistentProcess = IMG_FALSE; + + { + PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData(); + if(psPerProc != IMG_NULL) + { + bPersistentProcess = psPerProc->bPDumpPersistent; + } + } +#endif + + if (!CCB_OFFSET_IS_VALID(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset)) + { + PVR_DPF((PVR_DBG_ERROR, "SGXSubmit2DKM: Invalid CCB offset")); + return PVRSRV_ERROR_INVALID_PARAMS; + } + + + ps2DCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset); + + OSMemSet(ps2DCmd, 0, sizeof(*ps2DCmd)); + + + if (psKick->hTASyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo; + + ps2DCmd->sTASyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++; + ps2DCmd->sTASyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; + + ps2DCmd->sTASyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + ps2DCmd->sTASyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + } + + + if (psKick->h3DSyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo; + + ps2DCmd->s3DSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++; + ps2DCmd->s3DSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; + + ps2DCmd->s3DSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + ps2DCmd->s3DSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + } + + + ps2DCmd->ui32NumSrcSync = psKick->ui32NumSrcSync; + for (i = 0; i < psKick->ui32NumSrcSync; i++) + { + psSyncInfo = psKick->ahSrcSyncInfo[i]; + + ps2DCmd->sSrcSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; + ps2DCmd->sSrcSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; + + ps2DCmd->sSrcSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + ps2DCmd->sSrcSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + } + + if (psKick->hDstSyncInfo != IMG_NULL) + { + psSyncInfo = psKick->hDstSyncInfo; + + ps2DCmd->sDstSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; + ps2DCmd->sDstSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; + + ps2DCmd->sDstSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; + ps2DCmd->sDstSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; + } + + + for (i = 0; i < psKick->ui32NumSrcSync; i++) + { + psSyncInfo = psKick->ahSrcSyncInfo[i]; + psSyncInfo->psSyncData->ui32ReadOpsPending++; + } + + if (psKick->hDstSyncInfo != IMG_NULL) + { + psSyncInfo = psKick->hDstSyncInfo; + psSyncInfo->psSyncData->ui32WriteOpsPending++; + } + +#if defined(PDUMP) + if ((PDumpIsCaptureFrameKM() + || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) + && (bPersistentProcess == IMG_FALSE) ) + { + + PDUMPCOMMENT("Shared part of 2D command\r\n"); + PDUMPMEM(ps2DCmd, + psCCBMemInfo, + psKick->ui32CCBDumpWOff, + sizeof(SGXMKIF_2DCMD_SHARED), + psKick->ui32PDumpFlags, + MAKEUNIQUETAG(psCCBMemInfo)); + + for (i = 0; i < psKick->ui32NumSrcSync; i++) + { + psSyncInfo = psKick->ahSrcSyncInfo[i]; + + PDUMPCOMMENT("Hack src surface write op in 2D cmd\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psCCBMemInfo, + psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32WriteOpsPendingVal), + sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal), + psKick->ui32PDumpFlags, + MAKEUNIQUETAG(psCCBMemInfo)); + + PDUMPCOMMENT("Hack src surface read op in 2D cmd\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psCCBMemInfo, + psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32ReadOpsPendingVal), + sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal), + psKick->ui32PDumpFlags, + MAKEUNIQUETAG(psCCBMemInfo)); + } + + if (psKick->hDstSyncInfo != IMG_NULL) + { + psSyncInfo = psKick->hDstSyncInfo; + + PDUMPCOMMENT("Hack dest surface write op in 2D cmd\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psCCBMemInfo, + psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32WriteOpsPendingVal), + sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal), + psKick->ui32PDumpFlags, + MAKEUNIQUETAG(psCCBMemInfo)); + + PDUMPCOMMENT("Hack dest surface read op in 2D cmd\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psCCBMemInfo, + psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOpsPendingVal), + sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal), + psKick->ui32PDumpFlags, + MAKEUNIQUETAG(psCCBMemInfo)); + } + + + for (i = 0; i < psKick->ui32NumSrcSync; i++) + { + psSyncInfo = psKick->ahSrcSyncInfo[i]; + psSyncInfo->psSyncData->ui32LastReadOpDumpVal++; + } + + if (psKick->hDstSyncInfo != IMG_NULL) + { + psSyncInfo = psKick->hDstSyncInfo; + psSyncInfo->psSyncData->ui32LastOpDumpVal++; + } + } +#endif + + sCommand.ui32Data[1] = psKick->sHW2DContextDevVAddr.uiAddr; + + eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_2D, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags); + + if (eError == PVRSRV_ERROR_RETRY) + { + + +#if defined(PDUMP) + if (PDumpIsCaptureFrameKM()) + { + for (i = 0; i < psKick->ui32NumSrcSync; i++) + { + psSyncInfo = psKick->ahSrcSyncInfo[i]; + psSyncInfo->psSyncData->ui32LastReadOpDumpVal--; + } + + if (psKick->hDstSyncInfo != IMG_NULL) + { + psSyncInfo = psKick->hDstSyncInfo; + psSyncInfo->psSyncData->ui32LastOpDumpVal--; + } + } +#endif + + for (i = 0; i < psKick->ui32NumSrcSync; i++) + { + psSyncInfo = psKick->ahSrcSyncInfo[i]; + psSyncInfo->psSyncData->ui32ReadOpsPending--; + } + + if (psKick->hDstSyncInfo != IMG_NULL) + { + psSyncInfo = psKick->hDstSyncInfo; + psSyncInfo->psSyncData->ui32WriteOpsPending--; + } + + + if (psKick->hTASyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo; + + psSyncInfo->psSyncData->ui32WriteOpsPending--; + } + + + if (psKick->h3DSyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo; + + psSyncInfo->psSyncData->ui32WriteOpsPending--; + } + } + + + + +#if defined(NO_HARDWARE) + + for(i = 0; i < psKick->ui32NumSrcSync; i++) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i]; + psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending; + } + + if (psKick->hDstSyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hDstSyncInfo; + + psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; + } + + if (psKick->hTASyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo; + + psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; + } + + if (psKick->h3DSyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo; + + psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; + } +#endif + + return eError; +} +#endif +#endif diff --git a/drivers/gpu/pvr/sgx/sgxutils.c b/drivers/gpu/pvr/sgx/sgxutils.c new file mode 100644 index 0000000..d8b6de7 --- /dev/null +++ b/drivers/gpu/pvr/sgx/sgxutils.c @@ -0,0 +1,1010 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 <stddef.h> + +#include "sgxdefs.h" +#include "services_headers.h" +#include "buffer_manager.h" +#include "sgx_bridge_km.h" +#include "sgxapi_km.h" +#include "sgxinfo.h" +#include "sgx_mkif_km.h" +#include "sysconfig.h" +#include "pdump_km.h" +#include "mmu.h" +#include "pvr_bridge_km.h" +#include "osfunc.h" +#include "pvr_debug.h" +#include "sgxutils.h" + +#ifdef __linux__ +#include <linux/kernel.h> +#include <linux/string.h> +#else +#include <stdio.h> +#endif + + +#if defined(SYS_CUSTOM_POWERDOWN) +PVRSRV_ERROR SysPowerDownMISR(PVRSRV_DEVICE_NODE * psDeviceNode, IMG_UINT32 ui32CallerID); +#endif + + + +static IMG_VOID SGXPostActivePowerEvent(PVRSRV_DEVICE_NODE * psDeviceNode, + IMG_UINT32 ui32CallerID) +{ + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl; + + + psSGXHostCtl->ui32NumActivePowerEvents++; + + if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE) != 0) + { + + + + if (ui32CallerID == ISR_ID) + { + psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE; + } + else + { + SGXScheduleProcessQueuesKM(psDeviceNode); + } + } +} + + +IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE *psDeviceNode, + IMG_UINT32 ui32CallerID) +{ + PVRSRV_ERROR eError = PVRSRV_OK; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl; + + if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) && + ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0)) + { + + psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER; + + + PDUMPSUSPEND(); + +#if defined(SYS_CUSTOM_POWERDOWN) + + + + eError = SysPowerDownMISR(psDeviceNode, ui32CallerID); +#else + eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex, + PVRSRV_DEV_POWER_STATE_OFF, + ui32CallerID, IMG_FALSE); + if (eError == PVRSRV_OK) + { + SGXPostActivePowerEvent(psDeviceNode, ui32CallerID); + } +#endif + if (eError == PVRSRV_ERROR_RETRY) + { + + + psSGXHostCtl->ui32InterruptClearFlags &= ~PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER; + eError = PVRSRV_OK; + } + + + PDUMPRESUME(); + } + + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%u", eError)); + } +} + + +#ifdef INLINE_IS_PRAGMA +#pragma inline(SGXAcquireKernelCCBSlot) +#endif +static INLINE SGXMKIF_COMMAND * SGXAcquireKernelCCBSlot(PVRSRV_SGX_CCB_INFO *psCCB) +{ + LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) + { + if(((*psCCB->pui32WriteOffset + 1) & 255) != *psCCB->pui32ReadOffset) + { + return &psCCB->psCommands[*psCCB->pui32WriteOffset]; + } + + OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT); + } END_LOOP_UNTIL_TIMEOUT(); + + + return IMG_NULL; +} + +PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_SGXDEV_INFO *psDevInfo, + SGXMKIF_CMD_TYPE eCmdType, + SGXMKIF_COMMAND *psCommandData, + IMG_UINT32 ui32CallerID, + IMG_UINT32 ui32PDumpFlags) +{ + PVRSRV_SGX_CCB_INFO *psKernelCCB; + PVRSRV_ERROR eError = PVRSRV_OK; + SGXMKIF_COMMAND *psSGXCommand; + SYS_DATA *psSysData; +#if defined(PDUMP) + IMG_VOID *pvDumpCommand; + IMG_BOOL bPDumpIsSuspended = PDumpIsSuspended(); + IMG_BOOL bPersistentProcess = IMG_FALSE; +#else + PVR_UNREFERENCED_PARAMETER(ui32CallerID); + PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags); +#endif + +#if defined(FIX_HW_BRN_28889) + + + + + if ( (eCmdType != SGXMKIF_CMD_PROCESS_QUEUES) && + ((psDevInfo->ui32CacheControl & SGXMKIF_CC_INVAL_DATA) != 0) && + ((psDevInfo->ui32CacheControl & (SGXMKIF_CC_INVAL_BIF_PT | SGXMKIF_CC_INVAL_BIF_PD)) != 0)) + { + #if defined(PDUMP) + PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo; + #endif + SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl; + SGXMKIF_COMMAND sCacheCommand = {0}; + + eError = SGXScheduleCCBCommand(psDevInfo, + SGXMKIF_CMD_PROCESS_QUEUES, + &sCacheCommand, + ui32CallerID, + ui32PDumpFlags); + if (eError != PVRSRV_OK) + { + goto Exit; + } + + + #if !defined(NO_HARDWARE) + if(PollForValueKM(&psSGXHostCtl->ui32InvalStatus, + PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE, + PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE, + 2 * MAX_HW_TIME_US/WAIT_TRY_COUNT, + WAIT_TRY_COUNT) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommand: Wait for uKernel to Invalidate BIF cache failed")); + PVR_DBG_BREAK; + } + #endif + + #if defined(PDUMP) + + PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for BIF cache invalidate request to complete"); + PDUMPMEMPOL(psSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32InvalStatus), + PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE, + PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE, + PDUMP_POLL_OPERATOR_EQUAL, + 0, + MAKEUNIQUETAG(psSGXHostCtlMemInfo)); + #endif + + psSGXHostCtl->ui32InvalStatus &= ~(PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE); + PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo)); + } +#endif + +#if defined(PDUMP) + + { + PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData(); + if(psPerProc != IMG_NULL) + { + bPersistentProcess = psPerProc->bPDumpPersistent; + } + } +#endif + psKernelCCB = psDevInfo->psKernelCCBInfo; + + psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB); + + + if(!psSGXCommand) + { + eError = PVRSRV_ERROR_TIMEOUT; + goto Exit; + } + + + psCommandData->ui32CacheControl = psDevInfo->ui32CacheControl; + +#if defined(PDUMP) + + psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl; +#endif + + + psDevInfo->ui32CacheControl = 0; + + + *psSGXCommand = *psCommandData; + + if (eCmdType >= SGXMKIF_CMD_MAX) + { + PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM: Unknown command type: %d", eCmdType)) ; + eError = PVRSRV_ERROR_INVALID_CCB_COMMAND; + goto Exit; + } + + + SysAcquireData(&psSysData); + + if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) + { + OSFlushCPUCacheKM(); + } + else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) + { + OSCleanCPUCacheKM(); + } + + + psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE; + + PVR_ASSERT(eCmdType < SGXMKIF_CMD_MAX); + psSGXCommand->ui32ServiceAddress = psDevInfo->aui32HostKickAddr[eCmdType]; + +#if defined(PDUMP) + if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE) && + (bPersistentProcess == IMG_FALSE) ) + { + + PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for space in the Kernel CCB\r\n"); + PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo, + offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset), + (psKernelCCB->ui32CCBDumpWOff + 1) & 0xff, + 0xff, + PDUMP_POLL_OPERATOR_NOTEQUAL, + ui32PDumpFlags, + MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo)); + + PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB command (type == %d)\r\n", eCmdType); + pvDumpCommand = (IMG_VOID *)((IMG_UINT8 *)psKernelCCB->psCCBMemInfo->pvLinAddrKM + (*psKernelCCB->pui32WriteOffset * sizeof(SGXMKIF_COMMAND))); + + PDUMPMEM(pvDumpCommand, + psKernelCCB->psCCBMemInfo, + psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND), + sizeof(SGXMKIF_COMMAND), + ui32PDumpFlags, + MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo)); + + + PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl, + psKernelCCB->psCCBMemInfo, + psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND) + + offsetof(SGXMKIF_COMMAND, ui32CacheControl), + sizeof(IMG_UINT32), + ui32PDumpFlags, + MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo)); + + if (PDumpIsCaptureFrameKM() + || ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) + { + + psDevInfo->sPDContext.ui32CacheControl = 0; + } + } +#endif + +#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE) + + eError = PollForValueKM (psKernelCCB->pui32ReadOffset, + *psKernelCCB->pui32WriteOffset, + 0xFF, + MAX_HW_TIME_US/WAIT_TRY_COUNT, + WAIT_TRY_COUNT); + if (eError != PVRSRV_OK) + { + eError = PVRSRV_ERROR_TIMEOUT; + goto Exit; + } +#endif + + + + *psKernelCCB->pui32WriteOffset = (*psKernelCCB->pui32WriteOffset + 1) & 255; + +#if defined(PDUMP) + if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE) && + (bPersistentProcess == IMG_FALSE) ) + { + #if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE) + PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for previous Kernel CCB CMD to be read\r\n"); + PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo, + offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset), + (psKernelCCB->ui32CCBDumpWOff), + 0xFF, + PDUMP_POLL_OPERATOR_EQUAL, + ui32PDumpFlags, + MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo)); + #endif + + if (PDumpIsCaptureFrameKM() + || ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) + { + psKernelCCB->ui32CCBDumpWOff = (psKernelCCB->ui32CCBDumpWOff + 1) & 0xFF; + psDevInfo->ui32KernelCCBEventKickerDumpVal = (psDevInfo->ui32KernelCCBEventKickerDumpVal + 1) & 0xFF; + } + + PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB write offset\r\n"); + PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff, + psKernelCCB->psCCBCtlMemInfo, + offsetof(PVRSRV_SGX_CCB_CTL, ui32WriteOffset), + sizeof(IMG_UINT32), + ui32PDumpFlags, + MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo)); + PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB event kicker\r\n"); + PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal, + psDevInfo->psKernelCCBEventKickerMemInfo, + 0, + sizeof(IMG_UINT32), + ui32PDumpFlags, + MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo)); + PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kick the SGX microkernel\r\n"); + #if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE) + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK, ui32PDumpFlags); + #else + PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK, ui32PDumpFlags); + #endif + } +#endif + + *psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF; + + OSWriteMemoryBarrier(); + +#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE) + OSWriteHWReg(psDevInfo->pvRegsBaseKM, + SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), + EUR_CR_EVENT_KICK2_NOW_MASK); +#else + OSWriteHWReg(psDevInfo->pvRegsBaseKM, + SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), + EUR_CR_EVENT_KICK_NOW_MASK); +#endif + + OSMemoryBarrier(); + +#if defined(NO_HARDWARE) + + *psKernelCCB->pui32ReadOffset = (*psKernelCCB->pui32ReadOffset + 1) & 255; +#endif + +Exit: + return eError; +} + + +PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode, + SGXMKIF_CMD_TYPE eCmdType, + SGXMKIF_COMMAND *psCommandData, + IMG_UINT32 ui32CallerID, + IMG_UINT32 ui32PDumpFlags) +{ + PVRSRV_ERROR eError; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + + + PDUMPSUSPEND(); + + + eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex, + PVRSRV_DEV_POWER_STATE_ON, + ui32CallerID, + IMG_TRUE); + + PDUMPRESUME(); + + if (eError == PVRSRV_OK) + { + psDeviceNode->bReProcessDeviceCommandComplete = IMG_FALSE; + } + else + { + if (eError == PVRSRV_ERROR_RETRY) + { + if (ui32CallerID == ISR_ID) + { + + + + psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE; + eError = PVRSRV_OK; + } + else + { + + + } + } + else + { + PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - " + "ui32CallerID:%d eError:%u", ui32CallerID, eError)); + } + + return eError; + } + + eError = SGXScheduleCCBCommand(psDevInfo, eCmdType, psCommandData, ui32CallerID, ui32PDumpFlags); + + PVRSRVPowerUnlock(ui32CallerID); + + + if (ui32CallerID != ISR_ID) + { + + + + SGXTestActivePowerEvent(psDeviceNode, ui32CallerID); + } + + return eError; +} + + +PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode) +{ + PVRSRV_ERROR eError; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + SGXMKIF_HOST_CTL *psHostCtl = psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM; + IMG_UINT32 ui32PowerStatus; + SGXMKIF_COMMAND sCommand = {0}; + + ui32PowerStatus = psHostCtl->ui32PowerStatus; + if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0) + { + + return PVRSRV_OK; + } + + eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_PROCESS_QUEUES, &sCommand, ISR_ID, 0); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXScheduleProcessQueuesKM failed to schedule CCB command: %u", eError)); + return eError; + } + + return PVRSRV_OK; +} + + +IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode) +{ + return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex); +} + +IMG_EXPORT +PVRSRV_ERROR SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie, + SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo) +{ + PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice; + + psSGXInternalDevInfo->ui32Flags = psDevInfo->ui32Flags; + psSGXInternalDevInfo->bForcePTOff = (IMG_BOOL)psDevInfo->bForcePTOff; + + + psSGXInternalDevInfo->hHostCtlKernelMemInfoHandle = + (IMG_HANDLE)psDevInfo->psKernelSGXHostCtlMemInfo; + + return PVRSRV_OK; +} + + +IMG_VOID SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode, + IMG_DEV_VIRTADDR *psHWDataDevVAddr, + IMG_UINT32 ui32CleanupType) +{ + PVRSRV_ERROR eError; + PVRSRV_SGXDEV_INFO *psSGXDevInfo = psDeviceNode->pvDevice; + PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo = psSGXDevInfo->psKernelSGXHostCtlMemInfo; + SGXMKIF_HOST_CTL *psSGXHostCtl = psSGXHostCtlMemInfo->pvLinAddrKM; + + if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0) + { + + } + else + { + SGXMKIF_COMMAND sCommand = {0}; + + PDUMPCOMMENTWITHFLAGS(0, "Request ukernel resouce clean-up"); + sCommand.ui32Data[0] = ui32CleanupType; + sCommand.ui32Data[1] = (psHWDataDevVAddr == IMG_NULL) ? 0 : psHWDataDevVAddr->uiAddr; + + eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_CLEANUP, &sCommand, KERNEL_ID, 0); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Failed to submit clean-up command")); + PVR_DBG_BREAK; + } + + + #if !defined(NO_HARDWARE) + if(PollForValueKM(&psSGXHostCtl->ui32CleanupStatus, + PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE, + PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE, + 2 * MAX_HW_TIME_US/WAIT_TRY_COUNT, + WAIT_TRY_COUNT) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Wait for uKernel to clean up (%u) failed", ui32CleanupType)); + PVR_DBG_BREAK; + } + #endif + + #if defined(PDUMP) + + PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for clean-up request to complete"); + PDUMPMEMPOL(psSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), + PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE, + PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE, + PDUMP_POLL_OPERATOR_EQUAL, + 0, + MAKEUNIQUETAG(psSGXHostCtlMemInfo)); + #endif + + psSGXHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE); + PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo)); + + + #if defined(SGX_FEATURE_SYSTEM_CACHE) + psSGXDevInfo->ui32CacheControl |= (SGXMKIF_CC_INVAL_BIF_SL | SGXMKIF_CC_INVAL_DATA); + #else + psSGXDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_DATA; + #endif + } +} + + +typedef struct _SGX_HW_RENDER_CONTEXT_CLEANUP_ +{ + PVRSRV_DEVICE_NODE *psDeviceNode; + IMG_DEV_VIRTADDR sHWRenderContextDevVAddr; + IMG_HANDLE hBlockAlloc; + PRESMAN_ITEM psResItem; +} SGX_HW_RENDER_CONTEXT_CLEANUP; + + +static PVRSRV_ERROR SGXCleanupHWRenderContextCallback(IMG_PVOID pvParam, + IMG_UINT32 ui32Param) +{ + SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup = pvParam; + + PVR_UNREFERENCED_PARAMETER(ui32Param); + + SGXCleanupRequest(psCleanup->psDeviceNode, + &psCleanup->sHWRenderContextDevVAddr, + PVRSRV_CLEANUPCMD_RC); + + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP), + psCleanup, + psCleanup->hBlockAlloc); + + + return PVRSRV_OK; +} + +typedef struct _SGX_HW_TRANSFER_CONTEXT_CLEANUP_ +{ + PVRSRV_DEVICE_NODE *psDeviceNode; + IMG_DEV_VIRTADDR sHWTransferContextDevVAddr; + IMG_HANDLE hBlockAlloc; + PRESMAN_ITEM psResItem; +} SGX_HW_TRANSFER_CONTEXT_CLEANUP; + + +static PVRSRV_ERROR SGXCleanupHWTransferContextCallback(IMG_PVOID pvParam, + IMG_UINT32 ui32Param) +{ + SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)pvParam; + + PVR_UNREFERENCED_PARAMETER(ui32Param); + + SGXCleanupRequest(psCleanup->psDeviceNode, + &psCleanup->sHWTransferContextDevVAddr, + PVRSRV_CLEANUPCMD_TC); + + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP), + psCleanup, + psCleanup->hBlockAlloc); + + + return PVRSRV_OK; +} + +IMG_EXPORT +IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE psDeviceNode, + IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + PVRSRV_ERROR eError; + IMG_HANDLE hBlockAlloc; + SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup; + PRESMAN_ITEM psResItem; + + eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP), + (IMG_VOID **)&psCleanup, + &hBlockAlloc, + "SGX Hardware Render Context Cleanup"); + + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Couldn't allocate memory for SGX_HW_RENDER_CONTEXT_CLEANUP structure")); + return IMG_NULL; + } + + psCleanup->hBlockAlloc = hBlockAlloc; + psCleanup->psDeviceNode = psDeviceNode; + psCleanup->sHWRenderContextDevVAddr = *psHWRenderContextDevVAddr; + + psResItem = ResManRegisterRes(psPerProc->hResManContext, + RESMAN_TYPE_HW_RENDER_CONTEXT, + (IMG_VOID *)psCleanup, + 0, + &SGXCleanupHWRenderContextCallback); + + if (psResItem == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: ResManRegisterRes failed")); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP), + psCleanup, + psCleanup->hBlockAlloc); + + + return IMG_NULL; + } + + psCleanup->psResItem = psResItem; + + return (IMG_HANDLE)psCleanup; +} + +IMG_EXPORT +PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext) +{ + PVRSRV_ERROR eError; + SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup; + + PVR_ASSERT(hHWRenderContext != IMG_NULL); + + psCleanup = (SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext; + + if (psCleanup == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWRenderContextKM: invalid parameter")); + return PVRSRV_ERROR_INVALID_PARAMS; + } + + eError = ResManFreeResByPtr(psCleanup->psResItem); + + return eError; +} + + +IMG_EXPORT +IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE psDeviceNode, + IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + PVRSRV_ERROR eError; + IMG_HANDLE hBlockAlloc; + SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup; + PRESMAN_ITEM psResItem; + + eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP), + (IMG_VOID **)&psCleanup, + &hBlockAlloc, + "SGX Hardware Transfer Context Cleanup"); + + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Couldn't allocate memory for SGX_HW_TRANSFER_CONTEXT_CLEANUP structure")); + return IMG_NULL; + } + + psCleanup->hBlockAlloc = hBlockAlloc; + psCleanup->psDeviceNode = psDeviceNode; + psCleanup->sHWTransferContextDevVAddr = *psHWTransferContextDevVAddr; + + psResItem = ResManRegisterRes(psPerProc->hResManContext, + RESMAN_TYPE_HW_TRANSFER_CONTEXT, + psCleanup, + 0, + &SGXCleanupHWTransferContextCallback); + + if (psResItem == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: ResManRegisterRes failed")); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP), + psCleanup, + psCleanup->hBlockAlloc); + + + return IMG_NULL; + } + + psCleanup->psResItem = psResItem; + + return (IMG_HANDLE)psCleanup; +} + +IMG_EXPORT +PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext) +{ + PVRSRV_ERROR eError; + SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup; + + PVR_ASSERT(hHWTransferContext != IMG_NULL); + + psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext; + + if (psCleanup == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWTransferContextKM: invalid parameter")); + return PVRSRV_ERROR_INVALID_PARAMS; + } + + eError = ResManFreeResByPtr(psCleanup->psResItem); + + return eError; +} + +#if defined(SGX_FEATURE_2D_HARDWARE) +typedef struct _SGX_HW_2D_CONTEXT_CLEANUP_ +{ + PVRSRV_DEVICE_NODE *psDeviceNode; + IMG_DEV_VIRTADDR sHW2DContextDevVAddr; + IMG_HANDLE hBlockAlloc; + PRESMAN_ITEM psResItem; +} SGX_HW_2D_CONTEXT_CLEANUP; + +static PVRSRV_ERROR SGXCleanupHW2DContextCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param) +{ + SGX_HW_2D_CONTEXT_CLEANUP *psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)pvParam; + + PVR_UNREFERENCED_PARAMETER(ui32Param); + + SGXCleanupRequest(psCleanup->psDeviceNode, + &psCleanup->sHW2DContextDevVAddr, + PVRSRV_CLEANUPCMD_2DC); + + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(SGX_HW_2D_CONTEXT_CLEANUP), + psCleanup, + psCleanup->hBlockAlloc); + + + return PVRSRV_OK; +} + +IMG_EXPORT +IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE psDeviceNode, + IMG_DEV_VIRTADDR *psHW2DContextDevVAddr, + PVRSRV_PER_PROCESS_DATA *psPerProc) +{ + PVRSRV_ERROR eError; + IMG_HANDLE hBlockAlloc; + SGX_HW_2D_CONTEXT_CLEANUP *psCleanup; + PRESMAN_ITEM psResItem; + + eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(SGX_HW_2D_CONTEXT_CLEANUP), + (IMG_VOID **)&psCleanup, + &hBlockAlloc, + "SGX Hardware 2D Context Cleanup"); + + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Couldn't allocate memory for SGX_HW_2D_CONTEXT_CLEANUP structure")); + return IMG_NULL; + } + + psCleanup->hBlockAlloc = hBlockAlloc; + psCleanup->psDeviceNode = psDeviceNode; + psCleanup->sHW2DContextDevVAddr = *psHW2DContextDevVAddr; + + psResItem = ResManRegisterRes(psPerProc->hResManContext, + RESMAN_TYPE_HW_2D_CONTEXT, + psCleanup, + 0, + &SGXCleanupHW2DContextCallback); + + if (psResItem == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: ResManRegisterRes failed")); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(SGX_HW_2D_CONTEXT_CLEANUP), + psCleanup, + psCleanup->hBlockAlloc); + + + return IMG_NULL; + } + + psCleanup->psResItem = psResItem; + + return (IMG_HANDLE)psCleanup; +} + +IMG_EXPORT +PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext) +{ + PVRSRV_ERROR eError; + SGX_HW_2D_CONTEXT_CLEANUP *psCleanup; + + PVR_ASSERT(hHW2DContext != IMG_NULL); + + if (hHW2DContext == IMG_NULL) + { + return (PVRSRV_ERROR_INVALID_PARAMS); + } + + psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)hHW2DContext; + + eError = ResManFreeResByPtr(psCleanup->psResItem); + + return eError; +} +#endif + +#ifdef INLINE_IS_PRAGMA +#pragma inline(SGX2DQuerySyncOpsComplete) +#endif +static INLINE +IMG_BOOL SGX2DQuerySyncOpsComplete(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, + IMG_UINT32 ui32ReadOpsPending, + IMG_UINT32 ui32WriteOpsPending) +{ + PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData; + + return (IMG_BOOL)( + (psSyncData->ui32ReadOpsComplete >= ui32ReadOpsPending) && + (psSyncData->ui32WriteOpsComplete >= ui32WriteOpsPending) + ); +} + +IMG_EXPORT +PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo, + PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, + IMG_BOOL bWaitForComplete) +{ + IMG_UINT32 ui32ReadOpsPending, ui32WriteOpsPending; + + PVR_UNREFERENCED_PARAMETER(psDevInfo); + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start")); + + ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending; + ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending; + + if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending)) + { + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Blits complete.")); + return PVRSRV_OK; + } + + + if (!bWaitForComplete) + { + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Ops pending.")); + return PVRSRV_ERROR_CMD_NOT_PROCESSED; + } + + + PVR_DPF((PVR_DBG_MESSAGE, "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling.")); + + LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) + { + OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT); + + if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending)) + { + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Wait over. Blits complete.")); + return PVRSRV_OK; + } + + OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT); + } END_LOOP_UNTIL_TIMEOUT(); + + + PVR_DPF((PVR_DBG_ERROR,"SGX2DQueryBlitsCompleteKM: Timed out. Ops pending.")); + +#if defined(DEBUG) + { + PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData; + + PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Syncinfo: 0x%x, Syncdata: 0x%x", + (IMG_UINTPTR_T)psSyncInfo, (IMG_UINTPTR_T)psSyncData)); + + PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Read ops complete: %d, Read ops pending: %d", psSyncData->ui32ReadOpsComplete, psSyncData->ui32ReadOpsPending)); + PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Write ops complete: %d, Write ops pending: %d", psSyncData->ui32WriteOpsComplete, psSyncData->ui32WriteOpsPending)); + + } +#endif + + return PVRSRV_ERROR_TIMEOUT; +} + + +IMG_EXPORT +IMG_VOID SGXFlushHWRenderTargetKM(IMG_HANDLE psDeviceNode, IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr) +{ + PVR_ASSERT(sHWRTDataSetDevVAddr.uiAddr != IMG_NULL); + + SGXCleanupRequest(psDeviceNode, + &sHWRTDataSetDevVAddr, + PVRSRV_CLEANUPCMD_RT); +} + + +IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_UINT32 ui32TimeWraps, + IMG_UINT32 ui32Time) +{ +#if defined(EUR_CR_TIMER) + PVR_UNREFERENCED_PARAMETER(psDevInfo); + PVR_UNREFERENCED_PARAMETER(ui32TimeWraps); + return ui32Time; +#else + IMG_UINT64 ui64Clocks; + IMG_UINT32 ui32Clocksx16; + + ui64Clocks = ((IMG_UINT64)ui32TimeWraps * psDevInfo->ui32uKernelTimerClock) + + (psDevInfo->ui32uKernelTimerClock - (ui32Time & EUR_CR_EVENT_TIMER_VALUE_MASK)); + ui32Clocksx16 = (IMG_UINT32)(ui64Clocks / 16); + + return ui32Clocksx16; +#endif +} + + + diff --git a/drivers/gpu/pvr/sgx/sgxutils.h b/drivers/gpu/pvr/sgx/sgxutils.h new file mode 100644 index 0000000..aeee635 --- /dev/null +++ b/drivers/gpu/pvr/sgx/sgxutils.h @@ -0,0 +1,100 @@ +/********************************************************************** + * + * Copyright(c) 2008 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 "perproc.h" +#include "sgxinfokm.h" + + +#define CCB_OFFSET_IS_VALID(type, psCCBMemInfo, psCCBKick, offset) \ + ((sizeof(type) <= (psCCBMemInfo)->ui32AllocSize) && \ + ((psCCBKick)->offset <= (psCCBMemInfo)->ui32AllocSize - sizeof(type))) + +#define CCB_DATA_FROM_OFFSET(type, psCCBMemInfo, psCCBKick, offset) \ + ((type *)(((IMG_CHAR *)(psCCBMemInfo)->pvLinAddrKM) + \ + (psCCBKick)->offset)) + + +IMG_IMPORT +IMG_VOID SGXTestActivePowerEvent(PVRSRV_DEVICE_NODE *psDeviceNode, + IMG_UINT32 ui32CallerID); + +IMG_IMPORT +PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_SGXDEV_INFO *psDevInfo, + SGXMKIF_CMD_TYPE eCommandType, + SGXMKIF_COMMAND *psCommandData, + IMG_UINT32 ui32CallerID, + IMG_UINT32 ui32PDumpFlags); +IMG_IMPORT +PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode, + SGXMKIF_CMD_TYPE eCommandType, + SGXMKIF_COMMAND *psCommandData, + IMG_UINT32 ui32CallerID, + IMG_UINT32 ui32PDumpFlags); + +IMG_IMPORT +PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode); + +IMG_IMPORT +IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode); + +IMG_IMPORT +IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE psDeviceNode, + IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr, + PVRSRV_PER_PROCESS_DATA *psPerProc); + +IMG_IMPORT +IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE psDeviceNode, + IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr, + PVRSRV_PER_PROCESS_DATA *psPerProc); + +IMG_IMPORT +IMG_VOID SGXFlushHWRenderTargetKM(IMG_HANDLE psSGXDevInfo, IMG_DEV_VIRTADDR psHWRTDataSetDevVAddr); + +IMG_IMPORT +PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext); + +IMG_IMPORT +PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext); + +#if defined(SGX_FEATURE_2D_HARDWARE) +IMG_IMPORT +IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE psDeviceNode, + IMG_DEV_VIRTADDR *psHW2DContextDevVAddr, + PVRSRV_PER_PROCESS_DATA *psPerProc); + +IMG_IMPORT +PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext); +#endif + +IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_UINT32 ui32TimeWraps, + IMG_UINT32 ui32Time); + +IMG_VOID SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode, + IMG_DEV_VIRTADDR *psHWDataDevVAddr, + IMG_UINT32 ui32CleanupType); + + |