1 /*************************************************************************/ /*!
3 @Title Device specific initialisation routines
4 @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description Device specific functions
6 @License Dual MIT/GPLv2
8 The contents of this file are subject to the MIT license as set out below.
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
20 Alternatively, the contents of this file may be used under the terms of
21 the GNU General Public License Version 2 ("GPL") in which case the provisions
22 of GPL are applicable instead of those above.
24 If you wish to allow use of your version of this file only under the terms of
25 GPL, and not to allow others to use your version of this file under the terms
26 of the MIT license, indicate your decision by deleting the provisions above
27 and replace them with the notice and other provisions required by GPL as set
28 out in the file called "GPL-COPYING" included in this distribution. If you do
29 not delete the provisions above, a recipient may use your version of this file
30 under the terms of either the MIT license or GPL.
32 This License is also included in this distribution in the file called
35 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
36 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
37 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
39 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
40 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
41 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 */ /**************************************************************************/
47 #include "rgxheapconfig.h"
55 #include "devicemem_pdump.h"
57 #include "sync_internal.h"
60 #include "rgxfwutils.h"
61 #include "rgx_fwif_km.h"
63 #include "rgxmmuinit.h"
64 #include "devicemem_utils.h"
65 #include "devicemem_server.h"
66 #include "physmem_osmem.h"
69 #include "rgxhwperf.h"
71 #include "rgx_options_km.h"
72 #include "pvrversion.h"
74 #include "rgx_compat_bvnc.h"
76 #include "rgx_heaps.h"
79 #include "debug_request_ids.h"
81 static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32ClientBuildOptions);
82 static PVRSRV_ERROR RGXDevVersionString(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_CHAR **ppszVersionString);
83 static PVRSRV_ERROR RGXDevClockSpeed(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_PUINT32 pui32RGXClockSpeed);
84 static PVRSRV_ERROR RGXSoftReset(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT64 ui64ResetValue);
86 #define RGX_MMU_LOG2_PAGE_SIZE_4KB (12)
87 #define RGX_MMU_LOG2_PAGE_SIZE_16KB (14)
88 #define RGX_MMU_LOG2_PAGE_SIZE_64KB (16)
89 #define RGX_MMU_LOG2_PAGE_SIZE_256KB (18)
90 #define RGX_MMU_LOG2_PAGE_SIZE_1MB (20)
91 #define RGX_MMU_LOG2_PAGE_SIZE_2MB (21)
93 #define RGX_MMU_PAGE_SIZE_4KB ( 4 * 1024)
94 #define RGX_MMU_PAGE_SIZE_16KB ( 16 * 1024)
95 #define RGX_MMU_PAGE_SIZE_64KB ( 64 * 1024)
96 #define RGX_MMU_PAGE_SIZE_256KB ( 256 * 1024)
97 #define RGX_MMU_PAGE_SIZE_1MB (1024 * 1024)
98 #define RGX_MMU_PAGE_SIZE_2MB (2048 * 1024)
99 #define RGX_MMU_PAGE_SIZE_MIN RGX_MMU_PAGE_SIZE_4KB
100 #define RGX_MMU_PAGE_SIZE_MAX RGX_MMU_PAGE_SIZE_2MB
105 static IMG_BOOL g_bDevInit2Done = IMG_FALSE;
108 static IMG_VOID RGX_DeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo);
110 IMG_UINT32 g_ui32HostSampleIRQCount = 0;
112 #if !defined(NO_HARDWARE)
117 static IMG_BOOL RGX_LISRHandler (IMG_VOID *pvData)
119 PVRSRV_DEVICE_NODE *psDeviceNode;
120 PVRSRV_DEVICE_CONFIG *psDevConfig;
121 PVRSRV_RGXDEV_INFO *psDevInfo;
122 IMG_UINT32 ui32IRQStatus;
123 IMG_BOOL bInterruptProcessed = IMG_FALSE;
125 psDeviceNode = pvData;
126 psDevConfig = psDeviceNode->psDevConfig;
127 psDevInfo = psDeviceNode->pvDevice;
129 if (psDevInfo->bIgnoreFurtherIRQs)
134 ui32IRQStatus = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVIRQSTATUS);
136 if (ui32IRQStatus & RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN)
138 OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVIRQSTATUS, RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK);
140 #if defined(RGX_FEATURE_OCPBUS)
141 OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_OCP_IRQSTATUS_2, RGX_CR_OCP_IRQSTATUS_2_RGX_IRQ_STATUS_EN);
144 if (psDevConfig->pfnInterruptHandled)
146 psDevConfig->pfnInterruptHandled(psDevConfig);
149 bInterruptProcessed = IMG_TRUE;
151 /* Sample the current count from the FW _after_ we've cleared the interrupt. */
152 g_ui32HostSampleIRQCount = psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount;
154 OSScheduleMISR(psDevInfo->pvMISRData);
156 if (psDevInfo->pvAPMISRData != IMG_NULL)
158 OSScheduleMISR(psDevInfo->pvAPMISRData);
161 return bInterruptProcessed;
164 static IMG_VOID RGXCheckFWActivePowerState(IMG_VOID *psDevice)
166 PVRSRV_DEVICE_NODE *psDeviceNode = psDevice;
167 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
168 RGXFWIF_TRACEBUF *psFWTraceBuf = psDevInfo->psRGXFWIfTraceBuf;
169 PVRSRV_ERROR eError = PVRSRV_OK;
171 if (psFWTraceBuf->ePowState == RGXFWIF_POW_IDLE)
173 /* The FW is IDLE and therefore could be shut down */
174 eError = RGXActivePowerRequest(psDeviceNode);
176 if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED))
178 PVR_DPF((PVR_DBG_WARNING,"RGXCheckFWActivePowerState: Failed RGXActivePowerRequest call (device index: %d) with %s",
179 psDeviceNode->sDevId.ui32DeviceIndex,
180 PVRSRVGetErrorStringKM(eError)));
182 PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, IMG_NULL);
188 static RGXFWIF_GPU_UTIL_STATS RGXGetGpuUtilStats(PVRSRV_DEVICE_NODE *psDeviceNode)
190 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
191 RGXFWIF_GPU_UTIL_FWCB *psUtilFWCb = psDevInfo->psRGXFWIfGpuUtilFWCb;
192 IMG_UINT32 ui32StatActiveLow = 0, ui32StatActiveHigh = 0, ui32StatBlocked = 0, ui32StatIdle = 0;
193 IMG_UINT32 ui32StatCumulative = 0;
194 IMG_UINT32 ui32WOffSample, ui32PrevWOffSample, ui32PriorWOffSample;
195 IMG_UINT32 ui32WOffSampleSaved;
196 IMG_UINT64 ui64CurrentTimer;
197 IMG_UINT32 ui32Remainder;
198 RGXFWIF_GPU_UTIL_STATS sRet;
199 PVRSRV_DEV_POWER_STATE ePowerState;
200 // PVRSRV_ERROR eError;
202 IMG_UINT32 ui32NextType;
204 static RGXFWIF_GPU_UTIL_STATS sPreviousStats;
205 static IMG_UINT32 ui32WarningTicks = 0;
208 sRet.ui32GpuStatActiveHigh = 0;
209 sRet.ui32GpuStatActiveLow = 0;
210 sRet.ui32GpuStatBlocked = 0;
211 sRet.ui32GpuStatIdle = 0;
212 sRet.bValid = IMG_FALSE;
213 sRet.bIncompleteData = IMG_FALSE;
215 /* take the power lock as we might issue an OSReadHWReg64 below */
216 /* eError = PVRSRVPowerLock();
217 if (eError != PVRSRV_OK)
222 /* write offset is incremented after writing to FWCB, so subtract 1 */
223 ui32WOffSample = psUtilFWCb->ui32WriteOffset;
224 if(ui32WOffSample == 0)
226 ui32WOffSample = RGXFWIF_GPU_UTIL_FWCB_SIZE;
229 ui32WOffSampleSaved = ui32PrevWOffSample = ui32PriorWOffSample = ui32WOffSample;
231 PVRSRVGetDevicePowerState(psDeviceNode->sDevId.ui32DeviceIndex, &ePowerState);
232 if (ePowerState != PVRSRV_DEV_POWER_STATE_ON) /* GPU powered off */
234 ui64CurrentTimer = OSClockus64() & RGXFWIF_GPU_UTIL_FWCB_OS_TIMER_MASK;
235 ui32NextType = RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_ON;
237 else /* GPU powered on */
239 ui64CurrentTimer = RGXReadHWTimerReg(psDevInfo);
240 ui32NextType = RGXFWIF_GPU_UTIL_FWCB_TYPE_CRTIME;
242 //PVRSRVPowerUnlock();
246 IMG_UINT64 ui64FWCbEntryCurrent = psUtilFWCb->aui64CB[ui32WOffSample];
248 if (ui64FWCbEntryCurrent != RGXFWIF_GPU_UTIL_FWCB_RESERVED)
250 IMG_UINT64 ui64Period = 0;
252 ui32Type = RGXFWIF_GPU_UTIL_FWCB_ENTRY_TYPE(ui64FWCbEntryCurrent);
256 case RGXFWIF_GPU_UTIL_FWCB_TYPE_CRTIME:
258 IMG_UINT32 ui32DVFSHistClock =
259 psDevInfo->psGpuDVFSHistory->aui32DVFSClockCB[RGXFWIF_GPU_UTIL_FWCB_ENTRY_ID(ui64FWCbEntryCurrent)];
261 if (ui32DVFSHistClock < 256)
263 /* DVFS frequency is 0 in DVFS history entry, which means that
264 system layer doesn't define core clock frequency */
265 ui32StatCumulative = 0;
267 goto gpuutilstats_endloop;
270 /* Calculate the difference between current CR timer and CR timer at DVFS transition */
271 ui64Period = ui64CurrentTimer - RGXFWIF_GPU_UTIL_FWCB_ENTRY_CR_TIMER(ui64FWCbEntryCurrent);
273 /* Scale the difference to microseconds */
274 ui64Period = OSDivide64((ui64Period * 1000000), (ui32DVFSHistClock / 256), &ui32Remainder);
276 /* Update "now" to CR Timer of current entry */
277 ui64CurrentTimer = RGXFWIF_GPU_UTIL_FWCB_ENTRY_CR_TIMER(ui64FWCbEntryCurrent);
282 case RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_OFF:
284 /* Calculate the difference between OS timers at power-on/power-off transitions */
285 ui64Period = ui64CurrentTimer - RGXFWIF_GPU_UTIL_FWCB_ENTRY_OS_TIMER(ui64FWCbEntryCurrent);
289 case RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_ON:
290 case RGXFWIF_GPU_UTIL_FWCB_TYPE_END_CRTIME:
292 /* Update "now" to the Timer of current entry */
293 if(ui32Type == RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_ON)
295 ui64CurrentTimer = RGXFWIF_GPU_UTIL_FWCB_ENTRY_OS_TIMER(ui64FWCbEntryCurrent);
299 ui64CurrentTimer = RGXFWIF_GPU_UTIL_FWCB_ENTRY_CR_TIMER(ui64FWCbEntryCurrent);
302 /* Move to next-previous state transition */
303 if(ui32WOffSample == 0)
305 ui32WOffSample = RGXFWIF_GPU_UTIL_FWCB_SIZE;
309 /* Remember the next-previous entry type */
310 ui32NextType = ui32Type;
315 PVR_DPF((PVR_DBG_WARNING,"RGXGetGpuUtilStats: Wrong type: %8.8X\n", ui32Type));
319 /* If calculated period goes beyond the time window that we want to look at to calculate stats,
320 cut it down to this window */
321 if (((IMG_UINT64)ui32StatCumulative + ui64Period) > (IMG_UINT64)RGXFWIF_GPU_STATS_WINDOW_SIZE_US)
323 ui64Period = RGXFWIF_GPU_STATS_WINDOW_SIZE_US - ui32StatCumulative;
326 /* Update cumulative time of state transition */
327 ui32StatCumulative += (IMG_UINT32)ui64Period;
329 /* Update per-state cumulative times */
330 switch (RGXFWIF_GPU_UTIL_FWCB_ENTRY_STATE(ui64FWCbEntryCurrent))
332 case RGXFWIF_GPU_UTIL_FWCB_STATE_ACTIVE_LOW:
333 ui32StatActiveLow += (IMG_UINT32)ui64Period;
335 case RGXFWIF_GPU_UTIL_FWCB_STATE_IDLE:
336 ui32StatIdle += (IMG_UINT32)ui64Period;
338 case RGXFWIF_GPU_UTIL_FWCB_STATE_ACTIVE_HIGH:
339 ui32StatActiveHigh += (IMG_UINT32)ui64Period;
341 case RGXFWIF_GPU_UTIL_FWCB_STATE_BLOCKED:
342 ui32StatBlocked += (IMG_UINT32)ui64Period;
348 /* current sample is reserved */
352 /* Move to next-previous state transition */
353 ui32PriorWOffSample = ui32PrevWOffSample;
354 ui32PrevWOffSample = ui32WOffSample;
355 if(ui32WOffSample == 0)
357 ui32WOffSample = RGXFWIF_GPU_UTIL_FWCB_SIZE;
361 /* Remember the next-previous entry type */
362 ui32NextType = ui32Type;
364 ui32WOffSampleSaved = psUtilFWCb->ui32WriteOffset;
366 /* break if the FW or the Host wrote something to the CB while we were reading it
367 * or if we have already calculated the whole window */
368 while ((ui32WOffSample != ui32WOffSampleSaved) &&
369 (ui32PrevWOffSample != ui32WOffSampleSaved) &&
370 (ui32PriorWOffSample != ui32WOffSampleSaved) &&
371 (ui32StatCumulative < RGXFWIF_GPU_STATS_WINDOW_SIZE_US));
373 gpuutilstats_endloop:
375 if (ui32StatCumulative)
378 sRet.ui32GpuStatActiveLow = OSDivide64(((IMG_UINT64)ui32StatActiveLow * RGXFWIF_GPU_STATS_MAX_VALUE_OF_STATE), ui32StatCumulative, &ui32Remainder);
379 sRet.ui32GpuStatActiveHigh = OSDivide64(((IMG_UINT64)ui32StatActiveHigh * RGXFWIF_GPU_STATS_MAX_VALUE_OF_STATE), ui32StatCumulative, &ui32Remainder);
380 sRet.ui32GpuStatBlocked = OSDivide64(((IMG_UINT64)ui32StatBlocked * RGXFWIF_GPU_STATS_MAX_VALUE_OF_STATE), ui32StatCumulative, &ui32Remainder);
381 sRet.ui32GpuStatIdle = OSDivide64(((IMG_UINT64)ui32StatIdle * RGXFWIF_GPU_STATS_MAX_VALUE_OF_STATE), ui32StatCumulative, &ui32Remainder);
382 sRet.bValid = IMG_TRUE;
384 if(ui32StatCumulative < RGXFWIF_GPU_STATS_WINDOW_SIZE_US)
386 #define RGX_GPU_UTIL_STAT_MULTIPLIER 1000 /* Multiply everything to get some better accuracy when weighting last and previous values */
387 #define RGX_GPU_UTIL_STAT_SCALE 4 /* Give less importance to the values just computed */
388 #define RGX_GPU_UTIL_STAT_WARNING_PERIOD 8
389 IMG_UINT32 ui32LastStatWeight = (RGX_GPU_UTIL_STAT_MULTIPLIER * ui32StatCumulative)/(RGX_GPU_UTIL_STAT_SCALE * RGXFWIF_GPU_STATS_WINDOW_SIZE_US);
390 IMG_UINT32 ui32PrevStatWeight = (RGX_GPU_UTIL_STAT_MULTIPLIER - ui32LastStatWeight);
392 sRet.ui32GpuStatActiveHigh = ( (sRet.ui32GpuStatActiveHigh * ui32LastStatWeight) + (sPreviousStats.ui32GpuStatActiveHigh * ui32PrevStatWeight) ) / RGX_GPU_UTIL_STAT_MULTIPLIER;
393 sRet.ui32GpuStatActiveLow = ( (sRet.ui32GpuStatActiveLow * ui32LastStatWeight) + (sPreviousStats.ui32GpuStatActiveLow * ui32PrevStatWeight) ) / RGX_GPU_UTIL_STAT_MULTIPLIER;
394 sRet.ui32GpuStatBlocked = ( (sRet.ui32GpuStatBlocked * ui32LastStatWeight) + (sPreviousStats.ui32GpuStatBlocked * ui32PrevStatWeight) ) / RGX_GPU_UTIL_STAT_MULTIPLIER;
395 sRet.ui32GpuStatIdle = ( (sRet.ui32GpuStatIdle * ui32LastStatWeight) + (sPreviousStats.ui32GpuStatIdle * ui32PrevStatWeight) ) / RGX_GPU_UTIL_STAT_MULTIPLIER;
396 sRet.bIncompleteData = IMG_TRUE;
398 if((ui32WarningTicks % RGX_GPU_UTIL_STAT_WARNING_PERIOD) == 0)
400 PVR_DPF((PVR_DBG_WARNING,"RGXGetGpuUtilStats: Time window shorter than expected, returned data may be inaccurate\n"));
405 sPreviousStats.ui32GpuStatActiveLow = sRet.ui32GpuStatActiveLow;
406 sPreviousStats.ui32GpuStatActiveHigh = sRet.ui32GpuStatActiveHigh;
407 sPreviousStats.ui32GpuStatBlocked = sRet.ui32GpuStatBlocked;
408 sPreviousStats.ui32GpuStatIdle = sRet.ui32GpuStatIdle;
417 static IMG_VOID RGX_MISRHandler (IMG_VOID *pvData)
419 PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
421 /* Inform other services devices that we have finished an operation */
422 PVRSRVCheckStatus(psDeviceNode);
424 /* Give the HWPerf service a chance to transfer some data from the FW
425 * buffer to the host driver transport layer buffer.
427 RGXHWPerfDataStoreCB(psDeviceNode);
429 /* Process all firmware CCBs for pending commands */
430 RGXCheckFirmwareCCBs(psDeviceNode->pvDevice);
436 * PVRSRVRGXInitDevPart2KM
439 PVRSRV_ERROR PVRSRVRGXInitDevPart2KM (PVRSRV_DEVICE_NODE *psDeviceNode,
440 RGX_INIT_COMMAND *psInitScript,
441 RGX_INIT_COMMAND *psDbgScript,
442 RGX_INIT_COMMAND *psDbgBusScript,
443 RGX_INIT_COMMAND *psDeinitScript,
444 IMG_UINT32 ui32KernelCatBaseIdReg,
445 IMG_UINT32 ui32KernelCatBaseId,
446 IMG_UINT32 ui32KernelCatBaseReg,
447 IMG_UINT32 ui32KernelCatBaseWordSize,
448 IMG_UINT32 ui32KernelCatBaseAlignShift,
449 IMG_UINT32 ui32KernelCatBaseShift,
450 IMG_UINT64 ui64KernelCatBaseMask,
451 IMG_UINT32 ui32DeviceFlags,
452 RGX_ACTIVEPM_CONF eActivePMConf,
453 DEVMEM_EXPORTCOOKIE *psFWCodeAllocServerExportCookie,
454 DEVMEM_EXPORTCOOKIE *psFWDataAllocServerExportCookie,
455 DEVMEM_EXPORTCOOKIE *psFWCorememAllocServerExportCookie)
458 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
459 PVRSRV_DEV_POWER_STATE eDefaultPowerState;
460 PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
462 PDUMPCOMMENT("RGX Initialisation Part 2");
464 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
465 psDevInfo->bEnableProcessStats=IMG_TRUE;
467 psDevInfo->bEnableProcessStats=IMG_FALSE;
470 psDevInfo->ui32KernelCatBaseIdReg = ui32KernelCatBaseIdReg;
471 psDevInfo->ui32KernelCatBaseId = ui32KernelCatBaseId;
472 psDevInfo->ui32KernelCatBaseReg = ui32KernelCatBaseReg;
473 psDevInfo->ui32KernelCatBaseAlignShift = ui32KernelCatBaseAlignShift;
474 psDevInfo->ui32KernelCatBaseShift = ui32KernelCatBaseShift;
475 psDevInfo->ui32KernelCatBaseWordSize = ui32KernelCatBaseWordSize;
476 psDevInfo->ui64KernelCatBaseMask = ui64KernelCatBaseMask;
481 #if !defined(NO_HARDWARE)
482 psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psDevConfig->sRegsCpuPBase,
483 psDevConfig->ui32RegsSize,
486 if (psDevInfo->pvRegsBaseKM == IMG_NULL)
488 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: Failed to create RGX register mapping\n"));
489 return PVRSRV_ERROR_BAD_MAPPING;
492 psDevInfo->pvRegsBaseKM = IMG_NULL;
493 #endif /* !NO_HARDWARE */
495 /* free the export cookies provided to srvinit */
496 DevmemUnexport(psDevInfo->psRGXFWCodeMemDesc, psFWCodeAllocServerExportCookie);
497 DevmemUnexport(psDevInfo->psRGXFWDataMemDesc, psFWDataAllocServerExportCookie);
498 if (DevmemIsValidExportCookie(psFWCorememAllocServerExportCookie))
500 DevmemUnexport(psDevInfo->psRGXFWCorememMemDesc, psFWCorememAllocServerExportCookie);
506 OSMemCopy(psDevInfo->psScripts->asInitCommands, psInitScript,
507 RGX_MAX_INIT_COMMANDS * sizeof(*psInitScript));
509 OSMemCopy(psDevInfo->psScripts->asDbgCommands, psDbgScript,
510 RGX_MAX_INIT_COMMANDS * sizeof(*psDbgScript));
512 OSMemCopy(psDevInfo->psScripts->asDbgBusCommands, psDbgBusScript,
513 RGX_MAX_DBGBUS_COMMANDS * sizeof(*psDbgBusScript));
515 OSMemCopy(psDevInfo->psScripts->asDeinitCommands, psDeinitScript,
516 RGX_MAX_DEINIT_COMMANDS * sizeof(*psDeinitScript));
519 /* Run the deinit script to feed the last-frame deinit buffer */
520 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_DEINIT, "RGX deinitialisation script");
521 RGXRunScript(psDevInfo, psDevInfo->psScripts->asDeinitCommands, RGX_MAX_DEINIT_COMMANDS, PDUMP_FLAGS_DEINIT | PDUMP_FLAGS_NOHW, IMG_NULL);
525 psDevInfo->ui32RegSize = psDevConfig->ui32RegsSize;
526 psDevInfo->sRegsPhysBase = psDevConfig->sRegsCpuPBase;
528 /* Initialise Device Flags */
529 psDevInfo->ui32DeviceFlags = 0;
530 if (ui32DeviceFlags & RGXKMIF_DEVICE_STATE_ZERO_FREELIST)
532 psDevInfo->ui32DeviceFlags |= RGXKM_DEVICE_STATE_ZERO_FREELIST;
535 if (ui32DeviceFlags & RGXKMIF_DEVICE_STATE_DISABLE_DW_LOGGING_EN)
537 psDevInfo->ui32DeviceFlags |= RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN;
540 #if defined(SUPPORT_GPUTRACE_EVENTS)
541 /* If built, always setup FTrace consumer thread. */
542 RGXHWPerfFTraceGPUInit(psDeviceNode->pvDevice);
544 RGXHWPerfFTraceGPUEventsEnabledSet((ui32DeviceFlags & RGXKMIF_DEVICE_STATE_FTRACE_EN) ? IMG_TRUE: IMG_FALSE);
547 /* Initialise lists of ZSBuffers */
548 eError = OSLockCreate(&psDevInfo->hLockZSBuffer,LOCK_TYPE_PASSIVE);
549 PVR_ASSERT(eError == PVRSRV_OK);
550 dllist_init(&psDevInfo->sZSBufferHead);
551 psDevInfo->ui32ZSBufferCurrID = 1;
553 /* Initialise lists of growable Freelists */
554 eError = OSLockCreate(&psDevInfo->hLockFreeList,LOCK_TYPE_PASSIVE);
555 PVR_ASSERT(eError == PVRSRV_OK);
556 dllist_init(&psDevInfo->sFreeListHead);
557 psDevInfo->ui32FreelistCurrID = 1;
559 /* Allocate DVFS History */
560 psDevInfo->psGpuDVFSHistory = OSAllocZMem(sizeof(*(psDevInfo->psGpuDVFSHistory)));
561 if (psDevInfo->psGpuDVFSHistory == IMG_NULL)
563 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: failed to allocate gpu dvfs history storage"));
564 return PVRSRV_ERROR_OUT_OF_MEMORY;
567 /* Reset DVFS history */
568 psDevInfo->psGpuDVFSHistory->ui32CurrentDVFSId = 0;
569 psDevInfo->psGpuDVFSHistory->aui32DVFSClockCB[0] = 0;
571 /* Setup GPU Utilization stat update callback */
572 #if !defined(NO_HARDWARE)
573 psDevInfo->pfnGetGpuUtilStats = RGXGetGpuUtilStats;
576 eDefaultPowerState = PVRSRV_DEV_POWER_STATE_ON;
578 /* set-up the Active Power Mgmt callback */
579 #if !defined(NO_HARDWARE)
581 RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
582 IMG_BOOL bSysEnableAPM = psRGXData->psRGXTimingInfo->bEnableActivePM;
583 IMG_BOOL bEnableAPM = ((eActivePMConf == RGX_ACTIVEPM_DEFAULT) && bSysEnableAPM) ||
584 (eActivePMConf == RGX_ACTIVEPM_FORCE_ON);
588 eError = OSInstallMISR(&psDevInfo->pvAPMISRData, RGXCheckFWActivePowerState, psDeviceNode);
589 if (eError != PVRSRV_OK)
594 /* Prevent the device being woken up before there is something to do. */
595 eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
600 /* Register the device with the power manager. */
601 eError = PVRSRVRegisterPowerDevice (psDeviceNode->sDevId.ui32DeviceIndex,
602 &RGXPrePowerState, &RGXPostPowerState,
603 psDevConfig->pfnPrePowerState, psDevConfig->pfnPostPowerState,
604 &RGXPreClockSpeedChange, &RGXPostClockSpeedChange,
605 (IMG_HANDLE)psDeviceNode,
606 PVRSRV_DEV_POWER_STATE_OFF,
608 if (eError != PVRSRV_OK)
610 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: failed to register device with power manager"));
614 #if !defined(NO_HARDWARE)
615 eError = RGXInstallProcessQueuesMISR(&psDevInfo->hProcessQueuesMISR, psDeviceNode);
616 if (eError != PVRSRV_OK)
618 if (psDevInfo->pvAPMISRData != IMG_NULL)
620 (IMG_VOID) OSUninstallMISR(psDevInfo->pvAPMISRData);
625 /* Register the interrupt handlers */
626 eError = OSInstallMISR(&psDevInfo->pvMISRData,
627 RGX_MISRHandler, psDeviceNode);
628 if (eError != PVRSRV_OK)
630 if (psDevInfo->pvAPMISRData != IMG_NULL)
632 (IMG_VOID) OSUninstallMISR(psDevInfo->pvAPMISRData);
634 (IMG_VOID) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
638 eError = OSInstallDeviceLISR(psDevConfig, &psDevInfo->pvLISRData,
639 RGX_LISRHandler, psDeviceNode);
640 if (eError != PVRSRV_OK)
642 if (psDevInfo->pvAPMISRData != IMG_NULL)
644 (IMG_VOID) OSUninstallMISR(psDevInfo->pvAPMISRData);
646 (IMG_VOID) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
647 (IMG_VOID) OSUninstallMISR(psDevInfo->pvMISRData);
652 g_bDevInit2Done = IMG_TRUE;
658 PVRSRV_ERROR RGXAllocateFWCodeRegion(PVRSRV_DEVICE_NODE *psDeviceNode,
659 IMG_DEVMEM_SIZE_T ui32FWCodeAllocSize,
660 IMG_UINT32 uiMemAllocFlags)
664 #if ! defined(TDMETACODE)
665 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
667 uiMemAllocFlags |= PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
668 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
670 PDUMPCOMMENT("Allocate and export code memory for fw");
672 eError = DevmemFwAllocateExportable(psDeviceNode,
675 "FirmwareCodeRegion",
676 &psDevInfo->psRGXFWCodeMemDesc);
677 if (eError != PVRSRV_OK)
679 PVR_DPF((PVR_DBG_ERROR,"DevmemFwAllocateExportable failed (%u)",
686 PMR *psTDMetaCodePMR;
687 IMG_DEVMEM_SIZE_T uiMemDescSize;
688 IMG_DEV_VIRTADDR sTmpDevVAddr;
689 PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
691 PDUMPCOMMENT("Allocate TD META code memory for fw");
693 eError = PhysmemNewTDMetaCodePMR(psDeviceNode,
698 if(eError != PVRSRV_OK)
703 PDUMPCOMMENT("Import TD META code memory for fw");
705 /* NB: psTDMetaCodePMR refcount: 1 -> 2 */
706 eError = DevmemLocalImport(IMG_NULL, /* bridge handle not applicable here */
709 &psDevInfo->psRGXFWCodeMemDesc,
711 if(eError != PVRSRV_OK)
716 eError = DevmemMapToDevice(psDevInfo->psRGXFWCodeMemDesc,
717 psDevInfo->psFirmwareHeap,
719 if(eError != PVRSRV_OK)
721 PVR_DPF((PVR_DBG_ERROR,"Failed to map TD META code PMR (%u)", eError));
725 /* Caution, oddball code follows:
726 When doing the DevmemLocalImport above, we wrap the PMR in a memdesc and increment
727 the PMR's refcount. We would like to implicitly say now, that memdesc is our
728 tracking mechanism for the PMR, and no longer the original pointer to it. The call
729 to PMRUnimportPMR below does that. For reasons explained below, this is only done
730 if this function will return successfully.
732 NB: i.e., psTDMetaCodePMR refcount: 2 -> 1
734 PMRUnimportPMR(psTDMetaCodePMR);
739 DevmemFree(psDevInfo->psRGXFWCodeMemDesc);
742 /* This is done even after the DevmemFree above because as a result of the PMRUnimportPMR
743 at the end of the function never getting hit on an error condition, the PMR must be
744 unreferenced "again" as part of the cleanup */
745 PMRUnimportPMR(psTDMetaCodePMR);
754 PVRSRV_ERROR PVRSRVRGXInitAllocFWImgMemKM(PVRSRV_DEVICE_NODE *psDeviceNode,
755 IMG_DEVMEM_SIZE_T uiFWCodeLen,
756 IMG_DEVMEM_SIZE_T uiFWDataLen,
757 IMG_DEVMEM_SIZE_T uiFWCorememLen,
758 DEVMEM_EXPORTCOOKIE **ppsFWCodeAllocServerExportCookie,
759 IMG_DEV_VIRTADDR *psFWCodeDevVAddrBase,
760 DEVMEM_EXPORTCOOKIE **ppsFWDataAllocServerExportCookie,
761 IMG_DEV_VIRTADDR *psFWDataDevVAddrBase,
762 DEVMEM_EXPORTCOOKIE **ppsFWCorememAllocServerExportCookie,
763 IMG_DEV_VIRTADDR *psFWCorememDevVAddrBase,
764 RGXFWIF_DEV_VIRTADDR *psFWCorememMetaVAddrBase)
766 DEVMEM_FLAGS_T uiMemAllocFlags;
767 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
770 /* set up memory contexts */
772 /* Register callbacks for creation of device memory contexts */
773 psDeviceNode->pfnRegisterMemoryContext = RGXRegisterMemoryContext;
774 psDeviceNode->pfnUnregisterMemoryContext = RGXUnregisterMemoryContext;
776 /* Create the memory context for the firmware. */
777 eError = DevmemCreateContext(IMG_NULL, psDeviceNode,
779 &psDevInfo->psKernelDevmemCtx);
780 if (eError != PVRSRV_OK)
782 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitAllocFWImgMemKM: Failed DevmemCreateContext (%u)", eError));
783 goto failed_to_create_ctx;
786 eError = DevmemFindHeapByName(psDevInfo->psKernelDevmemCtx,
788 &psDevInfo->psFirmwareHeap);
789 if (eError != PVRSRV_OK)
791 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitAllocFWImgMemKM: Failed DevmemFindHeapByName (%u)", eError));
792 goto failed_to_find_heap;
796 * Set up Allocation for FW code section
798 uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
799 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
800 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
801 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
802 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
803 PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
804 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE;
807 eError = RGXAllocateFWCodeRegion(psDeviceNode,
811 if (eError != PVRSRV_OK)
813 PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw code mem (%u)",
815 goto failFWCodeMemDescAlloc;
818 eError = DevmemExport(psDevInfo->psRGXFWCodeMemDesc,
819 &psDevInfo->sRGXFWCodeExportCookie);
820 if (eError != PVRSRV_OK)
822 PVR_DPF((PVR_DBG_ERROR,"Failed to export fw code mem (%u)",
824 goto failFWCodeMemDescExport;
827 eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc,
828 psFWCodeDevVAddrBase);
829 if (eError != PVRSRV_OK)
831 PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw code mem (%u)",
833 goto failFWCodeMemDescAqDevVirt;
837 * The FW code must be the first allocation in the firmware heap, otherwise
838 * the bootloader will not work (META will not be able to find the bootloader).
840 PVR_ASSERT(psFWCodeDevVAddrBase->uiAddr == RGX_FIRMWARE_HEAP_BASE);
843 * Set up Allocation for FW data section
845 uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
846 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
847 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
848 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
849 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
850 PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
851 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
852 PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
853 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
855 PDUMPCOMMENT("Allocate and export data memory for fw");
857 eError = DevmemFwAllocateExportable(psDeviceNode,
860 "FirmwareDataRegion",
861 &psDevInfo->psRGXFWDataMemDesc);
862 if (eError != PVRSRV_OK)
864 PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw data mem (%u)",
866 goto failFWDataMemDescAlloc;
869 eError = DevmemExport(psDevInfo->psRGXFWDataMemDesc,
870 &psDevInfo->sRGXFWDataExportCookie);
871 if (eError != PVRSRV_OK)
873 PVR_DPF((PVR_DBG_ERROR,"Failed to export fw data mem (%u)",
875 goto failFWDataMemDescExport;
878 eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWDataMemDesc,
879 psFWDataDevVAddrBase);
880 if (eError != PVRSRV_OK)
882 PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw data mem (%u)",
884 goto failFWDataMemDescAqDevVirt;
887 if (uiFWCorememLen != 0)
890 * Set up Allocation for FW coremem section
892 uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
893 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) |
894 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
895 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
896 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
897 PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
898 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
899 PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
900 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
902 PDUMPCOMMENT("Allocate and export coremem memory for fw");
904 eError = DevmemFwAllocateExportable(psDeviceNode,
907 "FirmwareCorememRegion",
908 &psDevInfo->psRGXFWCorememMemDesc);
909 if (eError != PVRSRV_OK)
911 PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw coremem mem, size: %lld, flags: %x (%u)",
912 uiFWCorememLen, uiMemAllocFlags, eError));
913 goto failFWCorememMemDescAlloc;
916 eError = DevmemExport(psDevInfo->psRGXFWCorememMemDesc,
917 &psDevInfo->sRGXFWCorememExportCookie);
918 if (eError != PVRSRV_OK)
920 PVR_DPF((PVR_DBG_ERROR,"Failed to export fw coremem mem (%u)",
922 goto failFWCorememMemDescExport;
925 eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCorememMemDesc,
926 psFWCorememDevVAddrBase);
927 if (eError != PVRSRV_OK)
929 PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw coremem mem (%u)",
931 goto failFWCorememMemDescAqDevVirt;
934 RGXSetFirmwareAddress(psFWCorememMetaVAddrBase,
935 psDevInfo->psRGXFWCorememMemDesc,
936 0, RFW_FWADDR_NOREF_FLAG);
938 #if defined(HW_ERN_45914)
939 /* temporarily make sure the coremem is init using the SLC */
940 psFWCorememMetaVAddrBase->ui32Addr &= ~RGXFW_SEGMMU_DMAP_ADDR_START;
941 psFWCorememMetaVAddrBase->ui32Addr |= RGXFW_BOOTLDR_META_ADDR;
946 *ppsFWCodeAllocServerExportCookie = &psDevInfo->sRGXFWCodeExportCookie;
947 *ppsFWDataAllocServerExportCookie = &psDevInfo->sRGXFWDataExportCookie;
948 /* Set all output arguments to ensure safe use in Part2 initialisation */
949 *ppsFWCorememAllocServerExportCookie = &psDevInfo->sRGXFWCorememExportCookie;
954 failFWCorememMemDescAqDevVirt:
956 if (uiFWCorememLen != 0)
958 DevmemUnexport(psDevInfo->psRGXFWCorememMemDesc, &psDevInfo->sRGXFWCorememExportCookie);
960 failFWCorememMemDescExport:
962 if (uiFWCorememLen != 0)
964 DevmemFwFree(psDevInfo->psRGXFWCorememMemDesc);
966 failFWCorememMemDescAlloc:
968 DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWDataMemDesc);
969 failFWDataMemDescAqDevVirt:
971 DevmemUnexport(psDevInfo->psRGXFWDataMemDesc, &psDevInfo->sRGXFWDataExportCookie);
972 failFWDataMemDescExport:
974 DevmemFwFree(psDevInfo->psRGXFWDataMemDesc);
975 failFWDataMemDescAlloc:
977 DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
978 failFWCodeMemDescAqDevVirt:
980 DevmemUnexport(psDevInfo->psRGXFWCodeMemDesc, &psDevInfo->sRGXFWCodeExportCookie);
981 failFWCodeMemDescExport:
983 DevmemFwFree(psDevInfo->psRGXFWCodeMemDesc);
984 failFWCodeMemDescAlloc:
988 * Clear the mem context create callbacks before destroying the RGX firmware
989 * context to avoid a spurious callback.
991 psDeviceNode->pfnRegisterMemoryContext = IMG_NULL;
992 psDeviceNode->pfnUnregisterMemoryContext = IMG_NULL;
993 DevmemDestroyContext(psDevInfo->psKernelDevmemCtx);
994 failed_to_create_ctx:
1000 * PVRSRVRGXInitFirmwareKM
1003 PVRSRV_ERROR PVRSRVRGXInitFirmwareKM(PVRSRV_DEVICE_NODE *psDeviceNode,
1004 RGXFWIF_DEV_VIRTADDR *psRGXFwInit,
1005 IMG_BOOL bEnableSignatureChecks,
1006 IMG_UINT32 ui32SignatureChecksBufSize,
1007 IMG_UINT32 ui32HWPerfFWBufSizeKB,
1008 IMG_UINT64 ui64HWPerfFilter,
1009 IMG_UINT32 ui32RGXFWAlignChecksSize,
1010 IMG_UINT32 *pui32RGXFWAlignChecks,
1011 IMG_UINT32 ui32ConfigFlags,
1012 IMG_UINT32 ui32LogType,
1013 IMG_UINT32 ui32FilterFlags,
1014 RGXFWIF_COMPCHECKS_BVNC *psClientBVNC)
1016 PVRSRV_ERROR eError;
1017 RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sBVNC);
1018 IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV;
1019 IMG_UINT32 ui32NumBIFTilingConfigs, *pui32BIFTilingXStrides, i;
1022 /* Check if BVNC numbers of client and driver are compatible */
1023 rgx_bvnc_packed(&sBVNC.ui32BNC, sBVNC.aszV, sBVNC.ui32VLenMax, RGX_BVNC_KM_B, RGX_BVNC_KM_V_ST, RGX_BVNC_KM_N, RGX_BVNC_KM_C);
1025 RGX_BVNC_EQUAL(sBVNC, *psClientBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
1027 if (!bCompatibleAll)
1029 if (!bCompatibleVersion)
1031 PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of driver (%d) and client (%d).",
1033 sBVNC.ui32LayoutVersion,
1034 psClientBVNC->ui32LayoutVersion));
1035 eError = PVRSRV_ERROR_BVNC_MISMATCH;
1037 goto failed_to_pass_compatibility_check;
1040 if (!bCompatibleLenMax)
1042 PVR_LOG(("(FAIL) %s: Incompatible V maxlen of driver (%d) and client (%d).",
1045 psClientBVNC->ui32VLenMax));
1046 eError = PVRSRV_ERROR_BVNC_MISMATCH;
1048 goto failed_to_pass_compatibility_check;
1051 if (!bCompatibleBNC)
1053 PVR_LOG(("(FAIL) %s: Incompatible driver BNC (%d._.%d.%d) / client BNC (%d._.%d.%d).",
1055 RGX_BVNC_PACKED_EXTR_B(sBVNC),
1056 RGX_BVNC_PACKED_EXTR_N(sBVNC),
1057 RGX_BVNC_PACKED_EXTR_C(sBVNC),
1058 RGX_BVNC_PACKED_EXTR_B(*psClientBVNC),
1059 RGX_BVNC_PACKED_EXTR_N(*psClientBVNC),
1060 RGX_BVNC_PACKED_EXTR_C(*psClientBVNC)));
1061 eError = PVRSRV_ERROR_BVNC_MISMATCH;
1063 goto failed_to_pass_compatibility_check;
1068 PVR_LOG(("(FAIL) %s: Incompatible driver BVNC (%d.%s.%d.%d) / client BVNC (%d.%s.%d.%d).",
1070 RGX_BVNC_PACKED_EXTR_B(sBVNC),
1071 RGX_BVNC_PACKED_EXTR_V(sBVNC),
1072 RGX_BVNC_PACKED_EXTR_N(sBVNC),
1073 RGX_BVNC_PACKED_EXTR_C(sBVNC),
1074 RGX_BVNC_PACKED_EXTR_B(*psClientBVNC),
1075 RGX_BVNC_PACKED_EXTR_V(*psClientBVNC),
1076 RGX_BVNC_PACKED_EXTR_N(*psClientBVNC),
1077 RGX_BVNC_PACKED_EXTR_C(*psClientBVNC)));
1078 eError = PVRSRV_ERROR_BVNC_MISMATCH;
1080 goto failed_to_pass_compatibility_check;
1085 PVR_DPF((PVR_DBG_MESSAGE, "%s: COMPAT_TEST: driver BVNC (%d.%s.%d.%d) and client BVNC (%d.%s.%d.%d) match. [ OK ]",
1087 RGX_BVNC_PACKED_EXTR_B(sBVNC),
1088 RGX_BVNC_PACKED_EXTR_V(sBVNC),
1089 RGX_BVNC_PACKED_EXTR_N(sBVNC),
1090 RGX_BVNC_PACKED_EXTR_C(sBVNC),
1091 RGX_BVNC_PACKED_EXTR_B(*psClientBVNC),
1092 RGX_BVNC_PACKED_EXTR_V(*psClientBVNC),
1093 RGX_BVNC_PACKED_EXTR_N(*psClientBVNC),
1094 RGX_BVNC_PACKED_EXTR_C(*psClientBVNC)));
1097 GetNumBifTilingHeapConfigs(&ui32NumBIFTilingConfigs);
1098 pui32BIFTilingXStrides = OSAllocMem(sizeof(IMG_UINT32) * ui32NumBIFTilingConfigs);
1099 if(pui32BIFTilingXStrides == IMG_NULL)
1101 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1102 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: OSAllocMem failed (%u)", eError));
1103 goto failed_BIF_tiling_alloc;
1105 for(i = 0; i < ui32NumBIFTilingConfigs; i++)
1107 eError = GetBIFTilingHeapXStride(i+1, &pui32BIFTilingXStrides[i]);
1108 if(eError != PVRSRV_OK)
1110 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: GetBIFTilingHeapXStride for heap %u failed (%u)",
1112 goto failed_BIF_heap_init;
1116 eError = RGXSetupFirmware(psDeviceNode,
1117 bEnableSignatureChecks,
1118 ui32SignatureChecksBufSize,
1119 ui32HWPerfFWBufSizeKB,
1121 ui32RGXFWAlignChecksSize,
1122 pui32RGXFWAlignChecks,
1125 ui32NumBIFTilingConfigs,
1126 pui32BIFTilingXStrides,
1129 if (eError != PVRSRV_OK)
1131 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: RGXSetupFirmware failed (%u)", eError));
1132 goto failed_init_firmware;
1135 OSFreeMem(pui32BIFTilingXStrides);
1138 failed_init_firmware:
1139 failed_BIF_heap_init:
1140 OSFreeMem(pui32BIFTilingXStrides);
1141 failed_BIF_tiling_alloc:
1142 failed_to_pass_compatibility_check:
1143 PVR_ASSERT(eError != PVRSRV_OK);
1150 /* See device.h for function declaration */
1151 static PVRSRV_ERROR RGXAllocUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
1152 DEVMEM_MEMDESC **psMemDesc,
1153 IMG_UINT32 *puiSyncPrimVAddr,
1154 IMG_UINT32 *puiSyncPrimBlockSize)
1156 PVRSRV_RGXDEV_INFO *psDevInfo;
1157 PVRSRV_ERROR eError;
1158 RGXFWIF_DEV_VIRTADDR pFirmwareAddr;
1159 IMG_DEVMEM_SIZE_T uiUFOBlockSize = sizeof(IMG_UINT32);
1160 IMG_DEVMEM_ALIGN_T ui32UFOBlockAlign = sizeof(IMG_UINT32);
1162 psDevInfo = psDeviceNode->pvDevice;
1164 /* Size and align are 'expanded' because we request an Exportalign allocation */
1165 DevmemExportalignAdjustSizeAndAlign(psDevInfo->psFirmwareHeap,
1167 &ui32UFOBlockAlign);
1169 eError = DevmemFwAllocateExportable(psDeviceNode,
1171 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1172 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
1173 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
1174 PVRSRV_MEMALLOCFLAG_CACHE_COHERENT |
1175 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1176 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1177 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
1178 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE,
1181 if (eError != PVRSRV_OK)
1186 DevmemPDumpLoadMem(*psMemDesc,
1189 PDUMP_FLAGS_CONTINUOUS);
1191 RGXSetFirmwareAddress(&pFirmwareAddr, *psMemDesc, 0, RFW_FWADDR_FLAG_NONE);
1192 *puiSyncPrimVAddr = pFirmwareAddr.ui32Addr;
1193 *puiSyncPrimBlockSize = TRUNCATE_64BITS_TO_32BITS(uiUFOBlockSize);
1197 DevmemFwFree(*psMemDesc);
1202 /* See device.h for function declaration */
1203 static IMG_VOID RGXFreeUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
1204 DEVMEM_MEMDESC *psMemDesc)
1207 If the system has snooping of the device cache then the UFO block
1208 might be in the cache so we need to flush it out before freeing
1211 if (PVRSRVSystemSnoopingOfDeviceCache())
1213 RGXFWIF_KCCB_CMD sFlushInvalCmd;
1214 PVRSRV_ERROR eError;
1216 /* Schedule the SLC flush command ... */
1218 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
1220 sFlushInvalCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
1221 sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_TRUE;
1222 sFlushInvalCmd.uCmdData.sSLCFlushInvalData.eDM = RGXFWIF_DM_2D; //Covers all of Sidekick
1223 sFlushInvalCmd.uCmdData.sSLCFlushInvalData.psContext.ui32Addr = 0;
1225 eError = RGXSendCommandWithPowLock(psDeviceNode->pvDevice,
1228 sizeof(sFlushInvalCmd),
1230 if (eError != PVRSRV_OK)
1232 PVR_DPF((PVR_DBG_ERROR,"RGXFreeUFOBlock: Failed to schedule SLC flush command with error (%u)", eError));
1236 /* Wait for the SLC flush to complete */
1237 eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
1238 if (eError != PVRSRV_OK)
1240 PVR_DPF((PVR_DBG_ERROR,"RGXFreeUFOBlock: SLC flush and invalidate aborted with error (%u)", eError));
1245 RGXUnsetFirmwareAddress(psMemDesc);
1246 DevmemFwFree(psMemDesc);
1252 PVRSRV_ERROR DevDeInitRGX (PVRSRV_DEVICE_NODE *psDeviceNode)
1254 PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO*)psDeviceNode->pvDevice;
1255 PVRSRV_ERROR eError;
1256 DEVICE_MEMORY_INFO *psDevMemoryInfo;
1260 /* Can happen if DevInitRGX failed */
1261 PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Null DevInfo"));
1265 /* Unregister debug request notifiers first as they could depend on anything. */
1266 PVRSRVUnregisterDbgRequestNotify(psDeviceNode->hDbgReqNotify);
1268 /* Cancel notifications to this device */
1269 PVRSRVUnregisterCmdCompleteNotify(psDeviceNode->hCmdCompNotify);
1270 psDeviceNode->hCmdCompNotify = IMG_NULL;
1273 * De-initialise in reverse order, so stage 2 init is undone first.
1275 if (g_bDevInit2Done)
1277 g_bDevInit2Done = IMG_FALSE;
1279 #if !defined(NO_HARDWARE)
1280 (IMG_VOID) OSUninstallDeviceLISR(psDevInfo->pvLISRData);
1281 (IMG_VOID) OSUninstallMISR(psDevInfo->pvMISRData);
1282 (IMG_VOID) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
1283 if (psDevInfo->pvAPMISRData != IMG_NULL)
1285 (IMG_VOID) OSUninstallMISR(psDevInfo->pvAPMISRData);
1287 #endif /* !NO_HARDWARE */
1289 /* Remove the device from the power manager */
1290 eError = PVRSRVRemovePowerDevice(psDeviceNode->sDevId.ui32DeviceIndex);
1291 if (eError != PVRSRV_OK)
1296 /* Free DVFS History */
1297 if (psDevInfo->psGpuDVFSHistory != IMG_NULL)
1299 OSFreeMem(psDevInfo->psGpuDVFSHistory);
1300 psDevInfo->psGpuDVFSHistory = IMG_NULL;
1303 /* De-init Freelists/ZBuffers... */
1304 OSLockDestroy(psDevInfo->hLockFreeList);
1305 OSLockDestroy(psDevInfo->hLockZSBuffer);
1307 /* De-init HWPerf Ftrace thread resources for the RGX device */
1308 #if defined(SUPPORT_GPUTRACE_EVENTS)
1309 RGXHWPerfFTraceGPUDeInit(psDevInfo);
1312 /* Unregister MMU related stuff */
1313 eError = RGXMMUInit_Unregister(psDeviceNode);
1314 if (eError != PVRSRV_OK)
1316 PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Failed RGXMMUInit_Unregister (0x%x)", eError));
1321 if (psDevInfo->pvRegsBaseKM != IMG_NULL)
1323 #if !defined(NO_HARDWARE)
1324 OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
1325 psDevInfo->ui32RegSize,
1327 #endif /* !NO_HARDWARE */
1328 psDevInfo->pvRegsBaseKM = IMG_NULL;
1332 #if 0 /* not required at this time */
1333 if (psDevInfo->hTimer)
1335 eError = OSRemoveTimer(psDevInfo->hTimer);
1336 if (eError != PVRSRV_OK)
1338 PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Failed to remove timer"));
1341 psDevInfo->hTimer = IMG_NULL;
1345 psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
1347 RGX_DeInitHeaps(psDevMemoryInfo);
1349 if (DevmemIsValidExportCookie(&psDevInfo->sRGXFWCodeExportCookie))
1351 /* if the export cookie is valid, the init sequence failed */
1352 PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: FW Code Export cookie still valid (should have been unexported at init time)"));
1353 DevmemUnexport(psDevInfo->psRGXFWCodeMemDesc, &psDevInfo->sRGXFWCodeExportCookie);
1356 if (DevmemIsValidExportCookie(&psDevInfo->sRGXFWDataExportCookie))
1358 /* if the export cookie is valid, the init sequence failed */
1359 PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: FW Data Export cookie still valid (should have been unexported at init time)"));
1360 DevmemUnexport(psDevInfo->psRGXFWDataMemDesc, &psDevInfo->sRGXFWDataExportCookie);
1363 if (DevmemIsValidExportCookie(&psDevInfo->sRGXFWCorememExportCookie))
1365 /* if the export cookie is valid, the init sequence failed */
1366 PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: FW Coremem Export cookie still valid (should have been unexported at init time)"));
1367 DevmemUnexport(psDevInfo->psRGXFWCorememMemDesc, &psDevInfo->sRGXFWCorememExportCookie);
1371 Free the firmware allocations.
1373 RGXFreeFirmware(psDevInfo);
1376 * Clear the mem context create callbacks before destroying the RGX firmware
1377 * context to avoid a spurious callback.
1379 psDeviceNode->pfnRegisterMemoryContext = IMG_NULL;
1380 psDeviceNode->pfnUnregisterMemoryContext = IMG_NULL;
1382 if (psDevInfo->psKernelDevmemCtx)
1384 eError = DevmemDestroyContext(psDevInfo->psKernelDevmemCtx);
1386 PVR_ASSERT(eError == PVRSRV_OK);
1389 /* destroy the context list locks */
1390 OSWRLockDestroy(psDevInfo->hRenderCtxListLock);
1391 OSWRLockDestroy(psDevInfo->hComputeCtxListLock);
1392 OSWRLockDestroy(psDevInfo->hTransferCtxListLock);
1393 OSWRLockDestroy(psDevInfo->hRaytraceCtxListLock);
1394 OSWRLockDestroy(psDevInfo->hMemoryCtxListLock);
1396 /* Free the init scripts. */
1397 OSFreeMem(psDevInfo->psScripts);
1399 /* DeAllocate devinfo */
1400 OSFreeMem(psDevInfo);
1402 psDeviceNode->pvDevice = IMG_NULL;
1408 ******************************************************************************
1410 @Function RGXDebugRequestNotify
1412 @Description Dump the debug data for RGX
1414 ******************************************************************************/
1415 static IMG_VOID RGXDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDbgReqestHandle, IMG_UINT32 ui32VerbLevel)
1417 PVRSRV_DEVICE_NODE *psDeviceNode = hDbgReqestHandle;
1419 /* Only action the request if we've fully init'ed */
1420 if (g_bDevInit2Done)
1422 RGXDebugRequestProcess(g_pfnDumpDebugPrintf, psDeviceNode->pvDevice, ui32VerbLevel);
1428 PVRSRV_ERROR RGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode)
1430 PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)(psDeviceNode->pvDevice);
1433 for (ui32Idx = 0; ui32Idx < RGXFWIF_DM_MAX; ui32Idx++)
1435 psDevInfo->abDumpedKCCBCtlAlready[ui32Idx] = IMG_FALSE;
1444 static PVRSRV_ERROR RGX_InitHeaps(DEVICE_MEMORY_INFO *psNewMemoryInfo)
1446 DEVMEM_HEAP_BLUEPRINT *psDeviceMemoryHeapCursor;
1449 psNewMemoryInfo->psDeviceMemoryHeap = OSAllocMem(sizeof(DEVMEM_HEAP_BLUEPRINT) * RGX_MAX_HEAP_ID);
1450 if(psNewMemoryInfo->psDeviceMemoryHeap == IMG_NULL)
1452 PVR_DPF((PVR_DBG_ERROR,"RGXRegisterDevice : Failed to alloc memory for DEVMEM_HEAP_BLUEPRINT"));
1456 psDeviceMemoryHeapCursor = psNewMemoryInfo->psDeviceMemoryHeap;
1458 /************* general ***************/
1459 psDeviceMemoryHeapCursor->pszName = RGX_GENERAL_HEAP_IDENT;
1460 psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_GENERAL_HEAP_BASE;
1461 psDeviceMemoryHeapCursor->uiHeapLength = RGX_GENERAL_HEAP_SIZE;
1462 psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
1464 psDeviceMemoryHeapCursor++;/* advance to the next heap */
1466 /************* PDS code and data ***************/
1467 psDeviceMemoryHeapCursor->pszName = RGX_PDSCODEDATA_HEAP_IDENT;
1468 psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_PDSCODEDATA_HEAP_BASE;
1469 psDeviceMemoryHeapCursor->uiHeapLength = RGX_PDSCODEDATA_HEAP_SIZE;
1470 psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
1472 psDeviceMemoryHeapCursor++;/* advance to the next heap */
1474 /************* USC code ***************/
1475 psDeviceMemoryHeapCursor->pszName = RGX_USCCODE_HEAP_IDENT;
1476 psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_USCCODE_HEAP_BASE;
1477 psDeviceMemoryHeapCursor->uiHeapLength = RGX_USCCODE_HEAP_SIZE;
1478 psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
1480 psDeviceMemoryHeapCursor++;/* advance to the next heap */
1482 /************* TQ 3D Parameters ***************/
1483 psDeviceMemoryHeapCursor->pszName = RGX_TQ3DPARAMETERS_HEAP_IDENT;
1484 psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_TQ3DPARAMETERS_HEAP_BASE;
1485 psDeviceMemoryHeapCursor->uiHeapLength = RGX_TQ3DPARAMETERS_HEAP_SIZE;
1486 psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
1488 psDeviceMemoryHeapCursor++;/* advance to the next heap */
1490 /************ Tiling Heaps ************/
1491 #define INIT_TILING_HEAP(N) \
1493 psDeviceMemoryHeapCursor->pszName = RGX_BIF_TILING_HEAP_ ## N ## _IDENT; \
1494 psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_BIF_TILING_HEAP_ ## N ## _BASE; \
1495 psDeviceMemoryHeapCursor->uiHeapLength = RGX_BIF_TILING_HEAP_SIZE; \
1496 psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE(); \
1497 psDeviceMemoryHeapCursor++; \
1499 INIT_TILING_HEAP(1);
1500 INIT_TILING_HEAP(2);
1501 INIT_TILING_HEAP(3);
1502 INIT_TILING_HEAP(4);
1503 #undef INIT_TILING_HEAP
1505 /************* Doppler ***************/
1506 psDeviceMemoryHeapCursor->pszName = RGX_DOPPLER_HEAP_IDENT;
1507 psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_DOPPLER_HEAP_BASE;
1508 psDeviceMemoryHeapCursor->uiHeapLength = RGX_DOPPLER_HEAP_SIZE;
1509 psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
1511 psDeviceMemoryHeapCursor++;/* advance to the next heap */
1513 /************* Doppler Overflow ***************/
1514 psDeviceMemoryHeapCursor->pszName = RGX_DOPPLER_OVERFLOW_HEAP_IDENT;
1515 psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_DOPPLER_OVERFLOW_HEAP_BASE;
1516 psDeviceMemoryHeapCursor->uiHeapLength = RGX_DOPPLER_OVERFLOW_HEAP_SIZE;
1517 psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
1519 psDeviceMemoryHeapCursor++;/* advance to the next heap */
1521 /************* HWBRN37200 ***************/
1522 #if defined(FIX_HW_BRN_37200)
1523 psDeviceMemoryHeapCursor->pszName = "HWBRN37200";
1524 psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_HWBRN37200_HEAP_BASE;
1525 psDeviceMemoryHeapCursor->uiHeapLength = RGX_HWBRN37200_HEAP_SIZE;
1526 psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
1528 psDeviceMemoryHeapCursor++;/* advance to the next heap */
1531 /************* Firmware ***************/
1532 psDeviceMemoryHeapCursor->pszName = "Firmware";
1533 psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_FIRMWARE_HEAP_BASE;
1534 psDeviceMemoryHeapCursor->uiHeapLength = RGX_FIRMWARE_HEAP_SIZE;
1535 psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
1537 psDeviceMemoryHeapCursor++;/* advance to the next heap */
1539 /* set the heap count */
1540 psNewMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeapCursor - psNewMemoryInfo->psDeviceMemoryHeap);
1542 PVR_ASSERT(psNewMemoryInfo->ui32HeapCount <= RGX_MAX_HEAP_ID);
1544 /* the new way: we'll set up 2 heap configs: one will be for Meta
1545 only, and has only the firmware heap in it.
1546 The remaining one shall be for clients only, and shall have all
1547 the other heaps in it */
1549 psNewMemoryInfo->uiNumHeapConfigs = 2;
1550 psNewMemoryInfo->psDeviceMemoryHeapConfigArray = OSAllocMem(sizeof(DEVMEM_HEAP_CONFIG) * psNewMemoryInfo->uiNumHeapConfigs);
1551 if (psNewMemoryInfo->psDeviceMemoryHeapConfigArray == IMG_NULL)
1553 PVR_DPF((PVR_DBG_ERROR,"RGXRegisterDevice : Failed to alloc memory for DEVMEM_HEAP_CONFIG"));
1557 psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].pszName = "Default Heap Configuration";
1558 psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].uiNumHeaps = psNewMemoryInfo->ui32HeapCount-1;
1559 psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].psHeapBlueprintArray = psNewMemoryInfo->psDeviceMemoryHeap;
1561 psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].pszName = "Firmware Heap Configuration";
1562 #if defined(FIX_HW_BRN_37200)
1563 psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].uiNumHeaps = 2;
1564 psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].psHeapBlueprintArray = psDeviceMemoryHeapCursor-2;
1566 psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].uiNumHeaps = 1;
1567 psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].psHeapBlueprintArray = psDeviceMemoryHeapCursor-1;
1572 OSFreeMem(psNewMemoryInfo->psDeviceMemoryHeap);
1574 return PVRSRV_ERROR_OUT_OF_MEMORY;
1577 static IMG_VOID RGX_DeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo)
1579 OSFreeMem(psDevMemoryInfo->psDeviceMemoryHeapConfigArray);
1580 OSFreeMem(psDevMemoryInfo->psDeviceMemoryHeap);
1587 PVRSRV_ERROR RGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
1589 PVRSRV_ERROR eError;
1590 DEVICE_MEMORY_INFO *psDevMemoryInfo;
1591 PVRSRV_RGXDEV_INFO *psDevInfo;
1593 /* pdump info about the core */
1594 PDUMPCOMMENT("RGX Version Information (KM): %s", RGX_BVNC_KM);
1596 #if defined(RGX_FEATURE_SYSTEM_CACHE)
1597 PDUMPCOMMENT("RGX System Level Cache is present");
1598 #endif /* RGX_FEATURE_SYSTEM_CACHE */
1600 PDUMPCOMMENT("RGX Initialisation (Part 1)");
1602 /*********************
1603 * Device node setup *
1604 *********************/
1605 /* Setup static data and callbacks on the device agnostic device node */
1606 psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
1607 psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
1609 psDeviceNode->sDevId.pszPDumpRegName = RGX_PDUMPREG_NAME;
1611 psDeviceNode->sDevId.pszPDumpDevName = PhysHeapPDumpMemspaceName(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
1612 psDeviceNode->pfnPDumpInitDevice = &RGXResetPDump;
1615 psDeviceNode->eHealthStatus = PVRSRV_DEVICE_HEALTH_STATUS_OK;
1617 #if defined(SUPPORT_MEMORY_TILING)
1618 psDeviceNode->pfnAllocMemTilingRange = RGX_AllocMemTilingRange;
1619 psDeviceNode->pfnFreeMemTilingRange = RGX_FreeMemTilingRange;
1622 /* Configure MMU specific stuff */
1623 RGXMMUInit_Register(psDeviceNode);
1625 psDeviceNode->pfnMMUCacheInvalidate = RGXMMUCacheInvalidate;
1627 psDeviceNode->pfnSLCCacheInvalidateRequest = RGXSLCCacheInvalidateRequest;
1629 /* Register RGX to receive notifies when other devices complete some work */
1630 PVRSRVRegisterCmdCompleteNotify(&psDeviceNode->hCmdCompNotify, &RGXScheduleProcessQueuesKM, psDeviceNode);
1632 psDeviceNode->pfnInitDeviceCompatCheck = &RGXDevInitCompatCheck;
1634 /* Register callbacks for creation of device memory contexts */
1635 psDeviceNode->pfnRegisterMemoryContext = RGXRegisterMemoryContext;
1636 psDeviceNode->pfnUnregisterMemoryContext = RGXUnregisterMemoryContext;
1638 /* Register callbacks for Unified Fence Objects */
1639 psDeviceNode->pfnAllocUFOBlock = RGXAllocUFOBlock;
1640 psDeviceNode->pfnFreeUFOBlock = RGXFreeUFOBlock;
1642 /* Register callback for dumping debug info */
1643 PVRSRVRegisterDbgRequestNotify(&psDeviceNode->hDbgReqNotify, &RGXDebugRequestNotify, DEBUG_REQUEST_RGX, psDeviceNode);
1645 /* Register callback for checking the device's health */
1646 psDeviceNode->pfnUpdateHealthStatus = RGXUpdateHealthStatus;
1648 /* Register method to service the FW HWPerf buffer */
1649 psDeviceNode->pfnServiceHWPerf = RGXHWPerfDataStoreCB;
1651 /* Register callback for getting the device version information string */
1652 psDeviceNode->pfnDeviceVersionString = RGXDevVersionString;
1654 /* Register callback for getting the device clock speed */
1655 psDeviceNode->pfnDeviceClockSpeed = RGXDevClockSpeed;
1657 /* Register callback for soft resetting some device modules */
1658 psDeviceNode->pfnSoftReset = RGXSoftReset;
1660 /* Register callback for resetting the HWR logs */
1661 psDeviceNode->pfnResetHWRLogs = RGXResetHWRLogs;
1664 /*********************
1665 * Device info setup *
1666 *********************/
1667 /* Allocate device control block */
1668 psDevInfo = OSAllocMem(sizeof(*psDevInfo));
1669 if (psDevInfo == IMG_NULL)
1671 PVR_DPF((PVR_DBG_ERROR,"DevInitRGXPart1 : Failed to alloc memory for DevInfo"));
1672 return (PVRSRV_ERROR_OUT_OF_MEMORY);
1674 OSMemSet (psDevInfo, 0, sizeof(*psDevInfo));
1676 /* create locks for the context lists stored in the DevInfo structure.
1677 * these lists are modified on context create/destroy and read by the
1681 eError = OSWRLockCreate(&(psDevInfo->hRenderCtxListLock));
1682 if (eError != PVRSRV_OK)
1684 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create render context list lock", __func__));
1688 eError = OSWRLockCreate(&(psDevInfo->hComputeCtxListLock));
1689 if (eError != PVRSRV_OK)
1691 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create compute context list lock", __func__));
1695 eError = OSWRLockCreate(&(psDevInfo->hTransferCtxListLock));
1696 if (eError != PVRSRV_OK)
1698 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create transfer context list lock", __func__));
1702 eError = OSWRLockCreate(&(psDevInfo->hRaytraceCtxListLock));
1703 if (eError != PVRSRV_OK)
1705 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create raytrace context list lock", __func__));
1709 eError = OSWRLockCreate(&(psDevInfo->hMemoryCtxListLock));
1710 if (eError != PVRSRV_OK)
1712 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create memory context list lock", __func__));
1716 dllist_init(&(psDevInfo->sRenderCtxtListHead));
1717 dllist_init(&(psDevInfo->sComputeCtxtListHead));
1718 dllist_init(&(psDevInfo->sTransferCtxtListHead));
1719 dllist_init(&(psDevInfo->sRaytraceCtxtListHead));
1721 dllist_init(&(psDevInfo->sCommonCtxtListHead));
1722 psDevInfo->ui32CommonCtxtCurrentID = 1;
1724 psDeviceNode->pvDevice = psDevInfo;
1725 dllist_init(&psDevInfo->sMemoryContextList);
1727 /* Allocate space for scripts. */
1728 psDevInfo->psScripts = OSAllocMem(sizeof(*psDevInfo->psScripts));
1729 if (!psDevInfo->psScripts)
1731 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1732 PVR_LOGG_IF_ERROR(PVRSRV_ERROR_OUT_OF_MEMORY, "OSAllocMem", e5);
1735 /* Setup static data and callbacks on the device specific device info */
1736 psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
1737 psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
1738 psDevInfo->psDeviceNode = psDeviceNode;
1740 psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
1741 psDevMemoryInfo->ui32AddressSpaceSizeLog2 = RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS;
1742 psDevInfo->pvDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
1744 /* flags, backing store details to be specified by system */
1745 psDevMemoryInfo->ui32Flags = 0;
1747 eError = RGX_InitHeaps(psDevMemoryInfo);
1748 if (eError != PVRSRV_OK)
1750 PVR_LOGG_IF_ERROR(eError, "RGX_InitHeaps", e6);
1756 OSFreeMem(psDevInfo->psScripts);
1757 psDevInfo->psScripts = NULL;
1759 OSWRLockDestroy(psDevInfo->hMemoryCtxListLock);
1761 OSWRLockDestroy(psDevInfo->hRaytraceCtxListLock);
1763 OSWRLockDestroy(psDevInfo->hTransferCtxListLock);
1765 OSWRLockDestroy(psDevInfo->hComputeCtxListLock);
1767 OSWRLockDestroy(psDevInfo->hRenderCtxListLock);
1769 psDeviceNode->pvDevice = NULL;
1770 OSFreeMem(psDevInfo);
1771 PVR_ASSERT(eError != PVRSRV_OK);
1776 *******************************************************************************
1778 @Function RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver
1782 Validate the FW build options against KM driver build options (KM build options only)
1784 Following check is reduntant, because next check checks the same bits.
1785 Redundancy occurs because if client-server are build-compatible and client-firmware are
1786 build-compatible then server-firmware are build-compatible as well.
1788 This check is left for clarity in error messages if any incompatibility occurs.
1790 @Input psRGXFWInit - FW init data
1792 @Return PVRSRV_ERROR - depending on mismatch found
1794 ******************************************************************************/
1795 static PVRSRV_ERROR RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver(RGXFWIF_INIT *psRGXFWInit)
1797 #if !defined(NO_HARDWARE)
1798 IMG_UINT32 ui32BuildOptions, ui32BuildOptionsFWKMPart, ui32BuildOptionsMismatch;
1800 if (psRGXFWInit == IMG_NULL)
1801 return PVRSRV_ERROR_INVALID_PARAMS;
1803 ui32BuildOptions = (RGX_BUILD_OPTIONS_KM);
1805 ui32BuildOptionsFWKMPart = psRGXFWInit->sRGXCompChecks.ui32BuildOptions & RGX_BUILD_OPTIONS_MASK_KM;
1807 if (ui32BuildOptions != ui32BuildOptionsFWKMPart)
1809 ui32BuildOptionsMismatch = ui32BuildOptions ^ ui32BuildOptionsFWKMPart;
1810 if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
1812 PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware and KM driver build options; "
1813 "extra options present in the KM driver: (0x%x). Please check rgx_options_km.h",
1814 ui32BuildOptions & ui32BuildOptionsMismatch ));
1817 if ( (ui32BuildOptionsFWKMPart & ui32BuildOptionsMismatch) != 0)
1819 PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware-side and KM driver build options; "
1820 "extra options present in Firmware: (0x%x). Please check rgx_options_km.h",
1821 ui32BuildOptionsFWKMPart & ui32BuildOptionsMismatch ));
1823 return PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
1827 PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Firmware and KM driver build options match. [ OK ]"));
1835 *******************************************************************************
1837 @Function RGXDevInitCompatCheck_BuildOptions_FWAgainstClient
1841 Validate the FW build options against client build options (KM and non-KM)
1843 @Input psDevInfo - device info
1844 @Input psRGXFWInit - FW init data
1845 @Input ui32ClientBuildOptions - client build options flags
1847 @Return PVRSRV_ERROR - depending on mismatch found
1849 ******************************************************************************/
1850 static PVRSRV_ERROR RGXDevInitCompatCheck_BuildOptions_FWAgainstClient(PVRSRV_RGXDEV_INFO *psDevInfo,
1851 RGXFWIF_INIT *psRGXFWInit,
1852 IMG_UINT32 ui32ClientBuildOptions)
1854 #if !defined(NO_HARDWARE)
1855 IMG_UINT32 ui32BuildOptionsMismatch;
1856 IMG_UINT32 ui32BuildOptionsFW;
1859 PVRSRV_ERROR eError;
1863 PDUMPCOMMENT("Compatibility check: client and FW build options");
1864 eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
1865 offsetof(RGXFWIF_INIT, sRGXCompChecks) +
1866 offsetof(RGXFWIF_COMPCHECKS, ui32BuildOptions),
1867 ui32ClientBuildOptions,
1869 PDUMP_POLL_OPERATOR_EQUAL,
1870 PDUMP_FLAGS_CONTINUOUS);
1871 if (eError != PVRSRV_OK)
1873 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
1878 #if !defined(NO_HARDWARE)
1879 if (psRGXFWInit == IMG_NULL)
1880 return PVRSRV_ERROR_INVALID_PARAMS;
1882 ui32BuildOptionsFW = psRGXFWInit->sRGXCompChecks.ui32BuildOptions;
1884 if (ui32ClientBuildOptions != ui32BuildOptionsFW)
1886 ui32BuildOptionsMismatch = ui32ClientBuildOptions ^ ui32BuildOptionsFW;
1887 if ( (ui32ClientBuildOptions & ui32BuildOptionsMismatch) != 0)
1889 PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware and client build options; "
1890 "extra options present in client: (0x%x). Please check rgx_options.h",
1891 ui32ClientBuildOptions & ui32BuildOptionsMismatch ));
1894 if ( (ui32BuildOptionsFW & ui32BuildOptionsMismatch) != 0)
1896 PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware and client build options; "
1897 "extra options present in Firmware: (0x%x). Please check rgx_options.h",
1898 ui32BuildOptionsFW & ui32BuildOptionsMismatch ));
1900 return PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
1904 PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Firmware and client build options match. [ OK ]"));
1912 *******************************************************************************
1914 @Function RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver
1918 Validate FW DDK version against driver DDK version
1920 @Input psDevInfo - device info
1921 @Input psRGXFWInit - FW init data
1923 @Return PVRSRV_ERROR - depending on mismatch found
1925 ******************************************************************************/
1926 static PVRSRV_ERROR RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
1927 RGXFWIF_INIT *psRGXFWInit)
1929 #if defined(PDUMP)||(!defined(NO_HARDWARE))
1930 IMG_UINT32 ui32DDKVersion;
1931 PVRSRV_ERROR eError;
1933 ui32DDKVersion = PVRVERSION_PACK(PVRVERSION_MAJ, PVRVERSION_MIN);
1937 PDUMPCOMMENT("Compatibility check: KM driver and FW DDK version");
1938 eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
1939 offsetof(RGXFWIF_INIT, sRGXCompChecks) +
1940 offsetof(RGXFWIF_COMPCHECKS, ui32DDKVersion),
1943 PDUMP_POLL_OPERATOR_EQUAL,
1944 PDUMP_FLAGS_CONTINUOUS);
1945 if (eError != PVRSRV_OK)
1947 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
1952 #if !defined(NO_HARDWARE)
1953 if (psRGXFWInit == IMG_NULL)
1954 return PVRSRV_ERROR_INVALID_PARAMS;
1956 if (psRGXFWInit->sRGXCompChecks.ui32DDKVersion != ui32DDKVersion)
1958 PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Incompatible driver DDK revision (%u.%u) / Firmware DDK revision (%u.%u).",
1959 PVRVERSION_MAJ, PVRVERSION_MIN,
1960 PVRVERSION_UNPACK_MAJ(psRGXFWInit->sRGXCompChecks.ui32DDKVersion),
1961 PVRVERSION_UNPACK_MIN(psRGXFWInit->sRGXCompChecks.ui32DDKVersion)));
1962 eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
1968 PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: driver DDK revision (%u.%u) and Firmware DDK revision (%u.%u) match. [ OK ]",
1969 PVRVERSION_MAJ, PVRVERSION_MIN,
1970 PVRVERSION_MAJ, PVRVERSION_MIN));
1978 *******************************************************************************
1980 @Function RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver
1984 Validate FW DDK build against driver DDK build
1986 @Input psDevInfo - device info
1987 @Input psRGXFWInit - FW init data
1989 @Return PVRSRV_ERROR - depending on mismatch found
1991 ******************************************************************************/
1992 static PVRSRV_ERROR RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
1993 RGXFWIF_INIT *psRGXFWInit)
1995 #if defined(PDUMP)||(!defined(NO_HARDWARE))
1996 IMG_UINT32 ui32DDKBuild;
1997 PVRSRV_ERROR eError;
1999 ui32DDKBuild = PVRVERSION_BUILD;
2003 PDUMPCOMMENT("Compatibility check: KM driver and FW DDK build");
2004 eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
2005 offsetof(RGXFWIF_INIT, sRGXCompChecks) +
2006 offsetof(RGXFWIF_COMPCHECKS, ui32DDKBuild),
2009 PDUMP_POLL_OPERATOR_EQUAL,
2010 PDUMP_FLAGS_CONTINUOUS);
2011 if (eError != PVRSRV_OK)
2013 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2018 #if !defined(NO_HARDWARE)
2019 if (psRGXFWInit == IMG_NULL)
2020 return PVRSRV_ERROR_INVALID_PARAMS;
2022 if (psRGXFWInit->sRGXCompChecks.ui32DDKBuild != ui32DDKBuild)
2024 PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Incompatible driver DDK build (%d) / Firmware DDK build (%d).",
2025 ui32DDKBuild, psRGXFWInit->sRGXCompChecks.ui32DDKBuild));
2026 eError = PVRSRV_ERROR_DDK_BUILD_MISMATCH;
2032 PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: driver DDK build (%d) and Firmware DDK build (%d) match. [ OK ]",
2033 ui32DDKBuild, psRGXFWInit->sRGXCompChecks.ui32DDKBuild));
2040 *******************************************************************************
2042 @Function RGXDevInitCompatCheck_BVNC_FWAgainstDriver
2046 Validate FW BVNC against driver BVNC
2048 @Input psDevInfo - device info
2049 @Input psRGXFWInit - FW init data
2051 @Return PVRSRV_ERROR - depending on mismatch found
2053 ******************************************************************************/
2054 static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_FWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
2055 RGXFWIF_INIT *psRGXFWInit)
2060 #if !defined(NO_HARDWARE)
2061 IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV;
2063 #if defined(PDUMP)||(!defined(NO_HARDWARE))
2064 RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sBVNC);
2065 PVRSRV_ERROR eError;
2067 rgx_bvnc_packed(&sBVNC.ui32BNC, sBVNC.aszV, sBVNC.ui32VLenMax, RGX_BVNC_KM_B, RGX_BVNC_KM_V_ST, RGX_BVNC_KM_N, RGX_BVNC_KM_C);
2071 PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (struct version)");
2072 eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
2073 offsetof(RGXFWIF_INIT, sRGXCompChecks) +
2074 offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
2075 offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32LayoutVersion),
2076 sBVNC.ui32LayoutVersion,
2078 PDUMP_POLL_OPERATOR_EQUAL,
2079 PDUMP_FLAGS_CONTINUOUS);
2080 if (eError != PVRSRV_OK)
2082 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2085 PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (maxlen)");
2086 eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
2087 offsetof(RGXFWIF_INIT, sRGXCompChecks) +
2088 offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
2089 offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32VLenMax),
2092 PDUMP_POLL_OPERATOR_EQUAL,
2093 PDUMP_FLAGS_CONTINUOUS);
2094 if (eError != PVRSRV_OK)
2096 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2099 PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (BNC part)");
2100 eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
2101 offsetof(RGXFWIF_INIT, sRGXCompChecks) +
2102 offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
2103 offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32BNC),
2106 PDUMP_POLL_OPERATOR_EQUAL,
2107 PDUMP_FLAGS_CONTINUOUS);
2108 if (eError != PVRSRV_OK)
2110 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2113 for (i = 0; i < sBVNC.ui32VLenMax; i += sizeof(IMG_UINT32))
2115 PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (V part)");
2116 eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
2117 offsetof(RGXFWIF_INIT, sRGXCompChecks) +
2118 offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
2119 offsetof(RGXFWIF_COMPCHECKS_BVNC, aszV) +
2121 *((IMG_UINT32 *)(sBVNC.aszV + i)),
2123 PDUMP_POLL_OPERATOR_EQUAL,
2124 PDUMP_FLAGS_CONTINUOUS);
2125 if (eError != PVRSRV_OK)
2127 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2132 #if !defined(NO_HARDWARE)
2133 if (psRGXFWInit == IMG_NULL)
2134 return PVRSRV_ERROR_INVALID_PARAMS;
2136 RGX_BVNC_EQUAL(sBVNC, psRGXFWInit->sRGXCompChecks.sFWBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
2138 if (!bCompatibleAll)
2140 if (!bCompatibleVersion)
2142 PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of driver (%d) and firmware (%d).",
2144 sBVNC.ui32LayoutVersion,
2145 psRGXFWInit->sRGXCompChecks.sFWBVNC.ui32LayoutVersion));
2146 eError = PVRSRV_ERROR_BVNC_MISMATCH;
2150 if (!bCompatibleLenMax)
2152 PVR_LOG(("(FAIL) %s: Incompatible V maxlen of driver (%d) and firmware (%d).",
2155 psRGXFWInit->sRGXCompChecks.sFWBVNC.ui32VLenMax));
2156 eError = PVRSRV_ERROR_BVNC_MISMATCH;
2160 if (!bCompatibleBNC)
2162 PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in KM driver BNC (%d._.%d.%d) and Firmware BNC (%d._.%d.%d)",
2163 RGX_BVNC_PACKED_EXTR_B(sBVNC),
2164 RGX_BVNC_PACKED_EXTR_N(sBVNC),
2165 RGX_BVNC_PACKED_EXTR_C(sBVNC),
2166 RGX_BVNC_PACKED_EXTR_B(psRGXFWInit->sRGXCompChecks.sFWBVNC),
2167 RGX_BVNC_PACKED_EXTR_N(psRGXFWInit->sRGXCompChecks.sFWBVNC),
2168 RGX_BVNC_PACKED_EXTR_C(psRGXFWInit->sRGXCompChecks.sFWBVNC)));
2169 eError = PVRSRV_ERROR_BVNC_MISMATCH;
2175 PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in KM driver BVNC (%d.%s.%d.%d) and Firmware BVNC (%d.%s.%d.%d)",
2176 RGX_BVNC_PACKED_EXTR_B(sBVNC),
2177 RGX_BVNC_PACKED_EXTR_V(sBVNC),
2178 RGX_BVNC_PACKED_EXTR_N(sBVNC),
2179 RGX_BVNC_PACKED_EXTR_C(sBVNC),
2180 RGX_BVNC_PACKED_EXTR_B(psRGXFWInit->sRGXCompChecks.sFWBVNC),
2181 RGX_BVNC_PACKED_EXTR_V(psRGXFWInit->sRGXCompChecks.sFWBVNC),
2182 RGX_BVNC_PACKED_EXTR_N(psRGXFWInit->sRGXCompChecks.sFWBVNC),
2183 RGX_BVNC_PACKED_EXTR_C(psRGXFWInit->sRGXCompChecks.sFWBVNC)));
2184 eError = PVRSRV_ERROR_BVNC_MISMATCH;
2190 PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Firmware BVNC and KM driver BNVC match. [ OK ]"));
2197 *******************************************************************************
2199 @Function RGXDevInitCompatCheck_BVNC_HWAgainstDriver
2203 Validate HW BVNC against driver BVNC
2205 @Input psDevInfo - device info
2206 @Input psRGXFWInit - FW init data
2208 @Return PVRSRV_ERROR - depending on mismatch found
2210 ******************************************************************************/
2211 #if ((!defined(NO_HARDWARE))&&(!defined(EMULATOR)))
2212 #define TARGET_SILICON /* definition for everything that is not emu and not nohw configuration */
2215 #if defined(FIX_HW_BRN_38835)
2216 #define COMPAT_BVNC_MASK_B
2217 #define COMPAT_BVNC_MASK_V
2220 static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_HWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
2221 RGXFWIF_INIT *psRGXFWInit)
2223 #if defined(PDUMP) || defined(TARGET_SILICON)
2224 IMG_UINT32 ui32MaskBNC = RGX_BVNC_PACK_MASK_B |
2225 RGX_BVNC_PACK_MASK_N |
2226 RGX_BVNC_PACK_MASK_C;
2228 IMG_UINT32 bMaskV = IMG_FALSE;
2230 PVRSRV_ERROR eError;
2231 RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sSWBVNC);
2234 #if defined(TARGET_SILICON)
2235 RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sHWBVNC);
2236 IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV;
2239 #if defined(PDUMP) || defined(TARGET_SILICON)
2241 #if defined(COMPAT_BVNC_MASK_B)
2242 ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_B;
2244 #if defined(COMPAT_BVNC_MASK_V)
2247 #if defined(COMPAT_BVNC_MASK_N)
2248 ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_N;
2250 #if defined(COMPAT_BVNC_MASK_C)
2251 ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_C;
2254 rgx_bvnc_packed(&sSWBVNC.ui32BNC, sSWBVNC.aszV, sSWBVNC.ui32VLenMax, RGX_BVNC_KM_B, RGX_BVNC_KM_V_ST, RGX_BVNC_KM_N, RGX_BVNC_KM_C);
2256 #if defined(FIX_HW_BRN_38344)
2257 if (RGX_BVNC_KM_C >= 10)
2259 ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_C;
2263 if ((ui32MaskBNC != (RGX_BVNC_PACK_MASK_B | RGX_BVNC_PACK_MASK_N | RGX_BVNC_PACK_MASK_C)) || bMaskV)
2265 PVR_LOG(("Compatibility checks: Ignoring fields: '%s%s%s%s' of HW BVNC.",
2266 ((!(ui32MaskBNC & RGX_BVNC_PACK_MASK_B))?("B"):("")),
2267 ((bMaskV)?("V"):("")),
2268 ((!(ui32MaskBNC & RGX_BVNC_PACK_MASK_N))?("N"):("")),
2269 ((!(ui32MaskBNC & RGX_BVNC_PACK_MASK_C))?("C"):(""))));
2273 #if defined(EMULATOR)
2274 PVR_LOG(("Compatibility checks for emu target: Ignoring HW BVNC checks."));
2278 PDUMPCOMMENT("Compatibility check: Layout version of compchecks struct");
2279 eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
2280 offsetof(RGXFWIF_INIT, sRGXCompChecks) +
2281 offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
2282 offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32LayoutVersion),
2283 sSWBVNC.ui32LayoutVersion,
2285 PDUMP_POLL_OPERATOR_EQUAL,
2286 PDUMP_FLAGS_CONTINUOUS);
2287 if (eError != PVRSRV_OK)
2289 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2293 PDUMPCOMMENT("Compatibility check: HW V max len and FW V max len");
2294 eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
2295 offsetof(RGXFWIF_INIT, sRGXCompChecks) +
2296 offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
2297 offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32VLenMax),
2298 sSWBVNC.ui32VLenMax,
2300 PDUMP_POLL_OPERATOR_EQUAL,
2301 PDUMP_FLAGS_CONTINUOUS);
2302 if (eError != PVRSRV_OK)
2304 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2308 if (ui32MaskBNC != 0)
2310 PDUMPIF("DISABLE_HWBNC_CHECK");
2311 PDUMPELSE("DISABLE_HWBNC_CHECK");
2312 PDUMPCOMMENT("Compatibility check: HW BNC and FW BNC");
2313 eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
2314 offsetof(RGXFWIF_INIT, sRGXCompChecks) +
2315 offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
2316 offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32BNC),
2319 PDUMP_POLL_OPERATOR_EQUAL,
2320 PDUMP_FLAGS_CONTINUOUS);
2321 if (eError != PVRSRV_OK)
2323 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2326 PDUMPFI("DISABLE_HWBNC_CHECK");
2331 PDUMPIF("DISABLE_HWV_CHECK");
2332 PDUMPELSE("DISABLE_HWV_CHECK");
2333 for (i = 0; i < sSWBVNC.ui32VLenMax; i += sizeof(IMG_UINT32))
2335 PDUMPCOMMENT("Compatibility check: HW V and FW V");
2336 eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
2337 offsetof(RGXFWIF_INIT, sRGXCompChecks) +
2338 offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
2339 offsetof(RGXFWIF_COMPCHECKS_BVNC, aszV) +
2341 *((IMG_UINT32 *)(sSWBVNC.aszV + i)),
2343 PDUMP_POLL_OPERATOR_EQUAL,
2344 PDUMP_FLAGS_CONTINUOUS);
2345 if (eError != PVRSRV_OK)
2347 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2351 PDUMPFI("DISABLE_HWV_CHECK");
2355 #if defined(TARGET_SILICON)
2356 if (psRGXFWInit == IMG_NULL)
2358 return PVRSRV_ERROR_INVALID_PARAMS;
2361 sHWBVNC = psRGXFWInit->sRGXCompChecks.sHWBVNC;
2363 sHWBVNC.ui32BNC &= ui32MaskBNC;
2364 sSWBVNC.ui32BNC &= ui32MaskBNC;
2368 sHWBVNC.aszV[0] = '\0';
2369 sSWBVNC.aszV[0] = '\0';
2372 RGX_BVNC_EQUAL(sSWBVNC, sHWBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
2374 #if defined(FIX_HW_BRN_42480)
2375 if (!bCompatibleAll && bCompatibleVersion)
2377 if ((RGX_BVNC_PACKED_EXTR_B(sSWBVNC) == 1) &&
2378 !(OSStringCompare(RGX_BVNC_PACKED_EXTR_V(sSWBVNC),"76")) &&
2379 (RGX_BVNC_PACKED_EXTR_N(sSWBVNC) == 4) &&
2380 (RGX_BVNC_PACKED_EXTR_C(sSWBVNC) == 6))
2382 if ((RGX_BVNC_PACKED_EXTR_B(sHWBVNC) == 1) &&
2383 !(OSStringCompare(RGX_BVNC_PACKED_EXTR_V(sHWBVNC),"69")) &&
2384 (RGX_BVNC_PACKED_EXTR_N(sHWBVNC) == 4) &&
2385 (RGX_BVNC_PACKED_EXTR_C(sHWBVNC) == 4))
2387 bCompatibleBNC = IMG_TRUE;
2388 bCompatibleLenMax = IMG_TRUE;
2389 bCompatibleV = IMG_TRUE;
2390 bCompatibleAll = IMG_TRUE;
2396 if (!bCompatibleAll)
2398 if (!bCompatibleVersion)
2400 PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of HW (%d) and FW (%d).",
2402 sHWBVNC.ui32LayoutVersion,
2403 sSWBVNC.ui32LayoutVersion));
2404 eError = PVRSRV_ERROR_BVNC_MISMATCH;
2408 if (!bCompatibleLenMax)
2410 PVR_LOG(("(FAIL) %s: Incompatible V maxlen of HW (%d) and FW (%d).",
2412 sHWBVNC.ui32VLenMax,
2413 sSWBVNC.ui32VLenMax));
2414 eError = PVRSRV_ERROR_BVNC_MISMATCH;
2418 if (!bCompatibleBNC)
2420 PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Incompatible HW BNC (%d._.%d.%d) and FW BNC (%d._.%d.%d).",
2421 RGX_BVNC_PACKED_EXTR_B(sHWBVNC),
2422 RGX_BVNC_PACKED_EXTR_N(sHWBVNC),
2423 RGX_BVNC_PACKED_EXTR_C(sHWBVNC),
2424 RGX_BVNC_PACKED_EXTR_B(sSWBVNC),
2425 RGX_BVNC_PACKED_EXTR_N(sSWBVNC),
2426 RGX_BVNC_PACKED_EXTR_C(sSWBVNC)));
2427 eError = PVRSRV_ERROR_BVNC_MISMATCH;
2433 PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Incompatible HW BVNC (%d.%s.%d.%d) and FW BVNC (%d.%s.%d.%d).",
2434 RGX_BVNC_PACKED_EXTR_B(sHWBVNC),
2435 RGX_BVNC_PACKED_EXTR_V(sHWBVNC),
2436 RGX_BVNC_PACKED_EXTR_N(sHWBVNC),
2437 RGX_BVNC_PACKED_EXTR_C(sHWBVNC),
2438 RGX_BVNC_PACKED_EXTR_B(sSWBVNC),
2439 RGX_BVNC_PACKED_EXTR_V(sSWBVNC),
2440 RGX_BVNC_PACKED_EXTR_N(sSWBVNC),
2441 RGX_BVNC_PACKED_EXTR_C(sSWBVNC)));
2442 eError = PVRSRV_ERROR_BVNC_MISMATCH;
2448 PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: HW BVNC (%d.%s.%d.%d) and FW BVNC (%d.%s.%d.%d) match. [ OK ]",
2449 RGX_BVNC_PACKED_EXTR_B(sHWBVNC),
2450 RGX_BVNC_PACKED_EXTR_V(sHWBVNC),
2451 RGX_BVNC_PACKED_EXTR_N(sHWBVNC),
2452 RGX_BVNC_PACKED_EXTR_C(sHWBVNC),
2453 RGX_BVNC_PACKED_EXTR_B(sSWBVNC),
2454 RGX_BVNC_PACKED_EXTR_V(sSWBVNC),
2455 RGX_BVNC_PACKED_EXTR_N(sSWBVNC),
2456 RGX_BVNC_PACKED_EXTR_C(sSWBVNC)));
2464 *******************************************************************************
2466 @Function RGXDevInitCompatCheck_METACoreVersion_AgainstDriver
2470 Validate HW META version against driver META version
2472 @Input psDevInfo - device info
2473 @Input psRGXFWInit - FW init data
2475 @Return PVRSRV_ERROR - depending on mismatch found
2477 ******************************************************************************/
2479 static PVRSRV_ERROR RGXDevInitCompatCheck_METACoreVersion_AgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
2480 RGXFWIF_INIT *psRGXFWInit)
2482 #if defined(PDUMP)||(!defined(NO_HARDWARE))
2483 PVRSRV_ERROR eError;
2487 PDUMPIF("DISABLE_HWMETA_CHECK");
2488 PDUMPELSE("DISABLE_HWMETA_CHECK");
2489 PDUMPCOMMENT("Compatibility check: KM driver and HW META version");
2490 eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
2491 offsetof(RGXFWIF_INIT, sRGXCompChecks) +
2492 offsetof(RGXFWIF_COMPCHECKS, ui32METAVersion),
2493 RGX_CR_META_CORE_ID_VALUE,
2495 PDUMP_POLL_OPERATOR_EQUAL,
2496 PDUMP_FLAGS_CONTINUOUS);
2497 if (eError != PVRSRV_OK)
2499 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2502 PDUMPFI("DISABLE_HWMETA_CHECK");
2505 #if !defined(NO_HARDWARE)
2506 if (psRGXFWInit == IMG_NULL)
2507 return PVRSRV_ERROR_INVALID_PARAMS;
2509 if (psRGXFWInit->sRGXCompChecks.ui32METAVersion != RGX_CR_META_CORE_ID_VALUE)
2511 PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Incompatible driver META version (%d) / HW META version (%d).",
2512 RGX_CR_META_CORE_ID_VALUE, psRGXFWInit->sRGXCompChecks.ui32METAVersion));
2513 eError = PVRSRV_ERROR_META_MISMATCH;
2519 PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: driver META version (%d) and HW META version (%d) match. [ OK ]",
2520 RGX_CR_META_CORE_ID_VALUE, psRGXFWInit->sRGXCompChecks.ui32METAVersion));
2527 *******************************************************************************
2529 @Function RGXDevInitCompatCheck
2533 Check compatibility of host driver and firmware (DDK and build options)
2534 for RGX devices at services/device initialisation
2536 @Input psDeviceNode - device node
2538 @Return PVRSRV_ERROR - depending on mismatch found
2540 ******************************************************************************/
2541 static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32ClientBuildOptions)
2543 PVRSRV_ERROR eError;
2544 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
2545 RGXFWIF_INIT *psRGXFWInit = IMG_NULL;
2546 #if !defined(NO_HARDWARE)
2547 IMG_UINT32 ui32RegValue;
2550 /* Ensure it's a RGX device */
2551 if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_RGX)
2553 PVR_LOG(("(FAIL) %s: Device not of type RGX", __FUNCTION__));
2554 eError = PVRSRV_ERROR_INVALID_PARAMS;
2559 * Retrieve the FW information
2562 #if !defined(NO_HARDWARE)
2563 eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc,
2564 (IMG_VOID **)&psRGXFWInit);
2565 if (eError != PVRSRV_OK)
2567 PVR_DPF((PVR_DBG_ERROR,"%s: Failed to acquire kernel fw compatibility check info (%u)",
2568 __FUNCTION__, eError));
2572 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
2574 if(*((volatile IMG_BOOL *)&psRGXFWInit->sRGXCompChecks.bUpdated))
2576 /* No need to wait if the FW has already updated the values */
2579 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
2580 } END_LOOP_UNTIL_TIMEOUT();
2583 eError = RGXReadMETAReg(psDevInfo, META_CR_T0ENABLE_OFFSET, &ui32RegValue);
2585 if (eError != PVRSRV_OK)
2587 PVR_LOG(("%s: Reading RGX META register failed. Is the GPU correctly powered up? (%u)",
2588 __FUNCTION__, eError));
2592 if (!(ui32RegValue & META_CR_TXENABLE_ENABLE_BIT))
2594 eError = PVRSRV_ERROR_META_THREAD0_NOT_ENABLED;
2595 PVR_DPF((PVR_DBG_ERROR,"%s: RGX META is not running. Is the GPU correctly powered up? %d (%u)",
2596 __FUNCTION__, psRGXFWInit->sRGXCompChecks.bUpdated, eError));
2600 if (!*((volatile IMG_BOOL *)&psRGXFWInit->sRGXCompChecks.bUpdated))
2602 eError = PVRSRV_ERROR_TIMEOUT;
2603 PVR_DPF((PVR_DBG_ERROR,"%s: Missing compatibility info from FW (%u)",
2604 __FUNCTION__, eError));
2609 eError = RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver(psRGXFWInit);
2610 if (eError != PVRSRV_OK)
2615 eError = RGXDevInitCompatCheck_BuildOptions_FWAgainstClient(psDevInfo, psRGXFWInit, ui32ClientBuildOptions);
2616 if (eError != PVRSRV_OK)
2621 eError = RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver(psDevInfo, psRGXFWInit);
2622 if (eError != PVRSRV_OK)
2627 eError = RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver(psDevInfo, psRGXFWInit);
2628 if (eError != PVRSRV_OK)
2633 eError = RGXDevInitCompatCheck_BVNC_FWAgainstDriver(psDevInfo, psRGXFWInit);
2634 if (eError != PVRSRV_OK)
2639 eError = RGXDevInitCompatCheck_BVNC_HWAgainstDriver(psDevInfo, psRGXFWInit);
2640 if (eError != PVRSRV_OK)
2645 eError = RGXDevInitCompatCheck_METACoreVersion_AgainstDriver(psDevInfo, psRGXFWInit);
2646 if (eError != PVRSRV_OK)
2653 #if !defined(NO_HARDWARE)
2654 DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
2659 #define MAKESTRING(x) #x
2660 #define TOSTRING(x) MAKESTRING(x)
2668 IMG_CHAR *pcFWImgDestAddr,
2669 IMG_CHAR *pcFWImgSrcAddr,
2670 IMG_SIZE_T uiFWImgLen,
2671 IMG_CHAR *pcFWImgSigAddr,
2672 IMG_UINT64 ui64FWSigLen)
2675 if(OSMemCmp(pcFWImgDestAddr, pcFWImgSrcAddr, uiFWImgLen) != 0)
2677 return PVRSRV_ERROR_INIT_TDMETACODE_PAGES_FAIL;
2680 PVR_UNREFERENCED_PARAMETER(pcFWImgSigAddr);
2681 PVR_UNREFERENCED_PARAMETER(ui64FWSigLen);
2683 PVR_UNREFERENCED_PARAMETER(pcFWImgDestAddr);
2684 PVR_UNREFERENCED_PARAMETER(uiFWImgLen);
2685 PVR_UNREFERENCED_PARAMETER(pcFWImgSigAddr);
2686 PVR_UNREFERENCED_PARAMETER(ui64FWSigLen);
2693 PMRCopy(PMR *psDstPMR, PMR *psSrcPMR, IMG_SIZE_T uiMaxCopyLen)
2695 IMG_CHAR acBuf[512];
2696 IMG_UINT64 uiBytesCopied;
2697 PVRSRV_ERROR eStatus;
2700 while(uiBytesCopied < uiMaxCopyLen)
2702 IMG_SIZE_T uiRead, uiWritten;
2703 IMG_SIZE_T uiCopyAmt;
2704 uiCopyAmt = sizeof(acBuf) > uiMaxCopyLen ? uiMaxCopyLen : sizeof(acBuf);
2705 eStatus = PMR_ReadBytes(psSrcPMR,
2710 if(eStatus != PVRSRV_OK)
2714 eStatus = PMR_WriteBytes(psDstPMR,
2719 if(eStatus != PVRSRV_OK)
2723 PVR_ASSERT(uiRead == uiWritten);
2724 PVR_ASSERT(uiRead == uiCopyAmt);
2725 uiBytesCopied += uiCopyAmt;
2731 IMG_EXPORT PVRSRV_ERROR
2732 PVRSRVRGXInitLoadFWImageKM(
2733 PMR *psFWImgDestPMR,
2735 IMG_UINT64 ui64FWImgLen,
2737 IMG_UINT64 ui64FWSigLen)
2739 IMG_CHAR *pcFWImgSigAddr, *pcFWImgDestAddr, *pcFWImgSrcAddr;
2740 IMG_HANDLE hFWImgSigHdl, hFWImgDestHdl, hFWImgSrcHdl;
2742 PVRSRV_ERROR eStatus;
2744 /* The purpose of this function is to do the following:
2745 - copy the data contained in psFWImgSrcPMR into psFWImgDestPMR
2746 - use the data contained in psFWImgSigPMR to validate the contents of psFWImgDestPMR
2748 This is a functional placeholder that is meant to be overridden when actually using
2749 the protected META code feature. As a result, normally, the memory backed by
2750 psFWImgDestPMR will not be read/writeable from this layer. Thus the operation of
2751 actually doing the copy and verify must be handled in a mode with more privilege,
2752 typically a hypervisor.
2754 Because psFWImgSrcPMR and psFWImgSigPMR are normal OS-memory controlled PMR's, it
2755 should be sufficient to acquire their kernel mappings and pass the pointers to
2756 their mapped addressed into the hypervisor. However, since psFWImgDestPMR references
2757 a region of memory that would typically be allocated (and writeable) by a hypervisor,
2758 it will be necessary to pass the psFWImgDestPMR->pvFlavourData (or a field contained
2759 within it) to the hypervisor to identify the region of memory to copy to and validate.
2761 In the example function provided below, the following things happen:
2762 - kernel mappings are acquired for the destination and signature PMRs
2763 - a copy is done using the PMR_ReadBytes / PMR_WriteBytes callback functionality in
2765 - a validation is done by reading back the destination buffer and comparing it against
2768 c.f. a real implementation, where the following things would likely happen:
2769 - kernel mappings are acquired for the source and signature PMRs
2770 - the source/signature mapped addresses and lengths, and psFWImgDestPMR->pvFlavourData
2771 are passed into the hypervisor to do the copy/validate.
2774 eStatus = PMRAcquireKernelMappingData(psFWImgDestPMR,
2777 (IMG_VOID **) &pcFWImgDestAddr,
2780 if(eStatus != PVRSRV_OK)
2782 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Acquire mapping for dest failed (%u)", eStatus));
2785 if(ui64FWImgLen > uiLen)
2787 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: PMR dst len (%llu) > mapped len (%llu)",
2788 ui64FWImgLen, (unsigned long long)uiLen));
2792 eStatus = PMRAcquireKernelMappingData(psFWImgSrcPMR,
2795 (IMG_VOID **) &pcFWImgSrcAddr,
2798 if(eStatus != PVRSRV_OK)
2800 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Acquire mapping for src failed (%u)", eStatus));
2803 if(ui64FWImgLen > uiLen)
2805 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: PMR dst len (%llu) > mapped len (%llu)",
2806 ui64FWImgLen, (unsigned long long)uiLen));
2810 eStatus = PMRAcquireKernelMappingData(psFWImgSigPMR,
2813 (IMG_VOID **) &pcFWImgSigAddr,
2816 if(eStatus != PVRSRV_OK)
2818 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Acquire mapping for sig failed (%u)", eStatus));
2821 if(ui64FWSigLen > uiLen)
2823 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: sig len (%llu) > mapped len (%llu)",
2824 ui64FWSigLen, (unsigned long long)uiLen));
2828 /* Copy the firmware image from the intermediate buffer to the real firmware memory allocation. */
2829 PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVDebugMiscInitFWImageKM: copying %llu bytes from PMR %p to PMR %p",
2830 ui64FWImgLen, psFWImgSrcPMR, psFWImgDestPMR));
2831 PMRCopy(psFWImgDestPMR, psFWImgSrcPMR, TRUNCATE_64BITS_TO_SIZE_T(ui64FWImgLen));
2833 /* validate the firmware image after it has been copied into place */
2834 eStatus = ValidateFWImage(pcFWImgDestAddr, pcFWImgSrcAddr, TRUNCATE_64BITS_TO_SIZE_T(ui64FWImgLen), pcFWImgSigAddr, ui64FWSigLen);
2835 if(eStatus != PVRSRV_OK)
2837 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Signature check failed"));
2841 eStatus = PMRReleaseKernelMappingData(psFWImgDestPMR,
2843 if(eStatus != PVRSRV_OK)
2845 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Release mapping for dest failed (%u)", eStatus));
2849 eStatus = PMRReleaseKernelMappingData(psFWImgSrcPMR,
2851 if(eStatus != PVRSRV_OK)
2853 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Release mapping for src failed (%u)", eStatus));
2857 eStatus = PMRReleaseKernelMappingData(psFWImgSigPMR,
2859 if(eStatus != PVRSRV_OK)
2861 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Release mapping for sig failed (%u)", eStatus));
2868 return PVRSRV_ERROR_INIT_TDMETACODE_PAGES_FAIL;
2873 /*************************************************************************/ /*!
2874 @Function RGXDevVersionString
2875 @Description Gets the version string for the given device node and returns
2876 a pointer to it in ppszVersionString. It is then the
2877 responsibility of the caller to free this memory.
2878 @Input psDeviceNode Device node from which to obtain the
2880 @Output ppszVersionString Contains the version string upon return
2881 @Return PVRSRV_ERROR
2882 */ /**************************************************************************/
2883 static PVRSRV_ERROR RGXDevVersionString(PVRSRV_DEVICE_NODE *psDeviceNode,
2884 IMG_CHAR **ppszVersionString)
2886 #if defined(COMPAT_BVNC_MASK_B) || defined(COMPAT_BVNC_MASK_V) || defined(COMPAT_BVNC_MASK_N) || defined(COMPAT_BVNC_MASK_C) || defined(NO_HARDWARE) || defined(EMULATOR)
2887 IMG_CHAR pszFormatString[] = "Rogue Version: %d.%s.%d.%d (SW)";
2889 IMG_CHAR pszFormatString[] = "Rogue Version: %d.%s.%d.%d (HW)";
2891 IMG_SIZE_T uiStringLength;
2893 if (psDeviceNode == NULL || ppszVersionString == NULL)
2895 return PVRSRV_ERROR_INVALID_PARAMS;
2898 uiStringLength = OSStringLength(pszFormatString);
2899 uiStringLength += OSStringLength(TOSTRING(RGX_BVNC_KM_B));
2900 uiStringLength += OSStringLength(TOSTRING(RGX_BVNC_KM_V));
2901 uiStringLength += OSStringLength(TOSTRING(RGX_BVNC_KM_N));
2902 uiStringLength += OSStringLength(TOSTRING(RGX_BVNC_KM_C));
2904 *ppszVersionString = OSAllocZMem(uiStringLength * sizeof(IMG_CHAR));
2905 if (*ppszVersionString == NULL)
2907 return PVRSRV_ERROR_OUT_OF_MEMORY;
2910 OSSNPrintf(*ppszVersionString, uiStringLength, pszFormatString,
2911 RGX_BVNC_KM_B, TOSTRING(RGX_BVNC_KM_V), RGX_BVNC_KM_N, RGX_BVNC_KM_C);
2916 /**************************************************************************/ /*!
2917 @Function RGXDevClockSpeed
2918 @Description Gets the clock speed for the given device node and returns
2919 it in pui32RGXClockSpeed.
2920 @Input psDeviceNode Device node
2921 @Output pui32RGXClockSpeed Variable for storing the clock speed
2922 @Return PVRSRV_ERROR
2923 */ /***************************************************************************/
2924 static PVRSRV_ERROR RGXDevClockSpeed(PVRSRV_DEVICE_NODE *psDeviceNode,
2925 IMG_PUINT32 pui32RGXClockSpeed)
2927 RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
2929 /* get clock speed */
2930 *pui32RGXClockSpeed = psRGXData->psRGXTimingInfo->ui32CoreClockSpeed;
2936 /**************************************************************************/ /*!
2937 @Function RGXSoftReset
2938 @Description Resets some modules of the RGX device
2939 @Input psDeviceNode Device node
2940 @Output ui64ResetValue a mask for which each bit set correspond
2941 to a module to reset.
2942 @Return PVRSRV_ERROR
2943 */ /***************************************************************************/
2944 static PVRSRV_ERROR RGXSoftReset(PVRSRV_DEVICE_NODE *psDeviceNode,
2945 IMG_UINT64 ui64ResetValue)
2947 PVRSRV_RGXDEV_INFO *psDevInfo;
2949 PVR_ASSERT(psDeviceNode != NULL);
2950 PVR_ASSERT(psDeviceNode->pvDevice != NULL);
2952 if ((ui64ResetValue & RGX_CR_SOFT_RESET_MASKFULL) != ui64ResetValue)
2954 return PVRSRV_ERROR_INVALID_PARAMS;
2957 /* the device info */
2958 psDevInfo = psDeviceNode->pvDevice;
2960 /* Set in soft-reset */
2961 OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, ui64ResetValue);
2963 /* Read soft-reset to fence previos write in order to clear the SOCIF pipeline */
2964 (IMG_VOID) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET);
2970 /******************************************************************************
2971 End of file (rgxinit.c)
2972 ******************************************************************************/