fdad3ef8d64da0c48bef7f4f0724724e10c36dcc
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue / services / server / common / pvrsrv.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          core services functions
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    Main APIs for core services 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 "rgxdebug.h"
45 #include "handle.h"
46 #include "connection_server.h"
47 #include "pdump_km.h"
48 #include "ra.h"
49 #include "allocmem.h"
50 #include "pmr.h"
51 #include "dc_server.h"
52 #include "pvrsrv.h"
53 #include "pvrsrv_device.h"
54 #include "pvr_debug.h"
55 #include "sync.h"
56 #include "sync_server.h"
57 #include "devicemem.h"
58
59 #include "pvrversion.h"
60
61 #include "lists.h"
62 #include "dllist.h"
63 #include "syscommon.h"
64
65 #include "physmem_lma.h"
66 #include "physmem_osmem.h"
67
68 #include "tlintern.h"
69
70 #if defined (SUPPORT_RGX)
71 #include "rgxinit.h"
72 #endif
73
74 #include "debug_request_ids.h"
75 #include "pvrsrv.h"
76
77 #if defined(PVR_RI_DEBUG)
78 #include "ri_server.h"
79 #endif
80
81 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
82 #include "process_stats.h"
83 #endif
84 /*! Wait 100ms before retrying deferred clean-up again */
85 #define CLEANUP_THREAD_WAIT_RETRY_TIMEOUT 0x00000064
86
87 /*! Wait 8hrs when no deferred clean-up required. Allows a poll several times
88  * a day to check for any missed clean-up. */
89 #define CLEANUP_THREAD_WAIT_SLEEP_TIMEOUT 0x01B77400
90
91
92 typedef struct DEBUG_REQUEST_ENTRY_TAG
93 {
94         IMG_UINT32              ui32RequesterID;
95         DLLIST_NODE             sListHead;
96 } DEBUG_REQUEST_ENTRY;
97
98 typedef struct DEBUG_REQUEST_TABLE_TAG
99 {
100         IMG_UINT32                              ui32RequestCount;
101         DEBUG_REQUEST_ENTRY             asEntry[1];
102 }DEBUG_REQUEST_TABLE;
103
104 static PVRSRV_DATA      *gpsPVRSRVData = IMG_NULL;
105 static IMG_HANDLE   g_hDbgSysNotify;
106
107 static PVRSRV_SYSTEM_CONFIG *gpsSysConfig = IMG_NULL;
108
109 typedef PVRSRV_ERROR (*PFN_REGISTER_DEVICE)(PVRSRV_DEVICE_NODE *psDeviceNode);
110 typedef PVRSRV_ERROR (*PFN_UNREGISTER_DEVICE)(PVRSRV_DEVICE_NODE *psDeviceNode);
111
112 static PFN_REGISTER_DEVICE sRegisterDevice[PVRSRV_DEVICE_TYPE_LAST + 1];
113 static PFN_UNREGISTER_DEVICE sUnregisterDevice[PVRSRV_DEVICE_TYPE_LAST + 1];
114
115 static PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PVRSRV_DEVICE_CONFIG *psDevConfig);
116 static PVRSRV_ERROR IMG_CALLCONV PVRSRVUnregisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
117
118 static PVRSRV_ERROR PVRSRVRegisterDbgTable(IMG_UINT32 *paui32Table, IMG_UINT32 ui32Length, IMG_PVOID *phTable);
119 static IMG_VOID PVRSRVUnregisterDbgTable(IMG_PVOID hTable);
120
121 static IMG_VOID _SysDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle, IMG_UINT32 ui32VerbLevel);
122
123 IMG_UINT32      g_ui32InitFlags;
124
125 /* mark which parts of Services were initialised */
126 #define         INIT_DATA_ENABLE_PDUMPINIT      0x1U
127 #define         INIT_GLOBAL_RESMAN 0x2U
128
129 /* Head of the list of callbacks called when Cmd complete happens */
130 static DLLIST_NODE sCmdCompNotifyHead;
131 static POSWR_LOCK hNotifyLock = IMG_NULL;
132
133 /* Debug request table and lock */
134 static POSWR_LOCK g_hDbgNotifyLock = IMG_NULL;
135 static DEBUG_REQUEST_TABLE *g_psDebugTable;
136
137 static IMG_PVOID g_hDebugTable = IMG_NULL;
138
139 static IMG_UINT32 g_aui32DebugOrderTable[] = {
140         DEBUG_REQUEST_SYS,
141         DEBUG_REQUEST_RGX,
142         DEBUG_REQUEST_DC,
143         DEBUG_REQUEST_SERVERSYNC,
144         DEBUG_REQUEST_ANDROIDSYNC
145 };
146
147 DUMPDEBUG_PRINTF_FUNC *g_pfnDumpDebugPrintf = IMG_NULL;
148 /*!
149 ******************************************************************************
150
151  @Function      AllocateDeviceID
152
153  @Description
154
155  allocates a device id from the pool of valid ids
156
157  @input psPVRSRVData :  Services private data
158
159  @input pui32DevID : device id to return
160
161  @Return device id
162
163 ******************************************************************************/
164 static PVRSRV_ERROR AllocateDeviceID(PVRSRV_DATA *psPVRSRVData, IMG_UINT32 *pui32DevID)
165 {
166         SYS_DEVICE_ID* psDeviceWalker;
167         SYS_DEVICE_ID* psDeviceEnd;
168
169         psDeviceWalker = &psPVRSRVData->sDeviceID[0];
170         psDeviceEnd = psDeviceWalker + SYS_DEVICE_COUNT;
171
172         /* find a free ID */
173         while (psDeviceWalker < psDeviceEnd)
174         {
175                 if (!psDeviceWalker->bInUse)
176                 {
177                         psDeviceWalker->bInUse = IMG_TRUE;
178                         *pui32DevID = psDeviceWalker->uiID;
179
180                         return PVRSRV_OK;
181                 }
182                 psDeviceWalker++;
183         }
184
185         PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!"));
186
187         /* Should never get here: sDeviceID[] may have been setup too small */
188         PVR_ASSERT(psDeviceWalker < psDeviceEnd);
189
190         return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVAILABLE;
191 }
192
193
194 /*!
195 ******************************************************************************
196
197  @Function      FreeDeviceID
198
199  @Description
200
201  frees a device id from the pool of valid ids
202
203  @input psPVRSRVData :  Services private data
204
205  @input ui32DevID : device id to free
206
207  @Return device id
208
209 ******************************************************************************/
210 static PVRSRV_ERROR FreeDeviceID(PVRSRV_DATA *psPVRSRVData, IMG_UINT32 ui32DevID)
211 {
212         SYS_DEVICE_ID* psDeviceWalker;
213         SYS_DEVICE_ID* psDeviceEnd;
214
215         psDeviceWalker = &psPVRSRVData->sDeviceID[0];
216         psDeviceEnd = psDeviceWalker + SYS_DEVICE_COUNT;
217
218         /* find the ID to free */
219         while (psDeviceWalker < psDeviceEnd)
220         {
221                 /* if matching id and in use, free */
222                 if      (
223                                 (psDeviceWalker->uiID == ui32DevID) &&
224                                 (psDeviceWalker->bInUse)
225                         )
226                 {
227                         psDeviceWalker->bInUse = IMG_FALSE;
228                         return PVRSRV_OK;
229                 }
230                 psDeviceWalker++;
231         }
232
233         PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
234
235         /* should never get here */
236         PVR_ASSERT(psDeviceWalker < psDeviceEnd);
237
238         return PVRSRV_ERROR_INVALID_DEVICEID;
239 }
240
241
242 /*!
243 ******************************************************************************
244  @Function      PVRSRVEnumerateDevicesKM_ForEachVaCb
245
246  @Description
247
248  Enumerates the device node (if is of the same class as given).
249
250  @Input psDeviceNode    - The device node to be enumerated
251                 va                              - variable arguments list, with:
252                                                         pui32DevCount   - The device count pointer (to be increased)
253                                                         ppeDeviceType     - The pointer to the device type pointer (to be updated and increased)
254                                                         ppeDeviceClass    - The pointer to the device classes pointer (to be updated and increased)
255                                                         ppui32DeviceIndex - The pointer to the device indexes pointer (to be updated and increased)
256 ******************************************************************************/
257 static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
258 {
259         IMG_UINT *pui32DevCount;
260         PVRSRV_DEVICE_TYPE **ppeDeviceType;
261         PVRSRV_DEVICE_CLASS **ppeDeviceClass;
262         IMG_UINT32 **ppui32DeviceIndex;
263
264         pui32DevCount = va_arg(va, IMG_UINT*);
265         ppeDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE**);
266         ppeDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS**);
267         ppui32DeviceIndex = va_arg(va, IMG_UINT32**);
268
269         if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT)
270         {
271                 **ppeDeviceType = psDeviceNode->sDevId.eDeviceType;
272                 **ppeDeviceClass = psDeviceNode->sDevId.eDeviceClass;
273                 **ppui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
274
275                 (*ppeDeviceType)++;
276                 (*ppeDeviceClass)++;
277                 (*ppui32DeviceIndex)++;
278
279                 (*pui32DevCount)++;
280         }
281 }
282
283
284
285 /*!
286 ******************************************************************************
287
288  @Function PVRSRVEnumerateDevicesKM
289
290  @Description
291  This function will enumerate all the devices supported by the
292  PowerVR services within the target system.
293  The function returns a list of the device ID structures stored either in
294  the services or constructed in the user mode glue component in certain
295  environments. The number of devices in the list is also returned.
296
297  In a binary layered component which does not support dynamic runtime selection,
298  the glue code should compile to return the supported devices statically,
299  e.g. multiple instances of the same device if multiple devices are supported,
300  or the target combination of Rogue and display device.
301
302  In the case of an environment (for instance) where one Rogue may connect to two
303  display devices this code would enumerate all three devices and even
304  non-dynamic Rogue selection code should retain the facility to parse the list
305  to find the index of the Rogue device
306
307  @output pui32NumDevices :      On success, contains the number of devices present
308                                                         in the system
309
310  @output peDeviceType    :      Pointer to called supplied buffer to receive the
311                                                         list of PVRSRV_DEVICE_TYPE
312
313  @output peDeviceClass   :      Pointer to called supplied buffer to receive the
314                                                         list of PVRSRV_DEVICE_CLASS
315
316  @output pui32DeviceIndex:      Pointer to called supplied buffer to receive the
317                                                         list of device indexes
318
319  @return PVRSRV_ERROR  :        
320
321 ******************************************************************************/
322 IMG_EXPORT
323 PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
324                                                    PVRSRV_DEVICE_TYPE *peDeviceType,
325                                                    PVRSRV_DEVICE_CLASS *peDeviceClass,
326                                                    IMG_UINT32 *pui32DeviceIndex)
327 {
328         PVRSRV_DATA                     *psPVRSRVData = PVRSRVGetPVRSRVData();
329         IMG_UINT32                      i;
330
331         if (!pui32NumDevices || !peDeviceType || !peDeviceClass || !pui32DeviceIndex)
332         {
333                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params"));
334                 return PVRSRV_ERROR_INVALID_PARAMS;
335         }
336
337         /*
338                 setup input buffer to be `empty'
339         */
340         for (i=0; i<PVRSRV_MAX_DEVICES; i++)
341         {
342                 peDeviceType[i] = PVRSRV_DEVICE_TYPE_UNKNOWN;
343         }
344
345         /* and zero device count */
346         *pui32NumDevices = 0;
347
348         /*
349                 Search through the device list for services managed devices
350                 return id info for each device and the number of devices
351                 available
352         */
353         List_PVRSRV_DEVICE_NODE_ForEach_va(psPVRSRVData->psDeviceNodeList,
354                                                                            &PVRSRVEnumerateDevicesKM_ForEachVaCb,
355                                                                            pui32NumDevices,
356                                                                            &peDeviceType,
357                                                                            &peDeviceClass,
358                                                                            &pui32DeviceIndex);
359
360         return PVRSRV_OK;
361 }
362
363 // #define CLEANUP_DPFL PVR_DBG_WARNING
364 #define CLEANUP_DPFL    PVR_DBG_MESSAGE
365
366 static IMG_VOID CleanupThread(IMG_PVOID pvData)
367 {
368         PVRSRV_DATA *psPVRSRVData = pvData;
369         IMG_BOOL     bRetryCleanup = IMG_FALSE;
370         IMG_HANDLE       hOSEvent;
371         PVRSRV_ERROR eRc;
372         IMG_UINT64   ui64TimesliceLimit;
373
374         /* Store the process id (pid) of the clean-up thread */
375         psPVRSRVData->cleanupThreadPid = OSGetCurrentProcessIDKM();
376
377         PVR_DPF((CLEANUP_DPFL, "CleanupThread: thread starting... "));
378
379         /* Open an event on the clean up event object so we can listen on it,
380          * abort the clean up thread and driver if this fails.
381          */
382         eRc = OSEventObjectOpen(psPVRSRVData->hCleanupEventObject, &hOSEvent);
383         PVR_ASSERT(eRc == PVRSRV_OK);
384
385         /* While the driver is in a good state and is not being unloaded
386          * try to free any deferred items when RESMAN signals
387          */
388         while ((psPVRSRVData->eServicesState == PVRSRV_SERVICES_STATE_OK) && 
389                         (!psPVRSRVData->bUnload))
390         {
391                 /* Wait until RESMAN signals for deferred clean up OR wait for a
392                  * short period if the previous deferred clean up was not able
393                  * to release all the resources before trying again.
394                  * Bridge lock re-acquired on our behalf before the wait call returns.
395                  */
396                 eRc = OSEventObjectWaitTimeout(hOSEvent, (bRetryCleanup) ?
397                                 CLEANUP_THREAD_WAIT_RETRY_TIMEOUT :
398                                 CLEANUP_THREAD_WAIT_SLEEP_TIMEOUT);
399                 if (eRc == PVRSRV_ERROR_TIMEOUT)
400                 {
401                         PVR_DPF((CLEANUP_DPFL, "CleanupThread: wait timeout"));
402                 }
403                 else if (eRc == PVRSRV_OK)
404                 {
405                         PVR_DPF((CLEANUP_DPFL, "CleanupThread: wait OK, signal received"));
406                 }
407                 else
408                 {
409                         PVR_DPF((PVR_DBG_ERROR, "CleanupThread: wait error %d", eRc));
410                 }
411
412                 /* Acquire the bridge lock to protect the flush of the deferred contexts
413                  * and to guarantee the consistency of the deferred contexts list.
414                  * In order to avoid to block the system during the cleanup the lock is
415                  * released periodically every time a specific time expires.
416                  */
417                 OSAcquireBridgeLock();
418
419                 /* Estimate the time limit as soon as we acquire the global lock */
420                 ui64TimesliceLimit = OSClockns64() + RESMAN_DEFERRED_CLEANUP_TIMESLICE_NS;
421
422                 /* Attempt to clean up all deferred contexts that may exist. If
423                  * resources still need cleanup on exit bRetryCleanup set to true.
424                  */
425                 bRetryCleanup = PVRSRVResManFlushDeferContext(
426                                 psPVRSRVData->hResManDeferContext,
427                                 ui64TimesliceLimit);
428
429                 /* Release the bridge lock after the cleanup of the defer context */
430                 OSReleaseBridgeLock();
431         }
432
433         eRc = OSEventObjectClose(hOSEvent);
434         PVR_LOG_IF_ERROR(eRc, "OSEventObjectClose");
435
436         PVR_DPF((CLEANUP_DPFL, "CleanupThread: thread ending... "));
437 }
438
439
440 static IMG_VOID DevicesWatchdogThread(IMG_PVOID pvData)
441 {
442         PVRSRV_DATA *psPVRSRVData = pvData;
443         PVRSRV_DEVICE_HEALTH_STATUS ePreviousHealthStatus = PVRSRV_DEVICE_HEALTH_STATUS_OK;
444         IMG_HANDLE hOSEvent;
445         PVRSRV_ERROR  eError;
446         IMG_UINT32 ui32Timeout = DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT;
447         PVRSRV_DEV_POWER_STATE ePowerState;
448
449         PVR_DPF((PVR_DBG_MESSAGE, "DevicesWatchdogThread: Power off sleep time: %d.",
450                         DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT));
451
452         /* Open an event on the devices watchdog event object so we can listen on it
453            and abort the devices watchdog thread. */
454         eError = OSEventObjectOpen(psPVRSRVData->hDevicesWatchdogEvObj, &hOSEvent);
455         PVR_LOGRN_IF_ERROR(eError, "OSEventObjectOpen");
456
457         /* Loop continuously checking the device status every few seconds. */
458         while (!psPVRSRVData->bUnload)
459         {
460                 IMG_UINT32 i;
461                 IMG_BOOL bPwrIsOn = IMG_FALSE;
462
463                 /* Wait time between polls (done at the start of the loop to allow devices
464                    to initialise) or for the event signal (shutdown or power on). */
465                 eError = OSEventObjectWaitTimeout(hOSEvent, ui32Timeout);
466
467 #ifdef PVR_TESTING_UTILS
468                 psPVRSRVData->ui32DevicesWdWakeupCounter++;
469 #endif
470                 if (eError == PVRSRV_OK)
471                 {
472                         if (psPVRSRVData->bUnload)
473                         {
474                                 PVR_DPF((PVR_DBG_MESSAGE, "DevicesWatchdogThread: Shutdown event received."));
475                                 break;
476                         }
477                         else
478                         {
479                                 PVR_DPF((PVR_DBG_MESSAGE, "DevicesWatchdogThread: Power state change event received."));
480                         }
481                 }
482                 else if (eError != PVRSRV_ERROR_TIMEOUT)
483                 {
484                         /* If timeout do nothing otherwise print warning message. */
485                         PVR_DPF((PVR_DBG_ERROR, "DevicesWatchdogThread: "
486                                         "Error (%d) when waiting for event!", eError));
487                 }
488
489                 eError = PVRSRVPowerLock();
490                 if (eError == PVRSRV_ERROR_RETRY)
491                 {
492                         /* power lock cannot be acquired at this time (sys power is off) */
493                         ui32Timeout = psPVRSRVData->ui32DevicesWatchdogTimeout = DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT;
494                 }
495                 else if (eError != PVRSRV_OK)
496                 {
497                         /* any other error is unexpected */
498                         PVR_DPF((PVR_DBG_ERROR,"DevicesWatchdogThread: Failed to acquire power lock (%s)", PVRSRVGetErrorStringKM(eError)));
499                 }
500                 else
501                 {
502                         /* Check if at least one of the devices is on. */
503                         for (i = 0; i < psPVRSRVData->ui32RegisteredDevices && !bPwrIsOn; i++)
504                         {
505                                 if (PVRSRVGetDevicePowerState(i, &ePowerState) == PVRSRV_OK)
506                                 {
507                                         bPwrIsOn = ePowerState == PVRSRV_DEV_POWER_STATE_ON;
508                                         break;
509                                 }
510                         }
511
512                         if (bPwrIsOn || psPVRSRVData->ui32DevicesWatchdogPwrTrans)
513                         {
514                                 psPVRSRVData->ui32DevicesWatchdogPwrTrans = 0;
515                                 ui32Timeout = psPVRSRVData->ui32DevicesWatchdogTimeout = DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT;
516                         }
517                         else
518                         {
519                                 ui32Timeout = psPVRSRVData->ui32DevicesWatchdogTimeout = DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT;
520                         }
521
522                         PVRSRVPowerUnlock();
523                 }
524
525                 for (i = 0;  i < psPVRSRVData->ui32RegisteredDevices; i++)
526                 {
527                         PVRSRV_DEVICE_NODE* psDeviceNode = psPVRSRVData->apsRegisteredDevNodes[i];
528                         PVRSRV_RGXDEV_INFO* psDevInfo = (PVRSRV_RGXDEV_INFO*) psDeviceNode->pvDevice;
529                         
530                         if (psDeviceNode->pfnUpdateHealthStatus != IMG_NULL)
531                         {
532                                 eError = psDeviceNode->pfnUpdateHealthStatus(psDeviceNode, IMG_TRUE);
533                                 if (eError != PVRSRV_OK)
534                                 {
535                                         PVR_DPF((PVR_DBG_WARNING, "DevicesWatchdogThread: "
536                                                         "Could not check for fatal error (%d)!",
537                                                         eError));
538                                 }
539                         }
540
541                         if (psDeviceNode->eHealthStatus != PVRSRV_DEVICE_HEALTH_STATUS_OK)
542                         {
543                                 if (psDeviceNode->eHealthStatus != ePreviousHealthStatus)
544                                 {
545                                         if (!(psDevInfo->ui32DeviceFlags & RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN))
546                                         {
547                                                 PVR_DPF((PVR_DBG_ERROR, "DevicesWatchdogThread: Device not responding!!!"));
548                                                 PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, IMG_NULL);
549                                         }
550                                 }
551                         }
552                         ePreviousHealthStatus = psDeviceNode->eHealthStatus;
553                         
554                         /* Attempt to service the HWPerf buffer to regularly transport 
555                          * idle / periodic packets to host buffer. */
556                         if (psDeviceNode->pfnServiceHWPerf != IMG_NULL)
557                         {
558                                 eError = psDeviceNode->pfnServiceHWPerf(psDeviceNode);
559                                 if (eError != PVRSRV_OK)
560                                 {
561                                         PVR_DPF((PVR_DBG_WARNING, "DevicesWatchdogThread: "
562                                                         "Error occurred when servicing HWPerf buffer (%d)",
563                                                         eError));
564                                 }
565                         }
566                 }
567         }
568
569         eError = OSEventObjectClose(hOSEvent);
570         PVR_LOG_IF_ERROR(eError, "OSEventObjectClose");
571 }
572
573
574 PVRSRV_DATA *PVRSRVGetPVRSRVData()
575 {
576         return gpsPVRSRVData;
577 }
578
579
580 PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(IMG_VOID)
581 {
582         PVRSRV_ERROR    eError;
583         PVRSRV_SYSTEM_CONFIG *psSysConfig;
584         IMG_UINT32 i;
585
586 #if defined (SUPPORT_RGX)
587         
588         sRegisterDevice[PVRSRV_DEVICE_TYPE_RGX] = RGXRegisterDevice;
589 #endif
590
591         SET_LOG2_PAGESIZE(OSGetPageShift());
592
593         eError = PhysHeapInit();
594         if (eError != PVRSRV_OK)
595         {
596                 goto Error;
597         }
598
599         /* Get the system config */
600         eError = SysCreateConfigData(&psSysConfig);
601         if (eError != PVRSRV_OK)
602         {
603                 return eError;
604         }
605
606         /* Save to global pointer for later */
607         gpsSysConfig = psSysConfig;
608
609     /*
610      * Allocate the device-independent data
611      */
612     gpsPVRSRVData = OSAllocMem(sizeof(*gpsPVRSRVData));
613     if (gpsPVRSRVData == IMG_NULL)
614     {
615         return PVRSRV_ERROR_OUT_OF_MEMORY;
616     }
617     OSMemSet(gpsPVRSRVData, 0, sizeof(*gpsPVRSRVData));
618         gpsPVRSRVData->ui32NumDevices = psSysConfig->uiDeviceCount;
619
620         for (i=0;i<SYS_DEVICE_COUNT;i++)
621         {
622                 gpsPVRSRVData->sDeviceID[i].uiID = i;
623                 gpsPVRSRVData->sDeviceID[i].bInUse = IMG_FALSE;
624         }
625
626         /*
627          * Register the physical memory heaps
628          */
629         PVR_ASSERT(psSysConfig->ui32PhysHeapCount <= SYS_PHYS_HEAP_COUNT);
630         for (i=0;i<psSysConfig->ui32PhysHeapCount;i++)
631         {
632                 eError = PhysHeapRegister(&psSysConfig->pasPhysHeaps[i],
633                                                                   &gpsPVRSRVData->apsRegisteredPhysHeaps[i]);
634                 if (eError != PVRSRV_OK)
635                 {
636                         goto Error;
637                 }
638                 gpsPVRSRVData->ui32RegisteredPhysHeaps++;
639         }
640
641         /* Init any OS specific's */
642         eError = OSInitEnvData();
643         if (eError != PVRSRV_OK)
644         {
645                 goto Error;
646         }
647
648         /* Initialise Resource Manager */
649         eError = ResManInit();
650         if (eError != PVRSRV_OK)
651         {
652                 goto Error;
653         }
654
655         eError = PVRSRVConnectionInit();
656         if(eError != PVRSRV_OK)
657         {
658                 goto Error;
659         }
660
661 #if defined(PVR_RI_DEBUG)
662         RIInitKM();
663 #endif
664
665         eError = PMRInit();
666         if (eError != PVRSRV_OK)
667         {
668                 goto Error;
669         }
670
671 #if !defined(UNDER_WDDM) && defined(SUPPORT_DISPLAY_CLASS)
672         eError = DCInit();
673         if (eError != PVRSRV_OK)
674         {
675                 goto Error;
676         }
677 #endif
678
679         /* Initialise handles */
680         eError = PVRSRVHandleInit();
681         if(eError != PVRSRV_OK)
682         {
683                 goto Error;
684         }
685
686         /* Initialise Power Manager Lock */
687         eError = OSLockCreate(&gpsPVRSRVData->hPowerLock, LOCK_TYPE_PASSIVE);
688         if (eError != PVRSRV_OK)
689         {
690                 goto Error;
691         }
692
693         /* Initialise system power state */
694         gpsPVRSRVData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_ON;
695         gpsPVRSRVData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
696
697         /* Initialise overall system state */
698         gpsPVRSRVData->eServicesState = PVRSRV_SERVICES_STATE_OK;
699
700         /* Create an event object */
701         eError = OSEventObjectCreate("PVRSRV_GLOBAL_EVENTOBJECT", &gpsPVRSRVData->hGlobalEventObject);
702         if (eError != PVRSRV_OK)
703         {
704                 goto Error;
705         }
706         gpsPVRSRVData->ui32GEOConsecutiveTimeouts = 0;
707
708         /* initialise list of command complete notifiers */
709         dllist_init(&sCmdCompNotifyHead);
710
711         /* Create a lock of the list notifiers */
712         eError = OSWRLockCreate(&hNotifyLock);
713         if (eError != PVRSRV_OK)
714         {
715                 goto Error;
716         }
717
718         /* Create a lock of the debug notifiers */
719         eError = OSWRLockCreate(&g_hDbgNotifyLock);
720         if (eError != PVRSRV_OK)
721         {
722                 goto Error;
723         }
724
725         eError = PVRSRVRegisterDbgTable(g_aui32DebugOrderTable,
726                                                                         sizeof(g_aui32DebugOrderTable)/sizeof(g_aui32DebugOrderTable[0]),
727                                                                         &g_hDebugTable);
728         if (eError != PVRSRV_OK)
729         {
730                 goto Error;
731         }
732
733         PVRSRVRegisterDbgRequestNotify(&g_hDbgSysNotify, &_SysDebugRequestNotify, DEBUG_REQUEST_SYS, gpsPVRSRVData);
734
735         eError = ServerSyncInit();
736         if (eError != PVRSRV_OK)
737         {
738                 goto Error;
739         }
740
741         /* Initialise pdump */
742         eError = PDUMPINIT();
743         if(eError != PVRSRV_OK)
744         {
745                 goto Error;
746         }
747
748         g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT;
749
750         /* Register all the system devices */
751         for (i=0;i<psSysConfig->uiDeviceCount;i++)
752         {
753                 if (PVRSRVRegisterDevice(&psSysConfig->pasDevices[i]) != PVRSRV_OK)
754                 {
755                         
756                         return eError;
757                 }
758
759                 /* Initialise the Transport Layer.
760                  * Need to remember the RGX device node for use in the Transport Layer
761                  * when allocating stream buffers that are shared with clients.
762                  * Note however when the device is an LMA device our buffers will not
763                  * be in host memory but card memory.
764                  */
765                 if (gpsPVRSRVData->apsRegisteredDevNodes[gpsPVRSRVData->ui32RegisteredDevices-1]->psDevConfig->eDeviceType == PVRSRV_DEVICE_TYPE_RGX)
766                 {
767                         eError = TLInit(gpsPVRSRVData->apsRegisteredDevNodes[gpsPVRSRVData->ui32RegisteredDevices-1]);
768                         PVR_LOGG_IF_ERROR(eError, "TLInit", Error);
769                 }
770         }
771
772         /* Create the clean up event object */
773         eError = OSEventObjectCreate("PVRSRV_CLEANUP_EVENTOBJECT", &gpsPVRSRVData->hCleanupEventObject);
774         PVR_LOGG_IF_ERROR(eError, "OSEventObjectCreate", Error);
775
776         eError = PVRSRVResManCreateDeferContext(gpsPVRSRVData->hCleanupEventObject,
777                         &gpsPVRSRVData->hResManDeferContext);
778         PVR_LOGG_IF_ERROR(eError, "PVRSRVResManCreateDeferContext", Error);
779
780         g_ui32InitFlags |= INIT_GLOBAL_RESMAN;
781
782         /* Create a thread which is used to do the deferred cleanup running with the
783          * lowest priority */
784         eError = OSThreadCreatePriority(&gpsPVRSRVData->hCleanupThread,
785                                                         "pvr_defer_free",
786                                                         CleanupThread,
787                                                         gpsPVRSRVData,
788                                                         LOWEST_PRIORITY);
789
790         if (eError != PVRSRV_OK)
791         {
792                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVInit: Failed to create deferred cleanup thread"));
793                 goto Error;
794         }
795
796         /* Create the devices watchdog event object */
797         eError = OSEventObjectCreate("PVRSRV_DEVICESWATCHDOG_EVENTOBJECT", &gpsPVRSRVData->hDevicesWatchdogEvObj);
798         PVR_LOGG_IF_ERROR(eError, "OSEventObjectCreate", Error);
799
800         /* Create a thread which is used to detect fatal errors */
801         eError = OSThreadCreate(&gpsPVRSRVData->hDevicesWatchdogThread,
802                                                         "pvr_devices_wd_thread",
803                                                         DevicesWatchdogThread,
804                                                         gpsPVRSRVData);
805         if (eError != PVRSRV_OK)
806         {
807                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVInit: Failed to create devices watchdog thread"));
808                 goto Error;
809         }
810
811 #if defined(PVR_TESTING_UTILS)
812         TUtilsInit();
813 #endif
814
815         return eError;
816
817 Error:
818         PVRSRVDeInit();
819         return eError;
820 }
821
822
823 IMG_VOID IMG_CALLCONV PVRSRVDeInit(IMG_VOID)
824 {
825         PVRSRV_DATA             *psPVRSRVData = PVRSRVGetPVRSRVData();
826         PVRSRV_ERROR    eError;
827         IMG_UINT32              i;
828
829         if (gpsPVRSRVData == IMG_NULL)
830         {
831                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit failed - invalid gpsPVRSRVData"));
832                 return;
833         }
834
835 #if defined(PVR_TESTING_UTILS)
836         TUtilsDeinit();
837 #endif
838
839 #if defined (SUPPORT_RGX)
840         sUnregisterDevice[PVRSRV_DEVICE_TYPE_RGX] = DevDeInitRGX;
841 #endif
842
843         psPVRSRVData->bUnload = IMG_TRUE;
844         if (psPVRSRVData->hGlobalEventObject)
845         {
846                 OSEventObjectSignal(psPVRSRVData->hGlobalEventObject);
847         }
848
849         /* Stop and cleanup the devices watchdog thread */
850         if (psPVRSRVData->hDevicesWatchdogThread)
851         {
852                 if (psPVRSRVData->hDevicesWatchdogEvObj)
853                 {
854                         eError = OSEventObjectSignal(psPVRSRVData->hDevicesWatchdogEvObj);
855                         PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
856                 }
857                 eError = OSThreadDestroy(gpsPVRSRVData->hDevicesWatchdogThread);
858                 gpsPVRSRVData->hDevicesWatchdogThread = IMG_NULL;
859                 PVR_LOG_IF_ERROR(eError, "OSThreadDestroy");
860         }
861
862         if (gpsPVRSRVData->hDevicesWatchdogEvObj)
863         {
864                 eError = OSEventObjectDestroy(gpsPVRSRVData->hDevicesWatchdogEvObj);
865                 gpsPVRSRVData->hDevicesWatchdogEvObj = IMG_NULL;
866                 PVR_LOG_IF_ERROR(eError, "OSEventObjectDestroy");
867         }
868
869         /* Stop and cleanup the deferred clean up thread, event object and
870          * deferred context list.
871          */
872         if (psPVRSRVData->hCleanupThread)
873         {
874                 if (psPVRSRVData->hCleanupEventObject)
875                 {
876                         eError = OSEventObjectSignal(psPVRSRVData->hCleanupEventObject);
877                         PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
878                 }
879                 eError = OSThreadDestroy(gpsPVRSRVData->hCleanupThread);
880                 gpsPVRSRVData->hCleanupThread = IMG_NULL;
881                 PVR_LOG_IF_ERROR(eError, "OSThreadDestroy");
882         }
883
884         if (gpsPVRSRVData->hCleanupEventObject)
885         {
886                 eError = OSEventObjectDestroy(gpsPVRSRVData->hCleanupEventObject);
887                 gpsPVRSRVData->hCleanupEventObject = IMG_NULL;
888                 PVR_LOG_IF_ERROR(eError, "OSEventObjectDestroy");
889         }
890
891         if (g_ui32InitFlags & INIT_GLOBAL_RESMAN)
892         {
893                 PVRSRVResManDestroyDeferContext(gpsPVRSRVData->hResManDeferContext);
894         }
895
896         /* Unregister all the system devices */
897         for (i=0;i<psPVRSRVData->ui32RegisteredDevices;i++)
898         {
899                 PVRSRV_DEVICE_NODE *psDeviceNode = psPVRSRVData->apsRegisteredDevNodes[i];
900
901                 /* set device state */
902                 psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_DEINIT;
903
904                 /* Counter part to what gets done in PVRSRVFinaliseSystem */
905                 if (psDeviceNode->hSyncPrimContext != IMG_NULL)
906                 {
907                         if (psDeviceNode->psSyncPrim != IMG_NULL)
908                         {
909                                 /* Free general pupose sync primitive */
910                                 SyncPrimFree(psDeviceNode->psSyncPrim);
911                                 psDeviceNode->psSyncPrim = IMG_NULL;
912                         }
913                         if (psDeviceNode->psSyncPrimPreKick != IMG_NULL)
914                         {
915                                 /* Free PreKick sync primitive */
916                                 SyncPrimFree(psDeviceNode->psSyncPrimPreKick);
917                                 psDeviceNode->psSyncPrimPreKick = IMG_NULL;
918                         }
919
920                         SyncPrimContextDestroy(psDeviceNode->hSyncPrimContext);
921                         psDeviceNode->hSyncPrimContext = IMG_NULL;
922                 }
923
924                 PVRSRVUnregisterDevice(psDeviceNode);
925                 psPVRSRVData->apsRegisteredDevNodes[i] = IMG_NULL;
926         }
927         SysDestroyConfigData(gpsSysConfig);
928
929         /* Clean up Transport Layer resources that remain. 
930          * Done after RGX node clean up as HWPerf stream is destroyed during 
931          * this
932          */
933         TLDeInit();
934
935         ServerSyncDeinit();
936
937         if (g_hDbgSysNotify)
938         {
939                 PVRSRVUnregisterDbgRequestNotify(g_hDbgSysNotify);
940         }
941
942         if (g_hDebugTable)
943         {
944                 PVRSRVUnregisterDbgTable(g_hDebugTable);
945         }
946
947         if (g_hDbgNotifyLock)
948         {
949                 OSWRLockDestroy(g_hDbgNotifyLock);
950         }
951
952         if (hNotifyLock)
953         {
954                 OSWRLockDestroy(hNotifyLock);
955         }
956
957         /* deinitialise pdump */
958         if ((g_ui32InitFlags & INIT_DATA_ENABLE_PDUMPINIT) > 0)
959         {
960                 PDUMPDEINIT();
961         }
962         
963         /* destroy event object */
964         if (gpsPVRSRVData->hGlobalEventObject)
965         {
966                 OSEventObjectDestroy(gpsPVRSRVData->hGlobalEventObject);
967                 gpsPVRSRVData->hGlobalEventObject = IMG_NULL;
968         }
969
970         /* Check there is no notify function */
971         if (!dllist_is_empty(&sCmdCompNotifyHead))
972         {
973                 PDLLIST_NODE psNode = dllist_get_next_node(&sCmdCompNotifyHead);
974
975                 /* some device did not unregistered properly */
976                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: Notify list for cmd complete is not empty!!"));
977
978                 /* clean the nodes anyway */
979                 while (psNode != IMG_NULL)
980                 {
981                         PVRSRV_CMDCOMP_NOTIFY   *psNotify;
982
983                         dllist_remove_node(psNode);
984                         
985                         psNotify = IMG_CONTAINER_OF(psNode, PVRSRV_CMDCOMP_NOTIFY, sListNode);
986                         OSFreeMem(psNotify);
987
988                         psNode = dllist_get_next_node(&sCmdCompNotifyHead);
989                 }
990         }
991
992         OSLockDestroy(gpsPVRSRVData->hPowerLock);
993
994         eError = PVRSRVHandleDeInit();
995         if (eError != PVRSRV_OK)
996         {
997                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed"));
998         }
999
1000 #if !defined(UNDER_WDDM) && defined(SUPPORT_DISPLAY_CLASS)
1001         eError = DCDeInit();
1002         if (eError != PVRSRV_OK)
1003         {
1004                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: DCInit() failed"));
1005         }
1006 #endif
1007
1008
1009     eError = PMRDeInit();
1010         if (eError != PVRSRV_OK)
1011         {
1012                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PMRDeInit() failed"));
1013         }
1014
1015 #if defined(PVR_RI_DEBUG)
1016         RIDeInitKM();
1017 #endif
1018
1019         eError = PVRSRVConnectionDeInit();
1020         if (eError != PVRSRV_OK)
1021         {
1022                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVConnectionDataDeInit failed"));
1023         }
1024
1025         ResManDeInit();
1026         
1027         OSDeInitEnvData();
1028
1029         for (i=0;i<gpsPVRSRVData->ui32RegisteredPhysHeaps;i++)
1030         {
1031                 PhysHeapUnregister(gpsPVRSRVData->apsRegisteredPhysHeaps[i]);
1032         }
1033         eError = PhysHeapDeinit();
1034         if (eError != PVRSRV_OK)
1035         {
1036                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PhysHeapDeinit() failed"));
1037         }
1038
1039         OSFreeMem(gpsPVRSRVData);
1040         gpsPVRSRVData = IMG_NULL;
1041 }
1042
1043 PVRSRV_ERROR LMA_MMUPxAlloc(PVRSRV_DEVICE_NODE *psDevNode, IMG_SIZE_T uiSize,
1044                                                         Px_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr)
1045 {
1046         IMG_BOOL bSuccess;
1047         RA_BASE_T uiCardAddr;
1048         RA_LENGTH_T uiActualSize;
1049
1050         PVR_ASSERT((uiSize & OSGetPageMask()) == 0);
1051
1052         bSuccess = RA_Alloc(psDevNode->psLocalDevMemArena, 
1053                                                 uiSize,
1054                                                 0,                                      /* No flags */
1055                                                 OSGetPageSize(),
1056                                                 &uiCardAddr,
1057                                                 &uiActualSize,
1058                                                 IMG_NULL);                      /* No private handle */
1059
1060         PVR_ASSERT(uiSize == uiActualSize);
1061
1062         psMemHandle->u.ui64Handle = uiCardAddr;
1063         psDevPAddr->uiAddr = (IMG_UINT64) uiCardAddr;
1064
1065         if (bSuccess)
1066         {
1067 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
1068 #if !defined(PVRSRV_ENABLE_MEMORY_STATS)
1069         /* Allocation is done a page at a time */
1070         PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA, OSGetPageSize());
1071 #else
1072                 IMG_CPU_PHYADDR sCpuPAddr;
1073                 sCpuPAddr.uiAddr = psDevPAddr->uiAddr;
1074                 PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
1075                                                                                                                          IMG_NULL,
1076                                                                                                                          sCpuPAddr,
1077                                                                                                                          OSGetPageSize(),
1078                                                                                                                          IMG_NULL);
1079 #endif
1080 #endif
1081                 return PVRSRV_OK;
1082         }
1083         else
1084                 return PVRSRV_ERROR_OUT_OF_MEMORY;
1085 }
1086
1087 IMG_VOID LMA_MMUPxFree(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle)
1088 {
1089         RA_BASE_T uiCardAddr = (RA_BASE_T) psMemHandle->u.ui64Handle;
1090
1091 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
1092 #if !defined(PVRSRV_ENABLE_MEMORY_STATS)
1093         /* Allocation is done a page at a time */
1094         PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA, OSGetPageSize());
1095 #else
1096                 PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA, (IMG_UINT64)uiCardAddr);
1097 #endif
1098 #endif
1099
1100         RA_Free(psDevNode->psLocalDevMemArena, uiCardAddr);
1101 }
1102
1103 PVRSRV_ERROR LMA_MMUPxMap(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle,
1104                                                         IMG_SIZE_T uiSize, IMG_DEV_PHYADDR *psDevPAddr,
1105                                                         IMG_VOID **pvPtr)
1106 {
1107         IMG_CPU_PHYADDR sCpuPAddr;
1108         PVR_UNREFERENCED_PARAMETER(psMemHandle);
1109         PVR_UNREFERENCED_PARAMETER(uiSize);
1110
1111         PhysHeapDevPAddrToCpuPAddr(psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], &sCpuPAddr, psDevPAddr);
1112         *pvPtr = OSMapPhysToLin(sCpuPAddr,
1113                                                         OSGetPageSize(),
1114                                                         0);
1115         if (*pvPtr == IMG_NULL)
1116         {
1117                 return PVRSRV_ERROR_OUT_OF_MEMORY;
1118         }
1119         else
1120         {
1121 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
1122 #if !defined(PVRSRV_ENABLE_MEMORY_STATS)
1123                 /* Mapping is done a page at a time */
1124                 PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, OSGetPageSize());
1125 #else
1126                 {
1127                         PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA,
1128                                                                                  *pvPtr,
1129                                                                                  sCpuPAddr,
1130                                                                                  uiSize,
1131                                                                                  IMG_NULL);
1132                 }
1133 #endif
1134 #endif
1135                 return PVRSRV_OK;
1136         }
1137 }
1138
1139 IMG_VOID LMA_MMUPxUnmap(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle,
1140                                                 IMG_VOID *pvPtr)
1141 {
1142         PVR_UNREFERENCED_PARAMETER(psMemHandle);
1143         PVR_UNREFERENCED_PARAMETER(psDevNode);
1144
1145 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
1146 #if !defined(PVRSRV_ENABLE_MEMORY_STATS)
1147                 /* Mapping is done a page at a time */
1148                 PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, OSGetPageSize());
1149 #else
1150         PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, (IMG_UINT64)(IMG_UINTPTR_T)pvPtr);
1151 #endif
1152 #endif
1153
1154         OSUnMapPhysToLin(pvPtr, OSGetPageSize(), 0);
1155 }
1156
1157 /*!
1158 ******************************************************************************
1159
1160  @Function      PVRSRVRegisterDevice
1161
1162  @Description
1163
1164  registers a device with the system
1165
1166  @Input    psDevConfig                  : Device configuration structure
1167
1168  @Return   PVRSRV_ERROR  :
1169
1170 ******************************************************************************/
1171 static PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PVRSRV_DEVICE_CONFIG *psDevConfig)
1172 {
1173         PVRSRV_DATA                             *psPVRSRVData = PVRSRVGetPVRSRVData();
1174         PVRSRV_ERROR                    eError;
1175         PVRSRV_DEVICE_NODE              *psDeviceNode;
1176         PVRSRV_DEVICE_PHYS_HEAP physHeapIndex;
1177
1178         /* Allocate device node */
1179         psDeviceNode = OSAllocMem(sizeof(PVRSRV_DEVICE_NODE));
1180         if (psDeviceNode == IMG_NULL)
1181         {
1182                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode"));
1183                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1184                 goto e0;
1185         }
1186         OSMemSet(psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
1187
1188         /* set device state */
1189         psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_INIT;
1190
1191         eError = PhysHeapAcquire(psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], &psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
1192         if (eError != PVRSRV_OK)
1193         {
1194                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to acquire PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL physical memory heap"));
1195                 goto e1;
1196         }
1197         eError = PhysHeapAcquire(psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL], &psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL]);
1198         if (eError != PVRSRV_OK)
1199         {
1200                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to acquire PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL physical memory heap"));
1201                 goto e1;
1202         }
1203
1204         /* Do we have card memory? If so create an RA to manage it */
1205         if (PhysHeapGetType(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]) == PHYS_HEAP_TYPE_LMA)
1206         {
1207                 RA_BASE_T uBase;
1208                 RA_LENGTH_T uSize;
1209                 IMG_CPU_PHYADDR sCpuPAddr;
1210                 IMG_UINT64 ui64Size;
1211
1212                 eError = PhysHeapGetAddress(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], &sCpuPAddr);
1213                 if (eError != PVRSRV_OK)
1214                 {
1215                         /* We can only get here if there is a bug in this module */
1216                         PVR_ASSERT(IMG_FALSE);
1217                         return eError;
1218                 }
1219
1220                 eError = PhysHeapGetSize(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], &ui64Size);
1221                 if (eError != PVRSRV_OK)
1222                 {
1223                         /* We can only get here if there is a bug in this module */
1224                         PVR_ASSERT(IMG_FALSE);
1225                         return eError;
1226                 }
1227
1228
1229                 PVR_DPF((PVR_DBG_MESSAGE, "Creating RA for card memory 0x%016llx-0x%016llx",
1230                                  (IMG_UINT64) sCpuPAddr.uiAddr, sCpuPAddr.uiAddr + ui64Size));
1231
1232                 OSSNPrintf(psDeviceNode->szRAName, sizeof(psDeviceNode->szRAName),
1233                                                                                         "%s card mem",
1234                                                                                         psDevConfig->pszName);
1235
1236                 uBase = 0;
1237                 if (psDevConfig->uiFlags & PVRSRV_DEVICE_CONFIG_LMA_USE_CPU_ADDR)
1238                 {
1239                         uBase = sCpuPAddr.uiAddr;
1240                 }
1241
1242                 uSize = (RA_LENGTH_T) ui64Size;
1243                 PVR_ASSERT(uSize == ui64Size);
1244
1245                 psDeviceNode->psLocalDevMemArena =
1246                         RA_Create(psDeviceNode->szRAName,
1247                                                 OSGetPageShift(),       /* Use host page size, keeps things simple */
1248                                                 RA_LOCKCLASS_0,     /* This arena doesn't use any other arenas. */
1249                                                 IMG_NULL,                       /* No Import */
1250                                                 IMG_NULL,                       /* No free import */
1251                                                 IMG_NULL);                      /* No import handle */
1252
1253                 if (psDeviceNode->psLocalDevMemArena == IMG_NULL)
1254                 {
1255                         eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1256                         goto e2;
1257                 }
1258
1259                 if (!RA_Add(psDeviceNode->psLocalDevMemArena, uBase, uSize, 0 /* No flags */, IMG_NULL /* No private data */))
1260                 {
1261                         RA_Delete(psDeviceNode->psLocalDevMemArena);
1262                         eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1263                         goto e2;                
1264                 }
1265
1266
1267                 psDeviceNode->pfnMMUPxAlloc = LMA_MMUPxAlloc;
1268                 psDeviceNode->pfnMMUPxFree = LMA_MMUPxFree;
1269                 psDeviceNode->pfnMMUPxMap = LMA_MMUPxMap;
1270                 psDeviceNode->pfnMMUPxUnmap = LMA_MMUPxUnmap;
1271                 psDeviceNode->uiMMUPxLog2AllocGran = OSGetPageShift();
1272                 psDeviceNode->ui32Flags = PRVSRV_DEVICE_FLAGS_LMA;
1273                 psDeviceNode->pfnCreateRamBackedPMR[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL] = PhysmemNewLocalRamBackedPMR;
1274         }
1275         else
1276         {
1277                 PVR_DPF((PVR_DBG_MESSAGE, "===== OS System memory only, no local card memory"));
1278
1279                 /* else we only have OS system memory */
1280                 psDeviceNode->pfnMMUPxAlloc = OSMMUPxAlloc;
1281                 psDeviceNode->pfnMMUPxFree = OSMMUPxFree;
1282                 psDeviceNode->pfnMMUPxMap = OSMMUPxMap;
1283                 psDeviceNode->pfnMMUPxUnmap = OSMMUPxUnmap;
1284                 psDeviceNode->pfnCreateRamBackedPMR[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL] = PhysmemNewOSRamBackedPMR;
1285         }
1286
1287         if (PhysHeapGetType(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL]) == PHYS_HEAP_TYPE_LMA)
1288         {
1289                 PVR_DPF((PVR_DBG_MESSAGE, "===== Local card memory only, no OS system memory"));
1290                 psDeviceNode->pfnCreateRamBackedPMR[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL] = PhysmemNewLocalRamBackedPMR;
1291         }
1292         else
1293         {
1294                 PVR_DPF((PVR_DBG_MESSAGE, "===== OS System memory, 2nd phys heap"));
1295                 psDeviceNode->pfnCreateRamBackedPMR[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL] = PhysmemNewOSRamBackedPMR;
1296         }
1297
1298         
1299         psDeviceNode->pszMMUPxPDumpMemSpaceName = PhysHeapPDumpMemspaceName(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
1300         psDeviceNode->uiMMUPxLog2AllocGran = OSGetPageShift();
1301
1302         /* Add the devnode to our list so we can unregister it later */
1303         psPVRSRVData->apsRegisteredDevNodes[psPVRSRVData->ui32RegisteredDevices++] = psDeviceNode;
1304
1305         psDeviceNode->ui32RefCount = 1;
1306         psDeviceNode->psDevConfig = psDevConfig;
1307
1308         /* all devices need a unique identifier */
1309         AllocateDeviceID(psPVRSRVData, &psDeviceNode->sDevId.ui32DeviceIndex);
1310
1311         /* Device type and class will be setup during this callback */
1312         eError = sRegisterDevice[psDevConfig->eDeviceType](psDeviceNode);
1313         if (eError != PVRSRV_OK)
1314         {
1315                 /*not nulling pointer, out of scope*/
1316                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
1317                 eError = PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
1318                 goto e3;
1319         }
1320
1321
1322         PVR_DPF((PVR_DBG_MESSAGE, "Registered device %d of type %d", psDeviceNode->sDevId.ui32DeviceIndex, psDeviceNode->sDevId.eDeviceType));
1323         PVR_DPF((PVR_DBG_MESSAGE, "Register bank address = 0x%08lx", (unsigned long)psDevConfig->sRegsCpuPBase.uiAddr));
1324         PVR_DPF((PVR_DBG_MESSAGE, "IRQ = %d", psDevConfig->ui32IRQ));
1325         
1326         /* and finally insert the device into the dev-list */
1327         List_PVRSRV_DEVICE_NODE_Insert(&psPVRSRVData->psDeviceNodeList, psDeviceNode);
1328
1329         /* set device state */
1330         psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_ACTIVE;
1331
1332         return PVRSRV_OK;
1333 e3:
1334         if (psDeviceNode->psLocalDevMemArena)
1335         {
1336                 RA_Delete(psDeviceNode->psLocalDevMemArena);
1337         }
1338 e2:
1339 e1:
1340         for(physHeapIndex=0; physHeapIndex < PVRSRV_DEVICE_PHYS_HEAP_LAST; physHeapIndex++)
1341         {
1342                 if (psDeviceNode->apsPhysHeap[physHeapIndex])
1343                 {
1344                         PhysHeapRelease(psDeviceNode->apsPhysHeap[physHeapIndex]);
1345                 }
1346         }
1347         OSFreeMem(psDeviceNode);
1348 e0:
1349         return eError;
1350 }
1351
1352 PVRSRV_ERROR IMG_CALLCONV PVRSRVSysPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState, IMG_BOOL bForced)
1353 {
1354         PVRSRV_ERROR eError = PVRSRV_OK;
1355
1356         PVR_UNREFERENCED_PARAMETER(bForced);
1357
1358         if (gpsSysConfig->pfnSysPrePowerState)
1359         {
1360                 eError = gpsSysConfig->pfnSysPrePowerState(eNewPowerState);
1361         }
1362         return eError;
1363 }
1364
1365 PVRSRV_ERROR IMG_CALLCONV PVRSRVSysPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState, IMG_BOOL bForced)
1366 {
1367         PVRSRV_ERROR eError = PVRSRV_OK;
1368
1369         PVR_UNREFERENCED_PARAMETER(bForced);
1370
1371         if (gpsSysConfig->pfnSysPostPowerState)
1372         {
1373                 eError = gpsSysConfig->pfnSysPostPowerState(eNewPowerState);
1374         }
1375         return eError;
1376 }
1377
1378 PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterExtDevice(PVRSRV_DEVICE_NODE *psDeviceNode,
1379                                                                                                         IMG_UINT32 *pui32DeviceIndex,
1380                                                                                                         IMG_UINT32 ui32PhysHeapID)
1381 {
1382         PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
1383         PHYS_HEAP   *psPhysHeapTmp;
1384         PVRSRV_DEVICE_PHYS_HEAP eDevPhysHeap;
1385         PVRSRV_ERROR eError;
1386
1387         psDeviceNode->ui32RefCount = 1;
1388
1389         eError = PhysHeapAcquire(ui32PhysHeapID, &psPhysHeapTmp);
1390         if (eError != PVRSRV_OK)
1391         {
1392                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterExtDevice: Failed to acquire physical memory heap"));
1393                 goto e0;
1394         }
1395         if (PhysHeapGetType(psPhysHeapTmp) == PHYS_HEAP_TYPE_LMA)
1396         {
1397                 eDevPhysHeap = PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL;
1398         }
1399         else
1400         {
1401                 eDevPhysHeap = PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL;
1402         }
1403         psDeviceNode->apsPhysHeap[eDevPhysHeap] = psPhysHeapTmp;
1404
1405         /* allocate a unique device id */
1406         eError = AllocateDeviceID(psPVRSRVData, &psDeviceNode->sDevId.ui32DeviceIndex);
1407         if (eError != PVRSRV_OK)
1408         {
1409                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterExtDevice: Failed to allocate Device ID"));
1410                 goto e1;
1411         }
1412
1413         if (pui32DeviceIndex)
1414         {
1415                 *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
1416         }
1417
1418         List_PVRSRV_DEVICE_NODE_Insert(&psPVRSRVData->psDeviceNodeList, psDeviceNode);
1419
1420         return PVRSRV_OK;
1421 e1:
1422         PhysHeapRelease(psDeviceNode->apsPhysHeap[eDevPhysHeap]);
1423 e0:
1424         return eError;
1425 }
1426
1427 IMG_VOID IMG_CALLCONV PVRSRVUnregisterExtDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
1428 {
1429         PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
1430         PVRSRV_DEVICE_PHYS_HEAP eDevPhysHeap;
1431
1432         List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
1433         (IMG_VOID)FreeDeviceID(psPVRSRVData, psDeviceNode->sDevId.ui32DeviceIndex);
1434         for (eDevPhysHeap = 0; eDevPhysHeap < PVRSRV_DEVICE_PHYS_HEAP_LAST; eDevPhysHeap++)
1435         {
1436                 if (psDeviceNode->apsPhysHeap[eDevPhysHeap])
1437                 {
1438                         PhysHeapRelease(psDeviceNode->apsPhysHeap[eDevPhysHeap]);
1439                 }
1440         }
1441 }
1442
1443 static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
1444 {
1445         PVRSRV_ERROR eError;
1446         PVRSRV_DEV_POWER_STATE ePowState;
1447
1448         ePowState = va_arg(va, PVRSRV_DEV_POWER_STATE);
1449
1450         eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
1451                                                                                  ePowState,
1452                                                                                  IMG_TRUE);
1453
1454         if (eError != PVRSRV_OK)
1455         {
1456                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (%s, device index: %d)", 
1457                                                 PVRSRVGetErrorStringKM(eError),
1458                                                 psDeviceNode->sDevId.ui32DeviceIndex));
1459         }
1460
1461         return eError;
1462 }
1463
1464 /*wraps the PVRSRVDevInitCompatCheck call and prints a debugging message if failed*/
1465 static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_Any_va(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
1466 {
1467         PVRSRV_ERROR eError;
1468         IMG_UINT32 *pui32ClientBuildOptions;
1469
1470         pui32ClientBuildOptions = va_arg(va, IMG_UINT32*);
1471
1472         eError = PVRSRVDevInitCompatCheck(psDeviceNode, *pui32ClientBuildOptions);
1473         if (eError != PVRSRV_OK)
1474         {
1475                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
1476         }
1477         return eError;
1478 }
1479
1480
1481 /*!
1482 ******************************************************************************
1483
1484  @Function      PVRSRVFinaliseSystem
1485
1486  @Description
1487
1488  Final part of system initialisation.
1489
1490  @Input    ui32DevIndex : Index to the required device
1491
1492  @Return   PVRSRV_ERROR  :
1493
1494 ******************************************************************************/
1495 PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful, IMG_UINT32 ui32ClientBuildOptions)
1496 {
1497         PVRSRV_DATA                     *psPVRSRVData = PVRSRVGetPVRSRVData();
1498         PVRSRV_ERROR            eError;
1499         IMG_UINT32                      i;
1500
1501         PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
1502
1503         if (bInitSuccessful)
1504         {
1505                 for (i=0;i<psPVRSRVData->ui32RegisteredDevices;i++)
1506                 {
1507                         PVRSRV_DEVICE_NODE *psDeviceNode = psPVRSRVData->apsRegisteredDevNodes[i];
1508
1509                         SyncPrimContextCreate(IMG_NULL,
1510                                                                   psDeviceNode,
1511                                                                   &psDeviceNode->hSyncPrimContext);
1512
1513                         /* Allocate general purpose sync primitive */
1514                         eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext, &psDeviceNode->psSyncPrim, "pvrsrv dev general");
1515                         if (eError != PVRSRV_OK)
1516                         {
1517                                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed to allocate sync primitive with error (%u)", eError));
1518                                 return eError;
1519                         }
1520                         /* Allocate PreKick sync primitive */
1521                         eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext, &psDeviceNode->psSyncPrimPreKick, "pvrsrv pre kick");
1522                         if (eError != PVRSRV_OK)
1523                         {
1524                                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed to allocate PreKick sync primitive with error (%u)", eError));
1525                                 return eError;
1526                         }
1527
1528                 }
1529
1530                 eError = PVRSRVPowerLock();
1531                 if (eError != PVRSRV_OK)
1532                 {
1533                         PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem_SetPowerState_AnyCb: Failed to acquire power lock"));
1534                         return eError;
1535                 }
1536
1537                 /* Always ensure a single power on command appears in the pdump.
1538                  * This should be the only power related call outside of PDUMPPOWCMDSTART/END.
1539                  * Place all devices into ON power state. */
1540                 eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psPVRSRVData->psDeviceNodeList,
1541                                                                                                                 &PVRSRVFinaliseSystem_SetPowerState_AnyCb,
1542                                                                                                                 PVRSRV_DEV_POWER_STATE_ON);
1543                 if (eError != PVRSRV_OK)
1544                 {
1545                         PVRSRVPowerUnlock();
1546                         return eError;
1547                 }
1548
1549                 /* Verify firmware compatibility for devices */
1550                 eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psPVRSRVData->psDeviceNodeList,
1551                                                                                                         &PVRSRVFinaliseSystem_CompatCheck_Any_va,
1552                                                                                                         &ui32ClientBuildOptions);
1553                 if (eError != PVRSRV_OK)
1554                 {
1555                         PVRSRVPowerUnlock();
1556                         PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, IMG_NULL);
1557                         return eError;
1558                 }
1559
1560                 PDUMPPOWCMDSTART();
1561                 /* Place all devices into their default power state. */
1562                 eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psPVRSRVData->psDeviceNodeList,
1563                                                                                                                 &PVRSRVFinaliseSystem_SetPowerState_AnyCb,
1564                                                                                                                 PVRSRV_DEV_POWER_STATE_DEFAULT);
1565                 PDUMPPOWCMDEND();
1566
1567                 if (eError != PVRSRV_OK)
1568                 {
1569                         PVRSRVPowerUnlock();
1570                         return eError;
1571                 }
1572
1573                 PVRSRVPowerUnlock();
1574
1575         }
1576
1577         eError = PDumpStopInitPhaseKM(IMG_SRV_INIT);
1578
1579         if(eError != PVRSRV_OK)
1580         {
1581                 PVR_DPF((PVR_DBG_ERROR, "Failed to stop PDump init phase"));
1582                 return eError;
1583         }
1584
1585         return PVRSRV_OK;
1586 }
1587
1588
1589 PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode,IMG_UINT32 ui32ClientBuildOptions)
1590 {
1591         /* Only check devices which specify a compatibility check callback */
1592         if (psDeviceNode->pfnInitDeviceCompatCheck)
1593                 return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode, ui32ClientBuildOptions);
1594         else
1595                 return PVRSRV_OK;
1596 }
1597
1598 /*!
1599 ******************************************************************************
1600
1601  @Function      PVRSRVAcquireDeviceDataKM
1602
1603  @Description
1604
1605  Matchs a device given a device type and a device index.
1606
1607  @input psDeviceNode :The device node to be matched.
1608
1609  @Input    va : Variable argument list with:
1610                         eDeviceType : Required device type. If type is unknown use ui32DevIndex
1611                                                  to locate device data
1612
1613                         ui32DevIndex : Index to the required device obtained from the
1614                                                 PVRSRVEnumerateDevice function
1615
1616  @Return   PVRSRV_ERROR  :
1617
1618 ******************************************************************************/
1619 static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
1620 {
1621         PVRSRV_DEVICE_TYPE eDeviceType;
1622         IMG_UINT32 ui32DevIndex;
1623
1624         eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE);
1625         ui32DevIndex = va_arg(va, IMG_UINT32);
1626
1627         if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN &&
1628                 psDeviceNode->sDevId.eDeviceType == eDeviceType) ||
1629                 (eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN &&
1630                  psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex))
1631         {
1632                 return psDeviceNode;
1633         }
1634         else
1635         {
1636                 return IMG_NULL;
1637         }
1638 }
1639
1640 /*!
1641 ******************************************************************************
1642
1643  @Function      PVRSRVAcquireDeviceDataKM
1644
1645  @Description
1646
1647  Returns device information
1648
1649  @Input    ui32DevIndex : Index to the required device obtained from the
1650                                                 PVRSRVEnumerateDevice function
1651
1652  @Input    eDeviceType : Required device type. If type is unknown use ui32DevIndex
1653                                                  to locate device data
1654
1655  @Output  *phDevCookie : Dev Cookie
1656
1657
1658  @Return   PVRSRV_ERROR  :
1659
1660 ******************************************************************************/
1661 IMG_EXPORT
1662 PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32                 ui32DevIndex,
1663                                                                                                          PVRSRV_DEVICE_TYPE     eDeviceType,
1664                                                                                                          IMG_HANDLE                     *phDevCookie)
1665 {
1666         PVRSRV_DATA                     *psPVRSRVData = PVRSRVGetPVRSRVData();
1667         PVRSRV_DEVICE_NODE      *psDeviceNode;
1668
1669         PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
1670
1671         /* Find device in the list */
1672         psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
1673                                                                                                 &PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
1674                                                                                                 eDeviceType,
1675                                                                                                 ui32DevIndex);
1676
1677
1678         if (!psDeviceNode)
1679         {
1680                 /* device can't be found in the list so it isn't in the system */
1681                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
1682                 return PVRSRV_ERROR_INIT_FAILURE;
1683         }
1684
1685 /*FoundDevice:*/
1686
1687         PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
1688
1689         /* return the dev cookie? */
1690         if (phDevCookie)
1691         {
1692                 *phDevCookie = (IMG_HANDLE)psDeviceNode;
1693         }
1694
1695         return PVRSRV_OK;
1696 }
1697
1698 IMG_EXPORT
1699 PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseDeviceDataKM (IMG_HANDLE hDevCookie)
1700 {
1701         PVR_UNREFERENCED_PARAMETER(hDevCookie);
1702
1703         /* 
1704           Empty release body as the lifetime of this resource accessed by 
1705           PVRSRVAcquireDeviceDataKM is linked to driver lifetime, not API allocation.
1706           This is one reason why this type crosses the bridge with a shared handle.
1707           Thus no server release action is required, just bridge action to ensure
1708           associated handle is freed.
1709     */ 
1710         return PVRSRV_OK;
1711 }
1712
1713 /*!
1714 ******************************************************************************
1715
1716  @Function      PVRSRVUnregisterDevice
1717
1718  @Description
1719
1720  This De-inits device
1721
1722  @Input    ui32DevIndex : Index to the required device
1723
1724  @Return   PVRSRV_ERROR  :
1725
1726 ******************************************************************************/
1727 static PVRSRV_ERROR IMG_CALLCONV PVRSRVUnregisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
1728 {
1729         PVRSRV_DATA                             *psPVRSRVData = PVRSRVGetPVRSRVData();
1730         PVRSRV_DEVICE_PHYS_HEAP ePhysHeapIdx;
1731         PVRSRV_ERROR                    eError;
1732
1733         eError = PVRSRVPowerLock();
1734         if (eError != PVRSRV_OK)
1735         {
1736                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVUnregisterDevice: Failed to acquire power lock"));
1737                 return eError;
1738         }
1739
1740         /*
1741                 Power down the device if necessary.
1742          */
1743         eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
1744                                                                                  PVRSRV_DEV_POWER_STATE_OFF,
1745                                                                                  IMG_TRUE);
1746
1747         PVRSRVPowerUnlock();
1748
1749         if (eError != PVRSRV_OK)
1750         {
1751                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVUnregisterDevice: Failed PVRSRVSetDevicePowerStateKM call (%s). Dump debug.", PVRSRVGetErrorStringKM(eError)));
1752
1753                 PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, IMG_NULL);
1754
1755                 /* If the driver is okay then return the error, otherwise we can ignore this error. */
1756                 if (PVRSRVGetPVRSRVData()->eServicesState == PVRSRV_SERVICES_STATE_OK)
1757                 {
1758                         return eError;
1759                 }
1760                 else
1761                 {
1762                         PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVUnregisterDevice: Will continue to unregister as driver status is not OK"));
1763                 }
1764         }
1765
1766         /*
1767                 De-init the device.
1768         */
1769         sUnregisterDevice[psDeviceNode->sDevId.eDeviceType](psDeviceNode);
1770
1771         /* Remove RA for local card memory */
1772         if (psDeviceNode->psLocalDevMemArena)
1773         {
1774                 RA_Delete(psDeviceNode->psLocalDevMemArena);
1775         }
1776
1777         /* remove node from list */
1778         List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
1779
1780         /* deallocate id and memory */
1781         (IMG_VOID)FreeDeviceID(psPVRSRVData, psDeviceNode->sDevId.ui32DeviceIndex);
1782
1783         for (ePhysHeapIdx = 0; ePhysHeapIdx < PVRSRV_DEVICE_PHYS_HEAP_LAST; ePhysHeapIdx++)
1784         {
1785                 if (psDeviceNode->apsPhysHeap[ePhysHeapIdx])
1786                 {
1787                         PhysHeapRelease(psDeviceNode->apsPhysHeap[ePhysHeapIdx]);
1788                 }
1789         }
1790
1791         OSFreeMem(psDeviceNode);
1792         /*not nulling pointer, out of scope*/
1793
1794         return (PVRSRV_OK);
1795 }
1796
1797
1798 /*
1799         PollForValueKM
1800 */
1801 static
1802 PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32*  pui32LinMemAddr,
1803                                                                                   IMG_UINT32                    ui32Value,
1804                                                                                   IMG_UINT32                    ui32Mask,
1805                                                                                   IMG_UINT32                    ui32Timeoutus,
1806                                                                                   IMG_UINT32                    ui32PollPeriodus,
1807                                                                                   IMG_BOOL                              bAllowPreemption)
1808 {
1809 #if defined(NO_HARDWARE)
1810         PVR_UNREFERENCED_PARAMETER(pui32LinMemAddr);
1811         PVR_UNREFERENCED_PARAMETER(ui32Value);
1812         PVR_UNREFERENCED_PARAMETER(ui32Mask);
1813         PVR_UNREFERENCED_PARAMETER(ui32Timeoutus);
1814         PVR_UNREFERENCED_PARAMETER(ui32PollPeriodus);
1815         PVR_UNREFERENCED_PARAMETER(bAllowPreemption);
1816         return PVRSRV_OK;
1817 #else
1818         IMG_UINT32      ui32ActualValue = 0xFFFFFFFFU; /* Initialiser only required to prevent incorrect warning */
1819
1820         if (bAllowPreemption)
1821         {
1822                 PVR_ASSERT(ui32PollPeriodus >= 1000);
1823         }
1824
1825         LOOP_UNTIL_TIMEOUT(ui32Timeoutus)
1826         {
1827                 ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
1828                 if(ui32ActualValue == ui32Value)
1829                 {
1830                         return PVRSRV_OK;
1831                 }
1832
1833                 if (gpsPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
1834                 {
1835                         return PVRSRV_ERROR_TIMEOUT;
1836                 }
1837
1838                 if (bAllowPreemption)
1839                 {
1840                         OSSleepms(ui32PollPeriodus / 1000);
1841                 }
1842                 else
1843                 {
1844                         OSWaitus(ui32PollPeriodus);
1845                 }
1846         } END_LOOP_UNTIL_TIMEOUT();
1847
1848         PVR_DPF((PVR_DBG_ERROR,"PollForValueKM: Timeout. Expected 0x%x but found 0x%x (mask 0x%x).",
1849                         ui32Value, ui32ActualValue, ui32Mask));
1850         
1851         return PVRSRV_ERROR_TIMEOUT;
1852 #endif /* NO_HARDWARE */
1853 }
1854
1855
1856 /*
1857         PVRSRVPollForValueKM
1858 */
1859 IMG_EXPORT
1860 PVRSRV_ERROR IMG_CALLCONV PVRSRVPollForValueKM (volatile IMG_UINT32     *pui32LinMemAddr,
1861                                                                                                 IMG_UINT32                      ui32Value,
1862                                                                                                 IMG_UINT32                      ui32Mask)
1863 {
1864         return PollForValueKM(pui32LinMemAddr, ui32Value, ui32Mask,
1865                                                   MAX_HW_TIME_US,
1866                                                   MAX_HW_TIME_US/WAIT_TRY_COUNT,
1867                                                   IMG_FALSE);
1868 }
1869
1870 /*
1871         PVRSRVWaitForValueKM
1872 */
1873 IMG_EXPORT
1874 PVRSRV_ERROR IMG_CALLCONV PVRSRVWaitForValueKM (volatile IMG_UINT32     *pui32LinMemAddr,
1875                                                                                                 IMG_UINT32                      ui32Value,
1876                                                                                                 IMG_UINT32                      ui32Mask)
1877 {
1878 #if defined(NO_HARDWARE)
1879         PVR_UNREFERENCED_PARAMETER(pui32LinMemAddr);
1880         PVR_UNREFERENCED_PARAMETER(ui32Value);
1881         PVR_UNREFERENCED_PARAMETER(ui32Mask);
1882         return PVRSRV_OK;
1883 #else
1884
1885         PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
1886         IMG_HANDLE hOSEvent;
1887         PVRSRV_ERROR eError;
1888         PVRSRV_ERROR eErrorWait;
1889         IMG_UINT32 ui32ActualValue;
1890
1891         eError = OSEventObjectOpen(psPVRSRVData->hGlobalEventObject, &hOSEvent);
1892         if (eError != PVRSRV_OK)
1893         {
1894                 PVR_DPF((PVR_DBG_ERROR,"PVRSRVWaitForValueKM: Failed to setup EventObject with error (%d)", eError));
1895                 goto EventObjectOpenError;
1896         }
1897
1898         eError = PVRSRV_ERROR_TIMEOUT;
1899         
1900         LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
1901         {
1902                 ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
1903
1904                 if (ui32ActualValue == ui32Value)
1905                 {
1906                         /* Expected value has been found */
1907                         eError = PVRSRV_OK;
1908                         break;
1909                 }
1910                 else if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
1911                 {
1912                         /* Services in bad state, don't wait any more */
1913                         eError = PVRSRV_ERROR_NOT_READY;
1914                         break;
1915                 }
1916                 else
1917                 {
1918                         /* wait for event and retry */
1919                         eErrorWait = OSEventObjectWait(hOSEvent);
1920                         if (eErrorWait != PVRSRV_OK  &&  eErrorWait != PVRSRV_ERROR_TIMEOUT)
1921                         {
1922                                 PVR_DPF((PVR_DBG_WARNING,"PVRSRVWaitForValueKM: Waiting for value failed with error %d. Expected 0x%x but found 0x%x (Mask 0x%08x). Retrying",
1923                                                         eErrorWait,
1924                                                         ui32Value,
1925                                                         ui32ActualValue,
1926                                                         ui32Mask));
1927                         }
1928                 }
1929         } END_LOOP_UNTIL_TIMEOUT();
1930
1931         OSEventObjectClose(hOSEvent);
1932
1933         /* One last check incase the object wait ended after the loop timeout... */
1934         if (eError != PVRSRV_OK  &&  (*pui32LinMemAddr & ui32Mask) == ui32Value)
1935         {
1936                 eError = PVRSRV_OK;
1937         }
1938
1939         /* Provide event timeout information to aid the Device Watchdog Thread... */
1940         if (eError == PVRSRV_OK)
1941         {
1942                 psPVRSRVData->ui32GEOConsecutiveTimeouts = 0;
1943         }
1944         else if (eError == PVRSRV_ERROR_TIMEOUT)
1945         {
1946                 psPVRSRVData->ui32GEOConsecutiveTimeouts++;
1947         }
1948
1949 EventObjectOpenError:
1950
1951         return eError;
1952
1953 #endif /* NO_HARDWARE */
1954 }
1955
1956 #if !defined(NO_HARDWARE)
1957 static IMG_BOOL _CheckStatus(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
1958 {
1959         PVRSRV_CMDCOMP_HANDLE   hCmdCompCallerHandle = (PVRSRV_CMDCOMP_HANDLE) pvCallbackData;
1960         PVRSRV_CMDCOMP_NOTIFY   *psNotify;
1961
1962         psNotify = IMG_CONTAINER_OF(psNode, PVRSRV_CMDCOMP_NOTIFY, sListNode);
1963
1964         /* A device has finished some processing, check if that unblocks other devices */
1965         if (hCmdCompCallerHandle != psNotify->hCmdCompHandle)
1966         {
1967                 psNotify->pfnCmdCompleteNotify(psNotify->hCmdCompHandle);
1968         }
1969
1970         /* keep processing until the end of the list */
1971         return IMG_TRUE;
1972 }
1973 #endif
1974
1975 IMG_VOID IMG_CALLCONV PVRSRVCheckStatus(PVRSRV_CMDCOMP_HANDLE hCmdCompCallerHandle)
1976 {
1977         PVRSRV_DATA                     *psPVRSRVData = PVRSRVGetPVRSRVData();
1978
1979         /* notify any registered device to check if block work items can now proceed */
1980 #if !defined(NO_HARDWARE)
1981         OSWRLockAcquireRead(hNotifyLock, GLOBAL_NOTIFY);
1982         dllist_foreach_node(&sCmdCompNotifyHead, _CheckStatus, hCmdCompCallerHandle);
1983         OSWRLockReleaseRead(hNotifyLock);
1984 #endif
1985
1986         /* signal global event object */
1987         if (psPVRSRVData->hGlobalEventObject)
1988         {
1989                 IMG_HANDLE hOSEventKM = psPVRSRVData->hGlobalEventObject;
1990                 if(hOSEventKM)
1991                 {
1992                         OSEventObjectSignal(hOSEventKM);
1993                 }
1994         }
1995 }
1996
1997 PVRSRV_ERROR IMG_CALLCONV PVRSRVKickDevicesKM(IMG_VOID)
1998 {
1999         PVR_DPF((PVR_DBG_ERROR, "PVRSRVKickDevicesKM"));
2000         PVRSRVCheckStatus(IMG_NULL);
2001         return PVRSRV_OK;
2002 }
2003
2004 /*!
2005  ******************************************************************************
2006
2007  @Function              PVRSRVGetErrorStringKM
2008
2009  @Description   Returns a text string relating to the PVRSRV_ERROR enum.
2010
2011  @Note          case statement used rather than an indexed arrary to ensure text is
2012                         synchronised with the correct enum
2013
2014  @Input         eError : PVRSRV_ERROR enum
2015
2016  @Return        const IMG_CHAR * : Text string
2017
2018  @Note          Must be kept in sync with servicesext.h
2019
2020 ******************************************************************************/
2021
2022 IMG_EXPORT
2023 const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError)
2024 {
2025         switch(eError)
2026         {
2027                 case PVRSRV_OK:
2028                         return "PVRSRV_OK";
2029 #define PVRE(x) \
2030                 case x: \
2031                         return #x;
2032 #include "pvrsrv_errors.h"
2033 #undef PVRE
2034                 default:
2035                         return "Unknown PVRSRV error number";
2036         }
2037 }
2038
2039 /*
2040         PVRSRVSystemDebugInfo
2041  */
2042 PVRSRV_ERROR PVRSRVSystemDebugInfo( DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
2043 {
2044         return SysDebugInfo(gpsSysConfig, pfnDumpDebugPrintf);
2045 }
2046
2047 /*
2048         PVRSRVGetSystemName
2049 */
2050 const IMG_CHAR *PVRSRVGetSystemName(IMG_VOID)
2051 {
2052         return gpsSysConfig->pszSystemName;
2053 }
2054
2055 /*
2056         PVRSRVSystemHasCacheSnooping
2057 */
2058 IMG_BOOL PVRSRVSystemHasCacheSnooping(IMG_VOID)
2059 {
2060         if (gpsSysConfig->eCacheSnoopingMode != PVRSRV_SYSTEM_SNOOP_NONE)
2061         {
2062                 return IMG_TRUE;
2063         }
2064         return IMG_FALSE;
2065 }
2066
2067 IMG_BOOL PVRSRVSystemSnoopingOfCPUCache(IMG_VOID)
2068 {
2069         if ((gpsSysConfig->eCacheSnoopingMode == PVRSRV_SYSTEM_SNOOP_CPU_ONLY) ||
2070                 (gpsSysConfig->eCacheSnoopingMode == PVRSRV_SYSTEM_SNOOP_CROSS))
2071         {
2072                 return IMG_TRUE;
2073         }
2074         return IMG_FALSE;       
2075 }
2076
2077 IMG_BOOL PVRSRVSystemSnoopingOfDeviceCache(IMG_VOID)
2078 {
2079         if ((gpsSysConfig->eCacheSnoopingMode == PVRSRV_SYSTEM_SNOOP_DEVICE_ONLY) ||
2080                 (gpsSysConfig->eCacheSnoopingMode == PVRSRV_SYSTEM_SNOOP_CROSS))
2081         {
2082                 return IMG_TRUE;
2083         }
2084         return IMG_FALSE;
2085 }
2086
2087 /*
2088         PVRSRVSystemWaitCycles
2089 */
2090 IMG_VOID PVRSRVSystemWaitCycles(PVRSRV_DEVICE_CONFIG *psDevConfig, IMG_UINT32 ui32Cycles)
2091 {
2092         /* Delay in us */
2093         IMG_UINT32 ui32Delayus = 1;
2094
2095         /* obtain the device freq */
2096         if (psDevConfig->pfnClockFreqGet != IMG_NULL)
2097         {
2098                 IMG_UINT32 ui32DeviceFreq;
2099
2100                 ui32DeviceFreq = psDevConfig->pfnClockFreqGet(psDevConfig->hSysData);
2101
2102                 ui32Delayus = (ui32Cycles*1000000)/ui32DeviceFreq;
2103
2104                 if (ui32Delayus == 0)
2105                 {
2106                         ui32Delayus = 1;
2107                 }
2108         }
2109
2110         OSWaitus(ui32Delayus);
2111 }
2112
2113 /*
2114         PVRSRVRegisterCmdCompleteNotify
2115 */
2116 PVRSRV_ERROR PVRSRVRegisterCmdCompleteNotify(IMG_HANDLE *phNotify, PFN_CMDCOMP_NOTIFY pfnCmdCompleteNotify, PVRSRV_CMDCOMP_HANDLE hCmdCompHandle)
2117 {
2118         PVRSRV_CMDCOMP_NOTIFY *psNotify;
2119
2120         if ((phNotify == IMG_NULL) || (pfnCmdCompleteNotify == IMG_NULL) || (hCmdCompHandle == IMG_NULL))
2121         {
2122                 PVR_DPF((PVR_DBG_ERROR,"%s: Bad arguments (%p, %p, %p)", __FUNCTION__, phNotify, pfnCmdCompleteNotify, hCmdCompHandle));
2123                 return PVRSRV_ERROR_INVALID_PARAMS;
2124         }
2125
2126         psNotify = OSAllocMem(sizeof(*psNotify));
2127         if (psNotify == IMG_NULL)
2128         {
2129                 PVR_DPF((PVR_DBG_ERROR,"%s: Not enough memory to allocate CmdCompleteNotify function", __FUNCTION__));
2130                 return PVRSRV_ERROR_OUT_OF_MEMORY;              
2131         }
2132
2133         /* Set-up the notify data */
2134         psNotify->hCmdCompHandle = hCmdCompHandle;
2135         psNotify->pfnCmdCompleteNotify = pfnCmdCompleteNotify;
2136
2137         /* Add it to the list of Notify functions */
2138         OSWRLockAcquireWrite(hNotifyLock, GLOBAL_NOTIFY);
2139         dllist_add_to_tail(&sCmdCompNotifyHead, &psNotify->sListNode);
2140         OSWRLockReleaseWrite(hNotifyLock);
2141
2142         *phNotify = psNotify;
2143
2144         return PVRSRV_OK;
2145 }
2146
2147 /*
2148         PVRSRVUnregisterCmdCompleteNotify
2149 */
2150 PVRSRV_ERROR PVRSRVUnregisterCmdCompleteNotify(IMG_HANDLE hNotify)
2151 {
2152         PVRSRV_CMDCOMP_NOTIFY *psNotify = (PVRSRV_CMDCOMP_NOTIFY*) hNotify;
2153
2154         if (psNotify == IMG_NULL)
2155         {
2156                 PVR_DPF((PVR_DBG_ERROR,"%s: Bad arguments (%p)", __FUNCTION__, hNotify));
2157                 return PVRSRV_ERROR_INVALID_PARAMS;
2158         }
2159
2160         /* remove the node from the list */
2161         OSWRLockAcquireWrite(hNotifyLock, GLOBAL_NOTIFY);
2162         dllist_remove_node(&psNotify->sListNode);
2163         OSWRLockReleaseWrite(hNotifyLock);
2164
2165         /* free the notify structure that holds the node */
2166         OSFreeMem(psNotify);
2167
2168         return PVRSRV_OK;
2169
2170 }
2171
2172 static IMG_VOID _SysDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle, IMG_UINT32 ui32VerbLevel)
2173 {
2174         PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA*) hDebugRequestHandle;
2175         DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf = IMG_NULL;
2176
2177         pfnDumpDebugPrintf = g_pfnDumpDebugPrintf;      
2178         /* only dump info on the lowest verbosity level */
2179         if (ui32VerbLevel != DEBUG_REQUEST_VERBOSITY_LOW)
2180         {
2181                 return;
2182         }
2183
2184         PVR_DUMPDEBUG_LOG(("DDK info: %s (%s) %s", PVRVERSION_STRING, PVR_BUILD_TYPE, PVR_BUILD_DIR));
2185
2186         /* Services state */
2187         switch (psPVRSRVData->eServicesState)
2188         {
2189                 case PVRSRV_SERVICES_STATE_OK:
2190                 {
2191                         PVR_DUMPDEBUG_LOG(("Services State: OK"));
2192                         break;
2193                 }
2194                 
2195                 case PVRSRV_SERVICES_STATE_BAD:
2196                 {
2197                         PVR_DUMPDEBUG_LOG(("Services State: BAD"));
2198                         break;
2199                 }
2200                 
2201                 default:
2202                 {
2203                         PVR_DUMPDEBUG_LOG(("Services State: UNKNOWN (%d)", psPVRSRVData->eServicesState));
2204                         break;
2205                 }
2206         }
2207
2208         /* Power state */
2209         switch (psPVRSRVData->eCurrentPowerState)
2210         {
2211                 case PVRSRV_SYS_POWER_STATE_OFF:
2212                 {
2213                         PVR_DUMPDEBUG_LOG(("System Power State: OFF"));
2214                         break;
2215                 }
2216                 case PVRSRV_SYS_POWER_STATE_ON:
2217                 {
2218                         PVR_DUMPDEBUG_LOG(("System Power State: ON"));
2219                         break;
2220                 }
2221                 default:
2222                 {
2223                         PVR_DUMPDEBUG_LOG(("System Power State: UNKNOWN (%d)", psPVRSRVData->eCurrentPowerState));
2224                         break;
2225                 }
2226         }
2227
2228         /* Dump system specific debug info */
2229         PVRSRVSystemDebugInfo(pfnDumpDebugPrintf);
2230
2231 }
2232
2233 static IMG_BOOL _DebugRequest(PDLLIST_NODE psNode, IMG_PVOID hVerbLevel)
2234 {
2235         IMG_UINT32 *pui32VerbLevel = (IMG_UINT32 *) hVerbLevel;
2236         PVRSRV_DBGREQ_NOTIFY *psNotify;
2237
2238         psNotify = IMG_CONTAINER_OF(psNode, PVRSRV_DBGREQ_NOTIFY, sListNode);
2239
2240         psNotify->pfnDbgRequestNotify(psNotify->hDbgRequestHandle, *pui32VerbLevel);
2241
2242         /* keep processing until the end of the list */
2243         return IMG_TRUE;
2244 }
2245
2246 /*
2247         PVRSRVDebugRequest
2248 */
2249 IMG_VOID IMG_CALLCONV PVRSRVDebugRequest(IMG_UINT32 ui32VerbLevel, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
2250 {
2251         IMG_UINT32 i,j;
2252
2253         g_pfnDumpDebugPrintf = pfnDumpDebugPrintf;
2254         OSDumpStack();
2255
2256         /* notify any registered device to check if block work items can now proceed */
2257         /* Lock the lists */
2258         OSWRLockAcquireRead(g_hDbgNotifyLock, GLOBAL_DBGNOTIFY);
2259
2260         PVR_DUMPDEBUG_LOG(("------------[ PVR DBG: START ]------------"));
2261
2262         /* For each verbosity level */
2263         for (j=0;j<(ui32VerbLevel+1);j++)
2264         {
2265                 /* For each requester */
2266                 for (i=0;i<g_psDebugTable->ui32RequestCount;i++)
2267                 {
2268                         dllist_foreach_node(&g_psDebugTable->asEntry[i].sListHead, _DebugRequest, &j);
2269                 }
2270         }
2271         PVR_DUMPDEBUG_LOG(("------------[ PVR DBG: END ]------------"));
2272
2273         /* Unlock the lists */
2274         OSWRLockReleaseRead(g_hDbgNotifyLock);
2275 }
2276
2277 /*
2278         PVRSRVRegisterDebugRequestNotify
2279 */
2280 PVRSRV_ERROR PVRSRVRegisterDbgRequestNotify(IMG_HANDLE *phNotify, PFN_DBGREQ_NOTIFY pfnDbgRequestNotify, IMG_UINT32 ui32RequesterID, PVRSRV_DBGREQ_HANDLE hDbgRequestHandle)
2281 {
2282         PVRSRV_DBGREQ_NOTIFY *psNotify;
2283         PDLLIST_NODE psHead = IMG_NULL;
2284         IMG_UINT32 i;
2285         PVRSRV_ERROR eError;
2286
2287         if ((phNotify == IMG_NULL) || (pfnDbgRequestNotify == IMG_NULL))
2288         {
2289                 PVR_DPF((PVR_DBG_ERROR,"%s: Bad arguments (%p, %p,)", __FUNCTION__, phNotify, pfnDbgRequestNotify));
2290                 eError = PVRSRV_ERROR_INVALID_PARAMS;
2291                 goto fail_params;
2292         }
2293
2294         psNotify = OSAllocMem(sizeof(*psNotify));
2295         if (psNotify == IMG_NULL)
2296         {
2297                 PVR_DPF((PVR_DBG_ERROR,"%s: Not enough memory to allocate DbgRequestNotify structure", __FUNCTION__));
2298                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
2299                 goto fail_alloc;
2300         }
2301
2302         /* Set-up the notify data */
2303         psNotify->hDbgRequestHandle = hDbgRequestHandle;
2304         psNotify->pfnDbgRequestNotify = pfnDbgRequestNotify;
2305         psNotify->ui32RequesterID = ui32RequesterID;
2306
2307         /* Lock down all the lists */
2308         OSWRLockAcquireWrite(g_hDbgNotifyLock, GLOBAL_DBGNOTIFY);
2309
2310         /* Find which list to add it to */
2311         for (i=0;i<g_psDebugTable->ui32RequestCount;i++)
2312         {
2313                 if (g_psDebugTable->asEntry[i].ui32RequesterID == ui32RequesterID)
2314                 {
2315                         psHead = &g_psDebugTable->asEntry[i].sListHead;
2316                 }
2317         }
2318
2319         if (psHead == IMG_NULL)
2320         {
2321                 PVR_DPF((PVR_DBG_ERROR,"%s: Failed to find debug requester", __FUNCTION__));
2322                 eError = PVRSRV_ERROR_INVALID_PARAMS;
2323                 goto fail_add;
2324         }
2325
2326         /* Add it to the list of Notify functions */
2327         dllist_add_to_tail(psHead, &psNotify->sListNode);
2328
2329         /* Unlock the lists */
2330         OSWRLockReleaseWrite(g_hDbgNotifyLock);
2331
2332         *phNotify = psNotify;
2333
2334         return PVRSRV_OK;
2335
2336 fail_add:
2337         OSWRLockReleaseWrite(g_hDbgNotifyLock);
2338         OSFreeMem(psNotify);
2339 fail_alloc:
2340 fail_params:
2341         return eError;
2342 }
2343
2344 /*
2345         PVRSRVUnregisterCmdCompleteNotify
2346 */
2347 PVRSRV_ERROR PVRSRVUnregisterDbgRequestNotify(IMG_HANDLE hNotify)
2348 {
2349         PVRSRV_DBGREQ_NOTIFY *psNotify = (PVRSRV_DBGREQ_NOTIFY*) hNotify;
2350
2351         if (psNotify == IMG_NULL)
2352         {
2353                 PVR_DPF((PVR_DBG_ERROR,"%s: Bad arguments (%p)", __FUNCTION__, hNotify));
2354                 return PVRSRV_ERROR_INVALID_PARAMS;
2355         }
2356
2357         /* remove the node from the list */
2358         OSWRLockAcquireWrite(g_hDbgNotifyLock, GLOBAL_DBGNOTIFY);
2359         dllist_remove_node(&psNotify->sListNode);
2360         OSWRLockReleaseWrite(g_hDbgNotifyLock);
2361
2362         /* free the notify structure that holds the node */
2363         OSFreeMem(psNotify);
2364
2365         return PVRSRV_OK;
2366 }
2367
2368
2369 static PVRSRV_ERROR PVRSRVRegisterDbgTable(IMG_UINT32 *paui32Table, IMG_UINT32 ui32Length, IMG_PVOID *phTable)
2370 {
2371         IMG_UINT32 i;
2372         if (g_psDebugTable != IMG_NULL)
2373         {
2374                 return PVRSRV_ERROR_DBGTABLE_ALREADY_REGISTERED;
2375         }
2376
2377         g_psDebugTable = OSAllocMem(sizeof(DEBUG_REQUEST_TABLE) + (sizeof(DEBUG_REQUEST_ENTRY) * (ui32Length-1)));
2378         if (!g_psDebugTable)
2379         {
2380                 return PVRSRV_ERROR_OUT_OF_MEMORY;
2381         }
2382
2383         g_psDebugTable->ui32RequestCount = ui32Length;
2384
2385         /* Init the list heads */
2386         for (i=0;i<ui32Length;i++)
2387         {
2388                 g_psDebugTable->asEntry[i].ui32RequesterID = paui32Table[i];
2389                 dllist_init(&g_psDebugTable->asEntry[i].sListHead);
2390         }
2391
2392         *phTable = g_psDebugTable;
2393         return PVRSRV_OK;
2394 }
2395
2396 static IMG_VOID PVRSRVUnregisterDbgTable(IMG_PVOID hTable)
2397 {
2398         IMG_UINT32 i;
2399
2400         PVR_ASSERT(hTable == g_psDebugTable);
2401
2402         for (i=0;i<g_psDebugTable->ui32RequestCount;i++)
2403         {
2404                 if (!dllist_is_empty(&g_psDebugTable->asEntry[i].sListHead))
2405                 {
2406                         PVR_DPF((PVR_DBG_ERROR, "PVRSRVUnregisterDbgTable: Found registered callback(s) on %d", i));
2407                 }
2408         }
2409         OSFREEMEM(g_psDebugTable);
2410         g_psDebugTable = IMG_NULL;
2411 }
2412
2413 PVRSRV_ERROR AcquireGlobalEventObjectServer(IMG_HANDLE *phGlobalEventObject)
2414 {
2415         PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
2416
2417         *phGlobalEventObject = psPVRSRVData->hGlobalEventObject;
2418
2419         return PVRSRV_OK;
2420 }
2421
2422 PVRSRV_ERROR ReleaseGlobalEventObjectServer(IMG_HANDLE hGlobalEventObject)
2423 {
2424         PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
2425
2426         PVR_ASSERT(psPVRSRVData->hGlobalEventObject == hGlobalEventObject);
2427
2428         return PVRSRV_OK;
2429 }
2430
2431 PVRSRV_ERROR GetBIFTilingHeapXStride(IMG_UINT32 uiHeapNum, IMG_UINT32 *puiXStride)
2432 {
2433         IMG_UINT32 uiMaxHeaps;
2434
2435         PVR_ASSERT(puiXStride != IMG_NULL);
2436
2437         GetNumBifTilingHeapConfigs(&uiMaxHeaps);
2438
2439         if(uiHeapNum < 1 || uiHeapNum > uiMaxHeaps) {
2440                 return PVRSRV_ERROR_INVALID_PARAMS;
2441         }
2442
2443         *puiXStride = gpsSysConfig->pui32BIFTilingHeapConfigs[uiHeapNum - 1];
2444
2445         return PVRSRV_OK;
2446 }
2447
2448 PVRSRV_ERROR GetNumBifTilingHeapConfigs(IMG_UINT32 *puiNumHeaps)
2449 {
2450         *puiNumHeaps = gpsSysConfig->ui32BIFTilingHeapCount;
2451         return PVRSRV_OK;
2452 }
2453
2454 /*
2455         PVRSRVResetHWRLogsKM
2456 */
2457 PVRSRV_ERROR PVRSRVResetHWRLogsKM(PVRSRV_DEVICE_NODE *psDeviceNode)
2458 {
2459         PVR_LOG(("User requested HWR logs reset"));
2460
2461         if(psDeviceNode && psDeviceNode->pfnResetHWRLogs)
2462         {
2463                 return psDeviceNode->pfnResetHWRLogs(psDeviceNode);
2464         }
2465
2466         return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
2467 }
2468
2469 /*****************************************************************************
2470  End of file (pvrsrv.c)
2471 *****************************************************************************/