gpu: pvr: get rid of unnecessary hash lookups for the proc object
[sgx.git] / pvr / deviceclass.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 #include <linux/module.h>
27
28 #include "services_headers.h"
29 #include "buffer_manager.h"
30 #include "kernelbuffer.h"
31 #include "pvr_bridge_km.h"
32
33 struct PVRSRV_DC_SRV2DISP_KMJTABLE;
34
35 struct PVRSRV_DC_BUFFER {
36         struct PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
37         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
38         struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
39 };
40
41 struct PVRSRV_DC_SWAPCHAIN {
42         void *hExtSwapChain;
43         struct PVRSRV_QUEUE_INFO *psQueue;
44         struct PVRSRV_DC_BUFFER asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
45         u32 ui32BufferCount;
46         struct PVRSRV_DC_BUFFER *psLastFlipBuffer;
47         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
48         void *hResItem;
49 };
50
51 struct PVRSRV_DISPLAYCLASS_INFO {
52         u32 ui32RefCount;
53         u32 ui32DeviceID;
54         void *hExtDevice;
55         struct PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable;
56         void *hDevMemContext;
57         struct PVRSRV_DC_BUFFER sSystemBuffer;
58 };
59
60 struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO {
61         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
62         struct RESMAN_ITEM *hResItem;
63 };
64
65 struct PVRSRV_BC_SRV2BUFFER_KMJTABLE;
66
67 struct PVRSRV_BC_BUFFER {
68         struct PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
69         struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
70 };
71
72 struct PVRSRV_BUFFERCLASS_INFO {
73         u32 ui32RefCount;
74         u32 ui32DeviceID;
75         void *hExtDevice;
76         struct PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable;
77         void *hDevMemContext;
78
79         u32 ui32BufferCount;
80         struct PVRSRV_BC_BUFFER *psBuffer;
81
82 };
83
84 struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO {
85         struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
86         void *hResItem;
87 };
88
89 static struct PVRSRV_DISPLAYCLASS_INFO *DCDeviceHandleToDCInfo(void *hDeviceKM)
90 {
91         struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
92
93         psDCPerContextInfo = (struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)
94                                 hDeviceKM;
95
96         return psDCPerContextInfo->psDCInfo;
97 }
98
99 static struct PVRSRV_BUFFERCLASS_INFO *BCDeviceHandleToBCInfo(void *hDeviceKM)
100 {
101         struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
102
103         psBCPerContextInfo = (struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)
104                                 hDeviceKM;
105
106         return psBCPerContextInfo->psBCInfo;
107 }
108
109 enum PVRSRV_ERROR PVRSRVEnumerateDCKM(enum PVRSRV_DEVICE_CLASS DeviceClass,
110                                      u32 *pui32DevCount, u32 *pui32DevID)
111 {
112         struct PVRSRV_DEVICE_NODE *psDeviceNode;
113         unsigned ui32DevCount = 0;
114         struct SYS_DATA *psSysData;
115
116         if (SysAcquireData(&psSysData) != PVRSRV_OK) {
117                 PVR_DPF(PVR_DBG_ERROR,
118                          "PVRSRVEnumerateDCKM: Failed to get SysData");
119                 return PVRSRV_ERROR_GENERIC;
120         }
121
122         psDeviceNode = psSysData->psDeviceNodeList;
123         while (psDeviceNode) {
124                 if ((psDeviceNode->sDevId.eDeviceClass == DeviceClass) &&
125                     (psDeviceNode->sDevId.eDeviceType ==
126                         PVRSRV_DEVICE_TYPE_EXT)) {
127                         ui32DevCount++;
128                         if (pui32DevID) {
129                                 *pui32DevID++ =
130                                     psDeviceNode->sDevId.ui32DeviceIndex;
131                         }
132                 }
133                 psDeviceNode = psDeviceNode->psNext;
134         }
135
136         if (pui32DevCount) {
137                 *pui32DevCount = ui32DevCount;
138         } else if (pui32DevID == NULL) {
139                 PVR_DPF(PVR_DBG_ERROR,
140                          "PVRSRVEnumerateDCKM: Invalid parameters");
141                 return PVRSRV_ERROR_INVALID_PARAMS;
142         }
143
144         return PVRSRV_OK;
145 }
146
147 static enum PVRSRV_ERROR PVRSRVRegisterDCDeviceKM(
148                         struct PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
149                         u32 *pui32DeviceID)
150 {
151         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo = NULL;
152         struct PVRSRV_DEVICE_NODE *psDeviceNode;
153         struct SYS_DATA *psSysData;
154
155         if (SysAcquireData(&psSysData) != PVRSRV_OK) {
156                 PVR_DPF(PVR_DBG_ERROR,
157                          "PVRSRVRegisterDCDeviceKM: Failed to get SysData");
158                 return PVRSRV_ERROR_GENERIC;
159         }
160
161         if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
162                        sizeof(*psDCInfo),
163                        (void **) &psDCInfo, NULL) != PVRSRV_OK) {
164                 PVR_DPF(PVR_DBG_ERROR,
165                          "PVRSRVRegisterDCDeviceKM: Failed psDCInfo alloc");
166                 return PVRSRV_ERROR_OUT_OF_MEMORY;
167         }
168         OSMemSet(psDCInfo, 0, sizeof(*psDCInfo));
169
170         if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
171                        sizeof(struct PVRSRV_DC_SRV2DISP_KMJTABLE),
172                        (void **)&psDCInfo->psFuncTable,
173                        NULL) != PVRSRV_OK) {
174                 PVR_DPF(PVR_DBG_ERROR,
175                          "PVRSRVRegisterDCDeviceKM: Failed psFuncTable alloc");
176                 goto ErrorExit;
177         }
178         OSMemSet(psDCInfo->psFuncTable, 0,
179                  sizeof(struct PVRSRV_DC_SRV2DISP_KMJTABLE));
180
181         *psDCInfo->psFuncTable = *psFuncTable;
182
183         if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
184                        sizeof(struct PVRSRV_DEVICE_NODE),
185                        (void **) &psDeviceNode, NULL) != PVRSRV_OK) {
186                 PVR_DPF(PVR_DBG_ERROR,
187                         "PVRSRVRegisterDCDeviceKM: Failed psDeviceNode alloc");
188                 goto ErrorExit;
189         }
190         OSMemSet(psDeviceNode, 0, sizeof(struct PVRSRV_DEVICE_NODE));
191
192         psDeviceNode->pvDevice = (void *) psDCInfo;
193         psDeviceNode->ui32pvDeviceSize = sizeof(*psDCInfo);
194         psDeviceNode->ui32RefCount = 1;
195         psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
196         psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY;
197         psDeviceNode->psSysData = psSysData;
198
199         AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
200         psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
201         if (pui32DeviceID)
202                 *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
203
204         SysRegisterExternalDevice(psDeviceNode);
205
206         psDeviceNode->psNext = psSysData->psDeviceNodeList;
207         psSysData->psDeviceNodeList = psDeviceNode;
208
209         return PVRSRV_OK;
210
211 ErrorExit:
212
213         if (psDCInfo->psFuncTable)
214                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
215                           sizeof(struct PVRSRV_DC_SRV2DISP_KMJTABLE),
216                           psDCInfo->psFuncTable, NULL);
217
218         OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
219                   sizeof(struct PVRSRV_DISPLAYCLASS_INFO),
220                   psDCInfo, NULL);
221
222         return PVRSRV_ERROR_OUT_OF_MEMORY;
223 }
224
225 static enum PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(u32 ui32DevIndex)
226 {
227         struct SYS_DATA *psSysData;
228         struct PVRSRV_DEVICE_NODE **ppsDeviceNode, *psDeviceNode;
229         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
230
231         if (SysAcquireData(&psSysData) != PVRSRV_OK) {
232                 PVR_DPF(PVR_DBG_ERROR,
233                          "PVRSRVRemoveDCDeviceKM: Failed to get SysData");
234                 return PVRSRV_ERROR_GENERIC;
235         }
236
237         ppsDeviceNode = &psSysData->psDeviceNodeList;
238         while (*ppsDeviceNode) {
239                 switch ((*ppsDeviceNode)->sDevId.eDeviceClass) {
240                 case PVRSRV_DEVICE_CLASS_DISPLAY:
241                         {
242                                 if ((*ppsDeviceNode)->sDevId.ui32DeviceIndex ==
243                                     ui32DevIndex)
244                                         goto FoundDevice;
245                                 break;
246                         }
247                 default:
248                         {
249                                 break;
250                         }
251                 }
252                 ppsDeviceNode = &((*ppsDeviceNode)->psNext);
253         }
254
255         PVR_DPF(PVR_DBG_ERROR,
256                  "PVRSRVRemoveDCDeviceKM: requested device %d not present",
257                  ui32DevIndex);
258
259         return PVRSRV_ERROR_GENERIC;
260
261 FoundDevice:
262
263         psDeviceNode = *ppsDeviceNode;
264
265         psDCInfo = (struct PVRSRV_DISPLAYCLASS_INFO *)psDeviceNode->pvDevice;
266
267         if (psDCInfo->ui32RefCount == 0) {
268                 *ppsDeviceNode = psDeviceNode->psNext;
269                 SysRemoveExternalDevice(psDeviceNode);
270                 PVR_ASSERT(psDCInfo->ui32RefCount == 0);
271                 FreeDeviceID(psSysData, ui32DevIndex);
272                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
273                           sizeof(struct PVRSRV_DC_SRV2DISP_KMJTABLE),
274                           psDCInfo->psFuncTable, NULL);
275                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
276                           sizeof(struct PVRSRV_DISPLAYCLASS_INFO), psDCInfo,
277                           NULL);
278                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
279                           sizeof(struct PVRSRV_DEVICE_NODE), psDeviceNode,
280                           NULL);
281         } else {
282                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVRemoveDCDeviceKM: "
283                                 "failed as %d Services DC API "
284                                 "connections are still open",
285                          psDCInfo->ui32RefCount);
286                 return PVRSRV_ERROR_GENERIC;
287         }
288
289         return PVRSRV_OK;
290 }
291
292 static enum PVRSRV_ERROR PVRSRVRegisterBCDeviceKM(
293                 struct PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable,
294                 u32 *pui32DeviceID)
295 {
296         struct PVRSRV_BUFFERCLASS_INFO *psBCInfo = NULL;
297         struct PVRSRV_DEVICE_NODE *psDeviceNode;
298         struct SYS_DATA *psSysData;
299
300         if (SysAcquireData(&psSysData) != PVRSRV_OK) {
301                 PVR_DPF(PVR_DBG_ERROR,
302                          "PVRSRVRegisterBCDeviceKM: Failed to get SysData");
303                 return PVRSRV_ERROR_GENERIC;
304         }
305
306         if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
307                        sizeof(*psBCInfo),
308                        (void **) &psBCInfo, NULL) != PVRSRV_OK) {
309                 PVR_DPF(PVR_DBG_ERROR,
310                          "PVRSRVRegisterBCDeviceKM: Failed psBCInfo alloc");
311                 return PVRSRV_ERROR_OUT_OF_MEMORY;
312         }
313         OSMemSet(psBCInfo, 0, sizeof(*psBCInfo));
314
315         if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
316                        sizeof(struct PVRSRV_BC_SRV2BUFFER_KMJTABLE),
317                        (void **) &psBCInfo->psFuncTable,
318                        NULL) != PVRSRV_OK) {
319                 PVR_DPF(PVR_DBG_ERROR,
320                          "PVRSRVRegisterBCDeviceKM: Failed psFuncTable alloc");
321                 goto ErrorExit;
322         }
323         OSMemSet(psBCInfo->psFuncTable, 0,
324                  sizeof(struct PVRSRV_BC_SRV2BUFFER_KMJTABLE));
325
326         *psBCInfo->psFuncTable = *psFuncTable;
327
328         if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
329                        sizeof(struct PVRSRV_DEVICE_NODE),
330                        (void **) &psDeviceNode, NULL) != PVRSRV_OK) {
331                 PVR_DPF(PVR_DBG_ERROR,
332                         "PVRSRVRegisterBCDeviceKM: Failed psDeviceNode alloc");
333                 goto ErrorExit;
334         }
335         OSMemSet(psDeviceNode, 0, sizeof(struct PVRSRV_DEVICE_NODE));
336
337         psDeviceNode->pvDevice = (void *) psBCInfo;
338         psDeviceNode->ui32pvDeviceSize = sizeof(*psBCInfo);
339         psDeviceNode->ui32RefCount = 1;
340         psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
341         psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER;
342         psDeviceNode->psSysData = psSysData;
343
344         AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
345         psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
346         if (pui32DeviceID)
347                 *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
348
349         psDeviceNode->psNext = psSysData->psDeviceNodeList;
350         psSysData->psDeviceNodeList = psDeviceNode;
351
352         return PVRSRV_OK;
353
354 ErrorExit:
355
356         if (psBCInfo->psFuncTable)
357                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
358                           sizeof(*psBCInfo->psFuncTable), psBCInfo->psFuncTable,
359                           NULL);
360
361         OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psBCInfo), psBCInfo, NULL);
362
363         return PVRSRV_ERROR_OUT_OF_MEMORY;
364 }
365
366 static enum PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(u32 ui32DevIndex)
367 {
368         struct SYS_DATA *psSysData;
369         struct PVRSRV_DEVICE_NODE **ppsDevNode, *psDevNode;
370         struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
371
372         if (SysAcquireData(&psSysData) != PVRSRV_OK) {
373                 PVR_DPF(PVR_DBG_ERROR,
374                          "PVRSRVRemoveBCDeviceKM: Failed to get SysData");
375                 return PVRSRV_ERROR_GENERIC;
376         }
377
378         ppsDevNode = &psSysData->psDeviceNodeList;
379         while (*ppsDevNode) {
380                 switch ((*ppsDevNode)->sDevId.eDeviceClass) {
381                 case PVRSRV_DEVICE_CLASS_BUFFER:
382                         {
383                                 if ((*ppsDevNode)->sDevId.ui32DeviceIndex ==
384                                     ui32DevIndex)
385                                         goto FoundDevice;
386                                 break;
387                         }
388                 default:
389                         {
390                                 break;
391                         }
392                 }
393                 ppsDevNode = &(*ppsDevNode)->psNext;
394         }
395
396         PVR_DPF(PVR_DBG_ERROR,
397                  "PVRSRVRemoveBCDeviceKM: requested device %d not present",
398                  ui32DevIndex);
399
400         return PVRSRV_ERROR_GENERIC;
401
402 FoundDevice:
403
404         psDevNode = *(ppsDevNode);
405
406         psBCInfo = (struct PVRSRV_BUFFERCLASS_INFO *)psDevNode->pvDevice;
407
408         if (psBCInfo->ui32RefCount == 0) {
409                 *ppsDevNode = psDevNode->psNext;
410                 FreeDeviceID(psSysData, ui32DevIndex);
411                 psBCInfo =
412                     (struct PVRSRV_BUFFERCLASS_INFO *)psDevNode->pvDevice;
413                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
414                           sizeof(struct PVRSRV_BC_SRV2BUFFER_KMJTABLE),
415                           psBCInfo->psFuncTable, NULL);
416                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
417                           sizeof(struct PVRSRV_BUFFERCLASS_INFO), psBCInfo,
418                           NULL);
419                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
420                           sizeof(struct PVRSRV_DEVICE_NODE), psDevNode, NULL);
421         } else {
422                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVRemoveBCDeviceKM: "
423                                 "failed as %d Services BC API "
424                                 "connections are still open",
425                          psBCInfo->ui32RefCount);
426                 return PVRSRV_ERROR_GENERIC;
427         }
428
429         return PVRSRV_OK;
430 }
431
432 enum PVRSRV_ERROR PVRSRVCloseDCDeviceKM(void *hDeviceKM,
433                                        IMG_BOOL bResManCallback)
434 {
435         struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
436
437         PVR_UNREFERENCED_PARAMETER(bResManCallback);
438
439         psDCPerContextInfo = (struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)
440                                                                 hDeviceKM;
441
442         ResManFreeResByPtr(psDCPerContextInfo->hResItem);
443
444         return PVRSRV_OK;
445 }
446
447 static enum PVRSRV_ERROR CloseDCDeviceCallBack(void *pvParam, u32 ui32Param)
448 {
449         struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
450         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
451
452         PVR_UNREFERENCED_PARAMETER(ui32Param);
453
454         psDCPerContextInfo = (struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)
455                                                                         pvParam;
456         psDCInfo = psDCPerContextInfo->psDCInfo;
457
458         psDCInfo->ui32RefCount--;
459         if (psDCInfo->ui32RefCount == 0) {
460                 struct PVRSRV_DC_SRV2DISP_KMJTABLE *jtbl;
461
462                 jtbl = psDCInfo->psFuncTable;
463
464                 jtbl->pfnCloseDCDevice(psDCInfo->hExtDevice);
465
466                 PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.
467                                      psKernelSyncInfo);
468
469                 psDCInfo->hDevMemContext = NULL;
470                 psDCInfo->hExtDevice = NULL;
471
472                 module_put(jtbl->owner);
473         }
474
475         OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
476                   sizeof(struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO),
477                   psDCPerContextInfo, NULL);
478
479         return PVRSRV_OK;
480 }
481
482 enum PVRSRV_ERROR PVRSRVOpenDCDeviceKM(
483                                 struct PVRSRV_PER_PROCESS_DATA *psPerProc,
484                                 u32 ui32DeviceID, void *hDevCookie,
485                                 void **phDeviceKM)
486 {
487         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
488         struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
489         struct PVRSRV_DC_SRV2DISP_KMJTABLE *jtbl;
490         struct PVRSRV_DEVICE_NODE *psDeviceNode;
491         struct SYS_DATA *psSysData;
492         enum PVRSRV_ERROR eError;
493
494         if (!phDeviceKM || !hDevCookie) {
495                 PVR_DPF(PVR_DBG_ERROR,
496                          "PVRSRVOpenDCDeviceKM: Invalid params");
497                 return PVRSRV_ERROR_GENERIC;
498         }
499
500         if (SysAcquireData(&psSysData) != PVRSRV_OK) {
501                 PVR_DPF(PVR_DBG_ERROR,
502                          "PVRSRVOpenDCDeviceKM: Failed to get SysData");
503                 return PVRSRV_ERROR_GENERIC;
504         }
505
506         psDeviceNode = psSysData->psDeviceNodeList;
507         while (psDeviceNode) {
508                 if ((psDeviceNode->sDevId.eDeviceClass ==
509                      PVRSRV_DEVICE_CLASS_DISPLAY) &&
510                      (psDeviceNode->sDevId.ui32DeviceIndex == ui32DeviceID)) {
511
512                         psDCInfo = (struct PVRSRV_DISPLAYCLASS_INFO *)
513                                                         psDeviceNode->pvDevice;
514                         goto FoundDevice;
515                 }
516                 psDeviceNode = psDeviceNode->psNext;
517         }
518
519         PVR_DPF(PVR_DBG_ERROR,
520                  "PVRSRVOpenDCDeviceKM: no devnode matching index %d",
521                  ui32DeviceID);
522
523         return PVRSRV_ERROR_GENERIC;
524
525 FoundDevice:
526
527         if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psDCPerContextInfo),
528                        (void **)&psDCPerContextInfo, NULL) != PVRSRV_OK) {
529                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: "
530                                         "Failed psDCPerContextInfo alloc");
531                 return PVRSRV_ERROR_OUT_OF_MEMORY;
532         }
533         OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo));
534
535         if (psDCInfo->ui32RefCount++ == 0) {
536                 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie;
537
538                 jtbl = psDCInfo->psFuncTable;
539                 if (!try_module_get(jtbl->owner)) {
540                         PVR_DPF(PVR_DBG_ERROR, "%s: can't get DC module");
541                         eError = PVRSRV_ERROR_INVALID_DEVICE;
542
543                         goto err1;
544                 }
545
546                 psDCInfo->hDevMemContext =
547                     (void *) psDeviceNode->sDevMemoryInfo.pBMKernelContext;
548
549                 eError = PVRSRVAllocSyncInfoKM(NULL,
550                                        (void *)psDeviceNode->
551                                                sDevMemoryInfo.pBMKernelContext,
552                                        &psDCInfo->sSystemBuffer.
553                                                sDeviceClassBuffer.
554                                                        psKernelSyncInfo);
555                 if (eError != PVRSRV_OK) {
556                         PVR_DPF(PVR_DBG_ERROR,
557                                "PVRSRVOpenDCDeviceKM: Failed sync info alloc");
558
559                         goto err2;
560                 }
561
562                 eError = jtbl->pfnOpenDCDevice(ui32DeviceID,
563                         &psDCInfo->hExtDevice,
564                         (struct PVRSRV_SYNC_DATA *)psDCInfo->sSystemBuffer.
565                                 sDeviceClassBuffer.psKernelSyncInfo->
566                                         psSyncDataMemInfoKM->pvLinAddrKM);
567                 if (eError != PVRSRV_OK) {
568                         PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: "
569                                         "Failed to open external DC device");
570                         goto err3;
571                 }
572         }
573
574         psDCPerContextInfo->psDCInfo = psDCInfo;
575         psDCPerContextInfo->hResItem =
576             ResManRegisterRes(psPerProc->hResManContext,
577                               RESMAN_TYPE_DISPLAYCLASS_DEVICE,
578                               psDCPerContextInfo, 0, CloseDCDeviceCallBack);
579
580         *phDeviceKM = (void *) psDCPerContextInfo;
581
582         return PVRSRV_OK;
583 err3:
584         PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.
585                              sDeviceClassBuffer.psKernelSyncInfo);
586 err2:
587         module_put(jtbl->owner);
588         psDCInfo->ui32RefCount--;
589 err1:
590         OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psDCPerContextInfo),
591                   psDCPerContextInfo, NULL);
592
593         return eError;
594 }
595
596 enum PVRSRV_ERROR PVRSRVEnumDCFormatsKM(void *hDeviceKM,
597                                        u32 *pui32Count,
598                                        struct DISPLAY_FORMAT *psFormat)
599 {
600         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
601
602         if (!hDeviceKM || !pui32Count || !psFormat) {
603                 PVR_DPF(PVR_DBG_ERROR,
604                          "PVRSRVEnumDCFormatsKM: Invalid parameters");
605                 return PVRSRV_ERROR_INVALID_PARAMS;
606         }
607
608         psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
609
610         return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice,
611                                                        pui32Count, psFormat);
612 }
613
614 enum PVRSRV_ERROR PVRSRVEnumDCDimsKM(void *hDeviceKM,
615                                     struct DISPLAY_FORMAT *psFormat,
616                                     u32 *pui32Count, struct DISPLAY_DIMS *psDim)
617 {
618         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
619
620         if (!hDeviceKM || !pui32Count || !psFormat) {
621                 PVR_DPF(PVR_DBG_ERROR,
622                          "PVRSRVEnumDCDimsKM: Invalid parameters");
623                 return PVRSRV_ERROR_INVALID_PARAMS;
624         }
625
626         psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
627
628         return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice,
629                                                   psFormat, pui32Count, psDim);
630 }
631
632 enum PVRSRV_ERROR PVRSRVGetDCSystemBufferKM(void *hDeviceKM, void **phBuffer)
633 {
634         enum PVRSRV_ERROR eError;
635         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
636         void *hExtBuffer;
637
638         if (!hDeviceKM || !phBuffer) {
639                 PVR_DPF(PVR_DBG_ERROR,
640                          "PVRSRVGetDCSystemBufferKM: Invalid parameters");
641                 return PVRSRV_ERROR_INVALID_PARAMS;
642         }
643
644         psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
645
646         eError =
647             psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice,
648                                                         &hExtBuffer);
649         if (eError != PVRSRV_OK) {
650                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVGetDCSystemBufferKM: "
651                      "Failed to get valid buffer handle from external driver");
652                 return eError;
653         }
654
655         psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr =
656             psDCInfo->psFuncTable->pfnGetBufferAddr;
657         psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext =
658             psDCInfo->hDevMemContext;
659         psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice =
660             psDCInfo->hExtDevice;
661         psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer = hExtBuffer;
662
663         psDCInfo->sSystemBuffer.psDCInfo = psDCInfo;
664
665         *phBuffer = (void *) &(psDCInfo->sSystemBuffer);
666
667         return PVRSRV_OK;
668 }
669
670 enum PVRSRV_ERROR PVRSRVGetDCInfoKM(void *hDeviceKM,
671                                 struct DISPLAY_INFO *psDisplayInfo)
672 {
673         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
674         enum PVRSRV_ERROR eError;
675
676         if (!hDeviceKM || !psDisplayInfo) {
677                 PVR_DPF(PVR_DBG_ERROR,
678                          "PVRSRVGetDCInfoKM: Invalid parameters");
679                 return PVRSRV_ERROR_INVALID_PARAMS;
680         }
681
682         psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
683
684         eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice,
685                                                         psDisplayInfo);
686         if (eError != PVRSRV_OK)
687                 return eError;
688
689         if (psDisplayInfo->ui32MaxSwapChainBuffers >
690             PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS) {
691                 psDisplayInfo->ui32MaxSwapChainBuffers =
692                     PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS;
693         }
694
695         return PVRSRV_OK;
696 }
697
698 enum PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(void *hSwapChain)
699 {
700         struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
701
702         if (!hSwapChain) {
703                 PVR_DPF(PVR_DBG_ERROR,
704                          "PVRSRVDestroyDCSwapChainKM: Invalid parameters");
705                 return PVRSRV_ERROR_INVALID_PARAMS;
706         }
707
708         psSwapChain = hSwapChain;
709
710         ResManFreeResByPtr(psSwapChain->hResItem);
711
712         return PVRSRV_OK;
713 }
714
715 static enum PVRSRV_ERROR DestroyDCSwapChainCallBack(void *pvParam,
716                                                u32 ui32Param)
717 {
718         enum PVRSRV_ERROR eError;
719         struct PVRSRV_DC_SWAPCHAIN *psSwapChain = pvParam;
720         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo = psSwapChain->psDCInfo;
721         u32 i;
722
723         PVR_UNREFERENCED_PARAMETER(ui32Param);
724
725         PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue);
726
727         eError =
728             psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice,
729                                                          psSwapChain->
730                                                                  hExtSwapChain);
731
732         if (eError != PVRSRV_OK) {
733                 PVR_DPF(PVR_DBG_ERROR, "DestroyDCSwapChainCallBack: "
734                                         "Failed to destroy DC swap chain");
735                 return eError;
736         }
737
738         for (i = 0; i < psSwapChain->ui32BufferCount; i++)
739                 if (psSwapChain->asBuffer[i].sDeviceClassBuffer.
740                     psKernelSyncInfo)
741                         PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].
742                                                      sDeviceClassBuffer.
743                                                              psKernelSyncInfo);
744
745         OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_DC_SWAPCHAIN),
746                   psSwapChain, NULL);
747
748         return eError;
749 }
750
751 enum PVRSRV_ERROR PVRSRVCreateDCSwapChainKM(
752                                 struct PVRSRV_PER_PROCESS_DATA *psPerProc,
753                                 void *hDeviceKM, u32 ui32Flags,
754                                 struct DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
755                                 struct DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
756                                 u32 ui32BufferCount, u32 ui32OEMFlags,
757                                 void **phSwapChain, u32 *pui32SwapChainID)
758 {
759         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
760         struct PVRSRV_DC_SWAPCHAIN *psSwapChain = NULL;
761         struct PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
762         struct PVRSRV_QUEUE_INFO *psQueue = NULL;
763         enum PVRSRV_ERROR eError;
764         u32 i;
765
766         if (!hDeviceKM || !psDstSurfAttrib || !psSrcSurfAttrib ||
767             !phSwapChain || !pui32SwapChainID) {
768                 PVR_DPF(PVR_DBG_ERROR,
769                          "PVRSRVCreateDCSwapChainKM: Invalid parameters");
770                 return PVRSRV_ERROR_INVALID_PARAMS;
771         }
772
773         if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS) {
774                 PVR_DPF(PVR_DBG_ERROR,
775                          "PVRSRVCreateDCSwapChainKM: Too many buffers");
776                 return PVRSRV_ERROR_TOOMANYBUFFERS;
777         }
778
779         if (ui32BufferCount < 2) {
780                 PVR_DPF(PVR_DBG_ERROR,
781                          "PVRSRVCreateDCSwapChainKM: Too few buffers");
782                 return PVRSRV_ERROR_TOO_FEW_BUFFERS;
783         }
784
785         psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
786
787         if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
788                        sizeof(struct PVRSRV_DC_SWAPCHAIN),
789                        (void **) &psSwapChain, NULL) != PVRSRV_OK) {
790                 PVR_DPF(PVR_DBG_ERROR,
791                          "PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc");
792                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
793                 goto ErrorExit;
794         }
795         OSMemSet(psSwapChain, 0, sizeof(struct PVRSRV_DC_SWAPCHAIN));
796
797         eError = PVRSRVCreateCommandQueueKM(1024, &psQueue);
798         if (eError != PVRSRV_OK) {
799                 PVR_DPF(PVR_DBG_ERROR,
800                         "PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue");
801                 goto ErrorExit;
802         }
803
804         psSwapChain->psQueue = psQueue;
805
806         for (i = 0; i < ui32BufferCount; i++) {
807                 eError = PVRSRVAllocSyncInfoKM(NULL,
808                                                psDCInfo->hDevMemContext,
809                                                &psSwapChain->asBuffer[i].
810                                                        sDeviceClassBuffer.
811                                                               psKernelSyncInfo);
812                 if (eError != PVRSRV_OK) {
813                         PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: "
814                                 "Failed to alloc syninfo for psSwapChain");
815                         goto ErrorExit;
816                 }
817
818                 psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr =
819                     psDCInfo->psFuncTable->pfnGetBufferAddr;
820                 psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext =
821                     psDCInfo->hDevMemContext;
822                 psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice =
823                     psDCInfo->hExtDevice;
824
825                 psSwapChain->asBuffer[i].psDCInfo = psDCInfo;
826                 psSwapChain->asBuffer[i].psSwapChain = psSwapChain;
827
828                 apsSyncData[i] =
829                     (struct PVRSRV_SYNC_DATA *)psSwapChain->asBuffer[i].
830                             sDeviceClassBuffer.psKernelSyncInfo->
831                                         psSyncDataMemInfoKM->pvLinAddrKM;
832         }
833
834         psSwapChain->ui32BufferCount = ui32BufferCount;
835         psSwapChain->psDCInfo = psDCInfo;
836
837         eError =
838             psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
839                                                 ui32Flags,
840                                                 psDstSurfAttrib,
841                                                 psSrcSurfAttrib,
842                                                 ui32BufferCount,
843                                                 apsSyncData,
844                                                 ui32OEMFlags,
845                                                 &psSwapChain->hExtSwapChain,
846                                                 pui32SwapChainID);
847         if (eError != PVRSRV_OK) {
848                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: "
849                                 "Failed to create 3rd party SwapChain");
850                 goto ErrorExit;
851         }
852
853         *phSwapChain = (void *) psSwapChain;
854
855         psSwapChain->hResItem = ResManRegisterRes(psPerProc->hResManContext,
856                                           RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN,
857                                           psSwapChain, 0,
858                                           DestroyDCSwapChainCallBack);
859
860         return eError;
861
862 ErrorExit:
863
864         for (i = 0; i < ui32BufferCount; i++) {
865                 if (psSwapChain->asBuffer[i].sDeviceClassBuffer.
866                     psKernelSyncInfo) {
867                         PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].
868                                                      sDeviceClassBuffer.
869                                                              psKernelSyncInfo);
870                 }
871         }
872
873         if (psQueue)
874                 PVRSRVDestroyCommandQueueKM(psQueue);
875
876         if (psSwapChain) {
877                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
878                           sizeof(struct PVRSRV_DC_SWAPCHAIN), psSwapChain,
879                           NULL);
880         }
881
882         return eError;
883 }
884
885 enum PVRSRV_ERROR PVRSRVSetDCDstRectKM(void *hDeviceKM, void *hSwapChain,
886                                        struct IMG_RECT *psRect)
887 {
888         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
889         struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
890
891         if (!hDeviceKM || !hSwapChain) {
892                 PVR_DPF(PVR_DBG_ERROR,
893                          "PVRSRVSetDCDstRectKM: Invalid parameters");
894                 return PVRSRV_ERROR_INVALID_PARAMS;
895         }
896
897         psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
898         psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain;
899
900         return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice,
901                                         psSwapChain->hExtSwapChain, psRect);
902 }
903
904 enum PVRSRV_ERROR PVRSRVSetDCSrcRectKM(void *hDeviceKM, void *hSwapChain,
905                                        struct IMG_RECT *psRect)
906 {
907         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
908         struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
909
910         if (!hDeviceKM || !hSwapChain) {
911                 PVR_DPF(PVR_DBG_ERROR,
912                          "PVRSRVSetDCSrcRectKM: Invalid parameters");
913                 return PVRSRV_ERROR_INVALID_PARAMS;
914         }
915
916         psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
917         psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain;
918
919         return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice,
920                                         psSwapChain->hExtSwapChain, psRect);
921 }
922
923 enum PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(void *hDeviceKM, void *hSwapChain,
924                                        u32 ui32CKColour)
925 {
926         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
927         struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
928
929         if (!hDeviceKM || !hSwapChain) {
930                 PVR_DPF(PVR_DBG_ERROR,
931                          "PVRSRVSetDCDstColourKeyKM: Invalid parameters");
932                 return PVRSRV_ERROR_INVALID_PARAMS;
933         }
934
935         psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
936         psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain;
937
938         return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice,
939                                      psSwapChain->hExtSwapChain, ui32CKColour);
940 }
941
942 enum PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(void *hDeviceKM, void *hSwapChain,
943                                            u32 ui32CKColour)
944 {
945         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
946         struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
947
948         if (!hDeviceKM || !hSwapChain) {
949                 PVR_DPF(PVR_DBG_ERROR,
950                          "PVRSRVSetDCSrcColourKeyKM: Invalid parameters");
951                 return PVRSRV_ERROR_INVALID_PARAMS;
952         }
953
954         psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
955         psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain;
956
957         return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice,
958                                      psSwapChain->hExtSwapChain, ui32CKColour);
959 }
960
961 enum PVRSRV_ERROR PVRSRVGetDCBuffersKM(void *hDeviceKM, void *hSwapChain,
962                                       u32 *pui32BufferCount, void **phBuffer)
963 {
964         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
965         struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
966         void *ahExtBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
967         enum PVRSRV_ERROR eError;
968         u32 i;
969
970         if (!hDeviceKM || !hSwapChain || !phBuffer) {
971                 PVR_DPF(PVR_DBG_ERROR,
972                          "PVRSRVGetDCBuffersKM: Invalid parameters");
973                 return PVRSRV_ERROR_INVALID_PARAMS;
974         }
975
976         psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
977         psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain;
978
979         eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice,
980                                                 psSwapChain->hExtSwapChain,
981                                                 pui32BufferCount, ahExtBuffer);
982
983         PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
984
985         for (i = 0; i < *pui32BufferCount; i++) {
986                 psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer =
987                                                                 ahExtBuffer[i];
988                 phBuffer[i] = (void *)&psSwapChain->asBuffer[i];
989         }
990
991         return eError;
992 }
993
994 enum PVRSRV_ERROR PVRSRVSwapToDCBufferKM(void *hDeviceKM, void *hBuffer,
995                                         u32 ui32SwapInterval, void *hPrivateTag,
996                                         u32 ui32ClipRectCount,
997                                         struct IMG_RECT *psClipRect)
998 {
999         enum PVRSRV_ERROR eError;
1000         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1001         struct PVRSRV_DC_BUFFER *psBuffer;
1002         struct PVRSRV_QUEUE_INFO *psQueue;
1003         struct DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
1004         u32 i;
1005         u32 ui32NumSrcSyncs = 1;
1006         struct PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
1007         struct PVRSRV_COMMAND *psCommand;
1008
1009         if (!hDeviceKM || !hBuffer || !psClipRect) {
1010                 PVR_DPF(PVR_DBG_ERROR,
1011                          "PVRSRVSwapToDCBufferKM: Invalid parameters");
1012                 return PVRSRV_ERROR_INVALID_PARAMS;
1013         }
1014
1015         psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
1016         psBuffer = (struct PVRSRV_DC_BUFFER *)hBuffer;
1017
1018         psQueue = psBuffer->psSwapChain->psQueue;
1019
1020         apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo;
1021         if (psBuffer->psSwapChain->psLastFlipBuffer &&
1022             psBuffer != psBuffer->psSwapChain->psLastFlipBuffer) {
1023                 apsSrcSync[1] =
1024                     psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.
1025                     psKernelSyncInfo;
1026                 ui32NumSrcSyncs++;
1027         }
1028
1029         eError = PVRSRVInsertCommandKM(psQueue, &psCommand,
1030                                       psDCInfo->ui32DeviceID, DC_FLIP_COMMAND,
1031                                       0, NULL, ui32NumSrcSyncs, apsSrcSync,
1032                                       sizeof(struct DISPLAYCLASS_FLIP_COMMAND) +
1033                                       (sizeof(struct IMG_RECT) *
1034                                                            ui32ClipRectCount));
1035         if (eError != PVRSRV_OK) {
1036                 PVR_DPF(PVR_DBG_ERROR,
1037                         "PVRSRVSwapToDCBufferKM: Failed to get space in queue");
1038                 goto Exit;
1039         }
1040
1041         psFlipCmd = (struct DISPLAYCLASS_FLIP_COMMAND *)psCommand->pvData;
1042         psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
1043         psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain;
1044         psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer;
1045         psFlipCmd->hPrivateTag = hPrivateTag;
1046         psFlipCmd->ui32ClipRectCount = ui32ClipRectCount;
1047         psFlipCmd->psClipRect =
1048             (struct IMG_RECT *)((u8 *) psFlipCmd +
1049                           sizeof(struct DISPLAYCLASS_FLIP_COMMAND));
1050
1051         for (i = 0; i < ui32ClipRectCount; i++)
1052                 psFlipCmd->psClipRect[i] = psClipRect[i];
1053
1054         psFlipCmd->ui32SwapInterval = ui32SwapInterval;
1055
1056         eError = PVRSRVSubmitCommandKM(psQueue, psCommand);
1057         if (eError != PVRSRV_OK) {
1058                 PVR_DPF(PVR_DBG_ERROR,
1059                          "PVRSRVSwapToDCBufferKM: Failed to submit command");
1060                 goto Exit;
1061         }
1062
1063         LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
1064                 if (PVRSRVProcessQueues(IMG_FALSE) !=
1065                     PVRSRV_ERROR_PROCESSING_BLOCKED) {
1066                         goto ProcessedQueues;
1067                 }
1068                 OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
1069         }
1070         END_LOOP_UNTIL_TIMEOUT();
1071
1072         PVR_DPF(PVR_DBG_ERROR,
1073                  "PVRSRVSwapToDCBufferKM: Failed to process queues");
1074
1075         eError = PVRSRV_ERROR_GENERIC;
1076         goto Exit;
1077
1078 ProcessedQueues:
1079
1080         psBuffer->psSwapChain->psLastFlipBuffer = psBuffer;
1081
1082 Exit:
1083         return eError;
1084 }
1085
1086 enum PVRSRV_ERROR PVRSRVSwapToDCSystemKM(void *hDeviceKM, void *hSwapChain)
1087 {
1088         enum PVRSRV_ERROR eError;
1089         struct PVRSRV_QUEUE_INFO *psQueue;
1090         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1091         struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
1092         struct DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
1093         u32 ui32NumSrcSyncs = 1;
1094         struct PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
1095         struct PVRSRV_COMMAND *psCommand;
1096
1097         if (!hDeviceKM || !hSwapChain) {
1098                 PVR_DPF(PVR_DBG_ERROR,
1099                          "PVRSRVSwapToDCSystemKM: Invalid parameters");
1100                 return PVRSRV_ERROR_INVALID_PARAMS;
1101         }
1102
1103         psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
1104         psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain;
1105
1106         psQueue = psSwapChain->psQueue;
1107
1108         apsSrcSync[0] =
1109             psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo;
1110         if (psSwapChain->psLastFlipBuffer) {
1111                 if (apsSrcSync[0] !=
1112                     psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.
1113                             psKernelSyncInfo) {
1114                         apsSrcSync[1] =
1115                             psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.
1116                                             psKernelSyncInfo;
1117                         ui32NumSrcSyncs++;
1118                 }
1119         }
1120
1121         eError = PVRSRVInsertCommandKM(psQueue, &psCommand,
1122                                       psDCInfo->ui32DeviceID, DC_FLIP_COMMAND,
1123                                       0, NULL, ui32NumSrcSyncs, apsSrcSync,
1124                                       sizeof(struct DISPLAYCLASS_FLIP_COMMAND));
1125         if (eError != PVRSRV_OK) {
1126                 PVR_DPF(PVR_DBG_ERROR,
1127                         "PVRSRVSwapToDCSystemKM: Failed to get space in queue");
1128                 goto Exit;
1129         }
1130
1131         psFlipCmd = (struct DISPLAYCLASS_FLIP_COMMAND *)psCommand->pvData;
1132         psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
1133         psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
1134         psFlipCmd->hExtBuffer =
1135             psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer;
1136         psFlipCmd->hPrivateTag = NULL;
1137         psFlipCmd->ui32ClipRectCount = 0;
1138         psFlipCmd->ui32SwapInterval = 1;
1139
1140         eError = PVRSRVSubmitCommandKM(psQueue, psCommand);
1141         if (eError != PVRSRV_OK) {
1142                 PVR_DPF(PVR_DBG_ERROR,
1143                          "PVRSRVSwapToDCSystemKM: Failed to submit command");
1144                 goto Exit;
1145         }
1146
1147         LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
1148                 if (PVRSRVProcessQueues(IMG_FALSE) !=
1149                     PVRSRV_ERROR_PROCESSING_BLOCKED) {
1150                         goto ProcessedQueues;
1151                 }
1152                 OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
1153         }
1154         END_LOOP_UNTIL_TIMEOUT();
1155
1156         PVR_DPF(PVR_DBG_ERROR,
1157                  "PVRSRVSwapToDCSystemKM: Failed to process queues");
1158         eError = PVRSRV_ERROR_GENERIC;
1159         goto Exit;
1160
1161 ProcessedQueues:
1162
1163         psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer;
1164
1165         eError = PVRSRV_OK;
1166
1167 Exit:
1168         return eError;
1169 }
1170
1171 static enum PVRSRV_ERROR PVRSRVRegisterSystemISRHandler(
1172                                         IMG_BOOL (*pfnISRHandler)(void *),
1173                                         void *pvISRHandlerData,
1174                                         u32 ui32ISRSourceMask,
1175                                         u32 ui32DeviceID)
1176 {
1177         struct SYS_DATA *psSysData;
1178         struct PVRSRV_DEVICE_NODE *psDevNode;
1179
1180         PVR_UNREFERENCED_PARAMETER(ui32ISRSourceMask);
1181
1182         if (SysAcquireData(&psSysData) != PVRSRV_OK) {
1183                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterSystemISRHandler: "
1184                                         "Failed to get SysData");
1185                 return PVRSRV_ERROR_GENERIC;
1186         }
1187
1188         psDevNode = psSysData->psDeviceNodeList;
1189         while (psDevNode) {
1190                 if (psDevNode->sDevId.ui32DeviceIndex == ui32DeviceID)
1191                         break;
1192                 psDevNode = psDevNode->psNext;
1193         }
1194
1195         if (psDevNode == NULL) {
1196                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterSystemISRHandler: "
1197                                         "Failed to get psDevNode");
1198                 PVR_DBG_BREAK;
1199                 return PVRSRV_ERROR_GENERIC;
1200         }
1201
1202         psDevNode->pvISRData = (void *) pvISRHandlerData;
1203
1204         psDevNode->pfnDeviceISR = pfnISRHandler;
1205
1206         return PVRSRV_OK;
1207 }
1208
1209 void PVRSRVSetDCState(u32 ui32State)
1210 {
1211         struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1212         struct PVRSRV_DEVICE_NODE *psDeviceNode;
1213         struct SYS_DATA *psSysData;
1214
1215         if (SysAcquireData(&psSysData) != PVRSRV_OK) {
1216                 PVR_DPF(PVR_DBG_ERROR,
1217                          "PVRSRVSetDCState: Failed to get SysData");
1218                 return;
1219         }
1220
1221         psDeviceNode = psSysData->psDeviceNodeList;
1222         while (psDeviceNode != NULL) {
1223                 if (psDeviceNode->sDevId.eDeviceClass ==
1224                     PVRSRV_DEVICE_CLASS_DISPLAY) {
1225                         psDCInfo = (struct PVRSRV_DISPLAYCLASS_INFO *)
1226                                                         psDeviceNode->pvDevice;
1227                         if (psDCInfo->psFuncTable->pfnSetDCState &&
1228                             psDCInfo->hExtDevice)
1229                                 psDCInfo->psFuncTable->pfnSetDCState(
1230                                                         psDCInfo->hExtDevice,
1231                                                         ui32State);
1232                 }
1233                 psDeviceNode = psDeviceNode->psNext;
1234         }
1235 }
1236
1237 IMG_BOOL PVRGetDisplayClassJTable(struct PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable)
1238 {
1239         psJTable->ui32TableSize = sizeof(struct PVRSRV_DC_DISP2SRV_KMJTABLE);
1240         psJTable->pfnPVRSRVRegisterDCDevice = PVRSRVRegisterDCDeviceKM;
1241         psJTable->pfnPVRSRVRemoveDCDevice = PVRSRVRemoveDCDeviceKM;
1242         psJTable->pfnPVRSRVOEMFunction = SysOEMFunction;
1243         psJTable->pfnPVRSRVRegisterCmdProcList = PVRSRVRegisterCmdProcListKM;
1244         psJTable->pfnPVRSRVRemoveCmdProcList = PVRSRVRemoveCmdProcListKM;
1245         psJTable->pfnPVRSRVCmdComplete = PVRSRVCommandCompleteKM;
1246         psJTable->pfnPVRSRVRegisterSystemISRHandler =
1247             PVRSRVRegisterSystemISRHandler;
1248         psJTable->pfnPVRSRVRegisterPowerDevice = PVRSRVRegisterPowerDevice;
1249
1250         return IMG_TRUE;
1251 }
1252 EXPORT_SYMBOL(PVRGetDisplayClassJTable);
1253
1254 enum PVRSRV_ERROR PVRSRVCloseBCDeviceKM(void *hDeviceKM,
1255                                        IMG_BOOL bResManCallback)
1256 {
1257         struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
1258
1259         PVR_UNREFERENCED_PARAMETER(bResManCallback);
1260
1261         psBCPerContextInfo = (struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)
1262                                 hDeviceKM;
1263
1264         ResManFreeResByPtr(psBCPerContextInfo->hResItem);
1265
1266         return PVRSRV_OK;
1267 }
1268
1269 static enum PVRSRV_ERROR CloseBCDeviceCallBack(void *pvParam, u32 ui32Param)
1270 {
1271         struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
1272         struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
1273
1274         PVR_UNREFERENCED_PARAMETER(ui32Param);
1275
1276         psBCPerContextInfo = (struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)
1277                                 pvParam;
1278         psBCInfo = psBCPerContextInfo->psBCInfo;
1279
1280         psBCInfo->ui32RefCount--;
1281         if (psBCInfo->ui32RefCount == 0) {
1282                 u32 i;
1283
1284                 psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->hExtDevice);
1285
1286                 for (i = 0; i < psBCInfo->ui32BufferCount; i++)
1287                         if (psBCInfo->psBuffer[i].sDeviceClassBuffer.
1288                                     psKernelSyncInfo)
1289                                 PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].
1290                                                         sDeviceClassBuffer.
1291                                                               psKernelSyncInfo);
1292
1293                 if (psBCInfo->psBuffer)
1294                         OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
1295                                   sizeof(struct PVRSRV_BC_BUFFER),
1296                                   psBCInfo->psBuffer, NULL);
1297         }
1298
1299         OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
1300                   sizeof(struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO),
1301                   psBCPerContextInfo, NULL);
1302
1303         return PVRSRV_OK;
1304 }
1305
1306 enum PVRSRV_ERROR PVRSRVOpenBCDeviceKM(
1307                                 struct PVRSRV_PER_PROCESS_DATA *psPerProc,
1308                                 u32 ui32DeviceID, void *hDevCookie,
1309                                 void **phDeviceKM)
1310 {
1311         struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
1312         struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
1313         struct PVRSRV_DEVICE_NODE *psDeviceNode;
1314         struct BUFFER_INFO sBufferInfo;
1315         struct SYS_DATA *psSysData;
1316         u32 i;
1317         enum PVRSRV_ERROR eError;
1318
1319         if (!phDeviceKM || !hDevCookie) {
1320                 PVR_DPF(PVR_DBG_ERROR,
1321                          "PVRSRVOpenBCDeviceKM: Invalid params");
1322                 return PVRSRV_ERROR_GENERIC;
1323         }
1324
1325         if (SysAcquireData(&psSysData) != PVRSRV_OK) {
1326                 PVR_DPF(PVR_DBG_ERROR,
1327                          "PVRSRVOpenBCDeviceKM: Failed to get SysData");
1328                 return PVRSRV_ERROR_GENERIC;
1329         }
1330
1331         psDeviceNode = psSysData->psDeviceNodeList;
1332         while (psDeviceNode) {
1333                 if ((psDeviceNode->sDevId.eDeviceClass ==
1334                      PVRSRV_DEVICE_CLASS_BUFFER) &&
1335                       (psDeviceNode->sDevId.ui32DeviceIndex == ui32DeviceID)) {
1336
1337                         psBCInfo = (struct PVRSRV_BUFFERCLASS_INFO *)
1338                                                         psDeviceNode->pvDevice;
1339                         goto FoundDevice;
1340                 }
1341                 psDeviceNode = psDeviceNode->psNext;
1342         }
1343
1344         PVR_DPF(PVR_DBG_ERROR,
1345                  "PVRSRVOpenBCDeviceKM: No devnode matching index %d",
1346                  ui32DeviceID);
1347
1348         return PVRSRV_ERROR_GENERIC;
1349
1350 FoundDevice:
1351
1352         if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
1353                        sizeof(*psBCPerContextInfo),
1354                        (void **)&psBCPerContextInfo, NULL) != PVRSRV_OK) {
1355                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: "
1356                                         "Failed psBCPerContextInfo alloc");
1357                 return PVRSRV_ERROR_OUT_OF_MEMORY;
1358         }
1359         OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo));
1360
1361         if (psBCInfo->ui32RefCount++ == 0) {
1362                 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie;
1363
1364                 psBCInfo->hDevMemContext =
1365                     (void *) psDeviceNode->sDevMemoryInfo.pBMKernelContext;
1366
1367                 eError =
1368                     psBCInfo->psFuncTable->pfnOpenBCDevice(&psBCInfo->
1369                                                            hExtDevice);
1370                 if (eError != PVRSRV_OK) {
1371                         PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: "
1372                                         "Failed to open external BC device");
1373                         goto err1;
1374                 }
1375
1376                 eError =
1377                     psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice,
1378                                                         &sBufferInfo);
1379                 if (eError != PVRSRV_OK) {
1380                         PVR_DPF(PVR_DBG_ERROR,
1381                                 "PVRSRVOpenBCDeviceKM : Failed to get BC Info");
1382                         goto err2;
1383                 }
1384
1385                 psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount;
1386
1387                 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
1388                                     sizeof(struct PVRSRV_BC_BUFFER) *
1389                                     sBufferInfo.ui32BufferCount,
1390                                     (void **) &psBCInfo->psBuffer,
1391                                     NULL);
1392                 if (eError != PVRSRV_OK) {
1393                         PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: "
1394                                         "Failed to allocate BC buffers");
1395                         goto err2;
1396                 }
1397                 OSMemSet(psBCInfo->psBuffer, 0,
1398                          sizeof(struct PVRSRV_BC_BUFFER) *
1399                          sBufferInfo.ui32BufferCount);
1400
1401                 for (i = 0; i < psBCInfo->ui32BufferCount; i++) {
1402
1403                         eError = PVRSRVAllocSyncInfoKM(NULL,
1404                                       psBCInfo->hDevMemContext,
1405                                       &psBCInfo->psBuffer[i].sDeviceClassBuffer.
1406                                                         psKernelSyncInfo);
1407                         if (eError != PVRSRV_OK) {
1408                                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: "
1409                                                 "Failed sync info alloc");
1410                                 goto err3;
1411                         }
1412
1413                         eError = psBCInfo->psFuncTable->pfnGetBCBuffer(
1414                                     psBCInfo->hExtDevice, i,
1415                                     psBCInfo->psBuffer[i].sDeviceClassBuffer.
1416                                                           psKernelSyncInfo->
1417                                                                      psSyncData,
1418                                     &psBCInfo->psBuffer[i].sDeviceClassBuffer.
1419                                                           hExtBuffer);
1420                         if (eError != PVRSRV_OK) {
1421                                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: "
1422                                                 "Failed to get BC buffers");
1423                                 goto err3;
1424                         }
1425
1426                         psBCInfo->psBuffer[i].sDeviceClassBuffer.
1427                             pfnGetBufferAddr =
1428                                     psBCInfo->psFuncTable->pfnGetBufferAddr;
1429                         psBCInfo->psBuffer[i].sDeviceClassBuffer.
1430                             hDevMemContext = psBCInfo->hDevMemContext;
1431                         psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice =
1432                             psBCInfo->hExtDevice;
1433                 }
1434         }
1435
1436         psBCPerContextInfo->psBCInfo = psBCInfo;
1437         psBCPerContextInfo->hResItem =
1438             ResManRegisterRes(psPerProc->hResManContext,
1439                               RESMAN_TYPE_BUFFERCLASS_DEVICE,
1440                               psBCPerContextInfo, 0, CloseBCDeviceCallBack);
1441
1442         *phDeviceKM = (void *)psBCPerContextInfo;
1443
1444         return PVRSRV_OK;
1445
1446 err3:
1447         for (i = 0; i < psBCInfo->ui32BufferCount; i++) {
1448                 if (psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) {
1449                         PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].
1450                                                      sDeviceClassBuffer.
1451                                                              psKernelSyncInfo);
1452                 }
1453         }
1454         OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
1455                   sizeof(struct PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount,
1456                   psBCInfo->psBuffer, NULL);
1457 err2:
1458         psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->hExtDevice);
1459 err1:
1460         OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psBCPerContextInfo),
1461                   psBCPerContextInfo, NULL);
1462         psBCInfo->ui32RefCount--;
1463
1464         return eError;
1465 }
1466
1467 enum PVRSRV_ERROR PVRSRVGetBCInfoKM(void *hDeviceKM,
1468                                     struct BUFFER_INFO *psBufferInfo)
1469 {
1470         struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
1471         enum PVRSRV_ERROR eError;
1472
1473         if (!hDeviceKM || !psBufferInfo) {
1474                 PVR_DPF(PVR_DBG_ERROR,
1475                          "PVRSRVGetBCInfoKM: Invalid parameters");
1476                 return PVRSRV_ERROR_INVALID_PARAMS;
1477         }
1478
1479         psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
1480
1481         eError =
1482             psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice,
1483                                                 psBufferInfo);
1484
1485         if (eError != PVRSRV_OK) {
1486                 PVR_DPF(PVR_DBG_ERROR,
1487                          "PVRSRVGetBCInfoKM : Failed to get BC Info");
1488                 return eError;
1489         }
1490
1491         return PVRSRV_OK;
1492 }
1493
1494 enum PVRSRV_ERROR PVRSRVGetBCBufferKM(void *hDeviceKM, u32 ui32BufferIndex,
1495                                  void **phBuffer)
1496 {
1497         struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
1498
1499         if (!hDeviceKM || !phBuffer) {
1500                 PVR_DPF(PVR_DBG_ERROR,
1501                          "PVRSRVGetBCBufferKM: Invalid parameters");
1502                 return PVRSRV_ERROR_INVALID_PARAMS;
1503         }
1504
1505         psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
1506
1507         if (ui32BufferIndex < psBCInfo->ui32BufferCount) {
1508                 *phBuffer = (void *)&psBCInfo->psBuffer[ui32BufferIndex];
1509         } else {
1510                 PVR_DPF(PVR_DBG_ERROR, "PVRSRVGetBCBufferKM: "
1511                                 "Buffer index %d out of range (%d)",
1512                          ui32BufferIndex, psBCInfo->ui32BufferCount);
1513                 return PVRSRV_ERROR_INVALID_PARAMS;
1514         }
1515
1516         return PVRSRV_OK;
1517 }
1518
1519 IMG_BOOL PVRGetBufferClassJTable(struct PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable)
1520 {
1521         psJTable->ui32TableSize = sizeof(struct PVRSRV_BC_BUFFER2SRV_KMJTABLE);
1522
1523         psJTable->pfnPVRSRVRegisterBCDevice = PVRSRVRegisterBCDeviceKM;
1524         psJTable->pfnPVRSRVRemoveBCDevice = PVRSRVRemoveBCDeviceKM;
1525
1526         return IMG_TRUE;
1527 }
1528 EXPORT_SYMBOL(PVRGetBufferClassJTable);
1529