diff options
Diffstat (limited to 'sgx_km/eurasia_km/services4/srvkm/common/pvrsrv.c')
-rw-r--r-- | sgx_km/eurasia_km/services4/srvkm/common/pvrsrv.c | 1909 |
1 files changed, 1909 insertions, 0 deletions
diff --git a/sgx_km/eurasia_km/services4/srvkm/common/pvrsrv.c b/sgx_km/eurasia_km/services4/srvkm/common/pvrsrv.c new file mode 100644 index 0000000..e823db4 --- /dev/null +++ b/sgx_km/eurasia_km/services4/srvkm/common/pvrsrv.c | |||
@@ -0,0 +1,1909 @@ | |||
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 | ||
6 | |||
7 | The contents of this file are subject to the MIT license as set out below. | ||
8 | |||
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: | ||
15 | |||
16 | The above copyright notice and this permission notice shall be included in | ||
17 | all copies or substantial portions of the Software. | ||
18 | |||
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. | ||
22 | |||
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. | ||
30 | |||
31 | This License is also included in this distribution in the file called | ||
32 | "MIT-COPYING". | ||
33 | |||
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 | */ /**************************************************************************/ | ||
42 | |||
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" | ||
56 | |||
57 | #include "pvrversion.h" | ||
58 | |||
59 | #include "lists.h" | ||
60 | |||
61 | IMG_UINT32 g_ui32InitFlags; | ||
62 | |||
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 | ||
67 | |||
68 | /*! | ||
69 | ****************************************************************************** | ||
70 | |||
71 | @Function AllocateDeviceID | ||
72 | |||
73 | @Description | ||
74 | |||
75 | allocates a device id from the pool of valid ids | ||
76 | |||
77 | @input psSysData : system data | ||
78 | |||
79 | @input pui32DevID : device id to return | ||
80 | |||
81 | @Return device id | ||
82 | |||
83 | ******************************************************************************/ | ||
84 | PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID) | ||
85 | { | ||
86 | SYS_DEVICE_ID* psDeviceWalker; | ||
87 | SYS_DEVICE_ID* psDeviceEnd; | ||
88 | |||
89 | psDeviceWalker = &psSysData->sDeviceID[0]; | ||
90 | psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices; | ||
91 | |||
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 | } | ||
103 | |||
104 | PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!")); | ||
105 | |||
106 | /* Should never get here: sDeviceID[] may have been setup too small */ | ||
107 | PVR_ASSERT(psDeviceWalker < psDeviceEnd); | ||
108 | |||
109 | return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE; | ||
110 | } | ||
111 | |||
112 | |||
113 | /*! | ||
114 | ****************************************************************************** | ||
115 | |||
116 | @Function FreeDeviceID | ||
117 | |||
118 | @Description | ||
119 | |||
120 | frees a device id from the pool of valid ids | ||
121 | |||
122 | @input psSysData : system data | ||
123 | |||
124 | @input ui32DevID : device id to free | ||
125 | |||
126 | @Return device id | ||
127 | |||
128 | ******************************************************************************/ | ||
129 | PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID) | ||
130 | { | ||
131 | SYS_DEVICE_ID* psDeviceWalker; | ||
132 | SYS_DEVICE_ID* psDeviceEnd; | ||
133 | |||
134 | psDeviceWalker = &psSysData->sDeviceID[0]; | ||
135 | psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices; | ||
136 | |||
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 | } | ||
151 | |||
152 | PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!")); | ||
153 | |||
154 | /* should never get here */ | ||
155 | PVR_ASSERT(psDeviceWalker < psDeviceEnd); | ||
156 | |||
157 | return PVRSRV_ERROR_INVALID_DEVICEID; | ||
158 | } | ||
159 | /*! | ||
160 | ****************************************************************************** | ||
161 | |||
162 | @Function PVRSRVCompatCheckKM | ||
163 | |||
164 | @Description UM/KM ddk branch Compatibility check function | ||
165 | |||
166 | @input psUserModeDDKDetails: User mode DDK version | ||
167 | |||
168 | @output In case of incompatibility, returns PVRSRV_ERROR_DDK_VERSION_MISMATCH | ||
169 | |||
170 | @Return PVRSRV_ERROR | ||
171 | |||
172 | ******************************************************************************/ | ||
173 | IMG_VOID IMG_CALLCONV PVRSRVCompatCheckKM(PVRSRV_BRIDGE_IN_COMPAT_CHECK *psUserModeDDKDetails, PVRSRV_BRIDGE_RETURN *psRetOUT) | ||
174 | { | ||
175 | #if defined(SUPPORT_TI_VERSION_STRING) | ||
176 | SYS_DATA *psSysData; | ||
177 | |||
178 | SysAcquireData(&psSysData); | ||
179 | #endif | ||
180 | |||
181 | if(psUserModeDDKDetails->ui32DDKVersion != ((PVRVERSION_MAJ << 16) | (PVRVERSION_MIN << 8)) | ||
182 | || (psUserModeDDKDetails->ui32DDKBuild != PVRVERSION_BUILD)) | ||
183 | { | ||
184 | psRetOUT->eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH; | ||
185 | PVR_LOG(("(FAIL) UM-KM DDK Mismatch UM-(%d) KM-(%d).", | ||
186 | psUserModeDDKDetails->ui32DDKBuild, PVRVERSION_BUILD)); | ||
187 | } | ||
188 | else | ||
189 | { | ||
190 | psRetOUT->eError = PVRSRV_OK; | ||
191 | PVR_LOG(("UM DDK-(%d) and KM DDK-(%d) match. [ OK ]", | ||
192 | psUserModeDDKDetails->ui32DDKBuild ,PVRVERSION_BUILD)); | ||
193 | } | ||
194 | |||
195 | #if defined(SUPPORT_TI_VERSION_STRING) | ||
196 | /* If TI version string is supported, populate it here. This will show | ||
197 | * up in proc entry. | ||
198 | * Probably a bad place to do this. FIXME | ||
199 | */ | ||
200 | memcpy(psSysData->szTIVersion, psUserModeDDKDetails->szTIVersion, 64); | ||
201 | #endif | ||
202 | } | ||
203 | |||
204 | /*! | ||
205 | ****************************************************************************** | ||
206 | |||
207 | @Function ReadHWReg | ||
208 | |||
209 | @Description | ||
210 | |||
211 | register access function | ||
212 | |||
213 | @input pvLinRegBaseAddr : lin addr of register block base | ||
214 | |||
215 | @input ui32Offset : byte offset from register base | ||
216 | |||
217 | @Return register value | ||
218 | |||
219 | ******************************************************************************/ | ||
220 | #ifndef ReadHWReg | ||
221 | IMG_EXPORT | ||
222 | IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset) | ||
223 | { | ||
224 | return *(volatile IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset); | ||
225 | } | ||
226 | #endif | ||
227 | |||
228 | |||
229 | /*! | ||
230 | ****************************************************************************** | ||
231 | |||
232 | @Function WriteHWReg | ||
233 | |||
234 | @Description | ||
235 | |||
236 | register access function | ||
237 | |||
238 | @input pvLinRegBaseAddr : lin addr of register block base | ||
239 | |||
240 | @input ui32Offset : byte offset from register base | ||
241 | |||
242 | @input ui32Value : value to write to register | ||
243 | |||
244 | @Return register value : original reg. value | ||
245 | |||
246 | ******************************************************************************/ | ||
247 | #ifndef WriteHWReg | ||
248 | IMG_EXPORT | ||
249 | IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value) | ||
250 | { | ||
251 | PVR_DPF((PVR_DBG_MESSAGE,"WriteHWReg Base:%p, Offset: %x, Value %x", | ||
252 | pvLinRegBaseAddr,ui32Offset,ui32Value)); | ||
253 | |||
254 | *(IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset) = ui32Value; | ||
255 | } | ||
256 | #endif | ||
257 | |||
258 | |||
259 | /*! | ||
260 | ****************************************************************************** | ||
261 | |||
262 | @Function WriteHWRegs | ||
263 | |||
264 | @Description | ||
265 | |||
266 | register access function | ||
267 | |||
268 | @input pvLinRegBaseAddr : lin addr of register block base | ||
269 | |||
270 | @input ui32Count : register count | ||
271 | |||
272 | @input psHWRegs : address/value register list | ||
273 | |||
274 | @Return none | ||
275 | |||
276 | ******************************************************************************/ | ||
277 | #ifndef WriteHWRegs | ||
278 | IMG_EXPORT | ||
279 | IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs) | ||
280 | { | ||
281 | while (ui32Count) | ||
282 | { | ||
283 | WriteHWReg (pvLinRegBaseAddr, psHWRegs->ui32RegAddr, psHWRegs->ui32RegVal); | ||
284 | psHWRegs++; | ||
285 | ui32Count--; | ||
286 | } | ||
287 | } | ||
288 | #endif | ||
289 | |||
290 | /*! | ||
291 | ****************************************************************************** | ||
292 | @Function PVRSRVEnumerateDCKM_ForEachVaCb | ||
293 | |||
294 | @Description | ||
295 | |||
296 | Enumerates the device node (if is of the same class as given). | ||
297 | |||
298 | @Input psDeviceNode - The device node to be enumerated | ||
299 | va - variable arguments list, with: | ||
300 | pui32DevCount - The device count pointer (to be increased) | ||
301 | ppui32DevID - The pointer to the device IDs pointer (to be updated and increased) | ||
302 | ******************************************************************************/ | ||
303 | static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) | ||
304 | { | ||
305 | IMG_UINT *pui32DevCount; | ||
306 | PVRSRV_DEVICE_IDENTIFIER **ppsDevIdList; | ||
307 | |||
308 | pui32DevCount = va_arg(va, IMG_UINT*); | ||
309 | ppsDevIdList = va_arg(va, PVRSRV_DEVICE_IDENTIFIER**); | ||
310 | |||
311 | if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT) | ||
312 | { | ||
313 | *(*ppsDevIdList) = psDeviceNode->sDevId; | ||
314 | (*ppsDevIdList)++; | ||
315 | (*pui32DevCount)++; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | |||
320 | |||
321 | /*! | ||
322 | ****************************************************************************** | ||
323 | |||
324 | @Function PVRSRVEnumerateDevicesKM | ||
325 | |||
326 | @Description | ||
327 | This function will enumerate all the devices supported by the | ||
328 | PowerVR services within the target system. | ||
329 | The function returns a list of the device ID strcutres stored either in | ||
330 | the services or constructed in the user mode glue component in certain | ||
331 | environments. The number of devices in the list is also returned. | ||
332 | |||
333 | In a binary layered component which does not support dynamic runtime selection, | ||
334 | the glue code should compile to return the supported devices statically, | ||
335 | e.g. multiple instances of the same device if multiple devices are supported, | ||
336 | or the target combination of MBX and display device. | ||
337 | |||
338 | In the case of an environment (for instance) where one MBX1 may connect to two | ||
339 | display devices this code would enumerate all three devices and even | ||
340 | non-dynamic MBX1 selection code should retain the facility to parse the list | ||
341 | to find the index of the MBX device | ||
342 | |||
343 | @output pui32NumDevices : On success, contains the number of devices present | ||
344 | in the system | ||
345 | |||
346 | @output psDevIdList : Pointer to called supplied buffer to receive the | ||
347 | list of PVRSRV_DEVICE_IDENTIFIER | ||
348 | |||
349 | @return PVRSRV_ERROR : PVRSRV_NO_ERROR | ||
350 | |||
351 | ******************************************************************************/ | ||
352 | IMG_EXPORT | ||
353 | PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices, | ||
354 | PVRSRV_DEVICE_IDENTIFIER *psDevIdList) | ||
355 | { | ||
356 | SYS_DATA *psSysData; | ||
357 | /* PVRSRV_DEVICE_NODE *psDeviceNode; */ | ||
358 | IMG_UINT32 i; | ||
359 | |||
360 | if (!pui32NumDevices || !psDevIdList) | ||
361 | { | ||
362 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params")); | ||
363 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
364 | } | ||
365 | |||
366 | SysAcquireData(&psSysData); | ||
367 | |||
368 | /* | ||
369 | setup input buffer to be `empty' | ||
370 | */ | ||
371 | for (i=0; i<PVRSRV_MAX_DEVICES; i++) | ||
372 | { | ||
373 | psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN; | ||
374 | } | ||
375 | |||
376 | /* and zero device count */ | ||
377 | *pui32NumDevices = 0; | ||
378 | |||
379 | /* | ||
380 | Search through the device list for services managed devices | ||
381 | return id info for each device and the number of devices | ||
382 | available | ||
383 | */ | ||
384 | List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList, | ||
385 | &PVRSRVEnumerateDevicesKM_ForEachVaCb, | ||
386 | pui32NumDevices, | ||
387 | &psDevIdList); | ||
388 | |||
389 | |||
390 | return PVRSRV_OK; | ||
391 | } | ||
392 | |||
393 | |||
394 | /*! | ||
395 | ****************************************************************************** | ||
396 | |||
397 | @Function PVRSRVInit | ||
398 | |||
399 | @Description Initialise services | ||
400 | |||
401 | @Input psSysData : sysdata structure | ||
402 | |||
403 | @Return PVRSRV_ERROR : | ||
404 | |||
405 | ******************************************************************************/ | ||
406 | PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData) | ||
407 | { | ||
408 | PVRSRV_ERROR eError; | ||
409 | |||
410 | /* Initialise Resource Manager */ | ||
411 | eError = ResManInit(); | ||
412 | if (eError != PVRSRV_OK) | ||
413 | { | ||
414 | goto Error; | ||
415 | } | ||
416 | |||
417 | eError = PVRSRVPerProcessDataInit(); | ||
418 | if(eError != PVRSRV_OK) | ||
419 | { | ||
420 | goto Error; | ||
421 | } | ||
422 | |||
423 | /* Initialise handles */ | ||
424 | eError = PVRSRVHandleInit(); | ||
425 | if(eError != PVRSRV_OK) | ||
426 | { | ||
427 | goto Error; | ||
428 | } | ||
429 | |||
430 | /* Initialise Power Manager Lock */ | ||
431 | eError = OSCreateResource(&psSysData->sPowerStateChangeResource); | ||
432 | if (eError != PVRSRV_OK) | ||
433 | { | ||
434 | goto Error; | ||
435 | } | ||
436 | |||
437 | /* Initialise system power state */ | ||
438 | psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0; | ||
439 | psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified; | ||
440 | |||
441 | /* Create an event object */ | ||
442 | if((eError = OSAllocMem( PVRSRV_PAGEABLE_SELECT, | ||
443 | sizeof(PVRSRV_EVENTOBJECT) , | ||
444 | (IMG_VOID **)&psSysData->psGlobalEventObject, 0, | ||
445 | "Event Object")) != PVRSRV_OK) | ||
446 | { | ||
447 | |||
448 | goto Error; | ||
449 | } | ||
450 | |||
451 | if((eError = OSEventObjectCreateKM("PVRSRV_GLOBAL_EVENTOBJECT", psSysData->psGlobalEventObject)) != PVRSRV_OK) | ||
452 | { | ||
453 | goto Error; | ||
454 | } | ||
455 | |||
456 | /* Store OS high res timer fallbacks, the system is free to overide these */ | ||
457 | psSysData->pfnHighResTimerCreate = OSFuncHighResTimerCreate; | ||
458 | psSysData->pfnHighResTimerGetus = OSFuncHighResTimerGetus; | ||
459 | psSysData->pfnHighResTimerDestroy = OSFuncHighResTimerDestroy; | ||
460 | |||
461 | #if defined(TTRACE) | ||
462 | eError = PVRSRVTimeTraceInit(); | ||
463 | if (eError != PVRSRV_OK) | ||
464 | goto Error; | ||
465 | g_ui32InitFlags |= INIT_DATA_ENABLE_TTRACE; | ||
466 | #endif | ||
467 | |||
468 | #if defined(PDUMP) | ||
469 | /* Initialise pdump */ | ||
470 | PDUMPINIT(); | ||
471 | g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT; | ||
472 | #endif | ||
473 | |||
474 | #if defined(SUPPORT_ION) || defined(SUPPORT_DMABUF) | ||
475 | eError = PVRSRVInitDeviceMem(); | ||
476 | if (eError != PVRSRV_OK) | ||
477 | goto Error; | ||
478 | g_ui32InitFlags |= INIT_DATA_ENABLE_DEVMEM; | ||
479 | #endif | ||
480 | |||
481 | PERFINIT(); | ||
482 | return eError; | ||
483 | |||
484 | Error: | ||
485 | PVRSRVDeInit(psSysData); | ||
486 | return eError; | ||
487 | } | ||
488 | |||
489 | |||
490 | |||
491 | /*! | ||
492 | ****************************************************************************** | ||
493 | |||
494 | @Function PVRSRVDeInit | ||
495 | |||
496 | @Description De-Initialise services | ||
497 | |||
498 | @Input psSysData : sysdata structure | ||
499 | |||
500 | @Return PVRSRV_ERROR : | ||
501 | |||
502 | ******************************************************************************/ | ||
503 | IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData) | ||
504 | { | ||
505 | PVRSRV_ERROR eError; | ||
506 | |||
507 | PVR_UNREFERENCED_PARAMETER(psSysData); | ||
508 | |||
509 | if (psSysData == IMG_NULL) | ||
510 | { | ||
511 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param")); | ||
512 | return; | ||
513 | } | ||
514 | |||
515 | PERFDEINIT(); | ||
516 | |||
517 | |||
518 | #if defined(SUPPORT_ION) || defined(SUPPORT_DMABUF) | ||
519 | if ((g_ui32InitFlags & INIT_DATA_ENABLE_DEVMEM) > 0) | ||
520 | { | ||
521 | PVRSRVDeInitDeviceMem(); | ||
522 | } | ||
523 | #endif | ||
524 | |||
525 | #if defined(MEM_TRACK_INFO_DEBUG) | ||
526 | /* Free the list of memory operations */ | ||
527 | PVRSRVFreeMemOps(); | ||
528 | #endif | ||
529 | |||
530 | #if defined(TTRACE) | ||
531 | /* deinitialise ttrace */ | ||
532 | if ((g_ui32InitFlags & INIT_DATA_ENABLE_TTRACE) > 0) | ||
533 | { | ||
534 | PVRSRVTimeTraceDeinit(); | ||
535 | } | ||
536 | #endif | ||
537 | |||
538 | #if defined(PDUMP) | ||
539 | /* deinitialise pdump */ | ||
540 | if( (g_ui32InitFlags & INIT_DATA_ENABLE_PDUMPINIT) > 0) | ||
541 | { | ||
542 | PDUMPDEINIT(); | ||
543 | } | ||
544 | #endif | ||
545 | |||
546 | /* destroy event object */ | ||
547 | if(psSysData->psGlobalEventObject) | ||
548 | { | ||
549 | OSEventObjectDestroyKM(psSysData->psGlobalEventObject); | ||
550 | OSFreeMem( PVRSRV_PAGEABLE_SELECT, | ||
551 | sizeof(PVRSRV_EVENTOBJECT), | ||
552 | psSysData->psGlobalEventObject, | ||
553 | 0); | ||
554 | psSysData->psGlobalEventObject = IMG_NULL; | ||
555 | } | ||
556 | |||
557 | eError = PVRSRVHandleDeInit(); | ||
558 | if (eError != PVRSRV_OK) | ||
559 | { | ||
560 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed")); | ||
561 | } | ||
562 | |||
563 | eError = PVRSRVPerProcessDataDeInit(); | ||
564 | if (eError != PVRSRV_OK) | ||
565 | { | ||
566 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed")); | ||
567 | } | ||
568 | |||
569 | ResManDeInit(); | ||
570 | } | ||
571 | |||
572 | |||
573 | /*! | ||
574 | ****************************************************************************** | ||
575 | |||
576 | @Function PVRSRVRegisterDevice | ||
577 | |||
578 | @Description | ||
579 | |||
580 | registers a device with the system | ||
581 | |||
582 | @Input psSysData : sysdata structure | ||
583 | |||
584 | @Input pfnRegisterDevice : device registration function | ||
585 | |||
586 | @Input ui32SOCInterruptBit : SoC interrupt bit for this device | ||
587 | |||
588 | @Output pui32DeviceIndex : unique device key (for case of multiple identical devices) | ||
589 | |||
590 | @Return PVRSRV_ERROR : | ||
591 | |||
592 | ******************************************************************************/ | ||
593 | PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData, | ||
594 | PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*), | ||
595 | IMG_UINT32 ui32SOCInterruptBit, | ||
596 | IMG_UINT32 *pui32DeviceIndex) | ||
597 | { | ||
598 | PVRSRV_ERROR eError; | ||
599 | PVRSRV_DEVICE_NODE *psDeviceNode; | ||
600 | |||
601 | /* Allocate device node */ | ||
602 | if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
603 | sizeof(PVRSRV_DEVICE_NODE), | ||
604 | (IMG_VOID **)&psDeviceNode, IMG_NULL, | ||
605 | "Device Node") != PVRSRV_OK) | ||
606 | { | ||
607 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode")); | ||
608 | return (PVRSRV_ERROR_OUT_OF_MEMORY); | ||
609 | } | ||
610 | OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE)); | ||
611 | |||
612 | eError = pfnRegisterDevice(psDeviceNode); | ||
613 | if (eError != PVRSRV_OK) | ||
614 | { | ||
615 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
616 | sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL); | ||
617 | /*not nulling pointer, out of scope*/ | ||
618 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device")); | ||
619 | return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED); | ||
620 | } | ||
621 | |||
622 | /* | ||
623 | make the refcount 1 and test on this to initialise device | ||
624 | at acquiredevinfo. On release if refcount is 1, deinitialise | ||
625 | and when refcount is 0 (sysdata de-alloc) deallocate the device | ||
626 | structures | ||
627 | */ | ||
628 | psDeviceNode->ui32RefCount = 1; | ||
629 | psDeviceNode->psSysData = psSysData; | ||
630 | psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit; | ||
631 | |||
632 | /* all devices need a unique identifier */ | ||
633 | AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex); | ||
634 | |||
635 | /* and finally insert the device into the dev-list */ | ||
636 | List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode); | ||
637 | |||
638 | /* and copy back index */ | ||
639 | *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex; | ||
640 | |||
641 | return PVRSRV_OK; | ||
642 | } | ||
643 | |||
644 | |||
645 | /*! | ||
646 | ****************************************************************************** | ||
647 | |||
648 | @Function PVRSRVInitialiseDevice | ||
649 | |||
650 | @Description | ||
651 | |||
652 | initialises device by index | ||
653 | |||
654 | @Input ui32DevIndex : Index to the required device | ||
655 | |||
656 | @Return PVRSRV_ERROR : | ||
657 | |||
658 | ******************************************************************************/ | ||
659 | PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex) | ||
660 | { | ||
661 | PVRSRV_DEVICE_NODE *psDeviceNode; | ||
662 | SYS_DATA *psSysData; | ||
663 | PVRSRV_ERROR eError; | ||
664 | |||
665 | PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice")); | ||
666 | |||
667 | SysAcquireData(&psSysData); | ||
668 | |||
669 | /* Find device in the list */ | ||
670 | psDeviceNode = (PVRSRV_DEVICE_NODE*) | ||
671 | List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, | ||
672 | &MatchDeviceKM_AnyVaCb, | ||
673 | ui32DevIndex, | ||
674 | IMG_TRUE); | ||
675 | if(!psDeviceNode) | ||
676 | { | ||
677 | /* Devinfo not in the list */ | ||
678 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: requested device is not present")); | ||
679 | return PVRSRV_ERROR_INIT_FAILURE; | ||
680 | } | ||
681 | /* | ||
682 | FoundDevice: | ||
683 | */ | ||
684 | |||
685 | PVR_ASSERT (psDeviceNode->ui32RefCount > 0); | ||
686 | |||
687 | /* | ||
688 | Create the device's resource manager context. | ||
689 | */ | ||
690 | eError = PVRSRVResManConnect(IMG_NULL, &psDeviceNode->hResManContext); | ||
691 | if (eError != PVRSRV_OK) | ||
692 | { | ||
693 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed PVRSRVResManConnect call")); | ||
694 | return eError; | ||
695 | } | ||
696 | |||
697 | /* Initialise the device */ | ||
698 | if(psDeviceNode->pfnInitDevice != IMG_NULL) | ||
699 | { | ||
700 | eError = psDeviceNode->pfnInitDevice(psDeviceNode); | ||
701 | if (eError != PVRSRV_OK) | ||
702 | { | ||
703 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed InitDevice call")); | ||
704 | return eError; | ||
705 | } | ||
706 | } | ||
707 | |||
708 | return PVRSRV_OK; | ||
709 | } | ||
710 | |||
711 | |||
712 | static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode) | ||
713 | { | ||
714 | PVRSRV_ERROR eError; | ||
715 | |||
716 | eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE); | ||
717 | if (eError != PVRSRV_OK) | ||
718 | { | ||
719 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVPowerLock call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex)); | ||
720 | return eError; | ||
721 | } | ||
722 | |||
723 | eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex, | ||
724 | PVRSRV_DEV_POWER_STATE_DEFAULT); | ||
725 | PVRSRVPowerUnlock(KERNEL_ID); | ||
726 | if (eError != PVRSRV_OK) | ||
727 | { | ||
728 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex)); | ||
729 | } | ||
730 | return eError; | ||
731 | } | ||
732 | |||
733 | /*wraps the PVRSRVDevInitCompatCheck call and prints a debugging message if failed*/ | ||
734 | static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode) | ||
735 | { | ||
736 | PVRSRV_ERROR eError; | ||
737 | eError = PVRSRVDevInitCompatCheck(psDeviceNode); | ||
738 | if (eError != PVRSRV_OK) | ||
739 | { | ||
740 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex)); | ||
741 | } | ||
742 | return eError; | ||
743 | } | ||
744 | |||
745 | |||
746 | /*! | ||
747 | ****************************************************************************** | ||
748 | |||
749 | @Function PVRSRVFinaliseSystem | ||
750 | |||
751 | @Description | ||
752 | |||
753 | Final part of system initialisation. | ||
754 | |||
755 | @Input ui32DevIndex : Index to the required device | ||
756 | |||
757 | @Return PVRSRV_ERROR : | ||
758 | |||
759 | ******************************************************************************/ | ||
760 | PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful) | ||
761 | { | ||
762 | /* PVRSRV_DEVICE_NODE *psDeviceNode;*/ | ||
763 | SYS_DATA *psSysData; | ||
764 | PVRSRV_ERROR eError; | ||
765 | |||
766 | PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem")); | ||
767 | |||
768 | SysAcquireData(&psSysData); | ||
769 | |||
770 | if (bInitSuccessful) | ||
771 | { | ||
772 | eError = SysFinalise(); | ||
773 | if (eError != PVRSRV_OK) | ||
774 | { | ||
775 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: SysFinalise failed (%d)", eError)); | ||
776 | return eError; | ||
777 | } | ||
778 | |||
779 | /* Place all devices into their default power state. */ | ||
780 | eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList, | ||
781 | &PVRSRVFinaliseSystem_SetPowerState_AnyCb); | ||
782 | if (eError != PVRSRV_OK) | ||
783 | { | ||
784 | return eError; | ||
785 | } | ||
786 | |||
787 | /* Verify microkernel compatibility for devices */ | ||
788 | eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList, | ||
789 | &PVRSRVFinaliseSystem_CompatCheck_AnyCb); | ||
790 | if (eError != PVRSRV_OK) | ||
791 | { | ||
792 | return eError; | ||
793 | } | ||
794 | } | ||
795 | |||
796 | /* Some platforms call this too early in the boot phase. */ | ||
797 | PDUMPENDINITPHASE(); | ||
798 | |||
799 | return PVRSRV_OK; | ||
800 | } | ||
801 | |||
802 | |||
803 | PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode) | ||
804 | { | ||
805 | /* Only check devices which specify a compatibility check callback */ | ||
806 | if (psDeviceNode->pfnInitDeviceCompatCheck) | ||
807 | return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode); | ||
808 | else | ||
809 | return PVRSRV_OK; | ||
810 | } | ||
811 | |||
812 | /*! | ||
813 | ****************************************************************************** | ||
814 | |||
815 | @Function PVRSRVAcquireDeviceDataKM | ||
816 | |||
817 | @Description | ||
818 | |||
819 | Matchs a device given a device type and a device index. | ||
820 | |||
821 | @input psDeviceNode :The device node to be matched. | ||
822 | |||
823 | @Input va : Variable argument list with: | ||
824 | eDeviceType : Required device type. If type is unknown use ui32DevIndex | ||
825 | to locate device data | ||
826 | |||
827 | ui32DevIndex : Index to the required device obtained from the | ||
828 | PVRSRVEnumerateDevice function | ||
829 | |||
830 | @Return PVRSRV_ERROR : | ||
831 | |||
832 | ******************************************************************************/ | ||
833 | static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) | ||
834 | { | ||
835 | PVRSRV_DEVICE_TYPE eDeviceType; | ||
836 | IMG_UINT32 ui32DevIndex; | ||
837 | |||
838 | eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE); | ||
839 | ui32DevIndex = va_arg(va, IMG_UINT32); | ||
840 | |||
841 | if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN && | ||
842 | psDeviceNode->sDevId.eDeviceType == eDeviceType) || | ||
843 | (eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN && | ||
844 | psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)) | ||
845 | { | ||
846 | return psDeviceNode; | ||
847 | } | ||
848 | else | ||
849 | { | ||
850 | return IMG_NULL; | ||
851 | } | ||
852 | } | ||
853 | |||
854 | /*! | ||
855 | ****************************************************************************** | ||
856 | |||
857 | @Function PVRSRVAcquireDeviceDataKM | ||
858 | |||
859 | @Description | ||
860 | |||
861 | Returns device information | ||
862 | |||
863 | @Input ui32DevIndex : Index to the required device obtained from the | ||
864 | PVRSRVEnumerateDevice function | ||
865 | |||
866 | @Input eDeviceType : Required device type. If type is unknown use ui32DevIndex | ||
867 | to locate device data | ||
868 | |||
869 | @Output *phDevCookie : Dev Cookie | ||
870 | |||
871 | |||
872 | @Return PVRSRV_ERROR : | ||
873 | |||
874 | ******************************************************************************/ | ||
875 | IMG_EXPORT | ||
876 | PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex, | ||
877 | PVRSRV_DEVICE_TYPE eDeviceType, | ||
878 | IMG_HANDLE *phDevCookie) | ||
879 | { | ||
880 | PVRSRV_DEVICE_NODE *psDeviceNode; | ||
881 | SYS_DATA *psSysData; | ||
882 | |||
883 | PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM")); | ||
884 | |||
885 | SysAcquireData(&psSysData); | ||
886 | |||
887 | /* Find device in the list */ | ||
888 | psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, | ||
889 | &PVRSRVAcquireDeviceDataKM_Match_AnyVaCb, | ||
890 | eDeviceType, | ||
891 | ui32DevIndex); | ||
892 | |||
893 | |||
894 | if (!psDeviceNode) | ||
895 | { | ||
896 | /* device can't be found in the list so it isn't in the system */ | ||
897 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present")); | ||
898 | return PVRSRV_ERROR_INIT_FAILURE; | ||
899 | } | ||
900 | |||
901 | /*FoundDevice:*/ | ||
902 | |||
903 | PVR_ASSERT (psDeviceNode->ui32RefCount > 0); | ||
904 | |||
905 | /* return the dev cookie? */ | ||
906 | if (phDevCookie) | ||
907 | { | ||
908 | *phDevCookie = (IMG_HANDLE)psDeviceNode; | ||
909 | } | ||
910 | |||
911 | return PVRSRV_OK; | ||
912 | } | ||
913 | |||
914 | |||
915 | /*! | ||
916 | ****************************************************************************** | ||
917 | |||
918 | @Function PVRSRVDeinitialiseDevice | ||
919 | |||
920 | @Description | ||
921 | |||
922 | This De-inits device | ||
923 | |||
924 | @Input ui32DevIndex : Index to the required device | ||
925 | |||
926 | @Return PVRSRV_ERROR : | ||
927 | |||
928 | ******************************************************************************/ | ||
929 | PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex) | ||
930 | { | ||
931 | PVRSRV_DEVICE_NODE *psDeviceNode; | ||
932 | SYS_DATA *psSysData; | ||
933 | PVRSRV_ERROR eError; | ||
934 | |||
935 | SysAcquireData(&psSysData); | ||
936 | |||
937 | psDeviceNode = (PVRSRV_DEVICE_NODE*) | ||
938 | List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, | ||
939 | &MatchDeviceKM_AnyVaCb, | ||
940 | ui32DevIndex, | ||
941 | IMG_TRUE); | ||
942 | |||
943 | if (!psDeviceNode) | ||
944 | { | ||
945 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: requested device %d is not present", ui32DevIndex)); | ||
946 | return PVRSRV_ERROR_DEVICEID_NOT_FOUND; | ||
947 | } | ||
948 | |||
949 | eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE); | ||
950 | if (eError != PVRSRV_OK) | ||
951 | { | ||
952 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVPowerLock call")); | ||
953 | return eError; | ||
954 | } | ||
955 | |||
956 | /* | ||
957 | Power down the device if necessary. | ||
958 | */ | ||
959 | eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex, | ||
960 | PVRSRV_DEV_POWER_STATE_OFF); | ||
961 | PVRSRVPowerUnlock(KERNEL_ID); | ||
962 | if (eError != PVRSRV_OK) | ||
963 | { | ||
964 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call")); | ||
965 | return eError; | ||
966 | } | ||
967 | |||
968 | /* | ||
969 | Free the dissociated device memory. | ||
970 | */ | ||
971 | eError = ResManFreeResByCriteria(psDeviceNode->hResManContext, | ||
972 | RESMAN_CRITERIA_RESTYPE, | ||
973 | RESMAN_TYPE_DEVICEMEM_ALLOCATION, | ||
974 | IMG_NULL, 0); | ||
975 | if (eError != PVRSRV_OK) | ||
976 | { | ||
977 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call")); | ||
978 | return eError; | ||
979 | } | ||
980 | |||
981 | /* | ||
982 | De-init the device. | ||
983 | */ | ||
984 | if(psDeviceNode->pfnDeInitDevice != IMG_NULL) | ||
985 | { | ||
986 | eError = psDeviceNode->pfnDeInitDevice(psDeviceNode); | ||
987 | if (eError != PVRSRV_OK) | ||
988 | { | ||
989 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed DeInitDevice call")); | ||
990 | return eError; | ||
991 | } | ||
992 | } | ||
993 | |||
994 | /* | ||
995 | Close the device's resource manager context. | ||
996 | */ | ||
997 | PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE); | ||
998 | psDeviceNode->hResManContext = IMG_NULL; | ||
999 | |||
1000 | /* remove node from list */ | ||
1001 | List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode); | ||
1002 | |||
1003 | /* deallocate id and memory */ | ||
1004 | (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex); | ||
1005 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
1006 | sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL); | ||
1007 | /*not nulling pointer, out of scope*/ | ||
1008 | |||
1009 | return (PVRSRV_OK); | ||
1010 | } | ||
1011 | |||
1012 | |||
1013 | IMG_EXPORT | ||
1014 | PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr, | ||
1015 | IMG_UINT32 ui32Value, | ||
1016 | IMG_UINT32 ui32Mask, | ||
1017 | IMG_UINT32 ui32Timeoutus, | ||
1018 | IMG_UINT32 ui32PollPeriodus, | ||
1019 | IMG_BOOL bAllowPreemption) | ||
1020 | { | ||
1021 | #if defined (EMULATOR) | ||
1022 | { | ||
1023 | PVR_UNREFERENCED_PARAMETER(bAllowPreemption); | ||
1024 | #if !defined(__linux__) | ||
1025 | PVR_UNREFERENCED_PARAMETER(ui32PollPeriodus); | ||
1026 | #endif | ||
1027 | |||
1028 | /* For the Emulator we want the system to stop when a lock-up is detected so the state can be analysed. | ||
1029 | * Also the Emulator is much slower than real silicon so timeouts are not valid. | ||
1030 | */ | ||
1031 | if((*pui32LinMemAddr & ui32Mask) == ui32Value) | ||
1032 | { | ||
1033 | return PVRSRV_OK; | ||
1034 | } | ||
1035 | |||
1036 | do | ||
1037 | { | ||
1038 | #if defined(__linux__) | ||
1039 | OSWaitus(ui32PollPeriodus); | ||
1040 | #else | ||
1041 | OSReleaseThreadQuanta(); | ||
1042 | #endif | ||
1043 | |||
1044 | if((*pui32LinMemAddr & ui32Mask) == ui32Value) | ||
1045 | { | ||
1046 | return PVRSRV_OK; | ||
1047 | } | ||
1048 | |||
1049 | } while (ui32Timeoutus); /* Endless loop only for the Emulator */ | ||
1050 | } | ||
1051 | #else | ||
1052 | { | ||
1053 | IMG_UINT32 ui32ActualValue = 0xFFFFFFFFU; /* Initialiser only required to prevent incorrect warning */ | ||
1054 | |||
1055 | if (bAllowPreemption) | ||
1056 | { | ||
1057 | PVR_ASSERT(ui32PollPeriodus >= 1000); | ||
1058 | } | ||
1059 | |||
1060 | ui32ActualValue = (*pui32LinMemAddr & ui32Mask); | ||
1061 | if(ui32ActualValue == ui32Value) | ||
1062 | { | ||
1063 | return PVRSRV_OK; | ||
1064 | } | ||
1065 | |||
1066 | /* PRQA S 3415,4109 1 */ /* macro format critical - leave alone */ | ||
1067 | LOOP_UNTIL_TIMEOUT(ui32Timeoutus) | ||
1068 | { | ||
1069 | if (bAllowPreemption) | ||
1070 | { | ||
1071 | OSSleepms(ui32PollPeriodus / 1000); | ||
1072 | } | ||
1073 | else | ||
1074 | { | ||
1075 | OSWaitus(ui32PollPeriodus); | ||
1076 | } | ||
1077 | |||
1078 | ui32ActualValue = (*pui32LinMemAddr & ui32Mask); | ||
1079 | if(ui32ActualValue == ui32Value) | ||
1080 | { | ||
1081 | return PVRSRV_OK; | ||
1082 | } | ||
1083 | |||
1084 | } END_LOOP_UNTIL_TIMEOUT(); | ||
1085 | |||
1086 | PVR_DPF((PVR_DBG_ERROR,"PollForValueKM: Timeout. Expected 0x%x but found 0x%x (mask 0x%x).", | ||
1087 | ui32Value, ui32ActualValue, ui32Mask)); | ||
1088 | } | ||
1089 | #endif /* #if defined (EMULATOR) */ | ||
1090 | |||
1091 | return PVRSRV_ERROR_TIMEOUT; | ||
1092 | } | ||
1093 | |||
1094 | |||
1095 | /*Level 3 of the loop nesting*/ | ||
1096 | static IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, va_list va) | ||
1097 | { | ||
1098 | IMG_CHAR **ppszStr; | ||
1099 | IMG_UINT32 *pui32StrLen; | ||
1100 | IMG_UINT32 ui32Mode; | ||
1101 | PVRSRV_ERROR (*pfnGetStats)(RA_ARENA *, IMG_CHAR **, IMG_UINT32 *); | ||
1102 | |||
1103 | ppszStr = va_arg(va, IMG_CHAR**); | ||
1104 | pui32StrLen = va_arg(va, IMG_UINT32*); | ||
1105 | ui32Mode = va_arg(va, IMG_UINT32); | ||
1106 | |||
1107 | /* Would be better to pass fn pointer in the variable args list | ||
1108 | * but MS C compiler complains with error C2066: In ANSI C, | ||
1109 | * it is not legal to cast between a function pointer and a data pointer. | ||
1110 | */ | ||
1111 | switch(ui32Mode) | ||
1112 | { | ||
1113 | case PVRSRV_MISC_INFO_MEMSTATS_PRESENT: | ||
1114 | pfnGetStats = &RA_GetStats; | ||
1115 | break; | ||
1116 | case PVRSRV_MISC_INFO_FREEMEM_PRESENT: | ||
1117 | pfnGetStats = &RA_GetStatsFreeMem; | ||
1118 | break; | ||
1119 | default: | ||
1120 | return; | ||
1121 | } | ||
1122 | |||
1123 | if(psBMHeap->pImportArena) | ||
1124 | { | ||
1125 | pfnGetStats(psBMHeap->pImportArena, | ||
1126 | ppszStr, | ||
1127 | pui32StrLen); | ||
1128 | } | ||
1129 | |||
1130 | if(psBMHeap->pVMArena) | ||
1131 | { | ||
1132 | pfnGetStats(psBMHeap->pVMArena, | ||
1133 | ppszStr, | ||
1134 | pui32StrLen); | ||
1135 | } | ||
1136 | } | ||
1137 | |||
1138 | /*Level 2 of the loop nesting*/ | ||
1139 | static PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va) | ||
1140 | { | ||
1141 | |||
1142 | IMG_UINT32 *pui32StrLen; | ||
1143 | IMG_INT32 *pi32Count; | ||
1144 | IMG_CHAR **ppszStr; | ||
1145 | IMG_UINT32 ui32Mode; | ||
1146 | |||
1147 | pui32StrLen = va_arg(va, IMG_UINT32*); | ||
1148 | pi32Count = va_arg(va, IMG_INT32*); | ||
1149 | ppszStr = va_arg(va, IMG_CHAR**); | ||
1150 | ui32Mode = va_arg(va, IMG_UINT32); | ||
1151 | |||
1152 | CHECK_SPACE(*pui32StrLen); | ||
1153 | *pi32Count = OSSNPrintf(*ppszStr, 100, "\nApplication Context (hDevMemContext) %p:\n", | ||
1154 | (IMG_HANDLE)psBMContext); | ||
1155 | UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen); | ||
1156 | |||
1157 | List_BM_HEAP_ForEach_va(psBMContext->psBMHeap, | ||
1158 | &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb, | ||
1159 | ppszStr, | ||
1160 | pui32StrLen, | ||
1161 | ui32Mode); | ||
1162 | return PVRSRV_OK; | ||
1163 | } | ||
1164 | |||
1165 | |||
1166 | /*level 1 of the loop nesting*/ | ||
1167 | static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) | ||
1168 | { | ||
1169 | IMG_UINT32 *pui32StrLen; | ||
1170 | IMG_INT32 *pi32Count; | ||
1171 | IMG_CHAR **ppszStr; | ||
1172 | IMG_UINT32 ui32Mode; | ||
1173 | |||
1174 | pui32StrLen = va_arg(va, IMG_UINT32*); | ||
1175 | pi32Count = va_arg(va, IMG_INT32*); | ||
1176 | ppszStr = va_arg(va, IMG_CHAR**); | ||
1177 | ui32Mode = va_arg(va, IMG_UINT32); | ||
1178 | |||
1179 | CHECK_SPACE(*pui32StrLen); | ||
1180 | *pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType); | ||
1181 | UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen); | ||
1182 | |||
1183 | /* kernel context: */ | ||
1184 | if(psDeviceNode->sDevMemoryInfo.pBMKernelContext) | ||
1185 | { | ||
1186 | CHECK_SPACE(*pui32StrLen); | ||
1187 | *pi32Count = OSSNPrintf(*ppszStr, 100, "\nKernel Context:\n"); | ||
1188 | UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen); | ||
1189 | |||
1190 | List_BM_HEAP_ForEach_va(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psBMHeap, | ||
1191 | &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb, | ||
1192 | ppszStr, | ||
1193 | pui32StrLen, | ||
1194 | ui32Mode); | ||
1195 | } | ||
1196 | |||
1197 | /* double loop app contexts:heaps */ | ||
1198 | return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext, | ||
1199 | &PVRSRVGetMiscInfoKM_BMContext_AnyVaCb, | ||
1200 | pui32StrLen, | ||
1201 | pi32Count, | ||
1202 | ppszStr, | ||
1203 | ui32Mode); | ||
1204 | } | ||
1205 | |||
1206 | |||
1207 | /*! | ||
1208 | ****************************************************************************** | ||
1209 | |||
1210 | @Function PVRSRVGetMiscInfoKM | ||
1211 | |||
1212 | @Description | ||
1213 | Retrieves misc. info. | ||
1214 | |||
1215 | @Output PVRSRV_MISC_INFO | ||
1216 | |||
1217 | @Return PVRSRV_ERROR : | ||
1218 | |||
1219 | ******************************************************************************/ | ||
1220 | IMG_EXPORT | ||
1221 | PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo) | ||
1222 | { | ||
1223 | SYS_DATA *psSysData; | ||
1224 | |||
1225 | if(!psMiscInfo) | ||
1226 | { | ||
1227 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters")); | ||
1228 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1229 | } | ||
1230 | |||
1231 | psMiscInfo->ui32StatePresent = 0; | ||
1232 | |||
1233 | /* do a basic check for uninitialised request flag */ | ||
1234 | if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT | ||
1235 | |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT | ||
1236 | |PVRSRV_MISC_INFO_MEMSTATS_PRESENT | ||
1237 | |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT | ||
1238 | |PVRSRV_MISC_INFO_DDKVERSION_PRESENT | ||
1239 | |PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT | ||
1240 | |PVRSRV_MISC_INFO_RESET_PRESENT | ||
1241 | |PVRSRV_MISC_INFO_FREEMEM_PRESENT | ||
1242 | |PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT | ||
1243 | |PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT | ||
1244 | |PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT)) | ||
1245 | { | ||
1246 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags")); | ||
1247 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1248 | } | ||
1249 | |||
1250 | SysAcquireData(&psSysData); | ||
1251 | |||
1252 | /* return SOC Timer registers */ | ||
1253 | if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) && | ||
1254 | (psSysData->pvSOCTimerRegisterKM != IMG_NULL)) | ||
1255 | { | ||
1256 | psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT; | ||
1257 | psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM; | ||
1258 | psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle; | ||
1259 | } | ||
1260 | else | ||
1261 | { | ||
1262 | psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL; | ||
1263 | psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL; | ||
1264 | } | ||
1265 | |||
1266 | /* return SOC Clock Gating registers */ | ||
1267 | if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) && | ||
1268 | (psSysData->pvSOCClockGateRegsBase != IMG_NULL)) | ||
1269 | { | ||
1270 | psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT; | ||
1271 | psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase; | ||
1272 | psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize; | ||
1273 | } | ||
1274 | |||
1275 | /* memory stats */ | ||
1276 | if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) && | ||
1277 | (psMiscInfo->pszMemoryStr != IMG_NULL)) | ||
1278 | { | ||
1279 | RA_ARENA **ppArena; | ||
1280 | /* BM_HEAP *psBMHeap; | ||
1281 | BM_CONTEXT *psBMContext; | ||
1282 | PVRSRV_DEVICE_NODE *psDeviceNode;*/ | ||
1283 | IMG_CHAR *pszStr; | ||
1284 | IMG_UINT32 ui32StrLen; | ||
1285 | IMG_INT32 i32Count; | ||
1286 | |||
1287 | pszStr = psMiscInfo->pszMemoryStr; | ||
1288 | ui32StrLen = psMiscInfo->ui32MemoryStrLen; | ||
1289 | |||
1290 | psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT; | ||
1291 | |||
1292 | /* Local backing stores */ | ||
1293 | ppArena = &psSysData->apsLocalDevMemArena[0]; | ||
1294 | while(*ppArena) | ||
1295 | { | ||
1296 | CHECK_SPACE(ui32StrLen); | ||
1297 | i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n"); | ||
1298 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1299 | |||
1300 | RA_GetStats(*ppArena, | ||
1301 | &pszStr, | ||
1302 | &ui32StrLen); | ||
1303 | /* advance through the array */ | ||
1304 | ppArena++; | ||
1305 | } | ||
1306 | |||
1307 | /* per device */ | ||
1308 | /* psDeviceNode = psSysData->psDeviceNodeList;*/ | ||
1309 | |||
1310 | /*triple loop; devices:contexts:heaps*/ | ||
1311 | List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, | ||
1312 | &PVRSRVGetMiscInfoKM_Device_AnyVaCb, | ||
1313 | &ui32StrLen, | ||
1314 | &i32Count, | ||
1315 | &pszStr, | ||
1316 | PVRSRV_MISC_INFO_MEMSTATS_PRESENT); | ||
1317 | |||
1318 | /* attach a new line and string terminate */ | ||
1319 | i32Count = OSSNPrintf(pszStr, 100, "\n"); | ||
1320 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1321 | } | ||
1322 | |||
1323 | /* Lean version of mem stats: only show free mem on each RA */ | ||
1324 | if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0) | ||
1325 | && psMiscInfo->pszMemoryStr) | ||
1326 | { | ||
1327 | IMG_CHAR *pszStr; | ||
1328 | IMG_UINT32 ui32StrLen; | ||
1329 | IMG_INT32 i32Count; | ||
1330 | |||
1331 | pszStr = psMiscInfo->pszMemoryStr; | ||
1332 | ui32StrLen = psMiscInfo->ui32MemoryStrLen; | ||
1333 | |||
1334 | psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT; | ||
1335 | |||
1336 | /* triple loop over devices:contexts:heaps */ | ||
1337 | List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, | ||
1338 | &PVRSRVGetMiscInfoKM_Device_AnyVaCb, | ||
1339 | &ui32StrLen, | ||
1340 | &i32Count, | ||
1341 | &pszStr, | ||
1342 | PVRSRV_MISC_INFO_FREEMEM_PRESENT); | ||
1343 | |||
1344 | i32Count = OSSNPrintf(pszStr, 100, "\n"); | ||
1345 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1346 | } | ||
1347 | |||
1348 | if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) && | ||
1349 | (psSysData->psGlobalEventObject != IMG_NULL)) | ||
1350 | { | ||
1351 | psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT; | ||
1352 | psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject; | ||
1353 | } | ||
1354 | |||
1355 | /* DDK version and memstats not supported in same call to GetMiscInfo */ | ||
1356 | |||
1357 | if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL) | ||
1358 | && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL) | ||
1359 | && (psMiscInfo->pszMemoryStr != IMG_NULL)) | ||
1360 | { | ||
1361 | IMG_CHAR *pszStr; | ||
1362 | IMG_UINT32 ui32StrLen; | ||
1363 | IMG_UINT32 ui32LenStrPerNum = 12; /* string length per UI32: 10 digits + '.' + '\0' = 12 bytes */ | ||
1364 | IMG_INT32 i32Count; | ||
1365 | IMG_INT i; | ||
1366 | psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT; | ||
1367 | |||
1368 | /* construct DDK string */ | ||
1369 | psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ; | ||
1370 | psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN; | ||
1371 | psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BUILD_HI; | ||
1372 | psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD_LO; | ||
1373 | |||
1374 | pszStr = psMiscInfo->pszMemoryStr; | ||
1375 | ui32StrLen = psMiscInfo->ui32MemoryStrLen; | ||
1376 | |||
1377 | for (i=0; i<4; i++) | ||
1378 | { | ||
1379 | if (ui32StrLen < ui32LenStrPerNum) | ||
1380 | { | ||
1381 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1382 | } | ||
1383 | |||
1384 | i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]); | ||
1385 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1386 | if (i != 3) | ||
1387 | { | ||
1388 | i32Count = OSSNPrintf(pszStr, 2, "."); | ||
1389 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1390 | } | ||
1391 | } | ||
1392 | } | ||
1393 | |||
1394 | if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL) | ||
1395 | { | ||
1396 | psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT; | ||
1397 | |||
1398 | if(psMiscInfo->sCacheOpCtl.bDeferOp) | ||
1399 | { | ||
1400 | /* For now, assume deferred ops are "full" cache ops, | ||
1401 | * and we don't need (or expect) a meminfo. | ||
1402 | */ | ||
1403 | psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType; | ||
1404 | } | ||
1405 | else | ||
1406 | { | ||
1407 | PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; | ||
1408 | PVRSRV_PER_PROCESS_DATA *psPerProc; | ||
1409 | |||
1410 | if(!psMiscInfo->sCacheOpCtl.u.hKernelMemInfo) | ||
1411 | { | ||
1412 | PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " | ||
1413 | "Ignoring non-deferred cache op with no meminfo")); | ||
1414 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1415 | } | ||
1416 | |||
1417 | if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE) | ||
1418 | { | ||
1419 | PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " | ||
1420 | "Deferred cache op is pending. It is unlikely you want " | ||
1421 | "to combine deferred cache ops with immediate ones")); | ||
1422 | } | ||
1423 | |||
1424 | psPerProc = PVRSRVFindPerProcessData(); | ||
1425 | |||
1426 | if(PVRSRVLookupHandle(psPerProc->psHandleBase, | ||
1427 | (IMG_PVOID *)&psKernelMemInfo, | ||
1428 | psMiscInfo->sCacheOpCtl.u.hKernelMemInfo, | ||
1429 | PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) | ||
1430 | { | ||
1431 | PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: " | ||
1432 | "Can't find kernel meminfo")); | ||
1433 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1434 | } | ||
1435 | |||
1436 | if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) | ||
1437 | { | ||
1438 | if(psMiscInfo->sCacheOpCtl.ui32Length!=0) | ||
1439 | { | ||
1440 | if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, | ||
1441 | 0, | ||
1442 | psMiscInfo->sCacheOpCtl.pvBaseVAddr, | ||
1443 | psMiscInfo->sCacheOpCtl.ui32Length)) | ||
1444 | { | ||
1445 | return PVRSRV_ERROR_CACHEOP_FAILED; | ||
1446 | } | ||
1447 | } | ||
1448 | } | ||
1449 | else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) | ||
1450 | { | ||
1451 | if(psMiscInfo->sCacheOpCtl.ui32Length!=0) | ||
1452 | { | ||
1453 | if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, | ||
1454 | 0, | ||
1455 | psMiscInfo->sCacheOpCtl.pvBaseVAddr, | ||
1456 | psMiscInfo->sCacheOpCtl.ui32Length)) | ||
1457 | { | ||
1458 | return PVRSRV_ERROR_CACHEOP_FAILED; | ||
1459 | } | ||
1460 | } | ||
1461 | } | ||
1462 | } | ||
1463 | } | ||
1464 | |||
1465 | if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT) != 0UL) | ||
1466 | { | ||
1467 | PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; | ||
1468 | PVRSRV_PER_PROCESS_DATA *psPerProc; | ||
1469 | |||
1470 | psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT; | ||
1471 | |||
1472 | psPerProc = PVRSRVFindPerProcessData(); | ||
1473 | |||
1474 | if(PVRSRVLookupHandle(psPerProc->psHandleBase, | ||
1475 | (IMG_PVOID *)&psKernelMemInfo, | ||
1476 | psMiscInfo->sGetRefCountCtl.u.hKernelMemInfo, | ||
1477 | PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) | ||
1478 | { | ||
1479 | PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: " | ||
1480 | "Can't find kernel meminfo")); | ||
1481 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1482 | } | ||
1483 | |||
1484 | psMiscInfo->sGetRefCountCtl.ui32RefCount = psKernelMemInfo->ui32RefCount; | ||
1485 | } | ||
1486 | |||
1487 | if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT) != 0UL) | ||
1488 | { | ||
1489 | psMiscInfo->ui32PageSize = HOST_PAGESIZE(); | ||
1490 | psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT; | ||
1491 | } | ||
1492 | |||
1493 | #if defined(PVRSRV_RESET_ON_HWTIMEOUT) | ||
1494 | if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL) | ||
1495 | { | ||
1496 | PVR_LOG(("User requested OS reset")); | ||
1497 | OSPanic(); | ||
1498 | } | ||
1499 | #endif /* #if defined(PVRSRV_RESET_ON_HWTIMEOUT) */ | ||
1500 | |||
1501 | #if defined(SUPPORT_PVRSRV_DEVICE_CLASS) | ||
1502 | if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT) != 0UL) | ||
1503 | { | ||
1504 | PVRSRVProcessQueues(IMG_TRUE); | ||
1505 | psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT; | ||
1506 | } | ||
1507 | #endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */ | ||
1508 | |||
1509 | return PVRSRV_OK; | ||
1510 | } | ||
1511 | |||
1512 | |||
1513 | /*! | ||
1514 | ****************************************************************************** | ||
1515 | |||
1516 | @Function PVRSRVDeviceLISR | ||
1517 | |||
1518 | @Description | ||
1519 | OS-independent Device Low-level Interrupt Service Routine | ||
1520 | |||
1521 | @Input psDeviceNode | ||
1522 | |||
1523 | @Return IMG_BOOL : Whether any interrupts were serviced | ||
1524 | |||
1525 | ******************************************************************************/ | ||
1526 | IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode) | ||
1527 | { | ||
1528 | SYS_DATA *psSysData; | ||
1529 | IMG_BOOL bStatus = IMG_FALSE; | ||
1530 | IMG_UINT32 ui32InterruptSource; | ||
1531 | |||
1532 | if(!psDeviceNode) | ||
1533 | { | ||
1534 | PVR_DPF((PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n")); | ||
1535 | goto out; | ||
1536 | } | ||
1537 | psSysData = psDeviceNode->psSysData; | ||
1538 | |||
1539 | /* query the SOC/system to see whether this device was the source of the interrupt */ | ||
1540 | ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode); | ||
1541 | if(ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit) | ||
1542 | { | ||
1543 | if(psDeviceNode->pfnDeviceISR != IMG_NULL) | ||
1544 | { | ||
1545 | bStatus = (*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData); | ||
1546 | } | ||
1547 | |||
1548 | SysClearInterrupts(psSysData, psDeviceNode->ui32SOCInterruptBit); | ||
1549 | } | ||
1550 | |||
1551 | out: | ||
1552 | return bStatus; | ||
1553 | } | ||
1554 | |||
1555 | static IMG_VOID PVRSRVSystemLISR_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) | ||
1556 | { | ||
1557 | |||
1558 | IMG_BOOL *pbStatus; | ||
1559 | IMG_UINT32 *pui32InterruptSource; | ||
1560 | IMG_UINT32 *pui32ClearInterrupts; | ||
1561 | |||
1562 | pbStatus = va_arg(va, IMG_BOOL*); | ||
1563 | pui32InterruptSource = va_arg(va, IMG_UINT32*); | ||
1564 | pui32ClearInterrupts = va_arg(va, IMG_UINT32*); | ||
1565 | |||
1566 | |||
1567 | if(psDeviceNode->pfnDeviceISR != IMG_NULL) | ||
1568 | { | ||
1569 | if(*pui32InterruptSource & psDeviceNode->ui32SOCInterruptBit) | ||
1570 | { | ||
1571 | if((*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData)) | ||
1572 | { | ||
1573 | /* Record if serviced any interrupts. */ | ||
1574 | *pbStatus = IMG_TRUE; | ||
1575 | } | ||
1576 | /* Combine the SOC clear bits. */ | ||
1577 | *pui32ClearInterrupts |= psDeviceNode->ui32SOCInterruptBit; | ||
1578 | } | ||
1579 | } | ||
1580 | } | ||
1581 | |||
1582 | /*! | ||
1583 | ****************************************************************************** | ||
1584 | |||
1585 | @Function PVRSRVSystemLISR | ||
1586 | |||
1587 | @Description | ||
1588 | OS-independent System Low-level Interrupt Service Routine | ||
1589 | |||
1590 | @Input pvSysData | ||
1591 | |||
1592 | @Return IMG_BOOL : Whether any interrupts were serviced | ||
1593 | |||
1594 | ******************************************************************************/ | ||
1595 | IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData) | ||
1596 | { | ||
1597 | SYS_DATA *psSysData = pvSysData; | ||
1598 | IMG_BOOL bStatus = IMG_FALSE; | ||
1599 | IMG_UINT32 ui32InterruptSource; | ||
1600 | IMG_UINT32 ui32ClearInterrupts = 0; | ||
1601 | /* PVRSRV_DEVICE_NODE *psDeviceNode;*/ | ||
1602 | |||
1603 | if(!psSysData) | ||
1604 | { | ||
1605 | PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n")); | ||
1606 | /* goto out; */ | ||
1607 | } | ||
1608 | else | ||
1609 | { | ||
1610 | /* query SOC for source of interrupts */ | ||
1611 | ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL); | ||
1612 | |||
1613 | /* only proceed if PVR interrupts */ | ||
1614 | if(ui32InterruptSource) | ||
1615 | { | ||
1616 | /* traverse the devices' ISR handlers */ | ||
1617 | List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList, | ||
1618 | &PVRSRVSystemLISR_ForEachVaCb, | ||
1619 | &bStatus, | ||
1620 | &ui32InterruptSource, | ||
1621 | &ui32ClearInterrupts); | ||
1622 | |||
1623 | SysClearInterrupts(psSysData, ui32ClearInterrupts); | ||
1624 | } | ||
1625 | /*out:*/ | ||
1626 | } | ||
1627 | return bStatus; | ||
1628 | } | ||
1629 | |||
1630 | |||
1631 | static IMG_VOID PVRSRVMISR_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode) | ||
1632 | { | ||
1633 | if(psDeviceNode->pfnDeviceMISR != IMG_NULL) | ||
1634 | { | ||
1635 | (*psDeviceNode->pfnDeviceMISR)(psDeviceNode->pvISRData); | ||
1636 | } | ||
1637 | } | ||
1638 | |||
1639 | /*! | ||
1640 | ****************************************************************************** | ||
1641 | |||
1642 | @Function PVRSRVMISR | ||
1643 | |||
1644 | @Input pvSysData | ||
1645 | |||
1646 | @Description | ||
1647 | OS-independent Medium-level Interrupt Service Routine | ||
1648 | |||
1649 | ******************************************************************************/ | ||
1650 | IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData) | ||
1651 | { | ||
1652 | SYS_DATA *psSysData = pvSysData; | ||
1653 | /* PVRSRV_DEVICE_NODE *psDeviceNode; */ | ||
1654 | |||
1655 | if(!psSysData) | ||
1656 | { | ||
1657 | PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n")); | ||
1658 | return; | ||
1659 | } | ||
1660 | |||
1661 | /* Traverse the devices' MISR handlers. */ | ||
1662 | List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, | ||
1663 | &PVRSRVMISR_ForEachCb); | ||
1664 | |||
1665 | #if defined(SUPPORT_PVRSRV_DEVICE_CLASS) | ||
1666 | /* Process the queues. */ | ||
1667 | if (PVRSRVProcessQueues(IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED) | ||
1668 | { | ||
1669 | PVRSRVProcessQueues(IMG_FALSE); | ||
1670 | } | ||
1671 | #endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */ | ||
1672 | |||
1673 | /* signal global event object */ | ||
1674 | if (psSysData->psGlobalEventObject) | ||
1675 | { | ||
1676 | IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM; | ||
1677 | if(hOSEventKM) | ||
1678 | { | ||
1679 | OSEventObjectSignalKM(hOSEventKM); | ||
1680 | } | ||
1681 | } | ||
1682 | } | ||
1683 | |||
1684 | |||
1685 | /*! | ||
1686 | ****************************************************************************** | ||
1687 | |||
1688 | @Function PVRSRVProcessConnect | ||
1689 | |||
1690 | @Description Inform services that a process has connected. | ||
1691 | |||
1692 | @Input ui32PID - process ID | ||
1693 | |||
1694 | @Return PVRSRV_ERROR | ||
1695 | |||
1696 | ******************************************************************************/ | ||
1697 | IMG_EXPORT | ||
1698 | PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags) | ||
1699 | { | ||
1700 | return PVRSRVPerProcessDataConnect(ui32PID, ui32Flags); | ||
1701 | } | ||
1702 | |||
1703 | |||
1704 | /*! | ||
1705 | ****************************************************************************** | ||
1706 | |||
1707 | @Function PVRSRVProcessDisconnect | ||
1708 | |||
1709 | @Description Inform services that a process has disconnected. | ||
1710 | |||
1711 | @Input ui32PID - process ID | ||
1712 | |||
1713 | @Return IMG_VOID | ||
1714 | |||
1715 | ******************************************************************************/ | ||
1716 | IMG_EXPORT | ||
1717 | IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID) | ||
1718 | { | ||
1719 | PVRSRVPerProcessDataDisconnect(ui32PID); | ||
1720 | } | ||
1721 | |||
1722 | |||
1723 | /*! | ||
1724 | ****************************************************************************** | ||
1725 | |||
1726 | @Function PVRSRVSaveRestoreLiveSegments | ||
1727 | |||
1728 | @Input pArena - the arena the segment was originally allocated from. | ||
1729 | pbyBuffer - the system memory buffer set to null to get the size needed. | ||
1730 | puiBufSize - size of system memory buffer. | ||
1731 | bSave - IMG_TRUE if a save is required | ||
1732 | |||
1733 | @Description | ||
1734 | Function to save or restore Resources Live segments | ||
1735 | |||
1736 | ******************************************************************************/ | ||
1737 | PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer, | ||
1738 | IMG_SIZE_T *puiBufSize, IMG_BOOL bSave) | ||
1739 | { | ||
1740 | IMG_SIZE_T uiBytesSaved = 0; | ||
1741 | IMG_PVOID pvLocalMemCPUVAddr; | ||
1742 | RA_SEGMENT_DETAILS sSegDetails; | ||
1743 | |||
1744 | if (hArena == IMG_NULL) | ||
1745 | { | ||
1746 | return (PVRSRV_ERROR_INVALID_PARAMS); | ||
1747 | } | ||
1748 | |||
1749 | sSegDetails.uiSize = 0; | ||
1750 | sSegDetails.sCpuPhyAddr.uiAddr = 0; | ||
1751 | sSegDetails.hSegment = 0; | ||
1752 | |||
1753 | /* walk the arena segments and write live one to the buffer */ | ||
1754 | while (RA_GetNextLiveSegment(hArena, &sSegDetails)) | ||
1755 | { | ||
1756 | if (pbyBuffer == IMG_NULL) | ||
1757 | { | ||
1758 | /* calc buffer required */ | ||
1759 | uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize; | ||
1760 | } | ||
1761 | else | ||
1762 | { | ||
1763 | if ((uiBytesSaved + sizeof(sSegDetails.uiSize) + sSegDetails.uiSize) > *puiBufSize) | ||
1764 | { | ||
1765 | return (PVRSRV_ERROR_OUT_OF_MEMORY); | ||
1766 | } | ||
1767 | |||
1768 | PVR_DPF(( | ||
1769 | PVR_DBG_MESSAGE, | ||
1770 | "PVRSRVSaveRestoreLiveSegments: Base " CPUPADDR_FMT " size %" SIZE_T_FMT_LEN "x", | ||
1771 | sSegDetails.sCpuPhyAddr.uiAddr, | ||
1772 | sSegDetails.uiSize)); | ||
1773 | |||
1774 | /* Map the device's local memory area onto the host. */ | ||
1775 | pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr, | ||
1776 | sSegDetails.uiSize, | ||
1777 | PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED, | ||
1778 | IMG_NULL); | ||
1779 | if (pvLocalMemCPUVAddr == IMG_NULL) | ||
1780 | { | ||
1781 | PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Failed to map local memory to host")); | ||
1782 | return (PVRSRV_ERROR_OUT_OF_MEMORY); | ||
1783 | } | ||
1784 | |||
1785 | if (bSave) | ||
1786 | { | ||
1787 | /* write segment size then segment data */ | ||
1788 | OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize)); | ||
1789 | pbyBuffer += sizeof(sSegDetails.uiSize); | ||
1790 | |||
1791 | OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr, sSegDetails.uiSize); | ||
1792 | pbyBuffer += sSegDetails.uiSize; | ||
1793 | } | ||
1794 | else | ||
1795 | { | ||
1796 | IMG_UINT32 uiSize; | ||
1797 | /* reag segment size and validate */ | ||
1798 | OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize)); | ||
1799 | |||
1800 | if (uiSize != sSegDetails.uiSize) | ||
1801 | { | ||
1802 | PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Segment size error")); | ||
1803 | } | ||
1804 | else | ||
1805 | { | ||
1806 | pbyBuffer += sizeof(sSegDetails.uiSize); | ||
1807 | |||
1808 | OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer, sSegDetails.uiSize); | ||
1809 | pbyBuffer += sSegDetails.uiSize; | ||
1810 | } | ||
1811 | } | ||
1812 | |||
1813 | |||
1814 | uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize; | ||
1815 | |||
1816 | OSUnMapPhysToLin(pvLocalMemCPUVAddr, | ||
1817 | sSegDetails.uiSize, | ||
1818 | PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED, | ||
1819 | IMG_NULL); | ||
1820 | } | ||
1821 | } | ||
1822 | |||
1823 | if (pbyBuffer == IMG_NULL) | ||
1824 | { | ||
1825 | *puiBufSize = uiBytesSaved; | ||
1826 | } | ||
1827 | |||
1828 | return (PVRSRV_OK); | ||
1829 | } | ||
1830 | |||
1831 | |||
1832 | /*! | ||
1833 | ****************************************************************************** | ||
1834 | |||
1835 | @Function PVRSRVGetErrorStringKM | ||
1836 | |||
1837 | @Description Returns a text string relating to the PVRSRV_ERROR enum. | ||
1838 | |||
1839 | @Note case statement used rather than an indexed arrary to ensure text is | ||
1840 | synchronised with the correct enum | ||
1841 | |||
1842 | @Input eError : PVRSRV_ERROR enum | ||
1843 | |||
1844 | @Return const IMG_CHAR * : Text string | ||
1845 | |||
1846 | @Note Must be kept in sync with servicesext.h | ||
1847 | |||
1848 | ******************************************************************************/ | ||
1849 | |||
1850 | IMG_EXPORT | ||
1851 | const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError) | ||
1852 | { | ||
1853 | /* PRQA S 5087 1 */ /* include file required here */ | ||
1854 | #include "pvrsrv_errors.h" | ||
1855 | } | ||
1856 | |||
1857 | static IMG_VOID PVRSRVCommandCompleteCallbacks_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode) | ||
1858 | { | ||
1859 | if(psDeviceNode->pfnDeviceCommandComplete != IMG_NULL) | ||
1860 | { | ||
1861 | /* Call the device's callback function. */ | ||
1862 | (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode); | ||
1863 | } | ||
1864 | } | ||
1865 | |||
1866 | /*! | ||
1867 | ****************************************************************************** | ||
1868 | |||
1869 | @Function PVRSRVScheduleDeviceCallbacks | ||
1870 | |||
1871 | @Description Schedule all device callbacks | ||
1872 | |||
1873 | @Return IMG_VOID | ||
1874 | |||
1875 | ******************************************************************************/ | ||
1876 | IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID) | ||
1877 | { | ||
1878 | SYS_DATA *psSysData; | ||
1879 | /* PVRSRV_DEVICE_NODE *psDeviceNode;*/ | ||
1880 | |||
1881 | SysAcquireData(&psSysData); | ||
1882 | |||
1883 | /*for all the device, invoke the callback function*/ | ||
1884 | List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, | ||
1885 | &PVRSRVCommandCompleteCallbacks_ForEachCb); | ||
1886 | } | ||
1887 | |||
1888 | /*! | ||
1889 | ****************************************************************************** | ||
1890 | |||
1891 | @Function PVRSRVScheduleDevices | ||
1892 | |||
1893 | @Description Schedules all Services-Managed Devices to check their pending | ||
1894 | command queues. The intention is that ScheduleDevices be called by the | ||
1895 | 3rd party BC driver after it has finished writing new data to its output | ||
1896 | texture. | ||
1897 | |||
1898 | @Return IMG_VOID | ||
1899 | |||
1900 | ******************************************************************************/ | ||
1901 | IMG_EXPORT | ||
1902 | IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID) | ||
1903 | { | ||
1904 | PVRSRVScheduleDeviceCallbacks(); | ||
1905 | } | ||
1906 | |||
1907 | /***************************************************************************** | ||
1908 | End of file (pvrsrv.c) | ||
1909 | *****************************************************************************/ | ||