summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'omap5/sgx_src/eurasia_km/services4/srvkm/common/deviceclass.c')
-rw-r--r--omap5/sgx_src/eurasia_km/services4/srvkm/common/deviceclass.c2863
1 files changed, 0 insertions, 2863 deletions
diff --git a/omap5/sgx_src/eurasia_km/services4/srvkm/common/deviceclass.c b/omap5/sgx_src/eurasia_km/services4/srvkm/common/deviceclass.c
deleted file mode 100644
index d047c78..0000000
--- a/omap5/sgx_src/eurasia_km/services4/srvkm/common/deviceclass.c
+++ /dev/null
@@ -1,2863 +0,0 @@
1/*************************************************************************/ /*!
2@Title Device class services functions
3@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
4@Description Kernel services functions for device class devices
5@License Dual MIT/GPLv2
6
7The contents of this file are subject to the MIT license as set out below.
8
9Permission is hereby granted, free of charge, to any person obtaining a copy
10of this software and associated documentation files (the "Software"), to deal
11in the Software without restriction, including without limitation the rights
12to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13copies of the Software, and to permit persons to whom the Software is
14furnished to do so, subject to the following conditions:
15
16The above copyright notice and this permission notice shall be included in
17all copies or substantial portions of the Software.
18
19Alternatively, the contents of this file may be used under the terms of
20the GNU General Public License Version 2 ("GPL") in which case the provisions
21of GPL are applicable instead of those above.
22
23If you wish to allow use of your version of this file only under the terms of
24GPL, and not to allow others to use your version of this file under the terms
25of the MIT license, indicate your decision by deleting the provisions above
26and replace them with the notice and other provisions required by GPL as set
27out in the file called "GPL-COPYING" included in this distribution. If you do
28not delete the provisions above, a recipient may use your version of this file
29under the terms of either the MIT license or GPL.
30
31This License is also included in this distribution in the file called
32"MIT-COPYING".
33
34EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
35PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
36BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
37PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
38COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
39IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
40CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41*/ /**************************************************************************/
42
43#include "services_headers.h"
44#include "buffer_manager.h"
45#include "kernelbuffer.h"
46#include "kerneldisplay.h"
47#include "pvr_bridge_km.h"
48#include "pdump_km.h"
49#include "deviceid.h"
50
51#include "lists.h"
52#if defined(CONFIG_GCBV)
53#include "gc_bvmapping.h"
54#endif
55
56PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
57PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
58
59#if defined(SUPPORT_MISR_IN_THREAD)
60void OSVSyncMISR(IMG_HANDLE, IMG_BOOL);
61#endif
62
63#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
64IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
65 IMG_BOOL bScheduleMISR);
66#endif
67/***********************************************************************
68 Local Display Class Structures
69************************************************************************/
70typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG *PPVRSRV_DC_SRV2DISP_KMJTABLE;
71
72/*
73 Display Class Buffer Info
74*/
75typedef struct PVRSRV_DC_BUFFER_TAG
76{
77 /* BC/DC common details - THIS MUST BE THE FIRST MEMBER */
78 PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
79
80 struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
81 struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
82} PVRSRV_DC_BUFFER;
83
84/*
85 Display Device Class kernel swapchain information structure
86*/
87typedef struct PVRSRV_DC_SWAPCHAIN_TAG
88{
89 IMG_HANDLE hExtSwapChain;
90 IMG_UINT32 ui32SwapChainID;
91 IMG_UINT32 ui32RefCount;
92 IMG_UINT32 ui32Flags;
93 PVRSRV_QUEUE_INFO *psQueue;
94 PVRSRV_DC_BUFFER asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
95 IMG_UINT32 ui32BufferCount;
96 PVRSRV_DC_BUFFER *psLastFlipBuffer;
97 IMG_UINT32 ui32MinSwapInterval;
98 IMG_UINT32 ui32MaxSwapInterval;
99#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
100 PVRSRV_KERNEL_SYNC_INFO **ppsLastSyncInfos;
101 IMG_UINT32 ui32LastNumSyncInfos;
102#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
103 struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
104 struct PVRSRV_DC_SWAPCHAIN_TAG *psNext;
105} PVRSRV_DC_SWAPCHAIN;
106
107
108/*
109 Display Device Class kernel swapchain referecne structure
110*/
111typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG
112{
113 struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
114 IMG_HANDLE hResItem;
115} PVRSRV_DC_SWAPCHAIN_REF;
116
117
118/*
119 Display Device Class kernel services information structure
120*/
121typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG
122{
123 IMG_UINT32 ui32RefCount;
124 IMG_UINT32 ui32DeviceID;
125 IMG_HANDLE hExtDevice;
126 PPVRSRV_DC_SRV2DISP_KMJTABLE psFuncTable;
127 IMG_HANDLE hDevMemContext;
128 PVRSRV_DC_BUFFER sSystemBuffer;
129 struct PVRSRV_DC_SWAPCHAIN_TAG *psDCSwapChainShared;
130} PVRSRV_DISPLAYCLASS_INFO;
131
132
133/*
134 Per-context Display Device Class kernel services information structure
135*/
136typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG
137{
138 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
139 PRESMAN_ITEM hResItem;
140} PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO;
141
142
143/***********************************************************************
144 Local Buffer Class Structures
145************************************************************************/
146typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG *PPVRSRV_BC_SRV2BUFFER_KMJTABLE;
147
148/*
149 Buffer Class Buffer Info
150*/
151typedef struct PVRSRV_BC_BUFFER_TAG
152{
153 /* BC/DC common details - THIS MUST BE THE FIRST MEMBER */
154 PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
155
156 struct PVRSRV_BUFFERCLASS_INFO_TAG *psBCInfo;
157} PVRSRV_BC_BUFFER;
158
159
160/*
161 Buffer Device Class kernel services information structure
162*/
163typedef struct PVRSRV_BUFFERCLASS_INFO_TAG
164{
165 IMG_UINT32 ui32RefCount;
166 IMG_UINT32 ui32DeviceID;
167 IMG_HANDLE hExtDevice;
168 PPVRSRV_BC_SRV2BUFFER_KMJTABLE psFuncTable;
169 IMG_HANDLE hDevMemContext;
170 /* buffer info returned from 3rd party driver */
171 IMG_UINT32 ui32BufferCount;
172 PVRSRV_BC_BUFFER *psBuffer;
173
174} PVRSRV_BUFFERCLASS_INFO;
175
176
177/*
178 Per-context Buffer Device Class kernel services information structure
179*/
180typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG
181{
182 PVRSRV_BUFFERCLASS_INFO *psBCInfo;
183 IMG_HANDLE hResItem;
184} PVRSRV_BUFFERCLASS_PERCONTEXT_INFO;
185
186
187/*!
188******************************************************************************
189 @Function DCDeviceHandleToDCInfo
190
191 @Description
192
193 Convert a client-visible 3rd party device class handle to an internal
194 PVRSRV_DISPLAYCLASS_INFO pointer.
195
196 @Input hDeviceKM - handle to display class device, returned from OpenDCDevice
197
198 @Return
199 success: pointer to PVRSRV_DISPLAYCLASS_INFO
200 failure: IMG_NULL
201******************************************************************************/
202static PVRSRV_DISPLAYCLASS_INFO* DCDeviceHandleToDCInfo (IMG_HANDLE hDeviceKM)
203{
204 PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
205
206 psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
207
208 return psDCPerContextInfo->psDCInfo;
209}
210
211
212/*!
213******************************************************************************
214 @Function BCDeviceHandleToBCInfo
215
216 @Description
217
218 Convert a client-visible 3rd party buffer class handle to an internal
219 PVRSRV_BUFFERCLASS_INFO pointer.
220
221 @Input hDeviceKM - handle to buffer class device, returned from OpenBCDevice
222
223 @Return
224 success: pointer to PVRSRV_BUFFERCLASS_INFO
225 failure: IMG_NULL
226******************************************************************************/
227static PVRSRV_BUFFERCLASS_INFO* BCDeviceHandleToBCInfo (IMG_HANDLE hDeviceKM)
228{
229 PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
230
231 psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
232
233 return psBCPerContextInfo->psBCInfo;
234}
235
236/*!
237******************************************************************************
238 @Function PVRSRVEnumerateDCKM_ForEachVaCb
239
240 @Description
241
242 Enumerates the device node (if is of the same class as given).
243
244 @Input psDeviceNode - The device node to be enumerated
245 va - variable arguments list, with:
246 pui32DevCount - The device count pointer (to be increased)
247 ppui32DevID - The pointer to the device IDs pointer (to be updated and increased)
248 peDeviceClass - The pointer to the device class of the psDeviceNode's to be enumerated.
249******************************************************************************/
250static IMG_VOID PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
251{
252 IMG_UINT *pui32DevCount;
253 IMG_UINT32 **ppui32DevID;
254 PVRSRV_DEVICE_CLASS peDeviceClass;
255
256 pui32DevCount = va_arg(va, IMG_UINT*);
257 ppui32DevID = va_arg(va, IMG_UINT32**);
258 peDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS);
259
260 if ((psDeviceNode->sDevId.eDeviceClass == peDeviceClass)
261 && (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_EXT))
262 {
263 (*pui32DevCount)++;
264 if(*ppui32DevID)
265 {
266 *(*ppui32DevID)++ = psDeviceNode->sDevId.ui32DeviceIndex;
267 }
268 }
269}
270
271
272/*!
273******************************************************************************
274
275 @Function PVRSRVEnumerateDCKM
276
277 @Description
278
279 Enumerates devices available in a given class.
280 On first call, pass valid ptr for pui32DevCount and IMG_NULL for pui32DevID,
281 On second call, pass same ptr for pui32DevCount and client allocated ptr
282 for pui32DevID device id list
283
284 @Input hServices - handle for services connection
285 @Input ui32DevClass - device class identifier
286 @Output pui32DevCount - number of devices available in class
287 @Output pui32DevID - list of device ids in the device class
288
289 @Return
290 success: handle to matching display class device
291 failure: IMG_NULL
292
293******************************************************************************/
294IMG_EXPORT
295PVRSRV_ERROR PVRSRVEnumerateDCKM (PVRSRV_DEVICE_CLASS DeviceClass,
296 IMG_UINT32 *pui32DevCount,
297 IMG_UINT32 *pui32DevID )
298{
299 /*PVRSRV_DEVICE_NODE *psDeviceNode;*/
300 IMG_UINT ui32DevCount = 0;
301 SYS_DATA *psSysData;
302
303 SysAcquireData(&psSysData);
304
305 /* search devonode list for devices in specified class and return the device ids */
306 List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
307 &PVRSRVEnumerateDCKM_ForEachVaCb,
308 &ui32DevCount,
309 &pui32DevID,
310 DeviceClass);
311
312 if(pui32DevCount)
313 {
314 *pui32DevCount = ui32DevCount;
315 }
316 else if(pui32DevID == IMG_NULL)
317 {
318 PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDCKM: Invalid parameters"));
319 return (PVRSRV_ERROR_INVALID_PARAMS);
320 }
321
322 return PVRSRV_OK;
323}
324
325
326/*!
327******************************************************************************
328
329 @Function PVRSRVRegisterDCDeviceKM
330
331 @Description
332
333 registers an external device with the system
334
335 @Input psFuncTable : device function table
336
337 @Output pui32DeviceID : unique device key (for case of multiple identical devices)
338
339 @Return PVRSRV_ERROR :
340
341******************************************************************************/
342static
343PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
344 IMG_UINT32 *pui32DeviceID)
345{
346 PVRSRV_DISPLAYCLASS_INFO *psDCInfo = IMG_NULL;
347 PVRSRV_DEVICE_NODE *psDeviceNode;
348 SYS_DATA *psSysData;
349
350 /*
351 IN:
352 - name of client side ext. device driver library for subsequent loading
353 - predefined list of callbacks into kernel ext. device driver (based on class type)
354
355 FUNCTION TASKS:
356 - allocate display device class info structure
357 - hang ext.device kernel callbacks on this structure (pfnKSwapToSystem)
358
359 OUT:
360 - DEVICE_ID
361 - pass back devinfo? no
362
363 Q&A:
364 - DEVICE_ID passed in or allocated - assume allocate
365 */
366
367 SysAcquireData(&psSysData);
368
369 /*
370 If we got this far we're doing dynamic enumeration
371 or first time static registration
372 */
373
374 /* Allocate device control block */
375 if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
376 sizeof(*psDCInfo),
377 (IMG_VOID **)&psDCInfo, IMG_NULL,
378 "Display Class Info") != PVRSRV_OK)
379 {
380 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDCInfo alloc"));
381 return PVRSRV_ERROR_OUT_OF_MEMORY;
382 }
383 OSMemSet (psDCInfo, 0, sizeof(*psDCInfo));
384
385 /* setup the display device information structure */
386 if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
387 sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
388 (IMG_VOID **)&psDCInfo->psFuncTable, IMG_NULL,
389 "Function table for SRVKM->DISPLAY") != PVRSRV_OK)
390 {
391 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psFuncTable alloc"));
392 goto ErrorExit;
393 }
394 OSMemSet (psDCInfo->psFuncTable, 0, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE));
395
396 /* copy the jump table */
397 *psDCInfo->psFuncTable = *psFuncTable;
398
399 /* Allocate device node */
400 if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
401 sizeof(PVRSRV_DEVICE_NODE),
402 (IMG_VOID **)&psDeviceNode, IMG_NULL,
403 "Device Node") != PVRSRV_OK)
404 {
405 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDeviceNode alloc"));
406 goto ErrorExit;
407 }
408 OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
409
410 psDeviceNode->pvDevice = (IMG_VOID*)psDCInfo;
411 psDeviceNode->ui32pvDeviceSize = sizeof(*psDCInfo);
412 psDeviceNode->ui32RefCount = 1;
413 psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
414 psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY;
415 psDeviceNode->psSysData = psSysData;
416
417 /* allocate a unique device id */
418 if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
419 {
420 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
421 goto ErrorExit;
422 }
423 psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
424 if (pui32DeviceID)
425 {
426 *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
427 }
428
429 /* Register the device with the system */
430 SysRegisterExternalDevice(psDeviceNode);
431
432 /* and finally insert the device into the dev-list */
433 List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
434
435 return PVRSRV_OK;
436
437ErrorExit:
438
439 if(psDCInfo->psFuncTable)
440 {
441 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
442 psDCInfo->psFuncTable = IMG_NULL;
443 }
444
445 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
446 /*not nulling pointer, out of scope*/
447
448 return PVRSRV_ERROR_OUT_OF_MEMORY;
449}
450
451/*!
452******************************************************************************
453
454 @Function PVRSRVRemoveDCDeviceKM
455
456 @Description
457
458 Removes external device from services system record
459
460 @Input ui32DeviceIndex : unique device key (for case of multiple identical devices)
461
462 @Return PVRSRV_ERROR :
463
464******************************************************************************/
465static PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
466{
467 SYS_DATA *psSysData;
468 PVRSRV_DEVICE_NODE *psDeviceNode;
469 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
470
471 SysAcquireData(&psSysData);
472
473 /*search the node matching the devindex and display class*/
474 psDeviceNode = (PVRSRV_DEVICE_NODE*)
475 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
476 &MatchDeviceKM_AnyVaCb,
477 ui32DevIndex,
478 IMG_FALSE,
479 PVRSRV_DEVICE_CLASS_DISPLAY);
480 if (!psDeviceNode)
481 {
482 /*device not found*/
483 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: requested device %d not present", ui32DevIndex));
484 return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
485 }
486
487 /* setup DCInfo ptr */
488 psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
489
490 /*
491 The device can only be removed if there are
492 no open connections in the Services interface
493 */
494 if(psDCInfo->ui32RefCount == 0)
495 {
496 /*
497 Remove from the device list.
498 */
499 List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
500
501 /* Unregister the device with the system */
502 SysRemoveExternalDevice(psDeviceNode);
503
504 /*
505 OK found a device with a matching devindex
506 remove registration information
507 */
508 PVR_ASSERT(psDCInfo->ui32RefCount == 0);
509 (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
510 (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
511 psDCInfo->psFuncTable = IMG_NULL;
512 (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
513 /*not nulling original pointer, overwritten*/
514 (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
515 /*not nulling pointer, out of scope*/
516 }
517 else
518 {
519 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: failed as %d Services DC API connections are still open", psDCInfo->ui32RefCount));
520 return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE;
521 }
522
523 return PVRSRV_OK;
524}
525
526
527/*!
528******************************************************************************
529
530 @Function PVRSRVRegisterBCDeviceKM
531
532 @Description
533
534 registers an external device with the system
535
536 @Input psFuncTable : device function table
537 @Input ui32DeviceIndex : unique device key (for case of multiple identical devices)
538
539 @Return PVRSRV_ERROR :
540
541******************************************************************************/
542static
543PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable,
544 IMG_UINT32 *pui32DeviceID)
545{
546 PVRSRV_BUFFERCLASS_INFO *psBCInfo = IMG_NULL;
547 PVRSRV_DEVICE_NODE *psDeviceNode;
548 SYS_DATA *psSysData;
549 /*
550 IN:
551 - name of client side ext. device driver library for subsequent loading
552 - predefined list of callbacks into kernel ext. device driver (based on class type)
553
554 FUNCTION TASKS:
555 - allocate buffer device class info structure
556
557 OUT:
558 - DEVICE_ID
559 - pass back devinfo? no
560
561 Q&A:
562 - DEVICE_ID passed in or allocated - assume allcoate
563 */
564
565 SysAcquireData(&psSysData);
566
567 /*
568 If we got this far we're doing dynamic enumeration
569 or first time static registration
570 */
571
572 /* Allocate device control block */
573 if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
574 sizeof(*psBCInfo),
575 (IMG_VOID **)&psBCInfo, IMG_NULL,
576 "Buffer Class Info") != PVRSRV_OK)
577 {
578 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psBCInfo alloc"));
579 return PVRSRV_ERROR_OUT_OF_MEMORY;
580 }
581 OSMemSet (psBCInfo, 0, sizeof(*psBCInfo));
582
583 /* setup the buffer device information structure */
584 if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
585 sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE),
586 (IMG_VOID **)&psBCInfo->psFuncTable, IMG_NULL,
587 "Function table for SRVKM->BUFFER") != PVRSRV_OK)
588 {
589 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psFuncTable alloc"));
590 goto ErrorExit;
591 }
592 OSMemSet (psBCInfo->psFuncTable, 0, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE));
593
594 /* copy the jump table */
595 *psBCInfo->psFuncTable = *psFuncTable;
596
597 /* Allocate device node */
598 if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
599 sizeof(PVRSRV_DEVICE_NODE),
600 (IMG_VOID **)&psDeviceNode, IMG_NULL,
601 "Device Node") != PVRSRV_OK)
602 {
603 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psDeviceNode alloc"));
604 goto ErrorExit;
605 }
606 OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
607
608 psDeviceNode->pvDevice = (IMG_VOID*)psBCInfo;
609 psDeviceNode->ui32pvDeviceSize = sizeof(*psBCInfo);
610 psDeviceNode->ui32RefCount = 1;
611 psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
612 psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER;
613 psDeviceNode->psSysData = psSysData;
614
615 /* allocate a unique device id */
616 if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
617 {
618 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
619 goto ErrorExit;
620 }
621 psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
622 if (pui32DeviceID)
623 {
624 *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
625 }
626
627 /* and finally insert the device into the dev-list */
628 List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
629
630 return PVRSRV_OK;
631
632ErrorExit:
633
634 if(psBCInfo->psFuncTable)
635 {
636 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PPVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
637 psBCInfo->psFuncTable = IMG_NULL;
638 }
639
640 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
641 /*not nulling shared pointer, wasn't allocated to this point*/
642
643 return PVRSRV_ERROR_OUT_OF_MEMORY;
644}
645
646
647/*!
648******************************************************************************
649
650 @Function PVRSRVRemoveBCDeviceKM
651
652 @Description
653
654 Removes external device from services system record
655
656 @Input ui32DeviceIndex : unique device key (for case of multiple identical devices)
657
658 @Return PVRSRV_ERROR :
659
660******************************************************************************/
661static PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
662{
663 SYS_DATA *psSysData;
664 PVRSRV_DEVICE_NODE *psDevNode;
665 PVRSRV_BUFFERCLASS_INFO *psBCInfo;
666
667 SysAcquireData(&psSysData);
668
669 /*search the device node with the devindex and buffer class*/
670 psDevNode = (PVRSRV_DEVICE_NODE*)
671 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
672 &MatchDeviceKM_AnyVaCb,
673 ui32DevIndex,
674 IMG_FALSE,
675 PVRSRV_DEVICE_CLASS_BUFFER);
676
677 if (!psDevNode)
678 {
679 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: requested device %d not present", ui32DevIndex));
680 return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
681 }
682
683 /* set-up devnode ptr */
684/* psDevNode = *(ppsDevNode); */
685 /* setup BCInfo ptr */
686 psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDevNode->pvDevice;
687
688 /*
689 The device can only be removed if there are
690 no open connections in the Services interface
691 */
692 if(psBCInfo->ui32RefCount == 0)
693 {
694 /*
695 Remove from the device list.
696 */
697 List_PVRSRV_DEVICE_NODE_Remove(psDevNode);
698
699 /*
700 OK found a device with a matching devindex
701 remove registration information
702 */
703 (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
704 (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
705 psBCInfo->psFuncTable = IMG_NULL;
706 (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
707 /*not nulling pointer, copy on stack*/
708 (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDevNode, IMG_NULL);
709 /*not nulling pointer, out of scope*/
710 }
711 else
712 {
713 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: failed as %d Services BC API connections are still open", psBCInfo->ui32RefCount));
714 return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE;
715 }
716
717 return PVRSRV_OK;
718}
719
720
721
722/*!
723******************************************************************************
724
725 @Function PVRSRVCloseDCDeviceKM
726
727 @Description
728
729 Closes a connection to the Display Class device
730
731 @Input hDeviceKM : device handle
732
733 @Return PVRSRV_ERROR :
734
735******************************************************************************/
736IMG_EXPORT
737PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE hDeviceKM)
738{
739 PVRSRV_ERROR eError;
740 PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
741
742 psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
743
744 /* Remove the item from the resman list and trigger the callback. */
745 eError = ResManFreeResByPtr(psDCPerContextInfo->hResItem, CLEANUP_WITH_POLL);
746
747 return eError;
748}
749
750
751static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID pvParam,
752 IMG_UINT32 ui32Param,
753 IMG_BOOL bDummy)
754{
755 PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
756 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
757
758 PVR_UNREFERENCED_PARAMETER(ui32Param);
759 PVR_UNREFERENCED_PARAMETER(bDummy);
760
761 psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)pvParam;
762 psDCInfo = psDCPerContextInfo->psDCInfo;
763
764 if(psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount != 0)
765 {
766 PVR_DPF((PVR_DBG_MESSAGE,"CloseDCDeviceCallBack: system buffer (0x%p) still mapped (refcount = %d)",
767 &psDCInfo->sSystemBuffer.sDeviceClassBuffer,
768 psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount));
769 }
770
771 psDCInfo->ui32RefCount--;
772 if(psDCInfo->ui32RefCount == 0)
773 {
774 /* close the external device */
775 psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice);
776
777 PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
778
779 psDCInfo->hDevMemContext = IMG_NULL;
780 psDCInfo->hExtDevice = IMG_NULL;
781 }
782
783 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), psDCPerContextInfo, IMG_NULL);
784 /*not nulling pointer, copy on stack*/
785
786 return PVRSRV_OK;
787}
788
789
790/*!
791******************************************************************************
792
793 @Function PVRSRVOpenDCDeviceKM
794
795 @Description
796
797 Opens a connection to the Display Class device, associating the connection
798 with a Device Memory Context for a services managed device
799
800 @Input psPerProc : Per-process data
801 @Input ui32DeviceID : unique device index
802 @Input hDevCookie : devcookie used to derive the Device Memory
803 Context into BC surfaces will be mapped into
804 @Outut phDeviceKM : handle to the DC device
805
806 @Return PVRSRV_ERROR :
807
808******************************************************************************/
809IMG_EXPORT
810PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
811 IMG_UINT32 ui32DeviceID,
812 IMG_HANDLE hDevCookie,
813 IMG_HANDLE *phDeviceKM)
814{
815 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
816 PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
817 PVRSRV_DEVICE_NODE *psDeviceNode;
818 SYS_DATA *psSysData;
819 PVRSRV_ERROR eError;
820
821 if(!phDeviceKM || !hDevCookie)
822 {
823 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Invalid params"));
824 return PVRSRV_ERROR_INVALID_PARAMS;
825 }
826
827 SysAcquireData(&psSysData);
828
829 /* find the matching devicenode */
830 psDeviceNode = (PVRSRV_DEVICE_NODE*)
831 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
832 &MatchDeviceKM_AnyVaCb,
833 ui32DeviceID,
834 IMG_FALSE,
835 PVRSRV_DEVICE_CLASS_DISPLAY);
836 if (!psDeviceNode)
837 {
838 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID));
839 return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
840 }
841 psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
842
843 /*
844 Allocate the per-context DC Info before calling the external device,
845 to make error handling easier.
846 */
847 if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
848 sizeof(*psDCPerContextInfo),
849 (IMG_VOID **)&psDCPerContextInfo, IMG_NULL,
850 "Display Class per Context Info") != PVRSRV_OK)
851 {
852 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed psDCPerContextInfo alloc"));
853 return PVRSRV_ERROR_OUT_OF_MEMORY;
854 }
855 OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo));
856
857 if(psDCInfo->ui32RefCount++ == 0)
858 {
859
860 psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
861
862 /* store the device kernel context to map into */
863 psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
864
865 /* create a syncinfo for the device's system surface */
866 eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
867 (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext,
868 &psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
869 if(eError != PVRSRV_OK)
870 {
871 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed sync info alloc"));
872 psDCInfo->ui32RefCount--;
873 return eError;
874 }
875
876 /* open the external device */
877 eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID,
878 &psDCInfo->hExtDevice,
879 (PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM);
880 if(eError != PVRSRV_OK)
881 {
882 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device"));
883 psDCInfo->ui32RefCount--;
884 PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
885 return eError;
886 }
887
888 psDCPerContextInfo->psDCInfo = psDCInfo;
889 eError = PVRSRVGetDCSystemBufferKM(psDCPerContextInfo, IMG_NULL);
890 if(eError != PVRSRV_OK)
891 {
892 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to get system buffer"));
893 psDCInfo->ui32RefCount--;
894 PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
895 return eError;
896 }
897 psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount = 0;
898 }
899 else
900 {
901 psDCPerContextInfo->psDCInfo = psDCInfo;
902 }
903
904 psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
905 RESMAN_TYPE_DISPLAYCLASS_DEVICE,
906 psDCPerContextInfo,
907 0,
908 &CloseDCDeviceCallBack);
909
910 /* return a reference to the DCPerContextInfo */
911 *phDeviceKM = (IMG_HANDLE)psDCPerContextInfo;
912
913 return PVRSRV_OK;
914}
915
916
917/*!
918******************************************************************************
919
920 @Function PVRSRVEnumDCFormatsKM
921
922 @Description
923
924 Enumerates the devices pixel formats
925
926 @Input hDeviceKM : device handle
927 @Output pui32Count : number of pixel formats
928 @Output psFormat : format list
929
930 @Return PVRSRV_ERROR :
931
932******************************************************************************/
933IMG_EXPORT
934PVRSRV_ERROR PVRSRVEnumDCFormatsKM (IMG_HANDLE hDeviceKM,
935 IMG_UINT32 *pui32Count,
936 DISPLAY_FORMAT *psFormat)
937{
938 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
939
940 if(!hDeviceKM || !pui32Count || !psFormat)
941 {
942 PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCFormatsKM: Invalid parameters"));
943 return PVRSRV_ERROR_INVALID_PARAMS;
944 }
945
946 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
947
948 /* call into the display device driver to get info */
949 return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice, pui32Count, psFormat);
950}
951
952
953
954/*!
955******************************************************************************
956
957 @Function PVRSRVEnumDCDimsKM
958
959 @Description
960
961 Enumerates the devices mode dimensions for a given pixel format
962
963 @Input hDeviceKM : device handle
964 @Input psFormat : pixel format
965 @Output pui32Count : number of dimensions
966 @Output psDim : dimensions list
967
968 @Return PVRSRV_ERROR :
969
970******************************************************************************/
971IMG_EXPORT
972PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM,
973 DISPLAY_FORMAT *psFormat,
974 IMG_UINT32 *pui32Count,
975 DISPLAY_DIMS *psDim)
976{
977 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
978
979 if(!hDeviceKM || !pui32Count || !psFormat) // psDim==NULL to query number of dims
980 {
981 PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCDimsKM: Invalid parameters"));
982 return PVRSRV_ERROR_INVALID_PARAMS;
983 }
984
985 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
986
987 /* call into the display device driver to get info */
988 return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice, psFormat, pui32Count, psDim);
989}
990
991
992/*!
993******************************************************************************
994
995 @Function PVRSRVGetDCSystemBufferKM
996
997 @Description
998
999 Get the primary surface and optionally return its buffer handle
1000
1001 @Input hDeviceKM : device handle
1002 @Output phBuffer : Optional buffer handle
1003
1004 @Return PVRSRV_ERROR :
1005
1006******************************************************************************/
1007IMG_EXPORT
1008PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
1009 IMG_HANDLE *phBuffer)
1010{
1011 PVRSRV_ERROR eError;
1012 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1013 IMG_HANDLE hExtBuffer;
1014
1015 if(!hDeviceKM)
1016 {
1017 PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Invalid parameters"));
1018 return PVRSRV_ERROR_INVALID_PARAMS;
1019 }
1020
1021 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
1022
1023 /* call into the display device driver to get info */
1024 eError = psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice, &hExtBuffer);
1025 if(eError != PVRSRV_OK)
1026 {
1027 PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Failed to get valid buffer handle from external driver"));
1028 return eError;
1029 }
1030
1031 /* save the new info */
1032 psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
1033 psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
1034 psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
1035 psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer = hExtBuffer;
1036
1037 psDCInfo->sSystemBuffer.psDCInfo = psDCInfo;
1038
1039 /* return handle */
1040 if (phBuffer)
1041 {
1042 *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer);
1043 }
1044
1045 return PVRSRV_OK;
1046}
1047
1048
1049/******************************************************************************
1050
1051 @Function PVRSRVGetDCInfoKM
1052
1053 @Description
1054
1055 Gets Display Class device Info
1056
1057 @Input hDeviceKM : device handle
1058 @Output psDisplayInfo
1059
1060 @Return PVRSRV_ERROR :
1061
1062******************************************************************************/
1063IMG_EXPORT
1064PVRSRV_ERROR PVRSRVGetDCInfoKM (IMG_HANDLE hDeviceKM,
1065 DISPLAY_INFO *psDisplayInfo)
1066{
1067 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1068 PVRSRV_ERROR eError;
1069
1070 if(!hDeviceKM || !psDisplayInfo)
1071 {
1072 PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCInfoKM: Invalid parameters"));
1073 return PVRSRV_ERROR_INVALID_PARAMS;
1074 }
1075
1076 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
1077
1078 /* call into the display device driver to get info */
1079 eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, psDisplayInfo);
1080 if (eError != PVRSRV_OK)
1081 {
1082 return eError;
1083 }
1084
1085 if (psDisplayInfo->ui32MaxSwapChainBuffers > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
1086 {
1087 psDisplayInfo->ui32MaxSwapChainBuffers = PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS;
1088 }
1089
1090 return PVRSRV_OK;
1091}
1092
1093
1094IMG_EXPORT
1095PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE hSwapChainRef)
1096{
1097 PVRSRV_ERROR eError;
1098 PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
1099
1100 if(!hSwapChainRef)
1101 {
1102 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyDCSwapChainKM: Invalid parameters"));
1103 return PVRSRV_ERROR_INVALID_PARAMS;
1104 }
1105
1106 psSwapChainRef = hSwapChainRef;
1107
1108 eError = ResManFreeResByPtr(psSwapChainRef->hResItem, CLEANUP_WITH_POLL);
1109
1110 return eError;
1111}
1112
1113
1114static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain)
1115{
1116 PVRSRV_ERROR eError;
1117 PVRSRV_DISPLAYCLASS_INFO *psDCInfo = psSwapChain->psDCInfo;
1118 IMG_UINT32 i;
1119
1120 /* Update shared swapchains list */
1121 if( psDCInfo->psDCSwapChainShared )
1122 {
1123 if( psDCInfo->psDCSwapChainShared == psSwapChain )
1124 {
1125 psDCInfo->psDCSwapChainShared = psSwapChain->psNext;
1126 }
1127 else
1128 {
1129 PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
1130 psCurrentSwapChain = psDCInfo->psDCSwapChainShared;
1131 while( psCurrentSwapChain->psNext )
1132 {
1133 if( psCurrentSwapChain->psNext != psSwapChain )
1134 {
1135 psCurrentSwapChain = psCurrentSwapChain->psNext;
1136 continue;
1137 }
1138 psCurrentSwapChain->psNext = psSwapChain->psNext;
1139 break;
1140 }
1141 }
1142 }
1143
1144 /* Destroy command queue before swapchain - it may use the swapchain when commands are flushed. */
1145 PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue);
1146
1147 /* call into the display device driver to destroy a swapchain */
1148 eError = psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice,
1149 psSwapChain->hExtSwapChain);
1150
1151 if (eError != PVRSRV_OK)
1152 {
1153 PVR_DPF((PVR_DBG_ERROR,"DestroyDCSwapChainCallBack: Failed to destroy DC swap chain"));
1154 return eError;
1155 }
1156
1157 /* free the resources */
1158 for(i=0; i<psSwapChain->ui32BufferCount; i++)
1159 {
1160 if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
1161 {
1162 PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
1163 }
1164 }
1165
1166#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
1167 if (psSwapChain->ppsLastSyncInfos)
1168 {
1169 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos,
1170 psSwapChain->ppsLastSyncInfos, IMG_NULL);
1171 }
1172#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
1173
1174 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
1175 /*not nulling pointer, copy on stack*/
1176
1177 return eError;
1178}
1179
1180
1181static PVRSRV_ERROR DestroyDCSwapChainRefCallBack(IMG_PVOID pvParam,
1182 IMG_UINT32 ui32Param,
1183 IMG_BOOL bDummy)
1184{
1185 PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF *) pvParam;
1186 PVRSRV_ERROR eError = PVRSRV_OK;
1187 IMG_UINT32 i;
1188
1189 PVR_UNREFERENCED_PARAMETER(ui32Param);
1190 PVR_UNREFERENCED_PARAMETER(bDummy);
1191
1192 for (i = 0; i < psSwapChainRef->psSwapChain->ui32BufferCount; i++)
1193 {
1194 if (psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount != 0)
1195 {
1196 PVR_DPF((PVR_DBG_ERROR, "DestroyDCSwapChainRefCallBack: swapchain (0x%p) still mapped (ui32MemMapRefCount = %d)",
1197 &psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer,
1198 psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount));
1199 }
1200 }
1201
1202 if(--psSwapChainRef->psSwapChain->ui32RefCount == 0)
1203 {
1204 eError = DestroyDCSwapChain(psSwapChainRef->psSwapChain);
1205 }
1206
1207 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN_REF), psSwapChainRef, IMG_NULL);
1208 return eError;
1209}
1210
1211static PVRSRV_DC_SWAPCHAIN* PVRSRVFindSharedDCSwapChainKM(PVRSRV_DISPLAYCLASS_INFO *psDCInfo,
1212 IMG_UINT32 ui32SwapChainID)
1213{
1214 PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
1215
1216 for(psCurrentSwapChain = psDCInfo->psDCSwapChainShared;
1217 psCurrentSwapChain;
1218 psCurrentSwapChain = psCurrentSwapChain->psNext)
1219 {
1220 if(psCurrentSwapChain->ui32SwapChainID == ui32SwapChainID)
1221 return psCurrentSwapChain;
1222 }
1223 return IMG_NULL;
1224}
1225
1226static PVRSRV_ERROR PVRSRVCreateDCSwapChainRefKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
1227 PVRSRV_DC_SWAPCHAIN *psSwapChain,
1228 PVRSRV_DC_SWAPCHAIN_REF **ppsSwapChainRef)
1229{
1230 PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
1231
1232 /* Allocate swapchain reference structre*/
1233 if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
1234 sizeof(PVRSRV_DC_SWAPCHAIN_REF),
1235 (IMG_VOID **)&psSwapChainRef, IMG_NULL,
1236 "Display Class Swapchain Reference") != PVRSRV_OK)
1237 {
1238 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainRefKM: Failed psSwapChainRef alloc"));
1239 return PVRSRV_ERROR_OUT_OF_MEMORY;
1240 }
1241 OSMemSet (psSwapChainRef, 0, sizeof(PVRSRV_DC_SWAPCHAIN_REF));
1242
1243 /* Bump refcount */
1244 psSwapChain->ui32RefCount++;
1245
1246 /* Create reference resource */
1247 psSwapChainRef->psSwapChain = psSwapChain;
1248 psSwapChainRef->hResItem = ResManRegisterRes(psPerProc->hResManContext,
1249 RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
1250 psSwapChainRef,
1251 0,
1252 &DestroyDCSwapChainRefCallBack);
1253 *ppsSwapChainRef = psSwapChainRef;
1254
1255 return PVRSRV_OK;
1256}
1257
1258
1259IMG_EXPORT
1260PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
1261 IMG_HANDLE hDeviceKM,
1262 IMG_UINT32 ui32Flags,
1263 DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
1264 DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
1265 IMG_UINT32 ui32BufferCount,
1266 IMG_UINT32 ui32OEMFlags,
1267 IMG_HANDLE *phSwapChainRef,
1268 IMG_UINT32 *pui32SwapChainID)
1269{
1270 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1271 PVRSRV_DC_SWAPCHAIN *psSwapChain = IMG_NULL;
1272 PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
1273 PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
1274 PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
1275 PVRSRV_ERROR eError;
1276 IMG_UINT32 i;
1277 DISPLAY_INFO sDisplayInfo;
1278
1279
1280 if(!hDeviceKM
1281 || !psDstSurfAttrib
1282 || !psSrcSurfAttrib
1283 || !phSwapChainRef
1284 || !pui32SwapChainID)
1285 {
1286 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Invalid parameters"));
1287 return PVRSRV_ERROR_INVALID_PARAMS;
1288 }
1289
1290 if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
1291 {
1292 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too many buffers"));
1293 return PVRSRV_ERROR_TOOMANYBUFFERS;
1294 }
1295
1296 if (ui32BufferCount < 2)
1297 {
1298 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too few buffers"));
1299 return PVRSRV_ERROR_TOO_FEW_BUFFERS;
1300 }
1301
1302 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
1303
1304 if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_QUERY )
1305 {
1306 /* Query - use pui32SwapChainID as input */
1307 psSwapChain = PVRSRVFindSharedDCSwapChainKM(psDCInfo, *pui32SwapChainID );
1308 if( psSwapChain )
1309 {
1310 /* Create new reference */
1311 eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
1312 psSwapChain,
1313 &psSwapChainRef);
1314 if( eError != PVRSRV_OK )
1315 {
1316 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
1317 return eError;
1318 }
1319
1320 *phSwapChainRef = (IMG_HANDLE)psSwapChainRef;
1321 return PVRSRV_OK;
1322 }
1323 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: No shared SwapChain found for query"));
1324 return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
1325 }
1326
1327 /* Allocate swapchain control structure for srvkm */
1328 if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
1329 sizeof(PVRSRV_DC_SWAPCHAIN),
1330 (IMG_VOID **)&psSwapChain, IMG_NULL,
1331 "Display Class Swapchain") != PVRSRV_OK)
1332 {
1333 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc"));
1334 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1335 goto ErrorExit;
1336 }
1337 OSMemSet (psSwapChain, 0, sizeof(PVRSRV_DC_SWAPCHAIN));
1338
1339 /* Create a command queue for the swapchain */
1340 eError = PVRSRVCreateCommandQueueKM(1024, &psQueue);
1341 if(eError != PVRSRV_OK)
1342 {
1343 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue"));
1344 goto ErrorExit;
1345 }
1346
1347 /* store the Queue */
1348 psSwapChain->psQueue = psQueue;
1349
1350 /* Create a Sync Object for each surface in the swapchain */
1351 for(i=0; i<ui32BufferCount; i++)
1352 {
1353 eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
1354 psDCInfo->hDevMemContext,
1355 &psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
1356 if(eError != PVRSRV_OK)
1357 {
1358 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to alloc syninfo for psSwapChain"));
1359 goto ErrorExit;
1360 }
1361
1362 /* setup common device class info */
1363 psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
1364 psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
1365 psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
1366
1367 /* save off useful ptrs */
1368 psSwapChain->asBuffer[i].psDCInfo = psDCInfo;
1369 psSwapChain->asBuffer[i].psSwapChain = psSwapChain;
1370
1371 /* syncinfos must be passed as array of syncdata ptrs to the 3rd party driver */
1372 apsSyncData[i] = (PVRSRV_SYNC_DATA*)psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
1373 }
1374
1375 psSwapChain->ui32BufferCount = ui32BufferCount;
1376 psSwapChain->psDCInfo = psDCInfo;
1377
1378#if defined(PDUMP)
1379 PDUMPCOMMENT("Allocate DC swap chain (SwapChainID == %u, BufferCount == %u)",
1380 *pui32SwapChainID,
1381 ui32BufferCount);
1382 PDUMPCOMMENT(" Src surface dimensions == %u x %u",
1383 psSrcSurfAttrib->sDims.ui32Width,
1384 psSrcSurfAttrib->sDims.ui32Height);
1385 PDUMPCOMMENT(" Dst surface dimensions == %u x %u",
1386 psDstSurfAttrib->sDims.ui32Width,
1387 psDstSurfAttrib->sDims.ui32Height);
1388#endif
1389
1390 eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, &sDisplayInfo);
1391 if (eError != PVRSRV_OK)
1392 {
1393 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to get DC info"));
1394 return eError;
1395 }
1396
1397 psSwapChain->ui32MinSwapInterval = sDisplayInfo.ui32MinSwapInterval;
1398 psSwapChain->ui32MaxSwapInterval = sDisplayInfo.ui32MaxSwapInterval;
1399
1400 /* call into the display device driver to create a swapchain */
1401 eError = psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
1402 ui32Flags,
1403 psDstSurfAttrib,
1404 psSrcSurfAttrib,
1405 ui32BufferCount,
1406 apsSyncData,
1407 ui32OEMFlags,
1408 &psSwapChain->hExtSwapChain,
1409 &psSwapChain->ui32SwapChainID);
1410 if(eError != PVRSRV_OK)
1411 {
1412 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create 3rd party SwapChain"));
1413 PDUMPCOMMENT("Swapchain allocation failed.");
1414 goto ErrorExit;
1415 }
1416
1417 /* Create new reference */
1418 eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
1419 psSwapChain,
1420 &psSwapChainRef);
1421 if( eError != PVRSRV_OK )
1422 {
1423 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
1424 PDUMPCOMMENT("Swapchain allocation failed.");
1425 goto ErrorExit;
1426 }
1427
1428 psSwapChain->ui32RefCount = 1;
1429 psSwapChain->ui32Flags = ui32Flags;
1430
1431 /* Save pointer in DC structure if ti's shared struct */
1432 if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_SHARED )
1433 {
1434 if(! psDCInfo->psDCSwapChainShared )
1435 {
1436 psDCInfo->psDCSwapChainShared = psSwapChain;
1437 }
1438 else
1439 {
1440 PVRSRV_DC_SWAPCHAIN *psOldHead = psDCInfo->psDCSwapChainShared;
1441 psDCInfo->psDCSwapChainShared = psSwapChain;
1442 psSwapChain->psNext = psOldHead;
1443 }
1444 }
1445
1446 /* We create swapchain - pui32SwapChainID is output */
1447 *pui32SwapChainID = psSwapChain->ui32SwapChainID;
1448
1449 /* return the swapchain reference handle */
1450 *phSwapChainRef= (IMG_HANDLE)psSwapChainRef;
1451
1452 return eError;
1453
1454ErrorExit:
1455
1456 for(i=0; i<ui32BufferCount; i++)
1457 {
1458 if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
1459 {
1460 PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
1461 }
1462 }
1463
1464 if(psQueue)
1465 {
1466 PVRSRVDestroyCommandQueueKM(psQueue);
1467 }
1468
1469 if(psSwapChain)
1470 {
1471 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
1472 /*not nulling pointer, out of scope*/
1473 }
1474
1475 return eError;
1476}
1477
1478
1479
1480
1481IMG_EXPORT
1482PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE hDeviceKM,
1483 IMG_HANDLE hSwapChainRef,
1484 IMG_RECT *psRect)
1485{
1486 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1487 PVRSRV_DC_SWAPCHAIN *psSwapChain;
1488
1489 if(!hDeviceKM || !hSwapChainRef)
1490 {
1491 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstRectKM: Invalid parameters"));
1492 return PVRSRV_ERROR_INVALID_PARAMS;
1493 }
1494
1495 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
1496 psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
1497
1498 return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice,
1499 psSwapChain->hExtSwapChain,
1500 psRect);
1501}
1502
1503
1504IMG_EXPORT
1505PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE hDeviceKM,
1506 IMG_HANDLE hSwapChainRef,
1507 IMG_RECT *psRect)
1508{
1509 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1510 PVRSRV_DC_SWAPCHAIN *psSwapChain;
1511
1512 if(!hDeviceKM || !hSwapChainRef)
1513 {
1514 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcRectKM: Invalid parameters"));
1515 return PVRSRV_ERROR_INVALID_PARAMS;
1516 }
1517
1518 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
1519 psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
1520
1521 return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice,
1522 psSwapChain->hExtSwapChain,
1523 psRect);
1524}
1525
1526
1527IMG_EXPORT
1528PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE hDeviceKM,
1529 IMG_HANDLE hSwapChainRef,
1530 IMG_UINT32 ui32CKColour)
1531{
1532 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1533 PVRSRV_DC_SWAPCHAIN *psSwapChain;
1534
1535 if(!hDeviceKM || !hSwapChainRef)
1536 {
1537 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstColourKeyKM: Invalid parameters"));
1538 return PVRSRV_ERROR_INVALID_PARAMS;
1539 }
1540
1541 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
1542 psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
1543
1544 return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice,
1545 psSwapChain->hExtSwapChain,
1546 ui32CKColour);
1547}
1548
1549
1550IMG_EXPORT
1551PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE hDeviceKM,
1552 IMG_HANDLE hSwapChainRef,
1553 IMG_UINT32 ui32CKColour)
1554{
1555 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1556 PVRSRV_DC_SWAPCHAIN *psSwapChain;
1557
1558 if(!hDeviceKM || !hSwapChainRef)
1559 {
1560 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcColourKeyKM: Invalid parameters"));
1561 return PVRSRV_ERROR_INVALID_PARAMS;
1562 }
1563
1564 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
1565 psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
1566
1567 return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice,
1568 psSwapChain->hExtSwapChain,
1569 ui32CKColour);
1570}
1571
1572
1573IMG_EXPORT
1574PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
1575 IMG_HANDLE hSwapChainRef,
1576 IMG_UINT32 *pui32BufferCount,
1577 IMG_HANDLE *phBuffer,
1578 IMG_SYS_PHYADDR *psPhyAddr)
1579{
1580 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1581 PVRSRV_DC_SWAPCHAIN *psSwapChain;
1582 IMG_HANDLE ahExtBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
1583 PVRSRV_ERROR eError;
1584 IMG_UINT32 i;
1585
1586 if(!hDeviceKM || !hSwapChainRef || !phBuffer || !psPhyAddr)
1587 {
1588 PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCBuffersKM: Invalid parameters"));
1589 return PVRSRV_ERROR_INVALID_PARAMS;
1590 }
1591
1592 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
1593 psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
1594
1595 /* call into the display device driver to get info */
1596 eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice,
1597 psSwapChain->hExtSwapChain,
1598 pui32BufferCount,
1599 ahExtBuffer);
1600
1601 PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
1602
1603 /*
1604 populate the srvkm's buffer structure with the 3rd party buffer handles
1605 and return the services buffer handles
1606 */
1607 for(i=0; i<*pui32BufferCount; i++)
1608 {
1609 psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer = ahExtBuffer[i];
1610 phBuffer[i] = (IMG_HANDLE)&psSwapChain->asBuffer[i];
1611 }
1612
1613#if defined(SUPPORT_GET_DC_BUFFERS_SYS_PHYADDRS)
1614 for(i = 0; i < *pui32BufferCount; i++)
1615 {
1616 IMG_UINT32 ui32ByteSize, ui32TilingStride;
1617 IMG_SYS_PHYADDR *pPhyAddr;
1618 IMG_BOOL bIsContiguous;
1619 IMG_HANDLE hOSMapInfo;
1620 IMG_VOID *pvVAddr;
1621
1622 eError = psDCInfo->psFuncTable->pfnGetBufferAddr(psDCInfo->hExtDevice,
1623 ahExtBuffer[i],
1624 &pPhyAddr,
1625 &ui32ByteSize,
1626 &pvVAddr,
1627 &hOSMapInfo,
1628 &bIsContiguous,
1629 &ui32TilingStride);
1630 if(eError != PVRSRV_OK)
1631 {
1632 break;
1633 }
1634
1635 psPhyAddr[i] = *pPhyAddr;
1636 }
1637#endif /* defined(SUPPORT_GET_DC_BUFFERS_SYS_PHYADDRS) */
1638
1639 return eError;
1640}
1641
1642
1643IMG_EXPORT
1644PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
1645 IMG_HANDLE hBuffer,
1646 IMG_UINT32 ui32SwapInterval,
1647 IMG_HANDLE hPrivateTag,
1648 IMG_UINT32 ui32ClipRectCount,
1649 IMG_RECT *psClipRect)
1650{
1651 PVRSRV_ERROR eError;
1652 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1653 PVRSRV_DC_BUFFER *psBuffer;
1654 PVRSRV_QUEUE_INFO *psQueue;
1655 DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
1656 IMG_UINT32 i;
1657 IMG_BOOL bAddReferenceToLast = IMG_TRUE;
1658 IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
1659 IMG_UINT32 ui32NumSrcSyncs = 1;
1660 PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
1661 PVRSRV_COMMAND *psCommand;
1662 SYS_DATA *psSysData;
1663
1664 if(!hDeviceKM || !hBuffer || !psClipRect)
1665 {
1666 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid parameters"));
1667 return PVRSRV_ERROR_INVALID_PARAMS;
1668 }
1669
1670 psBuffer = (PVRSRV_DC_BUFFER*)hBuffer;
1671 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
1672
1673 /* Validate swap interval against limits */
1674 if(ui32SwapInterval < psBuffer->psSwapChain->ui32MinSwapInterval ||
1675 ui32SwapInterval > psBuffer->psSwapChain->ui32MaxSwapInterval)
1676 {
1677 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid swap interval. Requested %u, Allowed range %u-%u",
1678 ui32SwapInterval, psBuffer->psSwapChain->ui32MinSwapInterval, psBuffer->psSwapChain->ui32MaxSwapInterval));
1679 return PVRSRV_ERROR_INVALID_SWAPINTERVAL;
1680 }
1681
1682#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
1683
1684 if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL)
1685 {
1686 psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice,
1687 psBuffer->psSwapChain->hExtSwapChain,
1688 psBuffer->sDeviceClassBuffer.hExtBuffer,
1689 hPrivateTag,
1690 &ui16SwapCommandID,
1691 &bAddReferenceToLast);
1692
1693 }
1694
1695#endif
1696
1697 /* get the queue from the buffer structure */
1698 psQueue = psBuffer->psSwapChain->psQueue;
1699
1700 /* specify the syncs */
1701 apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo;
1702 if(bAddReferenceToLast && psBuffer->psSwapChain->psLastFlipBuffer &&
1703 psBuffer != psBuffer->psSwapChain->psLastFlipBuffer)
1704 {
1705 apsSrcSync[1] = psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
1706 ui32NumSrcSyncs++;
1707 }
1708
1709 /* insert the command (header) */
1710 eError = PVRSRVInsertCommandKM (psQueue,
1711 &psCommand,
1712 psDCInfo->ui32DeviceID,
1713 ui16SwapCommandID,
1714 0,
1715 IMG_NULL,
1716 ui32NumSrcSyncs,
1717 apsSrcSync,
1718 sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount),
1719 IMG_NULL,
1720 IMG_NULL);
1721 if(eError != PVRSRV_OK)
1722 {
1723 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to get space in queue"));
1724 goto Exit;
1725 }
1726
1727 /* setup the flip command */
1728 psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
1729
1730 /* Ext Device Handle */
1731 psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
1732
1733 /* Ext SwapChain Handle */
1734 psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain;
1735
1736 /* Ext Buffer Handle (Buffer to Flip to) */
1737 psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer;
1738
1739 /* private tag */
1740 psFlipCmd->hPrivateTag = hPrivateTag;
1741
1742 /* setup the clip rects */
1743 psFlipCmd->ui32ClipRectCount = ui32ClipRectCount;
1744 /* cliprect memory appends the command structure */
1745 psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND)); // PRQA S 3305
1746 /* copy the clip rects */
1747 for(i=0; i<ui32ClipRectCount; i++)
1748 {
1749 psFlipCmd->psClipRect[i] = psClipRect[i];
1750 }
1751
1752 /* number of vsyncs between successive flips */
1753 psFlipCmd->ui32SwapInterval = ui32SwapInterval;
1754
1755 SysAcquireData(&psSysData);
1756
1757 /* Because we might be composing just software surfaces, without
1758 * any SGX renders since the last frame, we won't necessarily
1759 * have cleaned/flushed the CPU caches before the buffers need
1760 * to be displayed.
1761 *
1762 * Doing so now is safe because InsertCommand bumped ROP2 on the
1763 * affected buffers (preventing more SW renders starting) but the
1764 * display won't start to process the buffers until SubmitCommand.
1765 */
1766 {
1767 if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
1768 {
1769 OSFlushCPUCacheKM();
1770 }
1771 else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
1772 {
1773 OSCleanCPUCacheKM();
1774 }
1775
1776 psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
1777 }
1778
1779 /* submit the command */
1780 eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
1781 if (eError != PVRSRV_OK)
1782 {
1783 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to submit command"));
1784 goto Exit;
1785 }
1786
1787 /*
1788 Schedule an MISR to process it
1789 */
1790 eError = OSScheduleMISR(psSysData);
1791
1792 if (eError != PVRSRV_OK)
1793 {
1794 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to schedule MISR"));
1795 goto Exit;
1796 }
1797
1798 /* update the last flip buffer */
1799 psBuffer->psSwapChain->psLastFlipBuffer = psBuffer;
1800
1801Exit:
1802
1803 if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
1804 {
1805 eError = PVRSRV_ERROR_RETRY;
1806 }
1807
1808 return eError;
1809}
1810
1811typedef struct _CALLBACK_DATA_
1812{
1813 IMG_PVOID pvPrivData;
1814 IMG_UINT32 ui32PrivDataLength;
1815 IMG_PVOID ppvMemInfos;
1816 IMG_UINT32 ui32NumMemInfos;
1817} CALLBACK_DATA;
1818
1819static IMG_VOID FreePrivateData(IMG_HANDLE hCallbackData)
1820{
1821 CALLBACK_DATA *psCallbackData = hCallbackData;
1822
1823 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psCallbackData->ui32PrivDataLength,
1824 psCallbackData->pvPrivData, IMG_NULL);
1825 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
1826 sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos,
1827 psCallbackData->ppvMemInfos, IMG_NULL);
1828 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), hCallbackData, IMG_NULL);
1829}
1830
1831IMG_EXPORT
1832PVRSRV_ERROR PVRSRVSwapToDCBuffer2KM(IMG_HANDLE hDeviceKM,
1833 IMG_HANDLE hSwapChain,
1834 IMG_UINT32 ui32SwapInterval,
1835 PVRSRV_KERNEL_MEM_INFO **ppsMemInfos,
1836 PVRSRV_KERNEL_SYNC_INFO **ppsSyncInfos,
1837 IMG_UINT32 ui32NumMemSyncInfos,
1838 IMG_PVOID pvPrivData,
1839 IMG_UINT32 ui32PrivDataLength)
1840{
1841 PVRSRV_KERNEL_SYNC_INFO **ppsCompiledSyncInfos;
1842 IMG_UINT32 i, ui32NumCompiledSyncInfos;
1843 DISPLAYCLASS_FLIP_COMMAND2 *psFlipCmd;
1844 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
1845 PVRSRV_DC_SWAPCHAIN *psSwapChain;
1846 PVRSRV_ERROR eError = PVRSRV_OK;
1847 CALLBACK_DATA *psCallbackData;
1848 PVRSRV_QUEUE_INFO *psQueue;
1849 PVRSRV_COMMAND *psCommand;
1850 IMG_PVOID *ppvMemInfos;
1851 SYS_DATA *psSysData;
1852
1853 if(!hDeviceKM || !hSwapChain || !ppsMemInfos || !ppsSyncInfos || ui32NumMemSyncInfos < 1)
1854 {
1855 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid parameters"));
1856 return PVRSRV_ERROR_INVALID_PARAMS;
1857 }
1858
1859 psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChain)->psSwapChain;
1860 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
1861
1862 /* Validate swap interval against limits */
1863 if(ui32SwapInterval < psSwapChain->ui32MinSwapInterval ||
1864 ui32SwapInterval > psSwapChain->ui32MaxSwapInterval)
1865 {
1866 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid swap interval. Requested %u, Allowed range %u-%u",
1867 ui32SwapInterval, psSwapChain->ui32MinSwapInterval, psSwapChain->ui32MaxSwapInterval));
1868 return PVRSRV_ERROR_INVALID_SWAPINTERVAL;
1869 }
1870
1871 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
1872 sizeof(CALLBACK_DATA),
1873 (IMG_VOID **)&psCallbackData, IMG_NULL,
1874 "PVRSRVSwapToDCBuffer2KM callback data");
1875 if (eError != PVRSRV_OK)
1876 {
1877 return eError;
1878 }
1879
1880 psCallbackData->pvPrivData = pvPrivData;
1881 psCallbackData->ui32PrivDataLength = ui32PrivDataLength;
1882
1883 if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
1884 sizeof(IMG_VOID *) * ui32NumMemSyncInfos,
1885 (IMG_VOID **)&ppvMemInfos, IMG_NULL,
1886 "Swap Command Meminfos") != PVRSRV_OK)
1887 {
1888 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
1889 psCallbackData->ppvMemInfos = IMG_NULL;
1890 goto Exit;
1891 }
1892
1893 for(i = 0; i < ui32NumMemSyncInfos; i++)
1894 {
1895 ppvMemInfos[i] = ppsMemInfos[i];
1896 }
1897
1898 psCallbackData->ppvMemInfos = ppvMemInfos;
1899 psCallbackData->ui32NumMemInfos = ui32NumMemSyncInfos;
1900
1901 /* get the queue from the buffer structure */
1902 psQueue = psSwapChain->psQueue;
1903
1904#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
1905 if(psSwapChain->ppsLastSyncInfos)
1906 {
1907 IMG_UINT32 ui32NumUniqueSyncInfos = psSwapChain->ui32LastNumSyncInfos;
1908 IMG_UINT32 j;
1909
1910 for(j = 0; j < psSwapChain->ui32LastNumSyncInfos; j++)
1911 {
1912 for(i = 0; i < ui32NumMemSyncInfos; i++)
1913 {
1914 if(psSwapChain->ppsLastSyncInfos[j] == ppsSyncInfos[i])
1915 {
1916 psSwapChain->ppsLastSyncInfos[j] = IMG_NULL;
1917 ui32NumUniqueSyncInfos--;
1918 }
1919 }
1920 }
1921
1922 ui32NumCompiledSyncInfos = ui32NumMemSyncInfos + ui32NumUniqueSyncInfos;
1923
1924 if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
1925 sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos,
1926 (IMG_VOID **)&ppsCompiledSyncInfos, IMG_NULL,
1927 "Compiled syncinfos") != PVRSRV_OK)
1928 {
1929 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
1930 goto Exit;
1931 }
1932
1933 OSMemCopy(ppsCompiledSyncInfos, ppsSyncInfos, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumMemSyncInfos);
1934 for(j = 0, i = ui32NumMemSyncInfos; j < psSwapChain->ui32LastNumSyncInfos; j++)
1935 {
1936 if(psSwapChain->ppsLastSyncInfos[j])
1937 {
1938 ppsCompiledSyncInfos[i] = psSwapChain->ppsLastSyncInfos[j];
1939 i++;
1940 }
1941 }
1942 }
1943 else
1944#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
1945 {
1946 ppsCompiledSyncInfos = ppsSyncInfos;
1947 ui32NumCompiledSyncInfos = ui32NumMemSyncInfos;
1948 }
1949
1950 /* insert the command (header) */
1951 eError = PVRSRVInsertCommandKM (psQueue,
1952 &psCommand,
1953 psDCInfo->ui32DeviceID,
1954 DC_FLIP_COMMAND,
1955 0,
1956 IMG_NULL,
1957 ui32NumCompiledSyncInfos,
1958 ppsCompiledSyncInfos,
1959 sizeof(DISPLAYCLASS_FLIP_COMMAND2),
1960 FreePrivateData,
1961 psCallbackData);
1962
1963 if (ppsCompiledSyncInfos != ppsSyncInfos)
1964 {
1965 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
1966 sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos,
1967 (IMG_VOID *)ppsCompiledSyncInfos,
1968 IMG_NULL);
1969 }
1970 if(eError != PVRSRV_OK)
1971 {
1972 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to get space in queue"));
1973 goto Exit;
1974 }
1975
1976 /* setup the flip command */
1977 psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND2*)psCommand->pvData;
1978
1979 /* Ext Device Handle */
1980 psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
1981
1982 /* Ext SwapChain Handle */
1983 psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
1984
1985 /* number of vsyncs between successive flips */
1986 psFlipCmd->ui32SwapInterval = ui32SwapInterval;
1987
1988 /* Opaque private data, if supplied */
1989 psFlipCmd->pvPrivData = pvPrivData;
1990 psFlipCmd->ui32PrivDataLength = ui32PrivDataLength;
1991
1992 psFlipCmd->ppsMemInfos = (PDC_MEM_INFO *)ppvMemInfos;
1993 psFlipCmd->ui32NumMemInfos = ui32NumMemSyncInfos;
1994
1995 /* Even though this is "unused", we have to initialize it,
1996 * as the display controller might NULL-test it.
1997 */
1998 psFlipCmd->hUnused = IMG_NULL;
1999
2000 SysAcquireData(&psSysData);
2001
2002 /* Because we might be composing just software surfaces, without
2003 * any SGX renders since the last frame, we won't necessarily
2004 * have cleaned/flushed the CPU caches before the buffers need
2005 * to be displayed.
2006 *
2007 * Doing so now is safe because InsertCommand bumped ROP2 on the
2008 * affected buffers (preventing more SW renders starting) but the
2009 * display won't start to process the buffers until SubmitCommand.
2010 */
2011 {
2012 if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
2013 {
2014 OSFlushCPUCacheKM();
2015 }
2016 else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
2017 {
2018 OSCleanCPUCacheKM();
2019 }
2020
2021 psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
2022 }
2023
2024 /* submit the command */
2025 eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
2026 if (eError != PVRSRV_OK)
2027 {
2028 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to submit command"));
2029 goto Exit;
2030 }
2031
2032 /* The command has been submitted and so psCallbackData will be freed by the callback */
2033 psCallbackData = IMG_NULL;
2034
2035 /*
2036 Schedule an MISR to process it
2037 */
2038 eError = OSScheduleMISR(psSysData);
2039
2040 if (eError != PVRSRV_OK)
2041 {
2042 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to schedule MISR"));
2043 goto Exit;
2044 }
2045
2046#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
2047 /* Reallocate the syncinfo list if it was too small */
2048 if (psSwapChain->ui32LastNumSyncInfos < ui32NumMemSyncInfos)
2049 {
2050 if (psSwapChain->ppsLastSyncInfos)
2051 {
2052 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos,
2053 psSwapChain->ppsLastSyncInfos, IMG_NULL);
2054 }
2055
2056 if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
2057 sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumMemSyncInfos,
2058 (IMG_VOID **)&psSwapChain->ppsLastSyncInfos, IMG_NULL,
2059 "Last syncinfos") != PVRSRV_OK)
2060 {
2061 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
2062 goto Exit;
2063 }
2064 }
2065
2066 psSwapChain->ui32LastNumSyncInfos = ui32NumMemSyncInfos;
2067
2068 for(i = 0; i < ui32NumMemSyncInfos; i++)
2069 {
2070 psSwapChain->ppsLastSyncInfos[i] = ppsSyncInfos[i];
2071 }
2072#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
2073
2074Exit:
2075 if (psCallbackData)
2076 {
2077 if(psCallbackData->ppvMemInfos)
2078 {
2079 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
2080 sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos,
2081 psCallbackData->ppvMemInfos, IMG_NULL);
2082 }
2083 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), psCallbackData, IMG_NULL);
2084 }
2085 if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
2086 {
2087 eError = PVRSRV_ERROR_RETRY;
2088 }
2089
2090 return eError;
2091}
2092
2093
2094IMG_EXPORT
2095PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
2096 IMG_HANDLE hSwapChainRef)
2097{
2098 PVRSRV_ERROR eError;
2099 PVRSRV_QUEUE_INFO *psQueue;
2100 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
2101 PVRSRV_DC_SWAPCHAIN *psSwapChain;
2102 PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
2103 DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
2104 IMG_UINT32 ui32NumSrcSyncs = 1;
2105 PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
2106 PVRSRV_COMMAND *psCommand;
2107 IMG_BOOL bAddReferenceToLast = IMG_TRUE;
2108 IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
2109 SYS_DATA *psSysData;
2110
2111 if(!hDeviceKM || !hSwapChainRef)
2112 {
2113 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Invalid parameters"));
2114 return PVRSRV_ERROR_INVALID_PARAMS;
2115 }
2116
2117 psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
2118 psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef;
2119 psSwapChain = psSwapChainRef->psSwapChain;
2120
2121 /*
2122 If more then 1 reference to the swapchain exist then
2123 ignore any request to swap to the system buffer
2124 */
2125 if (psSwapChain->ui32RefCount > 1)
2126 {
2127 return PVRSRV_OK;
2128 }
2129
2130 /* get the queue from the buffer structure */
2131 psQueue = psSwapChain->psQueue;
2132
2133#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
2134
2135 if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL)
2136 {
2137 psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice,
2138 psSwapChain->hExtSwapChain,
2139 psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer,
2140 0,
2141 &ui16SwapCommandID,
2142 &bAddReferenceToLast);
2143
2144 }
2145
2146#endif
2147
2148 /* specify the syncs */
2149 apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo;
2150 if(bAddReferenceToLast && psSwapChain->psLastFlipBuffer)
2151 {
2152 /* Make sure we don't make a double dependency on the same server */
2153 if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo)
2154 {
2155 apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
2156 ui32NumSrcSyncs++;
2157 }
2158 }
2159
2160 /* insert the command (header) */
2161 eError = PVRSRVInsertCommandKM (psQueue,
2162 &psCommand,
2163 psDCInfo->ui32DeviceID,
2164 ui16SwapCommandID,
2165 0,
2166 IMG_NULL,
2167 ui32NumSrcSyncs,
2168 apsSrcSync,
2169 sizeof(DISPLAYCLASS_FLIP_COMMAND),
2170 IMG_NULL,
2171 IMG_NULL);
2172 if(eError != PVRSRV_OK)
2173 {
2174 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue"));
2175 goto Exit;
2176 }
2177
2178 /* setup the flip command */
2179 psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
2180
2181 /* Ext Device Handle */
2182 psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
2183
2184 /* Ext SwapChain Handle */
2185 psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
2186
2187 /* Ext Buffer Handle (Buffer to Flip to) */
2188 psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer;
2189
2190 /* private tag */
2191 psFlipCmd->hPrivateTag = IMG_NULL;
2192
2193 /* setup the clip rects */
2194 psFlipCmd->ui32ClipRectCount = 0;
2195
2196 psFlipCmd->ui32SwapInterval = 1;
2197
2198 /* submit the command */
2199 eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
2200 if (eError != PVRSRV_OK)
2201 {
2202 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to submit command"));
2203 goto Exit;
2204 }
2205
2206 /* Schedule an MISR to process it */
2207 SysAcquireData(&psSysData);
2208 eError = OSScheduleMISR(psSysData);
2209
2210 if (eError != PVRSRV_OK)
2211 {
2212 PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to schedule MISR"));
2213 goto Exit;
2214 }
2215
2216 /* update the last flip buffer */
2217 psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer;
2218
2219 eError = PVRSRV_OK;
2220
2221Exit:
2222
2223 if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
2224 {
2225 eError = PVRSRV_ERROR_RETRY;
2226 }
2227
2228 return eError;
2229}
2230
2231
2232/*!
2233******************************************************************************
2234
2235 @Function PVRSRVRegisterSystemISRHandler
2236
2237 @Description
2238
2239 registers an external ISR to be called of the back of a system ISR
2240
2241 @Input ppfnISRHandler : ISR pointer
2242
2243 @Input hISRHandlerData : Callback data
2244
2245 @Input ui32ISRSourceMask : ISR Mask
2246
2247 @Input ui32DeviceID : unique device key
2248
2249 @Return PVRSRV_ERROR :
2250
2251******************************************************************************/
2252static
2253PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER pfnISRHandler,
2254 IMG_VOID *pvISRHandlerData,
2255 IMG_UINT32 ui32ISRSourceMask,
2256 IMG_UINT32 ui32DeviceID)
2257{
2258 SYS_DATA *psSysData;
2259 PVRSRV_DEVICE_NODE *psDevNode;
2260
2261 PVR_UNREFERENCED_PARAMETER(ui32ISRSourceMask);
2262
2263 SysAcquireData(&psSysData);
2264
2265 /* Find Dev Node (just using the device id, ignore the class) */
2266 psDevNode = (PVRSRV_DEVICE_NODE*)
2267 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
2268 &MatchDeviceKM_AnyVaCb,
2269 ui32DeviceID,
2270 IMG_TRUE);
2271
2272 if (psDevNode == IMG_NULL)
2273 {
2274 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterSystemISRHandler: Failed to get psDevNode"));
2275 PVR_DBG_BREAK;
2276 return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
2277 }
2278
2279 /* set up data before enabling the ISR */
2280 psDevNode->pvISRData = (IMG_VOID*) pvISRHandlerData;
2281
2282 /* enable the ISR */
2283 psDevNode->pfnDeviceISR = pfnISRHandler;
2284
2285 return PVRSRV_OK;
2286}
2287
2288/*!
2289******************************************************************************
2290
2291 @Function PVRSRVSetDCState_ForEachVaCb
2292
2293 @Description
2294
2295 If the device node is a display, calls its set state function.
2296
2297 @Input psDeviceNode - the device node
2298 va - variable argument list with:
2299 ui32State - the state to be set.
2300
2301******************************************************************************/
2302static
2303IMG_VOID PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
2304{
2305 PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
2306 IMG_UINT32 ui32State;
2307 ui32State = va_arg(va, IMG_UINT32);
2308
2309 if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
2310 {
2311 psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *)psDeviceNode->pvDevice;
2312 if (psDCInfo->psFuncTable->pfnSetDCState && psDCInfo->hExtDevice)
2313 {
2314 psDCInfo->psFuncTable->pfnSetDCState(psDCInfo->hExtDevice, ui32State);
2315 }
2316 }
2317}
2318
2319
2320/*!
2321******************************************************************************
2322
2323 @Function PVRSRVSetDCState
2324
2325 @Description
2326
2327 Calls the display driver(s) to put them into the specified state.
2328
2329 @Input ui32State: new DC state - one of DC_STATE_*
2330
2331******************************************************************************/
2332IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State)
2333{
2334/* PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
2335 PVRSRV_DEVICE_NODE *psDeviceNode; */
2336 SYS_DATA *psSysData;
2337
2338 SysAcquireData(&psSysData);
2339
2340 List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
2341 &PVRSRVSetDCState_ForEachVaCb,
2342 ui32State);
2343}
2344
2345static PVRSRV_ERROR
2346PVRSRVDCMemInfoGetCpuVAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
2347 IMG_CPU_VIRTADDR *pVAddr)
2348{
2349 *pVAddr = psKernelMemInfo->pvLinAddrKM;
2350 return PVRSRV_OK;
2351}
2352
2353static PVRSRV_ERROR
2354PVRSRVDCMemInfoGetCpuPAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
2355 IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr)
2356{
2357 *pPAddr = OSMemHandleToCpuPAddr(psKernelMemInfo->sMemBlk.hOSMemHandle, uByteOffset);
2358 return PVRSRV_OK;
2359}
2360
2361static PVRSRV_ERROR
2362PVRSRVDCMemInfoGetByteSize(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
2363 IMG_SIZE_T *uByteSize)
2364{
2365 *uByteSize = psKernelMemInfo->uAllocSize;
2366 return PVRSRV_OK;
2367}
2368
2369static IMG_BOOL
2370PVRSRVDCMemInfoIsPhysContig(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
2371{
2372 return OSMemHandleIsPhysContig(psKernelMemInfo->sMemBlk.hOSMemHandle);
2373}
2374
2375static PVRSRV_ERROR PVRSRVDCMemInfoGetBvHandle(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo, IMG_VOID **handle)
2376{
2377#if !defined(CONFIG_GCBV)
2378 *handle = NULL;
2379 return PVRSRV_ERROR_NOT_SUPPORTED;
2380#else
2381 *handle = gc_meminfo_to_hndl(psKernelMemInfo);
2382 return PVRSRV_OK;
2383#endif
2384}
2385
2386/*!
2387******************************************************************************
2388
2389 @Function PVRSRVDCMemInfoGetCpuMultiPlanePAddr
2390
2391 @Description returns physical addresses of a multi-plane buffer
2392
2393
2394 @Input psKernelMemInfo - Pointer to Kernel Memory Info structure
2395 puPlaneByteOffsets - requested offset inside the plane.
2396 If the array is a NULL pointer, 0 requested offsets
2397 are assumed for all planes;
2398 pui32NumAddrOffsets - specifying the size of the user array.
2399 If the array is smaller than the number of the planes
2400 for this buffer, the correct size will be set and an
2401 error returned back;
2402
2403@Output pPlanePAddrs - array of plane physical addresses of the returned size
2404 in pui32NumAddrOffsets;
2405 pui32NumAddrOffsets - contains the real number of planes for the buffer;
2406
2407@Return IMG_INT32 : size of the entire buffer or negative number on ERROR
2408
2409******************************************************************************/
2410static IMG_INT32
2411PVRSRVDCMemInfoGetCpuMultiPlanePAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
2412 IMG_SIZE_T* puPlaneByteOffsets, IMG_CPU_PHYADDR* pPlanePAddrs,
2413 IMG_UINT32* pui32NumAddrOffsets)
2414{
2415 IMG_UINT32 aui32PlaneAddressOffsets[PVRSRV_MAX_NUMBER_OF_MM_BUFFER_PLANES];
2416 IMG_INT32 i32Ret;
2417 IMG_UINT32 i;
2418
2419 i32Ret = OSGetMemMultiPlaneInfo(psKernelMemInfo->sMemBlk.hOSMemHandle,
2420 aui32PlaneAddressOffsets,
2421 pui32NumAddrOffsets);
2422
2423 if((i32Ret < 0) || (pPlanePAddrs == IMG_NULL))
2424 return i32Ret;
2425
2426 for (i = 0; i < *pui32NumAddrOffsets; i++)
2427 {
2428 IMG_SIZE_T uiReqByteOffsets = puPlaneByteOffsets ? puPlaneByteOffsets[i] : 0;
2429
2430 uiReqByteOffsets += aui32PlaneAddressOffsets[i];
2431
2432 pPlanePAddrs[i] = OSMemHandleToCpuPAddr(psKernelMemInfo->sMemBlk.hOSMemHandle, uiReqByteOffsets);
2433 }
2434
2435 return i32Ret;
2436}
2437
2438/*!
2439******************************************************************************
2440
2441 @Function PVRGetDisplayClassJTable
2442
2443 @Description
2444
2445 Sets up function table for 3rd party Display Class Device to call through
2446
2447 @Input psJTable : pointer to function pointer table memory
2448
2449 @Return PVRSRV_ERROR :
2450
2451******************************************************************************/
2452IMG_EXPORT
2453IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable)
2454{
2455 psJTable->ui32TableSize = sizeof(PVRSRV_DC_DISP2SRV_KMJTABLE);
2456 psJTable->pfnPVRSRVRegisterDCDevice = &PVRSRVRegisterDCDeviceKM;
2457 psJTable->pfnPVRSRVRemoveDCDevice = &PVRSRVRemoveDCDeviceKM;
2458 psJTable->pfnPVRSRVOEMFunction = &SysOEMFunction;
2459 psJTable->pfnPVRSRVRegisterCmdProcList = &PVRSRVRegisterCmdProcListKM;
2460 psJTable->pfnPVRSRVRemoveCmdProcList = &PVRSRVRemoveCmdProcListKM;
2461#if defined(SUPPORT_MISR_IN_THREAD)
2462 psJTable->pfnPVRSRVCmdComplete = &OSVSyncMISR;
2463#else
2464 psJTable->pfnPVRSRVCmdComplete = &PVRSRVCommandCompleteKM;
2465#endif
2466 psJTable->pfnPVRSRVRegisterSystemISRHandler = &PVRSRVRegisterSystemISRHandler;
2467 psJTable->pfnPVRSRVRegisterPowerDevice = &PVRSRVRegisterPowerDevice;
2468#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
2469 psJTable->pfnPVRSRVFreeCmdCompletePacket = &PVRSRVFreeCommandCompletePacketKM;
2470#endif
2471 psJTable->pfnPVRSRVDCMemInfoGetCpuVAddr = &PVRSRVDCMemInfoGetCpuVAddr;
2472 psJTable->pfnPVRSRVDCMemInfoGetCpuPAddr = &PVRSRVDCMemInfoGetCpuPAddr;
2473 psJTable->pfnPVRSRVDCMemInfoGetByteSize = &PVRSRVDCMemInfoGetByteSize;
2474 psJTable->pfnPVRSRVDCMemInfoIsPhysContig = &PVRSRVDCMemInfoIsPhysContig;
2475 psJTable->pfnPVRSRVDCMemInfoGetBvHandle = &PVRSRVDCMemInfoGetBvHandle;
2476 psJTable->pfnPVRSRVDCMemInfoGetCpuMultiPlanePAddr = PVRSRVDCMemInfoGetCpuMultiPlanePAddr;
2477 return IMG_TRUE;
2478}
2479
2480
2481
2482/******************************************************************************
2483
2484 @Function PVRSRVCloseBCDeviceKM
2485
2486 @Description
2487
2488 Closes a connection to the Buffer Class device
2489
2490 @Input hDeviceKM : device handle
2491
2492 @Return PVRSRV_ERROR :
2493
2494******************************************************************************/
2495IMG_EXPORT
2496PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE hDeviceKM)
2497{
2498 PVRSRV_ERROR eError;
2499 PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
2500
2501 psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
2502
2503 /* Remove the item from the resman list and trigger the callback. */
2504 eError = ResManFreeResByPtr(psBCPerContextInfo->hResItem, CLEANUP_WITH_POLL);
2505
2506 return eError;
2507}
2508
2509
2510static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID pvParam,
2511 IMG_UINT32 ui32Param,
2512 IMG_BOOL bDummy)
2513{
2514 PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
2515 PVRSRV_BUFFERCLASS_INFO *psBCInfo;
2516 IMG_UINT32 i;
2517
2518 PVR_UNREFERENCED_PARAMETER(ui32Param);
2519 PVR_UNREFERENCED_PARAMETER(bDummy);
2520
2521 psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)pvParam;
2522
2523 psBCInfo = psBCPerContextInfo->psBCInfo;
2524
2525 for (i = 0; i < psBCInfo->ui32BufferCount; i++)
2526 {
2527 if (psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount != 0)
2528 {
2529 PVR_DPF((PVR_DBG_ERROR, "CloseBCDeviceCallBack: buffer %d (0x%p) still mapped (ui32MemMapRefCount = %d)",
2530 i,
2531 &psBCInfo->psBuffer[i].sDeviceClassBuffer,
2532 psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount));
2533 return PVRSRV_ERROR_STILL_MAPPED;
2534 }
2535 }
2536
2537 psBCInfo->ui32RefCount--;
2538 if(psBCInfo->ui32RefCount == 0)
2539 {
2540 /* close the external device */
2541 psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->ui32DeviceID, psBCInfo->hExtDevice);
2542
2543 /* free syncinfos */
2544 for(i=0; i<psBCInfo->ui32BufferCount; i++)
2545 {
2546 if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
2547 {
2548 PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
2549 }
2550 }
2551
2552 /* free buffers */
2553 if(psBCInfo->psBuffer)
2554 {
2555 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER) * psBCInfo->ui32BufferCount, psBCInfo->psBuffer, IMG_NULL);
2556 psBCInfo->psBuffer = IMG_NULL;
2557 }
2558 }
2559
2560 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), psBCPerContextInfo, IMG_NULL);
2561 /*not nulling pointer, copy on stack*/
2562
2563 return PVRSRV_OK;
2564}
2565
2566
2567/*!
2568******************************************************************************
2569
2570 @Function PVRSRVOpenBCDeviceKM
2571
2572 @Description
2573
2574 Opens a connection to the Buffer Class device, associating the connection
2575 with a Device Memory Context for a services managed device
2576
2577 @Input psPerProc : Per-process data
2578 @Input ui32DeviceID : unique device index
2579 @Input hDevCookie : devcookie used to derive the Device Memory
2580 Context into BC surfaces will be mapped into
2581 @Outut phDeviceKM : handle to the DC device
2582
2583 @Return PVRSRV_ERROR :
2584
2585******************************************************************************/
2586IMG_EXPORT
2587PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
2588 IMG_UINT32 ui32DeviceID,
2589 IMG_HANDLE hDevCookie,
2590 IMG_HANDLE *phDeviceKM)
2591{
2592 PVRSRV_BUFFERCLASS_INFO *psBCInfo;
2593 PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
2594 PVRSRV_DEVICE_NODE *psDeviceNode;
2595 SYS_DATA *psSysData;
2596 IMG_UINT32 i;
2597 PVRSRV_ERROR eError;
2598
2599 if(!phDeviceKM || !hDevCookie)
2600 {
2601 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Invalid params"));
2602 return PVRSRV_ERROR_INVALID_PARAMS;
2603 }
2604
2605 SysAcquireData(&psSysData);
2606
2607 /* find the matching devicenode */
2608 psDeviceNode = (PVRSRV_DEVICE_NODE*)
2609 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
2610 &MatchDeviceKM_AnyVaCb,
2611 ui32DeviceID,
2612 IMG_FALSE,
2613 PVRSRV_DEVICE_CLASS_BUFFER);
2614 if (!psDeviceNode)
2615 {
2616 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID));
2617 return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
2618 }
2619 psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice;
2620
2621/*
2622FoundDevice:
2623*/
2624 /*
2625 Allocate the per-context BC Info before calling the external device,
2626 to make error handling easier.
2627 */
2628 if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
2629 sizeof(*psBCPerContextInfo),
2630 (IMG_VOID **)&psBCPerContextInfo, IMG_NULL,
2631 "Buffer Class per Context Info") != PVRSRV_OK)
2632 {
2633 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed psBCPerContextInfo alloc"));
2634 return PVRSRV_ERROR_OUT_OF_MEMORY;
2635 }
2636 OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo));
2637
2638 if(psBCInfo->ui32RefCount++ == 0)
2639 {
2640 BUFFER_INFO sBufferInfo;
2641
2642 psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
2643
2644 /* store the device kernel context to map into */
2645 psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
2646
2647 /* open the external device */
2648 eError = psBCInfo->psFuncTable->pfnOpenBCDevice(ui32DeviceID, &psBCInfo->hExtDevice);
2649 if(eError != PVRSRV_OK)
2650 {
2651 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to open external BC device"));
2652 return eError;
2653 }
2654
2655 /* get information about the buffers */
2656 eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo);
2657 if(eError != PVRSRV_OK)
2658 {
2659 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM : Failed to get BC Info"));
2660 return eError;
2661 }
2662
2663 /* interpret and store info */
2664 psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount;
2665
2666 /* allocate BC buffers */
2667 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
2668 sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount,
2669 (IMG_VOID **)&psBCInfo->psBuffer,
2670 IMG_NULL,
2671 "Array of Buffer Class Buffer");
2672 if(eError != PVRSRV_OK)
2673 {
2674 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to allocate BC buffers"));
2675 return eError;
2676 }
2677 OSMemSet (psBCInfo->psBuffer,
2678 0,
2679 sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount);
2680
2681 for(i=0; i<psBCInfo->ui32BufferCount; i++)
2682 {
2683 /* create a syncinfo for the device's system surface */
2684 eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
2685 psBCInfo->hDevMemContext,
2686 &psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
2687 if(eError != PVRSRV_OK)
2688 {
2689 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc"));
2690 goto ErrorExit;
2691 }
2692
2693 /*
2694 get the buffers from the buffer class
2695 drivers by index, passing-in the syncdata objects
2696 */
2697 eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice,
2698 i,
2699 psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData,
2700 &psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtBuffer);
2701 if(eError != PVRSRV_OK)
2702 {
2703 PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to get BC buffers"));
2704 goto ErrorExit;
2705 }
2706
2707 /* setup common device class info */
2708 psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr;
2709 psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext;
2710 psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice;
2711 psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount = 0;
2712 }
2713 }
2714
2715 psBCPerContextInfo->psBCInfo = psBCInfo;
2716 psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
2717 RESMAN_TYPE_BUFFERCLASS_DEVICE,
2718 psBCPerContextInfo,
2719 0,
2720 &CloseBCDeviceCallBack);
2721
2722 /* return a reference to the BCPerContextInfo */
2723 *phDeviceKM = (IMG_HANDLE)psBCPerContextInfo;
2724
2725 return PVRSRV_OK;
2726
2727ErrorExit:
2728
2729 /* free syncinfos */
2730 for(i=0; i<psBCInfo->ui32BufferCount; i++)
2731 {
2732 if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
2733 {
2734 PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
2735 }
2736 }
2737
2738 /* free buffers */
2739 if(psBCInfo->psBuffer)
2740 {
2741 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL);
2742 psBCInfo->psBuffer = IMG_NULL;
2743 }
2744
2745 return eError;
2746}
2747
2748
2749
2750
2751/******************************************************************************
2752
2753 @Function PVRSRVGetBCInfoKM
2754
2755 @Description
2756
2757 Gets Buffer Class device Info
2758
2759 @Input hDeviceKM : device handle
2760 @Output psBufferInfo
2761
2762 @Return PVRSRV_ERROR :
2763
2764******************************************************************************/
2765IMG_EXPORT
2766PVRSRV_ERROR PVRSRVGetBCInfoKM (IMG_HANDLE hDeviceKM,
2767 BUFFER_INFO *psBufferInfo)
2768{
2769 PVRSRV_BUFFERCLASS_INFO *psBCInfo;
2770 PVRSRV_ERROR eError;
2771
2772 if(!hDeviceKM || !psBufferInfo)
2773 {
2774 PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM: Invalid parameters"));
2775 return PVRSRV_ERROR_INVALID_PARAMS;
2776 }
2777
2778 psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
2779
2780 eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, psBufferInfo);
2781
2782 if(eError != PVRSRV_OK)
2783 {
2784 PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM : Failed to get BC Info"));
2785 return eError;
2786 }
2787
2788 return PVRSRV_OK;
2789}
2790
2791
2792/******************************************************************************
2793
2794 @Function PVRSRVGetBCBufferKM
2795
2796 @Description
2797
2798 Gets Buffer Class Buffer Handle
2799
2800 @Input hDeviceKM : device handle
2801 @Output psBufferInfo
2802
2803 @Return PVRSRV_ERROR :
2804
2805******************************************************************************/
2806IMG_EXPORT
2807PVRSRV_ERROR PVRSRVGetBCBufferKM (IMG_HANDLE hDeviceKM,
2808 IMG_UINT32 ui32BufferIndex,
2809 IMG_HANDLE *phBuffer)
2810{
2811 PVRSRV_BUFFERCLASS_INFO *psBCInfo;
2812
2813 if(!hDeviceKM || !phBuffer)
2814 {
2815 PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Invalid parameters"));
2816 return PVRSRV_ERROR_INVALID_PARAMS;
2817 }
2818
2819 psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
2820
2821 if(ui32BufferIndex < psBCInfo->ui32BufferCount)
2822 {
2823 *phBuffer = (IMG_HANDLE)&psBCInfo->psBuffer[ui32BufferIndex];
2824 }
2825 else
2826 {
2827 PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Buffer index %d out of range (%d)", ui32BufferIndex,psBCInfo->ui32BufferCount));
2828 return PVRSRV_ERROR_INVALID_PARAMS;
2829 }
2830
2831 return PVRSRV_OK;
2832}
2833
2834
2835/*!
2836******************************************************************************
2837
2838 @Function PVRGetBufferClassJTable
2839
2840 @Description
2841
2842 Sets up function table for 3rd party Buffer Class Device to call through
2843
2844 @Input psJTable : pointer to function pointer table memory
2845
2846 @Return PVRSRV_ERROR :
2847
2848******************************************************************************/
2849IMG_EXPORT
2850IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable)
2851{
2852 psJTable->ui32TableSize = sizeof(PVRSRV_BC_BUFFER2SRV_KMJTABLE);
2853
2854 psJTable->pfnPVRSRVRegisterBCDevice = &PVRSRVRegisterBCDeviceKM;
2855 psJTable->pfnPVRSRVScheduleDevices = &PVRSRVScheduleDevicesKM;
2856 psJTable->pfnPVRSRVRemoveBCDevice = &PVRSRVRemoveBCDeviceKM;
2857
2858 return IMG_TRUE;
2859}
2860
2861/******************************************************************************
2862 End of file (deviceclass.c)
2863******************************************************************************/