| /********************************************************************** |
| * |
| * Copyright (C) Imagination Technologies Ltd. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms and conditions of the GNU General Public License, |
| * version 2, as published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope it will be useful but, except |
| * as otherwise stated in writing, without any warranty; without even the |
| * implied warranty of merchantability or fitness for a particular purpose. |
| * See the GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License along with |
| * this program; if not, write to the Free Software Foundation, Inc., |
| * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * The full GNU General Public License is included in this distribution in |
| * the file called "COPYING". |
| * |
| * Contact Information: |
| * Imagination Technologies Ltd. <[email protected]> |
| * 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" |
| #include "ttrace.h" |
| |
| #if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) |
| |
| static const IMG_CHAR *SGXUKernelStatusString(IMG_UINT32 code) |
| { |
| switch(code) |
| { |
| #define MKTC_ST(x) \ |
| case x: \ |
| return #x; |
| #include "sgx_ukernel_status_codes.h" |
| default: |
| return "(Unknown)"; |
| } |
| } |
| |
| #endif |
| |
| #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, |
| IMG_HANDLE hDevMemContext); |
| #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, |
| #if defined (SUPPORT_SID_INTERFACE) |
| SGX_BRIDGE_INIT_INFO_KM *psInitInfo) |
| #else |
| SGX_BRIDGE_INIT_INFO *psInitInfo) |
| #endif |
| { |
| 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; |
| |
| #if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920) |
| psDevInfo->psKernelSGXPTLAWriteBackMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXPTLAWriteBackMemInfo; |
| #endif |
| |
| 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(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559) |
| psDevInfo->psKernelVDMSnapShotBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelVDMSnapShotBufferMemInfo; |
| psDevInfo->psKernelVDMCtrlStreamBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelVDMCtrlStreamBufferMemInfo; |
| #endif |
| #if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \ |
| defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX) |
| psDevInfo->psKernelVDMStateUpdateBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelVDMStateUpdateBufferMemInfo; |
| #endif |
| #if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) |
| psDevInfo->psKernelEDMStatusBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelEDMStatusBufferMemInfo; |
| #endif |
| |
| psDevInfo->ui32ClientBuildOptions = psInitInfo->ui32ClientBuildOptions; |
| |
| |
| psDevInfo->sSGXStructSizes = psInitInfo->sSGXStructSizes; |
| |
| |
| |
| eError = OSAllocMem(PVRSRV_OS_NON_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->ui32ClkGateCtl = psInitInfo->ui32ClkGateCtl; |
| psDevInfo->ui32ClkGateCtl2 = psInitInfo->ui32ClkGateCtl2; |
| 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; |
| } |
| |
| #if defined(SUPPORT_MEMORY_TILING) |
| static PVRSRV_ERROR SGX_AllocMemTilingRangeInt(PVRSRV_SGXDEV_INFO *psDevInfo, |
| IMG_UINT32 ui32Start, |
| IMG_UINT32 ui32End, |
| IMG_UINT32 ui32TilingStride, |
| IMG_UINT32 *pui32RangeIndex) |
| { |
| IMG_UINT32 i; |
| IMG_UINT32 ui32Offset; |
| IMG_UINT32 ui32Val; |
| |
| |
| for(i=0; i < SGX_BIF_NUM_TILING_RANGES; i++) |
| { |
| if((psDevInfo->ui32MemTilingUsage & (1U << i)) == 0) |
| { |
| |
| psDevInfo->ui32MemTilingUsage |= 1U << i; |
| |
| if(pui32RangeIndex != IMG_NULL) |
| { |
| *pui32RangeIndex = i; |
| } |
| goto RangeAllocated; |
| } |
| } |
| |
| PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: all tiling ranges in use")); |
| return PVRSRV_ERROR_EXCEEDED_HW_LIMITS; |
| |
| RangeAllocated: |
| |
| |
| if(ui32Start & ~SGX_BIF_TILING_ADDR_MASK) |
| { |
| PVR_DPF((PVR_DBG_WARNING,"SGX_AllocMemTilingRangeInt: Tiling range start (0x%08X) fails" |
| "alignment test", ui32Start)); |
| } |
| if((ui32End + 0x00001000) & ~SGX_BIF_TILING_ADDR_MASK) |
| { |
| PVR_DPF((PVR_DBG_WARNING,"SGX_AllocMemTilingRangeInt: Tiling range end (0x%08X) fails" |
| "alignment test", ui32End)); |
| } |
| |
| ui32Offset = EUR_CR_BIF_TILE0 + (i<<2); |
| |
| ui32Val = ((ui32TilingStride << EUR_CR_BIF_TILE0_CFG_SHIFT) & EUR_CR_BIF_TILE0_CFG_MASK) |
| | (((ui32End>>SGX_BIF_TILING_ADDR_LSB) << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK) |
| | (((ui32Start>>SGX_BIF_TILING_ADDR_LSB) << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK) |
| | (EUR_CR_BIF_TILE0_ENABLE << EUR_CR_BIF_TILE0_CFG_SHIFT); |
| |
| OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val); |
| PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val); |
| |
| #if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS) |
| ui32Offset = EUR_CR_BIF_TILE0_ADDR_EXT + (i<<2); |
| |
| ui32Val = (((ui32End>>SGX_BIF_TILING_EXT_ADDR_LSB) << EUR_CR_BIF_TILE0_ADDR_EXT_MAX_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MAX_MASK) |
| | (((ui32Start>>SGX_BIF_TILING_EXT_ADDR_LSB) << 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); |
| #endif |
| |
| return PVRSRV_OK; |
| } |
| |
| #endif |
| |
| 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 |
| |
| #if defined(SGX_FEATURE_MP) |
| |
| #else |
| SGXInitClocks(psDevInfo, PDUMP_FLAGS_CONTINUOUS); |
| #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"); |
| |
| |
| psDevInfo->ui32NumResets++; |
| 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 |
| |
| #if defined(SUPPORT_MEMORY_TILING) |
| { |
| |
| DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDevInfo->pvDeviceMemoryHeap; |
| IMG_UINT32 i; |
| |
| psDevInfo->ui32MemTilingUsage = 0; |
| |
| for(i=0; i<psDevInfo->ui32HeapCount; i++) |
| { |
| if(psDeviceMemoryHeap[i].ui32XTileStride > 0) |
| { |
| |
| eError = SGX_AllocMemTilingRangeInt( |
| psDevInfo, |
| psDeviceMemoryHeap[i].sDevVAddrBase.uiAddr, |
| psDeviceMemoryHeap[i].sDevVAddrBase.uiAddr |
| + psDeviceMemoryHeap[i].ui32HeapSize, |
| psDeviceMemoryHeap[i].ui32XTileStride, |
| NULL); |
| if(eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "Unable to allocate SGX BIF tiling range for heap: %s", |
| psDeviceMemoryHeap[i].pszName)); |
| break; |
| } |
| } |
| } |
| } |
| #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, |
| MAX_HW_TIME_US/WAIT_TRY_COUNT, |
| IMG_FALSE) != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "SGXInitialise: Wait for uKernel initialisation failed")); |
| #if !defined(FIX_HW_BRN_23281) |
| SGXDumpDebugInfo(psDevInfo, IMG_FALSE); |
| 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) |
| #if !defined(SGX_FEATURE_MP_PLUS) |
| PDUMPCOMMENT("SGX Multi-processor: %d cores", SGX_FEATURE_MP_CORE_COUNT); |
| #else |
| PDUMPCOMMENT("SGX Multi-processor: %d TA cores, %d 3D cores", SGX_FEATURE_MP_CORE_COUNT_TA, SGX_FEATURE_MP_CORE_COUNT_3D); |
| #endif |
| #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->ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount; |
| 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: |
| { |
| |
| if (psDeviceMemoryHeap[i].ui32HeapSize > 0) |
| { |
| 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 |
| #if defined (SUPPORT_SID_INTERFACE) |
| PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, PVRSRV_HEAP_INFO_KM *pasHeapInfo, IMG_DEV_PHYADDR *psPDDevPAddr) |
| #else |
| PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo) |
| #endif |
| { |
| PVRSRV_DEVICE_NODE *psDeviceNode; |
| PVRSRV_SGXDEV_INFO *psDevInfo; |
| PVRSRV_ERROR eError; |
| |
| PDUMPCOMMENT("SGXGetInfoForSrvinit"); |
| |
| psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle; |
| psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice; |
| |
| #if defined (SUPPORT_SID_INTERFACE) |
| *psPDDevPAddr = psDevInfo->sKernelPDDevPAddr; |
| |
| eError = PVRSRVGetDeviceMemHeapsKM(hDevHandle, pasHeapInfo); |
| #else |
| psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr; |
| |
| eError = PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]); |
| #endif |
| 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, |
| #if defined (SUPPORT_SID_INTERFACE) |
| SGX_BRIDGE_INIT_INFO_KM *psInitInfo) |
| #else |
| SGX_BRIDGE_INIT_INFO *psInitInfo) |
| #endif |
| { |
| 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; |
| } |
| |
| |
| #if defined(RESTRICTED_REGISTERS) && defined(SGX_FEATURE_MP) |
| |
| static IMG_VOID SGXDumpMasterDebugReg (PVRSRV_SGXDEV_INFO *psDevInfo, |
| IMG_CHAR *pszName, |
| IMG_UINT32 ui32RegAddr) |
| { |
| IMG_UINT32 ui32RegVal; |
| ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32RegAddr); |
| PVR_LOG(("(HYD) %s%08X", pszName, ui32RegVal)); |
| } |
| |
| #endif |
| |
| 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)); |
| } |
| |
| void dsscomp_kdump(void); |
| IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo, |
| IMG_BOOL bDumpSGXRegs) |
| { |
| IMG_UINT32 ui32CoreNum; |
| |
| dsscomp_kdump(); |
| |
| 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)); |
| |
| SGXDumpDebugReg(psDevInfo, 0, "EUR_CR_CORE_ID: ", EUR_CR_CORE_ID); |
| SGXDumpDebugReg(psDevInfo, 0, "EUR_CR_CORE_REVISION: ", EUR_CR_CORE_REVISION); |
| #if defined(RESTRICTED_REGISTERS) && defined(SGX_FEATURE_MP) |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_BIF_INT_STAT: ", EUR_CR_MASTER_BIF_INT_STAT); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_BIF_FAULT: ",EUR_CR_MASTER_BIF_FAULT); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_CLKGATESTATUS2: ",EUR_CR_MASTER_CLKGATESTATUS2 ); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_PIM_STATUS: ",EUR_CR_MASTER_VDM_PIM_STATUS); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_BIF_BANK_SET: ",EUR_CR_MASTER_BIF_BANK_SET); |
| |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_EVENT_STATUS: ",EUR_CR_MASTER_EVENT_STATUS); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_EVENT_STATUS2: ",EUR_CR_MASTER_EVENT_STATUS2); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_MP_PRIMITIVE: ",EUR_CR_MASTER_MP_PRIMITIVE); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_DPM_DPLIST_STATUS: ",EUR_CR_MASTER_DPM_DPLIST_STATUS); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_DPM_PROACTIVE_PIM_SPEC: ",EUR_CR_MASTER_DPM_PROACTIVE_PIM_SPEC); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_PAGE_MANAGEOP: ",EUR_CR_MASTER_DPM_PAGE_MANAGEOP); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_CONTEXT_STORE_SNAPSHOT: ",EUR_CR_MASTER_VDM_CONTEXT_STORE_SNAPSHOT); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_CONTEXT_LOAD_STATUS: ",EUR_CR_MASTER_VDM_CONTEXT_LOAD_STATUS); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_CONTEXT_STORE_STREAM: ",EUR_CR_MASTER_VDM_CONTEXT_STORE_STREAM); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_CONTEXT_STORE_STATUS: ",EUR_CR_MASTER_VDM_CONTEXT_STORE_STATUS); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_CONTEXT_STORE_STATE0: ",EUR_CR_MASTER_VDM_CONTEXT_STORE_STATE0); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_CONTEXT_STORE_STATE1: ",EUR_CR_MASTER_VDM_CONTEXT_STORE_STATE1); |
| SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_WAIT_FOR_KICK: ",EUR_CR_MASTER_VDM_WAIT_FOR_KICK); |
| #endif |
| for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT_3D; 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 |
| } |
| |
| #if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && !defined(FIX_HW_BRN_31620) |
| { |
| IMG_UINT32 ui32RegVal; |
| IMG_UINT32 ui32PDDevPAddr; |
| |
| |
| |
| |
| ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT); |
| if (ui32RegVal & EUR_CR_BIF_INT_STAT_PF_N_RW_MASK) |
| { |
| ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT); |
| ui32RegVal &= EUR_CR_BIF_FAULT_ADDR_MASK; |
| ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0); |
| ui32PDDevPAddr &= EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK; |
| MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32RegVal); |
| } |
| } |
| #endif |
| } |
| |
| |
| |
| QueueDumpDebugInfo(); |
| |
| { |
| |
| |
| SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl; |
| IMG_UINT32 *pui32HostCtlBuffer = (IMG_UINT32 *)psSGXHostCtl; |
| IMG_UINT32 ui32LoopCounter; |
| |
| if (psSGXHostCtl->ui32AssertFail != 0) |
| { |
| PVR_LOG(("SGX Microkernel assert fail: 0x%08X", psSGXHostCtl->ui32AssertFail)); |
| psSGXHostCtl->ui32AssertFail = 0; |
| } |
| |
| 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->uAllocSize / 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 %s", |
| ui32LastStatusCode, SGXUKernelStatusString(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 %s", ui32LoopCounter, |
| pui32BufPtr[2], pui32BufPtr[3], pui32BufPtr[1], pui32BufPtr[0], |
| SGXUKernelStatusString(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 (TTRACE) |
| PVRSRVDumpTimeTraceBuffers(); |
| #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(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 ui32OpenCLDelayCounter = 0; |
| static IMG_UINT32 ui32NumResets = 0; |
| #if defined(FIX_HW_BRN_31093) |
| static IMG_BOOL bBRN31093Inval = IMG_FALSE; |
| #endif |
| IMG_UINT32 ui32CurrentEDMTasks; |
| IMG_UINT32 ui32CurrentOpenCLDelayCounter=0; |
| 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; |
| ui32CurrentOpenCLDelayCounter = (psDevInfo->psSGXHostCtl)->ui32OpenCLDelayCount; |
| if(0 != ui32CurrentOpenCLDelayCounter) |
| { |
| if(ui32OpenCLDelayCounter != ui32CurrentOpenCLDelayCounter){ |
| ui32OpenCLDelayCounter = ui32CurrentOpenCLDelayCounter; |
| }else{ |
| ui32OpenCLDelayCounter -= 1; |
| (psDevInfo->psSGXHostCtl)->ui32OpenCLDelayCount = ui32OpenCLDelayCounter; |
| } |
| goto SGX_NoUKernel_LockUp; |
| } |
| |
| |
| #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); |
| |
| SGXWaitClocks(psDevInfo, 200); |
| #endif |
| |
| bBRN31093Inval = IMG_TRUE; |
| |
| OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, EUR_CR_BIF_CTRL_INVAL_PTE_MASK); |
| |
| SGXWaitClocks(psDevInfo, 200); |
| |
| #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; |
| (psDevInfo->psSGXHostCtl)->ui32OpenCLDelayCount = 0; |
| } |
| } |
| } |
| else |
| { |
| #if defined(FIX_HW_BRN_31093) |
| bBRN31093Inval = IMG_FALSE; |
| #endif |
| ui32LockupCounter = 0; |
| ui32EDMTasks = ui32CurrentEDMTasks; |
| ui32NumResets = psDevInfo->ui32NumResets; |
| } |
| } |
| SGX_NoUKernel_LockUp: |
| |
| if (bLockup) |
| { |
| SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl; |
| |
| |
| psSGXHostCtl->ui32HostDetectedLockups ++; |
| |
| |
| HWRecoveryResetSGX(psDeviceNode, 0, ISR_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) |
| |
| IMG_INTERNAL |
| PVRSRV_ERROR SGX_AllocMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode, |
| PVRSRV_KERNEL_MEM_INFO *psMemInfo, |
| IMG_UINT32 ui32XTileStride, |
| IMG_UINT32 *pui32RangeIndex) |
| { |
| return SGX_AllocMemTilingRangeInt(psDeviceNode->pvDevice, |
| psMemInfo->sDevVAddr.uiAddr, |
| psMemInfo->sDevVAddr.uiAddr + ((IMG_UINT32) psMemInfo->uAllocSize) + SGX_MMU_PAGE_SIZE - 1, |
| ui32XTileStride, |
| pui32RangeIndex); |
| } |
| |
| IMG_INTERNAL |
| PVRSRV_ERROR SGX_FreeMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode, |
| IMG_UINT32 ui32RangeIndex) |
| { |
| 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; |
| } |
| |
| #endif |
| |
| |
| static IMG_VOID SGXCacheInvalidate(PVRSRV_DEVICE_NODE *psDeviceNode) |
| { |
| PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; |
| |
| #if defined(SGX_FEATURE_MP) |
| psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL; |
| #else |
| PVR_UNREFERENCED_PARAMETER(psDevInfo); |
| #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(FIX_HW_BRN_31620) |
| psDeviceNode->pfnMMUGetCacheFlushRange = &MMU_GetCacheFlushRange; |
| psDeviceNode->pfnMMUGetPDPhysAddr = &MMU_GetPDPhysAddr; |
| #else |
| psDeviceNode->pfnMMUGetCacheFlushRange = IMG_NULL; |
| psDeviceNode->pfnMMUGetPDPhysAddr = IMG_NULL; |
| #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; |
| |
| psDeviceNode->pfnCacheInvalidate = SGXCacheInvalidate; |
| |
| |
| |
| 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++; |
| |
| #if defined(SUPPORT_MEMORY_TILING) |
| |
| psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VPB_TILED_HEAP_ID); |
| psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VPB_TILED_HEAP_BASE; |
| psDeviceMemoryHeap->ui32HeapSize = SGX_VPB_TILED_HEAP_SIZE; |
| psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE |
| | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
| | PVRSRV_HAP_SINGLE_PROCESS; |
| psDeviceMemoryHeap->pszName = "VPB Tiled"; |
| psDeviceMemoryHeap->pszBSName = "VPB Tiled BS"; |
| psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; |
| |
| psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; |
| psDeviceMemoryHeap->ui32XTileStride = SGX_VPB_TILED_HEAP_STRIDE; |
| PVR_DPF((PVR_DBG_WARNING, "VPB tiling heap tiling stride = 0x%x", psDeviceMemoryHeap->ui32XTileStride)); |
| psDeviceMemoryHeap++; |
| #endif |
| |
| |
| 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_SHARED_3DPARAMETERS_HEAP_ID); |
| psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SHARED_3DPARAMETERS_HEAP_BASE; |
| psDeviceMemoryHeap->ui32HeapSize = SGX_SHARED_3DPARAMETERS_HEAP_SIZE; |
| psDeviceMemoryHeap->pszName = "Shared 3DParameters"; |
| psDeviceMemoryHeap->pszBSName = "Shared 3DParameters BS"; |
| psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE |
| | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
| | PVRSRV_HAP_MULTI_PROCESS; |
| psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED; |
| |
| |
| psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; |
| psDeviceMemoryHeap++; |
| |
| |
| psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PERCONTEXT_3DPARAMETERS_HEAP_ID); |
| psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE; |
| psDeviceMemoryHeap->ui32HeapSize = SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE; |
| psDeviceMemoryHeap->pszName = "Percontext 3DParameters"; |
| psDeviceMemoryHeap->pszBSName = "Percontext 3DParameters BS"; |
| psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE |
| | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
| | PVRSRV_HAP_SINGLE_PROCESS; |
| psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; |
| |
| 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_MEM_RAM_BACKED_ALLOCATION |
| | 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); |
| #if defined(PVRSRV_RESET_ON_HWTIMEOUT) |
| OSPanic(); |
| #else |
| PVR_LOG(("OSPanic disabled")); |
| #endif |
| } |
| |
| |
| 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, IMG_NULL); |
| |
| |
| 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; |
| 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, |
| IMG_HANDLE hDevMemContext) |
| { |
| 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, |
| hDevMemContext, |
| IMG_FALSE); |
| |
| 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, |
| hDevMemContext, |
| IMG_FALSE); |
| |
| 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_POLL_BREAKPOINT: |
| { |
| |
| |
| |
| |
| |
| |
| |
| #if !defined(NO_HARDWARE) |
| #if defined(SGX_FEATURE_MP) |
| IMG_BOOL bTrappedBPMaster; |
| IMG_UINT32 ui32CoreNum, ui32TrappedBPCoreNum; |
| #if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) |
| IMG_UINT32 ui32PipeNum, ui32TrappedBPPipeNum; |
| #define NUM_PIPES_PLUS_ONE (SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES+1) |
| #endif |
| IMG_BOOL bTrappedBPAny; |
| #endif |
| IMG_BOOL bFoundOne; |
| |
| #if defined(SGX_FEATURE_MP) |
| ui32TrappedBPCoreNum = 0; |
| bTrappedBPMaster = !!(EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT)); |
| bTrappedBPAny = bTrappedBPMaster; |
| #if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) |
| ui32TrappedBPPipeNum = 0; |
| #endif |
| for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT_3D; ui32CoreNum++) |
| { |
| #if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) |
| |
| |
| |
| #define SGX_MP_CORE_PIPE_SELECT(r,c,p) \ |
| ((SGX_MP_CORE_SELECT(EUR_CR_PARTITION_##r,c) + p*(EUR_CR_PIPE0_##r-EUR_CR_PARTITION_##r))) |
| for (ui32PipeNum = 0; ui32PipeNum < NUM_PIPES_PLUS_ONE; ui32PipeNum++) |
| { |
| bFoundOne = |
| 0 != (EUR_CR_PARTITION_BREAKPOINT_TRAPPED_MASK & |
| OSReadHWReg(psDevInfo->pvRegsBaseKM, |
| SGX_MP_CORE_PIPE_SELECT(BREAKPOINT, |
| ui32CoreNum, |
| ui32PipeNum))); |
| if (bFoundOne) |
| { |
| bTrappedBPAny = IMG_TRUE; |
| ui32TrappedBPCoreNum = ui32CoreNum; |
| ui32TrappedBPPipeNum = ui32PipeNum; |
| } |
| } |
| #else |
| bFoundOne = !!(EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum))); |
| if (bFoundOne) |
| { |
| bTrappedBPAny = IMG_TRUE; |
| ui32TrappedBPCoreNum = ui32CoreNum; |
| } |
| #endif |
| } |
| |
| psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = bTrappedBPAny; |
| #else |
| #if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) |
| #error Not yet considered the case for per-pipe regs in non-mp case |
| #endif |
| psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = 0 != (EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT)); |
| #endif |
| |
| if (psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP) |
| { |
| IMG_UINT32 ui32Info0, ui32Info1; |
| |
| #if defined(SGX_FEATURE_MP) |
| #if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) |
| ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0:SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP_INFO0, ui32TrappedBPCoreNum, ui32TrappedBPPipeNum)); |
| ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1:SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP_INFO1, ui32TrappedBPCoreNum, ui32TrappedBPPipeNum)); |
| #else |
| 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)); |
| #endif |
| #else |
| ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT_TRAP_INFO0); |
| ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT_TRAP_INFO1); |
| #endif |
| |
| #ifdef SGX_FEATURE_PERPIPE_BKPT_REGS |
| psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT; |
| psMiscInfo->uData.sSGXBreakpointInfo.sTrappedBPDevVAddr.uiAddr = ui32Info0 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK; |
| psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPBurstLength = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT; |
| psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBPRead = !!(ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_MASK); |
| psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPDataMaster = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT; |
| psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPTag = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_SHIFT; |
| #else |
| 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; |
| #endif |
| #if defined(SGX_FEATURE_MP) |
| #if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) |
| |
| psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:(ui32TrappedBPCoreNum + (ui32TrappedBPPipeNum<<10)); |
| #else |
| |
| psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:ui32TrappedBPCoreNum; |
| #endif |
| #else |
| #if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) |
| |
| #error non-mp perpipe regs not yet supported |
| #else |
| |
| psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = 65534; |
| #endif |
| #endif |
| } |
| #endif |
| return PVRSRV_OK; |
| } |
| |
| case SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT: |
| { |
| |
| |
| |
| #if !defined(NO_HARDWARE) |
| #if defined(SGX_FEATURE_MP) |
| IMG_UINT32 ui32CoreNum; |
| IMG_BOOL bMaster; |
| #if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) |
| IMG_UINT32 ui32PipeNum; |
| #endif |
| #endif |
| IMG_UINT32 ui32OldSeqNum, ui32NewSeqNum; |
| |
| #if defined(SGX_FEATURE_MP) |
| #if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) |
| ui32PipeNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum >> 10; |
| ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum & 1023; |
| bMaster = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum > 32767; |
| #else |
| ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum; |
| bMaster = ui32CoreNum > SGX_FEATURE_MP_CORE_COUNT_3D; |
| #endif |
| 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 |
| #endif |
| { |
| |
| #if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) |
| ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT, ui32CoreNum, ui32PipeNum)); |
| OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP, ui32CoreNum, ui32PipeNum), EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_MASK); |
| do |
| { |
| ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT, ui32CoreNum, ui32PipeNum)); |
| } |
| 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 |
| } |
| #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, hDevMemContext); |
| 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, |
| hDevMemContext, |
| IMG_FALSE); |
| 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].ui32PID = psMKPerfEntry->ui32PID; |
| psClientHWPerfEntry[i].ui32RTData = psMKPerfEntry->ui32RTData; |
| 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)); |
| |
| OSMemCopy(&psClientHWPerfEntry[i].ui32MiscCounters[0][0], |
| &psMKPerfEntry->ui32MiscCounters[0][0], |
| sizeof(psMKPerfEntry->ui32MiscCounters)); |
| |
| psHWPerfCB->ui32Roff = (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1); |
| } |
| |
| *pui32DataCount = i; |
| *pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed; |
| *pui32HostTimeStamp = OSClockus(); |
| |
| return eError; |
| } |
| |
| |