1 /*************************************************************************/ /*!
3 @Title PowerVR notifier interface
4 @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
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
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 */ /**************************************************************************/
48 #include "pvr_notifier.h"
50 #include "pvrversion.h"
53 /*************************************************************************/ /*!
54 Command Complete Notifier Interface
55 */ /**************************************************************************/
57 typedef struct PVRSRV_CMDCOMP_NOTIFY_TAG
59 PVRSRV_CMDCOMP_HANDLE hCmdCompHandle;
60 PFN_CMDCOMP_NOTIFY pfnCmdCompleteNotify;
61 DLLIST_NODE sListNode;
62 } PVRSRV_CMDCOMP_NOTIFY;
64 /* Head of the list of callbacks called when command complete happens */
65 static DLLIST_NODE g_sCmdCompNotifyHead;
66 static POSWR_LOCK g_hCmdCompNotifyLock;
69 PVRSRVCmdCompleteInit(void)
73 eError = OSWRLockCreate(&g_hCmdCompNotifyLock);
74 if (eError != PVRSRV_OK)
79 dllist_init(&g_sCmdCompNotifyHead);
85 PVRSRVCmdCompleteDeinit(void)
87 /* Check that all notify function have been unregistered */
88 if (!dllist_is_empty(&g_sCmdCompNotifyHead))
92 PVR_DPF((PVR_DBG_ERROR,
93 "%s: Command complete notify list is not empty!", __func__));
95 /* Clean up any stragglers */
96 psNode = dllist_get_next_node(&g_sCmdCompNotifyHead);
99 PVRSRV_CMDCOMP_NOTIFY *psNotify;
101 dllist_remove_node(psNode);
103 psNotify = IMG_CONTAINER_OF(psNode, PVRSRV_CMDCOMP_NOTIFY, sListNode);
106 psNode = dllist_get_next_node(&g_sCmdCompNotifyHead);
110 if (g_hCmdCompNotifyLock)
112 OSWRLockDestroy(g_hCmdCompNotifyLock);
117 PVRSRVRegisterCmdCompleteNotify(IMG_HANDLE *phNotify,
118 PFN_CMDCOMP_NOTIFY pfnCmdCompleteNotify,
119 PVRSRV_CMDCOMP_HANDLE hCmdCompHandle)
121 PVRSRV_CMDCOMP_NOTIFY *psNotify;
123 if (!phNotify || !pfnCmdCompleteNotify || !hCmdCompHandle)
125 PVR_DPF((PVR_DBG_ERROR, "%s: Bad arguments (%p, %p, %p)",
126 __func__, phNotify, pfnCmdCompleteNotify, hCmdCompHandle));
127 return PVRSRV_ERROR_INVALID_PARAMS;
130 psNotify = OSAllocMem(sizeof(*psNotify));
133 PVR_DPF((PVR_DBG_ERROR,
134 "%s: Not enough memory to allocate CmdCompleteNotify function",
136 return PVRSRV_ERROR_OUT_OF_MEMORY;
139 /* Set-up the notify data */
140 psNotify->hCmdCompHandle = hCmdCompHandle;
141 psNotify->pfnCmdCompleteNotify = pfnCmdCompleteNotify;
143 /* Add it to the list of Notify functions */
144 OSWRLockAcquireWrite(g_hCmdCompNotifyLock);
145 dllist_add_to_tail(&g_sCmdCompNotifyHead, &psNotify->sListNode);
146 OSWRLockReleaseWrite(g_hCmdCompNotifyLock);
148 *phNotify = psNotify;
154 PVRSRVUnregisterCmdCompleteNotify(IMG_HANDLE hNotify)
156 PVRSRV_CMDCOMP_NOTIFY *psNotify;
158 psNotify = (PVRSRV_CMDCOMP_NOTIFY *) hNotify;
161 PVR_DPF((PVR_DBG_ERROR," %s: Bad arguments (%p)", __func__, hNotify));
162 return PVRSRV_ERROR_INVALID_PARAMS;
165 OSWRLockAcquireWrite(g_hCmdCompNotifyLock);
166 dllist_remove_node(&psNotify->sListNode);
167 OSWRLockReleaseWrite(g_hCmdCompNotifyLock);
175 PVRSRVCheckStatus(PVRSRV_CMDCOMP_HANDLE hCmdCompCallerHandle)
177 PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
178 #if !defined(NO_HARDWARE)
179 DLLIST_NODE *psNode, *psNext;
182 /* Call notify callbacks to check if blocked work items can now proceed */
183 #if !defined(NO_HARDWARE)
184 OSWRLockAcquireRead(g_hCmdCompNotifyLock);
185 dllist_foreach_node(&g_sCmdCompNotifyHead, psNode, psNext)
187 PVRSRV_CMDCOMP_NOTIFY *psNotify =
188 IMG_CONTAINER_OF(psNode, PVRSRV_CMDCOMP_NOTIFY, sListNode);
190 if (hCmdCompCallerHandle != psNotify->hCmdCompHandle)
192 psNotify->pfnCmdCompleteNotify(psNotify->hCmdCompHandle);
195 OSWRLockReleaseRead(g_hCmdCompNotifyLock);
198 if (psPVRSRVData->hGlobalEventObject)
200 OSEventObjectSignal(psPVRSRVData->hGlobalEventObject);
204 /*************************************************************************/ /*!
205 Debug Notifier Interface
206 */ /**************************************************************************/
208 typedef struct DEBUG_REQUEST_ENTRY_TAG
210 IMG_UINT32 ui32RequesterID;
211 DLLIST_NODE sListHead;
212 } DEBUG_REQUEST_ENTRY;
214 typedef struct DEBUG_REQUEST_TABLE_TAG
217 IMG_UINT32 ui32RequestCount;
218 DEBUG_REQUEST_ENTRY asEntry[1];
219 } DEBUG_REQUEST_TABLE;
221 typedef struct DEBUG_REQUEST_NOTIFY_TAG
223 PVRSRV_DEVICE_NODE *psDevNode;
224 PVRSRV_DBGREQ_HANDLE hDbgRequestHandle;
225 PFN_DBGREQ_NOTIFY pfnDbgRequestNotify;
226 IMG_UINT32 ui32RequesterID;
227 DLLIST_NODE sListNode;
228 } DEBUG_REQUEST_NOTIFY;
232 PVRSRVRegisterDbgTable(PVRSRV_DEVICE_NODE *psDevNode, IMG_UINT32 *paui32Table,
233 IMG_UINT32 ui32Length)
235 DEBUG_REQUEST_TABLE *psDebugTable;
239 if (psDevNode->hDebugTable)
241 return PVRSRV_ERROR_DBGTABLE_ALREADY_REGISTERED;
244 psDebugTable = OSAllocMem(sizeof(DEBUG_REQUEST_TABLE) +
245 (sizeof(DEBUG_REQUEST_ENTRY) * (ui32Length-1)));
248 return PVRSRV_ERROR_OUT_OF_MEMORY;
251 eError = OSWRLockCreate(&psDebugTable->hLock);
252 if (eError != PVRSRV_OK)
254 goto ErrorFreeDebugTable;
257 psDebugTable->ui32RequestCount = ui32Length;
259 /* Init the list heads */
260 for (i = 0; i < ui32Length; i++)
262 psDebugTable->asEntry[i].ui32RequesterID = paui32Table[i];
263 dllist_init(&psDebugTable->asEntry[i].sListHead);
266 psDevNode->hDebugTable = (IMG_HANDLE *) psDebugTable;
271 OSFreeMem(psDebugTable);
278 PVRSRVUnregisterDbgTable(PVRSRV_DEVICE_NODE *psDevNode)
280 DEBUG_REQUEST_TABLE *psDebugTable;
283 PVR_ASSERT(psDevNode->hDebugTable);
284 psDebugTable = (DEBUG_REQUEST_TABLE *) psDevNode->hDebugTable;
285 psDevNode->hDebugTable = NULL;
287 for (i = 0; i < psDebugTable->ui32RequestCount; i++)
289 if (!dllist_is_empty(&psDebugTable->asEntry[i].sListHead))
291 PVR_DPF((PVR_DBG_ERROR, "%s: Found registered callback(s) on %d",
296 OSWRLockDestroy(psDebugTable->hLock);
297 psDebugTable->hLock = NULL;
299 OSFreeMem(psDebugTable);
303 PVRSRVRegisterDbgRequestNotify(IMG_HANDLE *phNotify,
304 PVRSRV_DEVICE_NODE *psDevNode,
305 PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
306 IMG_UINT32 ui32RequesterID,
307 PVRSRV_DBGREQ_HANDLE hDbgRequestHandle)
309 DEBUG_REQUEST_TABLE *psDebugTable;
310 DEBUG_REQUEST_NOTIFY *psNotify;
311 PDLLIST_NODE psHead = NULL;
315 if (!phNotify || !psDevNode || !pfnDbgRequestNotify)
317 PVR_DPF((PVR_DBG_ERROR, "%s: Bad arguments (%p, %p, %p)",
318 __func__, phNotify, psDevNode, pfnDbgRequestNotify));
319 return PVRSRV_ERROR_INVALID_PARAMS;
322 psDebugTable = (DEBUG_REQUEST_TABLE *) psDevNode->hDebugTable;
324 PVR_ASSERT(psDebugTable);
326 psNotify = OSAllocMem(sizeof(*psNotify));
329 PVR_DPF((PVR_DBG_ERROR,
330 "%s: Not enough memory to allocate DbgRequestNotify structure",
332 return PVRSRV_ERROR_OUT_OF_MEMORY;
335 /* Set-up the notify data */
336 psNotify->psDevNode = psDevNode;
337 psNotify->hDbgRequestHandle = hDbgRequestHandle;
338 psNotify->pfnDbgRequestNotify = pfnDbgRequestNotify;
339 psNotify->ui32RequesterID = ui32RequesterID;
341 /* Lock down all the lists */
342 OSWRLockAcquireWrite(psDebugTable->hLock);
344 /* Find which list to add it to */
345 for (i = 0; i < psDebugTable->ui32RequestCount; i++)
347 if (psDebugTable->asEntry[i].ui32RequesterID == ui32RequesterID)
349 psHead = &psDebugTable->asEntry[i].sListHead;
355 PVR_DPF((PVR_DBG_ERROR,"%s: Failed to find debug requester", __func__));
356 eError = PVRSRV_ERROR_INVALID_PARAMS;
357 goto ErrorReleaseLock;
360 /* Add it to the list of Notify functions */
361 dllist_add_to_tail(psHead, &psNotify->sListNode);
363 /* Unlock the lists */
364 OSWRLockReleaseWrite(psDebugTable->hLock);
366 *phNotify = psNotify;
371 OSWRLockReleaseWrite(psDebugTable->hLock);
378 PVRSRVUnregisterDbgRequestNotify(IMG_HANDLE hNotify)
380 DEBUG_REQUEST_NOTIFY *psNotify = (DEBUG_REQUEST_NOTIFY *) hNotify;
381 DEBUG_REQUEST_TABLE *psDebugTable;
385 PVR_DPF((PVR_DBG_ERROR, "%s: Bad arguments (%p)", __func__, hNotify));
386 return PVRSRV_ERROR_INVALID_PARAMS;
389 psDebugTable = (DEBUG_REQUEST_TABLE *) psNotify->psDevNode->hDebugTable;
391 OSWRLockAcquireWrite(psDebugTable->hLock);
392 dllist_remove_node(&psNotify->sListNode);
393 OSWRLockReleaseWrite(psDebugTable->hLock);
401 PVRSRVDebugRequest(PVRSRV_DEVICE_NODE *psDevNode,
402 IMG_UINT32 ui32VerbLevel,
403 DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
404 void *pvDumpDebugFile)
406 PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
407 DEBUG_REQUEST_TABLE *psDebugTable =
408 (DEBUG_REQUEST_TABLE *) psDevNode->hDebugTable;
409 static const IMG_CHAR *apszVerbosityTable[] = { "Low", "Medium", "High" };
410 const IMG_CHAR *szVerbosityLevel;
414 static_assert(IMG_ARR_NUM_ELEMS(apszVerbosityTable) == DEBUG_REQUEST_VERBOSITY_MAX+1,
415 "Incorrect number of verbosity levels");
417 PVR_ASSERT(psDebugTable);
419 if (!pfnDumpDebugPrintf)
422 * Only dump the call stack to the kernel log if the debug text is going
428 OSWRLockAcquireRead(psDebugTable->hLock);
430 if (ui32VerbLevel < IMG_ARR_NUM_ELEMS(apszVerbosityTable))
432 szVerbosityLevel = apszVerbosityTable[ui32VerbLevel];
436 szVerbosityLevel = "unknown";
437 PVR_ASSERT(!"Invalid verbosity level received");
440 PVR_DUMPDEBUG_LOG("------------[ PVR DBG: START (%s) ]------------",
443 PVR_DUMPDEBUG_LOG("DDK info: %s (%s) %s",
444 PVRVERSION_STRING, PVR_BUILD_TYPE, PVR_BUILD_DIR);
445 PVR_DUMPDEBUG_LOG("Time now: %015llu", OSClockus64());
447 switch (psPVRSRVData->eServicesState)
449 case PVRSRV_SERVICES_STATE_OK:
450 PVR_DUMPDEBUG_LOG("Services State: OK");
452 case PVRSRV_SERVICES_STATE_BAD:
453 PVR_DUMPDEBUG_LOG("Services State: BAD");
456 PVR_DUMPDEBUG_LOG("Services State: UNKNOWN (%d)",
457 psPVRSRVData->eServicesState);
461 /* For each verbosity level */
462 for (j = 0; j <= ui32VerbLevel; j++)
464 /* For each requester */
465 for (i = 0; i < psDebugTable->ui32RequestCount; i++)
470 dllist_foreach_node(&psDebugTable->asEntry[i].sListHead, psNode, psNext)
472 DEBUG_REQUEST_NOTIFY *psNotify =
473 IMG_CONTAINER_OF(psNode, DEBUG_REQUEST_NOTIFY, sListNode);
474 psNotify->pfnDbgRequestNotify(psNotify->hDbgRequestHandle, j,
475 pfnDumpDebugPrintf, pvDumpDebugFile);
480 PVR_DUMPDEBUG_LOG("------------[ PVR DBG: END ]------------");
481 OSWRLockReleaseRead(psDebugTable->hLock);