gpu: pvr: get rid of unnecessary hash lookups for the proc object
[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 "pvr_pdump.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 (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
150                        sizeof(struct PVRSRV_EVENTOBJECT),
151                        (void **) &psSysData->psGlobalEventObject,
152                        NULL) != PVRSRV_OK)
153
154                 goto Error;
155
156         if (OSEventObjectCreate("PVRSRV_GLOBAL_EVENTOBJECT",
157                                 psSysData->psGlobalEventObject) != PVRSRV_OK)
158                 goto Error;
159
160         return eError;
161
162 Error:
163         PVRSRVDeInit(psSysData);
164         return eError;
165 }
166
167 void PVRSRVDeInit(struct SYS_DATA *psSysData)
168 {
169         enum PVRSRV_ERROR eError;
170
171         PVR_UNREFERENCED_PARAMETER(psSysData);
172
173         if (psSysData == NULL) {
174                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVDeInit: "
175                                 "PVRSRVHandleDeInit failed - invalid param");
176                 return;
177         }
178
179         if (psSysData->psGlobalEventObject) {
180                 OSEventObjectDestroy(psSysData->psGlobalEventObject);
181                 OSFreeMem(PVRSRV_PAGEABLE_SELECT,
182                           sizeof(struct PVRSRV_EVENTOBJECT),
183                           psSysData->psGlobalEventObject, NULL);
184         }
185
186         eError = PVRSRVHandleDeInit();
187         if (eError != PVRSRV_OK)
188                 PVR_DPF(PVR_DBG_ERROR,
189                          "PVRSRVDeInit: PVRSRVHandleDeInit failed");
190
191         eError = PVRSRVPerProcessDataDeInit();
192         if (eError != PVRSRV_OK)
193                 PVR_DPF(PVR_DBG_ERROR,
194                          "PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed");
195
196         ResManDeInit();
197 }
198
199 enum PVRSRV_ERROR PVRSRVRegisterDevice(struct SYS_DATA *psSysData,
200                                   enum PVRSRV_ERROR(*pfnRegisterDevice)
201                                   (struct PVRSRV_DEVICE_NODE *),
202                                   u32 ui32SOCInterruptBit,
203                                   u32 *pui32DeviceIndex)
204 {
205         enum PVRSRV_ERROR eError;
206         struct PVRSRV_DEVICE_NODE *psDeviceNode;
207
208         if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
209                        sizeof(struct PVRSRV_DEVICE_NODE),
210                        (void **) &psDeviceNode, NULL) != PVRSRV_OK) {
211                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterDevice : "
212                                 "Failed to alloc memory for psDeviceNode");
213                 return PVRSRV_ERROR_OUT_OF_MEMORY;
214         }
215         OSMemSet(psDeviceNode, 0, sizeof(struct PVRSRV_DEVICE_NODE));
216
217         eError = pfnRegisterDevice(psDeviceNode);
218         if (eError != PVRSRV_OK) {
219                 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
220                           sizeof(struct PVRSRV_DEVICE_NODE), psDeviceNode,
221                           NULL);
222                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterDevice : "
223                                         "Failed to register device");
224                 return PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
225         }
226
227         psDeviceNode->ui32RefCount = 1;
228         psDeviceNode->psSysData = psSysData;
229         psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
230
231         AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
232
233         psDeviceNode->psNext = psSysData->psDeviceNodeList;
234         psSysData->psDeviceNodeList = psDeviceNode;
235
236         *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
237
238         return PVRSRV_OK;
239 }
240
241 enum PVRSRV_ERROR PVRSRVInitialiseDevice(u32 ui32DevIndex)
242 {
243         struct PVRSRV_DEVICE_NODE *psDeviceNode;
244         struct SYS_DATA *psSysData;
245         enum PVRSRV_ERROR eError;
246
247         PVR_DPF(PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice");
248
249         eError = SysAcquireData(&psSysData);
250         if (eError != PVRSRV_OK) {
251                 PVR_DPF(PVR_DBG_ERROR,
252                          "PVRSRVInitialiseDevice: Failed to get SysData");
253                 return eError;
254         }
255
256         psDeviceNode = psSysData->psDeviceNodeList;
257
258         while (psDeviceNode) {
259                 if (psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)
260                         goto FoundDevice;
261                 psDeviceNode = psDeviceNode->psNext;
262         }
263
264         PVR_DPF(PVR_DBG_ERROR,
265                  "PVRSRVInitialiseDevice: requested device is not present");
266         return PVRSRV_ERROR_INIT_FAILURE;
267
268 FoundDevice:
269
270         PVR_ASSERT(psDeviceNode->ui32RefCount > 0);
271
272         eError = PVRSRVResManConnect(NULL, &psDeviceNode->hResManContext);
273         if (eError != PVRSRV_OK) {
274                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVInitialiseDevice: "
275                                         "Failed PVRSRVResManConnect call");
276                 return eError;
277         }
278
279         if (psDeviceNode->pfnInitDevice != NULL) {
280                 eError = psDeviceNode->pfnInitDevice(psDeviceNode);
281                 if (eError != PVRSRV_OK) {
282                         PVR_DPF(PVR_DBG_ERROR, "PVRSRVInitialiseDevice: "
283                                                 "Failed InitDevice call");
284                         return eError;
285                 }
286         }
287
288         psDeviceNode->sync_table = HASH_Create(HASH_TAB_INIT_SIZE);
289         if (psDeviceNode->sync_table == NULL) {
290                 PVR_DPF(PVR_DBG_ERROR, "InitDevInfo: "
291                                 "Couldn't create syncobject hash table");
292                 eError = PVRSRV_ERROR_GENERIC;
293                 return eError;
294         }
295
296         return PVRSRV_OK;
297 }
298
299 enum PVRSRV_ERROR PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
300 {
301         struct PVRSRV_DEVICE_NODE *psDeviceNode;
302         struct SYS_DATA *psSysData;
303         enum PVRSRV_ERROR eError;
304
305         PVR_DPF(PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem");
306
307         eError = SysAcquireData(&psSysData);
308         if (eError != PVRSRV_OK) {
309                 PVR_DPF(PVR_DBG_ERROR,
310                          "PVRSRVFinaliseSystem: Failed to get SysData");
311                 return eError;
312         }
313
314         if (bInitSuccessful) {
315                 eError = SysFinalise();
316                 if (eError != PVRSRV_OK) {
317                         PVR_DPF(PVR_DBG_ERROR,
318                                 "PVRSRVFinaliseSystem: SysFinalise failed (%d)",
319                                  eError);
320                         return eError;
321                 }
322
323                 psDeviceNode = psSysData->psDeviceNodeList;
324                 while (psDeviceNode) {
325                         eError =
326                             PVRSRVSetDevicePowerStateKM(
327                                         psDeviceNode->sDevId.ui32DeviceIndex,
328                                         PVRSRV_POWER_Unspecified);
329                         if (eError != PVRSRV_OK)
330                                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVFinaliseSystem: "
331                                         "Failed PVRSRVSetDevicePowerStateKM "
332                                         "call (device index: %d)",
333                                  psDeviceNode->sDevId.ui32DeviceIndex);
334                         psDeviceNode = psDeviceNode->psNext;
335                 }
336
337                 psDeviceNode = psSysData->psDeviceNodeList;
338                 while (psDeviceNode) {
339                         if (psDeviceNode->pfnInitDeviceCompatCheck) {
340                                 eError = PVRSRVDevInitCompatCheck(psDeviceNode);
341                                 if (eError != PVRSRV_OK) {
342                                         PVR_DPF(PVR_DBG_ERROR,
343                                         "PVRSRVFinaliseSystem: "
344                                         "Failed PVRSRVDevInitCompatCheck "
345                                         "call (device index: %d)",
346                                                  psDeviceNode->sDevId.
347                                                  ui32DeviceIndex);
348                                         return eError;
349                                 }
350                         }
351                         psDeviceNode = psDeviceNode->psNext;
352
353                 }
354
355         }
356
357         return PVRSRV_OK;
358 }
359
360 enum PVRSRV_ERROR PVRSRVDevInitCompatCheck(struct PVRSRV_DEVICE_NODE
361                                            *psDeviceNode)
362 {
363
364         return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
365 }
366
367 enum PVRSRV_ERROR PVRSRVAcquireDeviceDataKM(u32 ui32DevIndex,
368                                 enum PVRSRV_DEVICE_TYPE eDeviceType,
369                                 void **phDevCookie)
370 {
371         struct PVRSRV_DEVICE_NODE *psDeviceNode;
372         struct SYS_DATA *psSysData;
373         enum PVRSRV_ERROR eError;
374
375         PVR_DPF(PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM");
376
377         eError = SysAcquireData(&psSysData);
378         if (eError != PVRSRV_OK) {
379                 PVR_DPF(PVR_DBG_ERROR,
380                          "PVRSRVAcquireDeviceDataKM: Failed to get SysData");
381                 return eError;
382         }
383
384         psDeviceNode = psSysData->psDeviceNodeList;
385
386         if (eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN) {
387                 while (psDeviceNode) {
388                         if (psDeviceNode->sDevId.eDeviceType == eDeviceType)
389                                 goto FoundDevice;
390                         psDeviceNode = psDeviceNode->psNext;
391                 }
392         } else {
393                 while (psDeviceNode) {
394                         if (psDeviceNode->sDevId.ui32DeviceIndex ==
395                             ui32DevIndex) {
396                                 goto FoundDevice;
397                         }
398                         psDeviceNode = psDeviceNode->psNext;
399                 }
400         }
401
402         PVR_DPF(PVR_DBG_ERROR,
403                  "PVRSRVAcquireDeviceDataKM: requested device is not present");
404         return PVRSRV_ERROR_INIT_FAILURE;
405
406 FoundDevice:
407
408         PVR_ASSERT(psDeviceNode->ui32RefCount > 0);
409
410         if (phDevCookie)
411                 *phDevCookie = (void *) psDeviceNode;
412
413         return PVRSRV_OK;
414 }
415
416 enum PVRSRV_ERROR PVRSRVDeinitialiseDevice(u32 ui32DevIndex)
417 {
418         struct PVRSRV_DEVICE_NODE *psDeviceNode;
419         struct PVRSRV_DEVICE_NODE **ppsDevNode;
420         struct SYS_DATA *psSysData;
421         enum PVRSRV_ERROR eError;
422
423         eError = SysAcquireData(&psSysData);
424         if (eError != PVRSRV_OK) {
425                 PVR_DPF(PVR_DBG_ERROR,
426                          "PVRSRVDeinitialiseDevice: Failed to get SysData");
427                 return eError;
428         }
429
430         ppsDevNode = &psSysData->psDeviceNodeList;
431         while (*ppsDevNode) {
432                 if ((*ppsDevNode)->sDevId.ui32DeviceIndex == ui32DevIndex) {
433                         psDeviceNode = *ppsDevNode;
434                         goto FoundDevice;
435                 }
436                 ppsDevNode = &((*ppsDevNode)->psNext);
437         }
438
439         PVR_DPF(PVR_DBG_ERROR,
440                  "PVRSRVDeinitialiseDevice: requested device %d is not present",
441                  ui32DevIndex);
442
443         return PVRSRV_ERROR_GENERIC;
444
445 FoundDevice:
446
447         eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
448                                              PVRSRV_POWER_STATE_D3);
449         if (eError != PVRSRV_OK) {
450                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVDeinitialiseDevice: "
451                                 "Failed PVRSRVSetDevicePowerStateKM call");
452                 return eError;
453         }
454
455         HASH_Delete(psDeviceNode->sync_table);
456
457         ResManFreeResByCriteria(psDeviceNode->hResManContext,
458                                          RESMAN_CRITERIA_RESTYPE,
459                                          RESMAN_TYPE_DEVICEMEM_ALLOCATION,
460                                          NULL, 0);
461
462         if (psDeviceNode->pfnDeInitDevice != NULL) {
463                 eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
464                 if (eError != PVRSRV_OK) {
465                         PVR_DPF(PVR_DBG_ERROR, "PVRSRVDeinitialiseDevice: "
466                                                 "Failed DeInitDevice call");
467                         return eError;
468                 }
469         }
470
471         PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE);
472         psDeviceNode->hResManContext = NULL;
473
474         *ppsDevNode = psDeviceNode->psNext;
475
476         FreeDeviceID(psSysData, ui32DevIndex);
477         OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
478                   sizeof(struct PVRSRV_DEVICE_NODE), psDeviceNode, NULL);
479
480         return PVRSRV_OK;
481 }
482
483 enum PVRSRV_ERROR PollForValueKM(u32 __iomem *pui32LinMemAddr,
484                                  u32 ui32Value, u32 ui32Mask, u32 ui32Waitus,
485                                  u32 ui32Tries)
486 {
487         u32 uiMaxTime;
488
489         uiMaxTime = ui32Tries * ui32Waitus;
490
491         LOOP_UNTIL_TIMEOUT(uiMaxTime) {
492                 if ((readl(pui32LinMemAddr) & ui32Mask) == ui32Value)
493                         return PVRSRV_OK;
494         }
495         END_LOOP_UNTIL_TIMEOUT();
496
497         return PVRSRV_ERROR_GENERIC;
498 }
499
500
501 enum PVRSRV_ERROR PVRSRVGetMiscInfoKM(struct PVRSRV_MISC_INFO *psMiscInfo)
502 {
503         struct SYS_DATA *psSysData;
504         enum PVRSRV_ERROR eError;
505
506         if (!psMiscInfo) {
507                 PVR_DPF(PVR_DBG_ERROR,
508                          "PVRSRVGetMiscInfoKM: invalid parameters");
509                 return PVRSRV_ERROR_INVALID_PARAMS;
510         }
511
512         psMiscInfo->ui32StatePresent = 0;
513
514         if (psMiscInfo->ui32StateRequest & ~(
515                                 PVRSRV_MISC_INFO_TIMER_PRESENT             |
516                           PVRSRV_MISC_INFO_CLOCKGATE_PRESENT |
517                           PVRSRV_MISC_INFO_MEMSTATS_PRESENT |
518                                 PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT |
519                                 PVRSRV_MISC_INFO_DDKVERSION_PRESENT)) {
520                 PVR_DPF(PVR_DBG_ERROR,
521                          "PVRSRVGetMiscInfoKM: invalid state request flags");
522                 return PVRSRV_ERROR_INVALID_PARAMS;
523         }
524
525         eError = SysAcquireData(&psSysData);
526         if (eError != PVRSRV_OK) {
527                 PVR_DPF(PVR_DBG_ERROR,
528                          "PVRSRVGetMiscInfoKM: Failed to get SysData");
529                 return eError;
530         }
531
532         if (((psMiscInfo->ui32StateRequest &
533              PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
534              (psSysData->pvSOCTimerRegisterKM != NULL)) {
535                 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
536                 psMiscInfo->pvSOCTimerRegisterKM =
537                     psSysData->pvSOCTimerRegisterKM;
538                 psMiscInfo->hSOCTimerRegisterOSMemHandle =
539                     psSysData->hSOCTimerRegisterOSMemHandle;
540         } else {
541                 psMiscInfo->pvSOCTimerRegisterKM = NULL;
542                 psMiscInfo->hSOCTimerRegisterOSMemHandle = NULL;
543         }
544
545         if (((psMiscInfo->ui32StateRequest &
546             PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
547             (psSysData->pvSOCClockGateRegsBase != NULL)) {
548                 psMiscInfo->ui32StatePresent |=
549                     PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
550                 psMiscInfo->pvSOCClockGateRegs =
551                     psSysData->pvSOCClockGateRegsBase;
552                 psMiscInfo->ui32SOCClockGateRegsSize =
553                     psSysData->ui32SOCClockGateRegsSize;
554         }
555
556         if (((psMiscInfo->ui32StateRequest &
557               PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
558              (psMiscInfo->pszMemoryStr != NULL)) {
559                 struct RA_ARENA **ppArena;
560                 struct BM_HEAP *psBMHeap;
561                 struct BM_CONTEXT *psBMContext;
562                 struct PVRSRV_DEVICE_NODE *psDeviceNode;
563                 char *pszStr;
564                 u32 ui32StrLen;
565                 s32 i32Count;
566
567                 pszStr = psMiscInfo->pszMemoryStr;
568                 ui32StrLen = psMiscInfo->ui32MemoryStrLen;
569
570                 psMiscInfo->ui32StatePresent |=
571                     PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
572
573                 ppArena = &psSysData->apsLocalDevMemArena[0];
574                 while (*ppArena) {
575                         CHECK_SPACE(ui32StrLen);
576                         i32Count =
577                             OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n");
578                         UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
579
580                         RA_GetStats(*ppArena, &pszStr, &ui32StrLen);
581
582                         ppArena++;
583                 }
584
585                 psDeviceNode = psSysData->psDeviceNodeList;
586                 while (psDeviceNode) {
587                         CHECK_SPACE(ui32StrLen);
588                         i32Count =
589                             OSSNPrintf(pszStr, 100, "\n\nDevice Type %d:\n",
590                                        psDeviceNode->sDevId.eDeviceType);
591                         UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
592
593                         if (psDeviceNode->sDevMemoryInfo.pBMKernelContext) {
594                                 CHECK_SPACE(ui32StrLen);
595                                 i32Count =
596                                     OSSNPrintf(pszStr, 100,
597                                                "\nKernel Context:\n");
598                                 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
599
600                                 psBMHeap =
601                                     psDeviceNode->sDevMemoryInfo.
602                                     pBMKernelContext->psBMHeap;
603                                 while (psBMHeap) {
604                                         if (psBMHeap->pImportArena) {
605                                                 RA_GetStats(psBMHeap->
606                                                                 pImportArena,
607                                                             &pszStr,
608                                                             &ui32StrLen);
609                                         }
610
611                                         if (psBMHeap->pVMArena) {
612                                                 RA_GetStats(psBMHeap->pVMArena,
613                                                             &pszStr,
614                                                             &ui32StrLen);
615                                         }
616                                         psBMHeap = psBMHeap->psNext;
617                                 }
618                         }
619
620                         psBMContext = psDeviceNode->sDevMemoryInfo.pBMContext;
621                         while (psBMContext) {
622                                 CHECK_SPACE(ui32StrLen);
623                                 i32Count =
624                                     OSSNPrintf(pszStr, 100,
625                         "\nApplication Context (hDevMemContext) 0x%08X:\n",
626                                                    (void *)psBMContext);
627                                 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
628
629                                 psBMHeap = psBMContext->psBMHeap;
630                                 while (psBMHeap) {
631                                         if (psBMHeap->pImportArena) {
632                                                 RA_GetStats(psBMHeap->
633                                                                 pImportArena,
634                                                             &pszStr,
635                                                             &ui32StrLen);
636                                         }
637
638                                         if (psBMHeap->pVMArena) {
639                                                 RA_GetStats(psBMHeap->pVMArena,
640                                                             &pszStr,
641                                                             &ui32StrLen);
642                                         }
643                                         psBMHeap = psBMHeap->psNext;
644                                 }
645                                 psBMContext = psBMContext->psNext;
646                         }
647                         psDeviceNode = psDeviceNode->psNext;
648                 }
649
650                 i32Count = OSSNPrintf(pszStr, 100, "\n\0");
651                 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
652         }
653
654         if (((psMiscInfo->ui32StateRequest &
655               PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) &&
656              (psSysData->psGlobalEventObject != NULL)) {
657                 psMiscInfo->ui32StatePresent |=
658                     PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
659                 psMiscInfo->sGlobalEventObject =
660                     *psSysData->psGlobalEventObject;
661         }
662
663         if (((psMiscInfo->ui32StateRequest &
664                         PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL) &&
665             ((psMiscInfo->ui32StateRequest &
666                         PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL) &&
667              (psMiscInfo->pszMemoryStr != NULL)) {
668                 char *pszStr;
669                 u32 ui32StrLen;
670                 u32 ui32LenStrPerNum = 12;
671                 s32 i32Count;
672                 int i;
673                 psMiscInfo->ui32StatePresent |=
674                     PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
675
676                 psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ;
677                 psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN;
678                 psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BRANCH;
679                 psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD;
680
681                 pszStr = psMiscInfo->pszMemoryStr;
682                 ui32StrLen = psMiscInfo->ui32MemoryStrLen;
683
684                 for (i = 0; i < 4; i++) {
685                         if (ui32StrLen < ui32LenStrPerNum)
686                                 return PVRSRV_ERROR_INVALID_PARAMS;
687
688                         i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%ld",
689                                        psMiscInfo->aui32DDKVersion[i]);
690                         UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
691                         if (i != 3) {
692                                 i32Count = OSSNPrintf(pszStr, 2, ".");
693                                 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
694                         }
695                 }
696         }
697
698         return PVRSRV_OK;
699 }
700
701 IMG_BOOL PVRSRVDeviceLISR(struct PVRSRV_DEVICE_NODE *psDeviceNode)
702 {
703         struct SYS_DATA *psSysData;
704         IMG_BOOL bStatus = IMG_FALSE;
705         u32 ui32InterruptSource;
706
707         if (!psDeviceNode) {
708                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n");
709                 goto out;
710         }
711         psSysData = psDeviceNode->psSysData;
712
713         ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
714         if (ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit) {
715                 if (psDeviceNode->pfnDeviceISR != NULL)
716                         bStatus =
717                             (*psDeviceNode->pfnDeviceISR) (psDeviceNode->
718                                                            pvISRData);
719
720                 SysClearInterrupts(psSysData,
721                                    psDeviceNode->ui32SOCInterruptBit);
722         }
723
724 out:
725         return bStatus;
726 }
727
728 IMG_BOOL PVRSRVSystemLISR(void *pvSysData)
729 {
730         struct SYS_DATA *psSysData = pvSysData;
731         IMG_BOOL bStatus = IMG_FALSE;
732         u32 ui32InterruptSource;
733         u32 ui32ClearInterrupts = 0;
734         struct PVRSRV_DEVICE_NODE *psDeviceNode;
735
736         if (!psSysData) {
737                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n");
738                 goto out;
739         }
740
741         ui32InterruptSource = SysGetInterruptSource(psSysData, NULL);
742
743         if (ui32InterruptSource == 0)
744                 goto out;
745
746         psDeviceNode = psSysData->psDeviceNodeList;
747         while (psDeviceNode != NULL) {
748                 if (psDeviceNode->pfnDeviceISR != NULL)
749                         if (ui32InterruptSource & psDeviceNode->
750                             ui32SOCInterruptBit) {
751                                 if ((*psDeviceNode->pfnDeviceISR)
752                                                 (psDeviceNode->pvISRData))
753                                         bStatus = IMG_TRUE;
754
755                                 ui32ClearInterrupts |=
756                                     psDeviceNode->ui32SOCInterruptBit;
757                         }
758                 psDeviceNode = psDeviceNode->psNext;
759         }
760
761         SysClearInterrupts(psSysData, ui32ClearInterrupts);
762
763 out:
764         return bStatus;
765 }
766
767 void PVRSRVMISR(void *pvSysData)
768 {
769         struct SYS_DATA *psSysData = pvSysData;
770         struct PVRSRV_DEVICE_NODE *psDeviceNode;
771
772         if (!psSysData) {
773                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n");
774                 return;
775         }
776
777         pvr_lock();
778
779         if (pvr_is_disabled()) {
780                 pvr_unlock();
781                 return;
782         }
783
784         psDeviceNode = psSysData->psDeviceNodeList;
785         while (psDeviceNode != NULL) {
786                 if (psDeviceNode->pfnDeviceMISR != NULL)
787                         (*psDeviceNode->pfnDeviceMISR)(psDeviceNode->
788                                                                 pvISRData);
789                 psDeviceNode = psDeviceNode->psNext;
790         }
791
792         PVRSRVProcessQueues(IMG_FALSE);
793
794         if (psSysData->psGlobalEventObject) {
795                 void *hOSEventKM =
796                     psSysData->psGlobalEventObject->hOSEventKM;
797                 if (hOSEventKM)
798                         OSEventObjectSignal(hOSEventKM);
799         }
800
801         pvr_handle_sync_events();
802
803         pvr_unlock();
804 }
805
806 enum PVRSRV_ERROR PVRSRVProcessConnect(u32 ui32PID)
807 {
808         return PVRSRVPerProcessDataConnect(ui32PID);
809 }
810
811 void PVRSRVProcessDisconnect(u32 ui32PID)
812 {
813         PVRSRVPerProcessDataDisconnect(ui32PID);
814 }
815
816 enum PVRSRV_ERROR PVRSRVSaveRestoreLiveSegments(void *hArena, u8 *pbyBuffer,
817                                            u32 *puiBufSize, IMG_BOOL bSave)
818 {
819         u32 uiBytesSaved = 0;
820         void *pvLocalMemCPUVAddr;
821         struct RA_SEGMENT_DETAILS sSegDetails;
822
823         if (hArena == NULL)
824                 return PVRSRV_ERROR_INVALID_PARAMS;
825
826         sSegDetails.uiSize = 0;
827         sSegDetails.sCpuPhyAddr.uiAddr = 0;
828         sSegDetails.hSegment = NULL;
829
830         while (RA_GetNextLiveSegment(hArena, &sSegDetails))
831                 if (pbyBuffer == NULL) {
832                         uiBytesSaved +=
833                             sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
834                 } else {
835                         if ((uiBytesSaved + sizeof(sSegDetails.uiSize) +
836                              sSegDetails.uiSize) > *puiBufSize)
837                                 return PVRSRV_ERROR_OUT_OF_MEMORY;
838
839                         PVR_DPF(PVR_DBG_MESSAGE,
840                                  "PVRSRVSaveRestoreLiveSegments: "
841                                  "Base %08x size %08x",
842                                  sSegDetails.sCpuPhyAddr.uiAddr,
843                                  sSegDetails.uiSize);
844
845                         pvLocalMemCPUVAddr = (void __force *)
846                             OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
847                                            sSegDetails.uiSize,
848                                            PVRSRV_HAP_KERNEL_ONLY |
849                                            PVRSRV_HAP_UNCACHED, NULL);
850                         if (pvLocalMemCPUVAddr == NULL) {
851                                 PVR_DPF(PVR_DBG_ERROR,
852                                          "PVRSRVSaveRestoreLiveSegments: "
853                                          "Failed to map local memory to host");
854                                 return PVRSRV_ERROR_OUT_OF_MEMORY;
855                         }
856
857                         if (bSave) {
858                                 OSMemCopy(pbyBuffer, &sSegDetails.uiSize,
859                                           sizeof(sSegDetails.uiSize));
860                                 pbyBuffer += sizeof(sSegDetails.uiSize);
861
862                                 OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr,
863                                           sSegDetails.uiSize);
864                                 pbyBuffer += sSegDetails.uiSize;
865                         } else {
866                                 u32 uiSize;
867
868                                 OSMemCopy(&uiSize, pbyBuffer,
869                                           sizeof(sSegDetails.uiSize));
870
871                                 if (uiSize != sSegDetails.uiSize) {
872                                         PVR_DPF(PVR_DBG_ERROR,
873                                                 "PVRSRVSaveRestoreLiveSegments:"
874                                                 " Segment size error");
875                                 } else {
876                                         pbyBuffer += sizeof(sSegDetails.uiSize);
877
878                                         OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer,
879                                                   sSegDetails.uiSize);
880                                         pbyBuffer += sSegDetails.uiSize;
881                                 }
882                         }
883
884                         uiBytesSaved +=
885                             sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
886
887                         OSUnMapPhysToLin((void __force __iomem *)
888                                                         pvLocalMemCPUVAddr,
889                                          sSegDetails.uiSize,
890                                          PVRSRV_HAP_KERNEL_ONLY |
891                                          PVRSRV_HAP_UNCACHED, NULL);
892                 }
893
894         if (pbyBuffer == NULL)
895                 *puiBufSize = uiBytesSaved;
896
897         return PVRSRV_OK;
898 }