diff options
author | Eric Luong <x0119002@ti.com> | 2015-02-06 10:54:56 -0800 |
---|---|---|
committer | Hashcode <hashcode0f@gmail.com> | 2015-02-06 10:59:59 -0800 |
commit | 391c312c8964088c512de2cfb1e29c78d245d06b (patch) | |
tree | bdef0b7ecb2ff0da3c9b5922fa358fca1bdbbe73 /pvr-source/services4/srvkm/devices/sgx/sgxinit.c | |
parent | 882c2b4c53e1b2633700906b50c86d4b5f4ce274 (diff) | |
download | hardware_ti_omap4-391c312c8964088c512de2cfb1e29c78d245d06b.tar.gz hardware_ti_omap4-391c312c8964088c512de2cfb1e29c78d245d06b.tar.bz2 hardware_ti_omap4-391c312c8964088c512de2cfb1e29c78d245d06b.zip |
IMG DDK 1.9@2166536 for Android
IMG DDK Release 1.9@2166536 for Android.
Included in this release:
- User space and Kernel module binaries
- Kernel module source code
TI's Patches:
- 084d3db SGX-KM: sgxfreq: Enable on3demand governor as default
- c1e1f93 SGX-KM: on3demand: Added polling based on timeout
- 1baf19c Build: Compile OMAP4 kernel modules with arm-eabi toolchain
- e166956 Build: Add production build option to build script
- 9efd5d3 SGX UM: Properly update vertex shader constants when recompiled
- f6e71f1 Revert "Build: Add optional flag to disable uKernel logging"
- a49e042 SGXKM: Inherit PVRSRV_HAP_GPU_PAGEABLE flag
- f05da87 SGXUM: Creates a new PVRSRV_HAP MAPPING CTRL mask
- 0e6ac23 SGXKM: Creates a new PVRSRV_HAP MAPPING CTRL mask
- 5044cbb SGXKM: Divorce Sparse Mapping from GPU Pageable
- 4abdd37 SGX-KM: sgxfreq: Header for GPL license
- 7a1e61b gpu: thermal: adding cooling device for "case" management
- 1221aba SGX-KM: Add 'userspace' governor to sgxfreq
- 7cc1319 SGX-KM: Add on3demand governor to sgxfreq
- c3283ff SGX-KM: Allow sgxfreq active notification when prev state was active
- 7275e62 SGX-KM: Add idle and active time caluclation to sgxfreq
- e15265c SGX-KM: Add frame_done interface to sgxfreq
- a021f10 SGX-KM: Add activeidle governor to sgxfreq
- bbdceee SGX-KM: Add active/idle notification to sgxfreq
- 4e1e8d9 SGX-UM: Rework SGX idle notification
- fce3459 SGX-KM: Rework SGX idle notification
- 17cdf8c SGX-KM: Add onoff governor to sgxfreq
- 403caa1 SGX-KM: Add cooling device interface to sgxfreq
- 1d785b8 SGX-KM: Add sgxfreq subsystem for DVFS control
- 14de6d8 Build: Add optional flag to disable uKernel logging
- 374bea1 SGX UM: Set ro.product.processor before loading modules
- 91d286d SGX UM: Pvrsrvinit fix typo in remount command
- 3d08869 SGX UM: Remove BRN32044 for omap5
- 086f52b OMAP5: WA: Race condition when SGX is powered down
- 1a904c2 SGX KM: ShrinkPagePool statistics changed to PVR_DBG_MESSAGE
- fbf2890 SGX KM: Fix num_handle calculation for ion handles
- 322af97 BUILD: fix usage and help
- 50440d3 BUILD: Add install option "adb"
- ee66bfb pvr-km: gc: Add page offset for ion allocated buffers
- be4fe11 pvr-km: gc: Improve gc map/unmap logging
- 51da16d gralloc: Map NV12 buffers with the GC MMU
- 210b590 SGX-KM: Enable APM for OMAP5
- 31e2f05 SGX-UM: Enable APM for OMAP5
- a98b81b SGX-UM: Don't load omaplfb module when in-kernel driver is present
- b20f5c6 SGX-KM: Support in-kernel omaplfb
- 0955f19 SGXKM: Multi-plane support for deviceclass i-face
- 11f6682 build: remove omaplfb from install step
- 9ecd6e0 pvr-um: use arm-linux-androideabi- and fix JB debug build
- abef31d PVR-UM: Make pvrsrvinit wrapper compatible with Jellybean
- 5b4e4f0 Revert "SGXUM: Implements Gralloc late CPU mapping"
- 5f25289 SGX-UM: build - Remove target platform based configuration
- 9d5ac31 OMAP5: BUILD: Remove unused variable
- 5365b64 readme: Correct DDK version
- 8095cc6 SGX-UM: Add support for hardware specific powervr.ini files
- 7e13d26 PVR-UM: Add support to DDK for powervr.ini files
- e545f59 SGX-UM: Added 16 bit depth EGL configs
- 27da0ae SGX UM: Srvinit block until services ready
- ba35538 SGX UM: HAL block OpenPVRServices until services initialized
- 43f8c1f SGX UM: Fix calculation of chroma plane in blit_internal
- f6a6944 SGX KM: Dump dsscomp info during HW recovery
- fc6d85b SGXKM: Adds support for 1D buffer allocation
- d8d061b SGXKM: Do not perform explicit invalidate on mmap
- 3ac6e1f SGXUM: Implements Gralloc late CPU mapping
- b621744 SGXUM: Gralloc allow for late or no GPU mapping
- dde30cf SGXUM: Add allocation of images from system heap
- 552c0f5 SGXUM: Adds A8/U8/Y8 color format to WSEGL
- f1c7822 SGXKM: Increase XPROC_WORKAROUND to 500
- 65f61bf SGXKM: Fix cc-check.sh file permissions
- 0dfe392 SGXKM: Make the DMM offset optional
- 946eb30 gralloc: add support for GRALLOC_USAGE_EXCLUSIVE_DISP
- 5cf7248 gralloc: publicly define omap specific usage flags
- afcb9bd SGX-KM: Block DPLL cascading when SGX clock is enabled
- 616ff0b SGX-KM: Hold wake lock during hardware recovery
- 872b4c0 SGXKM: Fix NULL handle warning when blitting GC320
- 39de55c SGXKM: Allow for late or no GPU mapping
- d229a7b SGXKM: Allow for SW access to a tiler buffer
- 7024790 SGXUM: Adds YUV plane offsets for MM
- d202649 SGXKM: SGX Tiler non-page-aligned support
- 2b2ac18 SGXUM: Implements GPU Common Buffer Interface
- 86cd052 SGXUM: Multi-buffer manage bridge
- d272c49 SGXKM: Multi-buffer manage bridge
- 4d8facf SGXKM: Implements Heap Alloc Failure Report
- 6d4253a SGXUM: Add support for GPU unmap/remap
- 64f4805 SGXKM: Add support for GPU unmap/remap
- 5425356 SGX-KM: Use CONFIG_DRM_OMAP_DMM_TILER for kernel 3.4
- 853be19 SGX-KM: Use pud_offset to get pmd_offset
- 5ec5d70 PVR-KM: Prevent compilation of dc_omapfb3_linux
- 1bbe8a2 SGX-KM: Remove hardcoding of values in egl.cfg
- 83b8af6 pvr-km: kfree phys info at unmap instead of map
- f347fb9 pvr-km: add a struct size to the physical descriptor
- 6ccff8f gralloc: Set flag to enable GC MMU mapping in PVR services
- 0cfaa6d PVR-KM: Add function to obtain BV descriptor through 3PDC interface
- c8f4c5f PVR-KM: Map buffers to GC core MMU on allocation time with Bltsville
- 65b2b84 SGXKM: Prevent mapping of export with zero ref
- f4cc0a2 OMAP4-SGX-UM: Allow for tiler buffer SW access
- 5c97ded OMAP4-SGX-UM: Gralloc SW access and caching flags
- bbf5424 OMAP4-SGX-UM: Gralloc HAL_PIXEL_FORMAT_NV12 format
- ec6cc69 SGX-KM: Make PVRSRVExportFDToIONHandles generic and register it with ion
- 8c1255d PVR-KM: OMAP5: Use shared device for Tiler 2D Mappings
- 2391ac8 PVR-KM: OMAP5: Hardcode core version value
- 7d87962 SGX-KM: OMAP5: HACK: Set the size of the SGX registers
- 9f40224 SGX-UM: add detection of OMAP5432 in pvrsrvinit
- f75d48b SGX-UM: build: Add panda5 and omap5sevm to product list
- c23eff9 SGX-KM: BUILD: Add OMAP5 support
- 5cc4ade SGX-UM: BUILD: Consolidate build into a single Makefile
- 2c6a2f6 SGX-KM: (build) Remove Android product and version dependency
- 6f54fe8 Build: Don't install egl.cfg anymore
- a49c59c SGX-KM: egl.cfg sysfs entry
- c759928 SGX-KM: Enable DPF, TRACE and ASSERT
- 1628094 build-km: Enable blaze and blaze_tablet for ICS environment
- 05f00eb build: Enable blaze and blaze_tablet for ICS environment
- 542e279 SGX-KM: Add ability to build multiple sets of GFX kernel modules
- 69d3661 build: Set correct load directory for kernel modules.
- 2dfe14b KM: add support for sgx544sc
- 58f317a SGX-UM: Add ability to build multiple sets of GFX binaries
- 04e5deb SGX-KM: Use platform data for OPP symbols.
- 5eed373 SGX-UM: Enable building binaries for specific SGX
- 0801be2 readme: Add README
- 649d010 build: Add build_DDK.sh
- fe34640 Create gitignore file
- 519ca9a IMG DDK 1.9@2166536 for Android
Change-Id: I4a060344fa134a2484d1b7a69fc87963455e9e34
Signed-off-by: Eric Luong <x0119002@ti.com>
Diffstat (limited to 'pvr-source/services4/srvkm/devices/sgx/sgxinit.c')
-rw-r--r-- | pvr-source/services4/srvkm/devices/sgx/sgxinit.c | 3428 |
1 files changed, 3428 insertions, 0 deletions
diff --git a/pvr-source/services4/srvkm/devices/sgx/sgxinit.c b/pvr-source/services4/srvkm/devices/sgx/sgxinit.c new file mode 100644 index 0000000..199aa9d --- /dev/null +++ b/pvr-source/services4/srvkm/devices/sgx/sgxinit.c @@ -0,0 +1,3428 @@ +/*************************************************************************/ /*! +@Title Device specific initialisation routines +@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved +@License Dual MIT/GPLv2 + +The contents of this file are subject to the MIT license as set out below. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +Alternatively, the contents of this file may be used under the terms of +the GNU General Public License Version 2 ("GPL") in which case the provisions +of GPL are applicable instead of those above. + +If you wish to allow use of your version of this file only under the terms of +GPL, and not to allow others to use your version of this file under the terms +of the MIT license, indicate your decision by deleting the provisions above +and replace them with the notice and other provisions required by GPL as set +out in the file called "GPL-COPYING" included in this distribution. If you do +not delete the provisions above, a recipient may use your version of this file +under the terms of either the MIT license or GPL. + +This License is also included in this distribution in the file called +"MIT-COPYING". + +EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS +PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ /**************************************************************************/ + +#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" + +extern int powering_down; + +#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 /* defined(PVRSRV_USSE_EDM_STATUS_DEBUG) */ + +#define VAR(x) #x +/* PRQA S 0881 11 */ /* ignore 'order of evaluation' warning */ +#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 + +/*! +******************************************************************************* + + @Function SGXCommandComplete + + @Description + + SGX command complete handler + + @Input psDeviceNode - SGX device node + + @Return none + +******************************************************************************/ +static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE *psDeviceNode) +{ +#if defined(OS_SUPPORTS_IN_LISR) + if (OSInLISR(psDeviceNode->psSysData)) + { + /* + * We shouldn't call SGXScheduleProcessQueuesKM in an + * LISR, as it may attempt to power up SGX. + * We assume that the LISR will schedule the MISR, which + * will test the following flag, and call + * SGXScheduleProcessQueuesKM if the flag is set. + */ + psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE; + } + else + { + SGXScheduleProcessQueuesKM(psDeviceNode); + } +#else + SGXScheduleProcessQueuesKM(psDeviceNode); +#endif +} + +/*! +******************************************************************************* + + @Function DeinitDevInfo + + @Description + + Deinits DevInfo + + @Input none + + @Return none + +******************************************************************************/ +static IMG_UINT32 DeinitDevInfo(PVRSRV_SGXDEV_INFO *psDevInfo) +{ + if (psDevInfo->psKernelCCBInfo != IMG_NULL) + { + /* + Free CCB info. + */ + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SGX_CCB_INFO), psDevInfo->psKernelCCBInfo, IMG_NULL); + } + + return PVRSRV_OK; +} + +/*! +******************************************************************************* + + @Function InitDevInfo + + @Description + + Loads DevInfo + + @Input psDeviceNode + + @Return PVRSRV_ERROR + +******************************************************************************/ +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 + /* + * Assign client-side build options for later verification + */ + psDevInfo->ui32ClientBuildOptions = psInitInfo->ui32ClientBuildOptions; + + /* + * Assign microkernel IF structure sizes for later verification + */ + psDevInfo->sSGXStructSizes = psInitInfo->sSGXStructSizes; + + /* + Setup the kernel version of the CCB control + */ + 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; + + /* + Copy the USE code addresses for the host kick. + */ + 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 /* SGX_FEATURE_MP */ + + + /* Initialise Dev Data */ + 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; + } + case SGX_INIT_OP_READ_HW_REG: + { + OSReadHWReg(psDevInfo->pvRegsBaseKM, psComm->sReadHWReg.ui32Offset); +#if defined(PDUMP) + PDUMPCOMMENT("SGXRunScript: Read HW reg operation"); + PDumpRegRead(SGX_PDUMPREG_NAME, psComm->sReadHWReg.ui32Offset, PDUMP_FLAGS_CONTINUOUS); +#endif + 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: + /* FALLTHROUGH */ + 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; + + /* HW supports 10 ranges */ + for(i=0; i < SGX_BIF_NUM_TILING_RANGES; i++) + { + if((psDevInfo->ui32MemTilingUsage & (1U << i)) == 0) + { + /* mark in use */ + psDevInfo->ui32MemTilingUsage |= 1U << i; + /* output range index if the caller wants it */ + 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: + + /* An improperly aligned range could cause BIF not to tile some memory which is intended to be tiled, + * or cause BIF to tile some memory which is not intended to be. + */ + 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 /* SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS */ + + return PVRSRV_OK; +} + +#endif /* SUPPORT_MEMORY_TILING */ + +/*! +******************************************************************************* + + @Function SGXInitialise + + @Description + + (client invoked) chip-reset and initialisation + + @Input pvDeviceNode - device info. structure + @Input bHardwareRecovery - true if recovering powered hardware, + false if powering up + + @Return PVRSRV_ERROR + +******************************************************************************/ +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 /* PDUMP */ + +#if defined(SGX_FEATURE_MP) + /* Slave core clocks must be enabled during reset */ +#else + SGXInitClocks(psDevInfo, PDUMP_FLAGS_CONTINUOUS); +#endif /* SGX_FEATURE_MP */ + + /* + Part 1 of the initialisation script runs before resetting SGX. + */ + 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"); + + /* Reset the chip */ + psDevInfo->ui32NumResets++; + +#if !defined(SGX_FEATURE_MP) + bHardwareRecovery |= bFirstTime; +#endif /* SGX_FEATURE_MP */ + + SGXReset(psDevInfo, bHardwareRecovery, PDUMP_FLAGS_CONTINUOUS); + +#if defined(EUR_CR_POWER) +#if defined(SGX531) + /* + Disable half the pipes. + 531 has 2 pipes within a 4 pipe framework, so + the 2 redundant pipes must be disabled even + though they do not exist. + */ + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 1); + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 1); +#else + /* set the default pipe count (all fully enabled) */ + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 0); + PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 0); +#endif +#endif + + /* Initialise the kernel CCB event kicker value */ + *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 /* PDUMP */ + +#if defined(SUPPORT_MEMORY_TILING) + { + /* Initialise EUR_CR_BIF_TILE registers for any tiling heaps */ + 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) + { + /* Set up the HW control registers */ + 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 + + /* + Part 2 of the initialisation script runs after resetting SGX. + */ + 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"); + + /* Record the system timestamp for the microkernel */ + 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 /* PDUMP */ + +#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 /* SGX_FEATURE_MULTI_EVENT_KICK */ + + OSMemoryBarrier(); + +#if defined(PDUMP) + /* + Dump the host kick. + */ + 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 /* SGX_FEATURE_MULTI_EVENT_KICK */ + } +#endif /* PDUMP */ + +#if !defined(NO_HARDWARE) + /* + Wait for the microkernel to finish initialising. + */ + 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")); + + SGXDumpDebugInfo(psDevInfo, IMG_FALSE); + PVR_DBG_BREAK; + + return PVRSRV_ERROR_RETRY; + } +#endif /* NO_HARDWARE */ + +#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 /* PDUMP */ + + PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset == psDevInfo->psKernelCCBCtl->ui32WriteOffset); + + bFirstTime = IMG_FALSE; + + return PVRSRV_OK; +} + +/*! +******************************************************************************* + + @Function SGXDeinitialise + + @Description + + (client invoked) chip-reset and deinitialisation + + @Input hDevCookie - device info. handle + + @Return PVRSRV_ERROR + +******************************************************************************/ +PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie) + +{ + PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *) hDevCookie; + PVRSRV_ERROR eError; + + /* Did SGXInitialise map the SGX registers in? */ + 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; +} + + +/*! +******************************************************************************* + + @Function DevInitSGXPart1 + + @Description + + Reset and initialise Chip + + @Input pvDeviceNode - device info. structure + + @Return PVRSRV_ERROR + +******************************************************************************/ +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; + + /* pdump info about the core */ + 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 /* SGX_FEATURE_MP */ + +#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 /* SGX_BYPASS_SYSTEM_CACHE */ + #endif /* SGX_FEATURE_SYSTEM_CACHE */ + + PDUMPCOMMENT("SGX Initialisation Part 1"); + + /* Allocate device control block */ + 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)); + + /* setup info from jdisplayconfig.h (variations controlled by build) */ + psDevInfo->eDeviceType = DEV_DEVICE_TYPE; + psDevInfo->eDeviceClass = DEV_DEVICE_CLASS; + + /* Initialize SGX idle status */ + psDevInfo->bSGXIdle = IMG_TRUE; + + /* Store the devinfo as its needed by dynamically enumerated systems called from BM */ + psDeviceNode->pvDevice = (IMG_PVOID)psDevInfo; + + /* get heap info from the devnode */ + psDevInfo->ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount; + psDevInfo->pvDeviceMemoryHeap = (IMG_VOID*)psDeviceMemoryHeap; + + /* create the kernel memory context */ + 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; + + /* create the kernel, shared and shared_exported heaps */ + 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: + { + /* Shared PB heap could be zero size */ + if (psDeviceMemoryHeap[i].ui32HeapSize > 0) + { + hDevMemHeap = BM_CreateHeap (hKernelDevMemContext, + &psDeviceMemoryHeap[i]); + /* + in the case of kernel context heaps just store + the heap handle in the heap info structure + */ + psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap; + } + break; + } + } + } +#if defined(PDUMP) + if(hDevMemHeap) + { + /* set up the MMU pdump info */ + 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; +} + +/*! +******************************************************************************* + + @Function SGXGetInfoForSrvinitKM + + @Description + + Get SGX related information necessary for initilisation server + + @Input hDevHandle - device handle + psInitInfo - pointer to structure for returned information + + @Output psInitInfo - pointer to structure containing returned information + + @Return PVRSRV_ERROR + +******************************************************************************/ +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; +} + +/*! +******************************************************************************* + + @Function DevInitSGXPart2KM + + @Description + + Reset and initialise Chip + + @Input pvDeviceNode - device info. structure + + @Return PVRSRV_ERROR + +******************************************************************************/ +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; + + /* + Init devinfo + */ + 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; + } + + /* Registers already mapped? */ + if (psSGXDeviceMap->pvRegsCpuVBase) + { + psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase; + } + else + { + /* Map Regs */ + 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) + { + /* Map Host Port */ + 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/* #ifdef SGX_FEATURE_HOST_PORT */ + +#if defined (SYS_USING_INTERRUPTS) + + /* Set up ISR callback information. */ + psDeviceNode->pvISRData = psDeviceNode; + /* ISR handler address was set up earlier */ + PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler); + +#endif /* SYS_USING_INTERRUPTS */ + + /* Prevent the microkernel being woken up before there is something to do. */ + psDevInfo->psSGXHostCtl->ui32PowerStatus |= PVRSRV_USSE_EDM_POWMAN_NO_WORK; + eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF; + /* Register the device with the power manager. */ + 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(SUPPORT_EXTERNAL_SYSTEM_CACHE) + /* map the external system cache control registers into the SGX MMU */ + 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 /* SUPPORT_EXTERNAL_SYSTEM_CACHE */ + + /* + Initialise the Kernel CCB + */ + 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; +} + +/*! +******************************************************************************* + + @Function DevDeInitSGX + + @Description + + Reset and deinitialise Chip + + @Input pvDeviceNode - device info. structure + + @Return PVRSRV_ERROR + +******************************************************************************/ +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) + { + /* Can happen if DevInitSGX failed */ + 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 /* SUPPORT_HW_RECOVERY */ + +#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE) + /* unmap the external system cache control registers */ + eError = MMU_UnmapExtSystemCacheRegs(psDeviceNode); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to unmap ext system cache registers")); + return eError; + } +#endif /* SUPPORT_EXTERNAL_SYSTEM_CACHE */ + + MMU_BIFResetPDFree(psDevInfo); + + /* + DeinitDevInfo the DevInfo + */ + DeinitDevInfo(psDevInfo); + + /* Destroy heaps. */ + 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; + } + } + } + + /* Destroy the kernel context. */ + 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; + } + + /* remove the device from the power manager */ + 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; + } + + /* Only unmap the registers if they were mapped here */ + if (!psSGXDeviceMap->pvRegsCpuVBase) + { + /* UnMap Regs */ + 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) + { + /* unMap Host Port */ + if (psDevInfo->pvHostPortBaseKM != IMG_NULL) + { + OSUnMapPhysToLin(psDevInfo->pvHostPortBaseKM, + psDevInfo->ui32HPSize, + PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED, + IMG_NULL); + } + } +#endif /* #ifdef SGX_FEATURE_HOST_PORT */ + + + /* DeAllocate devinfo */ + OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, + sizeof(PVRSRV_SGXDEV_INFO), + psDevInfo, + 0); + + psDeviceNode->pvDevice = IMG_NULL; + + if (psDeviceMemoryHeap != IMG_NULL) + { + /* Free the device memory heap info. */ + 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) + +/*! +******************************************************************************* + + @Function SGXDumpMasterDebugReg + + @Description + + Dump a single SGX debug register value + + @Input psDevInfo - SGX device info + @Input pszName - string used for logging + @Input ui32RegAddr - SGX register offset + + @Return IMG_VOID + +******************************************************************************/ +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 /* defined(RESTRICTED_REGISTERS) */ + +/*! +******************************************************************************* + + @Function SGXDumpDebugReg + + @Description + + Dump a single SGX debug register value + + @Input psDevInfo - SGX device info + @Input ui32CoreNum - processor number + @Input pszName - string used for logging + @Input ui32RegAddr - SGX register offset + + @Return IMG_VOID + +******************************************************************************/ +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)); +} + +#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) || defined(FIX_HW_BRN_31620) +static INLINE IMG_UINT32 GetDirListBaseReg(IMG_UINT32 ui32Index) +{ + if (ui32Index == 0) + { + return EUR_CR_BIF_DIR_LIST_BASE0; + } + else + { + return (EUR_CR_BIF_DIR_LIST_BASE1 + ((ui32Index - 1) * 0x4)); + } +} +#endif + +void dsscomp_kdump(void); +/*! +******************************************************************************* + + @Function SGXDumpDebugInfo + + @Description + + Dump useful debugging info + + @Input psDevInfo - SGX device info + @Input bDumpSGXRegs - Whether to dump SGX debug registers. Must not be done + when SGX is not powered. + + @Return IMG_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++) + { + /* Dump HW event status */ + 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(RESTRICTED_REGISTERS) + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_BANK_SET: ", EUR_CR_BIF_BANK_SET); + + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_CLKGATECTL: ", EUR_CR_CLKGATECTL); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_CLKGATESTATUS: ", EUR_CR_CLKGATESTATUS); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_MTE_CTRL: ", EUR_CR_MTE_CTRL); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_OTHER_PDS_EXEC: ", EUR_CR_EVENT_OTHER_PDS_EXEC); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_OTHER_PDS_DATA: ", EUR_CR_EVENT_OTHER_PDS_DATA); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_OTHER_PDS_INFO: ", EUR_CR_EVENT_OTHER_PDS_INFO); + + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_ZLS_PAGE_THRESHOLD: ", EUR_CR_DPM_ZLS_PAGE_THRESHOLD); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_TA_GLOBAL_LIST: ", EUR_CR_DPM_TA_GLOBAL_LIST); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_STATE_CONTEXT_ID: ", EUR_CR_DPM_STATE_CONTEXT_ID); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_CONTEXT_PB_BASE: ", EUR_CR_DPM_CONTEXT_PB_BASE); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_TA_ALLOC_FREE_LIST_STATUS1: ", EUR_CR_DPM_TA_ALLOC_FREE_LIST_STATUS1); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_3D_FREE_LIST_STATUS1: ", EUR_CR_DPM_3D_FREE_LIST_STATUS1); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_TA_ALLOC_FREE_LIST_STATUS2: ", EUR_CR_DPM_TA_ALLOC_FREE_LIST_STATUS2); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_3D_FREE_LIST_STATUS2: ", EUR_CR_DPM_3D_FREE_LIST_STATUS2); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_ABORT_STATUS_MTILE: ", EUR_CR_DPM_ABORT_STATUS_MTILE); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_PAGE_STATUS: ", EUR_CR_DPM_PAGE_STATUS); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_PAGE: ", EUR_CR_DPM_PAGE); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_GLOBAL_PAGE_STATUS: ", EUR_CR_DPM_GLOBAL_PAGE_STATUS); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_CONTEXT_LOAD_STATUS: ", EUR_CR_VDM_CONTEXT_LOAD_STATUS); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_CONTEXT_STORE_STATUS: ", EUR_CR_VDM_CONTEXT_STORE_STATUS); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_TASK_KICK_STATUS: ", EUR_CR_VDM_TASK_KICK_STATUS); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_CONTEXT_STORE_STATE0: ", EUR_CR_VDM_CONTEXT_STORE_STATE0); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_CONTEXT_STORE_STATE1: ", EUR_CR_VDM_CONTEXT_STORE_STATE1); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_REQUESTING: ", EUR_CR_DPM_REQUESTING); + SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_REQUESTING: ", EUR_CR_DPM_REQUESTING); + +#endif + } + + #if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && !defined(FIX_HW_BRN_31620) + { + IMG_UINT32 ui32RegVal; + IMG_UINT32 ui32PDDevPAddr; + + /* + If there was a SGX pagefault check the page table too see if the + host thinks the fault is correct + */ + 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); + } + } + #else + { + IMG_UINT32 ui32FaultAddress; + IMG_UINT32 ui32Bank0; + IMG_UINT32 ui32DirListIndex; + IMG_UINT32 ui32PDDevPAddr; + + ui32FaultAddress = OSReadHWReg(psDevInfo->pvRegsBaseKM, + EUR_CR_BIF_FAULT); + ui32FaultAddress = ui32FaultAddress & EUR_CR_BIF_FAULT_ADDR_MASK; + + ui32Bank0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0); + + /* Check the EDM's's memory context */ + ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_EDM_MASK) >> EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT; + ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, + GetDirListBaseReg(ui32DirListIndex)); + PVR_LOG(("Checking EDM memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr)); + MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress); + + /* Check the TA's memory context */ + ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_TA_MASK) >> EUR_CR_BIF_BANK0_INDEX_TA_SHIFT; + ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, + GetDirListBaseReg(ui32DirListIndex)); + PVR_LOG(("Checking TA memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr)); + MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress); + + /* Check the 3D's memory context */ + ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_3D_MASK) >> EUR_CR_BIF_BANK0_INDEX_3D_SHIFT; + ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, + GetDirListBaseReg(ui32DirListIndex)); + PVR_LOG(("Checking 3D memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr)); + MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress); + + #if defined(EUR_CR_BIF_BANK0_INDEX_2D_MASK) + /* Check the 2D's memory context */ + ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_2D_MASK) >> EUR_CR_BIF_BANK0_INDEX_2D_SHIFT; + ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, + GetDirListBaseReg(ui32DirListIndex)); + PVR_LOG(("Checking 2D memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr)); + MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress); + #endif + + #if defined(EUR_CR_BIF_BANK0_INDEX_PTLA_MASK) + /* Check the 2D's memory context */ + ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_PTLA_MASK) >> EUR_CR_BIF_BANK0_INDEX_PTLA_SHIFT; + ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, + GetDirListBaseReg(ui32DirListIndex)); + PVR_LOG(("Checking PTLA memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr)); + MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress); + #endif + + #if defined(EUR_CR_BIF_BANK0_INDEX_HOST_MASK) + /* Check the Host's memory context */ + ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_HOST_MASK) >> EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT; + ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, + GetDirListBaseReg(ui32DirListIndex)); + PVR_LOG(("Checking Host memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr)); + MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress); + #endif + } + #endif + } + /* + Dump out the outstanding queue items. + */ + QueueDumpDebugInfo(); + + { + /* + Dump out the Host control. + */ + 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])); + } + } + + { + /* + Dump out the TA/3D control. + */ + 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) + /* + Dump the raw microkernel trace buffer to the log. + */ + { + 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 /* PVRSRV_DUMP_MK_TRACE */ + } + #endif /* PVRSRV_USSE_EDM_STATUS_DEBUG */ + + { + /* + Dump out the kernel CCB. + */ + 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 /* PVRSRV_DUMP_KERNEL_CCB */ + } + #if defined (TTRACE) + PVRSRVDumpTimeTraceBuffers(); + #endif + +} + + +#if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY) +/*! +******************************************************************************* + + @Function HWRecoveryResetSGX + + @Description + + Resets SGX + + Note: may be called from an ISR so should not call pdump. + + @Input psDevInfo - dev info + + @Input ui32Component - core component to reset + + @Return IMG_VOID + +******************************************************************************/ +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; + +#if defined(SUPPORT_HWRECOVERY_TRACE_LIMIT) + static IMG_UINT32 ui32Clockinus = 0; + static IMG_UINT32 ui32HWRecoveryCount=0; + IMG_UINT32 ui32TempClockinus=0; +#endif + + PVR_UNREFERENCED_PARAMETER(ui32Component); + + /* Debug dumps associated with HWR can be long. Delay system suspend */ + SysLockSystemSuspend(); + + /* + Ensure that hardware recovery is serialised with any power transitions. + */ + eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE); + if(eError != PVRSRV_OK) + { + /* + Unable to obtain lock because there is already a power transition + in progress. + */ + 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")); + +#if defined(SUPPORT_HWRECOVERY_TRACE_LIMIT) +/* + * The following defines are system specific and should be defined in + * the corresponding sysconfig.h file. The values indicated are examples only. + SYS_SGX_HWRECOVERY_TRACE_RESET_TIME_PERIOD 5000000 //(5 Seconds) + SYS_SGX_MAX_HWRECOVERY_OCCURANCE_COUNT 5 + */ + ui32TempClockinus = OSClockus(); + if((ui32TempClockinus-ui32Clockinus) < SYS_SGX_HWRECOVERY_TRACE_RESET_TIME_PERIOD){ + ui32HWRecoveryCount++; + if(SYS_SGX_MAX_HWRECOVERY_OCCURANCE_COUNT <= ui32HWRecoveryCount){ + OSPanic(); + } + }else{ + ui32Clockinus = ui32TempClockinus; + SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE); + ui32HWRecoveryCount = 0; + } +#else + SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE); +#endif + + /* Suspend pdumping. */ + PDUMPSUSPEND(); + + /* Reset and re-initialise SGX. */ + eError = SGXInitialise(psDevInfo, IMG_TRUE); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"HWRecoveryResetSGX: SGXInitialise failed (%d)", eError)); + } + + /* Resume pdumping. */ + PDUMPRESUME(); + + PVRSRVPowerUnlock(ui32CallerID); + + SysUnlockSystemSuspend(); + + /* Send a dummy kick so that we start processing again */ + SGXScheduleProcessQueuesKM(psDeviceNode); + + /* Flush any old commands from the queues. */ + PVRSRVProcessQueues(IMG_TRUE); +} +#endif /* #if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY) */ + + +#if defined(SUPPORT_HW_RECOVERY) +/*! +****************************************************************************** + + @Function SGXOSTimer + + @Description + + Timer function for SGX + + @Input pvData - private data + + @Return PVRSRV_ERROR + +******************************************************************************/ +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; /* To prevent false positives */ + 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; + + /* increment a timestamp */ + psDevInfo->ui32TimeStamp++; + +#if defined(NO_HARDWARE) + bPoweredDown = IMG_TRUE; +#else + bPoweredDown = (SGXIsDevicePowered(psDeviceNode)) ? IMG_FALSE : IMG_TRUE; +#endif /* NO_HARDWARE */ + + /* + * Check whether EDM timer tasks are getting scheduled. If not, assume + * that SGX has locked up and reset the chip. + */ + + /* Check whether the timer should be running */ + if (bPoweredDown) + { + ui32LockupCounter = 0; + #if defined(FIX_HW_BRN_31093) + bBRN31093Inval = IMG_FALSE; + #endif + } + else + { + /* The PDS timer should be running. */ + 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) + { + /* It could be a BIF hang so do a INVAL_PTE */ + #if defined(FIX_HW_BRN_29997) + IMG_UINT32 ui32BIFCtrl; + /* Pause the BIF before issuing the invalidate */ + ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_PAUSE_MASK); + /* delay for 200 clocks */ + SGXWaitClocks(psDevInfo, 200); + #endif + /* Flag that we have attempt to un-block the BIF */ + bBRN31093Inval = IMG_TRUE; + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, EUR_CR_BIF_CTRL_INVAL_PTE_MASK); + /* delay for 200 clocks */ + SGXWaitClocks(psDevInfo, 200); + + #if defined(FIX_HW_BRN_29997) + /* un-pause the BIF by restoring the BIF_CTRL */ + 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; + + /* increment the counter so we know the host detected the lockup */ + psSGXHostCtl->ui32HostDetectedLockups ++; + + /* Reset the chip and process the queues. */ + HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID); + } +} +#endif /* defined(SUPPORT_HW_RECOVERY) */ + + + +#if defined(SYS_USING_INTERRUPTS) + +/* + SGX ISR Handler +*/ +IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData) +{ + IMG_BOOL bInterruptProcessed = IMG_FALSE; + + + /* Real Hardware */ + { + IMG_UINT32 ui32EventStatus = 0, ui32EventEnable = 0; + 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; + + /* check for null pointers */ + 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; + + if(!powering_down) { + ui32EventStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS); + ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE); + } + + /* test only the unmasked bits */ + ui32EventStatus &= ui32EventEnable; + +#if defined(SGX_FEATURE_DATA_BREAKPOINTS) + if(!powering_down) { + ui32EventStatus2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2); + ui32EventEnable2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE2); + } + + /* test only the unmasked bits */ + ui32EventStatus2 &= ui32EventEnable2; +#endif /* defined(SGX_FEATURE_DATA_BREAKPOINTS) */ + + /* Thought: is it better to insist that the bit assignment in + the "clear" register(s) matches that of the "status" register(s)? + It would greatly simplify this LISR */ + + 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 /* defined(SGX_FEATURE_DATA_BREAKPOINTS) */ + + if (ui32EventClear || ui32EventClear2) + { + bInterruptProcessed = IMG_TRUE; + + /* Clear master interrupt bit */ + ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK; + + if(!powering_down) { + /* clear the events */ + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32EventClear); + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32EventClear2); + } + } + } + + return bInterruptProcessed; +} + + +/* + SGX MISR Handler +*/ +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 (SYS_USING_INTERRUPTS) */ + +#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; + } + + /* clear the usage bit */ + psDevInfo->ui32MemTilingUsage &= ~(1<<ui32RangeIndex); + + /* disable the range */ + ui32Offset = EUR_CR_BIF_TILE0 + (ui32RangeIndex<<2); + ui32Val = 0; + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val); + PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val); + + return PVRSRV_OK; +} + +#endif /* defined(SUPPORT_MEMORY_TILING) */ + + +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 /* SGX_FEATURE_MP */ +} + +/*! +******************************************************************************* + + @Function SGXRegisterDevice + + @Description + + Registers the device with the system + + @Input: psDeviceNode - device node + + @Return PVRSRV_ERROR : + +******************************************************************************/ +PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode) +{ + DEVICE_MEMORY_INFO *psDevMemoryInfo; + DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; + + /* setup details that never change */ + psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE; + psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS; +#if defined(PDUMP) + { + /* memory space names are set up in system code */ + 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 /* PDUMP */ + + psDeviceNode->pfnInitDevice = &DevInitSGXPart1; + psDeviceNode->pfnDeInitDevice = &DevDeInitSGX; + + psDeviceNode->pfnInitDeviceCompatCheck = &SGXDevInitCompatCheck; +#if defined(PDUMP) + psDeviceNode->pfnPDumpInitDevice = &SGXResetPDump; + psDeviceNode->pfnMMUGetContextID = &MMU_GetPDumpContextID; +#endif + /* + MMU callbacks + */ + 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 + psDeviceNode->pfnMMUMapPagesSparse = &MMU_MapPagesSparse; + psDeviceNode->pfnMMUMapShadowSparse = &MMU_MapShadowSparse; + +#if defined (SYS_USING_INTERRUPTS) + /* + SGX ISR handler + */ + psDeviceNode->pfnDeviceISR = SGX_ISRHandler; + psDeviceNode->pfnDeviceMISR = SGX_MISRHandler; +#endif + +#if defined(SUPPORT_MEMORY_TILING) + psDeviceNode->pfnAllocMemTilingRange = SGX_AllocMemTilingRange; + psDeviceNode->pfnFreeMemTilingRange = SGX_FreeMemTilingRange; +#endif + + /* + SGX command complete handler + */ + psDeviceNode->pfnDeviceCommandComplete = &SGXCommandComplete; + + psDeviceNode->pfnCacheInvalidate = SGXCacheInvalidate; + + /* + and setup the device's memory map: + */ + psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo; + /* size of address space */ + psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_FEATURE_ADDRESS_SPACE_SIZE; + + /* flags, backing store details to be specified by system */ + psDevMemoryInfo->ui32Flags = 0; + + /* device memory heap info about each heap in a device address space */ + 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; + + /* + setup heaps + Note: backing store to be setup by system (defaults to UMA) + */ + + /************* general ***************/ + 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; + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; +#if !defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) + /* specify the mapping heap ID for this device */ + psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap); +#endif + psDeviceMemoryHeap++;/* advance to the next heap */ + +#if defined(SUPPORT_MEMORY_TILING) + /************* VPB 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; + /* set the default (4k). System can override these as required */ + 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++;/* advance to the next heap */ +#endif + +#if defined(SUPPORT_ION) + /************* Ion Heap ***************/ + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_ION_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_ION_HEAP_BASE; + psDeviceMemoryHeap->ui32HeapSize = SGX_ION_HEAP_SIZE; + psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE + | PVRSRV_HAP_SINGLE_PROCESS; + psDeviceMemoryHeap->pszName = "Ion"; + psDeviceMemoryHeap->pszBSName = "Ion BS"; + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; + /* specify the ion heap ID for this device */ + psDevMemoryInfo->ui32IonHeapID = SGX_ION_HEAP_ID; + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++;/* advance to the next heap */ +#endif + + /************* TA data ***************/ + 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; + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++;/* advance to the next heap */ + + + /************* kernel code ***************/ + 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; + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++;/* advance to the next heap */ + + + /************* Kernel Video Data ***************/ + 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; + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++;/* advance to the next heap */ + + + /************* PixelShaderUSSE ***************/ + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PIXELSHADER_HEAP_BASE; + /* + The actual size of the pixel and vertex shader heap must be such that all + addresses are within range of the one of the USSE code base registers, but + the addressable range is hardware-dependent. + SGX_PIXELSHADER_HEAP_SIZE is defined to be the maximum possible size + to ensure that the heap layout is consistent across all SGXs. + */ + 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; + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++;/* advance to the next heap */ + + + /************* VertexShaderUSSE ***************/ + psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID); + psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VERTEXSHADER_HEAP_BASE; + /* See comment above with PixelShaderUSSE ui32HeapSize */ + 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; + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++;/* advance to the next heap */ + + + /************* PDS Pixel Code/Data ***************/ + 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; + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++;/* advance to the next heap */ + + + /************* PDS Vertex Code/Data ***************/ + 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; + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++;/* advance to the next heap */ + + + /************* CacheCoherent ***************/ + 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; + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + /* set the sync heap id */ + psDevMemoryInfo->ui32SyncHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap); + psDeviceMemoryHeap++;/* advance to the next heap */ + + + /************* Shared 3D Parameters ***************/ + 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; + + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++;/* advance to the next heap */ + + /************* Percontext 3D Parameters ***************/ + 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; + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++;/* advance to the next heap */ + + +#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) + /************* General Mapping ***************/ + 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) + /* + if((2D hardware is enabled) + && (multi-mem contexts enabled) + && (BRN23410 is present)) + - then don't make the heap per-context otherwise + the TA and 2D requestors must always be aligned to + the same address space which could affect performance + */ + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED; + #else /* defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410) */ + psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT; + #endif /* defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410) */ + + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + /* specify the mapping heap ID for this device */ + psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap); + psDeviceMemoryHeap++;/* advance to the next heap */ +#endif /* #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) */ + + +#if defined(SGX_FEATURE_2D_HARDWARE) + /************* 2D HW Heap ***************/ + 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; + /* set the default (4k). System can override these as required */ + psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE; + psDeviceMemoryHeap++;/* advance to the next heap */ +#endif /* #if defined(SGX_FEATURE_2D_HARDWARE) */ + + + /* set the heap count */ + 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 /* PDUMP */ + + +/*! +******************************************************************************* + + @Function SGXGetClientInfoKM + + @Description Gets the client information + + @Input hDevCookie + + @Output psClientInfo + + @Return PVRSRV_ERROR : + +******************************************************************************/ +IMG_EXPORT +PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie, + SGX_CLIENT_INFO* psClientInfo) +{ + PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice; + + /* + If this is the first client to connect to SGX perform initialisation + */ + psDevInfo->ui32ClientRefCount++; + + /* + Copy information to the client info. + */ + psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM(); + + /* + Copy requested information. + */ + OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData, sizeof(psClientInfo->asDevData)); + + /* just return OK */ + return PVRSRV_OK; +} + + +/*! +******************************************************************************* + + @Function SGXPanic + + @Description + + Called when an unrecoverable situation is detected. Dumps SGX debug + information and tells the OS to panic. + + @Input psDevInfo - SGX device info + + @Return IMG_VOID + +******************************************************************************/ +IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo) +{ + PVR_LOG(("SGX panic")); + SGXDumpDebugInfo(psDevInfo, IMG_FALSE); + OSPanic(); +} + + +/*! +******************************************************************************* + + @Function SGXDevInitCompatCheck + + @Description + + Check compatibility of host driver and microkernel (DDK and build options) + for SGX devices at services/device initialisation + + @Input psDeviceNode - device node + + @Return PVRSRV_ERROR - depending on mismatch found + +******************************************************************************/ +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; /*!< internal misc info for ukernel */ + PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures; + SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes; /*!< microkernel structure sizes */ + IMG_BOOL bStructSizesFailed; + + /* Exceptions list for core rev check, format is pairs of (hw rev, sw rev) */ + IMG_BOOL bCheckCoreRev; + const IMG_UINT32 aui32CoreRevExceptions[] = + { + 0x10100, 0x10101 + }; + const IMG_UINT32 ui32NumCoreExceptions = sizeof(aui32CoreRevExceptions) / (2*sizeof(IMG_UINT32)); + IMG_UINT i; +#endif + + /* Ensure it's a SGX device */ + 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; + + /* + * 1. Check kernel-side and client-side build options + * 2. Ensure ukernel DDK version and driver DDK version are compatible + * 3. Check ukernel build options against kernel-side build options + */ + + /* + * Check KM build options against client-side host driver + */ + + 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; + + /* Clear state (not strictly necessary since this is the first call) */ + psSGXMiscInfoInt = psMemInfo->pvLinAddrKM; + psSGXMiscInfoInt->ui32MiscInfoFlags = 0; + psSGXMiscInfoInt->ui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES; + eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode, IMG_NULL); + + /* + * Validate DDK version + */ + 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)); + } + + /* + * Check hardware core revision is compatible with the one in software + */ + if (psSGXFeatures->ui32CoreRevSW == 0) + { + /* + Head core revision cannot be checked. + */ + PVR_LOG(("SGXInit: HW core rev (%x) check skipped.", + psSGXFeatures->ui32CoreRev)); + } + else + { + /* For some cores the hw/sw core revisions are expected not to match. For these + * exceptional cases the core rev compatibility check should be skipped. + */ + 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)); + } + } + } + + /* + * Check ukernel structure sizes are the same as those in the driver + */ + 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 ]")); + } + + /* + * Check ukernel build options against KM host driver + */ + + 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 // NO_HARDWARE + + eError = PVRSRV_OK; +chk_exit: +#if defined(IGNORE_SGX_INIT_COMPATIBILITY_CHECK) + return PVRSRV_OK; +#else + return eError; +#endif +} + +/* + * @Function SGXGetMiscInfoUkernel + * + * @Description Returns misc info (e.g. SGX build info/flags) from microkernel + * + * @Input psDevInfo : device info from init phase + * @Input psDeviceNode : device node, used for scheduling ukernel to query SGX features + * + * @Return PVRSRV_ERROR : + * + */ +static +PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo, + PVRSRV_DEVICE_NODE *psDeviceNode, + IMG_HANDLE hDevMemContext) +{ + PVRSRV_ERROR eError; + SGXMKIF_COMMAND sCommandData; /* CCB command data */ + PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt; /*!< internal misc info for ukernel */ + PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures; /*!< sgx features for client */ + SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes; /*!< internal info: microkernel structure sizes */ + + 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; + + /* Reset SGX features */ + OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures)); + OSMemSet(psSGXStructSizes, 0, sizeof(*psSGXStructSizes)); + + /* set up buffer address for SGX features in CCB */ + sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr; /* device V addr of output buffer */ + + 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; + } + + /* FIXME: DWORD value to determine code path in ukernel? + * E.g. could use getMiscInfo to obtain register values for diagnostics? */ + +#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 the loop exited because a timeout*/ + if (!bExit) + { + PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Timeout occurred waiting for misc info.")); + return PVRSRV_ERROR_TIMEOUT; + } + } +#endif /* NO_HARDWARE */ + + return PVRSRV_OK; +} + + + +/* + * @Function SGXGetMiscInfoKM + * + * @Description Returns miscellaneous SGX info + * + * @Input psDevInfo : device info from init phase + * @Input psDeviceNode : device node, used for scheduling ukernel to query SGX features + * + * @Output psMiscInfo : query request plus user-mode mem for holding returned data + * + * @Return PVRSRV_ERROR : + * + */ +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; + + /* Reset the misc info state flags */ + *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; + + /* Set or Clear BP? */ + if(psMiscInfo->uData.sSGXBreakpointInfo.bBPEnable) + { + /* set the break point */ + IMG_DEV_VIRTADDR sBPDevVAddr = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddr; + IMG_DEV_VIRTADDR sBPDevVAddrEnd = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddrEnd; + + /* BP address */ + 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; + + /* normal data BP */ + 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 + { + /* clear the break point */ + ui32RegVal = ui32StartRegVal = ui32EndRegVal = 0; + } + + /* setup the command */ + sCommandData.ui32Data[0] = psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex; + sCommandData.ui32Data[1] = ui32StartRegVal; + sCommandData.ui32Data[2] = ui32EndRegVal; + sCommandData.ui32Data[3] = ui32RegVal; + + /* clear signal flags */ + 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) + /* clear signal flags */ + 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; + /* clear signal flags */ + psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0; + break; + } + } END_LOOP_UNTIL_TIMEOUT(); + + /*if the loop exited because a timeout*/ + if (!bExit) + { + PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: Timeout occurred waiting BP set/clear")); + return PVRSRV_ERROR_TIMEOUT; + } + } +#endif /* NO_HARDWARE */ + + return PVRSRV_OK; + } + + case SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT: + { + /* This request checks to see whether a breakpoint has + been trapped. If so, it returns the number of the + breakpoint number that was trapped in ui32BPIndex, + sTrappedBPDevVAddr to the address which was trapped, + and sets bTrappedBP. Otherwise, bTrappedBP will be + false, and other fields should be ignored. */ + /* The uKernel is not used, since if we are stopped on a + breakpoint, it is not possible to guarantee that the + uKernel would be able to run */ +#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; +/* ui32PipeNum is the pipe number plus 1, or 0 to represent "partition" */ +#define NUM_PIPES_PLUS_ONE (SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES+1) +#endif + IMG_BOOL bTrappedBPAny; +#endif /* defined(SGX_FEATURE_MP) */ + 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; /* just to keep the (incorrect) compiler happy */ +#endif + for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT_3D; ui32CoreNum++) + { +#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) + /* FIXME: this macro makes the assumption that the PARTITION regs are the same + distance before the PIPE0 regs as the PIPE1 regs are after it, _and_ + assumes that the fields in the partition regs are in the same place + in the pipe regs. Need to validate these assumptions, or assert them */ +#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 /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ + 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 /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ + } + + psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = bTrappedBPAny; +#else /* defined(SGX_FEATURE_MP) */ +#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 /* defined(SGX_FEATURE_MP) */ + + 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 /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ + 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 /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ +#else /* defined(SGX_FEATURE_MP) */ + ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT_TRAP_INFO0); + ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT_TRAP_INFO1); +#endif /* defined(SGX_FEATURE_MP) */ + +#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 /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ + 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 /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ +#if defined(SGX_FEATURE_MP) +#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) + /* mp, per-pipe regbanks */ + psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:(ui32TrappedBPCoreNum + (ui32TrappedBPPipeNum<<10)); +#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ + /* mp, regbanks unsplit */ + psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:ui32TrappedBPCoreNum; +#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ +#else /* defined(SGX_FEATURE_MP) */ +#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS) + /* non-mp, per-pipe regbanks */ +#error non-mp perpipe regs not yet supported +#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ + /* non-mp */ + psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = 65534; +#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ +#endif /* defined(SGX_FEATURE_MP) */ + } +#endif /* !defined(NO_HARDWARE) */ + return PVRSRV_OK; + } + + case SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT: + { + /* This request resumes from the currently trapped breakpoint. */ + /* Core number must be supplied */ + /* Polls for notify to be acknowledged by h/w */ +#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 /* defined(SGX_FEATURE_MP) */ + 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 /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ + ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum; + bMaster = ui32CoreNum > SGX_FEATURE_MP_CORE_COUNT_3D; +#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ + if (bMaster) + { + /* master */ + /* EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK | EUR_CR_MASTER_BREAKPOINT_SEQNUM_MASK */ + 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 /* defined(SGX_FEATURE_MP) */ + { + /* core */ +#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 /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ + 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 /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */ + } +#endif /* !defined(NO_HARDWARE) */ + return PVRSRV_OK; + } +#endif /* SGX_FEATURE_DATA_BREAKPOINTS) */ + + 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: + { + /* this is dealt with in UM */ + return PVRSRV_OK; + } + + case SGX_MISC_INFO_REQUEST_SGXREV: + { + PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures; +// PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo; + + 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; + + /* Copy SGX features into misc info struct, to return to client */ + psMiscInfo->uData.sSGXFeatures = *psSGXFeatures; + + /* Debug output */ + 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)); + + /* done! */ + return PVRSRV_OK; + } + + case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV: + { + PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures; + + psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures; + + /* Reset the misc information to prevent + * confusion with values returned from the ukernel + */ + OSMemSet(psMemInfo->pvLinAddrKM, 0, + sizeof(PVRSRV_SGX_MISCINFO_INFO)); + + psSGXFeatures->ui32DDKVersion = + (PVRVERSION_MAJ << 16) | + (PVRVERSION_MIN << 8) | + PVRVERSION_BRANCH; + psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD; + + /* Also report the kernel module build options -- used in SGXConnectionCheck() */ + psSGXFeatures->ui32BuildOptions = (SGX_BUILD_OPTIONS); + +#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) + /* Report the EDM status buffer location in memory */ + psSGXFeatures->sDevVAEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->sDevVAddr; + psSGXFeatures->pvEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM; +#endif + + /* Copy SGX features into misc info struct, to return to client */ + 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; /* user-defined mem read */ + PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemDest; /* user-defined mem write */ + + { + /* Set the mem read flag; src is user-defined */ + *pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMREAD; + psSGXMemSrc = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessSrc; + + if(psMiscInfo->sDevVAddrSrc.uiAddr != 0) + { + psSGXMemSrc->sDevVAddr = psMiscInfo->sDevVAddrSrc; /* src address */ + } + else + { + return PVRSRV_ERROR_INVALID_PARAMS; + } + } + + if( psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMCOPY) + { + /* Set the mem write flag; dest is user-defined */ + *pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMWRITE; + psSGXMemDest = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessDest; + + if(psMiscInfo->sDevVAddrDest.uiAddr != 0) + { + psSGXMemDest->sDevVAddr = psMiscInfo->sDevVAddrDest; /* dest address */ + } + else + { + return PVRSRV_ERROR_INVALID_PARAMS; + } + } + + /* Get physical address of PD for memory read (may need to switch context in microkernel) */ + if(psMiscInfo->hDevMemContext != IMG_NULL) + { + SGXGetMMUPDAddrKM( (IMG_HANDLE)psDeviceNode, hDevMemContext, &psSGXMemSrc->sPDDevPAddr); + + /* Single app will always use the same src and dest mem context */ + psSGXMemDest->sPDDevPAddr = psSGXMemSrc->sPDDevPAddr; + } + else + { + return PVRSRV_ERROR_INVALID_PARAMS; + } + + /* Submit the task to the ukernel */ + 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 + /* Copy SGX features into misc info struct, to return to client */ + psMiscInfo->uData.sSGXFeatures = *psSGXFeatures; + return PVRSRV_OK; + } +#endif /* SUPPORT_SGX_EDM_MEMORY_DEBUG */ + +#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}; + + /* Check for valid flags */ + 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 /* PDUMP */ + + /* Copy the new group selector(s) to the host ctl for the ukernel */ + #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)); + psDevInfo->psSGXHostCtl->ui32PerfCounterBitSelect = psSetHWPerfStatus->ui32PerfCounterBitSelect; + psDevInfo->psSGXHostCtl->ui32PerfSumMux = psSetHWPerfStatus->ui32PerfSumMux; + #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)); + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32PerfCounterBitSelect), + sizeof(psDevInfo->psSGXHostCtl->ui32PerfCounterBitSelect), + PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32PerfSumMux), + sizeof(psDevInfo->psSGXHostCtl->ui32PerfSumMux), + PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); + #endif /* PDUMP */ + #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 /* PDUMP */ + #endif /* SGX_FEATURE_EXTENDED_PERF_COUNTERS */ + + /* Kick the ukernel to update the hardware state */ + sCommandData.ui32Data[0] = psSetHWPerfStatus->ui32NewHWPerfStatus; + eError = SGXScheduleCCBCommandKM(psDeviceNode, + SGXMKIF_CMD_SETHWPERFSTATUS, + &sCommandData, + KERNEL_ID, + 0, + hDevMemContext, + IMG_FALSE); + return eError; + } +#endif /* SUPPORT_SGX_HWPERF */ + + case SGX_MISC_INFO_DUMP_DEBUG_INFO: + { + PVR_LOG(("User requested SGX debug info")); + + /* Dump SGX debug data to the kernel log. */ + SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_FALSE); + + return PVRSRV_OK; + } + + case SGX_MISC_INFO_DUMP_DEBUG_INFO_FORCE_REGS: + { + PVR_LOG(("User requested SGX debug info")); + + /* Dump SGX debug data to the kernel log. */ + SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE); + + return PVRSRV_OK; + } + +#if defined(DEBUG) + /* Don't allow user-mode to reboot the device in production drivers */ + case SGX_MISC_INFO_PANIC: + { + PVR_LOG(("User requested SGX panic")); + + SGXPanic(psDeviceNode->pvDevice); + + return PVRSRV_OK; + } +#endif + + default: + { + /* switch statement fell though, so: */ + 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; +} + + +/****************************************************************************** + End of file (sgxinit.c) +******************************************************************************/ |