ac8e1e3f81a1c175e443ff98f7df81402a3bda3d
[android-sdk/device-ti-proprietary-open.git] / jacinto6 / sgx_src / eurasia_km / services4 / srvkm / common / pvrsrv.c
1 /*************************************************************************/ /*!
2 @Title core services functions
3 @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
4 @Description Main APIs for core services functions
5 @License Dual MIT/GPLv2
7 The contents of this file are subject to the MIT license as set out below.
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
19 Alternatively, the contents of this file may be used under the terms of
20 the GNU General Public License Version 2 ("GPL") in which case the provisions
21 of GPL are applicable instead of those above.
23 If you wish to allow use of your version of this file only under the terms of
24 GPL, and not to allow others to use your version of this file under the terms
25 of the MIT license, indicate your decision by deleting the provisions above
26 and replace them with the notice and other provisions required by GPL as set
27 out in the file called "GPL-COPYING" included in this distribution. If you do
28 not delete the provisions above, a recipient may use your version of this file
29 under the terms of either the MIT license or GPL.
31 This License is also included in this distribution in the file called
32 "MIT-COPYING".
34 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
35 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
36 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
37 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
38 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
39 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
40 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41 */ /**************************************************************************/
43 #include "services_headers.h"
44 #include "buffer_manager.h"
45 #include "pvr_bridge_km.h"
46 #include "handle.h"
47 #include "perproc.h"
48 #include "pdump_km.h"
49 #include "deviceid.h"
50 #include "ra.h"
51 #if defined(TTRACE)
52 #include "ttrace.h"
53 #endif
54 #include "perfkm.h"
55 #include "devicemem.h"
57 #include "pvrversion.h"
59 #include "lists.h"
61 IMG_UINT32 g_ui32InitFlags;
63 /* mark which parts of Services were initialised */
64 #define INIT_DATA_ENABLE_PDUMPINIT 0x1U
65 #define INIT_DATA_ENABLE_TTRACE 0x2U
66 #define INIT_DATA_ENABLE_DEVMEM 0x4U
68 /*!
69 ******************************************************************************
71 @Function AllocateDeviceID
73 @Description
75 allocates a device id from the pool of valid ids
77 @input psSysData : system data
79 @input pui32DevID : device id to return
81 @Return device id
83 ******************************************************************************/
84 PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID)
85 {
86 SYS_DEVICE_ID* psDeviceWalker;
87 SYS_DEVICE_ID* psDeviceEnd;
89 psDeviceWalker = &psSysData->sDeviceID[0];
90 psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
92 /* find a free ID */
93 while (psDeviceWalker < psDeviceEnd)
94 {
95 if (!psDeviceWalker->bInUse)
96 {
97 psDeviceWalker->bInUse = IMG_TRUE;
98 *pui32DevID = psDeviceWalker->uiID;
99 return PVRSRV_OK;
100 }
101 psDeviceWalker++;
102 }
104 PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!"));
106 /* Should never get here: sDeviceID[] may have been setup too small */
107 PVR_ASSERT(psDeviceWalker < psDeviceEnd);
109 return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE;
110 }
113 /*!
114 ******************************************************************************
116 @Function FreeDeviceID
118 @Description
120 frees a device id from the pool of valid ids
122 @input psSysData : system data
124 @input ui32DevID : device id to free
126 @Return device id
128 ******************************************************************************/
129 PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID)
130 {
131 SYS_DEVICE_ID* psDeviceWalker;
132 SYS_DEVICE_ID* psDeviceEnd;
134 psDeviceWalker = &psSysData->sDeviceID[0];
135 psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
137 /* find the ID to free */
138 while (psDeviceWalker < psDeviceEnd)
139 {
140 /* if matching id and in use, free */
141 if (
142 (psDeviceWalker->uiID == ui32DevID) &&
143 (psDeviceWalker->bInUse)
144 )
145 {
146 psDeviceWalker->bInUse = IMG_FALSE;
147 return PVRSRV_OK;
148 }
149 psDeviceWalker++;
150 }
152 PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
154 /* should never get here */
155 PVR_ASSERT(psDeviceWalker < psDeviceEnd);
157 return PVRSRV_ERROR_INVALID_DEVICEID;
158 }
159 /*!
160 ******************************************************************************
162 @Function PVRSRVCompatCheckKM
164 @Description UM/KM ddk branch Compatibility check function
166 @input psUserModeDDKDetails: User mode DDK version
168 @output In case of incompatibility, returns PVRSRV_ERROR_DDK_VERSION_MISMATCH
170 @Return PVRSRV_ERROR
172 ******************************************************************************/
173 IMG_VOID IMG_CALLCONV PVRSRVCompatCheckKM(PVRSRV_BRIDGE_IN_COMPAT_CHECK *psUserModeDDKDetails, PVRSRV_BRIDGE_RETURN *psRetOUT)
174 {
176 if(psUserModeDDKDetails->ui32DDKVersion != ((PVRVERSION_MAJ << 16) | (PVRVERSION_MIN << 8))
177 || (psUserModeDDKDetails->ui32DDKBuild != PVRVERSION_BUILD))
178 {
179 psRetOUT->eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
180 PVR_LOG(("(FAIL) UM-KM DDK Mismatch UM-(%d) KM-(%d).",
181 psUserModeDDKDetails->ui32DDKBuild, PVRVERSION_BUILD));
182 }
183 else
184 {
185 psRetOUT->eError = PVRSRV_OK;
186 PVR_LOG(("UM DDK-(%d) and KM DDK-(%d) match. [ OK ]",
187 psUserModeDDKDetails->ui32DDKBuild ,PVRVERSION_BUILD));
188 }
189 }
191 /*!
192 ******************************************************************************
194 @Function ReadHWReg
196 @Description
198 register access function
200 @input pvLinRegBaseAddr : lin addr of register block base
202 @input ui32Offset : byte offset from register base
204 @Return register value
206 ******************************************************************************/
207 #ifndef ReadHWReg
208 IMG_EXPORT
209 IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
210 {
211 return *(volatile IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset);
212 }
213 #endif
216 /*!
217 ******************************************************************************
219 @Function WriteHWReg
221 @Description
223 register access function
225 @input pvLinRegBaseAddr : lin addr of register block base
227 @input ui32Offset : byte offset from register base
229 @input ui32Value : value to write to register
231 @Return register value : original reg. value
233 ******************************************************************************/
234 #ifndef WriteHWReg
235 IMG_EXPORT
236 IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
237 {
238 PVR_DPF((PVR_DBG_MESSAGE,"WriteHWReg Base:%p, Offset: %x, Value %x",
239 pvLinRegBaseAddr,ui32Offset,ui32Value));
241 *(IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset) = ui32Value;
242 }
243 #endif
246 /*!
247 ******************************************************************************
249 @Function WriteHWRegs
251 @Description
253 register access function
255 @input pvLinRegBaseAddr : lin addr of register block base
257 @input ui32Count : register count
259 @input psHWRegs : address/value register list
261 @Return none
263 ******************************************************************************/
264 #ifndef WriteHWRegs
265 IMG_EXPORT
266 IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs)
267 {
268 while (ui32Count)
269 {
270 WriteHWReg (pvLinRegBaseAddr, psHWRegs->ui32RegAddr, psHWRegs->ui32RegVal);
271 psHWRegs++;
272 ui32Count--;
273 }
274 }
275 #endif
277 /*!
278 ******************************************************************************
279 @Function PVRSRVEnumerateDCKM_ForEachVaCb
281 @Description
283 Enumerates the device node (if is of the same class as given).
285 @Input psDeviceNode - The device node to be enumerated
286 va - variable arguments list, with:
287 pui32DevCount - The device count pointer (to be increased)
288 ppui32DevID - The pointer to the device IDs pointer (to be updated and increased)
289 ******************************************************************************/
290 static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
291 {
292 IMG_UINT *pui32DevCount;
293 PVRSRV_DEVICE_IDENTIFIER **ppsDevIdList;
295 pui32DevCount = va_arg(va, IMG_UINT*);
296 ppsDevIdList = va_arg(va, PVRSRV_DEVICE_IDENTIFIER**);
298 if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT)
299 {
300 *(*ppsDevIdList) = psDeviceNode->sDevId;
301 (*ppsDevIdList)++;
302 (*pui32DevCount)++;
303 }
304 }
308 /*!
309 ******************************************************************************
311 @Function PVRSRVEnumerateDevicesKM
313 @Description
314 This function will enumerate all the devices supported by the
315 PowerVR services within the target system.
316 The function returns a list of the device ID strcutres stored either in
317 the services or constructed in the user mode glue component in certain
318 environments. The number of devices in the list is also returned.
320 In a binary layered component which does not support dynamic runtime selection,
321 the glue code should compile to return the supported devices statically,
322 e.g. multiple instances of the same device if multiple devices are supported,
323 or the target combination of MBX and display device.
325 In the case of an environment (for instance) where one MBX1 may connect to two
326 display devices this code would enumerate all three devices and even
327 non-dynamic MBX1 selection code should retain the facility to parse the list
328 to find the index of the MBX device
330 @output pui32NumDevices : On success, contains the number of devices present
331 in the system
333 @output psDevIdList : Pointer to called supplied buffer to receive the
334 list of PVRSRV_DEVICE_IDENTIFIER
336 @return PVRSRV_ERROR : PVRSRV_NO_ERROR
338 ******************************************************************************/
339 IMG_EXPORT
340 PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
341 PVRSRV_DEVICE_IDENTIFIER *psDevIdList)
342 {
343 SYS_DATA *psSysData;
344 /* PVRSRV_DEVICE_NODE *psDeviceNode; */
345 IMG_UINT32 i;
347 if (!pui32NumDevices || !psDevIdList)
348 {
349 PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params"));
350 return PVRSRV_ERROR_INVALID_PARAMS;
351 }
353 SysAcquireData(&psSysData);
355 /*
356 setup input buffer to be `empty'
357 */
358 for (i=0; i<PVRSRV_MAX_DEVICES; i++)
359 {
360 psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
361 }
363 /* and zero device count */
364 *pui32NumDevices = 0;
366 /*
367 Search through the device list for services managed devices
368 return id info for each device and the number of devices
369 available
370 */
371 List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
372 &PVRSRVEnumerateDevicesKM_ForEachVaCb,
373 pui32NumDevices,
374 &psDevIdList);
377 return PVRSRV_OK;
378 }
381 /*!
382 ******************************************************************************
384 @Function PVRSRVInit
386 @Description Initialise services
388 @Input psSysData : sysdata structure
390 @Return PVRSRV_ERROR :
392 ******************************************************************************/
393 PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
394 {
395 PVRSRV_ERROR eError;
397 /* Initialise Resource Manager */
398 eError = ResManInit();
399 if (eError != PVRSRV_OK)
400 {
401 goto Error;
402 }
404 eError = PVRSRVPerProcessDataInit();
405 if(eError != PVRSRV_OK)
406 {
407 goto Error;
408 }
410 /* Initialise handles */
411 eError = PVRSRVHandleInit();
412 if(eError != PVRSRV_OK)
413 {
414 goto Error;
415 }
417 /* Initialise Power Manager Lock */
418 eError = OSCreateResource(&psSysData->sPowerStateChangeResource);
419 if (eError != PVRSRV_OK)
420 {
421 goto Error;
422 }
424 /* Initialise system power state */
425 psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
426 psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
428 /* Create an event object */
429 if((eError = OSAllocMem( PVRSRV_PAGEABLE_SELECT,
430 sizeof(PVRSRV_EVENTOBJECT) ,
431 (IMG_VOID **)&psSysData->psGlobalEventObject, 0,
432 "Event Object")) != PVRSRV_OK)
433 {
435 goto Error;
436 }
438 if((eError = OSEventObjectCreateKM("PVRSRV_GLOBAL_EVENTOBJECT", psSysData->psGlobalEventObject)) != PVRSRV_OK)
439 {
440 goto Error;
441 }
443 /* Store OS high res timer fallbacks, the system is free to overide these */
444 psSysData->pfnHighResTimerCreate = OSFuncHighResTimerCreate;
445 psSysData->pfnHighResTimerGetus = OSFuncHighResTimerGetus;
446 psSysData->pfnHighResTimerDestroy = OSFuncHighResTimerDestroy;
448 #if defined(TTRACE)
449 eError = PVRSRVTimeTraceInit();
450 if (eError != PVRSRV_OK)
451 goto Error;
452 g_ui32InitFlags |= INIT_DATA_ENABLE_TTRACE;
453 #endif
455 #if defined(PDUMP)
456 /* Initialise pdump */
457 PDUMPINIT();
458 g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT;
459 #endif
461 #if defined(SUPPORT_ION)
462 eError = PVRSRVInitDeviceMem();
463 if (eError != PVRSRV_OK)
464 goto Error;
465 g_ui32InitFlags |= INIT_DATA_ENABLE_DEVMEM;
466 #endif
468 PERFINIT();
469 return eError;
471 Error:
472 PVRSRVDeInit(psSysData);
473 return eError;
474 }
478 /*!
479 ******************************************************************************
481 @Function PVRSRVDeInit
483 @Description De-Initialise services
485 @Input psSysData : sysdata structure
487 @Return PVRSRV_ERROR :
489 ******************************************************************************/
490 IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
491 {
492 PVRSRV_ERROR eError;
494 PVR_UNREFERENCED_PARAMETER(psSysData);
496 if (psSysData == IMG_NULL)
497 {
498 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param"));
499 return;
500 }
502 PERFDEINIT();
505 #if defined(SUPPORT_ION)
506 if ((g_ui32InitFlags & INIT_DATA_ENABLE_DEVMEM) > 0)
507 {
508 PVRSRVDeInitDeviceMem();
509 }
510 #endif
512 #if defined(MEM_TRACK_INFO_DEBUG)
513 /* Free the list of memory operations */
514 PVRSRVFreeMemOps();
515 #endif
517 #if defined(TTRACE)
518 /* deinitialise ttrace */
519 if ((g_ui32InitFlags & INIT_DATA_ENABLE_TTRACE) > 0)
520 {
521 PVRSRVTimeTraceDeinit();
522 }
523 #endif
525 #if defined(PDUMP)
526 /* deinitialise pdump */
527 if( (g_ui32InitFlags & INIT_DATA_ENABLE_PDUMPINIT) > 0)
528 {
529 PDUMPDEINIT();
530 }
531 #endif
533 /* destroy event object */
534 if(psSysData->psGlobalEventObject)
535 {
536 OSEventObjectDestroyKM(psSysData->psGlobalEventObject);
537 OSFreeMem( PVRSRV_PAGEABLE_SELECT,
538 sizeof(PVRSRV_EVENTOBJECT),
539 psSysData->psGlobalEventObject,
540 0);
541 psSysData->psGlobalEventObject = IMG_NULL;
542 }
544 eError = PVRSRVHandleDeInit();
545 if (eError != PVRSRV_OK)
546 {
547 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed"));
548 }
550 eError = PVRSRVPerProcessDataDeInit();
551 if (eError != PVRSRV_OK)
552 {
553 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed"));
554 }
556 ResManDeInit();
557 }
560 /*!
561 ******************************************************************************
563 @Function PVRSRVRegisterDevice
565 @Description
567 registers a device with the system
569 @Input psSysData : sysdata structure
571 @Input pfnRegisterDevice : device registration function
573 @Input ui32SOCInterruptBit : SoC interrupt bit for this device
575 @Output pui32DeviceIndex : unique device key (for case of multiple identical devices)
577 @Return PVRSRV_ERROR :
579 ******************************************************************************/
580 PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
581 PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
582 IMG_UINT32 ui32SOCInterruptBit,
583 IMG_UINT32 *pui32DeviceIndex)
584 {
585 PVRSRV_ERROR eError;
586 PVRSRV_DEVICE_NODE *psDeviceNode;
588 /* Allocate device node */
589 if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
590 sizeof(PVRSRV_DEVICE_NODE),
591 (IMG_VOID **)&psDeviceNode, IMG_NULL,
592 "Device Node") != PVRSRV_OK)
593 {
594 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode"));
595 return (PVRSRV_ERROR_OUT_OF_MEMORY);
596 }
597 OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
599 eError = pfnRegisterDevice(psDeviceNode);
600 if (eError != PVRSRV_OK)
601 {
602 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
603 sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
604 /*not nulling pointer, out of scope*/
605 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
606 return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED);
607 }
609 /*
610 make the refcount 1 and test on this to initialise device
611 at acquiredevinfo. On release if refcount is 1, deinitialise
612 and when refcount is 0 (sysdata de-alloc) deallocate the device
613 structures
614 */
615 psDeviceNode->ui32RefCount = 1;
616 psDeviceNode->psSysData = psSysData;
617 psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
619 /* all devices need a unique identifier */
620 AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
622 /* and finally insert the device into the dev-list */
623 List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
625 /* and copy back index */
626 *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
628 return PVRSRV_OK;
629 }
632 /*!
633 ******************************************************************************
635 @Function PVRSRVInitialiseDevice
637 @Description
639 initialises device by index
641 @Input ui32DevIndex : Index to the required device
643 @Return PVRSRV_ERROR :
645 ******************************************************************************/
646 PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
647 {
648 PVRSRV_DEVICE_NODE *psDeviceNode;
649 SYS_DATA *psSysData;
650 PVRSRV_ERROR eError;
652 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice"));
654 SysAcquireData(&psSysData);
656 /* Find device in the list */
657 psDeviceNode = (PVRSRV_DEVICE_NODE*)
658 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
659 &MatchDeviceKM_AnyVaCb,
660 ui32DevIndex,
661 IMG_TRUE);
662 if(!psDeviceNode)
663 {
664 /* Devinfo not in the list */
665 PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: requested device is not present"));
666 return PVRSRV_ERROR_INIT_FAILURE;
667 }
668 /*
669 FoundDevice:
670 */
672 PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
674 /*
675 Create the device's resource manager context.
676 */
677 eError = PVRSRVResManConnect(IMG_NULL, &psDeviceNode->hResManContext);
678 if (eError != PVRSRV_OK)
679 {
680 PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed PVRSRVResManConnect call"));
681 return eError;
682 }
684 /* Initialise the device */
685 if(psDeviceNode->pfnInitDevice != IMG_NULL)
686 {
687 eError = psDeviceNode->pfnInitDevice(psDeviceNode);
688 if (eError != PVRSRV_OK)
689 {
690 PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed InitDevice call"));
691 return eError;
692 }
693 }
695 return PVRSRV_OK;
696 }
699 static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
700 {
701 PVRSRV_ERROR eError;
703 eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
704 if (eError != PVRSRV_OK)
705 {
706 PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVPowerLock call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
707 return eError;
708 }
710 eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
711 PVRSRV_DEV_POWER_STATE_DEFAULT);
712 PVRSRVPowerUnlock(KERNEL_ID);
713 if (eError != PVRSRV_OK)
714 {
715 PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
716 }
717 return eError;
718 }
720 /*wraps the PVRSRVDevInitCompatCheck call and prints a debugging message if failed*/
721 static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
722 {
723 PVRSRV_ERROR eError;
724 eError = PVRSRVDevInitCompatCheck(psDeviceNode);
725 if (eError != PVRSRV_OK)
726 {
727 PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
728 }
729 return eError;
730 }
733 /*!
734 ******************************************************************************
736 @Function PVRSRVFinaliseSystem
738 @Description
740 Final part of system initialisation.
742 @Input ui32DevIndex : Index to the required device
744 @Return PVRSRV_ERROR :
746 ******************************************************************************/
747 PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
748 {
749 /* PVRSRV_DEVICE_NODE *psDeviceNode;*/
750 SYS_DATA *psSysData;
751 PVRSRV_ERROR eError;
753 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
755 SysAcquireData(&psSysData);
757 if (bInitSuccessful)
758 {
759 eError = SysFinalise();
760 if (eError != PVRSRV_OK)
761 {
762 PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: SysFinalise failed (%d)", eError));
763 return eError;
764 }
766 /* Place all devices into their default power state. */
767 eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
768 &PVRSRVFinaliseSystem_SetPowerState_AnyCb);
769 if (eError != PVRSRV_OK)
770 {
771 return eError;
772 }
774 /* Verify microkernel compatibility for devices */
775 eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
776 &PVRSRVFinaliseSystem_CompatCheck_AnyCb);
777 if (eError != PVRSRV_OK)
778 {
779 return eError;
780 }
781 }
783 /* Some platforms call this too early in the boot phase. */
784 PDUMPENDINITPHASE();
786 return PVRSRV_OK;
787 }
790 PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
791 {
792 /* Only check devices which specify a compatibility check callback */
793 if (psDeviceNode->pfnInitDeviceCompatCheck)
794 return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
795 else
796 return PVRSRV_OK;
797 }
799 /*!
800 ******************************************************************************
802 @Function PVRSRVAcquireDeviceDataKM
804 @Description
806 Matchs a device given a device type and a device index.
808 @input psDeviceNode :The device node to be matched.
810 @Input va : Variable argument list with:
811 eDeviceType : Required device type. If type is unknown use ui32DevIndex
812 to locate device data
814 ui32DevIndex : Index to the required device obtained from the
815 PVRSRVEnumerateDevice function
817 @Return PVRSRV_ERROR :
819 ******************************************************************************/
820 static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
821 {
822 PVRSRV_DEVICE_TYPE eDeviceType;
823 IMG_UINT32 ui32DevIndex;
825 eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE);
826 ui32DevIndex = va_arg(va, IMG_UINT32);
828 if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN &&
829 psDeviceNode->sDevId.eDeviceType == eDeviceType) ||
830 (eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN &&
831 psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex))
832 {
833 return psDeviceNode;
834 }
835 else
836 {
837 return IMG_NULL;
838 }
839 }
841 /*!
842 ******************************************************************************
844 @Function PVRSRVAcquireDeviceDataKM
846 @Description
848 Returns device information
850 @Input ui32DevIndex : Index to the required device obtained from the
851 PVRSRVEnumerateDevice function
853 @Input eDeviceType : Required device type. If type is unknown use ui32DevIndex
854 to locate device data
856 @Output *phDevCookie : Dev Cookie
859 @Return PVRSRV_ERROR :
861 ******************************************************************************/
862 IMG_EXPORT
863 PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex,
864 PVRSRV_DEVICE_TYPE eDeviceType,
865 IMG_HANDLE *phDevCookie)
866 {
867 PVRSRV_DEVICE_NODE *psDeviceNode;
868 SYS_DATA *psSysData;
870 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
872 SysAcquireData(&psSysData);
874 /* Find device in the list */
875 psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
876 &PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
877 eDeviceType,
878 ui32DevIndex);
881 if (!psDeviceNode)
882 {
883 /* device can't be found in the list so it isn't in the system */
884 PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
885 return PVRSRV_ERROR_INIT_FAILURE;
886 }
888 /*FoundDevice:*/
890 PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
892 /* return the dev cookie? */
893 if (phDevCookie)
894 {
895 *phDevCookie = (IMG_HANDLE)psDeviceNode;
896 }
898 return PVRSRV_OK;
899 }
902 /*!
903 ******************************************************************************
905 @Function PVRSRVDeinitialiseDevice
907 @Description
909 This De-inits device
911 @Input ui32DevIndex : Index to the required device
913 @Return PVRSRV_ERROR :
915 ******************************************************************************/
916 PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
917 {
918 PVRSRV_DEVICE_NODE *psDeviceNode;
919 SYS_DATA *psSysData;
920 PVRSRV_ERROR eError;
922 SysAcquireData(&psSysData);
924 psDeviceNode = (PVRSRV_DEVICE_NODE*)
925 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
926 &MatchDeviceKM_AnyVaCb,
927 ui32DevIndex,
928 IMG_TRUE);
930 if (!psDeviceNode)
931 {
932 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: requested device %d is not present", ui32DevIndex));
933 return PVRSRV_ERROR_DEVICEID_NOT_FOUND;
934 }
936 eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
937 if (eError != PVRSRV_OK)
938 {
939 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVPowerLock call"));
940 return eError;
941 }
943 /*
944 Power down the device if necessary.
945 */
946 eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
947 PVRSRV_DEV_POWER_STATE_OFF);
948 PVRSRVPowerUnlock(KERNEL_ID);
949 if (eError != PVRSRV_OK)
950 {
951 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call"));
952 return eError;
953 }
955 /*
956 Free the dissociated device memory.
957 */
958 eError = ResManFreeResByCriteria(psDeviceNode->hResManContext,
959 RESMAN_CRITERIA_RESTYPE,
960 RESMAN_TYPE_DEVICEMEM_ALLOCATION,
961 IMG_NULL, 0);
962 if (eError != PVRSRV_OK)
963 {
964 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call"));
965 return eError;
966 }
968 /*
969 De-init the device.
970 */
971 if(psDeviceNode->pfnDeInitDevice != IMG_NULL)
972 {
973 eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
974 if (eError != PVRSRV_OK)
975 {
976 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed DeInitDevice call"));
977 return eError;
978 }
979 }
981 /*
982 Close the device's resource manager context.
983 */
984 PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE);
985 psDeviceNode->hResManContext = IMG_NULL;
987 /* remove node from list */
988 List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
990 /* deallocate id and memory */
991 (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
992 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
993 sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
994 /*not nulling pointer, out of scope*/
996 return (PVRSRV_OK);
997 }
1000 IMG_EXPORT
1001 PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr,
1002 IMG_UINT32 ui32Value,
1003 IMG_UINT32 ui32Mask,
1004 IMG_UINT32 ui32Timeoutus,
1005 IMG_UINT32 ui32PollPeriodus,
1006 IMG_BOOL bAllowPreemption)
1007 {
1008 #if defined (EMULATOR)
1009 {
1010 PVR_UNREFERENCED_PARAMETER(bAllowPreemption);
1011 #if !defined(__linux__)
1012 PVR_UNREFERENCED_PARAMETER(ui32PollPeriodus);
1013 #endif
1015 /* For the Emulator we want the system to stop when a lock-up is detected so the state can be analysed.
1016 * Also the Emulator is much slower than real silicon so timeouts are not valid.
1017 */
1018 do
1019 {
1020 if((*pui32LinMemAddr & ui32Mask) == ui32Value)
1021 {
1022 return PVRSRV_OK;
1023 }
1025 #if defined(__linux__)
1026 OSWaitus(ui32PollPeriodus);
1027 #else
1028 OSReleaseThreadQuanta();
1029 #endif
1031 } while (ui32Timeoutus); /* Endless loop only for the Emulator */
1032 }
1033 #else
1034 {
1035 IMG_UINT32 ui32ActualValue = 0xFFFFFFFFU; /* Initialiser only required to prevent incorrect warning */
1037 if (bAllowPreemption)
1038 {
1039 PVR_ASSERT(ui32PollPeriodus >= 1000);
1040 }
1042 /* PRQA S 3415,4109 1 */ /* macro format critical - leave alone */
1043 LOOP_UNTIL_TIMEOUT(ui32Timeoutus)
1044 {
1045 ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
1046 if(ui32ActualValue == ui32Value)
1047 {
1048 return PVRSRV_OK;
1049 }
1051 if (bAllowPreemption)
1052 {
1053 OSSleepms(ui32PollPeriodus / 1000);
1054 }
1055 else
1056 {
1057 OSWaitus(ui32PollPeriodus);
1058 }
1059 } END_LOOP_UNTIL_TIMEOUT();
1061 PVR_DPF((PVR_DBG_ERROR,"PollForValueKM: Timeout. Expected 0x%x but found 0x%x (mask 0x%x).",
1062 ui32Value, ui32ActualValue, ui32Mask));
1063 }
1064 #endif /* #if defined (EMULATOR) */
1066 return PVRSRV_ERROR_TIMEOUT;
1067 }
1070 /*Level 3 of the loop nesting*/
1071 static IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
1072 {
1073 IMG_CHAR **ppszStr;
1074 IMG_UINT32 *pui32StrLen;
1075 IMG_UINT32 ui32Mode;
1076 PVRSRV_ERROR (*pfnGetStats)(RA_ARENA *, IMG_CHAR **, IMG_UINT32 *);
1078 ppszStr = va_arg(va, IMG_CHAR**);
1079 pui32StrLen = va_arg(va, IMG_UINT32*);
1080 ui32Mode = va_arg(va, IMG_UINT32);
1082 /* Would be better to pass fn pointer in the variable args list
1083 * but MS C compiler complains with error C2066: In ANSI C,
1084 * it is not legal to cast between a function pointer and a data pointer.
1085 */
1086 switch(ui32Mode)
1087 {
1088 case PVRSRV_MISC_INFO_MEMSTATS_PRESENT:
1089 pfnGetStats = &RA_GetStats;
1090 break;
1091 case PVRSRV_MISC_INFO_FREEMEM_PRESENT:
1092 pfnGetStats = &RA_GetStatsFreeMem;
1093 break;
1094 default:
1095 return;
1096 }
1098 if(psBMHeap->pImportArena)
1099 {
1100 pfnGetStats(psBMHeap->pImportArena,
1101 ppszStr,
1102 pui32StrLen);
1103 }
1105 if(psBMHeap->pVMArena)
1106 {
1107 pfnGetStats(psBMHeap->pVMArena,
1108 ppszStr,
1109 pui32StrLen);
1110 }
1111 }
1113 /*Level 2 of the loop nesting*/
1114 static PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va)
1115 {
1117 IMG_UINT32 *pui32StrLen;
1118 IMG_INT32 *pi32Count;
1119 IMG_CHAR **ppszStr;
1120 IMG_UINT32 ui32Mode;
1122 pui32StrLen = va_arg(va, IMG_UINT32*);
1123 pi32Count = va_arg(va, IMG_INT32*);
1124 ppszStr = va_arg(va, IMG_CHAR**);
1125 ui32Mode = va_arg(va, IMG_UINT32);
1127 CHECK_SPACE(*pui32StrLen);
1128 *pi32Count = OSSNPrintf(*ppszStr, 100, "\nApplication Context (hDevMemContext) %p:\n",
1129 (IMG_HANDLE)psBMContext);
1130 UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
1132 List_BM_HEAP_ForEach_va(psBMContext->psBMHeap,
1133 &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
1134 ppszStr,
1135 pui32StrLen,
1136 ui32Mode);
1137 return PVRSRV_OK;
1138 }
1141 /*level 1 of the loop nesting*/
1142 static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
1143 {
1144 IMG_UINT32 *pui32StrLen;
1145 IMG_INT32 *pi32Count;
1146 IMG_CHAR **ppszStr;
1147 IMG_UINT32 ui32Mode;
1149 pui32StrLen = va_arg(va, IMG_UINT32*);
1150 pi32Count = va_arg(va, IMG_INT32*);
1151 ppszStr = va_arg(va, IMG_CHAR**);
1152 ui32Mode = va_arg(va, IMG_UINT32);
1154 CHECK_SPACE(*pui32StrLen);
1155 *pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType);
1156 UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
1158 /* kernel context: */
1159 if(psDeviceNode->sDevMemoryInfo.pBMKernelContext)
1160 {
1161 CHECK_SPACE(*pui32StrLen);
1162 *pi32Count = OSSNPrintf(*ppszStr, 100, "\nKernel Context:\n");
1163 UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
1165 List_BM_HEAP_ForEach_va(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psBMHeap,
1166 &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
1167 ppszStr,
1168 pui32StrLen,
1169 ui32Mode);
1170 }
1172 /* double loop app contexts:heaps */
1173 return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext,
1174 &PVRSRVGetMiscInfoKM_BMContext_AnyVaCb,
1175 pui32StrLen,
1176 pi32Count,
1177 ppszStr,
1178 ui32Mode);
1179 }
1182 /*!
1183 ******************************************************************************
1185 @Function PVRSRVGetMiscInfoKM
1187 @Description
1188 Retrieves misc. info.
1190 @Output PVRSRV_MISC_INFO
1192 @Return PVRSRV_ERROR :
1194 ******************************************************************************/
1195 IMG_EXPORT
1196 PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
1197 {
1198 SYS_DATA *psSysData;
1200 if(!psMiscInfo)
1201 {
1202 PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters"));
1203 return PVRSRV_ERROR_INVALID_PARAMS;
1204 }
1206 psMiscInfo->ui32StatePresent = 0;
1208 /* do a basic check for uninitialised request flag */
1209 if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT
1210 |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
1211 |PVRSRV_MISC_INFO_MEMSTATS_PRESENT
1212 |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT
1213 |PVRSRV_MISC_INFO_DDKVERSION_PRESENT
1214 |PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT
1215 |PVRSRV_MISC_INFO_RESET_PRESENT
1216 |PVRSRV_MISC_INFO_FREEMEM_PRESENT
1217 |PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT
1218 |PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT
1219 |PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT))
1220 {
1221 PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags"));
1222 return PVRSRV_ERROR_INVALID_PARAMS;
1223 }
1225 SysAcquireData(&psSysData);
1227 /* return SOC Timer registers */
1228 if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
1229 (psSysData->pvSOCTimerRegisterKM != IMG_NULL))
1230 {
1231 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
1232 psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM;
1233 psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle;
1234 }
1235 else
1236 {
1237 psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL;
1238 psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL;
1239 }
1241 /* return SOC Clock Gating registers */
1242 if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
1243 (psSysData->pvSOCClockGateRegsBase != IMG_NULL))
1244 {
1245 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
1246 psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase;
1247 psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize;
1248 }
1250 /* memory stats */
1251 if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
1252 (psMiscInfo->pszMemoryStr != IMG_NULL))
1253 {
1254 RA_ARENA **ppArena;
1255 /* BM_HEAP *psBMHeap;
1256 BM_CONTEXT *psBMContext;
1257 PVRSRV_DEVICE_NODE *psDeviceNode;*/
1258 IMG_CHAR *pszStr;
1259 IMG_UINT32 ui32StrLen;
1260 IMG_INT32 i32Count;
1262 pszStr = psMiscInfo->pszMemoryStr;
1263 ui32StrLen = psMiscInfo->ui32MemoryStrLen;
1265 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
1267 /* Local backing stores */
1268 ppArena = &psSysData->apsLocalDevMemArena[0];
1269 while(*ppArena)
1270 {
1271 CHECK_SPACE(ui32StrLen);
1272 i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n");
1273 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1275 RA_GetStats(*ppArena,
1276 &pszStr,
1277 &ui32StrLen);
1278 /* advance through the array */
1279 ppArena++;
1280 }
1282 /* per device */
1283 /* psDeviceNode = psSysData->psDeviceNodeList;*/
1285 /*triple loop; devices:contexts:heaps*/
1286 List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
1287 &PVRSRVGetMiscInfoKM_Device_AnyVaCb,
1288 &ui32StrLen,
1289 &i32Count,
1290 &pszStr,
1291 PVRSRV_MISC_INFO_MEMSTATS_PRESENT);
1293 /* attach a new line and string terminate */
1294 i32Count = OSSNPrintf(pszStr, 100, "\n");
1295 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1296 }
1298 /* Lean version of mem stats: only show free mem on each RA */
1299 if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0)
1300 && psMiscInfo->pszMemoryStr)
1301 {
1302 IMG_CHAR *pszStr;
1303 IMG_UINT32 ui32StrLen;
1304 IMG_INT32 i32Count;
1306 pszStr = psMiscInfo->pszMemoryStr;
1307 ui32StrLen = psMiscInfo->ui32MemoryStrLen;
1309 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT;
1311 /* triple loop over devices:contexts:heaps */
1312 List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
1313 &PVRSRVGetMiscInfoKM_Device_AnyVaCb,
1314 &ui32StrLen,
1315 &i32Count,
1316 &pszStr,
1317 PVRSRV_MISC_INFO_FREEMEM_PRESENT);
1319 i32Count = OSSNPrintf(pszStr, 100, "\n");
1320 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1321 }
1323 if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) &&
1324 (psSysData->psGlobalEventObject != IMG_NULL))
1325 {
1326 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
1327 psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject;
1328 }
1330 /* DDK version and memstats not supported in same call to GetMiscInfo */
1332 if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL)
1333 && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL)
1334 && (psMiscInfo->pszMemoryStr != IMG_NULL))
1335 {
1336 IMG_CHAR *pszStr;
1337 IMG_UINT32 ui32StrLen;
1338 IMG_UINT32 ui32LenStrPerNum = 12; /* string length per UI32: 10 digits + '.' + '\0' = 12 bytes */
1339 IMG_INT32 i32Count;
1340 IMG_INT i;
1341 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
1343 /* construct DDK string */
1344 psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ;
1345 psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN;
1346 psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BUILD_HI;
1347 psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD_LO;
1349 pszStr = psMiscInfo->pszMemoryStr;
1350 ui32StrLen = psMiscInfo->ui32MemoryStrLen;
1352 for (i=0; i<4; i++)
1353 {
1354 if (ui32StrLen < ui32LenStrPerNum)
1355 {
1356 return PVRSRV_ERROR_INVALID_PARAMS;
1357 }
1359 i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]);
1360 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1361 if (i != 3)
1362 {
1363 i32Count = OSSNPrintf(pszStr, 2, ".");
1364 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1365 }
1366 }
1367 }
1369 if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL)
1370 {
1371 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT;
1373 if(psMiscInfo->sCacheOpCtl.bDeferOp)
1374 {
1375 /* For now, assume deferred ops are "full" cache ops,
1376 * and we don't need (or expect) a meminfo.
1377 */
1378 psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType;
1379 }
1380 else
1381 {
1382 PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
1383 PVRSRV_PER_PROCESS_DATA *psPerProc;
1385 if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo)
1386 {
1387 PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
1388 "Ignoring non-deferred cache op with no meminfo"));
1389 return PVRSRV_ERROR_INVALID_PARAMS;
1390 }
1392 if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE)
1393 {
1394 PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
1395 "Deferred cache op is pending. It is unlikely you want "
1396 "to combine deferred cache ops with immediate ones"));
1397 }
1399 psPerProc = PVRSRVFindPerProcessData();
1401 if(PVRSRVLookupHandle(psPerProc->psHandleBase,
1402 (IMG_PVOID *)&psKernelMemInfo,
1403 psMiscInfo->sCacheOpCtl.u.psKernelMemInfo,
1404 PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
1405 {
1406 PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
1407 "Can't find kernel meminfo"));
1408 return PVRSRV_ERROR_INVALID_PARAMS;
1409 }
1411 if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
1412 {
1413 if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
1414 0,
1415 psMiscInfo->sCacheOpCtl.pvBaseVAddr,
1416 psMiscInfo->sCacheOpCtl.ui32Length))
1417 {
1418 return PVRSRV_ERROR_CACHEOP_FAILED;
1419 }
1420 }
1421 else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
1422 {
1423 if(psMiscInfo->sCacheOpCtl.ui32Length!=0)
1424 {
1425 if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
1426 0,
1427 psMiscInfo->sCacheOpCtl.pvBaseVAddr,
1428 psMiscInfo->sCacheOpCtl.ui32Length))
1429 {
1430 return PVRSRV_ERROR_CACHEOP_FAILED;
1431 }
1432 }
1433 }
1434 }
1435 }
1437 if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT) != 0UL)
1438 {
1439 PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
1440 PVRSRV_PER_PROCESS_DATA *psPerProc;
1442 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT;
1444 psPerProc = PVRSRVFindPerProcessData();
1446 if(PVRSRVLookupHandle(psPerProc->psHandleBase,
1447 (IMG_PVOID *)&psKernelMemInfo,
1448 psMiscInfo->sGetRefCountCtl.u.psKernelMemInfo,
1449 PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
1450 {
1451 PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
1452 "Can't find kernel meminfo"));
1453 return PVRSRV_ERROR_INVALID_PARAMS;
1454 }
1456 psMiscInfo->sGetRefCountCtl.ui32RefCount = psKernelMemInfo->ui32RefCount;
1457 }
1459 if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT) != 0UL)
1460 {
1461 psMiscInfo->ui32PageSize = HOST_PAGESIZE();
1462 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT;
1463 }
1465 #if defined(PVRSRV_RESET_ON_HWTIMEOUT)
1466 if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL)
1467 {
1468 PVR_LOG(("User requested OS reset"));
1469 OSPanic();
1470 }
1471 #endif /* #if defined(PVRSRV_RESET_ON_HWTIMEOUT) */
1473 #if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
1474 if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT) != 0UL)
1475 {
1476 PVRSRVProcessQueues(IMG_TRUE);
1477 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT;
1478 }
1479 #endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
1481 return PVRSRV_OK;
1482 }
1485 /*!
1486 ******************************************************************************
1488 @Function PVRSRVDeviceLISR
1490 @Description
1491 OS-independent Device Low-level Interrupt Service Routine
1493 @Input psDeviceNode
1495 @Return IMG_BOOL : Whether any interrupts were serviced
1497 ******************************************************************************/
1498 IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode)
1499 {
1500 SYS_DATA *psSysData;
1501 IMG_BOOL bStatus = IMG_FALSE;
1502 IMG_UINT32 ui32InterruptSource;
1504 if(!psDeviceNode)
1505 {
1506 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n"));
1507 goto out;
1508 }
1509 psSysData = psDeviceNode->psSysData;
1511 /* query the SOC/system to see whether this device was the source of the interrupt */
1512 ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
1513 if(ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
1514 {
1515 if(psDeviceNode->pfnDeviceISR != IMG_NULL)
1516 {
1517 bStatus = (*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData);
1518 }
1520 SysClearInterrupts(psSysData, psDeviceNode->ui32SOCInterruptBit);
1521 }
1523 out:
1524 return bStatus;
1525 }
1527 static IMG_VOID PVRSRVSystemLISR_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
1528 {
1530 IMG_BOOL *pbStatus;
1531 IMG_UINT32 *pui32InterruptSource;
1532 IMG_UINT32 *pui32ClearInterrupts;
1534 pbStatus = va_arg(va, IMG_BOOL*);
1535 pui32InterruptSource = va_arg(va, IMG_UINT32*);
1536 pui32ClearInterrupts = va_arg(va, IMG_UINT32*);
1539 if(psDeviceNode->pfnDeviceISR != IMG_NULL)
1540 {
1541 if(*pui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
1542 {
1543 if((*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData))
1544 {
1545 /* Record if serviced any interrupts. */
1546 *pbStatus = IMG_TRUE;
1547 }
1548 /* Combine the SOC clear bits. */
1549 *pui32ClearInterrupts |= psDeviceNode->ui32SOCInterruptBit;
1550 }
1551 }
1552 }
1554 /*!
1555 ******************************************************************************
1557 @Function PVRSRVSystemLISR
1559 @Description
1560 OS-independent System Low-level Interrupt Service Routine
1562 @Input pvSysData
1564 @Return IMG_BOOL : Whether any interrupts were serviced
1566 ******************************************************************************/
1567 IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData)
1568 {
1569 SYS_DATA *psSysData = pvSysData;
1570 IMG_BOOL bStatus = IMG_FALSE;
1571 IMG_UINT32 ui32InterruptSource;
1572 IMG_UINT32 ui32ClearInterrupts = 0;
1573 /* PVRSRV_DEVICE_NODE *psDeviceNode;*/
1575 if(!psSysData)
1576 {
1577 PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n"));
1578 /* goto out; */
1579 }
1580 else
1581 {
1582 /* query SOC for source of interrupts */
1583 ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL);
1585 /* only proceed if PVR interrupts */
1586 if(ui32InterruptSource)
1587 {
1588 /* traverse the devices' ISR handlers */
1589 List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
1590 &PVRSRVSystemLISR_ForEachVaCb,
1591 &bStatus,
1592 &ui32InterruptSource,
1593 &ui32ClearInterrupts);
1595 SysClearInterrupts(psSysData, ui32ClearInterrupts);
1596 }
1597 /*out:*/
1598 }
1599 return bStatus;
1600 }
1603 static IMG_VOID PVRSRVMISR_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
1604 {
1605 if(psDeviceNode->pfnDeviceMISR != IMG_NULL)
1606 {
1607 (*psDeviceNode->pfnDeviceMISR)(psDeviceNode->pvISRData);
1608 }
1609 }
1611 /*!
1612 ******************************************************************************
1614 @Function PVRSRVMISR
1616 @Input pvSysData
1618 @Description
1619 OS-independent Medium-level Interrupt Service Routine
1621 ******************************************************************************/
1622 IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData)
1623 {
1624 SYS_DATA *psSysData = pvSysData;
1625 /* PVRSRV_DEVICE_NODE *psDeviceNode; */
1627 if(!psSysData)
1628 {
1629 PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n"));
1630 return;
1631 }
1633 /* Traverse the devices' MISR handlers. */
1634 List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
1635 &PVRSRVMISR_ForEachCb);
1637 #if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
1638 /* Process the queues. */
1639 if (PVRSRVProcessQueues(IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED)
1640 {
1641 PVRSRVProcessQueues(IMG_FALSE);
1642 }
1643 #endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
1645 /* signal global event object */
1646 if (psSysData->psGlobalEventObject)
1647 {
1648 IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
1649 if(hOSEventKM)
1650 {
1651 OSEventObjectSignalKM(hOSEventKM);
1652 }
1653 }
1654 }
1657 /*!
1658 ******************************************************************************
1660 @Function PVRSRVProcessConnect
1662 @Description Inform services that a process has connected.
1664 @Input ui32PID - process ID
1666 @Return PVRSRV_ERROR
1668 ******************************************************************************/
1669 IMG_EXPORT
1670 PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags)
1671 {
1672 return PVRSRVPerProcessDataConnect(ui32PID, ui32Flags);
1673 }
1676 /*!
1677 ******************************************************************************
1679 @Function PVRSRVProcessDisconnect
1681 @Description Inform services that a process has disconnected.
1683 @Input ui32PID - process ID
1685 @Return IMG_VOID
1687 ******************************************************************************/
1688 IMG_EXPORT
1689 IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID)
1690 {
1691 PVRSRVPerProcessDataDisconnect(ui32PID);
1692 }
1695 /*!
1696 ******************************************************************************
1698 @Function PVRSRVSaveRestoreLiveSegments
1700 @Input pArena - the arena the segment was originally allocated from.
1701 pbyBuffer - the system memory buffer set to null to get the size needed.
1702 puiBufSize - size of system memory buffer.
1703 bSave - IMG_TRUE if a save is required
1705 @Description
1706 Function to save or restore Resources Live segments
1708 ******************************************************************************/
1709 PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer,
1710 IMG_SIZE_T *puiBufSize, IMG_BOOL bSave)
1711 {
1712 IMG_SIZE_T uiBytesSaved = 0;
1713 IMG_PVOID pvLocalMemCPUVAddr;
1714 RA_SEGMENT_DETAILS sSegDetails;
1716 if (hArena == IMG_NULL)
1717 {
1718 return (PVRSRV_ERROR_INVALID_PARAMS);
1719 }
1721 sSegDetails.uiSize = 0;
1722 sSegDetails.sCpuPhyAddr.uiAddr = 0;
1723 sSegDetails.hSegment = 0;
1725 /* walk the arena segments and write live one to the buffer */
1726 while (RA_GetNextLiveSegment(hArena, &sSegDetails))
1727 {
1728 if (pbyBuffer == IMG_NULL)
1729 {
1730 /* calc buffer required */
1731 uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
1732 }
1733 else
1734 {
1735 if ((uiBytesSaved + sizeof(sSegDetails.uiSize) + sSegDetails.uiSize) > *puiBufSize)
1736 {
1737 return (PVRSRV_ERROR_OUT_OF_MEMORY);
1738 }
1740 PVR_DPF((
1741 PVR_DBG_MESSAGE,
1742 "PVRSRVSaveRestoreLiveSegments: Base " CPUPADDR_FMT " size %" SIZE_T_FMT_LEN "x",
1743 sSegDetails.sCpuPhyAddr.uiAddr,
1744 sSegDetails.uiSize));
1746 /* Map the device's local memory area onto the host. */
1747 pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
1748 sSegDetails.uiSize,
1749 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
1750 IMG_NULL);
1751 if (pvLocalMemCPUVAddr == IMG_NULL)
1752 {
1753 PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Failed to map local memory to host"));
1754 return (PVRSRV_ERROR_OUT_OF_MEMORY);
1755 }
1757 if (bSave)
1758 {
1759 /* write segment size then segment data */
1760 OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize));
1761 pbyBuffer += sizeof(sSegDetails.uiSize);
1763 OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr, sSegDetails.uiSize);
1764 pbyBuffer += sSegDetails.uiSize;
1765 }
1766 else
1767 {
1768 IMG_UINT32 uiSize;
1769 /* reag segment size and validate */
1770 OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize));
1772 if (uiSize != sSegDetails.uiSize)
1773 {
1774 PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Segment size error"));
1775 }
1776 else
1777 {
1778 pbyBuffer += sizeof(sSegDetails.uiSize);
1780 OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer, sSegDetails.uiSize);
1781 pbyBuffer += sSegDetails.uiSize;
1782 }
1783 }
1786 uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
1788 OSUnMapPhysToLin(pvLocalMemCPUVAddr,
1789 sSegDetails.uiSize,
1790 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
1791 IMG_NULL);
1792 }
1793 }
1795 if (pbyBuffer == IMG_NULL)
1796 {
1797 *puiBufSize = uiBytesSaved;
1798 }
1800 return (PVRSRV_OK);
1801 }
1804 /*!
1805 ******************************************************************************
1807 @Function PVRSRVGetErrorStringKM
1809 @Description Returns a text string relating to the PVRSRV_ERROR enum.
1811 @Note case statement used rather than an indexed arrary to ensure text is
1812 synchronised with the correct enum
1814 @Input eError : PVRSRV_ERROR enum
1816 @Return const IMG_CHAR * : Text string
1818 @Note Must be kept in sync with servicesext.h
1820 ******************************************************************************/
1822 IMG_EXPORT
1823 const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError)
1824 {
1825 /* PRQA S 5087 1 */ /* include file required here */
1826 #include "pvrsrv_errors.h"
1827 }
1829 static IMG_VOID PVRSRVCommandCompleteCallbacks_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
1830 {
1831 if(psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
1832 {
1833 /* Call the device's callback function. */
1834 (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
1835 }
1836 }
1838 /*!
1839 ******************************************************************************
1841 @Function PVRSRVScheduleDeviceCallbacks
1843 @Description Schedule all device callbacks
1845 @Return IMG_VOID
1847 ******************************************************************************/
1848 IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID)
1849 {
1850 SYS_DATA *psSysData;
1851 /* PVRSRV_DEVICE_NODE *psDeviceNode;*/
1853 SysAcquireData(&psSysData);
1855 /*for all the device, invoke the callback function*/
1856 List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
1857 &PVRSRVCommandCompleteCallbacks_ForEachCb);
1858 }
1860 /*!
1861 ******************************************************************************
1863 @Function PVRSRVScheduleDevices
1865 @Description Schedules all Services-Managed Devices to check their pending
1866 command queues. The intention is that ScheduleDevices be called by the
1867 3rd party BC driver after it has finished writing new data to its output
1868 texture.
1870 @Return IMG_VOID
1872 ******************************************************************************/
1873 IMG_EXPORT
1874 IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID)
1875 {
1876 PVRSRVScheduleDeviceCallbacks();
1877 }
1879 /*****************************************************************************
1880 End of file (pvrsrv.c)
1881 *****************************************************************************/