1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful but, except
10 * as otherwise stated in writing, without any warranty; without even the
11 * implied warranty of merchantability or fitness for a particular purpose.
12 * See the GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
27 #include "services_headers.h"
31 static int QueuePrintCommands(struct PVRSRV_QUEUE_INFO *psQueue, char *buffer,
36 u32 ui32ReadOffset = psQueue->ui32ReadOffset;
37 u32 ui32WriteOffset = psQueue->ui32WriteOffset;
38 struct PVRSRV_COMMAND *psCmd;
40 while (ui32ReadOffset != ui32WriteOffset) {
41 psCmd = (struct PVRSRV_COMMAND *)((u32) psQueue->pvLinQueueKM +
44 off = printAppend(buffer, size, off,
45 "%p %p %5u %6u %3u %5u %2u %2u %3u \n",
46 psQueue, psCmd, psCmd->ui32ProcessID,
47 psCmd->CommandType, psCmd->ui32CmdSize,
48 psCmd->ui32DevIndex, psCmd->ui32DstSyncCount,
49 psCmd->ui32SrcSyncCount, psCmd->ui32DataSize);
51 ui32ReadOffset += psCmd->ui32CmdSize;
52 ui32ReadOffset &= psQueue->ui32QueueSize - 1;
56 off = printAppend(buffer, size, off, "%p <empty>\n", psQueue);
60 off_t QueuePrintQueues(char *buffer, size_t size, off_t off)
62 struct SYS_DATA *psSysData;
63 struct PVRSRV_QUEUE_INFO *psQueue;
65 if (SysAcquireData(&psSysData) != PVRSRV_OK)
69 return printAppend(buffer, size, 0,
70 "Command Queues\nQueue CmdPtr "
71 "Pid Command Size DevInd DSC SSC #Data ...\n");
73 for (psQueue = psSysData->psQueueList; --off && psQueue;
74 psQueue = psQueue->psNextKM)
78 QueuePrintCommands(psQueue, buffer, size) : END_OF_FILE;
81 #define GET_SPACE_IN_CMDQ(psQueue) \
82 (((psQueue->ui32ReadOffset - psQueue->ui32WriteOffset) + \
83 (psQueue->ui32QueueSize - 1)) & (psQueue->ui32QueueSize - 1))
85 #define UPDATE_QUEUE_WOFF(psQueue, ui32Size) \
86 psQueue->ui32WriteOffset = (psQueue->ui32WriteOffset + ui32Size) & \
87 (psQueue->ui32QueueSize - 1);
89 #define SYNCOPS_STALE(ui32OpsComplete, ui32OpsPending) \
90 (ui32OpsComplete >= ui32OpsPending)
92 static u32 NearestPower2(u32 ui32Value)
94 u32 ui32Temp, ui32Result = 1;
99 ui32Temp = ui32Value - 1;
108 enum PVRSRV_ERROR PVRSRVCreateCommandQueueKM(u32 ui32QueueSize,
109 struct PVRSRV_QUEUE_INFO **ppsQueueInfo)
111 struct PVRSRV_QUEUE_INFO *psQueueInfo;
112 u32 ui32Power2QueueSize = NearestPower2(ui32QueueSize);
113 struct SYS_DATA *psSysData;
114 enum PVRSRV_ERROR eError;
117 eError = SysAcquireData(&psSysData);
118 if (eError != PVRSRV_OK)
121 if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
122 sizeof(struct PVRSRV_QUEUE_INFO),
123 (void **) &psQueueInfo, &hMemBlock) != PVRSRV_OK) {
124 PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateCommandQueueKM: "
125 "Failed to alloc queue struct");
128 OSMemSet(psQueueInfo, 0, sizeof(struct PVRSRV_QUEUE_INFO));
130 psQueueInfo->hMemBlock[0] = hMemBlock;
131 psQueueInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
133 if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
134 ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE,
135 &psQueueInfo->pvLinQueueKM, &hMemBlock) != PVRSRV_OK) {
136 PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateCommandQueueKM: "
137 "Failed to alloc queue buffer");
141 psQueueInfo->hMemBlock[1] = hMemBlock;
142 psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM;
144 PVR_ASSERT(psQueueInfo->ui32ReadOffset == 0);
145 PVR_ASSERT(psQueueInfo->ui32WriteOffset == 0);
147 psQueueInfo->ui32QueueSize = ui32Power2QueueSize;
149 if (psSysData->psQueueList == NULL) {
150 eError = OSCreateResource(&psSysData->sQProcessResource);
151 if (eError != PVRSRV_OK)
155 if (OSLockResource(&psSysData->sQProcessResource,
156 KERNEL_ID) != PVRSRV_OK)
159 psQueueInfo->psNextKM = psSysData->psQueueList;
160 psSysData->psQueueList = psQueueInfo;
162 if (OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID) !=
166 *ppsQueueInfo = psQueueInfo;
173 if (psQueueInfo->pvLinQueueKM)
174 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
175 psQueueInfo->ui32QueueSize,
176 psQueueInfo->pvLinQueueKM,
177 psQueueInfo->hMemBlock[1]);
179 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
180 sizeof(struct PVRSRV_QUEUE_INFO),
181 psQueueInfo, psQueueInfo->hMemBlock[0]);
184 return PVRSRV_ERROR_GENERIC;
187 enum PVRSRV_ERROR PVRSRVDestroyCommandQueueKM(
188 struct PVRSRV_QUEUE_INFO *psQueueInfo)
190 struct PVRSRV_QUEUE_INFO *psQueue;
191 struct SYS_DATA *psSysData;
192 enum PVRSRV_ERROR eError;
193 IMG_BOOL bTimeout = IMG_TRUE;
195 eError = SysAcquireData(&psSysData);
196 if (eError != PVRSRV_OK)
199 psQueue = psSysData->psQueueList;
201 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
202 if (psQueueInfo->ui32ReadOffset ==
203 psQueueInfo->ui32WriteOffset) {
204 bTimeout = IMG_FALSE;
207 OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
209 END_LOOP_UNTIL_TIMEOUT();
212 PVR_DPF(PVR_DBG_ERROR,
213 "PVRSRVDestroyCommandQueueKM : Failed to empty queue");
214 eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE;
218 eError = OSLockResource(&psSysData->sQProcessResource, KERNEL_ID);
219 if (eError != PVRSRV_OK)
222 if (psQueue == psQueueInfo) {
223 psSysData->psQueueList = psQueueInfo->psNextKM;
225 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
226 psQueueInfo->ui32QueueSize,
227 psQueueInfo->pvLinQueueKM, psQueueInfo->hMemBlock[1]);
228 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
229 sizeof(struct PVRSRV_QUEUE_INFO),
230 psQueueInfo, psQueueInfo->hMemBlock[0]);
233 if (psQueue->psNextKM == psQueueInfo) {
234 psQueue->psNextKM = psQueueInfo->psNextKM;
236 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
237 psQueueInfo->ui32QueueSize,
238 psQueueInfo->pvLinQueueKM,
239 psQueueInfo->hMemBlock[1]);
240 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
241 sizeof(struct PVRSRV_QUEUE_INFO),
243 psQueueInfo->hMemBlock[0]);
246 psQueue = psQueue->psNextKM;
251 OSUnlockResource(&psSysData->sQProcessResource,
253 if (eError != PVRSRV_OK)
255 eError = PVRSRV_ERROR_INVALID_PARAMS;
260 eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
261 if (eError != PVRSRV_OK)
264 if (psSysData->psQueueList == NULL) {
265 eError = OSDestroyResource(&psSysData->sQProcessResource);
266 if (eError != PVRSRV_OK)
275 enum PVRSRV_ERROR PVRSRVGetQueueSpaceKM(struct PVRSRV_QUEUE_INFO *psQueue,
276 u32 ui32ParamSize, void **ppvSpace)
278 IMG_BOOL bTimeout = IMG_TRUE;
280 ui32ParamSize = (ui32ParamSize + 3) & 0xFFFFFFFC;
282 if (ui32ParamSize > PVRSRV_MAX_CMD_SIZE) {
283 PVR_DPF(PVR_DBG_WARNING,
284 "PVRSRVGetQueueSpace: max command size is %d bytes",
285 PVRSRV_MAX_CMD_SIZE);
286 return PVRSRV_ERROR_CMD_TOO_BIG;
289 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
290 if (GET_SPACE_IN_CMDQ(psQueue) > ui32ParamSize) {
291 bTimeout = IMG_FALSE;
294 OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
296 END_LOOP_UNTIL_TIMEOUT();
298 if (bTimeout == IMG_TRUE) {
301 return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE;
303 *ppvSpace = (void *)(psQueue->ui32WriteOffset +
304 (u32)psQueue->pvLinQueueUM);
310 enum PVRSRV_ERROR PVRSRVInsertCommandKM(struct PVRSRV_QUEUE_INFO *psQueue,
311 struct PVRSRV_COMMAND **ppsCommand,
312 u32 ui32DevIndex, u16 CommandType,
313 u32 ui32DstSyncCount,
314 struct PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
315 u32 ui32SrcSyncCount,
316 struct PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
317 u32 ui32DataByteSize)
319 enum PVRSRV_ERROR eError;
320 struct PVRSRV_COMMAND *psCommand;
324 ui32DataByteSize = (ui32DataByteSize + 3) & 0xFFFFFFFC;
326 ui32CommandSize = sizeof(struct PVRSRV_COMMAND) +
327 ((ui32DstSyncCount + ui32SrcSyncCount) *
328 sizeof(struct PVRSRV_SYNC_OBJECT)) + ui32DataByteSize;
330 eError = PVRSRVGetQueueSpaceKM(psQueue, ui32CommandSize,
331 (void **) &psCommand);
332 if (eError != PVRSRV_OK)
335 psCommand->ui32ProcessID = OSGetCurrentProcessIDKM();
337 psCommand->ui32CmdSize = ui32CommandSize;
338 psCommand->ui32DevIndex = ui32DevIndex;
339 psCommand->CommandType = CommandType;
340 psCommand->ui32DstSyncCount = ui32DstSyncCount;
341 psCommand->ui32SrcSyncCount = ui32SrcSyncCount;
342 psCommand->psDstSync =
343 (struct PVRSRV_SYNC_OBJECT *)(((u8 *) psCommand) +
344 sizeof(struct PVRSRV_COMMAND));
346 psCommand->psSrcSync =
347 (struct PVRSRV_SYNC_OBJECT *)(((u8 *) psCommand->psDstSync) +
349 sizeof(struct PVRSRV_SYNC_OBJECT)));
352 (struct PVRSRV_SYNC_OBJECT *)(((u8 *) psCommand->psSrcSync) +
354 sizeof(struct PVRSRV_SYNC_OBJECT)));
356 psCommand->ui32DataSize = ui32DataByteSize;
358 for (i = 0; i < ui32DstSyncCount; i++) {
359 psCommand->psDstSync[i].psKernelSyncInfoKM = apsDstSync[i];
360 psCommand->psDstSync[i].ui32WriteOpsPending =
361 PVRSRVGetWriteOpsPending(apsDstSync[i], IMG_FALSE);
362 psCommand->psDstSync[i].ui32ReadOpsPending =
363 PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
366 for (i = 0; i < ui32SrcSyncCount; i++) {
367 psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i];
368 psCommand->psSrcSync[i].ui32WriteOpsPending =
369 PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE);
370 psCommand->psSrcSync[i].ui32ReadOpsPending =
371 PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
374 *ppsCommand = psCommand;
379 enum PVRSRV_ERROR PVRSRVSubmitCommandKM(struct PVRSRV_QUEUE_INFO *psQueue,
380 struct PVRSRV_COMMAND *psCommand)
383 if (psCommand->ui32DstSyncCount > 0) {
384 psCommand->psDstSync = (struct PVRSRV_SYNC_OBJECT *)
385 (((u8 *)psQueue->pvLinQueueKM) +
386 psQueue->ui32WriteOffset +
387 sizeof(struct PVRSRV_COMMAND));
390 if (psCommand->ui32SrcSyncCount > 0) {
391 psCommand->psSrcSync = (struct PVRSRV_SYNC_OBJECT *)
392 (((u8 *)psQueue->pvLinQueueKM) +
393 psQueue->ui32WriteOffset +
394 sizeof(struct PVRSRV_COMMAND) +
395 (psCommand->ui32DstSyncCount *
396 sizeof(struct PVRSRV_SYNC_OBJECT)));
399 psCommand->pvData = (struct PVRSRV_SYNC_OBJECT *)
400 (((u8 *)psQueue->pvLinQueueKM) +
401 psQueue->ui32WriteOffset +
402 sizeof(struct PVRSRV_COMMAND) +
403 (psCommand->ui32DstSyncCount *
404 sizeof(struct PVRSRV_SYNC_OBJECT)) +
405 (psCommand->ui32SrcSyncCount *
406 sizeof(struct PVRSRV_SYNC_OBJECT)));
408 UPDATE_QUEUE_WOFF(psQueue, psCommand->ui32CmdSize);
413 static enum PVRSRV_ERROR PVRSRVProcessCommand(struct SYS_DATA *psSysData,
414 struct PVRSRV_COMMAND *psCommand,
417 struct PVRSRV_SYNC_OBJECT *psWalkerObj;
418 struct PVRSRV_SYNC_OBJECT *psEndObj;
420 struct COMMAND_COMPLETE_DATA *psCmdCompleteData;
421 enum PVRSRV_ERROR eError = PVRSRV_OK;
422 u32 ui32WriteOpsComplete;
423 u32 ui32ReadOpsComplete;
425 psWalkerObj = psCommand->psDstSync;
426 psEndObj = psWalkerObj + psCommand->ui32DstSyncCount;
427 while (psWalkerObj < psEndObj) {
428 struct PVRSRV_SYNC_DATA *psSyncData =
429 psWalkerObj->psKernelSyncInfoKM->psSyncData;
431 ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
432 ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
434 if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
435 || (ui32ReadOpsComplete !=
436 psWalkerObj->ui32ReadOpsPending)) {
438 !SYNCOPS_STALE(ui32WriteOpsComplete,
439 psWalkerObj->ui32WriteOpsPending) ||
440 !SYNCOPS_STALE(ui32ReadOpsComplete,
441 psWalkerObj->ui32ReadOpsPending)) {
442 return PVRSRV_ERROR_FAILED_DEPENDENCIES;
449 psWalkerObj = psCommand->psSrcSync;
450 psEndObj = psWalkerObj + psCommand->ui32SrcSyncCount;
451 while (psWalkerObj < psEndObj) {
452 struct PVRSRV_SYNC_DATA *psSyncData =
453 psWalkerObj->psKernelSyncInfoKM->psSyncData;
455 ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
456 ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
458 if ((ui32WriteOpsComplete !=
459 psWalkerObj->ui32WriteOpsPending) ||
460 (ui32ReadOpsComplete !=
461 psWalkerObj->ui32ReadOpsPending)) {
463 SYNCOPS_STALE(ui32WriteOpsComplete,
464 psWalkerObj->ui32WriteOpsPending) &&
465 SYNCOPS_STALE(ui32ReadOpsComplete,
466 psWalkerObj->ui32ReadOpsPending)) {
467 PVR_DPF(PVR_DBG_WARNING,
468 "PVRSRVProcessCommand: Stale syncops psSyncData:0x%x "
469 "ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
470 psSyncData, ui32WriteOpsComplete,
471 psWalkerObj->ui32WriteOpsPending);
475 !SYNCOPS_STALE(ui32WriteOpsComplete,
476 psWalkerObj->ui32WriteOpsPending) ||
477 !SYNCOPS_STALE(ui32ReadOpsComplete,
478 psWalkerObj->ui32ReadOpsPending)) {
479 return PVRSRV_ERROR_FAILED_DEPENDENCIES;
485 if (psCommand->ui32DevIndex >= SYS_DEVICE_COUNT) {
486 PVR_DPF(PVR_DBG_ERROR,
487 "PVRSRVProcessCommand: invalid DeviceType 0x%x",
488 psCommand->ui32DevIndex);
489 return PVRSRV_ERROR_INVALID_PARAMS;
493 psSysData->ppsCmdCompleteData[psCommand->ui32DevIndex][psCommand->
495 if (psCmdCompleteData->bInUse)
497 return PVRSRV_ERROR_FAILED_DEPENDENCIES;
499 psCmdCompleteData->bInUse = IMG_TRUE;
501 psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount;
502 for (i = 0; i < psCommand->ui32DstSyncCount; i++)
503 psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i];
505 psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
506 for (i = 0; i < psCommand->ui32SrcSyncCount; i++)
507 psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
509 if (psSysData->ppfnCmdProcList[psCommand->ui32DevIndex]
510 [psCommand->CommandType]((void *)
512 psCommand->ui32DataSize,
513 psCommand->pvData) == IMG_FALSE) {
514 psCmdCompleteData->bInUse = IMG_FALSE;
515 eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
521 enum PVRSRV_ERROR PVRSRVProcessQueues(u32 ui32CallerID, IMG_BOOL bFlush)
523 struct PVRSRV_QUEUE_INFO *psQueue;
524 struct SYS_DATA *psSysData;
525 struct PVRSRV_COMMAND *psCommand;
526 struct PVRSRV_DEVICE_NODE *psDeviceNode;
527 enum PVRSRV_ERROR eError;
529 eError = SysAcquireData(&psSysData);
530 if (eError != PVRSRV_OK)
533 psSysData->bReProcessQueues = IMG_FALSE;
535 eError = OSLockResource(&psSysData->sQProcessResource, ui32CallerID);
536 if (eError != PVRSRV_OK) {
537 psSysData->bReProcessQueues = IMG_TRUE;
539 if (ui32CallerID == ISR_ID) {
541 PVR_DPF(PVR_DBG_ERROR, "PVRSRVProcessQueues: "
542 "Couldn't acquire queue processing "
545 PVR_DPF(PVR_DBG_MESSAGE,
546 "PVRSRVProcessQueues: "
547 "Couldn't acquire queue "
551 PVR_DPF(PVR_DBG_MESSAGE, "PVRSRVProcessQueues: "
552 "Queue processing lock-acquire failed "
553 "when called from the Services driver.");
554 PVR_DPF(PVR_DBG_MESSAGE,
555 "This is due to MISR queue processing "
556 "being interrupted by the Services driver.");
562 psQueue = psSysData->psQueueList;
565 PVR_DPF(PVR_DBG_MESSAGE,
566 "No Queues installed - cannot process commands");
570 PVRSRVSetDCState(DC_STATE_FLUSH_COMMANDS);
573 while (psQueue->ui32ReadOffset != psQueue->ui32WriteOffset) {
574 psCommand = (struct PVRSRV_COMMAND *)((u32) psQueue->
575 pvLinQueueKM + psQueue->ui32ReadOffset);
577 if (PVRSRVProcessCommand(psSysData, psCommand, bFlush)
579 UPDATE_QUEUE_ROFF(psQueue,
580 psCommand->ui32CmdSize)
586 psQueue = psQueue->psNextKM;
590 PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
592 psDeviceNode = psSysData->psDeviceNodeList;
593 while (psDeviceNode != NULL) {
594 if (psDeviceNode->bReProcessDeviceCommandComplete &&
595 psDeviceNode->pfnDeviceCommandComplete != NULL) {
597 pfnDeviceCommandComplete) (psDeviceNode);
599 psDeviceNode = psDeviceNode->psNext;
602 OSUnlockResource(&psSysData->sQProcessResource, ui32CallerID);
604 if (psSysData->bReProcessQueues)
605 return PVRSRV_ERROR_PROCESSING_BLOCKED;
610 void PVRSRVCommandCompleteKM(void *hCmdCookie, IMG_BOOL bScheduleMISR)
613 struct COMMAND_COMPLETE_DATA *psCmdCompleteData =
614 (struct COMMAND_COMPLETE_DATA *)hCmdCookie;
615 struct SYS_DATA *psSysData;
617 if (SysAcquireData(&psSysData) != PVRSRV_OK)
620 for (i = 0; i < psCmdCompleteData->ui32DstSyncCount; i++) {
621 psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->
622 ui32WriteOpsComplete++;
625 for (i = 0; i < psCmdCompleteData->ui32SrcSyncCount; i++) {
626 psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->
627 ui32ReadOpsComplete++;
630 psCmdCompleteData->bInUse = IMG_FALSE;
632 PVRSRVCommandCompleteCallbacks();
635 OSScheduleMISR(psSysData);
638 void PVRSRVCommandCompleteCallbacks(void)
640 struct SYS_DATA *psSysData;
641 struct PVRSRV_DEVICE_NODE *psDeviceNode;
643 if (SysAcquireData(&psSysData) != PVRSRV_OK) {
644 PVR_DPF(PVR_DBG_ERROR, "PVRSRVCommandCompleteCallbacks: "
645 "SysAcquireData failed");
649 psDeviceNode = psSysData->psDeviceNodeList;
650 while (psDeviceNode != NULL) {
651 if (psDeviceNode->pfnDeviceCommandComplete != NULL)
652 (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
653 psDeviceNode = psDeviceNode->psNext;
657 enum PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(u32 ui32DevIndex,
658 IMG_BOOL (**ppfnCmdProcList)(void *, u32, void *),
659 u32 ui32MaxSyncsPerCmd[][2], u32 ui32CmdCount)
661 struct SYS_DATA *psSysData;
662 enum PVRSRV_ERROR eError;
665 IMG_BOOL (**ppfnCmdProc)(void *, u32, void *);
666 struct COMMAND_COMPLETE_DATA *psCmdCompleteData;
668 if (ui32DevIndex >= SYS_DEVICE_COUNT) {
669 PVR_DPF(PVR_DBG_ERROR,
670 "PVRSRVRegisterCmdProcListKM: invalid DeviceType 0x%x",
672 return PVRSRV_ERROR_INVALID_PARAMS;
675 eError = SysAcquireData(&psSysData);
676 if (eError != PVRSRV_OK) {
677 PVR_DPF(PVR_DBG_ERROR,
678 "PVRSRVRegisterCmdProcListKM: SysAcquireData failed");
682 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, ui32CmdCount *
683 sizeof(IMG_BOOL (*)(void *, u32, void *)),
684 (void **)&psSysData->ppfnCmdProcList[ui32DevIndex],
686 if (eError != PVRSRV_OK) {
687 PVR_DPF(PVR_DBG_ERROR,
688 "PVRSRVRegisterCmdProcListKM: Failed to alloc queue");
692 ppfnCmdProc = psSysData->ppfnCmdProcList[ui32DevIndex];
694 for (i = 0; i < ui32CmdCount; i++)
695 ppfnCmdProc[i] = ppfnCmdProcList[i];
697 ui32AllocSize = ui32CmdCount * sizeof(struct COMMAND_COMPLETE_DATA *);
698 eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
700 (void **) &psSysData->
701 ppsCmdCompleteData[ui32DevIndex], NULL);
702 if (eError != PVRSRV_OK) {
703 PVR_DPF(PVR_DBG_ERROR,
704 "PVRSRVRegisterCmdProcListKM: Failed to alloc CC data");
708 /* clear the list to ensure that we don't try to access uninitialised
709 * pointer in the 'error' execution path */
710 OSMemSet(psSysData->ppsCmdCompleteData[ui32DevIndex], 0x00,
713 for (i = 0; i < ui32CmdCount; i++) {
714 ui32AllocSize = sizeof(struct COMMAND_COMPLETE_DATA)
715 + ((ui32MaxSyncsPerCmd[i][0] + ui32MaxSyncsPerCmd[i][1])
716 * sizeof(struct PVRSRV_SYNC_OBJECT));
718 eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
720 (void **)&psSysData->
721 ppsCmdCompleteData[ui32DevIndex][i],
723 if (eError != PVRSRV_OK) {
724 PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterCmdProcListKM: "
725 "Failed to alloc cmd %d",
730 OSMemSet(psSysData->ppsCmdCompleteData[ui32DevIndex][i], 0x00,
734 psSysData->ppsCmdCompleteData[ui32DevIndex][i];
736 psCmdCompleteData->psDstSync = (struct PVRSRV_SYNC_OBJECT *)
737 (((u32) psCmdCompleteData) +
738 sizeof(struct COMMAND_COMPLETE_DATA));
739 psCmdCompleteData->psSrcSync = (struct PVRSRV_SYNC_OBJECT *)
740 (((u32) psCmdCompleteData->psDstSync) +
741 (sizeof(struct PVRSRV_SYNC_OBJECT) *
742 ui32MaxSyncsPerCmd[i][0]));
743 psCmdCompleteData->ui32AllocSize = ui32AllocSize;
750 if (psSysData->ppsCmdCompleteData[ui32DevIndex] != NULL) {
751 for (i = 0; i < ui32CmdCount; i++) {
752 if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] !=
756 ppsCmdCompleteData[ui32DevIndex][i];
757 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
758 psCmdCompleteData->ui32AllocSize,
759 psCmdCompleteData, NULL);
763 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
764 ui32CmdCount * sizeof(struct COMMAND_COMPLETE_DATA *),
765 psSysData->ppsCmdCompleteData[ui32DevIndex],
769 if (psSysData->ppfnCmdProcList[ui32DevIndex] != NULL) {
770 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
771 psSysData->ppfnCmdProcList[ui32DevIndex], NULL);
777 enum PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(u32 ui32DevIndex, u32 ui32CmdCount)
779 struct SYS_DATA *psSysData;
780 enum PVRSRV_ERROR eError;
783 if (ui32DevIndex >= SYS_DEVICE_COUNT) {
784 PVR_DPF(PVR_DBG_ERROR,
785 "PVRSRVRemoveCmdProcListKM: invalid DeviceType 0x%x",
787 return PVRSRV_ERROR_INVALID_PARAMS;
790 eError = SysAcquireData(&psSysData);
791 if (eError != PVRSRV_OK) {
792 PVR_DPF(PVR_DBG_ERROR,
793 "PVRSRVRemoveCmdProcListKM: SysAcquireData failed");
797 if (psSysData->ppsCmdCompleteData[ui32DevIndex] == NULL) {
798 PVR_DPF(PVR_DBG_ERROR,
799 "PVRSRVRemoveCmdProcListKM: Invalid command array");
800 return PVRSRV_ERROR_INVALID_PARAMS;
802 for (i = 0; i < ui32CmdCount; i++) {
804 if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] !=
806 struct COMMAND_COMPLETE_DATA *
807 psCmdCompleteData = psSysData->
808 ppsCmdCompleteData[ui32DevIndex][i];
809 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
810 psCmdCompleteData->ui32AllocSize,
811 psCmdCompleteData, NULL);
815 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
816 ui32CmdCount * sizeof(struct COMMAND_COMPLETE_DATA *),
817 psSysData->ppsCmdCompleteData[ui32DevIndex], NULL);
820 if (psSysData->ppfnCmdProcList[ui32DevIndex] != NULL) {
821 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
823 sizeof(IMG_BOOL (*)(void *, u32, void *)),
824 psSysData->ppfnCmdProcList[ui32DevIndex], NULL);