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