gpu: pvr: move debugfs infrastructure to its own files
[sgx.git] / pvr / pvrsrv.c
1 /**********************************************************************
2  *
3  * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful but, except
10  * as otherwise stated in writing, without any warranty; without even the
11  * implied warranty of merchantability or fitness for a particular purpose.
12  * See the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * The full GNU General Public License is included in this distribution in
19  * the file called "COPYING".
20  *
21  * Contact Information:
22  * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23  * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
24  *
25  ******************************************************************************/
26
27 #include <linux/io.h>
28
29 #include "services_headers.h"
30 #include "buffer_manager.h"
31 #include "pvr_bridge_km.h"
32 #include "handle.h"
33 #include "perproc.h"
34 #include "pdump_km.h"
35 #include "ra.h"
36 #include "pvr_events.h"
37
38 #include "pvrversion.h"
39
40 #define HASH_TAB_INIT_SIZE      32
41 enum PVRSRV_ERROR AllocateDeviceID(struct SYS_DATA *psSysData, u32 *pui32DevID)
42 {
43         struct SYS_DEVICE_ID *psDeviceWalker;
44         struct SYS_DEVICE_ID *psDeviceEnd;
45
46         psDeviceWalker = &psSysData->sDeviceID[0];
47         psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
48
49         while (psDeviceWalker < psDeviceEnd) {
50                 if (!psDeviceWalker->bInUse) {
51                         psDeviceWalker->bInUse = IMG_TRUE;
52                         *pui32DevID = psDeviceWalker->uiID;
53                         return PVRSRV_OK;
54                 }
55                 psDeviceWalker++;
56         }
57
58         PVR_DPF(PVR_DBG_ERROR,
59                  "AllocateDeviceID: No free and valid device IDs available!");
60
61         PVR_ASSERT(psDeviceWalker < psDeviceEnd);
62
63         return PVRSRV_ERROR_GENERIC;
64 }
65
66 enum PVRSRV_ERROR FreeDeviceID(struct SYS_DATA *psSysData, u32 ui32DevID)
67 {
68         struct SYS_DEVICE_ID *psDeviceWalker;
69         struct SYS_DEVICE_ID *psDeviceEnd;
70
71         psDeviceWalker = &psSysData->sDeviceID[0];
72         psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
73
74         while (psDeviceWalker < psDeviceEnd) {
75                 if ((psDeviceWalker->uiID == ui32DevID) &&
76                     (psDeviceWalker->bInUse)) {
77                         psDeviceWalker->bInUse = IMG_FALSE;
78                         return PVRSRV_OK;
79                 }
80                 psDeviceWalker++;
81         }
82
83         PVR_DPF(PVR_DBG_ERROR,
84                  "FreeDeviceID: no matching dev ID that is in use!");
85
86         PVR_ASSERT(psDeviceWalker < psDeviceEnd);
87
88         return PVRSRV_ERROR_GENERIC;
89 }
90
91 enum PVRSRV_ERROR PVRSRVEnumerateDevicesKM(u32 *pui32NumDevices,
92                                struct PVRSRV_DEVICE_IDENTIFIER *psDevIdList)
93 {
94         enum PVRSRV_ERROR eError;
95         struct SYS_DATA *psSysData;
96         struct PVRSRV_DEVICE_NODE *psDeviceNode;
97         u32 i;
98
99         if (!pui32NumDevices || !psDevIdList) {
100                 PVR_DPF(PVR_DBG_ERROR,
101                          "PVRSRVEnumerateDevicesKM: Invalid params");
102                 return PVRSRV_ERROR_INVALID_PARAMS;
103         }
104
105         eError = SysAcquireData(&psSysData);
106         if (eError != PVRSRV_OK) {
107                 PVR_DPF(PVR_DBG_ERROR,
108                          "PVRSRVEnumerateDevicesKM: Failed to get SysData");
109                 return eError;
110         }
111
112         for (i = 0; i < PVRSRV_MAX_DEVICES; i++)
113                 psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
114
115         *pui32NumDevices = 0;
116
117         psDeviceNode = psSysData->psDeviceNodeList;
118         for (i = 0; psDeviceNode != NULL; i++) {
119                 if (psDeviceNode->sDevId.eDeviceType !=
120                     PVRSRV_DEVICE_TYPE_EXT) {
121                         *psDevIdList++ = psDeviceNode->sDevId;
122                         (*pui32NumDevices)++;
123                 }
124                 psDeviceNode = psDeviceNode->psNext;
125         }
126
127         return PVRSRV_OK;
128 }
129
130 enum PVRSRV_ERROR PVRSRVInit(struct SYS_DATA *psSysData)
131 {
132         enum PVRSRV_ERROR eError;
133
134         eError = ResManInit();
135         if (eError != PVRSRV_OK)
136                 goto Error;
137
138         eError = PVRSRVPerProcessDataInit();
139         if (eError != PVRSRV_OK)
140                 goto Error;
141
142         eError = PVRSRVHandleInit();
143         if (eError != PVRSRV_OK)
144                 goto Error;
145
146         psSysData->eCurrentPowerState = PVRSRV_POWER_STATE_D0;
147         psSysData->eFailedPowerState = PVRSRV_POWER_Unspecified;
148
149 #if defined(PDUMP)
150         psSysData->bPowerUpPDumped = IMG_FALSE;
151 #endif
152
153         if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
154                        sizeof(struct PVRSRV_EVENTOBJECT),
155                        (void **) &psSysData->psGlobalEventObject,
156                        NULL) != PVRSRV_OK)
157
158                 goto Error;
159
160         if (OSEventObjectCreate("PVRSRV_GLOBAL_EVENTOBJECT",
161                                 psSysData->psGlobalEventObject) != PVRSRV_OK)
162                 goto Error;
163
164         return eError;
165
166 Error:
167         PVRSRVDeInit(psSysData);
168         return eError;
169 }
170
171 void PVRSRVDeInit(struct SYS_DATA *psSysData)
172 {
173         enum PVRSRV_ERROR eError;
174
175         PVR_UNREFERENCED_PARAMETER(psSysData);
176
177         if (psSysData == NULL) {
178                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVDeInit: "
179                                 "PVRSRVHandleDeInit failed - invalid param");
180                 return;
181         }
182
183         if (psSysData->psGlobalEventObject) {
184                 OSEventObjectDestroy(psSysData->psGlobalEventObject);
185                 OSFreeMem(PVRSRV_PAGEABLE_SELECT,
186                           sizeof(struct PVRSRV_EVENTOBJECT),
187                           psSysData->psGlobalEventObject, NULL);
188         }
189
190         eError = PVRSRVHandleDeInit();
191         if (eError != PVRSRV_OK)
192                 PVR_DPF(PVR_DBG_ERROR,
193                          "PVRSRVDeInit: PVRSRVHandleDeInit failed");
194
195         eError = PVRSRVPerProcessDataDeInit();
196         if (eError != PVRSRV_OK)
197                 PVR_DPF(PVR_DBG_ERROR,
198                          "PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed");
199
200         ResManDeInit();
201 }
202
203 enum PVRSRV_ERROR PVRSRVRegisterDevice(struct SYS_DATA *psSysData,
204                                   enum PVRSRV_ERROR(*pfnRegisterDevice)
205                                   (struct PVRSRV_DEVICE_NODE *),
206                                   u32 ui32SOCInterruptBit,
207                                   u32 *pui32DeviceIndex)
208 {
209         enum PVRSRV_ERROR eError;
210         struct PVRSRV_DEVICE_NODE *psDeviceNode;
211
212         if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
213                        sizeof(struct PVRSRV_DEVICE_NODE),
214                        (void **) &psDeviceNode, NULL) != PVRSRV_OK) {
215                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterDevice : "
216                                 "Failed to alloc memory for psDeviceNode");
217                 return PVRSRV_ERROR_OUT_OF_MEMORY;
218         }
219         OSMemSet(psDeviceNode, 0, sizeof(struct PVRSRV_DEVICE_NODE));
220
221         eError = pfnRegisterDevice(psDeviceNode);
222         if (eError != PVRSRV_OK) {
223                 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
224                           sizeof(struct PVRSRV_DEVICE_NODE), psDeviceNode,
225                           NULL);
226                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterDevice : "
227                                         "Failed to register device");
228                 return PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
229         }
230
231         psDeviceNode->ui32RefCount = 1;
232         psDeviceNode->psSysData = psSysData;
233         psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
234
235         AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
236
237         psDeviceNode->psNext = psSysData->psDeviceNodeList;
238         psSysData->psDeviceNodeList = psDeviceNode;
239
240         *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
241
242         return PVRSRV_OK;
243 }
244
245 enum PVRSRV_ERROR PVRSRVInitialiseDevice(u32 ui32DevIndex)
246 {
247         struct PVRSRV_DEVICE_NODE *psDeviceNode;
248         struct SYS_DATA *psSysData;
249         enum PVRSRV_ERROR eError;
250
251         PVR_DPF(PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice");
252
253         eError = SysAcquireData(&psSysData);
254         if (eError != PVRSRV_OK) {
255                 PVR_DPF(PVR_DBG_ERROR,
256                          "PVRSRVInitialiseDevice: Failed to get SysData");
257                 return eError;
258         }
259
260         psDeviceNode = psSysData->psDeviceNodeList;
261
262         while (psDeviceNode) {
263                 if (psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)
264                         goto FoundDevice;
265                 psDeviceNode = psDeviceNode->psNext;
266         }
267
268         PVR_DPF(PVR_DBG_ERROR,
269                  "PVRSRVInitialiseDevice: requested device is not present");
270         return PVRSRV_ERROR_INIT_FAILURE;
271
272 FoundDevice:
273
274         PVR_ASSERT(psDeviceNode->ui32RefCount > 0);
275
276         eError = PVRSRVResManConnect(NULL, &psDeviceNode->hResManContext);
277         if (eError != PVRSRV_OK) {
278                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVInitialiseDevice: "
279                                         "Failed PVRSRVResManConnect call");
280                 return eError;
281         }
282
283         if (psDeviceNode->pfnInitDevice != NULL) {
284                 eError = psDeviceNode->pfnInitDevice(psDeviceNode);
285                 if (eError != PVRSRV_OK) {
286                         PVR_DPF(PVR_DBG_ERROR, "PVRSRVInitialiseDevice: "
287                                                 "Failed InitDevice call");
288                         return eError;
289                 }
290         }
291
292         psDeviceNode->sync_table = HASH_Create(HASH_TAB_INIT_SIZE);
293         if (psDeviceNode->sync_table == NULL) {
294                 PVR_DPF(PVR_DBG_ERROR, "InitDevInfo: "
295                                 "Couldn't create syncobject hash table");
296                 eError = PVRSRV_ERROR_GENERIC;
297                 return eError;
298         }
299
300         return PVRSRV_OK;
301 }
302
303 enum PVRSRV_ERROR PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
304 {
305         struct PVRSRV_DEVICE_NODE *psDeviceNode;
306         struct SYS_DATA *psSysData;
307         enum PVRSRV_ERROR eError;
308
309         PVR_DPF(PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem");
310
311         eError = SysAcquireData(&psSysData);
312         if (eError != PVRSRV_OK) {
313                 PVR_DPF(PVR_DBG_ERROR,
314                          "PVRSRVFinaliseSystem: Failed to get SysData");
315                 return eError;
316         }
317
318         if (bInitSuccessful) {
319                 eError = SysFinalise();
320                 if (eError != PVRSRV_OK) {
321                         PVR_DPF(PVR_DBG_ERROR,
322                                 "PVRSRVFinaliseSystem: SysFinalise failed (%d)",
323                                  eError);
324                         return eError;
325                 }
326
327                 psDeviceNode = psSysData->psDeviceNodeList;
328                 while (psDeviceNode) {
329                         eError =
330                             PVRSRVSetDevicePowerStateKM(
331                                         psDeviceNode->sDevId.ui32DeviceIndex,
332                                         PVRSRV_POWER_Unspecified);
333                         if (eError != PVRSRV_OK)
334                                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVFinaliseSystem: "
335                                         "Failed PVRSRVSetDevicePowerStateKM "
336                                         "call (device index: %d)",
337                                  psDeviceNode->sDevId.ui32DeviceIndex);
338                         psDeviceNode = psDeviceNode->psNext;
339                 }
340
341                 psDeviceNode = psSysData->psDeviceNodeList;
342                 while (psDeviceNode) {
343                         if (psDeviceNode->pfnInitDeviceCompatCheck) {
344                                 eError = PVRSRVDevInitCompatCheck(psDeviceNode);
345                                 if (eError != PVRSRV_OK) {
346                                         PVR_DPF(PVR_DBG_ERROR,
347                                         "PVRSRVFinaliseSystem: "
348                                         "Failed PVRSRVDevInitCompatCheck "
349                                         "call (device index: %d)",
350                                                  psDeviceNode->sDevId.
351                                                  ui32DeviceIndex);
352                                         return eError;
353                                 }
354                         }
355                         psDeviceNode = psDeviceNode->psNext;
356
357                 }
358
359         }
360
361         return PVRSRV_OK;
362 }
363
364 enum PVRSRV_ERROR PVRSRVDevInitCompatCheck(struct PVRSRV_DEVICE_NODE
365                                            *psDeviceNode)
366 {
367
368         return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
369 }
370
371 enum PVRSRV_ERROR PVRSRVAcquireDeviceDataKM(u32 ui32DevIndex,
372                                 enum PVRSRV_DEVICE_TYPE eDeviceType,
373                                 void **phDevCookie)
374 {
375         struct PVRSRV_DEVICE_NODE *psDeviceNode;
376         struct SYS_DATA *psSysData;
377         enum PVRSRV_ERROR eError;
378
379         PVR_DPF(PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM");
380
381         eError = SysAcquireData(&psSysData);
382         if (eError != PVRSRV_OK) {
383                 PVR_DPF(PVR_DBG_ERROR,
384                          "PVRSRVAcquireDeviceDataKM: Failed to get SysData");
385                 return eError;
386         }
387
388         psDeviceNode = psSysData->psDeviceNodeList;
389
390         if (eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN) {
391                 while (psDeviceNode) {
392                         if (psDeviceNode->sDevId.eDeviceType == eDeviceType)
393                                 goto FoundDevice;
394                         psDeviceNode = psDeviceNode->psNext;
395                 }
396         } else {
397                 while (psDeviceNode) {
398                         if (psDeviceNode->sDevId.ui32DeviceIndex ==
399                             ui32DevIndex) {
400                                 goto FoundDevice;
401                         }
402                         psDeviceNode = psDeviceNode->psNext;
403                 }
404         }
405
406         PVR_DPF(PVR_DBG_ERROR,
407                  "PVRSRVAcquireDeviceDataKM: requested device is not present");
408         return PVRSRV_ERROR_INIT_FAILURE;
409
410 FoundDevice:
411
412         PVR_ASSERT(psDeviceNode->ui32RefCount > 0);
413
414         if (phDevCookie)
415                 *phDevCookie = (void *) psDeviceNode;
416
417         return PVRSRV_OK;
418 }
419
420 enum PVRSRV_ERROR PVRSRVDeinitialiseDevice(u32 ui32DevIndex)
421 {
422         struct PVRSRV_DEVICE_NODE *psDeviceNode;
423         struct PVRSRV_DEVICE_NODE **ppsDevNode;
424         struct SYS_DATA *psSysData;
425         enum PVRSRV_ERROR eError;
426
427         eError = SysAcquireData(&psSysData);
428         if (eError != PVRSRV_OK) {
429                 PVR_DPF(PVR_DBG_ERROR,
430                          "PVRSRVDeinitialiseDevice: Failed to get SysData");
431                 return eError;
432         }
433
434         ppsDevNode = &psSysData->psDeviceNodeList;
435         while (*ppsDevNode) {
436                 if ((*ppsDevNode)->sDevId.ui32DeviceIndex == ui32DevIndex) {
437                         psDeviceNode = *ppsDevNode;
438                         goto FoundDevice;
439                 }
440                 ppsDevNode = &((*ppsDevNode)->psNext);
441         }
442
443         PVR_DPF(PVR_DBG_ERROR,
444                  "PVRSRVDeinitialiseDevice: requested device %d is not present",
445                  ui32DevIndex);
446
447         return PVRSRV_ERROR_GENERIC;
448
449 FoundDevice:
450
451         eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
452                                              PVRSRV_POWER_STATE_D3);
453         if (eError != PVRSRV_OK) {
454                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVDeinitialiseDevice: "
455                                 "Failed PVRSRVSetDevicePowerStateKM call");
456                 return eError;
457         }
458
459         HASH_Delete(psDeviceNode->sync_table);
460
461         ResManFreeResByCriteria(psDeviceNode->hResManContext,
462                                          RESMAN_CRITERIA_RESTYPE,
463                                          RESMAN_TYPE_DEVICEMEM_ALLOCATION,
464                                          NULL, 0);
465
466         if (psDeviceNode->pfnDeInitDevice != NULL) {
467                 eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
468                 if (eError != PVRSRV_OK) {
469                         PVR_DPF(PVR_DBG_ERROR, "PVRSRVDeinitialiseDevice: "
470                                                 "Failed DeInitDevice call");
471                         return eError;
472                 }
473         }
474
475         PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE);
476         psDeviceNode->hResManContext = NULL;
477
478         *ppsDevNode = psDeviceNode->psNext;
479
480         FreeDeviceID(psSysData, ui32DevIndex);
481         OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
482                   sizeof(struct PVRSRV_DEVICE_NODE), psDeviceNode, NULL);
483
484         return PVRSRV_OK;
485 }
486
487 enum PVRSRV_ERROR PollForValueKM(u32 __iomem *pui32LinMemAddr,
488                                  u32 ui32Value, u32 ui32Mask, u32 ui32Waitus,
489                                  u32 ui32Tries)
490 {
491         u32 uiMaxTime;
492
493         uiMaxTime = ui32Tries * ui32Waitus;
494
495         LOOP_UNTIL_TIMEOUT(uiMaxTime) {
496                 if ((readl(pui32LinMemAddr) & ui32Mask) == ui32Value)
497                         return PVRSRV_OK;
498         }
499         END_LOOP_UNTIL_TIMEOUT();
500
501         return PVRSRV_ERROR_GENERIC;
502 }
503
504
505 enum PVRSRV_ERROR PVRSRVGetMiscInfoKM(struct PVRSRV_MISC_INFO *psMiscInfo)
506 {
507         struct SYS_DATA *psSysData;
508         enum PVRSRV_ERROR eError;
509
510         if (!psMiscInfo) {
511                 PVR_DPF(PVR_DBG_ERROR,
512                          "PVRSRVGetMiscInfoKM: invalid parameters");
513                 return PVRSRV_ERROR_INVALID_PARAMS;
514         }
515
516         psMiscInfo->ui32StatePresent = 0;
517
518         if (psMiscInfo->ui32StateRequest & ~(
519                                 PVRSRV_MISC_INFO_TIMER_PRESENT             |
520                           PVRSRV_MISC_INFO_CLOCKGATE_PRESENT |
521                           PVRSRV_MISC_INFO_MEMSTATS_PRESENT |
522                                 PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT |
523                                 PVRSRV_MISC_INFO_DDKVERSION_PRESENT)) {
524                 PVR_DPF(PVR_DBG_ERROR,
525                          "PVRSRVGetMiscInfoKM: invalid state request flags");
526                 return PVRSRV_ERROR_INVALID_PARAMS;
527         }
528
529         eError = SysAcquireData(&psSysData);
530         if (eError != PVRSRV_OK) {
531                 PVR_DPF(PVR_DBG_ERROR,
532                          "PVRSRVGetMiscInfoKM: Failed to get SysData");
533                 return eError;
534         }
535
536         if (((psMiscInfo->ui32StateRequest &
537              PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
538              (psSysData->pvSOCTimerRegisterKM != NULL)) {
539                 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
540                 psMiscInfo->pvSOCTimerRegisterKM =
541                     psSysData->pvSOCTimerRegisterKM;
542                 psMiscInfo->hSOCTimerRegisterOSMemHandle =
543                     psSysData->hSOCTimerRegisterOSMemHandle;
544         } else {
545                 psMiscInfo->pvSOCTimerRegisterKM = NULL;
546                 psMiscInfo->hSOCTimerRegisterOSMemHandle = NULL;
547         }
548
549         if (((psMiscInfo->ui32StateRequest &
550             PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
551             (psSysData->pvSOCClockGateRegsBase != NULL)) {
552                 psMiscInfo->ui32StatePresent |=
553                     PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
554                 psMiscInfo->pvSOCClockGateRegs =
555                     psSysData->pvSOCClockGateRegsBase;
556                 psMiscInfo->ui32SOCClockGateRegsSize =
557                     psSysData->ui32SOCClockGateRegsSize;
558         }
559
560         if (((psMiscInfo->ui32StateRequest &
561               PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
562              (psMiscInfo->pszMemoryStr != NULL)) {
563                 struct RA_ARENA **ppArena;
564                 struct BM_HEAP *psBMHeap;
565                 struct BM_CONTEXT *psBMContext;
566                 struct PVRSRV_DEVICE_NODE *psDeviceNode;
567                 char *pszStr;
568                 u32 ui32StrLen;
569                 s32 i32Count;
570
571                 pszStr = psMiscInfo->pszMemoryStr;
572                 ui32StrLen = psMiscInfo->ui32MemoryStrLen;
573
574                 psMiscInfo->ui32StatePresent |=
575                     PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
576
577                 ppArena = &psSysData->apsLocalDevMemArena[0];
578                 while (*ppArena) {
579                         CHECK_SPACE(ui32StrLen);
580                         i32Count =
581                             OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n");
582                         UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
583
584                         RA_GetStats(*ppArena, &pszStr, &ui32StrLen);
585
586                         ppArena++;
587                 }
588
589                 psDeviceNode = psSysData->psDeviceNodeList;
590                 while (psDeviceNode) {
591                         CHECK_SPACE(ui32StrLen);
592                         i32Count =
593                             OSSNPrintf(pszStr, 100, "\n\nDevice Type %d:\n",
594                                        psDeviceNode->sDevId.eDeviceType);
595                         UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
596
597                         if (psDeviceNode->sDevMemoryInfo.pBMKernelContext) {
598                                 CHECK_SPACE(ui32StrLen);
599                                 i32Count =
600                                     OSSNPrintf(pszStr, 100,
601                                                "\nKernel Context:\n");
602                                 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
603
604                                 psBMHeap =
605                                     psDeviceNode->sDevMemoryInfo.
606                                     pBMKernelContext->psBMHeap;
607                                 while (psBMHeap) {
608                                         if (psBMHeap->pImportArena) {
609                                                 RA_GetStats(psBMHeap->
610                                                                 pImportArena,
611                                                             &pszStr,
612                                                             &ui32StrLen);
613                                         }
614
615                                         if (psBMHeap->pVMArena) {
616                                                 RA_GetStats(psBMHeap->pVMArena,
617                                                             &pszStr,
618                                                             &ui32StrLen);
619                                         }
620                                         psBMHeap = psBMHeap->psNext;
621                                 }
622                         }
623
624                         psBMContext = psDeviceNode->sDevMemoryInfo.pBMContext;
625                         while (psBMContext) {
626                                 CHECK_SPACE(ui32StrLen);
627                                 i32Count =
628                                     OSSNPrintf(pszStr, 100,
629                         "\nApplication Context (hDevMemContext) 0x%08X:\n",
630                                                    (void *)psBMContext);
631                                 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
632
633                                 psBMHeap = psBMContext->psBMHeap;
634                                 while (psBMHeap) {
635                                         if (psBMHeap->pImportArena) {
636                                                 RA_GetStats(psBMHeap->
637                                                                 pImportArena,
638                                                             &pszStr,
639                                                             &ui32StrLen);
640                                         }
641
642                                         if (psBMHeap->pVMArena) {
643                                                 RA_GetStats(psBMHeap->pVMArena,
644                                                             &pszStr,
645                                                             &ui32StrLen);
646                                         }
647                                         psBMHeap = psBMHeap->psNext;
648                                 }
649                                 psBMContext = psBMContext->psNext;
650                         }
651                         psDeviceNode = psDeviceNode->psNext;
652                 }
653
654                 i32Count = OSSNPrintf(pszStr, 100, "\n\0");
655                 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
656         }
657
658         if (((psMiscInfo->ui32StateRequest &
659               PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) &&
660              (psSysData->psGlobalEventObject != NULL)) {
661                 psMiscInfo->ui32StatePresent |=
662                     PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
663                 psMiscInfo->sGlobalEventObject =
664                     *psSysData->psGlobalEventObject;
665         }
666
667         if (((psMiscInfo->ui32StateRequest &
668                         PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL) &&
669             ((psMiscInfo->ui32StateRequest &
670                         PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL) &&
671              (psMiscInfo->pszMemoryStr != NULL)) {
672                 char *pszStr;
673                 u32 ui32StrLen;
674                 u32 ui32LenStrPerNum = 12;
675                 s32 i32Count;
676                 int i;
677                 psMiscInfo->ui32StatePresent |=
678                     PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
679
680                 psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ;
681                 psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN;
682                 psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BRANCH;
683                 psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD;
684
685                 pszStr = psMiscInfo->pszMemoryStr;
686                 ui32StrLen = psMiscInfo->ui32MemoryStrLen;
687
688                 for (i = 0; i < 4; i++) {
689                         if (ui32StrLen < ui32LenStrPerNum)
690                                 return PVRSRV_ERROR_INVALID_PARAMS;
691
692                         i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%ld",
693                                        psMiscInfo->aui32DDKVersion[i]);
694                         UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
695                         if (i != 3) {
696                                 i32Count = OSSNPrintf(pszStr, 2, ".");
697                                 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
698                         }
699                 }
700         }
701
702         return PVRSRV_OK;
703 }
704
705 enum PVRSRV_ERROR PVRSRVGetFBStatsKM(u32 *pui32Total, u32 *pui32Available)
706 {
707         u32 ui32Total = 0, i = 0;
708         u32 ui32Available = 0;
709
710         *pui32Total = 0;
711         *pui32Available = 0;
712
713         while (BM_ContiguousStatistics(i, &ui32Total, &ui32Available) ==
714                IMG_TRUE) {
715                 *pui32Total += ui32Total;
716                 *pui32Available += ui32Available;
717
718                 i++;
719         }
720
721         return PVRSRV_OK;
722 }
723
724 IMG_BOOL PVRSRVDeviceLISR(struct PVRSRV_DEVICE_NODE *psDeviceNode)
725 {
726         struct SYS_DATA *psSysData;
727         IMG_BOOL bStatus = IMG_FALSE;
728         u32 ui32InterruptSource;
729
730         if (!psDeviceNode) {
731                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n");
732                 goto out;
733         }
734         psSysData = psDeviceNode->psSysData;
735
736         ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
737         if (ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit) {
738                 if (psDeviceNode->pfnDeviceISR != NULL)
739                         bStatus =
740                             (*psDeviceNode->pfnDeviceISR) (psDeviceNode->
741                                                            pvISRData);
742
743                 SysClearInterrupts(psSysData,
744                                    psDeviceNode->ui32SOCInterruptBit);
745         }
746
747 out:
748         return bStatus;
749 }
750
751 IMG_BOOL PVRSRVSystemLISR(void *pvSysData)
752 {
753         struct SYS_DATA *psSysData = pvSysData;
754         IMG_BOOL bStatus = IMG_FALSE;
755         u32 ui32InterruptSource;
756         u32 ui32ClearInterrupts = 0;
757         struct PVRSRV_DEVICE_NODE *psDeviceNode;
758
759         if (!psSysData) {
760                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n");
761                 goto out;
762         }
763
764         ui32InterruptSource = SysGetInterruptSource(psSysData, NULL);
765
766         if (ui32InterruptSource == 0)
767                 goto out;
768
769         psDeviceNode = psSysData->psDeviceNodeList;
770         while (psDeviceNode != NULL) {
771                 if (psDeviceNode->pfnDeviceISR != NULL)
772                         if (ui32InterruptSource & psDeviceNode->
773                             ui32SOCInterruptBit) {
774                                 if ((*psDeviceNode->pfnDeviceISR)
775                                                 (psDeviceNode->pvISRData))
776                                         bStatus = IMG_TRUE;
777
778                                 ui32ClearInterrupts |=
779                                     psDeviceNode->ui32SOCInterruptBit;
780                         }
781                 psDeviceNode = psDeviceNode->psNext;
782         }
783
784         SysClearInterrupts(psSysData, ui32ClearInterrupts);
785
786 out:
787         return bStatus;
788 }
789
790 void PVRSRVMISR(void *pvSysData)
791 {
792         struct SYS_DATA *psSysData = pvSysData;
793         struct PVRSRV_DEVICE_NODE *psDeviceNode;
794
795         if (!psSysData) {
796                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n");
797                 return;
798         }
799
800         pvr_lock();
801
802         if (pvr_is_disabled()) {
803                 pvr_unlock();
804                 return;
805         }
806
807         psDeviceNode = psSysData->psDeviceNodeList;
808         while (psDeviceNode != NULL) {
809                 if (psDeviceNode->pfnDeviceMISR != NULL)
810                         (*psDeviceNode->pfnDeviceMISR)(psDeviceNode->
811                                                                 pvISRData);
812                 psDeviceNode = psDeviceNode->psNext;
813         }
814
815         PVRSRVProcessQueues(IMG_FALSE);
816
817         if (psSysData->psGlobalEventObject) {
818                 void *hOSEventKM =
819                     psSysData->psGlobalEventObject->hOSEventKM;
820                 if (hOSEventKM)
821                         OSEventObjectSignal(hOSEventKM);
822         }
823
824         pvr_handle_sync_events();
825
826         pvr_unlock();
827 }
828
829 enum PVRSRV_ERROR PVRSRVProcessConnect(u32 ui32PID)
830 {
831         return PVRSRVPerProcessDataConnect(ui32PID);
832 }
833
834 void PVRSRVProcessDisconnect(u32 ui32PID)
835 {
836         PVRSRVPerProcessDataDisconnect(ui32PID);
837 }
838
839 enum PVRSRV_ERROR PVRSRVSaveRestoreLiveSegments(void *hArena, u8 *pbyBuffer,
840                                            u32 *puiBufSize, IMG_BOOL bSave)
841 {
842         u32 uiBytesSaved = 0;
843         void *pvLocalMemCPUVAddr;
844         struct RA_SEGMENT_DETAILS sSegDetails;
845
846         if (hArena == NULL)
847                 return PVRSRV_ERROR_INVALID_PARAMS;
848
849         sSegDetails.uiSize = 0;
850         sSegDetails.sCpuPhyAddr.uiAddr = 0;
851         sSegDetails.hSegment = NULL;
852
853         while (RA_GetNextLiveSegment(hArena, &sSegDetails))
854                 if (pbyBuffer == NULL) {
855                         uiBytesSaved +=
856                             sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
857                 } else {
858                         if ((uiBytesSaved + sizeof(sSegDetails.uiSize) +
859                              sSegDetails.uiSize) > *puiBufSize)
860                                 return PVRSRV_ERROR_OUT_OF_MEMORY;
861
862                         PVR_DPF(PVR_DBG_MESSAGE,
863                                  "PVRSRVSaveRestoreLiveSegments: "
864                                  "Base %08x size %08x",
865                                  sSegDetails.sCpuPhyAddr.uiAddr,
866                                  sSegDetails.uiSize);
867
868                         pvLocalMemCPUVAddr = (void __force *)
869                             OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
870                                            sSegDetails.uiSize,
871                                            PVRSRV_HAP_KERNEL_ONLY |
872                                            PVRSRV_HAP_UNCACHED, NULL);
873                         if (pvLocalMemCPUVAddr == NULL) {
874                                 PVR_DPF(PVR_DBG_ERROR,
875                                          "PVRSRVSaveRestoreLiveSegments: "
876                                          "Failed to map local memory to host");
877                                 return PVRSRV_ERROR_OUT_OF_MEMORY;
878                         }
879
880                         if (bSave) {
881                                 OSMemCopy(pbyBuffer, &sSegDetails.uiSize,
882                                           sizeof(sSegDetails.uiSize));
883                                 pbyBuffer += sizeof(sSegDetails.uiSize);
884
885                                 OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr,
886                                           sSegDetails.uiSize);
887                                 pbyBuffer += sSegDetails.uiSize;
888                         } else {
889                                 u32 uiSize;
890
891                                 OSMemCopy(&uiSize, pbyBuffer,
892                                           sizeof(sSegDetails.uiSize));
893
894                                 if (uiSize != sSegDetails.uiSize) {
895                                         PVR_DPF(PVR_DBG_ERROR,
896                                                 "PVRSRVSaveRestoreLiveSegments:"
897                                                 " Segment size error");
898                                 } else {
899                                         pbyBuffer += sizeof(sSegDetails.uiSize);
900
901                                         OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer,
902                                                   sSegDetails.uiSize);
903                                         pbyBuffer += sSegDetails.uiSize;
904                                 }
905                         }
906
907                         uiBytesSaved +=
908                             sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
909
910                         OSUnMapPhysToLin((void __force __iomem *)
911                                                         pvLocalMemCPUVAddr,
912                                          sSegDetails.uiSize,
913                                          PVRSRV_HAP_KERNEL_ONLY |
914                                          PVRSRV_HAP_UNCACHED, NULL);
915                 }
916
917         if (pbyBuffer == NULL)
918                 *puiBufSize = uiBytesSaved;
919
920         return PVRSRV_OK;
921 }