[android-sdk/device-ti-proprietary-open.git] / omap5 / 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(__linux__)
52 #include "sysfs.h"
53 #endif
54 #if defined(TTRACE)
55 #include "ttrace.h"
56 #endif
57 #include "perfkm.h"
59 #include "pvrversion.h"
61 #include "lists.h"
63 IMG_UINT32 g_ui32InitFlags;
64 extern int powering_down;
66 /* mark which parts of Services were initialised */
67 #define INIT_DATA_ENABLE_PDUMPINIT 0x1U
68 #define INIT_DATA_ENABLE_TTARCE 0x2U
70 /*!
71 ******************************************************************************
73 @Function AllocateDeviceID
75 @Description
77 allocates a device id from the pool of valid ids
79 @input psSysData : system data
81 @input pui32DevID : device id to return
83 @Return device id
85 ******************************************************************************/
86 PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID)
87 {
88 SYS_DEVICE_ID* psDeviceWalker;
89 SYS_DEVICE_ID* psDeviceEnd;
91 psDeviceWalker = &psSysData->sDeviceID[0];
92 psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
94 /* find a free ID */
95 while (psDeviceWalker < psDeviceEnd)
96 {
97 if (!psDeviceWalker->bInUse)
98 {
99 psDeviceWalker->bInUse = IMG_TRUE;
100 *pui32DevID = psDeviceWalker->uiID;
101 return PVRSRV_OK;
102 }
103 psDeviceWalker++;
104 }
106 PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!"));
108 /* Should never get here: sDeviceID[] may have been setup too small */
109 PVR_ASSERT(psDeviceWalker < psDeviceEnd);
111 return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE;
112 }
115 /*!
116 ******************************************************************************
118 @Function FreeDeviceID
120 @Description
122 frees a device id from the pool of valid ids
124 @input psSysData : system data
126 @input ui32DevID : device id to free
128 @Return device id
130 ******************************************************************************/
131 PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID)
132 {
133 SYS_DEVICE_ID* psDeviceWalker;
134 SYS_DEVICE_ID* psDeviceEnd;
136 psDeviceWalker = &psSysData->sDeviceID[0];
137 psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
139 /* find the ID to free */
140 while (psDeviceWalker < psDeviceEnd)
141 {
142 /* if matching id and in use, free */
143 if (
144 (psDeviceWalker->uiID == ui32DevID) &&
145 (psDeviceWalker->bInUse)
146 )
147 {
148 psDeviceWalker->bInUse = IMG_FALSE;
149 return PVRSRV_OK;
150 }
151 psDeviceWalker++;
152 }
154 PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
156 /* should never get here */
157 PVR_ASSERT(psDeviceWalker < psDeviceEnd);
159 return PVRSRV_ERROR_INVALID_DEVICEID;
160 }
163 /*!
164 ******************************************************************************
166 @Function ReadHWReg
168 @Description
170 register access function
172 @input pvLinRegBaseAddr : lin addr of register block base
174 @input ui32Offset : byte offset from register base
176 @Return register value
178 ******************************************************************************/
179 #ifndef ReadHWReg
180 IMG_EXPORT
181 IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
182 {
183 return *(volatile IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset);
184 }
185 #endif
188 /*!
189 ******************************************************************************
191 @Function WriteHWReg
193 @Description
195 register access function
197 @input pvLinRegBaseAddr : lin addr of register block base
199 @input ui32Offset : byte offset from register base
201 @input ui32Value : value to write to register
203 @Return register value : original reg. value
205 ******************************************************************************/
206 #ifndef WriteHWReg
207 IMG_EXPORT
208 IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
209 {
210 PVR_DPF((PVR_DBG_MESSAGE,"WriteHWReg Base:%x, Offset: %x, Value %x",
211 (IMG_UINTPTR_T)pvLinRegBaseAddr,ui32Offset,ui32Value));
213 *(IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset) = ui32Value;
214 }
215 #endif
218 /*!
219 ******************************************************************************
221 @Function WriteHWRegs
223 @Description
225 register access function
227 @input pvLinRegBaseAddr : lin addr of register block base
229 @input ui32Count : register count
231 @input psHWRegs : address/value register list
233 @Return none
235 ******************************************************************************/
236 #ifndef WriteHWRegs
237 IMG_EXPORT
238 IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs)
239 {
240 while (ui32Count)
241 {
242 WriteHWReg (pvLinRegBaseAddr, psHWRegs->ui32RegAddr, psHWRegs->ui32RegVal);
243 psHWRegs++;
244 ui32Count--;
245 }
246 }
247 #endif
249 /*!
250 ******************************************************************************
251 @Function PVRSRVEnumerateDCKM_ForEachVaCb
253 @Description
255 Enumerates the device node (if is of the same class as given).
257 @Input psDeviceNode - The device node to be enumerated
258 va - variable arguments list, with:
259 pui32DevCount - The device count pointer (to be increased)
260 ppui32DevID - The pointer to the device IDs pointer (to be updated and increased)
261 ******************************************************************************/
262 static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
263 {
264 IMG_UINT *pui32DevCount;
265 PVRSRV_DEVICE_IDENTIFIER **ppsDevIdList;
267 pui32DevCount = va_arg(va, IMG_UINT*);
268 ppsDevIdList = va_arg(va, PVRSRV_DEVICE_IDENTIFIER**);
270 if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT)
271 {
272 *(*ppsDevIdList) = psDeviceNode->sDevId;
273 (*ppsDevIdList)++;
274 (*pui32DevCount)++;
275 }
276 }
280 /*!
281 ******************************************************************************
283 @Function PVRSRVEnumerateDevicesKM
285 @Description
286 This function will enumerate all the devices supported by the
287 PowerVR services within the target system.
288 The function returns a list of the device ID strcutres stored either in
289 the services or constructed in the user mode glue component in certain
290 environments. The number of devices in the list is also returned.
292 In a binary layered component which does not support dynamic runtime selection,
293 the glue code should compile to return the supported devices statically,
294 e.g. multiple instances of the same device if multiple devices are supported,
295 or the target combination of MBX and display device.
297 In the case of an environment (for instance) where one MBX1 may connect to two
298 display devices this code would enumerate all three devices and even
299 non-dynamic MBX1 selection code should retain the facility to parse the list
300 to find the index of the MBX device
302 @output pui32NumDevices : On success, contains the number of devices present
303 in the system
305 @output psDevIdList : Pointer to called supplied buffer to receive the
306 list of PVRSRV_DEVICE_IDENTIFIER
308 @return PVRSRV_ERROR : PVRSRV_NO_ERROR
310 ******************************************************************************/
311 IMG_EXPORT
312 PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
313 PVRSRV_DEVICE_IDENTIFIER *psDevIdList)
314 {
315 SYS_DATA *psSysData;
316 /* PVRSRV_DEVICE_NODE *psDeviceNode; */
317 IMG_UINT32 i;
319 if (!pui32NumDevices || !psDevIdList)
320 {
321 PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params"));
322 return PVRSRV_ERROR_INVALID_PARAMS;
323 }
325 SysAcquireData(&psSysData);
327 /*
328 setup input buffer to be `empty'
329 */
330 for (i=0; i<PVRSRV_MAX_DEVICES; i++)
331 {
332 psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
333 }
335 /* and zero device count */
336 *pui32NumDevices = 0;
338 /*
339 Search through the device list for services managed devices
340 return id info for each device and the number of devices
341 available
342 */
343 List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
344 &PVRSRVEnumerateDevicesKM_ForEachVaCb,
345 pui32NumDevices,
346 &psDevIdList);
349 return PVRSRV_OK;
350 }
353 /*!
354 ******************************************************************************
356 @Function PVRSRVInit
358 @Description Initialise services
360 @Input psSysData : sysdata structure
362 @Return PVRSRV_ERROR :
364 ******************************************************************************/
365 PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
366 {
367 PVRSRV_ERROR eError;
369 #if defined(__linux__)
370 eError = PVRSRVCreateSysfsEntry();
371 if (eError != PVRSRV_OK)
372 {
373 goto Error;
374 }
375 #endif
377 /* Initialise Resource Manager */
378 eError = ResManInit();
379 if (eError != PVRSRV_OK)
380 {
381 goto Error;
382 }
384 eError = PVRSRVPerProcessDataInit();
385 if(eError != PVRSRV_OK)
386 {
387 goto Error;
388 }
390 /* Initialise handles */
391 eError = PVRSRVHandleInit();
392 if(eError != PVRSRV_OK)
393 {
394 goto Error;
395 }
397 /* Initialise Power Manager Lock */
398 eError = OSCreateResource(&psSysData->sPowerStateChangeResource);
399 if (eError != PVRSRV_OK)
400 {
401 goto Error;
402 }
404 /* Initialise system power state */
405 psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
406 psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
408 /* Create an event object */
409 if(OSAllocMem( PVRSRV_PAGEABLE_SELECT,
410 sizeof(PVRSRV_EVENTOBJECT) ,
411 (IMG_VOID **)&psSysData->psGlobalEventObject, 0,
412 "Event Object") != PVRSRV_OK)
413 {
415 goto Error;
416 }
418 if(OSEventObjectCreateKM("PVRSRV_GLOBAL_EVENTOBJECT", psSysData->psGlobalEventObject) != PVRSRV_OK)
419 {
420 goto Error;
421 }
423 /* Store OS high res timer fallbacks, the system is free to overide these */
424 psSysData->pfnHighResTimerCreate = OSFuncHighResTimerCreate;
425 psSysData->pfnHighResTimerGetus = OSFuncHighResTimerGetus;
426 psSysData->pfnHighResTimerDestroy = OSFuncHighResTimerDestroy;
428 #if defined(TTRACE)
429 eError = PVRSRVTimeTraceInit();
430 if (eError != PVRSRV_OK)
431 goto Error;
432 g_ui32InitFlags |= INIT_DATA_ENABLE_TTARCE;
433 #endif
435 /* Initialise pdump */
436 PDUMPINIT();
437 g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT;
439 PERFINIT();
440 return eError;
442 Error:
443 PVRSRVDeInit(psSysData);
444 return eError;
445 }
449 /*!
450 ******************************************************************************
452 @Function PVRSRVDeInit
454 @Description De-Initialise services
456 @Input psSysData : sysdata structure
458 @Return PVRSRV_ERROR :
460 ******************************************************************************/
461 IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
462 {
463 PVRSRV_ERROR eError;
465 PVR_UNREFERENCED_PARAMETER(psSysData);
467 if (psSysData == IMG_NULL)
468 {
469 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param"));
470 return;
471 }
473 PERFDEINIT();
475 #if defined(TTRACE)
476 /* deinitialise ttrace */
477 if ((g_ui32InitFlags & INIT_DATA_ENABLE_TTARCE) > 0)
478 {
479 PVRSRVTimeTraceDeinit();
480 }
481 #endif
482 /* deinitialise pdump */
483 if( (g_ui32InitFlags & INIT_DATA_ENABLE_PDUMPINIT) > 0)
484 {
485 PDUMPDEINIT();
486 }
488 /* destroy event object */
489 if(psSysData->psGlobalEventObject)
490 {
491 OSEventObjectDestroyKM(psSysData->psGlobalEventObject);
492 OSFreeMem( PVRSRV_PAGEABLE_SELECT,
493 sizeof(PVRSRV_EVENTOBJECT),
494 psSysData->psGlobalEventObject,
495 0);
496 psSysData->psGlobalEventObject = IMG_NULL;
497 }
499 eError = PVRSRVHandleDeInit();
500 if (eError != PVRSRV_OK)
501 {
502 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed"));
503 }
505 eError = PVRSRVPerProcessDataDeInit();
506 if (eError != PVRSRV_OK)
507 {
508 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed"));
509 }
511 ResManDeInit();
512 }
515 /*!
516 ******************************************************************************
518 @Function PVRSRVRegisterDevice
520 @Description
522 registers a device with the system
524 @Input psSysData : sysdata structure
526 @Input pfnRegisterDevice : device registration function
528 @Input ui32SOCInterruptBit : SoC interrupt bit for this device
530 @Output pui32DeviceIndex : unique device key (for case of multiple identical devices)
532 @Return PVRSRV_ERROR :
534 ******************************************************************************/
535 PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
536 PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
537 IMG_UINT32 ui32SOCInterruptBit,
538 IMG_UINT32 *pui32DeviceIndex)
539 {
540 PVRSRV_ERROR eError;
541 PVRSRV_DEVICE_NODE *psDeviceNode;
543 /* Allocate device node */
544 if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
545 sizeof(PVRSRV_DEVICE_NODE),
546 (IMG_VOID **)&psDeviceNode, IMG_NULL,
547 "Device Node") != PVRSRV_OK)
548 {
549 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode"));
550 return (PVRSRV_ERROR_OUT_OF_MEMORY);
551 }
552 OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
554 eError = pfnRegisterDevice(psDeviceNode);
555 if (eError != PVRSRV_OK)
556 {
557 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
558 sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
559 /*not nulling pointer, out of scope*/
560 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
561 return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED);
562 }
564 /*
565 make the refcount 1 and test on this to initialise device
566 at acquiredevinfo. On release if refcount is 1, deinitialise
567 and when refcount is 0 (sysdata de-alloc) deallocate the device
568 structures
569 */
570 psDeviceNode->ui32RefCount = 1;
571 psDeviceNode->psSysData = psSysData;
572 psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
574 /* all devices need a unique identifier */
575 AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
577 /* and finally insert the device into the dev-list */
578 List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
580 /* and copy back index */
581 *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
583 return PVRSRV_OK;
584 }
587 /*!
588 ******************************************************************************
590 @Function PVRSRVInitialiseDevice
592 @Description
594 initialises device by index
596 @Input ui32DevIndex : Index to the required device
598 @Return PVRSRV_ERROR :
600 ******************************************************************************/
601 PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
602 {
603 PVRSRV_DEVICE_NODE *psDeviceNode;
604 SYS_DATA *psSysData;
605 PVRSRV_ERROR eError;
607 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice"));
609 SysAcquireData(&psSysData);
611 /* Find device in the list */
612 psDeviceNode = (PVRSRV_DEVICE_NODE*)
613 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
614 &MatchDeviceKM_AnyVaCb,
615 ui32DevIndex,
616 IMG_TRUE);
617 if(!psDeviceNode)
618 {
619 /* Devinfo not in the list */
620 PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: requested device is not present"));
621 return PVRSRV_ERROR_INIT_FAILURE;
622 }
623 /*
624 FoundDevice:
625 */
627 PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
629 /*
630 Create the device's resource manager context.
631 */
632 eError = PVRSRVResManConnect(IMG_NULL, &psDeviceNode->hResManContext);
633 if (eError != PVRSRV_OK)
634 {
635 PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed PVRSRVResManConnect call"));
636 return eError;
637 }
639 /* Initialise the device */
640 if(psDeviceNode->pfnInitDevice != IMG_NULL)
641 {
642 eError = psDeviceNode->pfnInitDevice(psDeviceNode);
643 if (eError != PVRSRV_OK)
644 {
645 PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed InitDevice call"));
646 return eError;
647 }
648 }
650 return PVRSRV_OK;
651 }
654 static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
655 {
656 PVRSRV_ERROR eError;
658 eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
659 if (eError != PVRSRV_OK)
660 {
661 PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVPowerLock call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
662 return eError;
663 }
665 eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
666 PVRSRV_DEV_POWER_STATE_DEFAULT);
667 PVRSRVPowerUnlock(KERNEL_ID);
668 if (eError != PVRSRV_OK)
669 {
670 PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
671 }
672 return eError;
673 }
675 /*wraps the PVRSRVDevInitCompatCheck call and prints a debugging message if failed*/
676 static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
677 {
678 PVRSRV_ERROR eError;
679 eError = PVRSRVDevInitCompatCheck(psDeviceNode);
680 if (eError != PVRSRV_OK)
681 {
682 PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
683 }
684 return eError;
685 }
688 /*!
689 ******************************************************************************
691 @Function PVRSRVFinaliseSystem
693 @Description
695 Final part of system initialisation.
697 @Input ui32DevIndex : Index to the required device
699 @Return PVRSRV_ERROR :
701 ******************************************************************************/
702 PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
703 {
704 /* PVRSRV_DEVICE_NODE *psDeviceNode;*/
705 SYS_DATA *psSysData;
706 PVRSRV_ERROR eError;
708 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
710 SysAcquireData(&psSysData);
712 if (bInitSuccessful)
713 {
714 eError = SysFinalise();
715 if (eError != PVRSRV_OK)
716 {
717 PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: SysFinalise failed (%d)", eError));
718 return eError;
719 }
721 /* Place all devices into their default power state. */
722 eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
723 &PVRSRVFinaliseSystem_SetPowerState_AnyCb);
724 if (eError != PVRSRV_OK)
725 {
726 return eError;
727 }
729 /* Verify microkernel compatibility for devices */
730 eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
731 &PVRSRVFinaliseSystem_CompatCheck_AnyCb);
732 if (eError != PVRSRV_OK)
733 {
734 return eError;
735 }
736 }
738 /* Some platforms call this too early in the boot phase. */
739 PDUMPENDINITPHASE();
741 return PVRSRV_OK;
742 }
745 PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
746 {
747 /* Only check devices which specify a compatibility check callback */
748 if (psDeviceNode->pfnInitDeviceCompatCheck)
749 return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
750 else
751 return PVRSRV_OK;
752 }
754 /*!
755 ******************************************************************************
757 @Function PVRSRVAcquireDeviceDataKM
759 @Description
761 Matchs a device given a device type and a device index.
763 @input psDeviceNode :The device node to be matched.
765 @Input va : Variable argument list with:
766 eDeviceType : Required device type. If type is unknown use ui32DevIndex
767 to locate device data
769 ui32DevIndex : Index to the required device obtained from the
770 PVRSRVEnumerateDevice function
772 @Return PVRSRV_ERROR :
774 ******************************************************************************/
775 static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
776 {
777 PVRSRV_DEVICE_TYPE eDeviceType;
778 IMG_UINT32 ui32DevIndex;
780 eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE);
781 ui32DevIndex = va_arg(va, IMG_UINT32);
783 if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN &&
784 psDeviceNode->sDevId.eDeviceType == eDeviceType) ||
785 (eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN &&
786 psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex))
787 {
788 return psDeviceNode;
789 }
790 else
791 {
792 return IMG_NULL;
793 }
794 }
796 /*!
797 ******************************************************************************
799 @Function PVRSRVAcquireDeviceDataKM
801 @Description
803 Returns device information
805 @Input ui32DevIndex : Index to the required device obtained from the
806 PVRSRVEnumerateDevice function
808 @Input eDeviceType : Required device type. If type is unknown use ui32DevIndex
809 to locate device data
811 @Output *phDevCookie : Dev Cookie
814 @Return PVRSRV_ERROR :
816 ******************************************************************************/
817 IMG_EXPORT
818 PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex,
819 PVRSRV_DEVICE_TYPE eDeviceType,
820 IMG_HANDLE *phDevCookie)
821 {
822 PVRSRV_DEVICE_NODE *psDeviceNode;
823 SYS_DATA *psSysData;
825 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
827 SysAcquireData(&psSysData);
829 /* Find device in the list */
830 psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
831 &PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
832 eDeviceType,
833 ui32DevIndex);
836 if (!psDeviceNode)
837 {
838 /* device can't be found in the list so it isn't in the system */
839 PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
840 return PVRSRV_ERROR_INIT_FAILURE;
841 }
843 /*FoundDevice:*/
845 PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
847 /* return the dev cookie? */
848 if (phDevCookie)
849 {
850 *phDevCookie = (IMG_HANDLE)psDeviceNode;
851 }
853 return PVRSRV_OK;
854 }
857 /*!
858 ******************************************************************************
860 @Function PVRSRVDeinitialiseDevice
862 @Description
864 This De-inits device
866 @Input ui32DevIndex : Index to the required device
868 @Return PVRSRV_ERROR :
870 ******************************************************************************/
871 PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
872 {
873 PVRSRV_DEVICE_NODE *psDeviceNode;
874 SYS_DATA *psSysData;
875 PVRSRV_ERROR eError;
877 SysAcquireData(&psSysData);
879 psDeviceNode = (PVRSRV_DEVICE_NODE*)
880 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
881 &MatchDeviceKM_AnyVaCb,
882 ui32DevIndex,
883 IMG_TRUE);
885 if (!psDeviceNode)
886 {
887 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: requested device %d is not present", ui32DevIndex));
888 return PVRSRV_ERROR_DEVICEID_NOT_FOUND;
889 }
891 eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
892 if (eError != PVRSRV_OK)
893 {
894 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVPowerLock call"));
895 return eError;
896 }
898 /*
899 Power down the device if necessary.
900 */
901 eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
902 PVRSRV_DEV_POWER_STATE_OFF);
903 PVRSRVPowerUnlock(KERNEL_ID);
904 if (eError != PVRSRV_OK)
905 {
906 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call"));
907 return eError;
908 }
910 /*
911 Free the dissociated device memory.
912 */
913 eError = ResManFreeResByCriteria(psDeviceNode->hResManContext,
914 RESMAN_CRITERIA_RESTYPE,
915 RESMAN_TYPE_DEVICEMEM_ALLOCATION,
916 IMG_NULL, 0);
917 if (eError != PVRSRV_OK)
918 {
919 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call"));
920 return eError;
921 }
923 /*
924 De-init the device.
925 */
926 if(psDeviceNode->pfnDeInitDevice != IMG_NULL)
927 {
928 eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
929 if (eError != PVRSRV_OK)
930 {
931 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed DeInitDevice call"));
932 return eError;
933 }
934 }
936 /*
937 Close the device's resource manager context.
938 */
939 PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE);
940 psDeviceNode->hResManContext = IMG_NULL;
942 /* remove node from list */
943 List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
945 /* deallocate id and memory */
946 (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
947 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
948 sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
949 /*not nulling pointer, out of scope*/
951 return (PVRSRV_OK);
952 }
955 IMG_EXPORT
956 PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr,
957 IMG_UINT32 ui32Value,
958 IMG_UINT32 ui32Mask,
959 IMG_UINT32 ui32Timeoutus,
960 IMG_UINT32 ui32PollPeriodus,
961 IMG_BOOL bAllowPreemption)
962 {
963 #if defined (EMULATOR)
964 {
965 PVR_UNREFERENCED_PARAMETER(bAllowPreemption);
966 #if !defined(__linux__)
967 PVR_UNREFERENCED_PARAMETER(ui32PollPeriodus);
968 #endif
970 /* For the Emulator we want the system to stop when a lock-up is detected so the state can be analysed.
971 * Also the Emulator is much slower than real silicon so timeouts are not valid.
972 */
973 do
974 {
975 if((*pui32LinMemAddr & ui32Mask) == ui32Value)
976 {
977 return PVRSRV_OK;
978 }
980 #if defined(__linux__)
981 OSWaitus(ui32PollPeriodus);
982 #else
983 OSReleaseThreadQuanta();
984 #endif
986 } while (ui32Timeoutus); /* Endless loop only for the Emulator */
987 }
988 #else
989 {
990 IMG_UINT32 ui32ActualValue = 0xFFFFFFFFU; /* Initialiser only required to prevent incorrect warning */
992 if (bAllowPreemption)
993 {
994 PVR_ASSERT(ui32PollPeriodus >= 1000);
995 }
997 /* PRQA S 3415,4109 1 */ /* macro format critical - leave alone */
998 LOOP_UNTIL_TIMEOUT(ui32Timeoutus)
999 {
1000 ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
1001 if(ui32ActualValue == ui32Value)
1002 {
1003 return PVRSRV_OK;
1004 }
1006 if (bAllowPreemption)
1007 {
1008 OSSleepms(ui32PollPeriodus / 1000);
1009 }
1010 else
1011 {
1012 OSWaitus(ui32PollPeriodus);
1013 }
1014 } END_LOOP_UNTIL_TIMEOUT();
1016 PVR_DPF((PVR_DBG_ERROR,"PollForValueKM: Timeout. Expected 0x%x but found 0x%x (mask 0x%x).",
1017 ui32Value, ui32ActualValue, ui32Mask));
1018 }
1019 #endif /* #if defined (EMULATOR) */
1021 return PVRSRV_ERROR_TIMEOUT;
1022 }
1025 /*Level 3 of the loop nesting*/
1026 static IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
1027 {
1028 IMG_CHAR **ppszStr;
1029 IMG_UINT32 *pui32StrLen;
1030 IMG_UINT32 ui32Mode;
1031 PVRSRV_ERROR (*pfnGetStats)(RA_ARENA *, IMG_CHAR **, IMG_UINT32 *);
1033 ppszStr = va_arg(va, IMG_CHAR**);
1034 pui32StrLen = va_arg(va, IMG_UINT32*);
1035 ui32Mode = va_arg(va, IMG_UINT32);
1037 /* Would be better to pass fn pointer in the variable args list
1038 * but MS C compiler complains with error C2066: In ANSI C,
1039 * it is not legal to cast between a function pointer and a data pointer.
1040 */
1041 switch(ui32Mode)
1042 {
1043 case PVRSRV_MISC_INFO_MEMSTATS_PRESENT:
1044 pfnGetStats = &RA_GetStats;
1045 break;
1046 case PVRSRV_MISC_INFO_FREEMEM_PRESENT:
1047 pfnGetStats = &RA_GetStatsFreeMem;
1048 break;
1049 default:
1050 return;
1051 }
1053 if(psBMHeap->pImportArena)
1054 {
1055 pfnGetStats(psBMHeap->pImportArena,
1056 ppszStr,
1057 pui32StrLen);
1058 }
1060 if(psBMHeap->pVMArena)
1061 {
1062 pfnGetStats(psBMHeap->pVMArena,
1063 ppszStr,
1064 pui32StrLen);
1065 }
1066 }
1068 /*Level 2 of the loop nesting*/
1069 static PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va)
1070 {
1072 IMG_UINT32 *pui32StrLen;
1073 IMG_INT32 *pi32Count;
1074 IMG_CHAR **ppszStr;
1075 IMG_UINT32 ui32Mode;
1077 pui32StrLen = va_arg(va, IMG_UINT32*);
1078 pi32Count = va_arg(va, IMG_INT32*);
1079 ppszStr = va_arg(va, IMG_CHAR**);
1080 ui32Mode = va_arg(va, IMG_UINT32);
1082 CHECK_SPACE(*pui32StrLen);
1083 *pi32Count = OSSNPrintf(*ppszStr, 100, "\nApplication Context (hDevMemContext) %p:\n",
1084 (IMG_HANDLE)psBMContext);
1085 UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
1087 List_BM_HEAP_ForEach_va(psBMContext->psBMHeap,
1088 &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
1089 ppszStr,
1090 pui32StrLen,
1091 ui32Mode);
1092 return PVRSRV_OK;
1093 }
1096 /*level 1 of the loop nesting*/
1097 static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
1098 {
1099 IMG_UINT32 *pui32StrLen;
1100 IMG_INT32 *pi32Count;
1101 IMG_CHAR **ppszStr;
1102 IMG_UINT32 ui32Mode;
1104 pui32StrLen = va_arg(va, IMG_UINT32*);
1105 pi32Count = va_arg(va, IMG_INT32*);
1106 ppszStr = va_arg(va, IMG_CHAR**);
1107 ui32Mode = va_arg(va, IMG_UINT32);
1109 CHECK_SPACE(*pui32StrLen);
1110 *pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType);
1111 UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
1113 /* kernel context: */
1114 if(psDeviceNode->sDevMemoryInfo.pBMKernelContext)
1115 {
1116 CHECK_SPACE(*pui32StrLen);
1117 *pi32Count = OSSNPrintf(*ppszStr, 100, "\nKernel Context:\n");
1118 UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
1120 List_BM_HEAP_ForEach_va(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psBMHeap,
1121 &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
1122 ppszStr,
1123 pui32StrLen,
1124 ui32Mode);
1125 }
1127 /* double loop app contexts:heaps */
1128 return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext,
1129 &PVRSRVGetMiscInfoKM_BMContext_AnyVaCb,
1130 pui32StrLen,
1131 pi32Count,
1132 ppszStr,
1133 ui32Mode);
1134 }
1137 /*!
1138 ******************************************************************************
1140 @Function PVRSRVGetMiscInfoKM
1142 @Description
1143 Retrieves misc. info.
1145 @Output PVRSRV_MISC_INFO
1147 @Return PVRSRV_ERROR :
1149 ******************************************************************************/
1150 IMG_EXPORT
1151 #if defined (SUPPORT_SID_INTERFACE)
1152 PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO_KM *psMiscInfo)
1153 #else
1154 PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
1155 #endif
1156 {
1157 SYS_DATA *psSysData;
1159 if(!psMiscInfo)
1160 {
1161 PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters"));
1162 return PVRSRV_ERROR_INVALID_PARAMS;
1163 }
1165 psMiscInfo->ui32StatePresent = 0;
1167 /* do a basic check for uninitialised request flag */
1168 if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT
1169 |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
1170 |PVRSRV_MISC_INFO_MEMSTATS_PRESENT
1171 |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT
1172 |PVRSRV_MISC_INFO_DDKVERSION_PRESENT
1173 |PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT
1174 |PVRSRV_MISC_INFO_RESET_PRESENT
1175 |PVRSRV_MISC_INFO_FREEMEM_PRESENT
1176 |PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT
1177 |PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT
1178 |PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT))
1179 {
1180 PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags"));
1181 return PVRSRV_ERROR_INVALID_PARAMS;
1182 }
1184 SysAcquireData(&psSysData);
1186 /* return SOC Timer registers */
1187 if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
1188 (psSysData->pvSOCTimerRegisterKM != IMG_NULL))
1189 {
1190 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
1191 psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM;
1192 psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle;
1193 }
1194 else
1195 {
1196 psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL;
1197 psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL;
1198 }
1200 /* return SOC Clock Gating registers */
1201 if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
1202 (psSysData->pvSOCClockGateRegsBase != IMG_NULL))
1203 {
1204 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
1205 psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase;
1206 psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize;
1207 }
1209 /* memory stats */
1210 if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
1211 (psMiscInfo->pszMemoryStr != IMG_NULL))
1212 {
1213 RA_ARENA **ppArena;
1214 /* BM_HEAP *psBMHeap;
1215 BM_CONTEXT *psBMContext;
1216 PVRSRV_DEVICE_NODE *psDeviceNode;*/
1217 IMG_CHAR *pszStr;
1218 IMG_UINT32 ui32StrLen;
1219 IMG_INT32 i32Count;
1221 pszStr = psMiscInfo->pszMemoryStr;
1222 ui32StrLen = psMiscInfo->ui32MemoryStrLen;
1224 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
1226 /* Local backing stores */
1227 ppArena = &psSysData->apsLocalDevMemArena[0];
1228 while(*ppArena)
1229 {
1230 CHECK_SPACE(ui32StrLen);
1231 i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n");
1232 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1234 RA_GetStats(*ppArena,
1235 &pszStr,
1236 &ui32StrLen);
1237 /* advance through the array */
1238 ppArena++;
1239 }
1241 /* per device */
1242 /* psDeviceNode = psSysData->psDeviceNodeList;*/
1244 /*triple loop; devices:contexts:heaps*/
1245 List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
1246 &PVRSRVGetMiscInfoKM_Device_AnyVaCb,
1247 &ui32StrLen,
1248 &i32Count,
1249 &pszStr,
1250 PVRSRV_MISC_INFO_MEMSTATS_PRESENT);
1252 /* attach a new line and string terminate */
1253 i32Count = OSSNPrintf(pszStr, 100, "\n");
1254 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1255 }
1257 /* Lean version of mem stats: only show free mem on each RA */
1258 if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0)
1259 && psMiscInfo->pszMemoryStr)
1260 {
1261 IMG_CHAR *pszStr;
1262 IMG_UINT32 ui32StrLen;
1263 IMG_INT32 i32Count;
1265 pszStr = psMiscInfo->pszMemoryStr;
1266 ui32StrLen = psMiscInfo->ui32MemoryStrLen;
1268 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT;
1270 /* triple loop over devices:contexts:heaps */
1271 List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
1272 &PVRSRVGetMiscInfoKM_Device_AnyVaCb,
1273 &ui32StrLen,
1274 &i32Count,
1275 &pszStr,
1276 PVRSRV_MISC_INFO_FREEMEM_PRESENT);
1278 i32Count = OSSNPrintf(pszStr, 100, "\n");
1279 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1280 }
1282 if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) &&
1283 (psSysData->psGlobalEventObject != IMG_NULL))
1284 {
1285 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
1286 psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject;
1287 }
1289 /* DDK version and memstats not supported in same call to GetMiscInfo */
1291 if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL)
1292 && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL)
1293 && (psMiscInfo->pszMemoryStr != IMG_NULL))
1294 {
1295 IMG_CHAR *pszStr;
1296 IMG_UINT32 ui32StrLen;
1297 IMG_UINT32 ui32LenStrPerNum = 12; /* string length per UI32: 10 digits + '.' + '\0' = 12 bytes */
1298 IMG_INT32 i32Count;
1299 IMG_INT i;
1300 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
1302 /* construct DDK string */
1303 psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ;
1304 psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN;
1305 psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BUILD_HI;
1306 psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD_LO;
1308 pszStr = psMiscInfo->pszMemoryStr;
1309 ui32StrLen = psMiscInfo->ui32MemoryStrLen;
1311 for (i=0; i<4; i++)
1312 {
1313 if (ui32StrLen < ui32LenStrPerNum)
1314 {
1315 return PVRSRV_ERROR_INVALID_PARAMS;
1316 }
1318 i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]);
1319 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1320 if (i != 3)
1321 {
1322 i32Count = OSSNPrintf(pszStr, 2, ".");
1323 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1324 }
1325 }
1326 }
1328 if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL)
1329 {
1330 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT;
1332 if(psMiscInfo->sCacheOpCtl.bDeferOp)
1333 {
1334 /* For now, assume deferred ops are "full" cache ops,
1335 * and we don't need (or expect) a meminfo.
1336 */
1337 psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType;
1338 }
1339 else
1340 {
1341 #if defined (SUPPORT_SID_INTERFACE)
1342 PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = psMiscInfo->sCacheOpCtl.psKernelMemInfo;
1344 if(!psMiscInfo->sCacheOpCtl.psKernelMemInfo)
1345 #else
1346 PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
1347 PVRSRV_PER_PROCESS_DATA *psPerProc;
1349 if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo)
1350 #endif
1351 {
1352 PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
1353 "Ignoring non-deferred cache op with no meminfo"));
1354 return PVRSRV_ERROR_INVALID_PARAMS;
1355 }
1357 if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE)
1358 {
1359 PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
1360 "Deferred cache op is pending. It is unlikely you want "
1361 "to combine deferred cache ops with immediate ones"));
1362 }
1364 #if defined (SUPPORT_SID_INTERFACE)
1365 PVR_DBG_BREAK
1366 #else
1367 psPerProc = PVRSRVFindPerProcessData();
1369 if(PVRSRVLookupHandle(psPerProc->psHandleBase,
1370 (IMG_PVOID *)&psKernelMemInfo,
1371 psMiscInfo->sCacheOpCtl.u.psKernelMemInfo,
1372 PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
1373 {
1374 PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
1375 "Can't find kernel meminfo"));
1376 return PVRSRV_ERROR_INVALID_PARAMS;
1377 }
1378 #endif
1380 if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
1381 {
1382 if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
1383 0,
1384 psMiscInfo->sCacheOpCtl.pvBaseVAddr,
1385 psMiscInfo->sCacheOpCtl.ui32Length))
1386 {
1387 return PVRSRV_ERROR_CACHEOP_FAILED;
1388 }
1389 }
1390 else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
1391 {
1392 if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
1393 0,
1394 psMiscInfo->sCacheOpCtl.pvBaseVAddr,
1395 psMiscInfo->sCacheOpCtl.ui32Length))
1396 {
1397 return PVRSRV_ERROR_CACHEOP_FAILED;
1398 }
1399 }
1400 }
1401 }
1403 if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT) != 0UL)
1404 {
1405 #if !defined (SUPPORT_SID_INTERFACE)
1406 PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
1407 PVRSRV_PER_PROCESS_DATA *psPerProc;
1408 #endif
1410 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT;
1412 #if defined (SUPPORT_SID_INTERFACE)
1413 PVR_DBG_BREAK
1414 #else
1415 psPerProc = PVRSRVFindPerProcessData();
1417 if(PVRSRVLookupHandle(psPerProc->psHandleBase,
1418 (IMG_PVOID *)&psKernelMemInfo,
1419 psMiscInfo->sGetRefCountCtl.u.psKernelMemInfo,
1420 PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
1421 {
1422 PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
1423 "Can't find kernel meminfo"));
1424 return PVRSRV_ERROR_INVALID_PARAMS;
1425 }
1427 psMiscInfo->sGetRefCountCtl.ui32RefCount = psKernelMemInfo->ui32RefCount;
1428 #endif
1429 }
1431 if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT) != 0UL)
1432 {
1433 psMiscInfo->ui32PageSize = HOST_PAGESIZE();
1434 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT;
1435 }
1437 #if defined(PVRSRV_RESET_ON_HWTIMEOUT)
1438 if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL)
1439 {
1440 PVR_LOG(("User requested OS reset"));
1441 OSPanic();
1442 }
1443 #endif /* #if defined(PVRSRV_RESET_ON_HWTIMEOUT) */
1445 if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT) != 0UL)
1446 {
1447 PVRSRVSetDCState(DC_STATE_FORCE_SWAP_TO_SYSTEM);
1448 psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT;
1449 }
1451 return PVRSRV_OK;
1452 }
1455 /*!
1456 ******************************************************************************
1458 @Function PVRSRVDeviceLISR
1460 @Description
1461 OS-independent Device Low-level Interrupt Service Routine
1463 @Input psDeviceNode
1465 @Return IMG_BOOL : Whether any interrupts were serviced
1467 ******************************************************************************/
1468 IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode)
1469 {
1470 SYS_DATA *psSysData;
1471 IMG_BOOL bStatus = IMG_FALSE;
1472 IMG_UINT32 ui32InterruptSource;
1474 if(!psDeviceNode)
1475 {
1476 PVR_DPF((PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n"));
1477 goto out;
1478 }
1479 psSysData = psDeviceNode->psSysData;
1481 /* query the SOC/system to see whether this device was the source of the interrupt */
1482 ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
1483 if(ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
1484 {
1485 if(psDeviceNode->pfnDeviceISR != IMG_NULL)
1486 {
1487 bStatus = (*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData);
1488 }
1489 if(!powering_down) {
1490 SysClearInterrupts(psSysData, psDeviceNode->ui32SOCInterruptBit);
1491 }
1492 }
1494 out:
1495 return bStatus;
1496 }
1498 static IMG_VOID PVRSRVSystemLISR_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
1499 {
1501 IMG_BOOL *pbStatus;
1502 IMG_UINT32 *pui32InterruptSource;
1503 IMG_UINT32 *pui32ClearInterrupts;
1505 pbStatus = va_arg(va, IMG_BOOL*);
1506 pui32InterruptSource = va_arg(va, IMG_UINT32*);
1507 pui32ClearInterrupts = va_arg(va, IMG_UINT32*);
1510 if(psDeviceNode->pfnDeviceISR != IMG_NULL)
1511 {
1512 if(*pui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
1513 {
1514 if((*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData))
1515 {
1516 /* Record if serviced any interrupts. */
1517 *pbStatus = IMG_TRUE;
1518 }
1519 /* Combine the SOC clear bits. */
1520 *pui32ClearInterrupts |= psDeviceNode->ui32SOCInterruptBit;
1521 }
1522 }
1523 }
1525 /*!
1526 ******************************************************************************
1528 @Function PVRSRVSystemLISR
1530 @Description
1531 OS-independent System Low-level Interrupt Service Routine
1533 @Input pvSysData
1535 @Return IMG_BOOL : Whether any interrupts were serviced
1537 ******************************************************************************/
1538 IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData)
1539 {
1540 SYS_DATA *psSysData = pvSysData;
1541 IMG_BOOL bStatus = IMG_FALSE;
1542 IMG_UINT32 ui32InterruptSource;
1543 IMG_UINT32 ui32ClearInterrupts = 0;
1544 /* PVRSRV_DEVICE_NODE *psDeviceNode;*/
1546 if(!psSysData)
1547 {
1548 PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n"));
1549 /* goto out; */
1550 }
1551 else
1552 {
1553 /* query SOC for source of interrupts */
1554 ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL);
1556 /* only proceed if PVR interrupts */
1557 if(ui32InterruptSource)
1558 {
1559 /* traverse the devices' ISR handlers */
1560 List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
1561 &PVRSRVSystemLISR_ForEachVaCb,
1562 &bStatus,
1563 &ui32InterruptSource,
1564 &ui32ClearInterrupts);
1566 SysClearInterrupts(psSysData, ui32ClearInterrupts);
1567 }
1568 /*out:*/
1569 }
1570 return bStatus;
1571 }
1574 static IMG_VOID PVRSRVMISR_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
1575 {
1576 if(psDeviceNode->pfnDeviceMISR != IMG_NULL)
1577 {
1578 (*psDeviceNode->pfnDeviceMISR)(psDeviceNode->pvISRData);
1579 }
1580 }
1582 /*!
1583 ******************************************************************************
1585 @Function PVRSRVMISR
1587 @Input pvSysData
1589 @Description
1590 OS-independent Medium-level Interrupt Service Routine
1592 ******************************************************************************/
1593 IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData)
1594 {
1595 SYS_DATA *psSysData = pvSysData;
1596 /* PVRSRV_DEVICE_NODE *psDeviceNode; */
1598 if(!psSysData)
1599 {
1600 PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n"));
1601 return;
1602 }
1604 /* Traverse the devices' MISR handlers. */
1605 List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
1606 &PVRSRVMISR_ForEachCb);
1608 /* Process the queues. */
1609 if (PVRSRVProcessQueues(IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED)
1610 {
1611 PVRSRVProcessQueues(IMG_FALSE);
1612 }
1614 /* signal global event object */
1615 if (psSysData->psGlobalEventObject)
1616 {
1617 IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
1618 if(hOSEventKM)
1619 {
1620 OSEventObjectSignalKM(hOSEventKM);
1621 }
1622 }
1623 }
1626 /*!
1627 ******************************************************************************
1629 @Function PVRSRVProcessConnect
1631 @Description Inform services that a process has connected.
1633 @Input ui32PID - process ID
1635 @Return PVRSRV_ERROR
1637 ******************************************************************************/
1638 IMG_EXPORT
1639 PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags)
1640 {
1641 return PVRSRVPerProcessDataConnect(ui32PID, ui32Flags);
1642 }
1645 /*!
1646 ******************************************************************************
1648 @Function PVRSRVProcessDisconnect
1650 @Description Inform services that a process has disconnected.
1652 @Input ui32PID - process ID
1654 @Return IMG_VOID
1656 ******************************************************************************/
1657 IMG_EXPORT
1658 IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID)
1659 {
1660 PVRSRVPerProcessDataDisconnect(ui32PID);
1661 }
1664 /*!
1665 ******************************************************************************
1667 @Function PVRSRVSaveRestoreLiveSegments
1669 @Input pArena - the arena the segment was originally allocated from.
1670 pbyBuffer - the system memory buffer set to null to get the size needed.
1671 puiBufSize - size of system memory buffer.
1672 bSave - IMG_TRUE if a save is required
1674 @Description
1675 Function to save or restore Resources Live segments
1677 ******************************************************************************/
1678 PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer,
1679 IMG_SIZE_T *puiBufSize, IMG_BOOL bSave)
1680 {
1681 IMG_SIZE_T uiBytesSaved = 0;
1682 IMG_PVOID pvLocalMemCPUVAddr;
1683 RA_SEGMENT_DETAILS sSegDetails;
1685 if (hArena == IMG_NULL)
1686 {
1687 return (PVRSRV_ERROR_INVALID_PARAMS);
1688 }
1690 sSegDetails.uiSize = 0;
1691 sSegDetails.sCpuPhyAddr.uiAddr = 0;
1692 sSegDetails.hSegment = 0;
1694 /* walk the arena segments and write live one to the buffer */
1695 while (RA_GetNextLiveSegment(hArena, &sSegDetails))
1696 {
1697 if (pbyBuffer == IMG_NULL)
1698 {
1699 /* calc buffer required */
1700 uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
1701 }
1702 else
1703 {
1704 if ((uiBytesSaved + sizeof(sSegDetails.uiSize) + sSegDetails.uiSize) > *puiBufSize)
1705 {
1706 return (PVRSRV_ERROR_OUT_OF_MEMORY);
1707 }
1709 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSaveRestoreLiveSegments: Base %08x size %08x", sSegDetails.sCpuPhyAddr.uiAddr, sSegDetails.uiSize));
1711 /* Map the device's local memory area onto the host. */
1712 pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
1713 sSegDetails.uiSize,
1714 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
1715 IMG_NULL);
1716 if (pvLocalMemCPUVAddr == IMG_NULL)
1717 {
1718 PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Failed to map local memory to host"));
1719 return (PVRSRV_ERROR_OUT_OF_MEMORY);
1720 }
1722 if (bSave)
1723 {
1724 /* write segment size then segment data */
1725 OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize));
1726 pbyBuffer += sizeof(sSegDetails.uiSize);
1728 OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr, sSegDetails.uiSize);
1729 pbyBuffer += sSegDetails.uiSize;
1730 }
1731 else
1732 {
1733 IMG_UINT32 uiSize;
1734 /* reag segment size and validate */
1735 OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize));
1737 if (uiSize != sSegDetails.uiSize)
1738 {
1739 PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Segment size error"));
1740 }
1741 else
1742 {
1743 pbyBuffer += sizeof(sSegDetails.uiSize);
1745 OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer, sSegDetails.uiSize);
1746 pbyBuffer += sSegDetails.uiSize;
1747 }
1748 }
1751 uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
1753 OSUnMapPhysToLin(pvLocalMemCPUVAddr,
1754 sSegDetails.uiSize,
1755 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
1756 IMG_NULL);
1757 }
1758 }
1760 if (pbyBuffer == IMG_NULL)
1761 {
1762 *puiBufSize = uiBytesSaved;
1763 }
1765 return (PVRSRV_OK);
1766 }
1769 /*!
1770 ******************************************************************************
1772 @Function PVRSRVGetErrorStringKM
1774 @Description Returns a text string relating to the PVRSRV_ERROR enum.
1776 @Note case statement used rather than an indexed arrary to ensure text is
1777 synchronised with the correct enum
1779 @Input eError : PVRSRV_ERROR enum
1781 @Return const IMG_CHAR * : Text string
1783 @Note Must be kept in sync with servicesext.h
1785 ******************************************************************************/
1787 IMG_EXPORT
1788 const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError)
1789 {
1790 /* PRQA S 5087 1 */ /* include file required here */
1791 #include "pvrsrv_errors.h"
1792 }
1794 static IMG_VOID PVRSRVCommandCompleteCallbacks_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
1795 {
1796 if(psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
1797 {
1798 /* Call the device's callback function. */
1799 (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
1800 }
1801 }
1803 /*!
1804 ******************************************************************************
1806 @Function PVRSRVScheduleDeviceCallbacks
1808 @Description Schedule all device callbacks
1810 @Return IMG_VOID
1812 ******************************************************************************/
1813 IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID)
1814 {
1815 SYS_DATA *psSysData;
1816 /* PVRSRV_DEVICE_NODE *psDeviceNode;*/
1818 SysAcquireData(&psSysData);
1820 /*for all the device, invoke the callback function*/
1821 List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
1822 &PVRSRVCommandCompleteCallbacks_ForEachCb);
1823 }
1825 /*!
1826 ******************************************************************************
1828 @Function PVRSRVScheduleDevices
1830 @Description Schedules all Services-Managed Devices to check their pending
1831 command queues. The intention is that ScheduleDevices be called by the
1832 3rd party BC driver after it has finished writing new data to its output
1833 texture.
1835 @Return IMG_VOID
1837 ******************************************************************************/
1838 IMG_EXPORT
1839 IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID)
1840 {
1841 PVRSRVScheduleDeviceCallbacks();
1842 }
1844 /*****************************************************************************
1845 End of file (pvrsrv.c)
1846 *****************************************************************************/