1.3.13.1607/3_00_00_08+flat+Lindent
[sgx.git] / pvr / sgxinit.c
1 /**********************************************************************
2  *
3  * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4  * 
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  * 
9  * This program is distributed in the hope it will be useful but, except 
10  * as otherwise stated in writing, without any warranty; without even the 
11  * implied warranty of merchantability or fitness for a particular purpose. 
12  * See the GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17  * 
18  * The full GNU General Public License is included in this distribution in
19  * the file called "COPYING".
20  *
21  * Contact Information:
22  * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23  * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
24  *
25  ******************************************************************************/
26
27 #include <stddef.h>
28
29 #include "sgxdefs.h"
30 #include "sgxmmu.h"
31 #include "services_headers.h"
32 #include "buffer_manager.h"
33 #include "sgxapi_km.h"
34 #include "sgxinfo.h"
35 #include "sgxinfokm.h"
36 #include "sgxconfig.h"
37 #include "sysconfig.h"
38 #include "pvr_bridge_km.h"
39
40 #include "pdump_km.h"
41 #include "ra.h"
42 #include "mmu.h"
43 #include "handle.h"
44 #include "perproc.h"
45
46 #include "sgxutils.h"
47
48 #if defined (SGX_FEATURE_2D_HARDWARE)
49 #define SGX_USING_CMD_PROC_LIST
50 #endif
51
52 IMG_BOOL SGX_ISRHandler(IMG_VOID * pvData);
53
54 IMG_UINT32 gui32EventStatusServicesByISR = 0;
55
56 IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO * psDevInfo, IMG_UINT32 ui32PDUMPFlags);
57
58 static PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO * psDevInfo,
59                                   IMG_BOOL bHardwareRecovery);
60 PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie);
61
62 static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE * psDeviceNode)
63 {
64         SGXScheduleProcessQueues(psDeviceNode);
65 }
66
67 static IMG_UINT32 DeinitDevInfo(PVRSRV_SGXDEV_INFO * psDevInfo)
68 {
69         if (psDevInfo->psKernelCCBInfo != IMG_NULL) {
70
71                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SGX_CCB_INFO),
72                           psDevInfo->psKernelCCBInfo, IMG_NULL);
73         }
74
75         return PVRSRV_OK;
76 }
77
78 static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA * psPerProc,
79                                 PVRSRV_DEVICE_NODE * psDeviceNode,
80                                 SGX_BRIDGE_INIT_INFO * psInitInfo)
81 {
82         PVRSRV_SGXDEV_INFO *psDevInfo =
83             (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
84         PVRSRV_ERROR eError;
85
86         PVRSRV_SGX_CCB_INFO *psKernelCCBInfo = IMG_NULL;
87
88         PVR_UNREFERENCED_PARAMETER(psPerProc);
89         psDevInfo->sScripts = psInitInfo->sScripts;
90
91         psDevInfo->psKernelCCBMemInfo =
92             (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelCCBMemInfo;
93         psDevInfo->psKernelCCB =
94             (PVRSRV_SGX_KERNEL_CCB *) psDevInfo->psKernelCCBMemInfo->
95             pvLinAddrKM;
96
97         psDevInfo->psKernelCCBCtlMemInfo =
98             (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelCCBCtlMemInfo;
99         psDevInfo->psKernelCCBCtl =
100             (PVRSRV_SGX_CCB_CTL *) psDevInfo->psKernelCCBCtlMemInfo->
101             pvLinAddrKM;
102
103         psDevInfo->psKernelCCBEventKickerMemInfo =
104             (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelCCBEventKickerMemInfo;
105         psDevInfo->pui32KernelCCBEventKicker =
106             (IMG_UINT32 *) psDevInfo->psKernelCCBEventKickerMemInfo->
107             pvLinAddrKM;
108
109         psDevInfo->psKernelSGXHostCtlMemInfo =
110             (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelSGXHostCtlMemInfo;
111         psDevInfo->psSGXHostCtl =
112             (PVRSRV_SGX_HOST_CTL *) psDevInfo->psKernelSGXHostCtlMemInfo->
113             pvLinAddrKM;
114
115 #if defined(SGX_SUPPORT_HWPROFILING)
116         psDevInfo->psKernelHWProfilingMemInfo =
117             (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelHWProfilingMemInfo;
118 #endif
119 #if defined(SUPPORT_SGX_HWPERF)
120         psDevInfo->psKernelHWPerfCBMemInfo =
121             (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelHWPerfCBMemInfo;
122 #endif
123 #if defined(SGX_FEATURE_OVERLAPPED_SPM)
124         psDevInfo->psKernelTmpRgnHeaderMemInfo =
125             (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelTmpRgnHeaderMemInfo;
126 #endif
127 #if defined(SGX_FEATURE_SPM_MODE_0)
128         psDevInfo->psKernelTmpDPMStateMemInfo =
129             (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelTmpDPMStateMemInfo;
130 #endif
131
132         eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
133                             sizeof(PVRSRV_SGX_CCB_INFO),
134                             (IMG_VOID **) & psKernelCCBInfo, 0);
135         if (eError != PVRSRV_OK) {
136                 PVR_DPF((PVR_DBG_ERROR, "InitDevInfo: Failed to alloc memory"));
137                 goto failed_allockernelccb;
138         }
139
140         OSMemSet(psKernelCCBInfo, 0, sizeof(PVRSRV_SGX_CCB_INFO));
141         psKernelCCBInfo->psCCBMemInfo = psDevInfo->psKernelCCBMemInfo;
142         psKernelCCBInfo->psCCBCtlMemInfo = psDevInfo->psKernelCCBCtlMemInfo;
143         psKernelCCBInfo->psCommands = psDevInfo->psKernelCCB->asCommands;
144         psKernelCCBInfo->pui32WriteOffset =
145             &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
146         psKernelCCBInfo->pui32ReadOffset =
147             &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
148         psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
149
150         psDevInfo->ui32TAKickAddress = psInitInfo->ui32TAKickAddress;
151
152         psDevInfo->ui32VideoHandlerAddress =
153             psInitInfo->ui32VideoHandlerAddress;
154
155         psDevInfo->bForcePTOff = IMG_FALSE;
156
157         psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl;
158
159         psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
160         psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
161         psDevInfo->ui32ClkGateCtl = psInitInfo->ui32ClkGateCtl;
162         psDevInfo->ui32ClkGateCtl2 = psInitInfo->ui32ClkGateCtl2;
163         psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
164
165         OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData,
166                   sizeof(psDevInfo->asSGXDevData));
167
168         return PVRSRV_OK;
169
170 failed_allockernelccb:
171         DeinitDevInfo(psDevInfo);
172
173         return eError;
174 }
175
176 static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO * psDevInfo)
177 {
178         IMG_UINT32 ui32RegVal =
179             EUR_CR_EVENT_TIMER_ENABLE_MASK | psDevInfo->ui32uKernelTimerClock;
180         OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_TIMER, ui32RegVal);
181         PDUMPREGWITHFLAGS(EUR_CR_EVENT_TIMER, ui32RegVal,
182                           PDUMP_FLAGS_CONTINUOUS);
183 }
184
185 PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE hDevHandle,
186                               PVR_POWER_STATE eNewPowerState,
187                               PVR_POWER_STATE eCurrentPowerState)
188 {
189         if (eNewPowerState != eCurrentPowerState) {
190                 PVRSRV_DEVICE_NODE *psDeviceNode =
191                     (PVRSRV_DEVICE_NODE *) hDevHandle;
192                 PVRSRV_SGXDEV_INFO *psDevInfo =
193                     (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
194
195                 if (eNewPowerState == PVRSRV_POWER_STATE_D3) {
196                         PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
197                             psDevInfo->psSGXHostCtl;
198
199 #if defined (SGX_FEATURE_AUTOCLOCKGATING) && (!defined(NO_HARDWARE) || defined(PDUMP))
200                         IMG_UINT32 ui32ClockMask =
201                             psDevInfo->ui32ClkGateStatusMask;
202 #endif
203
204 #if defined(SUPPORT_HW_RECOVERY)
205
206                         if (OSDisableTimer(psDevInfo->hTimer) != PVRSRV_OK) {
207                                 PVR_DPF((PVR_DBG_ERROR,
208                                          "SGXPrePowerState: Failed to disable timer"));
209                                 return PVRSRV_ERROR_GENERIC;
210                         }
211 #endif
212
213                         psSGXHostCtl->ui32PowManFlags |=
214                             PVRSRV_USSE_EDM_POWMAN_POWEROFF_REQUEST;
215
216                         PDUMPCOMMENT
217                             ("TA/3D CCB Control - Trigger power down event on uKernel...");
218                         PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
219                                  offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags),
220                                  sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
221                                  MAKEUNIQUETAG(psDevInfo->
222                                                psKernelSGXHostCtlMemInfo));
223
224 #if !defined(NO_HARDWARE)
225                         if (PollForValueKM
226                             ((volatile IMG_UINT32 *)(&psSGXHostCtl->
227                                                      ui32PowManFlags),
228                              PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE,
229                              PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE,
230                              MAX_HW_TIME_US / WAIT_TRY_COUNT,
231                              WAIT_TRY_COUNT) != PVRSRV_OK) {
232                                 PVR_DPF((PVR_DBG_ERROR,
233                                          "SGXPrePowerState: Wait for chip power off failed."));
234                         }
235 #endif
236
237 #ifdef PDUMP
238
239                         PDUMPCOMMENT
240                             ("TA/3D CCB Control - Wait for power down event on uKernel...");
241                         PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
242                                     offsetof(PVRSRV_SGX_HOST_CTL,
243                                              ui32PowManFlags),
244                                     PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE,
245                                     PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE,
246                                     PDUMP_POLL_OPERATOR_EQUAL, IMG_FALSE,
247                                     IMG_FALSE,
248                                     MAKEUNIQUETAG(psDevInfo->
249                                                   psKernelSGXHostCtlMemInfo));
250 #endif
251
252                         SGXDeinitialise(psDevInfo);
253
254 #if defined(SGX_FEATURE_AUTOCLOCKGATING)
255
256 #if !defined(NO_HARDWARE)
257                         if (PollForValueKM
258                             ((volatile IMG_UINT32 *)((IMG_UINT8 *) psDevInfo->
259                                                      pvRegsBaseKM +
260                                                      EUR_CR_CLKGATESTATUS), 0,
261                              ui32ClockMask, MAX_HW_TIME_US / WAIT_TRY_COUNT,
262                              WAIT_TRY_COUNT) != PVRSRV_OK) {
263                                 PVR_DPF((PVR_DBG_ERROR,
264                                          "SGXPrePowerState: Wait for chip idle failed."));
265                         }
266 #endif
267                         PDUMPREGPOL(EUR_CR_CLKGATESTATUS, 0, ui32ClockMask);
268 #endif
269                 }
270         }
271
272         return PVRSRV_OK;
273 }
274
275 PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE hDevHandle,
276                                PVR_POWER_STATE eNewPowerState,
277                                PVR_POWER_STATE eCurrentPowerState)
278 {
279         if (eNewPowerState != eCurrentPowerState) {
280                 PVRSRV_ERROR eError;
281                 PVRSRV_DEVICE_NODE *psDeviceNode =
282                     (PVRSRV_DEVICE_NODE *) hDevHandle;
283                 PVRSRV_SGXDEV_INFO *psDevInfo =
284                     (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
285                 SYS_DATA *psSysData;
286
287                 eError = SysAcquireData(&psSysData);
288                 if (eError != PVRSRV_OK) {
289                         return eError;
290                 }
291
292                 if (eCurrentPowerState == PVRSRV_POWER_STATE_D3) {
293                         PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
294                             psDevInfo->psSGXHostCtl;
295
296                         psSGXHostCtl->ui32PowManFlags = 0;
297
298                         PDUMPCOMMENT
299                             ("TA/3D CCB Control - Reset Power Manager flags");
300                         PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
301                                  offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags),
302                                  sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
303                                  MAKEUNIQUETAG(psDevInfo->
304                                                psKernelSGXHostCtlMemInfo));
305
306                         eError = SGXInitialise(psDevInfo, IMG_FALSE);
307
308                         if (eError != PVRSRV_OK) {
309                                 PVR_DPF((PVR_DBG_ERROR,
310                                          "SGXPostPowerState: SGXInitialise failed"));
311                                 return eError;
312                         }
313 #if defined(SUPPORT_HW_RECOVERY)
314                         eError = OSEnableTimer(psDevInfo->hTimer);
315                         if (eError != PVRSRV_OK) {
316                                 PVR_DPF((PVR_DBG_ERROR,
317                                          "SGXPostPowerState : Failed to enable host timer"));
318                                 return PVRSRV_ERROR_GENERIC;
319                         }
320 #endif
321                 }
322
323                 PVR_DPF((PVR_DBG_WARNING,
324                          "SGXPostPowerState : SGX Power Transition from %d to %d OK",
325                          eCurrentPowerState, eNewPowerState));
326         }
327
328         return PVRSRV_OK;
329 }
330
331 static IMG_VOID SGXGetTimingInfo(PVRSRV_SGXDEV_INFO * psDevInfo,
332                                  SGX_TIMING_INFORMATION * psSGXTimingInfo)
333 {
334         IMG_UINT32 ui32ActivePowManSampleRate;
335
336         psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
337         psDevInfo->ui32uKernelTimerClock =
338             psSGXTimingInfo->ui32CoreClockSpeed /
339             psSGXTimingInfo->ui32uKernelFreq;
340
341 #if defined(SUPPORT_HW_RECOVERY)
342         psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
343             psSGXTimingInfo->ui32uKernelFreq /
344             psSGXTimingInfo->ui32HWRecoveryFreq;
345 #endif
346
347         ui32ActivePowManSampleRate =
348             psSGXTimingInfo->ui32uKernelFreq *
349             psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
350
351         ui32ActivePowManSampleRate += 1;
352
353         psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate =
354             ui32ActivePowManSampleRate;
355 }
356
357 static PVRSRV_ERROR SGXPreClockSpeedChange(IMG_HANDLE hDevHandle,
358                                            IMG_BOOL bIdleDevice)
359 {
360         PVRSRV_ERROR eError;
361         PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
362         PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
363         SGX_DEVICE_MAP *psSGXDeviceMap;
364
365         eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
366                                        (IMG_VOID **) & psSGXDeviceMap);
367         if (eError != PVRSRV_OK) {
368                 PVR_DPF((PVR_DBG_ERROR,
369                          "DevInitSGXPart2KM: Failed to get device memory map!"));
370                 return PVRSRV_ERROR_INIT_FAILURE;
371         }
372
373         if (bIdleDevice) {
374
375         }
376
377         SGXGetTimingInfo(psDevInfo, &psSGXDeviceMap->sTimingInfo);
378
379         PVR_DPF((PVR_DBG_MESSAGE,
380                  "SGXPreClockSpeedChange: SGX clock speed now %luHz",
381                  psDevInfo->ui32CoreClockSpeed));
382
383         return PVRSRV_OK;
384 }
385
386 static PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE hDevHandle,
387                                             IMG_BOOL bIdleDevice)
388 {
389         PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
390         PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
391
392         if (bIdleDevice) {
393
394         } else {
395                 SGXStartTimer(psDevInfo);
396         }
397
398         return PVRSRV_OK;
399 }
400
401 static PVRSRV_ERROR SGXRunScript(PVRSRV_SGXDEV_INFO * psDevInfo,
402                                  SGX_INIT_COMMAND * psScript,
403                                  IMG_UINT32 ui32NumInitCommands)
404 {
405         IMG_UINT32 ui32PC;
406         SGX_INIT_COMMAND *psComm;
407
408         for (ui32PC = 0, psComm = psScript;
409              ui32PC < ui32NumInitCommands; ui32PC++, psComm++) {
410                 switch (psComm->eOp) {
411                 case SGX_INIT_OP_WRITE_HW_REG:
412                         {
413                                 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
414                                              psComm->sWriteHWReg.ui32Offset,
415                                              psComm->sWriteHWReg.ui32Value);
416                                 PDUMPREG(psComm->sWriteHWReg.ui32Offset,
417                                          psComm->sWriteHWReg.ui32Value);
418                                 break;
419                         }
420 #if defined(PDUMP)
421                 case SGX_INIT_OP_PDUMP_HW_REG:
422                         {
423                                 PDUMPREG(psComm->sPDumpHWReg.ui32Offset,
424                                          psComm->sPDumpHWReg.ui32Value);
425                                 break;
426                         }
427 #endif
428                 case SGX_INIT_OP_HALT:
429                         {
430                                 return PVRSRV_OK;
431                         }
432                 case SGX_INIT_OP_ILLEGAL:
433
434                 default:
435                         {
436                                 PVR_DPF((PVR_DBG_ERROR,
437                                          "SGXRunScript: PC %d: Illegal command: %d",
438                                          ui32PC, psComm->eOp));
439                                 return PVRSRV_ERROR_GENERIC;
440                         }
441                 }
442
443         }
444
445         return PVRSRV_ERROR_GENERIC;;
446 }
447
448 static PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO * psDevInfo,
449                                   IMG_BOOL bHardwareRecovery)
450 {
451         PVRSRV_ERROR eError;
452         IMG_UINT32 ui32ReadOffset, ui32WriteOffset;
453
454         OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL,
455                      psDevInfo->ui32ClkGateCtl);
456         PDUMPREGWITHFLAGS(EUR_CR_CLKGATECTL, psDevInfo->ui32ClkGateCtl,
457                           PDUMP_FLAGS_CONTINUOUS);
458 #if defined(SGX540)
459         OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL2,
460                      psDevInfo->ui32ClkGateCtl2);
461         PDUMPREGWITHFLAGS(EUR_CR_CLKGATECTL2, psDevInfo->ui32ClkGateCtl2,
462                           PDUMP_FLAGS_CONTINUOUS);
463 #endif
464
465         SGXReset(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
466
467 #if defined(EUR_CR_POWER)
468 #if defined(SGX531)
469
470         OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 1);
471         PDUMPREG(EUR_CR_POWER, 1);
472 #else
473
474         OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 0);
475         PDUMPREG(EUR_CR_POWER, 0);
476 #endif
477 #endif
478
479 #if defined(SGX_FEATURE_SYSTEM_CACHE)
480
481         OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MNE_CR_CTRL,
482                      EUR_CR_MNE_CR_CTRL_BYP_CC_MASK);
483         PDUMPREG(EUR_CR_MNE_CR_CTRL, EUR_CR_MNE_CR_CTRL_BYP_CC_MASK);
484 #endif
485
486         *psDevInfo->pui32KernelCCBEventKicker = 0;
487 #if defined(PDUMP)
488         PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
489                  sizeof(*psDevInfo->pui32KernelCCBEventKicker),
490                  PDUMP_FLAGS_CONTINUOUS,
491                  MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
492 #endif
493
494         psDevInfo->psSGXHostCtl->sTAHWPBDesc.uiAddr = 0;
495         psDevInfo->psSGXHostCtl->s3DHWPBDesc.uiAddr = 0;
496 #if defined(PDUMP)
497         PDUMPCOMMENT(" CCB Control - Reset HW PBDesc records");
498         PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
499                  offsetof(PVRSRV_SGX_HOST_CTL, sTAHWPBDesc),
500                  sizeof(IMG_DEV_VIRTADDR), PDUMP_FLAGS_CONTINUOUS,
501                  MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
502         PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
503                  offsetof(PVRSRV_SGX_HOST_CTL, s3DHWPBDesc),
504                  sizeof(IMG_DEV_VIRTADDR), PDUMP_FLAGS_CONTINUOUS,
505                  MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
506 #endif
507
508         eError =
509             SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommands,
510                          SGX_MAX_INIT_COMMANDS);
511         if (eError != PVRSRV_OK) {
512                 PVR_DPF((PVR_DBG_ERROR,
513                          "SGXInitialise: SGXRunScript failed (%d)", eError));
514                 return (PVRSRV_ERROR_GENERIC);
515         }
516
517         SGXStartTimer(psDevInfo);
518
519         if (bHardwareRecovery) {
520                 PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
521                     (PVRSRV_SGX_HOST_CTL *) psDevInfo->psSGXHostCtl;
522
523                 if (PollForValueKM
524                     ((volatile IMG_UINT32 *)(&psSGXHostCtl->
525                                              ui32InterruptClearFlags), 0,
526                      PVRSRV_USSE_EDM_INTERRUPT_HWR,
527                      MAX_HW_TIME_US / WAIT_TRY_COUNT, 1000) != PVRSRV_OK) {
528                         PVR_DPF((PVR_DBG_ERROR,
529                                  "SGXInitialise: Wait for uKernel HW Recovery failed"));
530                         return PVRSRV_ERROR_RETRY;
531                 }
532         }
533
534         for (ui32ReadOffset = psDevInfo->psKernelCCBCtl->ui32ReadOffset,
535              ui32WriteOffset = psDevInfo->psKernelCCBCtl->ui32WriteOffset;
536              ui32ReadOffset != ui32WriteOffset;
537              ui32ReadOffset = (ui32ReadOffset + 1) & 0xFF) {
538                 *psDevInfo->pui32KernelCCBEventKicker =
539                     (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
540                 OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_KICK,
541                              EUR_CR_EVENT_KICK_NOW_MASK);
542         }
543
544         return PVRSRV_OK;
545 }
546
547 PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie)
548 {
549         PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *) hDevCookie;
550         PVRSRV_ERROR eError;
551
552         if (psDevInfo->pvRegsBaseKM == IMG_NULL) {
553                 return PVRSRV_OK;
554         }
555
556         eError =
557             SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands,
558                          SGX_MAX_DEINIT_COMMANDS);
559         if (eError != PVRSRV_OK) {
560                 PVR_DPF((PVR_DBG_ERROR,
561                          "SGXDeinitialise: SGXRunScript failed (%d)", eError));
562                 return (PVRSRV_ERROR_GENERIC);
563         }
564
565         return PVRSRV_OK;
566 }
567
568 static PVRSRV_ERROR DevInitSGXPart1(IMG_VOID * pvDeviceNode)
569 {
570         PVRSRV_SGXDEV_INFO *psDevInfo;
571         IMG_HANDLE hKernelDevMemContext;
572         IMG_DEV_PHYADDR sPDDevPAddr;
573         IMG_UINT32 i;
574         PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *) pvDeviceNode;
575         DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap =
576             psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
577         IMG_HANDLE hDevInfoOSMemHandle = (IMG_HANDLE) IMG_NULL;
578         PVRSRV_ERROR eError;
579
580         PDUMPCOMMENT("SGX Initialisation Part 1");
581
582         PDUMPCOMMENT("SGX Core Version Information: %s",
583                      SGX_CORE_FRIENDLY_NAME);
584 #ifdef SGX_CORE_REV
585         PDUMPCOMMENT("SGX Core Revision Information: %d", SGX_CORE_REV);
586 #else
587         PDUMPCOMMENT("SGX Core Revision Information: head rtl");
588 #endif
589
590         if (OSAllocPages
591             (PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_HAP_MULTI_PROCESS |
592              PVRSRV_HAP_CACHED, sizeof(PVRSRV_SGXDEV_INFO),
593              (IMG_VOID **) & psDevInfo, &hDevInfoOSMemHandle) != PVRSRV_OK) {
594                 PVR_DPF((PVR_DBG_ERROR,
595                          "DevInitSGXPart1 : Failed to alloc memory for DevInfo"));
596                 return (PVRSRV_ERROR_OUT_OF_MEMORY);
597         }
598         OSMemSet(psDevInfo, 0, sizeof(PVRSRV_SGXDEV_INFO));
599
600         psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
601         psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
602
603         psDeviceNode->pvDevice = (IMG_PVOID) psDevInfo;
604         psDeviceNode->hDeviceOSMemHandle = hDevInfoOSMemHandle;
605
606         psDevInfo->pvDeviceMemoryHeap = (IMG_VOID *) psDeviceMemoryHeap;
607
608         hKernelDevMemContext = BM_CreateContext(psDeviceNode,
609                                                 &sPDDevPAddr,
610                                                 IMG_NULL, IMG_NULL);
611
612         psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
613
614         for (i = 0; i < psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++) {
615                 IMG_HANDLE hDevMemHeap;
616
617                 switch (psDeviceMemoryHeap[i].DevMemHeapType) {
618                 case DEVICE_MEMORY_HEAP_KERNEL:
619                 case DEVICE_MEMORY_HEAP_SHARED:
620                 case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
621                         {
622                                 hDevMemHeap =
623                                     BM_CreateHeap(hKernelDevMemContext,
624                                                   &psDeviceMemoryHeap[i]);
625
626                                 psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
627                                 break;
628                         }
629                 }
630         }
631
632         eError = MMU_BIFResetPDAlloc(psDevInfo);
633         if (eError != PVRSRV_OK) {
634                 PVR_DPF((PVR_DBG_ERROR,
635                          "DevInitSGX : Failed to alloc memory for BIF reset"));
636                 return PVRSRV_ERROR_GENERIC;
637         }
638
639         return PVRSRV_OK;
640 }
641
642 IMG_EXPORT
643     PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle,
644                                         SGX_BRIDGE_INFO_FOR_SRVINIT *
645                                         psInitInfo)
646 {
647         PVRSRV_DEVICE_NODE *psDeviceNode;
648         PVRSRV_SGXDEV_INFO *psDevInfo;
649         PVRSRV_ERROR eError;
650
651         PDUMPCOMMENT("SGXGetInfoForSrvinit");
652
653         psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevHandle;
654         psDevInfo = (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
655
656         psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
657
658         eError =
659             PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]);
660         if (eError != PVRSRV_OK) {
661                 PVR_DPF((PVR_DBG_ERROR,
662                          "SGXGetInfoForSrvinit: PVRSRVGetDeviceMemHeapsKM failed (%d)",
663                          eError));
664                 return PVRSRV_ERROR_GENERIC;
665         }
666
667         return eError;
668 }
669
670 IMG_EXPORT
671     PVRSRV_ERROR DevInitSGXPart2KM(PVRSRV_PER_PROCESS_DATA * psPerProc,
672                                    IMG_HANDLE hDevHandle,
673                                    SGX_BRIDGE_INIT_INFO * psInitInfo)
674 {
675         PVRSRV_DEVICE_NODE *psDeviceNode;
676         PVRSRV_SGXDEV_INFO *psDevInfo;
677         PVRSRV_ERROR eError;
678         SGX_DEVICE_MAP *psSGXDeviceMap;
679         PVR_POWER_STATE eDefaultPowerState;
680
681         PDUMPCOMMENT("SGX Initialisation Part 2");
682
683         psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevHandle;
684         psDevInfo = (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
685
686         eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
687         if (eError != PVRSRV_OK) {
688                 PVR_DPF((PVR_DBG_ERROR,
689                          "DevInitSGXPart2KM: Failed to load EDM program"));
690                 goto failed_init_dev_info;
691         }
692
693 #ifdef SGX_FEATURE_2D_HARDWARE
694         eError = OSCreateResource(&psDevInfo->s2DSlaveportResource);
695         if (eError != PVRSRV_OK) {
696                 PVR_DPF((PVR_DBG_ERROR,
697                          "DevInitSGXPart2KM: Failed to create resource !"));
698                 return PVRSRV_ERROR_INIT_FAILURE;
699         }
700 #endif
701
702         eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
703                                        (IMG_VOID **) & psSGXDeviceMap);
704         if (eError != PVRSRV_OK) {
705                 PVR_DPF((PVR_DBG_ERROR,
706                          "DevInitSGXPart2KM: Failed to get device memory map!"));
707                 return PVRSRV_ERROR_INIT_FAILURE;
708         }
709
710         if (psSGXDeviceMap->pvRegsCpuVBase) {
711                 psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
712         } else {
713
714                 psDevInfo->pvRegsBaseKM =
715                     OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
716                                    psSGXDeviceMap->ui32RegsSize,
717                                    PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
718                                    IMG_NULL);
719                 if (!psDevInfo->pvRegsBaseKM) {
720                         PVR_DPF((PVR_DBG_ERROR,
721                                  "DevInitSGXPart2KM: Failed to map in regs\n"));
722                         return PVRSRV_ERROR_BAD_MAPPING;
723                 }
724         }
725         psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize;
726         psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase;
727
728 #ifdef SGX_FEATURE_2D_HARDWARE
729
730         if (psSGXDeviceMap->pvSPCpuVBase) {
731                 psDevInfo->s2DSlavePortKM.pvData = psSGXDeviceMap->pvSPCpuVBase;
732         } else {
733
734                 psDevInfo->s2DSlavePortKM.pvData =
735                     OSMapPhysToLin(psSGXDeviceMap->sSPCpuPBase,
736                                    psSGXDeviceMap->ui32SPSize,
737                                    PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
738                                    IMG_NULL);
739
740                 if (!psDevInfo->s2DSlavePortKM.pvData) {
741                         PVR_DPF((PVR_DBG_ERROR,
742                                  "DevInitSGXPart2KM: Failed to map 2D Slave port region\n"));
743                         return PVRSRV_ERROR_BAD_MAPPING;
744                 }
745
746         }
747         psDevInfo->s2DSlavePortKM.ui32DataRange = psSGXDeviceMap->ui32SPSize;
748         psDevInfo->s2DSlavePortKM.sPhysBase = psSGXDeviceMap->sSPSysPBase;
749 #endif
750
751         SGXGetTimingInfo(psDevInfo, &psSGXDeviceMap->sTimingInfo);
752
753 #if defined (SYS_USING_INTERRUPTS)
754
755         psDeviceNode->pvISRData = psDeviceNode;
756
757         PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
758
759 #endif
760
761 #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
762
763         psDevInfo->psSGXHostCtl->ui32PowManFlags |=
764             PVRSRV_USSE_EDM_POWMAN_NO_WORK;
765         eDefaultPowerState = PVRSRV_POWER_STATE_D3;
766 #else
767         eDefaultPowerState = PVRSRV_POWER_STATE_D0;
768 #endif
769         eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
770                                            SGXPrePowerState, SGXPostPowerState,
771                                            SGXPreClockSpeedChange,
772                                            SGXPostClockSpeedChange,
773                                            (IMG_HANDLE) psDeviceNode,
774                                            PVRSRV_POWER_STATE_D3,
775                                            eDefaultPowerState);
776         if (eError != PVRSRV_OK) {
777                 PVR_DPF((PVR_DBG_ERROR,
778                          "DevInitSGXPart2KM: failed to register device with power manager"));
779                 return eError;
780         }
781
782         OSMemSet(psDevInfo->psKernelCCB, 0, sizeof(PVRSRV_SGX_KERNEL_CCB));
783         OSMemSet(psDevInfo->psKernelCCBCtl, 0, sizeof(PVRSRV_SGX_CCB_CTL));
784         OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0,
785                  sizeof(*psDevInfo->pui32KernelCCBEventKicker));
786         PDUMPCOMMENT("Kernel CCB");
787         PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBMemInfo, 0,
788                  sizeof(PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS,
789                  MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
790         PDUMPCOMMENT("Kernel CCB Control");
791         PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBCtlMemInfo, 0,
792                  sizeof(PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS,
793                  MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
794         PDUMPCOMMENT("Kernel CCB Event Kicker");
795         PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
796                  sizeof(*psDevInfo->pui32KernelCCBEventKicker),
797                  PDUMP_FLAGS_CONTINUOUS,
798                  MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
799
800 #if defined(SUPPORT_HW_RECOVERY)
801
802         psDevInfo->hTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
803                                        1000 * 50 /
804                                        psSGXDeviceMap->sTimingInfo.
805                                        ui32uKernelFreq);
806         if (psDevInfo->hTimer == IMG_NULL) {
807                 PVR_DPF((PVR_DBG_ERROR,
808                          "DevInitSGXPart2KM : Failed to register timer callback function"));
809                 return PVRSRV_ERROR_GENERIC;
810         }
811 #endif
812
813         return PVRSRV_OK;
814
815 failed_init_dev_info:
816         return eError;
817 }
818
819 static PVRSRV_ERROR DevDeInitSGX(IMG_VOID * pvDeviceNode)
820 {
821         PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *) pvDeviceNode;
822         PVRSRV_SGXDEV_INFO *psDevInfo =
823             (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
824         IMG_HANDLE hDevInfoOSMemHandle = psDeviceNode->hDeviceOSMemHandle;
825         PVRSRV_ERROR eError = PVRSRV_ERROR_INVALID_PARAMS;
826         IMG_UINT32 ui32Heap;
827         DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
828         SGX_DEVICE_MAP *psSGXDeviceMap;
829
830         if (!psDevInfo) {
831
832                 PVR_DPF((PVR_DBG_ERROR, "DevDeInitSGX: Null DevInfo"));
833                 return PVRSRV_OK;
834         }
835 #if defined(SUPPORT_HW_RECOVERY)
836         if (psDevInfo->hTimer) {
837                 eError = OSRemoveTimer(psDevInfo->hTimer);
838                 if (eError != PVRSRV_OK) {
839                         PVR_DPF((PVR_DBG_ERROR,
840                                  "DevDeInitSGX: Failed to remove timer"));
841                         return eError;
842                 }
843                 psDevInfo->hTimer = IMG_NULL;
844         }
845 #endif
846
847         MMU_BIFResetPDFree(psDevInfo);
848
849         DeinitDevInfo(psDevInfo);
850
851 #if defined(SGX_USING_CMD_PROC_LIST)
852         eError =
853             PVRSRVRemoveCmdProcListKM(psDeviceNode->sDevId.ui32DeviceIndex,
854                                       SGX_COMMAND_COUNT);
855         if (eError != PVRSRV_OK) {
856                 PVR_DPF((PVR_DBG_ERROR,
857                          "DevDeInitSGX: PVRSRVRemoveCmdProcList failed"));
858                 return eError;
859         }
860 #endif
861
862         psDeviceMemoryHeap =
863             (DEVICE_MEMORY_HEAP_INFO *) psDevInfo->pvDeviceMemoryHeap;
864         for (ui32Heap = 0;
865              ui32Heap < psDeviceNode->sDevMemoryInfo.ui32HeapCount;
866              ui32Heap++) {
867                 switch (psDeviceMemoryHeap[ui32Heap].DevMemHeapType) {
868                 case DEVICE_MEMORY_HEAP_KERNEL:
869                 case DEVICE_MEMORY_HEAP_SHARED:
870                 case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
871                         {
872                                 if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap !=
873                                     IMG_NULL) {
874                                         BM_DestroyHeap(psDeviceMemoryHeap
875                                                        [ui32Heap].hDevMemHeap);
876                                 }
877                                 break;
878                         }
879                 }
880         }
881
882         eError =
883             BM_DestroyContext(psDeviceNode->sDevMemoryInfo.pBMKernelContext,
884                               IMG_NULL);
885         if (eError != PVRSRV_OK) {
886                 PVR_DPF((PVR_DBG_ERROR,
887                          "DevDeInitSGX : Failed to destroy kernel context"));
888                 return eError;
889         }
890
891         eError =
892             PVRSRVRemovePowerDevice(((PVRSRV_DEVICE_NODE *) pvDeviceNode)->
893                                     sDevId.ui32DeviceIndex);
894         if (eError != PVRSRV_OK) {
895                 return eError;
896         }
897 #ifdef SGX_FEATURE_2D_HARDWARE
898         eError = OSDestroyResource(&psDevInfo->s2DSlaveportResource);
899         if (eError != PVRSRV_OK) {
900                 return eError;
901         }
902 #endif
903
904         eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
905                                        (IMG_VOID **) & psSGXDeviceMap);
906         if (eError != PVRSRV_OK) {
907                 PVR_DPF((PVR_DBG_ERROR,
908                          "DevDeInitSGX: Failed to get device memory map!"));
909                 return eError;
910         }
911
912         if (!psSGXDeviceMap->pvRegsCpuVBase) {
913
914                 if (psDevInfo->pvRegsBaseKM != IMG_NULL) {
915                         OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
916                                          psDevInfo->ui32RegSize,
917                                          PVRSRV_HAP_KERNEL_ONLY |
918                                          PVRSRV_HAP_UNCACHED, IMG_NULL);
919                 }
920         }
921 #ifdef SGX_FEATURE_2D_HARDWARE
922
923         if (!psSGXDeviceMap->pvSPCpuVBase) {
924                 if (psDevInfo->s2DSlavePortKM.pvData != IMG_NULL) {
925                         OSUnMapPhysToLin(psDevInfo->s2DSlavePortKM.pvData,
926                                          psDevInfo->s2DSlavePortKM.
927                                          ui32DataRange,
928                                          PVRSRV_HAP_KERNEL_ONLY |
929                                          PVRSRV_HAP_UNCACHED, IMG_NULL);
930                 }
931         }
932 #endif
933
934         OSFreePages(PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_HAP_MULTI_PROCESS,
935                     sizeof(PVRSRV_SGXDEV_INFO), psDevInfo, hDevInfoOSMemHandle);
936         psDeviceNode->pvDevice = IMG_NULL;
937
938         if (psDeviceMemoryHeap != IMG_NULL) {
939
940                 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
941                           sizeof(DEVICE_MEMORY_HEAP_INFO) *
942                           psDeviceNode->sDevMemoryInfo.ui32HeapCount,
943                           psDeviceMemoryHeap, 0);
944         }
945
946         return PVRSRV_OK;
947 }
948
949 #if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY)
950 static
951 IMG_VOID HWRecoveryResetSGX(PVRSRV_DEVICE_NODE * psDeviceNode,
952                             IMG_UINT32 ui32Component, IMG_UINT32 ui32CallerID)
953 {
954         PVRSRV_ERROR eError;
955         PVRSRV_SGXDEV_INFO *psDevInfo =
956             (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
957         PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
958             (PVRSRV_SGX_HOST_CTL *) psDevInfo->psSGXHostCtl;
959
960         PVR_UNREFERENCED_PARAMETER(ui32Component);
961
962         eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
963         if (eError != PVRSRV_OK) {
964
965                 PVR_DPF((PVR_DBG_WARNING,
966                          "HWRecoveryResetSGX: Power transition in progress"));
967                 return;
968         }
969
970         psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
971
972         PVR_DPF((PVR_DBG_ERROR,
973                  "HWRecoveryResetSGX: SGX Hardware Recovery triggered"));
974
975         PDUMPSUSPEND();
976
977         do {
978                 eError = SGXInitialise(psDevInfo, IMG_TRUE);
979         }
980         while (eError == PVRSRV_ERROR_RETRY);
981         if (eError != PVRSRV_OK) {
982                 PVR_DPF((PVR_DBG_ERROR,
983                          "HWRecoveryResetSGX: SGXInitialise failed (%d)",
984                          eError));
985         }
986
987         PDUMPRESUME();
988
989         PVRSRVPowerUnlock(ui32CallerID);
990
991         SGXScheduleProcessQueues(psDeviceNode);
992
993         PVRSRVProcessQueues(ui32CallerID, IMG_TRUE);
994 }
995 #endif
996
997 #if defined(SUPPORT_HW_RECOVERY)
998 IMG_VOID SGXOSTimer(IMG_VOID * pvData)
999 {
1000         PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
1001         PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1002         static IMG_UINT32 ui32EDMTasks = 0;
1003         static IMG_UINT32 ui32LockupCounter = 0;
1004         static IMG_UINT32 ui32NumResets = 0;
1005         IMG_UINT32 ui32CurrentEDMTasks;
1006         IMG_BOOL bLockup = IMG_FALSE;
1007         IMG_BOOL bPoweredDown;
1008
1009         psDevInfo->ui32TimeStamp++;
1010
1011         bPoweredDown = (IMG_BOOL) ! SGXIsDevicePowered(psDeviceNode);
1012
1013         if (bPoweredDown) {
1014                 ui32LockupCounter = 0;
1015         } else {
1016
1017                 ui32CurrentEDMTasks =
1018                     OSReadHWReg(psDevInfo->pvRegsBaseKM,
1019                                 psDevInfo->ui32EDMTaskReg0);
1020                 if (psDevInfo->ui32EDMTaskReg1 != 0) {
1021                         ui32CurrentEDMTasks ^=
1022                             OSReadHWReg(psDevInfo->pvRegsBaseKM,
1023                                         psDevInfo->ui32EDMTaskReg1);
1024                 }
1025                 if ((ui32CurrentEDMTasks == ui32EDMTasks) &&
1026                     (psDevInfo->ui32NumResets == ui32NumResets)) {
1027                         ui32LockupCounter++;
1028                         if (ui32LockupCounter == 3) {
1029                                 ui32LockupCounter = 0;
1030                                 PVR_DPF((PVR_DBG_ERROR,
1031                                          "SGXOSTimer() detected SGX lockup (0x%x tasks)",
1032                                          ui32EDMTasks));
1033
1034                                 bLockup = IMG_TRUE;
1035                         }
1036                 } else {
1037                         ui32LockupCounter = 0;
1038                         ui32EDMTasks = ui32CurrentEDMTasks;
1039                         ui32NumResets = psDevInfo->ui32NumResets;
1040                 }
1041         }
1042
1043         if (bLockup) {
1044                 PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
1045                     (PVRSRV_SGX_HOST_CTL *) psDevInfo->psSGXHostCtl;
1046
1047                 psSGXHostCtl->ui32HostDetectedLockups++;
1048
1049                 HWRecoveryResetSGX(psDeviceNode, 0, KERNEL_ID);
1050         }
1051 }
1052 #endif
1053
1054 #if defined(SYS_USING_INTERRUPTS)
1055
1056 IMG_BOOL SGX_ISRHandler(IMG_VOID * pvData)
1057 {
1058         IMG_BOOL bInterruptProcessed = IMG_FALSE;
1059
1060         {
1061                 IMG_UINT32 ui32EventStatus, ui32EventEnable;
1062                 IMG_UINT32 ui32EventClear = 0;
1063                 PVRSRV_DEVICE_NODE *psDeviceNode;
1064                 PVRSRV_SGXDEV_INFO *psDevInfo;
1065
1066                 if (pvData == IMG_NULL) {
1067                         PVR_DPF((PVR_DBG_ERROR,
1068                                  "SGX_ISRHandler: Invalid params\n"));
1069                         return bInterruptProcessed;
1070                 }
1071
1072                 psDeviceNode = (PVRSRV_DEVICE_NODE *) pvData;
1073                 psDevInfo = (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
1074
1075                 ui32EventStatus =
1076                     OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
1077                 ui32EventEnable =
1078                     OSReadHWReg(psDevInfo->pvRegsBaseKM,
1079                                 EUR_CR_EVENT_HOST_ENABLE);
1080
1081                 gui32EventStatusServicesByISR = ui32EventStatus;
1082
1083                 ui32EventStatus &= ui32EventEnable;
1084
1085                 if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK) {
1086                         ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
1087                 }
1088
1089                 if (ui32EventClear) {
1090                         bInterruptProcessed = IMG_TRUE;
1091
1092                         ui32EventClear |=
1093                             EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
1094
1095                         OSWriteHWReg(psDevInfo->pvRegsBaseKM,
1096                                      EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
1097                         //Read back to flush posted write to fix spurious IRQ
1098                         OSReadHWReg(psDevInfo->pvRegsBaseKM,
1099                                     EUR_CR_EVENT_HOST_CLEAR);
1100                 }
1101         }
1102
1103         return bInterruptProcessed;
1104 }
1105
1106 IMG_VOID SGX_MISRHandler(IMG_VOID * pvData)
1107 {
1108         PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *) pvData;
1109         PVRSRV_SGXDEV_INFO *psDevInfo =
1110             (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
1111         PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
1112             (PVRSRV_SGX_HOST_CTL *) psDevInfo->psSGXHostCtl;
1113
1114         if ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR)
1115             && !(psSGXHostCtl->
1116                  ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR)) {
1117                 HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
1118         }
1119 #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
1120         SGXTestActivePowerEvent(psDeviceNode, ISR_ID);
1121 #endif
1122 }
1123 #endif
1124
1125 PVRSRV_ERROR SGXRegisterDevice(PVRSRV_DEVICE_NODE * psDeviceNode)
1126 {
1127         DEVICE_MEMORY_INFO *psDevMemoryInfo;
1128         DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
1129
1130         psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
1131         psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
1132
1133         psDeviceNode->pfnInitDevice = DevInitSGXPart1;
1134         psDeviceNode->pfnDeInitDevice = DevDeInitSGX;
1135
1136         psDeviceNode->pfnMMUInitialise = MMU_Initialise;
1137         psDeviceNode->pfnMMUFinalise = MMU_Finalise;
1138         psDeviceNode->pfnMMUInsertHeap = MMU_InsertHeap;
1139         psDeviceNode->pfnMMUCreate = MMU_Create;
1140         psDeviceNode->pfnMMUDelete = MMU_Delete;
1141         psDeviceNode->pfnMMUAlloc = MMU_Alloc;
1142         psDeviceNode->pfnMMUFree = MMU_Free;
1143         psDeviceNode->pfnMMUMapPages = MMU_MapPages;
1144         psDeviceNode->pfnMMUMapShadow = MMU_MapShadow;
1145         psDeviceNode->pfnMMUUnmapPages = MMU_UnmapPages;
1146         psDeviceNode->pfnMMUMapScatter = MMU_MapScatter;
1147         psDeviceNode->pfnMMUGetPhysPageAddr = MMU_GetPhysPageAddr;
1148         psDeviceNode->pfnMMUGetPDDevPAddr = MMU_GetPDDevPAddr;
1149
1150 #if defined (SYS_USING_INTERRUPTS)
1151
1152         psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
1153         psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
1154 #endif
1155
1156         psDeviceNode->pfnDeviceCommandComplete = SGXCommandComplete;
1157
1158         psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
1159
1160         psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_ADDRESS_SPACE_SIZE;
1161
1162         psDevMemoryInfo->ui32Flags = 0;
1163
1164         psDevMemoryInfo->ui32HeapCount = SGX_MAX_HEAP_ID;
1165
1166         psDevMemoryInfo->ui32SyncHeapID = SGX_SYNCINFO_HEAP_ID;
1167
1168         psDevMemoryInfo->ui32MappingHeapID = SGX_GENERAL_MAPPING_HEAP_ID;
1169
1170         if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
1171                        sizeof(DEVICE_MEMORY_HEAP_INFO) *
1172                        psDevMemoryInfo->ui32HeapCount,
1173                        (IMG_VOID **) & psDevMemoryInfo->psDeviceMemoryHeap,
1174                        0) != PVRSRV_OK) {
1175                 PVR_DPF((PVR_DBG_ERROR,
1176                          "SGXRegisterDevice : Failed to alloc memory for DEVICE_MEMORY_HEAP_INFO"));
1177                 return (PVRSRV_ERROR_OUT_OF_MEMORY);
1178         }
1179         OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0,
1180                  sizeof(DEVICE_MEMORY_HEAP_INFO) *
1181                  psDevMemoryInfo->ui32HeapCount);
1182
1183         psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
1184
1185         psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32HeapID =
1186             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
1187         psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].sDevVAddrBase.uiAddr =
1188             SGX_GENERAL_HEAP_BASE;
1189         psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32HeapSize =
1190             SGX_GENERAL_HEAP_SIZE;
1191         psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32Attribs =
1192             PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1193             PVRSRV_HAP_SINGLE_PROCESS;
1194         psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].pszName = "General";
1195         psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].pszBSName = "General BS";
1196         psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].DevMemHeapType =
1197             DEVICE_MEMORY_HEAP_PERCONTEXT;
1198
1199         psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapID =
1200             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
1201         psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].sDevVAddrBase.uiAddr =
1202             SGX_TADATA_HEAP_BASE;
1203         psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapSize =
1204             SGX_TADATA_HEAP_SIZE;
1205         psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32Attribs =
1206             PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION
1207 #if 0
1208             | PVRSRV_HAP_KERNEL_ONLY;
1209 #else
1210             | PVRSRV_HAP_MULTI_PROCESS;
1211 #endif
1212         psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].pszName = "TA Data";
1213         psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].pszBSName = "TA Data BS";
1214         psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].DevMemHeapType =
1215             DEVICE_MEMORY_HEAP_PERCONTEXT;
1216
1217         psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapID =
1218             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
1219         psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].sDevVAddrBase.uiAddr =
1220             SGX_KERNEL_CODE_HEAP_BASE;
1221         psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapSize =
1222             SGX_KERNEL_CODE_HEAP_SIZE;
1223         psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32Attribs =
1224             PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION
1225 #if 0
1226             | PVRSRV_HAP_KERNEL_ONLY;
1227 #else
1228             | PVRSRV_HAP_MULTI_PROCESS;
1229 #endif
1230         psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszName = "Kernel";
1231         psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszBSName = "Kernel BS";
1232         psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].DevMemHeapType =
1233             DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1234
1235         psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].ui32HeapID =
1236             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_VIDEO_CODE_HEAP_ID);
1237         psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].sDevVAddrBase.uiAddr =
1238             SGX_VIDEO_CODE_HEAP_BASE;
1239         psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].ui32HeapSize =
1240             SGX_VIDEO_CODE_HEAP_SIZE;
1241         psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].ui32Attribs =
1242             PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1243             PVRSRV_HAP_KERNEL_ONLY;
1244         psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].pszName = "Video";
1245         psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].pszBSName = "Video BS";
1246         psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].DevMemHeapType =
1247             DEVICE_MEMORY_HEAP_SHARED;
1248
1249         psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].ui32HeapID =
1250             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_VIDEO_DATA_HEAP_ID);
1251         psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].sDevVAddrBase.uiAddr =
1252             SGX_KERNEL_VIDEO_DATA_HEAP_BASE;
1253         psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].ui32HeapSize =
1254             SGX_KERNEL_VIDEO_DATA_HEAP_SIZE;
1255         psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].ui32Attribs =
1256             PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1257 #if 0
1258             PVRSRV_HAP_KERNEL_ONLY;
1259 #else
1260             PVRSRV_HAP_MULTI_PROCESS;
1261 #endif
1262         psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].pszName =
1263             "KernelVideoData";
1264         psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].pszBSName =
1265             "KernelVideoData BS";
1266         psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].DevMemHeapType =
1267             DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1268
1269         psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapID =
1270             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
1271         psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
1272             SGX_PIXELSHADER_HEAP_BASE;
1273         psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapSize =
1274             SGX_PIXELSHADER_HEAP_SIZE;
1275         psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32Attribs =
1276             PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1277             PVRSRV_HAP_SINGLE_PROCESS;
1278         psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].pszName = "PixelShaderUSSE";
1279         psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].pszBSName =
1280             "PixelShaderUSSE BS";
1281         psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].DevMemHeapType =
1282             DEVICE_MEMORY_HEAP_PERCONTEXT;
1283
1284         psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapID =
1285             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
1286         psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
1287             SGX_VERTEXSHADER_HEAP_BASE;
1288         psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapSize =
1289             SGX_VERTEXSHADER_HEAP_SIZE;
1290         psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32Attribs =
1291             PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1292             PVRSRV_HAP_SINGLE_PROCESS;
1293         psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].pszName =
1294             "VertexShaderUSSE";
1295         psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].pszBSName =
1296             "VertexShaderUSSE BS";
1297         psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].DevMemHeapType =
1298             DEVICE_MEMORY_HEAP_PERCONTEXT;
1299
1300         psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapID =
1301             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
1302         psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].sDevVAddrBase.uiAddr =
1303             SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
1304         psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapSize =
1305             SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
1306         psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32Attribs =
1307             PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1308             PVRSRV_HAP_SINGLE_PROCESS;
1309         psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].pszName =
1310             "PDSPixelCodeData";
1311         psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].pszBSName =
1312             "PDSPixelCodeData BS";
1313         psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].DevMemHeapType =
1314             DEVICE_MEMORY_HEAP_PERCONTEXT;
1315
1316         psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapID =
1317             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
1318         psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].sDevVAddrBase.
1319             uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
1320         psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapSize =
1321             SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
1322         psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32Attribs =
1323             PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1324             PVRSRV_HAP_SINGLE_PROCESS;
1325         psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].pszName =
1326             "PDSVertexCodeData";
1327         psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].pszBSName =
1328             "PDSVertexCodeData BS";
1329         psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].DevMemHeapType =
1330             DEVICE_MEMORY_HEAP_PERCONTEXT;
1331
1332         psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapID =
1333             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
1334         psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].sDevVAddrBase.uiAddr =
1335             SGX_SYNCINFO_HEAP_BASE;
1336         psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapSize =
1337             SGX_SYNCINFO_HEAP_SIZE;
1338
1339         psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32Attribs =
1340             PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1341             PVRSRV_HAP_MULTI_PROCESS;
1342         psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].pszName = "CacheCoherent";
1343         psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].pszBSName = "CacheCoherent BS";
1344
1345         psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].DevMemHeapType =
1346             DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1347
1348         psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapID =
1349             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID);
1350         psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].sDevVAddrBase.uiAddr =
1351             SGX_3DPARAMETERS_HEAP_BASE;
1352         psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapSize =
1353             SGX_3DPARAMETERS_HEAP_SIZE;
1354         psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].pszName = "3DParameters";
1355         psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].pszBSName =
1356             "3DParameters BS";
1357 #if defined(SUPPORT_PERCONTEXT_PB)
1358         psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32Attribs =
1359             PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1360             PVRSRV_HAP_SINGLE_PROCESS;
1361         psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].DevMemHeapType =
1362             DEVICE_MEMORY_HEAP_PERCONTEXT;
1363 #else
1364         psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32Attribs =
1365             PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1366             PVRSRV_HAP_MULTI_PROCESS;
1367         psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].DevMemHeapType =
1368             DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1369 #endif
1370
1371         psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].ui32HeapID =
1372             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID);
1373         psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].sDevVAddrBase.uiAddr =
1374             SGX_GENERAL_MAPPING_HEAP_BASE;
1375         psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].ui32HeapSize =
1376             SGX_GENERAL_MAPPING_HEAP_SIZE;
1377         psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].ui32Attribs =
1378             PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_MULTI_PROCESS;
1379         psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].pszName =
1380             "GeneralMapping";
1381         psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].pszBSName =
1382             "GeneralMapping BS";
1383
1384         psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].DevMemHeapType =
1385             DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1386
1387 #if defined(SGX_FEATURE_2D_HARDWARE)
1388
1389         psDeviceMemoryHeap[SGX_2D_HEAP_ID].ui32HeapID =
1390             HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_2D_HEAP_ID);
1391         psDeviceMemoryHeap[SGX_2D_HEAP_ID].sDevVAddrBase.uiAddr =
1392             SGX_2D_HEAP_BASE;
1393         psDeviceMemoryHeap[SGX_2D_HEAP_ID].ui32HeapSize = SGX_2D_HEAP_SIZE;
1394         psDeviceMemoryHeap[SGX_2D_HEAP_ID].ui32Attribs = PVRSRV_HAP_WRITECOMBINE
1395             | PVRSRV_MEM_RAM_BACKED_ALLOCATION | PVRSRV_HAP_SINGLE_PROCESS;
1396         psDeviceMemoryHeap[SGX_2D_HEAP_ID].pszName = "2D";
1397         psDeviceMemoryHeap[SGX_2D_HEAP_ID].pszBSName = "2D BS";
1398
1399         psDeviceMemoryHeap[SGX_2D_HEAP_ID].DevMemHeapType =
1400             DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1401 #endif
1402
1403         return PVRSRV_OK;
1404 }
1405
1406 IMG_EXPORT
1407     PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie,
1408                                     PVR3DIF4_CLIENT_INFO * psClientInfo)
1409 {
1410         PVRSRV_SGXDEV_INFO *psDevInfo =
1411             (PVRSRV_SGXDEV_INFO *) ((PVRSRV_DEVICE_NODE *) hDevCookie)->
1412             pvDevice;
1413
1414         psDevInfo->ui32ClientRefCount++;
1415 #ifdef PDUMP
1416         if (psDevInfo->ui32ClientRefCount == 1) {
1417                 psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
1418         }
1419 #endif
1420
1421         psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
1422
1423         OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData,
1424                   sizeof(psClientInfo->asDevData));
1425
1426         return PVRSRV_OK;
1427 }
1428
1429 IMG_EXPORT
1430     PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO * psDevInfo,
1431                                   SGX_MISC_INFO * psMiscInfo)
1432 {
1433         switch (psMiscInfo->eRequest) {
1434         case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
1435                 {
1436                         psMiscInfo->uData.ui32SGXClockSpeed =
1437                             psDevInfo->ui32CoreClockSpeed;
1438                         return PVRSRV_OK;
1439                 }
1440 #ifdef SUPPORT_SGX_HWPERF
1441         case SGX_MISC_INFO_REQUEST_HWPERF_CB_ON:
1442                 {
1443                         psDevInfo->psSGXHostCtl->ui32HWPerfFlags |=
1444                             PVRSRV_SGX_HWPERF_ON;
1445                         return PVRSRV_OK;
1446                 }
1447         case SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF:
1448                 {
1449                         psDevInfo->psSGXHostCtl->ui32HWPerfFlags &=
1450                             ~PVRSRV_SGX_HWPERF_ON;
1451                         return PVRSRV_OK;
1452                 }
1453         case SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB:
1454                 {
1455                         SGX_MISC_INFO_HWPERF_RETRIEVE_CB *psRetrieve =
1456                             &psMiscInfo->uData.sRetrieveCB;
1457                         PVRSRV_SGX_HWPERF_CB *psHWPerfCB =
1458                             (PVRSRV_SGX_HWPERF_CB *) psDevInfo->
1459                             psKernelHWPerfCBMemInfo->pvLinAddrKM;
1460                         IMG_UINT i = 0;
1461
1462                         for (;
1463                              psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff
1464                              && i < psRetrieve->ui32ArraySize; i++) {
1465                                 PVRSRV_SGX_HWPERF_CBDATA *psData =
1466                                     &psHWPerfCB->psHWPerfCBData[psHWPerfCB->
1467                                                                 ui32Roff];
1468                                 OSMemCopy(&psRetrieve->psHWPerfData[i], psData,
1469                                           sizeof(PVRSRV_SGX_HWPERF_CBDATA));
1470                                 psRetrieve->psHWPerfData[i].ui32ClockSpeed =
1471                                     psDevInfo->ui32CoreClockSpeed;
1472                                 psRetrieve->psHWPerfData[i].ui32TimeMax =
1473                                     psDevInfo->ui32uKernelTimerClock;
1474                                 psHWPerfCB->ui32Roff =
1475                                     (psHWPerfCB->ui32Roff +
1476                                      1) & (PVRSRV_SGX_HWPERF_CBSIZE - 1);
1477                         }
1478                         psRetrieve->ui32DataCount = i;
1479                         psRetrieve->ui32Time = OSClockus();
1480                         return PVRSRV_OK;
1481                 }
1482 #endif
1483         default:
1484                 {
1485
1486                         return PVRSRV_ERROR_INVALID_PARAMS;
1487                 }
1488         }
1489 }
1490
1491 #if defined(SUPPORT_SGX_HWPERF)
1492 IMG_EXPORT
1493     PVRSRV_ERROR SGXReadDiffCountersKM(IMG_HANDLE hDevHandle,
1494                                        IMG_UINT32 ui32Reg,
1495                                        IMG_UINT32 * pui32Old,
1496                                        IMG_BOOL bNew,
1497                                        IMG_UINT32 ui32New,
1498                                        IMG_UINT32 ui32NewReset,
1499                                        IMG_UINT32 ui32CountersReg,
1500                                        IMG_UINT32 * pui32Time,
1501                                        IMG_BOOL * pbActive,
1502                                        PVRSRV_SGXDEV_DIFF_INFO * psDiffs)
1503 {
1504         PVRSRV_ERROR eError;
1505         SYS_DATA *psSysData;
1506         PVRSRV_POWER_DEV *psPowerDevice;
1507         IMG_BOOL bPowered = IMG_FALSE;
1508         PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
1509         PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1510
1511         if (bNew) {
1512                 psDevInfo->ui32HWGroupRequested = ui32New;
1513         }
1514         psDevInfo->ui32HWReset |= ui32NewReset;
1515
1516         eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
1517         if (eError != PVRSRV_OK) {
1518                 return eError;
1519         }
1520
1521         SysAcquireData(&psSysData);
1522
1523         psPowerDevice = psSysData->psPowerDeviceList;
1524         while (psPowerDevice) {
1525                 if (psPowerDevice->ui32DeviceIndex ==
1526                     psDeviceNode->sDevId.ui32DeviceIndex) {
1527                         bPowered =
1528                             (IMG_BOOL) (psPowerDevice->eCurrentPowerState ==
1529                                         PVRSRV_POWER_STATE_D0);
1530                         break;
1531                 }
1532
1533                 psPowerDevice = psPowerDevice->psNext;
1534         }
1535
1536         *pbActive = bPowered;
1537
1538         {
1539                 PVRSRV_SGXDEV_DIFF_INFO sNew, *psPrev = &psDevInfo->sDiffInfo;
1540                 IMG_UINT32 i;
1541
1542                 sNew.ui32Time[0] = OSClockus();
1543
1544                 *pui32Time = sNew.ui32Time[0];
1545
1546                 if (sNew.ui32Time[0] != psPrev->ui32Time[0] && bPowered) {
1547
1548                         *pui32Old =
1549                             OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32Reg);
1550
1551                         for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
1552                                 sNew.aui32Counters[i] =
1553                                     OSReadHWReg(psDevInfo->pvRegsBaseKM,
1554                                                 ui32CountersReg + (i * 4));
1555                         }
1556
1557                         if (psDevInfo->ui32HWGroupRequested != *pui32Old) {
1558
1559                                 if (psDevInfo->ui32HWReset != 0) {
1560                                         OSWriteHWReg(psDevInfo->pvRegsBaseKM,
1561                                                      ui32Reg,
1562                                                      psDevInfo->
1563                                                      ui32HWGroupRequested |
1564                                                      psDevInfo->ui32HWReset);
1565                                         psDevInfo->ui32HWReset = 0;
1566                                 }
1567
1568                                 OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Reg,
1569                                              psDevInfo->ui32HWGroupRequested);
1570                         }
1571
1572                         sNew.ui32Marker[0] = psDevInfo->ui32KickTACounter;
1573                         sNew.ui32Marker[1] = psDevInfo->ui32KickTARenderCounter;
1574
1575                         sNew.ui32Time[1] =
1576                             psDevInfo->psSGXHostCtl->ui32TimeWraps;
1577
1578                         for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
1579                                 psDiffs->aui32Counters[i] =
1580                                     sNew.aui32Counters[i] -
1581                                     psPrev->aui32Counters[i];
1582                         }
1583
1584                         psDiffs->ui32Marker[0] =
1585                             sNew.ui32Marker[0] - psPrev->ui32Marker[0];
1586                         psDiffs->ui32Marker[1] =
1587                             sNew.ui32Marker[1] - psPrev->ui32Marker[1];
1588
1589                         psDiffs->ui32Time[0] =
1590                             sNew.ui32Time[0] - psPrev->ui32Time[0];
1591                         psDiffs->ui32Time[1] =
1592                             sNew.ui32Time[1] - psPrev->ui32Time[1];
1593
1594                         *psPrev = sNew;
1595                 } else {
1596
1597                         for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
1598                                 psDiffs->aui32Counters[i] = 0;
1599                         }
1600
1601                         psDiffs->ui32Marker[0] = 0;
1602                         psDiffs->ui32Marker[1] = 0;
1603
1604                         psDiffs->ui32Time[0] = 0;
1605                         psDiffs->ui32Time[1] = 0;
1606                 }
1607         }
1608
1609         PVRSRVPowerUnlock(KERNEL_ID);
1610
1611 #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
1612         SGXTestActivePowerEvent(psDeviceNode, KERNEL_ID);
1613 #endif
1614
1615         return eError;
1616 }
1617 #else
1618 #endif