7e8ffb19bc0ad7f6e03a7c2dcf8db81bd094ff35
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue / services / server / devices / rgx / rgxinit.c
1 /*************************************************************************/ /*!
2 @File
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
7
8 The contents of this file are subject to the MIT license as set out below.
9
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:
16
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
19
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.
23
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.
31
32 This License is also included in this distribution in the file called
33 "MIT-COPYING".
34
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 */ /**************************************************************************/
43
44 #include <stddef.h>
45
46 #include "pvrsrv.h"
47 #include "rgxheapconfig.h"
48 #include "rgxpower.h"
49
50 #include "rgxinit.h"
51
52 #include "pdump_km.h"
53 #include "handle.h"
54 #include "allocmem.h"
55 #include "devicemem_pdump.h"
56 #include "rgxmem.h"
57 #include "sync_internal.h"
58
59 #include "rgxutils.h"
60 #include "rgxfwutils.h"
61 #include "rgx_fwif_km.h"
62
63 #include "rgxmmuinit.h"
64 #include "devicemem_utils.h"
65 #include "devicemem_server.h"
66 #include "physmem_osmem.h"
67
68 #include "rgxdebug.h"
69 #include "rgxhwperf.h"
70
71 #include "rgx_options_km.h"
72 #include "pvrversion.h"
73
74 #include "rgx_compat_bvnc.h"
75
76 #include "rgx_heaps.h"
77
78 #include "rgxta3d.h"
79 #include "debug_request_ids.h"
80
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);
85
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)
92
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
101
102 #define VAR(x) #x
103
104
105 static IMG_BOOL g_bDevInit2Done = IMG_FALSE;
106
107
108 static IMG_VOID RGX_DeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo);
109
110 IMG_UINT32 g_ui32HostSampleIRQCount = 0;
111
112 #if !defined(NO_HARDWARE)
113
114 /*
115         RGX LISR Handler
116 */
117 static IMG_BOOL RGX_LISRHandler (IMG_VOID *pvData)
118 {
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;
124
125         psDeviceNode = pvData;
126         psDevConfig = psDeviceNode->psDevConfig;
127         psDevInfo = psDeviceNode->pvDevice;
128
129         if (psDevInfo->bIgnoreFurtherIRQs)
130         {
131                 return IMG_FALSE;
132         }
133
134         ui32IRQStatus = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVIRQSTATUS);
135
136         if (ui32IRQStatus & RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN)
137         {
138                 OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVIRQSTATUS, RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK);
139                 
140 #if defined(RGX_FEATURE_OCPBUS)
141                 OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_OCP_IRQSTATUS_2, RGX_CR_OCP_IRQSTATUS_2_RGX_IRQ_STATUS_EN);
142 #endif
143
144                 if (psDevConfig->pfnInterruptHandled)
145                 {
146                         psDevConfig->pfnInterruptHandled(psDevConfig);
147                 }
148
149                 bInterruptProcessed = IMG_TRUE;
150                 
151                 /* Sample the current count from the FW _after_ we've cleared the interrupt. */
152                 g_ui32HostSampleIRQCount = psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount;
153
154                 OSScheduleMISR(psDevInfo->pvMISRData);
155
156                 if (psDevInfo->pvAPMISRData != IMG_NULL)
157                 {
158                         OSScheduleMISR(psDevInfo->pvAPMISRData);
159                 }
160         }
161         return bInterruptProcessed;
162 }
163
164 static IMG_VOID RGXCheckFWActivePowerState(IMG_VOID *psDevice)
165 {
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;
170         
171         if (psFWTraceBuf->ePowState == RGXFWIF_POW_IDLE)
172         {
173                 /* The FW is IDLE and therefore could be shut down */
174                 eError = RGXActivePowerRequest(psDeviceNode);
175
176                 if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED))
177                 {
178                         PVR_DPF((PVR_DBG_WARNING,"RGXCheckFWActivePowerState: Failed RGXActivePowerRequest call (device index: %d) with %s", 
179                                                 psDeviceNode->sDevId.ui32DeviceIndex,
180                                                 PVRSRVGetErrorStringKM(eError)));
181                         
182                         PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, IMG_NULL);
183                 }
184         }
185
186 }
187
188 static RGXFWIF_GPU_UTIL_STATS RGXGetGpuUtilStats(PVRSRV_DEVICE_NODE *psDeviceNode)
189 {
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;
201         IMG_UINT32                              ui32Type;
202         IMG_UINT32                              ui32NextType;
203         
204         static RGXFWIF_GPU_UTIL_STATS   sPreviousStats;
205     static IMG_UINT32       ui32WarningTicks = 0;
206
207         /* init response */
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;
214
215         /* take the power lock as we might issue an OSReadHWReg64 below */
216 /*      eError = PVRSRVPowerLock();
217         if (eError != PVRSRV_OK)
218         {
219                 return sRet;
220         }*/
221
222         /* write offset is incremented after writing to FWCB, so subtract 1 */
223         ui32WOffSample = psUtilFWCb->ui32WriteOffset;
224         if(ui32WOffSample == 0)
225         {
226                 ui32WOffSample = RGXFWIF_GPU_UTIL_FWCB_SIZE;
227         }
228         ui32WOffSample--;
229         ui32WOffSampleSaved = ui32PrevWOffSample = ui32PriorWOffSample = ui32WOffSample;
230
231         PVRSRVGetDevicePowerState(psDeviceNode->sDevId.ui32DeviceIndex, &ePowerState);
232         if (ePowerState != PVRSRV_DEV_POWER_STATE_ON)   /* GPU powered off */
233         {
234                 ui64CurrentTimer = OSClockus64() & RGXFWIF_GPU_UTIL_FWCB_OS_TIMER_MASK;
235                 ui32NextType = RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_ON;
236         }
237         else                                                                                    /* GPU powered on */
238         {
239                 ui64CurrentTimer = RGXReadHWTimerReg(psDevInfo);
240                 ui32NextType = RGXFWIF_GPU_UTIL_FWCB_TYPE_CRTIME;
241         }
242         //PVRSRVPowerUnlock();
243
244         do
245         {
246                 IMG_UINT64      ui64FWCbEntryCurrent = psUtilFWCb->aui64CB[ui32WOffSample];
247
248                 if (ui64FWCbEntryCurrent != RGXFWIF_GPU_UTIL_FWCB_RESERVED)
249                 {
250                         IMG_UINT64 ui64Period = 0;
251
252                         ui32Type = RGXFWIF_GPU_UTIL_FWCB_ENTRY_TYPE(ui64FWCbEntryCurrent);
253
254                         switch(ui32Type)
255                         {
256                                 case RGXFWIF_GPU_UTIL_FWCB_TYPE_CRTIME:
257                                 {
258                                         IMG_UINT32 ui32DVFSHistClock =
259                                                         psDevInfo->psGpuDVFSHistory->aui32DVFSClockCB[RGXFWIF_GPU_UTIL_FWCB_ENTRY_ID(ui64FWCbEntryCurrent)];
260
261                                         if (ui32DVFSHistClock < 256)
262                                         {
263                                                 /* DVFS frequency is 0 in DVFS history entry, which means that
264                                                                 system layer doesn't define core clock frequency */
265                                                 ui32StatCumulative = 0;
266
267                                                 goto gpuutilstats_endloop;
268                                         }
269
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);
272
273                                         /* Scale the difference to microseconds */
274                                         ui64Period = OSDivide64((ui64Period * 1000000), (ui32DVFSHistClock / 256), &ui32Remainder);
275
276                                         /* Update "now" to CR Timer of current entry */
277                                         ui64CurrentTimer = RGXFWIF_GPU_UTIL_FWCB_ENTRY_CR_TIMER(ui64FWCbEntryCurrent);
278
279                                         break;
280                                 }
281
282                                 case RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_OFF:
283
284                                         /* Calculate the difference between OS timers at power-on/power-off transitions */
285                                         ui64Period = ui64CurrentTimer - RGXFWIF_GPU_UTIL_FWCB_ENTRY_OS_TIMER(ui64FWCbEntryCurrent);
286
287                                         break;
288
289                                 case RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_ON:
290                                 case RGXFWIF_GPU_UTIL_FWCB_TYPE_END_CRTIME:
291
292                                         /* Update "now" to the Timer of current entry */
293                                         if(ui32Type == RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_ON)
294                                         {
295                                                 ui64CurrentTimer = RGXFWIF_GPU_UTIL_FWCB_ENTRY_OS_TIMER(ui64FWCbEntryCurrent);
296                                         }
297                                         else
298                                         {
299                                                 ui64CurrentTimer = RGXFWIF_GPU_UTIL_FWCB_ENTRY_CR_TIMER(ui64FWCbEntryCurrent);
300                                         }
301
302                                         /* Move to next-previous state transition */
303                                         if(ui32WOffSample == 0)
304                                         {
305                                                 ui32WOffSample = RGXFWIF_GPU_UTIL_FWCB_SIZE;
306                                         }
307                                         ui32WOffSample--;
308
309                                         /* Remember the next-previous entry type */
310                                         ui32NextType = ui32Type;
311
312                                         continue;
313
314                                 default:
315                                         PVR_DPF((PVR_DBG_WARNING,"RGXGetGpuUtilStats: Wrong type: %8.8X\n", ui32Type));
316                                         break;
317                         }
318
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)
322                         {
323                                 ui64Period = RGXFWIF_GPU_STATS_WINDOW_SIZE_US - ui32StatCumulative;
324                         }
325                 
326                         /* Update cumulative time of state transition */
327                         ui32StatCumulative += (IMG_UINT32)ui64Period;
328
329                         /* Update per-state cumulative times */
330                         switch (RGXFWIF_GPU_UTIL_FWCB_ENTRY_STATE(ui64FWCbEntryCurrent))
331                         {
332                                 case RGXFWIF_GPU_UTIL_FWCB_STATE_ACTIVE_LOW:
333                                         ui32StatActiveLow += (IMG_UINT32)ui64Period;
334                                         break;
335                                 case RGXFWIF_GPU_UTIL_FWCB_STATE_IDLE:
336                                         ui32StatIdle += (IMG_UINT32)ui64Period;
337                                         break;
338                                 case RGXFWIF_GPU_UTIL_FWCB_STATE_ACTIVE_HIGH:
339                                         ui32StatActiveHigh += (IMG_UINT32)ui64Period;
340                                         break;
341                                 case RGXFWIF_GPU_UTIL_FWCB_STATE_BLOCKED:
342                                         ui32StatBlocked += (IMG_UINT32)ui64Period;
343                                         break;
344                         }
345                 }
346                 else
347                 {
348                         /* current sample is reserved */
349                         break;
350                 }
351
352                 /* Move to next-previous state transition */
353                 ui32PriorWOffSample = ui32PrevWOffSample;
354                 ui32PrevWOffSample = ui32WOffSample;
355                 if(ui32WOffSample == 0)
356                 {
357                         ui32WOffSample = RGXFWIF_GPU_UTIL_FWCB_SIZE;
358                 }
359                 ui32WOffSample--;
360
361                 /* Remember the next-previous entry type */
362                 ui32NextType = ui32Type;
363
364                 ui32WOffSampleSaved = psUtilFWCb->ui32WriteOffset;
365         }
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));
372
373 gpuutilstats_endloop:
374
375         if (ui32StatCumulative)
376         {
377                 /* Update stats */
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;
383
384                 if(ui32StatCumulative < RGXFWIF_GPU_STATS_WINDOW_SIZE_US)
385                 {
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);
391
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;
397             
398             if((ui32WarningTicks % RGX_GPU_UTIL_STAT_WARNING_PERIOD) == 0)
399             {
400                 PVR_DPF((PVR_DBG_WARNING,"RGXGetGpuUtilStats: Time window shorter than expected, returned data may be inaccurate\n"));
401             }
402             ui32WarningTicks++;
403                 }
404
405                 sPreviousStats.ui32GpuStatActiveLow  = sRet.ui32GpuStatActiveLow;
406                 sPreviousStats.ui32GpuStatActiveHigh = sRet.ui32GpuStatActiveHigh;
407                 sPreviousStats.ui32GpuStatBlocked    = sRet.ui32GpuStatBlocked;
408                 sPreviousStats.ui32GpuStatIdle       = sRet.ui32GpuStatIdle;
409         }
410
411         return sRet;
412 }
413
414 /*
415         RGX MISR Handler
416 */
417 static IMG_VOID RGX_MISRHandler (IMG_VOID *pvData)
418 {
419         PVRSRV_DEVICE_NODE      *psDeviceNode = pvData;
420
421         /* Inform other services devices that we have finished an operation */
422         PVRSRVCheckStatus(psDeviceNode);
423
424         /* Give the HWPerf service a chance to transfer some data from the FW
425          * buffer to the host driver transport layer buffer.
426          */
427         RGXHWPerfDataStoreCB(psDeviceNode);
428
429         /* Process all firmware CCBs for pending commands */
430         RGXCheckFirmwareCCBs(psDeviceNode->pvDevice);
431 }
432 #endif
433
434
435 /*
436  * PVRSRVRGXInitDevPart2KM
437  */ 
438 IMG_EXPORT
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)
456 {
457         PVRSRV_ERROR                    eError;
458         PVRSRV_RGXDEV_INFO              *psDevInfo = psDeviceNode->pvDevice;
459         PVRSRV_DEV_POWER_STATE  eDefaultPowerState;
460         PVRSRV_DEVICE_CONFIG    *psDevConfig = psDeviceNode->psDevConfig;
461
462         PDUMPCOMMENT("RGX Initialisation Part 2");
463
464 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
465     psDevInfo->bEnableProcessStats=IMG_TRUE;
466 #else
467     psDevInfo->bEnableProcessStats=IMG_FALSE;
468 #endif
469
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;
477
478         /*
479          * Map RGX Registers
480          */
481 #if !defined(NO_HARDWARE)
482         psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psDevConfig->sRegsCpuPBase,
483                                                                                      psDevConfig->ui32RegsSize,
484                                                                                      0);
485
486         if (psDevInfo->pvRegsBaseKM == IMG_NULL)
487         {
488                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: Failed to create RGX register mapping\n"));
489                 return PVRSRV_ERROR_BAD_MAPPING;
490         }
491 #else
492         psDevInfo->pvRegsBaseKM = IMG_NULL;
493 #endif /* !NO_HARDWARE */
494
495         /* free the export cookies provided to srvinit */
496         DevmemUnexport(psDevInfo->psRGXFWCodeMemDesc, psFWCodeAllocServerExportCookie);
497         DevmemUnexport(psDevInfo->psRGXFWDataMemDesc, psFWDataAllocServerExportCookie);
498         if (DevmemIsValidExportCookie(psFWCorememAllocServerExportCookie))
499         {
500                 DevmemUnexport(psDevInfo->psRGXFWCorememMemDesc, psFWCorememAllocServerExportCookie);
501         }
502
503         /*
504          * Copy scripts
505          */
506         OSMemCopy(psDevInfo->psScripts->asInitCommands, psInitScript,
507                           RGX_MAX_INIT_COMMANDS * sizeof(*psInitScript));
508
509         OSMemCopy(psDevInfo->psScripts->asDbgCommands, psDbgScript,
510                           RGX_MAX_INIT_COMMANDS * sizeof(*psDbgScript));
511
512         OSMemCopy(psDevInfo->psScripts->asDbgBusCommands, psDbgBusScript,
513                           RGX_MAX_DBGBUS_COMMANDS * sizeof(*psDbgBusScript));
514
515         OSMemCopy(psDevInfo->psScripts->asDeinitCommands, psDeinitScript,
516                           RGX_MAX_DEINIT_COMMANDS * sizeof(*psDeinitScript));
517
518 #if defined(PDUMP)
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);
522 #endif
523
524
525         psDevInfo->ui32RegSize = psDevConfig->ui32RegsSize;
526         psDevInfo->sRegsPhysBase = psDevConfig->sRegsCpuPBase;
527
528         /* Initialise Device Flags */
529         psDevInfo->ui32DeviceFlags = 0;
530         if (ui32DeviceFlags & RGXKMIF_DEVICE_STATE_ZERO_FREELIST)
531         {
532                 psDevInfo->ui32DeviceFlags |= RGXKM_DEVICE_STATE_ZERO_FREELIST;
533         }
534
535         if (ui32DeviceFlags & RGXKMIF_DEVICE_STATE_DISABLE_DW_LOGGING_EN)
536         {
537                 psDevInfo->ui32DeviceFlags |= RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN;
538         }
539
540         #if defined(SUPPORT_GPUTRACE_EVENTS)
541         /* If built, always setup FTrace consumer thread. */
542         RGXHWPerfFTraceGPUInit(psDeviceNode->pvDevice);
543
544         RGXHWPerfFTraceGPUEventsEnabledSet((ui32DeviceFlags & RGXKMIF_DEVICE_STATE_FTRACE_EN) ? IMG_TRUE: IMG_FALSE);
545 #endif
546
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;
552
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;
558
559         /* Allocate DVFS History */
560         psDevInfo->psGpuDVFSHistory = OSAllocZMem(sizeof(*(psDevInfo->psGpuDVFSHistory)));
561         if (psDevInfo->psGpuDVFSHistory == IMG_NULL)
562         {
563                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: failed to allocate gpu dvfs history storage"));
564                 return PVRSRV_ERROR_OUT_OF_MEMORY;
565         }
566
567         /* Reset DVFS history */
568         psDevInfo->psGpuDVFSHistory->ui32CurrentDVFSId = 0;
569         psDevInfo->psGpuDVFSHistory->aui32DVFSClockCB[0] = 0;
570
571         /* Setup GPU Utilization stat update callback */
572 #if !defined(NO_HARDWARE)
573         psDevInfo->pfnGetGpuUtilStats = RGXGetGpuUtilStats;
574 #endif
575
576         eDefaultPowerState = PVRSRV_DEV_POWER_STATE_ON;
577
578         /* set-up the Active Power Mgmt callback */
579 #if !defined(NO_HARDWARE)
580         {
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);
585
586                 if (bEnableAPM)
587                 {
588                         eError = OSInstallMISR(&psDevInfo->pvAPMISRData, RGXCheckFWActivePowerState, psDeviceNode);
589                         if (eError != PVRSRV_OK)
590                         {
591                                 return eError;
592                         }
593
594                         /* Prevent the device being woken up before there is something to do. */
595                         eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
596                 }
597         }
598 #endif
599
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,
607                                                                                 eDefaultPowerState);
608         if (eError != PVRSRV_OK)
609         {
610                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: failed to register device with power manager"));
611                 return eError;
612         }
613
614 #if !defined(NO_HARDWARE)
615         eError = RGXInstallProcessQueuesMISR(&psDevInfo->hProcessQueuesMISR, psDeviceNode);
616         if (eError != PVRSRV_OK)
617         {
618                 if (psDevInfo->pvAPMISRData != IMG_NULL)
619                 {
620                         (IMG_VOID) OSUninstallMISR(psDevInfo->pvAPMISRData);
621                 }
622                 return eError;
623         }
624
625         /* Register the interrupt handlers */
626         eError = OSInstallMISR(&psDevInfo->pvMISRData,
627                                                                         RGX_MISRHandler, psDeviceNode);
628         if (eError != PVRSRV_OK)
629         {
630                 if (psDevInfo->pvAPMISRData != IMG_NULL)
631                 {
632                         (IMG_VOID) OSUninstallMISR(psDevInfo->pvAPMISRData);
633                 }
634                 (IMG_VOID) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
635                 return eError;
636         }
637
638         eError = OSInstallDeviceLISR(psDevConfig, &psDevInfo->pvLISRData,
639                                                                  RGX_LISRHandler, psDeviceNode);
640         if (eError != PVRSRV_OK)
641         {
642                 if (psDevInfo->pvAPMISRData != IMG_NULL)
643                 {
644                         (IMG_VOID) OSUninstallMISR(psDevInfo->pvAPMISRData);
645                 }
646                 (IMG_VOID) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
647                 (IMG_VOID) OSUninstallMISR(psDevInfo->pvMISRData);
648                 return eError;
649         }
650
651 #endif
652         g_bDevInit2Done = IMG_TRUE;
653
654         return PVRSRV_OK;
655 }
656
657 static
658 PVRSRV_ERROR RGXAllocateFWCodeRegion(PVRSRV_DEVICE_NODE *psDeviceNode,
659                                      IMG_DEVMEM_SIZE_T ui32FWCodeAllocSize,
660                                      IMG_UINT32 uiMemAllocFlags)
661 {
662         PVRSRV_ERROR eError;
663
664 #if ! defined(TDMETACODE)
665         PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
666
667         uiMemAllocFlags |= PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
668                            PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
669
670         PDUMPCOMMENT("Allocate and export code memory for fw");
671
672         eError = DevmemFwAllocateExportable(psDeviceNode,
673                                                                                 ui32FWCodeAllocSize,
674                                                                                 uiMemAllocFlags,
675                                                                                 "FirmwareCodeRegion",
676                                             &psDevInfo->psRGXFWCodeMemDesc);
677         if (eError != PVRSRV_OK)
678         {
679                 PVR_DPF((PVR_DBG_ERROR,"DevmemFwAllocateExportable failed (%u)",
680                                 eError));
681         }
682
683         return eError;
684
685 #else
686         PMR *psTDMetaCodePMR;
687         IMG_DEVMEM_SIZE_T uiMemDescSize;
688         IMG_DEV_VIRTADDR sTmpDevVAddr;
689         PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
690
691         PDUMPCOMMENT("Allocate TD META code memory for fw");
692
693         eError = PhysmemNewTDMetaCodePMR(psDeviceNode,
694                                          ui32FWCodeAllocSize,
695                                          12,
696                                          uiMemAllocFlags,
697                                          &psTDMetaCodePMR);
698         if(eError != PVRSRV_OK)
699         {
700                 goto PMRCreateError;
701         }
702
703         PDUMPCOMMENT("Import TD META code memory for fw");
704
705         /* NB: psTDMetaCodePMR refcount: 1 -> 2 */
706         eError = DevmemLocalImport(IMG_NULL, /* bridge handle not applicable here */
707                                    psTDMetaCodePMR,
708                                    uiMemAllocFlags,
709                                    &psDevInfo->psRGXFWCodeMemDesc,
710                                    &uiMemDescSize);
711         if(eError != PVRSRV_OK)
712         {
713                 goto ImportError;
714         }
715
716         eError = DevmemMapToDevice(psDevInfo->psRGXFWCodeMemDesc,
717                                                            psDevInfo->psFirmwareHeap,
718                                                            &sTmpDevVAddr);
719         if(eError != PVRSRV_OK)
720         {
721                 PVR_DPF((PVR_DBG_ERROR,"Failed to map TD META code PMR (%u)", eError));
722                 goto MapError;
723         }
724
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.
731
732            NB: i.e., psTDMetaCodePMR refcount: 2 -> 1
733         */
734         PMRUnimportPMR(psTDMetaCodePMR);
735
736         return eError;
737
738 MapError:
739         DevmemFree(psDevInfo->psRGXFWCodeMemDesc);
740
741 ImportError:
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);
746
747 PMRCreateError:
748
749         return eError;
750 #endif
751 }
752
753 IMG_EXPORT
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)
765 {
766         DEVMEM_FLAGS_T          uiMemAllocFlags;
767         PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
768         PVRSRV_ERROR        eError;
769
770         /* set up memory contexts */
771
772         /* Register callbacks for creation of device memory contexts */
773         psDeviceNode->pfnRegisterMemoryContext = RGXRegisterMemoryContext;
774         psDeviceNode->pfnUnregisterMemoryContext = RGXUnregisterMemoryContext;
775
776         /* Create the memory context for the firmware. */
777         eError = DevmemCreateContext(IMG_NULL, psDeviceNode,
778                                                                  DEVMEM_HEAPCFG_META,
779                                                                  &psDevInfo->psKernelDevmemCtx);
780         if (eError != PVRSRV_OK)
781         {
782                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitAllocFWImgMemKM: Failed DevmemCreateContext (%u)", eError));
783                 goto failed_to_create_ctx;
784         }
785         
786         eError = DevmemFindHeapByName(psDevInfo->psKernelDevmemCtx,
787                                                                   "Firmware", 
788                                                                   &psDevInfo->psFirmwareHeap);
789         if (eError != PVRSRV_OK)
790         {
791                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitAllocFWImgMemKM: Failed DevmemFindHeapByName (%u)", eError));
792                 goto failed_to_find_heap;
793         }
794
795         /* 
796          * Set up Allocation for FW code section 
797          */
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;
805
806
807         eError = RGXAllocateFWCodeRegion(psDeviceNode,
808                                      uiFWCodeLen,
809                                          uiMemAllocFlags);
810
811         if (eError != PVRSRV_OK)
812         {
813                 PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw code mem (%u)",
814                                 eError));
815                 goto failFWCodeMemDescAlloc;
816         }
817
818         eError = DevmemExport(psDevInfo->psRGXFWCodeMemDesc,
819                               &psDevInfo->sRGXFWCodeExportCookie);
820         if (eError != PVRSRV_OK)
821         {
822                 PVR_DPF((PVR_DBG_ERROR,"Failed to export fw code mem (%u)",
823                                 eError));
824                 goto failFWCodeMemDescExport;
825         }
826
827         eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc,
828                                           psFWCodeDevVAddrBase);
829         if (eError != PVRSRV_OK)
830         {
831                 PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw code mem (%u)",
832                                 eError));
833                 goto failFWCodeMemDescAqDevVirt;
834         }
835
836         /*
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).
839         */
840         PVR_ASSERT(psFWCodeDevVAddrBase->uiAddr == RGX_FIRMWARE_HEAP_BASE);
841
842         /* 
843          * Set up Allocation for FW data section 
844          */
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;
854
855         PDUMPCOMMENT("Allocate and export data memory for fw");
856
857         eError = DevmemFwAllocateExportable(psDeviceNode,
858                                                                                 uiFWDataLen,
859                                                                                 uiMemAllocFlags,
860                                                                                 "FirmwareDataRegion",
861                                             &psDevInfo->psRGXFWDataMemDesc);
862         if (eError != PVRSRV_OK)
863         {
864                 PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw data mem (%u)",
865                                 eError));
866                 goto failFWDataMemDescAlloc;
867         }
868
869         eError = DevmemExport(psDevInfo->psRGXFWDataMemDesc,
870                               &psDevInfo->sRGXFWDataExportCookie);
871         if (eError != PVRSRV_OK)
872         {
873                 PVR_DPF((PVR_DBG_ERROR,"Failed to export fw data mem (%u)",
874                                 eError));
875                 goto failFWDataMemDescExport;
876         }
877
878         eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWDataMemDesc,
879                                           psFWDataDevVAddrBase);
880         if (eError != PVRSRV_OK)
881         {
882                 PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw data mem (%u)",
883                                 eError));
884                 goto failFWDataMemDescAqDevVirt;
885         }
886
887         if (uiFWCorememLen != 0)
888         {
889                 /* 
890                  * Set up Allocation for FW coremem section 
891                  */
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;
901
902                 PDUMPCOMMENT("Allocate and export coremem memory for fw");
903
904                 eError = DevmemFwAllocateExportable(psDeviceNode,
905                                 uiFWCorememLen,
906                                 uiMemAllocFlags,
907                                 "FirmwareCorememRegion",
908                                 &psDevInfo->psRGXFWCorememMemDesc);
909                 if (eError != PVRSRV_OK)
910                 {
911                         PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw coremem mem, size: %lld, flags: %x (%u)",
912                                                 uiFWCorememLen, uiMemAllocFlags, eError));
913                         goto failFWCorememMemDescAlloc;
914                 }
915
916                 eError = DevmemExport(psDevInfo->psRGXFWCorememMemDesc,
917                                 &psDevInfo->sRGXFWCorememExportCookie);
918                 if (eError != PVRSRV_OK)
919                 {
920                         PVR_DPF((PVR_DBG_ERROR,"Failed to export fw coremem mem (%u)",
921                                                 eError));
922                         goto failFWCorememMemDescExport;
923                 }
924
925                 eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCorememMemDesc,
926                                 psFWCorememDevVAddrBase);
927                 if (eError != PVRSRV_OK)
928                 {
929                         PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw coremem mem (%u)",
930                                                 eError));
931                         goto failFWCorememMemDescAqDevVirt;
932                 }
933
934                 RGXSetFirmwareAddress(psFWCorememMetaVAddrBase,
935                                 psDevInfo->psRGXFWCorememMemDesc,
936                                 0, RFW_FWADDR_NOREF_FLAG);
937
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;
942 #endif
943
944         }
945
946         *ppsFWCodeAllocServerExportCookie = &psDevInfo->sRGXFWCodeExportCookie;
947         *ppsFWDataAllocServerExportCookie = &psDevInfo->sRGXFWDataExportCookie;
948         /* Set all output arguments to ensure safe use in Part2 initialisation */
949         *ppsFWCorememAllocServerExportCookie = &psDevInfo->sRGXFWCorememExportCookie;
950
951         return PVRSRV_OK;
952
953
954 failFWCorememMemDescAqDevVirt:
955
956         if (uiFWCorememLen != 0)
957         {
958                 DevmemUnexport(psDevInfo->psRGXFWCorememMemDesc, &psDevInfo->sRGXFWCorememExportCookie);
959         }
960 failFWCorememMemDescExport:
961
962         if (uiFWCorememLen != 0)
963         {
964                 DevmemFwFree(psDevInfo->psRGXFWCorememMemDesc);
965         }
966 failFWCorememMemDescAlloc:
967
968         DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWDataMemDesc);
969 failFWDataMemDescAqDevVirt:
970
971         DevmemUnexport(psDevInfo->psRGXFWDataMemDesc, &psDevInfo->sRGXFWDataExportCookie);
972 failFWDataMemDescExport:
973
974         DevmemFwFree(psDevInfo->psRGXFWDataMemDesc);
975 failFWDataMemDescAlloc:
976
977         DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
978 failFWCodeMemDescAqDevVirt:
979
980         DevmemUnexport(psDevInfo->psRGXFWCodeMemDesc, &psDevInfo->sRGXFWCodeExportCookie);
981 failFWCodeMemDescExport:
982
983         DevmemFwFree(psDevInfo->psRGXFWCodeMemDesc);
984 failFWCodeMemDescAlloc:
985
986 failed_to_find_heap:
987         /*
988          * Clear the mem context create callbacks before destroying the RGX firmware
989          * context to avoid a spurious callback.
990          */
991         psDeviceNode->pfnRegisterMemoryContext = IMG_NULL;
992         psDeviceNode->pfnUnregisterMemoryContext = IMG_NULL;
993         DevmemDestroyContext(psDevInfo->psKernelDevmemCtx);
994 failed_to_create_ctx:
995
996         return eError;
997 }
998
999 /*
1000  * PVRSRVRGXInitFirmwareKM
1001  */ 
1002 IMG_EXPORT
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)
1015 {
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;
1020
1021
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);
1024
1025         RGX_BVNC_EQUAL(sBVNC, *psClientBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
1026         
1027         if (!bCompatibleAll)
1028         {
1029                 if (!bCompatibleVersion)
1030                 {
1031                         PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of driver (%d) and client (%d).",
1032                                         __FUNCTION__, 
1033                                         sBVNC.ui32LayoutVersion, 
1034                                         psClientBVNC->ui32LayoutVersion));
1035                         eError = PVRSRV_ERROR_BVNC_MISMATCH;
1036                         PVR_DBG_BREAK;
1037                         goto failed_to_pass_compatibility_check;
1038                 }
1039
1040                 if (!bCompatibleLenMax)
1041                 {
1042                         PVR_LOG(("(FAIL) %s: Incompatible V maxlen of driver (%d) and client (%d).",
1043                                         __FUNCTION__, 
1044                                         sBVNC.ui32VLenMax, 
1045                                         psClientBVNC->ui32VLenMax));
1046                         eError = PVRSRV_ERROR_BVNC_MISMATCH;
1047                         PVR_DBG_BREAK;
1048                         goto failed_to_pass_compatibility_check;
1049                 }
1050
1051                 if (!bCompatibleBNC)
1052                 {
1053                         PVR_LOG(("(FAIL) %s: Incompatible driver BNC (%d._.%d.%d) / client BNC (%d._.%d.%d).",
1054                                         __FUNCTION__, 
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;
1062                         PVR_DBG_BREAK;
1063                         goto failed_to_pass_compatibility_check;
1064                 }
1065                 
1066                 if (!bCompatibleV)
1067                 {
1068                         PVR_LOG(("(FAIL) %s: Incompatible driver BVNC (%d.%s.%d.%d) / client BVNC (%d.%s.%d.%d).",
1069                                         __FUNCTION__, 
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;
1079                         PVR_DBG_BREAK;
1080                         goto failed_to_pass_compatibility_check;
1081                 }
1082         }
1083         else
1084         {
1085                 PVR_DPF((PVR_DBG_MESSAGE, "%s: COMPAT_TEST: driver BVNC (%d.%s.%d.%d) and client BVNC (%d.%s.%d.%d) match. [ OK ]",
1086                                 __FUNCTION__, 
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)));
1095         }
1096
1097         GetNumBifTilingHeapConfigs(&ui32NumBIFTilingConfigs);
1098         pui32BIFTilingXStrides = OSAllocMem(sizeof(IMG_UINT32) * ui32NumBIFTilingConfigs);
1099         if(pui32BIFTilingXStrides == IMG_NULL)
1100         {
1101                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1102                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: OSAllocMem failed (%u)", eError));
1103                 goto failed_BIF_tiling_alloc;
1104         }
1105         for(i = 0; i < ui32NumBIFTilingConfigs; i++)
1106         {
1107                 eError = GetBIFTilingHeapXStride(i+1, &pui32BIFTilingXStrides[i]);
1108                 if(eError != PVRSRV_OK)
1109                 {
1110                         PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: GetBIFTilingHeapXStride for heap %u failed (%u)",
1111                                  i + 1, eError));
1112                         goto failed_BIF_heap_init;
1113                 }
1114         }
1115
1116         eError = RGXSetupFirmware(psDeviceNode, 
1117                                                              bEnableSignatureChecks, 
1118                                                              ui32SignatureChecksBufSize,
1119                                                              ui32HWPerfFWBufSizeKB,
1120                                                              ui64HWPerfFilter,
1121                                                              ui32RGXFWAlignChecksSize,
1122                                                              pui32RGXFWAlignChecks,
1123                                                              ui32ConfigFlags,
1124                                                              ui32LogType,
1125                                                              ui32NumBIFTilingConfigs,
1126                                                              pui32BIFTilingXStrides,
1127                                                              ui32FilterFlags,
1128                                                              psRGXFwInit);
1129         if (eError != PVRSRV_OK)
1130         {
1131                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: RGXSetupFirmware failed (%u)", eError));
1132                 goto failed_init_firmware;
1133         }
1134
1135         OSFreeMem(pui32BIFTilingXStrides);
1136         return PVRSRV_OK;
1137
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);
1144         return eError;
1145 }
1146
1147
1148
1149
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)
1155 {
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);
1161
1162         psDevInfo = psDeviceNode->pvDevice;
1163
1164         /* Size and align are 'expanded' because we request an Exportalign allocation */
1165         DevmemExportalignAdjustSizeAndAlign(psDevInfo->psFirmwareHeap,
1166                                                                                 &uiUFOBlockSize,
1167                                                                                 &ui32UFOBlockAlign);
1168
1169         eError = DevmemFwAllocateExportable(psDeviceNode,
1170                                                                                 uiUFOBlockSize,
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,
1179                                                                                 "UFOBlock",
1180                                                                                 psMemDesc);
1181         if (eError != PVRSRV_OK)
1182         {
1183                 goto e0;
1184         }
1185
1186         DevmemPDumpLoadMem(*psMemDesc,
1187                                            0,
1188                                            uiUFOBlockSize,
1189                                            PDUMP_FLAGS_CONTINUOUS);
1190
1191         RGXSetFirmwareAddress(&pFirmwareAddr, *psMemDesc, 0, RFW_FWADDR_FLAG_NONE);
1192         *puiSyncPrimVAddr = pFirmwareAddr.ui32Addr;
1193         *puiSyncPrimBlockSize = TRUNCATE_64BITS_TO_32BITS(uiUFOBlockSize);
1194
1195         return PVRSRV_OK;
1196
1197         DevmemFwFree(*psMemDesc);
1198 e0:
1199         return eError;
1200 }
1201
1202 /* See device.h for function declaration */
1203 static IMG_VOID RGXFreeUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
1204                                                                 DEVMEM_MEMDESC *psMemDesc)
1205 {
1206         /*
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
1209                 the memory
1210         */
1211         if (PVRSRVSystemSnoopingOfDeviceCache())
1212         {
1213                 RGXFWIF_KCCB_CMD sFlushInvalCmd;
1214                 PVRSRV_ERROR eError;
1215
1216                 /* Schedule the SLC flush command ... */
1217 #if defined(PDUMP)
1218                 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
1219 #endif
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;
1224                 
1225                 eError = RGXSendCommandWithPowLock(psDeviceNode->pvDevice,
1226                                                                                         RGXFWIF_DM_GP,
1227                                                                                         &sFlushInvalCmd,
1228                                                                                         sizeof(sFlushInvalCmd),
1229                                                                                         IMG_TRUE);
1230                 if (eError != PVRSRV_OK)
1231                 {
1232                         PVR_DPF((PVR_DBG_ERROR,"RGXFreeUFOBlock: Failed to schedule SLC flush command with error (%u)", eError));
1233                 }
1234                 else
1235                 {
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)
1239                         {
1240                                 PVR_DPF((PVR_DBG_ERROR,"RGXFreeUFOBlock: SLC flush and invalidate aborted with error (%u)", eError));
1241                         }
1242                 }
1243         }
1244
1245         RGXUnsetFirmwareAddress(psMemDesc);
1246         DevmemFwFree(psMemDesc);
1247 }
1248
1249 /*
1250         DevDeInitRGX
1251 */
1252 PVRSRV_ERROR DevDeInitRGX (PVRSRV_DEVICE_NODE *psDeviceNode)
1253 {
1254         PVRSRV_RGXDEV_INFO                      *psDevInfo = (PVRSRV_RGXDEV_INFO*)psDeviceNode->pvDevice;
1255         PVRSRV_ERROR                            eError;
1256         DEVICE_MEMORY_INFO                  *psDevMemoryInfo;
1257
1258         if (!psDevInfo)
1259         {
1260                 /* Can happen if DevInitRGX failed */
1261                 PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Null DevInfo"));
1262                 return PVRSRV_OK;
1263         }
1264
1265         /* Unregister debug request notifiers first as they could depend on anything. */
1266         PVRSRVUnregisterDbgRequestNotify(psDeviceNode->hDbgReqNotify);
1267
1268         /* Cancel notifications to this device */
1269         PVRSRVUnregisterCmdCompleteNotify(psDeviceNode->hCmdCompNotify);
1270         psDeviceNode->hCmdCompNotify = IMG_NULL;
1271
1272         /*
1273          *  De-initialise in reverse order, so stage 2 init is undone first.
1274          */
1275         if (g_bDevInit2Done)
1276         {
1277                 g_bDevInit2Done = IMG_FALSE;
1278
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)
1284                 {
1285                         (IMG_VOID) OSUninstallMISR(psDevInfo->pvAPMISRData);
1286                 }
1287 #endif /* !NO_HARDWARE */
1288
1289                 /* Remove the device from the power manager */
1290                 eError = PVRSRVRemovePowerDevice(psDeviceNode->sDevId.ui32DeviceIndex);
1291                 if (eError != PVRSRV_OK)
1292                 {
1293                         return eError;
1294                 }
1295
1296                 /* Free DVFS History */
1297                 if (psDevInfo->psGpuDVFSHistory != IMG_NULL)
1298                 {
1299                         OSFreeMem(psDevInfo->psGpuDVFSHistory);
1300                         psDevInfo->psGpuDVFSHistory = IMG_NULL;
1301                 }
1302
1303                 /* De-init Freelists/ZBuffers... */
1304                 OSLockDestroy(psDevInfo->hLockFreeList);
1305                 OSLockDestroy(psDevInfo->hLockZSBuffer);
1306
1307                 /* De-init HWPerf Ftrace thread resources for the RGX device */
1308 #if defined(SUPPORT_GPUTRACE_EVENTS)
1309                 RGXHWPerfFTraceGPUDeInit(psDevInfo);
1310 #endif
1311
1312                 /* Unregister MMU related stuff */
1313                 eError = RGXMMUInit_Unregister(psDeviceNode);
1314                 if (eError != PVRSRV_OK)
1315                 {
1316                         PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Failed RGXMMUInit_Unregister (0x%x)", eError));
1317                         return eError;
1318                 }
1319
1320                 /* UnMap Regs */
1321                 if (psDevInfo->pvRegsBaseKM != IMG_NULL)
1322                 {
1323 #if !defined(NO_HARDWARE)
1324                         OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
1325                                                          psDevInfo->ui32RegSize,
1326                                                          0);
1327 #endif /* !NO_HARDWARE */
1328                         psDevInfo->pvRegsBaseKM = IMG_NULL;
1329                 }
1330         }
1331
1332 #if 0 /* not required at this time */
1333         if (psDevInfo->hTimer)
1334         {
1335                 eError = OSRemoveTimer(psDevInfo->hTimer);
1336                 if (eError != PVRSRV_OK)
1337                 {
1338                         PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Failed to remove timer"));
1339                         return  eError;
1340                 }
1341                 psDevInfo->hTimer = IMG_NULL;
1342         }
1343 #endif
1344
1345     psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
1346
1347         RGX_DeInitHeaps(psDevMemoryInfo);
1348
1349         if (DevmemIsValidExportCookie(&psDevInfo->sRGXFWCodeExportCookie))
1350         {
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);
1354         }
1355
1356         if (DevmemIsValidExportCookie(&psDevInfo->sRGXFWDataExportCookie))
1357         {
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);
1361         }
1362
1363         if (DevmemIsValidExportCookie(&psDevInfo->sRGXFWCorememExportCookie))
1364         {
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);
1368         }
1369
1370         /*
1371            Free the firmware allocations.
1372          */
1373         RGXFreeFirmware(psDevInfo);
1374
1375         /*
1376          * Clear the mem context create callbacks before destroying the RGX firmware
1377          * context to avoid a spurious callback.
1378          */
1379         psDeviceNode->pfnRegisterMemoryContext = IMG_NULL;
1380         psDeviceNode->pfnUnregisterMemoryContext = IMG_NULL;
1381
1382         if (psDevInfo->psKernelDevmemCtx)
1383         {
1384                 eError = DevmemDestroyContext(psDevInfo->psKernelDevmemCtx);
1385                 
1386                 PVR_ASSERT(eError == PVRSRV_OK);
1387         }
1388
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);
1395
1396         /* Free the init scripts. */
1397         OSFreeMem(psDevInfo->psScripts);
1398
1399         /* DeAllocate devinfo */
1400         OSFreeMem(psDevInfo);
1401
1402         psDeviceNode->pvDevice = IMG_NULL;
1403
1404         return PVRSRV_OK;
1405 }
1406
1407 /*!
1408 ******************************************************************************
1409  
1410  @Function      RGXDebugRequestNotify
1411
1412  @Description Dump the debug data for RGX
1413   
1414 ******************************************************************************/
1415 static IMG_VOID RGXDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDbgReqestHandle, IMG_UINT32 ui32VerbLevel)
1416 {
1417         PVRSRV_DEVICE_NODE *psDeviceNode = hDbgReqestHandle;
1418
1419         /* Only action the request if we've fully init'ed */
1420         if (g_bDevInit2Done)
1421         {
1422                 RGXDebugRequestProcess(g_pfnDumpDebugPrintf, psDeviceNode->pvDevice, ui32VerbLevel);
1423         }
1424 }
1425
1426 #if defined(PDUMP)
1427 static
1428 PVRSRV_ERROR RGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode)
1429 {
1430         PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)(psDeviceNode->pvDevice);
1431         IMG_UINT32                      ui32Idx;
1432
1433         for (ui32Idx = 0; ui32Idx < RGXFWIF_DM_MAX; ui32Idx++)
1434         {
1435                 psDevInfo->abDumpedKCCBCtlAlready[ui32Idx] = IMG_FALSE;
1436         }
1437
1438
1439         return PVRSRV_OK;
1440 }
1441 #endif /* PDUMP */
1442
1443
1444 static PVRSRV_ERROR RGX_InitHeaps(DEVICE_MEMORY_INFO *psNewMemoryInfo)
1445 {
1446     DEVMEM_HEAP_BLUEPRINT *psDeviceMemoryHeapCursor;
1447
1448     
1449         psNewMemoryInfo->psDeviceMemoryHeap = OSAllocMem(sizeof(DEVMEM_HEAP_BLUEPRINT) * RGX_MAX_HEAP_ID);
1450     if(psNewMemoryInfo->psDeviceMemoryHeap == IMG_NULL)
1451         {
1452                 PVR_DPF((PVR_DBG_ERROR,"RGXRegisterDevice : Failed to alloc memory for DEVMEM_HEAP_BLUEPRINT"));
1453                 goto e0;
1454         }
1455
1456         psDeviceMemoryHeapCursor = psNewMemoryInfo->psDeviceMemoryHeap;
1457
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();
1463
1464         psDeviceMemoryHeapCursor++;/* advance to the next heap */
1465
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();
1471
1472         psDeviceMemoryHeapCursor++;/* advance to the next heap */
1473         
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();
1479
1480         psDeviceMemoryHeapCursor++;/* advance to the next heap */
1481
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();
1487
1488         psDeviceMemoryHeapCursor++;/* advance to the next heap */
1489
1490         /************ Tiling Heaps ************/
1491         #define INIT_TILING_HEAP(N) \
1492         do { \
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++; \
1498         } while (0)
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
1504
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();
1510
1511         psDeviceMemoryHeapCursor++;/* advance to the next heap */
1512
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();
1518
1519         psDeviceMemoryHeapCursor++;/* advance to the next heap */
1520         
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();
1527
1528         psDeviceMemoryHeapCursor++;/* advance to the next heap */
1529 #endif
1530
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();
1536
1537         psDeviceMemoryHeapCursor++;/* advance to the next heap */
1538
1539         /* set the heap count */
1540         psNewMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeapCursor - psNewMemoryInfo->psDeviceMemoryHeap);
1541
1542         PVR_ASSERT(psNewMemoryInfo->ui32HeapCount <= RGX_MAX_HEAP_ID);
1543
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 */
1548
1549     psNewMemoryInfo->uiNumHeapConfigs = 2;
1550         psNewMemoryInfo->psDeviceMemoryHeapConfigArray = OSAllocMem(sizeof(DEVMEM_HEAP_CONFIG) * psNewMemoryInfo->uiNumHeapConfigs);
1551     if (psNewMemoryInfo->psDeviceMemoryHeapConfigArray == IMG_NULL)
1552         {
1553                 PVR_DPF((PVR_DBG_ERROR,"RGXRegisterDevice : Failed to alloc memory for DEVMEM_HEAP_CONFIG"));
1554                 goto e1;
1555         }
1556     
1557     psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].pszName = "Default Heap Configuration";
1558     psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].uiNumHeaps = psNewMemoryInfo->ui32HeapCount-1;
1559     psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].psHeapBlueprintArray = psNewMemoryInfo->psDeviceMemoryHeap;
1560
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;
1565 #else
1566     psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].uiNumHeaps = 1;
1567     psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].psHeapBlueprintArray = psDeviceMemoryHeapCursor-1;
1568 #endif
1569
1570         return PVRSRV_OK;
1571 e1:
1572         OSFreeMem(psNewMemoryInfo->psDeviceMemoryHeap);
1573 e0:
1574         return PVRSRV_ERROR_OUT_OF_MEMORY;
1575 }
1576
1577 static IMG_VOID RGX_DeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo)
1578 {
1579         OSFreeMem(psDevMemoryInfo->psDeviceMemoryHeapConfigArray);
1580         OSFreeMem(psDevMemoryInfo->psDeviceMemoryHeap);
1581 }
1582
1583
1584 /*
1585         RGXRegisterDevice
1586 */
1587 PVRSRV_ERROR RGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
1588 {
1589     PVRSRV_ERROR eError;
1590         DEVICE_MEMORY_INFO *psDevMemoryInfo;
1591         PVRSRV_RGXDEV_INFO      *psDevInfo;
1592
1593         /* pdump info about the core */
1594         PDUMPCOMMENT("RGX Version Information (KM): %s", RGX_BVNC_KM);
1595         
1596         #if defined(RGX_FEATURE_SYSTEM_CACHE)
1597         PDUMPCOMMENT("RGX System Level Cache is present");
1598         #endif /* RGX_FEATURE_SYSTEM_CACHE */
1599
1600         PDUMPCOMMENT("RGX Initialisation (Part 1)");
1601
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;
1608 #if defined(PDUMP)
1609         psDeviceNode->sDevId.pszPDumpRegName    = RGX_PDUMPREG_NAME;
1610         
1611         psDeviceNode->sDevId.pszPDumpDevName    = PhysHeapPDumpMemspaceName(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
1612         psDeviceNode->pfnPDumpInitDevice = &RGXResetPDump;
1613 #endif /* PDUMP */
1614
1615         psDeviceNode->eHealthStatus = PVRSRV_DEVICE_HEALTH_STATUS_OK;
1616
1617 #if defined(SUPPORT_MEMORY_TILING)
1618         psDeviceNode->pfnAllocMemTilingRange = RGX_AllocMemTilingRange;
1619         psDeviceNode->pfnFreeMemTilingRange = RGX_FreeMemTilingRange;
1620 #endif
1621
1622         /* Configure MMU specific stuff */
1623         RGXMMUInit_Register(psDeviceNode);
1624
1625         psDeviceNode->pfnMMUCacheInvalidate = RGXMMUCacheInvalidate;
1626
1627         psDeviceNode->pfnSLCCacheInvalidateRequest = RGXSLCCacheInvalidateRequest;
1628
1629         /* Register RGX to receive notifies when other devices complete some work */
1630         PVRSRVRegisterCmdCompleteNotify(&psDeviceNode->hCmdCompNotify, &RGXScheduleProcessQueuesKM, psDeviceNode);
1631
1632         psDeviceNode->pfnInitDeviceCompatCheck  = &RGXDevInitCompatCheck;
1633
1634         /* Register callbacks for creation of device memory contexts */
1635         psDeviceNode->pfnRegisterMemoryContext = RGXRegisterMemoryContext;
1636         psDeviceNode->pfnUnregisterMemoryContext = RGXUnregisterMemoryContext;
1637
1638         /* Register callbacks for Unified Fence Objects */
1639         psDeviceNode->pfnAllocUFOBlock = RGXAllocUFOBlock;
1640         psDeviceNode->pfnFreeUFOBlock = RGXFreeUFOBlock;
1641
1642         /* Register callback for dumping debug info */
1643         PVRSRVRegisterDbgRequestNotify(&psDeviceNode->hDbgReqNotify, &RGXDebugRequestNotify, DEBUG_REQUEST_RGX, psDeviceNode);
1644         
1645         /* Register callback for checking the device's health */
1646         psDeviceNode->pfnUpdateHealthStatus = RGXUpdateHealthStatus;
1647
1648         /* Register method to service the FW HWPerf buffer */
1649         psDeviceNode->pfnServiceHWPerf = RGXHWPerfDataStoreCB;
1650
1651         /* Register callback for getting the device version information string */
1652         psDeviceNode->pfnDeviceVersionString = RGXDevVersionString;
1653
1654         /* Register callback for getting the device clock speed */
1655         psDeviceNode->pfnDeviceClockSpeed = RGXDevClockSpeed;
1656
1657         /* Register callback for soft resetting some device modules */
1658         psDeviceNode->pfnSoftReset = RGXSoftReset;
1659
1660         /* Register callback for resetting the HWR logs */
1661         psDeviceNode->pfnResetHWRLogs = RGXResetHWRLogs;
1662
1663
1664         /*********************
1665          * Device info setup *
1666          *********************/
1667         /* Allocate device control block */
1668         psDevInfo = OSAllocMem(sizeof(*psDevInfo));
1669         if (psDevInfo == IMG_NULL)
1670         {
1671                 PVR_DPF((PVR_DBG_ERROR,"DevInitRGXPart1 : Failed to alloc memory for DevInfo"));
1672                 return (PVRSRV_ERROR_OUT_OF_MEMORY);
1673         }
1674         OSMemSet (psDevInfo, 0, sizeof(*psDevInfo));
1675
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
1678          * watchdog thread
1679          */
1680
1681         eError = OSWRLockCreate(&(psDevInfo->hRenderCtxListLock));
1682         if (eError != PVRSRV_OK)
1683         {
1684                 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create render context list lock", __func__));
1685                 goto e0;
1686         }
1687
1688         eError = OSWRLockCreate(&(psDevInfo->hComputeCtxListLock));
1689         if (eError != PVRSRV_OK)
1690         {
1691                 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create compute context list lock", __func__));
1692                 goto e1;
1693         }
1694
1695         eError = OSWRLockCreate(&(psDevInfo->hTransferCtxListLock));
1696         if (eError != PVRSRV_OK)
1697         {
1698                 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create transfer context list lock", __func__));
1699                 goto e2;
1700         }
1701
1702         eError = OSWRLockCreate(&(psDevInfo->hRaytraceCtxListLock));
1703         if (eError != PVRSRV_OK)
1704         {
1705                 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create raytrace context list lock", __func__));
1706                 goto e3;
1707         }
1708
1709         eError = OSWRLockCreate(&(psDevInfo->hMemoryCtxListLock));
1710         if (eError != PVRSRV_OK)
1711         {
1712                 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create memory context list lock", __func__));
1713                 goto e4;
1714         }
1715
1716         dllist_init(&(psDevInfo->sRenderCtxtListHead));
1717         dllist_init(&(psDevInfo->sComputeCtxtListHead));
1718         dllist_init(&(psDevInfo->sTransferCtxtListHead));
1719         dllist_init(&(psDevInfo->sRaytraceCtxtListHead));
1720
1721         dllist_init(&(psDevInfo->sCommonCtxtListHead));
1722         psDevInfo->ui32CommonCtxtCurrentID = 1;
1723
1724         psDeviceNode->pvDevice = psDevInfo;
1725         dllist_init(&psDevInfo->sMemoryContextList);
1726
1727         /* Allocate space for scripts. */
1728         psDevInfo->psScripts = OSAllocMem(sizeof(*psDevInfo->psScripts));
1729         if (!psDevInfo->psScripts)
1730         {
1731                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1732                 PVR_LOGG_IF_ERROR(PVRSRV_ERROR_OUT_OF_MEMORY, "OSAllocMem", e5);
1733         }
1734
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;
1739
1740         psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
1741         psDevMemoryInfo->ui32AddressSpaceSizeLog2 = RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS;
1742         psDevInfo->pvDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
1743
1744         /* flags, backing store details to be specified by system */
1745         psDevMemoryInfo->ui32Flags = 0;
1746
1747         eError = RGX_InitHeaps(psDevMemoryInfo);
1748         if (eError != PVRSRV_OK)
1749         {
1750                 PVR_LOGG_IF_ERROR(eError, "RGX_InitHeaps", e6);
1751         }
1752
1753         return PVRSRV_OK;
1754
1755 e6:
1756         OSFreeMem(psDevInfo->psScripts);
1757         psDevInfo->psScripts = NULL;
1758 e5:
1759         OSWRLockDestroy(psDevInfo->hMemoryCtxListLock);
1760 e4:
1761         OSWRLockDestroy(psDevInfo->hRaytraceCtxListLock);
1762 e3:
1763         OSWRLockDestroy(psDevInfo->hTransferCtxListLock);
1764 e2:
1765         OSWRLockDestroy(psDevInfo->hComputeCtxListLock);
1766 e1:
1767         OSWRLockDestroy(psDevInfo->hRenderCtxListLock);
1768 e0:
1769         psDeviceNode->pvDevice = NULL;
1770         OSFreeMem(psDevInfo);
1771         PVR_ASSERT(eError != PVRSRV_OK);
1772         return eError;
1773 }
1774
1775 /*!
1776 *******************************************************************************
1777
1778  @Function      RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver
1779
1780  @Description
1781
1782  Validate the FW build options against KM driver build options (KM build options only)
1783
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.
1787  
1788  This check is left for clarity in error messages if any incompatibility occurs.
1789
1790  @Input psRGXFWInit - FW init data
1791
1792  @Return   PVRSRV_ERROR - depending on mismatch found
1793
1794 ******************************************************************************/
1795 static PVRSRV_ERROR RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver(RGXFWIF_INIT *psRGXFWInit)
1796 {
1797 #if !defined(NO_HARDWARE)
1798         IMG_UINT32                      ui32BuildOptions, ui32BuildOptionsFWKMPart, ui32BuildOptionsMismatch;
1799
1800         if (psRGXFWInit == IMG_NULL)
1801                 return PVRSRV_ERROR_INVALID_PARAMS;
1802
1803         ui32BuildOptions = (RGX_BUILD_OPTIONS_KM);
1804
1805         ui32BuildOptionsFWKMPart = psRGXFWInit->sRGXCompChecks.ui32BuildOptions & RGX_BUILD_OPTIONS_MASK_KM;
1806         
1807         if (ui32BuildOptions != ui32BuildOptionsFWKMPart)
1808         {
1809                 ui32BuildOptionsMismatch = ui32BuildOptions ^ ui32BuildOptionsFWKMPart;
1810                 if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
1811                 {
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 ));
1815                 }
1816
1817                 if ( (ui32BuildOptionsFWKMPart & ui32BuildOptionsMismatch) != 0)
1818                 {
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 ));
1822                 }
1823                 return PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
1824         }
1825         else
1826         {
1827                 PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Firmware and KM driver build options match. [ OK ]"));
1828         }
1829 #endif
1830
1831         return PVRSRV_OK;
1832 }
1833
1834 /*!
1835 *******************************************************************************
1836
1837  @Function      RGXDevInitCompatCheck_BuildOptions_FWAgainstClient
1838
1839  @Description
1840
1841  Validate the FW build options against client build options (KM and non-KM)
1842
1843  @Input psDevInfo - device info
1844  @Input psRGXFWInit - FW init data
1845  @Input ui32ClientBuildOptions - client build options flags
1846
1847  @Return   PVRSRV_ERROR - depending on mismatch found
1848
1849 ******************************************************************************/
1850 static PVRSRV_ERROR RGXDevInitCompatCheck_BuildOptions_FWAgainstClient(PVRSRV_RGXDEV_INFO       *psDevInfo,
1851                                                                                                                                                         RGXFWIF_INIT *psRGXFWInit,
1852                                                                                                                                                         IMG_UINT32 ui32ClientBuildOptions)
1853 {
1854 #if !defined(NO_HARDWARE)
1855         IMG_UINT32                      ui32BuildOptionsMismatch;
1856         IMG_UINT32                      ui32BuildOptionsFW;
1857 #endif
1858 #if defined(PDUMP)
1859         PVRSRV_ERROR            eError;
1860 #endif
1861
1862 #if defined(PDUMP)
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,
1868                                                                                                 0xffffffff,
1869                                                                                                 PDUMP_POLL_OPERATOR_EQUAL,
1870                                                                                                 PDUMP_FLAGS_CONTINUOUS);
1871         if (eError != PVRSRV_OK)
1872         {
1873                 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
1874                 return eError;
1875         }
1876 #endif
1877
1878 #if !defined(NO_HARDWARE)
1879         if (psRGXFWInit == IMG_NULL)
1880                 return PVRSRV_ERROR_INVALID_PARAMS;
1881         
1882         ui32BuildOptionsFW = psRGXFWInit->sRGXCompChecks.ui32BuildOptions;
1883         
1884         if (ui32ClientBuildOptions != ui32BuildOptionsFW)
1885         {
1886                 ui32BuildOptionsMismatch = ui32ClientBuildOptions ^ ui32BuildOptionsFW;
1887                 if ( (ui32ClientBuildOptions & ui32BuildOptionsMismatch) != 0)
1888                 {
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 ));
1892                 }
1893
1894                 if ( (ui32BuildOptionsFW & ui32BuildOptionsMismatch) != 0)
1895                 {
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 ));
1899                 }
1900                 return PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
1901         }
1902         else
1903         {
1904                 PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Firmware and client build options match. [ OK ]"));
1905         }
1906 #endif
1907
1908         return PVRSRV_OK;
1909 }
1910
1911 /*!
1912 *******************************************************************************
1913
1914  @Function      RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver
1915
1916  @Description
1917
1918  Validate FW DDK version against driver DDK version
1919
1920  @Input psDevInfo - device info
1921  @Input psRGXFWInit - FW init data
1922
1923  @Return   PVRSRV_ERROR - depending on mismatch found
1924
1925 ******************************************************************************/
1926 static PVRSRV_ERROR RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
1927                                                                                                                                                         RGXFWIF_INIT *psRGXFWInit)
1928 {
1929 #if defined(PDUMP)||(!defined(NO_HARDWARE))
1930         IMG_UINT32                      ui32DDKVersion;
1931         PVRSRV_ERROR            eError;
1932         
1933         ui32DDKVersion = PVRVERSION_PACK(PVRVERSION_MAJ, PVRVERSION_MIN);
1934 #endif
1935
1936 #if defined(PDUMP)
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),
1941                                                                                                 ui32DDKVersion,
1942                                                                                                 0xffffffff,
1943                                                                                                 PDUMP_POLL_OPERATOR_EQUAL,
1944                                                                                                 PDUMP_FLAGS_CONTINUOUS);
1945         if (eError != PVRSRV_OK)
1946         {
1947                 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
1948                 return eError;
1949         }
1950 #endif
1951
1952 #if !defined(NO_HARDWARE)
1953         if (psRGXFWInit == IMG_NULL)
1954                 return PVRSRV_ERROR_INVALID_PARAMS;
1955
1956         if (psRGXFWInit->sRGXCompChecks.ui32DDKVersion != ui32DDKVersion)
1957         {
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;
1963                 PVR_DBG_BREAK;
1964                 return eError;
1965         }
1966         else
1967         {
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));
1971         }
1972 #endif  
1973
1974         return PVRSRV_OK;
1975 }
1976
1977 /*!
1978 *******************************************************************************
1979
1980  @Function      RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver
1981
1982  @Description
1983
1984  Validate FW DDK build against driver DDK build
1985
1986  @Input psDevInfo - device info
1987  @Input psRGXFWInit - FW init data
1988
1989  @Return   PVRSRV_ERROR - depending on mismatch found
1990
1991 ******************************************************************************/
1992 static PVRSRV_ERROR RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
1993                                                                                                                                                         RGXFWIF_INIT *psRGXFWInit)
1994 {
1995 #if defined(PDUMP)||(!defined(NO_HARDWARE))
1996         IMG_UINT32                      ui32DDKBuild;
1997         PVRSRV_ERROR            eError;
1998         
1999         ui32DDKBuild = PVRVERSION_BUILD;
2000 #endif
2001
2002 #if defined(PDUMP)
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),
2007                                                                                                 ui32DDKBuild,
2008                                                                                                 0xffffffff,
2009                                                                                                 PDUMP_POLL_OPERATOR_EQUAL,
2010                                                                                                 PDUMP_FLAGS_CONTINUOUS);
2011         if (eError != PVRSRV_OK)
2012         {
2013                 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2014                 return eError;
2015         }
2016 #endif
2017
2018 #if !defined(NO_HARDWARE)
2019         if (psRGXFWInit == IMG_NULL)
2020                 return PVRSRV_ERROR_INVALID_PARAMS;
2021
2022         if (psRGXFWInit->sRGXCompChecks.ui32DDKBuild != ui32DDKBuild)
2023         {
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;
2027                 PVR_DBG_BREAK;
2028                 return eError;
2029         }
2030         else
2031         {
2032                 PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: driver DDK build (%d) and Firmware DDK build (%d) match. [ OK ]",
2033                                 ui32DDKBuild, psRGXFWInit->sRGXCompChecks.ui32DDKBuild));
2034         }
2035 #endif
2036         return PVRSRV_OK;
2037 }
2038
2039 /*!
2040 *******************************************************************************
2041
2042  @Function      RGXDevInitCompatCheck_BVNC_FWAgainstDriver
2043
2044  @Description
2045
2046  Validate FW BVNC against driver BVNC
2047
2048  @Input psDevInfo - device info
2049  @Input psRGXFWInit - FW init data
2050
2051  @Return   PVRSRV_ERROR - depending on mismatch found
2052
2053 ******************************************************************************/
2054 static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_FWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
2055                                                                                                                                                         RGXFWIF_INIT *psRGXFWInit)
2056 {
2057 #if defined(PDUMP)
2058         IMG_UINT32                                      i;
2059 #endif
2060 #if !defined(NO_HARDWARE)
2061         IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV;
2062 #endif
2063 #if defined(PDUMP)||(!defined(NO_HARDWARE))
2064         RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sBVNC);
2065         PVRSRV_ERROR                            eError;
2066         
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);
2068 #endif
2069
2070 #if defined(PDUMP)
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,
2077                                                                                         0xffffffff,
2078                                                                                         PDUMP_POLL_OPERATOR_EQUAL,
2079                                                                                         PDUMP_FLAGS_CONTINUOUS);
2080         if (eError != PVRSRV_OK)
2081         {
2082                 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2083         }
2084
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),
2090                                                                                         sBVNC.ui32VLenMax,
2091                                                                                         0xffffffff,
2092                                                                                         PDUMP_POLL_OPERATOR_EQUAL,
2093                                                                                         PDUMP_FLAGS_CONTINUOUS);
2094         if (eError != PVRSRV_OK)
2095         {
2096                 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2097         }
2098
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),
2104                                                                                         sBVNC.ui32BNC,
2105                                                                                         0xffffffff,
2106                                                                                         PDUMP_POLL_OPERATOR_EQUAL,
2107                                                                                         PDUMP_FLAGS_CONTINUOUS);
2108         if (eError != PVRSRV_OK)
2109         {
2110                 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2111         }
2112
2113         for (i = 0; i < sBVNC.ui32VLenMax; i += sizeof(IMG_UINT32))
2114         {
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) + 
2120                                                                                                 i,
2121                                                                                                 *((IMG_UINT32 *)(sBVNC.aszV + i)),
2122                                                                                                 0xffffffff,
2123                                                                                                 PDUMP_POLL_OPERATOR_EQUAL,
2124                                                                                                 PDUMP_FLAGS_CONTINUOUS);
2125                 if (eError != PVRSRV_OK)
2126                 {
2127                         PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2128                 }
2129         }
2130 #endif
2131
2132 #if !defined(NO_HARDWARE)
2133         if (psRGXFWInit == IMG_NULL)
2134                 return PVRSRV_ERROR_INVALID_PARAMS;
2135
2136         RGX_BVNC_EQUAL(sBVNC, psRGXFWInit->sRGXCompChecks.sFWBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
2137         
2138         if (!bCompatibleAll)
2139         {
2140                 if (!bCompatibleVersion)
2141                 {
2142                         PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of driver (%d) and firmware (%d).",
2143                                         __FUNCTION__, 
2144                                         sBVNC.ui32LayoutVersion, 
2145                                         psRGXFWInit->sRGXCompChecks.sFWBVNC.ui32LayoutVersion));
2146                         eError = PVRSRV_ERROR_BVNC_MISMATCH;
2147                         return eError;
2148                 }
2149
2150                 if (!bCompatibleLenMax)
2151                 {
2152                         PVR_LOG(("(FAIL) %s: Incompatible V maxlen of driver (%d) and firmware (%d).",
2153                                         __FUNCTION__, 
2154                                         sBVNC.ui32VLenMax, 
2155                                         psRGXFWInit->sRGXCompChecks.sFWBVNC.ui32VLenMax));
2156                         eError = PVRSRV_ERROR_BVNC_MISMATCH;
2157                         return eError;
2158                 }
2159
2160                 if (!bCompatibleBNC)
2161                 {
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;
2170                         return eError;
2171                 }
2172                 
2173                 if (!bCompatibleV)
2174                 {
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;
2185                         return eError;
2186                 }
2187         }
2188         else
2189         {
2190                 PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Firmware BVNC and KM driver BNVC match. [ OK ]"));
2191         }
2192 #endif
2193         return PVRSRV_OK;
2194 }
2195
2196 /*!
2197 *******************************************************************************
2198
2199  @Function      RGXDevInitCompatCheck_BVNC_HWAgainstDriver
2200
2201  @Description
2202
2203  Validate HW BVNC against driver BVNC
2204
2205  @Input psDevInfo - device info
2206  @Input psRGXFWInit - FW init data
2207
2208  @Return   PVRSRV_ERROR - depending on mismatch found
2209
2210 ******************************************************************************/
2211 #if ((!defined(NO_HARDWARE))&&(!defined(EMULATOR)))
2212 #define TARGET_SILICON  /* definition for everything that is not emu and not nohw configuration */
2213 #endif
2214
2215 #if defined(FIX_HW_BRN_38835)
2216 #define COMPAT_BVNC_MASK_B
2217 #define COMPAT_BVNC_MASK_V
2218 #endif
2219
2220 static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_HWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
2221                                                                                                                                         RGXFWIF_INIT *psRGXFWInit)
2222 {
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;
2227
2228         IMG_UINT32 bMaskV = IMG_FALSE;
2229
2230         PVRSRV_ERROR                            eError;
2231         RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sSWBVNC);
2232 #endif
2233
2234 #if defined(TARGET_SILICON)
2235         RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sHWBVNC);
2236         IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV;
2237 #endif
2238
2239 #if defined(PDUMP) || defined(TARGET_SILICON)
2240
2241 #if defined(COMPAT_BVNC_MASK_B)
2242         ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_B;
2243 #endif
2244 #if defined(COMPAT_BVNC_MASK_V)
2245         bMaskV = IMG_TRUE;
2246 #endif
2247 #if defined(COMPAT_BVNC_MASK_N)
2248         ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_N;
2249 #endif
2250 #if defined(COMPAT_BVNC_MASK_C)
2251         ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_C;
2252 #endif
2253         
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);
2255
2256 #if defined(FIX_HW_BRN_38344)
2257         if (RGX_BVNC_KM_C >= 10)
2258         {
2259                 ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_C;
2260         }
2261 #endif
2262
2263         if ((ui32MaskBNC != (RGX_BVNC_PACK_MASK_B | RGX_BVNC_PACK_MASK_N | RGX_BVNC_PACK_MASK_C)) || bMaskV)
2264         {
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"):(""))));
2270         }
2271 #endif
2272
2273 #if defined(EMULATOR)
2274         PVR_LOG(("Compatibility checks for emu target: Ignoring HW BVNC checks."));
2275 #endif
2276
2277 #if defined(PDUMP)
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,
2284                                                                                         0xffffffff,
2285                                                                                         PDUMP_POLL_OPERATOR_EQUAL,
2286                                                                                         PDUMP_FLAGS_CONTINUOUS);
2287         if (eError != PVRSRV_OK)
2288         {
2289                 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2290                 return eError;
2291         }
2292
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,
2299                                                                                         0xffffffff,
2300                                                                                         PDUMP_POLL_OPERATOR_EQUAL,
2301                                                                                         PDUMP_FLAGS_CONTINUOUS);
2302         if (eError != PVRSRV_OK)
2303         {
2304                 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2305                 return eError;
2306         }
2307
2308         if (ui32MaskBNC != 0)
2309         {
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),
2317                                                                                                 sSWBVNC.ui32BNC,
2318                                                                                                 ui32MaskBNC,
2319                                                                                                 PDUMP_POLL_OPERATOR_EQUAL,
2320                                                                                                 PDUMP_FLAGS_CONTINUOUS);
2321                 if (eError != PVRSRV_OK)
2322                 {
2323                         PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2324                         return eError;
2325                 }
2326                 PDUMPFI("DISABLE_HWBNC_CHECK");
2327         }
2328         if (!bMaskV)
2329         {
2330                 IMG_UINT32 i;
2331                 PDUMPIF("DISABLE_HWV_CHECK");
2332                 PDUMPELSE("DISABLE_HWV_CHECK");
2333                 for (i = 0; i < sSWBVNC.ui32VLenMax; i += sizeof(IMG_UINT32))
2334                 {
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) + 
2340                                                                                                 i,
2341                                                                                                 *((IMG_UINT32 *)(sSWBVNC.aszV + i)),
2342                                                                                                 0xffffffff,
2343                                                                                                 PDUMP_POLL_OPERATOR_EQUAL,
2344                                                                                                 PDUMP_FLAGS_CONTINUOUS);
2345                         if (eError != PVRSRV_OK)
2346                         {
2347                                 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2348                                 return eError;
2349                         }
2350                 }
2351                 PDUMPFI("DISABLE_HWV_CHECK");
2352         }
2353 #endif
2354
2355 #if defined(TARGET_SILICON)
2356         if (psRGXFWInit == IMG_NULL)
2357         {
2358                 return PVRSRV_ERROR_INVALID_PARAMS;
2359         }
2360         
2361         sHWBVNC = psRGXFWInit->sRGXCompChecks.sHWBVNC;
2362
2363         sHWBVNC.ui32BNC &= ui32MaskBNC;
2364         sSWBVNC.ui32BNC &= ui32MaskBNC;
2365
2366         if (bMaskV)
2367         {
2368                 sHWBVNC.aszV[0] = '\0';
2369                 sSWBVNC.aszV[0] = '\0';
2370         }
2371
2372         RGX_BVNC_EQUAL(sSWBVNC, sHWBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
2373
2374 #if defined(FIX_HW_BRN_42480)
2375         if (!bCompatibleAll && bCompatibleVersion)
2376         {
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))
2381                 {
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))
2386                         {
2387                                 bCompatibleBNC = IMG_TRUE;
2388                                 bCompatibleLenMax = IMG_TRUE;
2389                                 bCompatibleV = IMG_TRUE;
2390                                 bCompatibleAll = IMG_TRUE;
2391                         }
2392                 }
2393         }
2394 #endif
2395
2396         if (!bCompatibleAll)
2397         {
2398                 if (!bCompatibleVersion)
2399                 {
2400                         PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of HW (%d) and FW (%d).",
2401                                         __FUNCTION__, 
2402                                         sHWBVNC.ui32LayoutVersion, 
2403                                         sSWBVNC.ui32LayoutVersion));
2404                         eError = PVRSRV_ERROR_BVNC_MISMATCH;
2405                         return eError;
2406                 }
2407
2408                 if (!bCompatibleLenMax)
2409                 {
2410                         PVR_LOG(("(FAIL) %s: Incompatible V maxlen of HW (%d) and FW (%d).",
2411                                         __FUNCTION__, 
2412                                         sHWBVNC.ui32VLenMax, 
2413                                         sSWBVNC.ui32VLenMax));
2414                         eError = PVRSRV_ERROR_BVNC_MISMATCH;
2415                         return eError;
2416                 }
2417
2418                 if (!bCompatibleBNC)
2419                 {
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;
2428                         return eError;
2429                 }
2430                 
2431                 if (!bCompatibleV)
2432                 {
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;
2443                         return eError;
2444                 }
2445         }
2446         else
2447         {
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)));
2457         }
2458 #endif
2459
2460         return PVRSRV_OK;
2461 }
2462
2463 /*!
2464 *******************************************************************************
2465
2466  @Function      RGXDevInitCompatCheck_METACoreVersion_AgainstDriver
2467
2468  @Description
2469
2470  Validate HW META version against driver META version
2471
2472  @Input psDevInfo - device info
2473  @Input psRGXFWInit - FW init data
2474
2475  @Return   PVRSRV_ERROR - depending on mismatch found
2476
2477 ******************************************************************************/
2478
2479 static PVRSRV_ERROR RGXDevInitCompatCheck_METACoreVersion_AgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
2480                                                                         RGXFWIF_INIT *psRGXFWInit)
2481 {
2482 #if defined(PDUMP)||(!defined(NO_HARDWARE))
2483         PVRSRV_ERROR            eError;
2484 #endif
2485
2486 #if defined(PDUMP)
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,
2494                                         0xffffffff,
2495                                         PDUMP_POLL_OPERATOR_EQUAL,
2496                                         PDUMP_FLAGS_CONTINUOUS);
2497         if (eError != PVRSRV_OK)
2498         {
2499                 PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
2500                 return eError;
2501         }
2502         PDUMPFI("DISABLE_HWMETA_CHECK");
2503 #endif
2504
2505 #if !defined(NO_HARDWARE)
2506         if (psRGXFWInit == IMG_NULL)
2507                 return PVRSRV_ERROR_INVALID_PARAMS;
2508
2509         if (psRGXFWInit->sRGXCompChecks.ui32METAVersion != RGX_CR_META_CORE_ID_VALUE)
2510         {
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;
2514                 PVR_DBG_BREAK;
2515                 return eError;
2516         }
2517         else
2518         {
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));
2521         }
2522 #endif
2523         return PVRSRV_OK;
2524 }
2525
2526 /*!
2527 *******************************************************************************
2528
2529  @Function      RGXDevInitCompatCheck
2530
2531  @Description
2532
2533  Check compatibility of host driver and firmware (DDK and build options)
2534  for RGX devices at services/device initialisation
2535
2536  @Input psDeviceNode - device node
2537
2538  @Return   PVRSRV_ERROR - depending on mismatch found
2539
2540 ******************************************************************************/
2541 static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32ClientBuildOptions)
2542 {
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;
2548 #endif
2549
2550         /* Ensure it's a RGX device */
2551         if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_RGX)
2552         {
2553                 PVR_LOG(("(FAIL) %s: Device not of type RGX", __FUNCTION__));
2554                 eError = PVRSRV_ERROR_INVALID_PARAMS;
2555                 goto chk_exit;
2556         }
2557
2558         /* 
2559          * Retrieve the FW information
2560          */
2561         
2562 #if !defined(NO_HARDWARE)
2563         eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc,
2564                                                                                                 (IMG_VOID **)&psRGXFWInit);
2565         if (eError != PVRSRV_OK)
2566         {
2567                 PVR_DPF((PVR_DBG_ERROR,"%s: Failed to acquire kernel fw compatibility check info (%u)",
2568                                 __FUNCTION__, eError));
2569                 return eError;
2570         }
2571
2572         LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
2573         {
2574                 if(*((volatile IMG_BOOL *)&psRGXFWInit->sRGXCompChecks.bUpdated))
2575                 {
2576                         /* No need to wait if the FW has already updated the values */
2577                         break;
2578                 }
2579                 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
2580         } END_LOOP_UNTIL_TIMEOUT();
2581
2582         ui32RegValue = 0;
2583         eError = RGXReadMETAReg(psDevInfo, META_CR_T0ENABLE_OFFSET, &ui32RegValue);
2584
2585         if (eError != PVRSRV_OK)
2586         {
2587                 PVR_LOG(("%s: Reading RGX META register failed. Is the GPU correctly powered up? (%u)",
2588                                 __FUNCTION__, eError));
2589                 goto chk_exit;
2590         }
2591
2592         if (!(ui32RegValue & META_CR_TXENABLE_ENABLE_BIT))
2593         {
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));
2597                 goto chk_exit;
2598         }
2599         
2600         if (!*((volatile IMG_BOOL *)&psRGXFWInit->sRGXCompChecks.bUpdated))
2601         {
2602                 eError = PVRSRV_ERROR_TIMEOUT;
2603                 PVR_DPF((PVR_DBG_ERROR,"%s: Missing compatibility info from FW (%u)",
2604                                 __FUNCTION__, eError));
2605                 goto chk_exit;
2606         }
2607 #endif
2608
2609         eError = RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver(psRGXFWInit);
2610         if (eError != PVRSRV_OK)
2611         {
2612                 goto chk_exit;
2613         }
2614
2615         eError = RGXDevInitCompatCheck_BuildOptions_FWAgainstClient(psDevInfo, psRGXFWInit, ui32ClientBuildOptions);
2616         if (eError != PVRSRV_OK)
2617         {
2618                 goto chk_exit;
2619         }
2620         
2621         eError = RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver(psDevInfo, psRGXFWInit);
2622         if (eError != PVRSRV_OK)
2623         {
2624                 goto chk_exit;
2625         }
2626
2627         eError = RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver(psDevInfo, psRGXFWInit);
2628         if (eError != PVRSRV_OK)
2629         {
2630                 goto chk_exit;
2631         }
2632
2633         eError = RGXDevInitCompatCheck_BVNC_FWAgainstDriver(psDevInfo, psRGXFWInit);
2634         if (eError != PVRSRV_OK)
2635         {
2636                 goto chk_exit;
2637         }
2638
2639         eError = RGXDevInitCompatCheck_BVNC_HWAgainstDriver(psDevInfo, psRGXFWInit);
2640         if (eError != PVRSRV_OK)
2641         {
2642                 goto chk_exit;
2643         }
2644
2645         eError = RGXDevInitCompatCheck_METACoreVersion_AgainstDriver(psDevInfo, psRGXFWInit);
2646         if (eError != PVRSRV_OK)
2647         {
2648                 goto chk_exit;
2649         }
2650
2651         eError = PVRSRV_OK;
2652 chk_exit:
2653 #if !defined(NO_HARDWARE)
2654         DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
2655 #endif
2656         return eError;
2657 }
2658
2659 #define MAKESTRING(x) #x
2660 #define TOSTRING(x) MAKESTRING(x)
2661
2662
2663
2664
2665
2666 static PVRSRV_ERROR
2667 ValidateFWImage(
2668         IMG_CHAR *pcFWImgDestAddr,
2669         IMG_CHAR *pcFWImgSrcAddr,
2670         IMG_SIZE_T uiFWImgLen,
2671         IMG_CHAR *pcFWImgSigAddr,
2672         IMG_UINT64 ui64FWSigLen)
2673 {
2674 #if defined(DEBUG)
2675         if(OSMemCmp(pcFWImgDestAddr, pcFWImgSrcAddr, uiFWImgLen) != 0)
2676         {
2677                 return PVRSRV_ERROR_INIT_TDMETACODE_PAGES_FAIL;
2678         }
2679
2680         PVR_UNREFERENCED_PARAMETER(pcFWImgSigAddr);
2681         PVR_UNREFERENCED_PARAMETER(ui64FWSigLen);
2682 #else
2683         PVR_UNREFERENCED_PARAMETER(pcFWImgDestAddr);
2684         PVR_UNREFERENCED_PARAMETER(uiFWImgLen);
2685         PVR_UNREFERENCED_PARAMETER(pcFWImgSigAddr);
2686         PVR_UNREFERENCED_PARAMETER(ui64FWSigLen);
2687 #endif
2688
2689         return PVRSRV_OK;
2690 }
2691
2692 static PVRSRV_ERROR
2693 PMRCopy(PMR *psDstPMR, PMR *psSrcPMR, IMG_SIZE_T uiMaxCopyLen)
2694 {
2695         IMG_CHAR acBuf[512];
2696         IMG_UINT64 uiBytesCopied;
2697         PVRSRV_ERROR eStatus;
2698         
2699         uiBytesCopied = 0;
2700         while(uiBytesCopied < uiMaxCopyLen)
2701         {
2702                 IMG_SIZE_T uiRead, uiWritten;
2703                 IMG_SIZE_T uiCopyAmt;
2704                 uiCopyAmt = sizeof(acBuf) > uiMaxCopyLen ? uiMaxCopyLen : sizeof(acBuf);
2705                 eStatus = PMR_ReadBytes(psSrcPMR,
2706                                         uiBytesCopied,
2707                                         acBuf,
2708                                         uiCopyAmt,
2709                                         &uiRead);
2710                 if(eStatus != PVRSRV_OK)
2711                 {
2712                         return eStatus;
2713                 }
2714                 eStatus = PMR_WriteBytes(psDstPMR,
2715                                          uiBytesCopied,
2716                                          acBuf,
2717                                          uiCopyAmt,
2718                                          &uiWritten);
2719                 if(eStatus != PVRSRV_OK)
2720                 {
2721                         return eStatus;
2722                 }
2723                 PVR_ASSERT(uiRead == uiWritten);
2724                 PVR_ASSERT(uiRead == uiCopyAmt);
2725                 uiBytesCopied += uiCopyAmt;
2726         }
2727
2728         return PVRSRV_OK;
2729 }
2730
2731 IMG_EXPORT PVRSRV_ERROR
2732 PVRSRVRGXInitLoadFWImageKM(
2733         PMR *psFWImgDestPMR,
2734         PMR *psFWImgSrcPMR,
2735         IMG_UINT64 ui64FWImgLen,
2736         PMR *psFWImgSigPMR,
2737         IMG_UINT64 ui64FWSigLen)
2738 {
2739         IMG_CHAR *pcFWImgSigAddr, *pcFWImgDestAddr, *pcFWImgSrcAddr;
2740         IMG_HANDLE hFWImgSigHdl, hFWImgDestHdl, hFWImgSrcHdl;
2741         IMG_SIZE_T uiLen;
2742         PVRSRV_ERROR eStatus;
2743
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
2747
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.
2753
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.
2760
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
2764              the PMR layer
2765            - a validation is done by reading back the destination buffer and comparing it against
2766              the source buffer.
2767
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.
2772         */
2773
2774         eStatus = PMRAcquireKernelMappingData(psFWImgDestPMR,
2775                                               0,
2776                                               0,
2777                                               (IMG_VOID **) &pcFWImgDestAddr,
2778                                               &uiLen,
2779                                           &hFWImgDestHdl);
2780         if(eStatus != PVRSRV_OK)
2781         {
2782                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Acquire mapping for dest failed (%u)", eStatus));
2783                 goto error;
2784         }
2785         if(ui64FWImgLen > uiLen)
2786         {
2787                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: PMR dst len (%llu) > mapped len (%llu)",
2788                          ui64FWImgLen, (unsigned long long)uiLen));
2789                 goto error;
2790         }
2791
2792         eStatus = PMRAcquireKernelMappingData(psFWImgSrcPMR,
2793                                               0,
2794                                               0,
2795                                               (IMG_VOID **) &pcFWImgSrcAddr,
2796                                               &uiLen,
2797                                           &hFWImgSrcHdl);
2798         if(eStatus != PVRSRV_OK)
2799         {
2800                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Acquire mapping for src failed (%u)", eStatus));
2801                 goto error;
2802         }
2803         if(ui64FWImgLen > uiLen)
2804         {
2805                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: PMR dst len (%llu) > mapped len (%llu)",
2806                          ui64FWImgLen, (unsigned long long)uiLen));
2807                 goto error;
2808         }
2809
2810         eStatus = PMRAcquireKernelMappingData(psFWImgSigPMR,
2811                                               0,
2812                                               0,
2813                                               (IMG_VOID **) &pcFWImgSigAddr,
2814                                               &uiLen,
2815                                           &hFWImgSigHdl);
2816         if(eStatus != PVRSRV_OK)
2817         {
2818                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Acquire mapping for sig failed (%u)", eStatus));
2819                 goto error;
2820         }
2821         if(ui64FWSigLen > uiLen)
2822         {
2823                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: sig len (%llu) > mapped len (%llu)",
2824                          ui64FWSigLen, (unsigned long long)uiLen));
2825                 goto error;
2826         }
2827
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));
2832
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)
2836         {
2837                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Signature check failed"));
2838                 goto error;
2839         }
2840
2841         eStatus = PMRReleaseKernelMappingData(psFWImgDestPMR,
2842                                               hFWImgDestHdl);
2843         if(eStatus != PVRSRV_OK)
2844         {
2845                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Release mapping for dest failed (%u)", eStatus));
2846                 goto error;
2847         }
2848
2849         eStatus = PMRReleaseKernelMappingData(psFWImgSrcPMR,
2850                                               hFWImgSrcHdl);
2851         if(eStatus != PVRSRV_OK)
2852         {
2853                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Release mapping for src failed (%u)", eStatus));
2854                 goto error;
2855         }
2856
2857         eStatus = PMRReleaseKernelMappingData(psFWImgSigPMR,
2858                                               hFWImgSigHdl);
2859         if(eStatus != PVRSRV_OK)
2860         {
2861                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Release mapping for sig failed (%u)", eStatus));
2862                 goto error;
2863         }
2864
2865         return PVRSRV_OK;
2866
2867 error:
2868         return PVRSRV_ERROR_INIT_TDMETACODE_PAGES_FAIL;
2869 }
2870
2871
2872
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 
2879                                         version string
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)
2885 {
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)";
2888 #else
2889         IMG_CHAR pszFormatString[] = "Rogue Version: %d.%s.%d.%d (HW)";
2890 #endif
2891         IMG_SIZE_T uiStringLength;
2892
2893         if (psDeviceNode == NULL || ppszVersionString == NULL)
2894         {
2895                 return PVRSRV_ERROR_INVALID_PARAMS;
2896         }
2897
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));
2903
2904         *ppszVersionString = OSAllocZMem(uiStringLength * sizeof(IMG_CHAR));
2905         if (*ppszVersionString == NULL)
2906         {
2907                 return PVRSRV_ERROR_OUT_OF_MEMORY;
2908         }
2909
2910         OSSNPrintf(*ppszVersionString, uiStringLength, pszFormatString, 
2911                    RGX_BVNC_KM_B, TOSTRING(RGX_BVNC_KM_V), RGX_BVNC_KM_N, RGX_BVNC_KM_C);
2912
2913         return PVRSRV_OK;
2914 }
2915
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)
2926 {
2927         RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
2928
2929         /* get clock speed */
2930         *pui32RGXClockSpeed = psRGXData->psRGXTimingInfo->ui32CoreClockSpeed;
2931
2932         return PVRSRV_OK;
2933 }
2934
2935
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)
2946 {
2947         PVRSRV_RGXDEV_INFO        *psDevInfo;
2948
2949         PVR_ASSERT(psDeviceNode != NULL);
2950         PVR_ASSERT(psDeviceNode->pvDevice != NULL);
2951
2952         if ((ui64ResetValue & RGX_CR_SOFT_RESET_MASKFULL) != ui64ResetValue)
2953         {
2954                 return PVRSRV_ERROR_INVALID_PARAMS;
2955         }
2956
2957         /* the device info */
2958         psDevInfo = psDeviceNode->pvDevice;
2959
2960         /* Set in soft-reset */
2961         OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, ui64ResetValue);
2962
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);
2965
2966         return PVRSRV_OK;
2967 }
2968
2969
2970 /******************************************************************************
2971  End of file (rgxinit.c)
2972 ******************************************************************************/