diff options
Diffstat (limited to 'drivers/gpu/pvr/queue.c')
-rw-r--r-- | drivers/gpu/pvr/queue.c | 1154 |
1 files changed, 1154 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/queue.c b/drivers/gpu/pvr/queue.c new file mode 100644 index 00000000000..5340571d64c --- /dev/null +++ b/drivers/gpu/pvr/queue.c | |||
@@ -0,0 +1,1154 @@ | |||
1 | /********************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved. | ||
4 | * | ||
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. | ||
8 | * | ||
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. | ||
13 | * | ||
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. | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in | ||
19 | * the file called "COPYING". | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Imagination Technologies Ltd. <gpl-support@imgtec.com> | ||
23 | * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK | ||
24 | * | ||
25 | ******************************************************************************/ | ||
26 | |||
27 | #include "services_headers.h" | ||
28 | |||
29 | #include "lists.h" | ||
30 | |||
31 | #if defined(__linux__) && defined(__KERNEL__) | ||
32 | |||
33 | #include "proc.h" | ||
34 | |||
35 | static IMG_INT | ||
36 | QueuePrintCommands (PVRSRV_QUEUE_INFO * psQueue, IMG_CHAR * buffer, size_t size) | ||
37 | { | ||
38 | off_t off = 0; | ||
39 | IMG_INT cmds = 0; | ||
40 | IMG_SIZE_T ui32ReadOffset = psQueue->ui32ReadOffset; | ||
41 | IMG_SIZE_T ui32WriteOffset = psQueue->ui32WriteOffset; | ||
42 | PVRSRV_COMMAND * psCmd; | ||
43 | |||
44 | while (ui32ReadOffset != ui32WriteOffset) | ||
45 | { | ||
46 | psCmd= (PVRSRV_COMMAND *)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + ui32ReadOffset); | ||
47 | |||
48 | off = printAppend(buffer, size, off, "%x %x %5u %6u %3u %5u %2u %2u %3u \n", | ||
49 | (IMG_UINTPTR_T)psQueue, | ||
50 | (IMG_UINTPTR_T)psCmd, | ||
51 | psCmd->ui32ProcessID, | ||
52 | psCmd->CommandType, | ||
53 | psCmd->ui32CmdSize, | ||
54 | psCmd->ui32DevIndex, | ||
55 | psCmd->ui32DstSyncCount, | ||
56 | psCmd->ui32SrcSyncCount, | ||
57 | psCmd->ui32DataSize); | ||
58 | |||
59 | ui32ReadOffset += psCmd->ui32CmdSize; | ||
60 | ui32ReadOffset &= psQueue->ui32QueueSize - 1; | ||
61 | cmds++; | ||
62 | } | ||
63 | if (cmds == 0) | ||
64 | { | ||
65 | off = printAppend(buffer, size, off, "%x <empty>\n", (IMG_UINTPTR_T)psQueue); | ||
66 | } | ||
67 | return off; | ||
68 | } | ||
69 | |||
70 | |||
71 | |||
72 | void ProcSeqShowQueue(struct seq_file *sfile,void* el) | ||
73 | { | ||
74 | PVRSRV_QUEUE_INFO * psQueue = (PVRSRV_QUEUE_INFO*)el; | ||
75 | IMG_INT cmds = 0; | ||
76 | IMG_SIZE_T ui32ReadOffset; | ||
77 | IMG_SIZE_T ui32WriteOffset; | ||
78 | PVRSRV_COMMAND * psCmd; | ||
79 | |||
80 | if(el == PVR_PROC_SEQ_START_TOKEN) | ||
81 | { | ||
82 | seq_printf( sfile, | ||
83 | "Command Queues\n" | ||
84 | "Queue CmdPtr Pid Command Size DevInd DSC SSC #Data ...\n"); | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | ui32ReadOffset = psQueue->ui32ReadOffset; | ||
89 | ui32WriteOffset = psQueue->ui32WriteOffset; | ||
90 | |||
91 | while (ui32ReadOffset != ui32WriteOffset) | ||
92 | { | ||
93 | psCmd= (PVRSRV_COMMAND *)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + ui32ReadOffset); | ||
94 | |||
95 | seq_printf(sfile, "%x %x %5u %6u %3u %5u %2u %2u %3u \n", | ||
96 | (IMG_UINTPTR_T)psQueue, | ||
97 | (IMG_UINTPTR_T)psCmd, | ||
98 | psCmd->ui32ProcessID, | ||
99 | psCmd->CommandType, | ||
100 | psCmd->ui32CmdSize, | ||
101 | psCmd->ui32DevIndex, | ||
102 | psCmd->ui32DstSyncCount, | ||
103 | psCmd->ui32SrcSyncCount, | ||
104 | psCmd->ui32DataSize); | ||
105 | |||
106 | ui32ReadOffset += psCmd->ui32CmdSize; | ||
107 | ui32ReadOffset &= psQueue->ui32QueueSize - 1; | ||
108 | cmds++; | ||
109 | } | ||
110 | |||
111 | if (cmds == 0) | ||
112 | { | ||
113 | seq_printf(sfile, "%x <empty>\n", (IMG_UINTPTR_T)psQueue); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off) | ||
118 | { | ||
119 | PVRSRV_QUEUE_INFO * psQueue; | ||
120 | SYS_DATA * psSysData; | ||
121 | |||
122 | PVR_UNREFERENCED_PARAMETER(sfile); | ||
123 | |||
124 | if(!off) | ||
125 | { | ||
126 | return PVR_PROC_SEQ_START_TOKEN; | ||
127 | } | ||
128 | |||
129 | |||
130 | SysAcquireData(&psSysData); | ||
131 | |||
132 | for (psQueue = psSysData->psQueueList; (((--off) > 0) && (psQueue != IMG_NULL)); psQueue = psQueue->psNextKM); | ||
133 | return psQueue; | ||
134 | } | ||
135 | |||
136 | off_t | ||
137 | QueuePrintQueues (IMG_CHAR * buffer, size_t size, off_t off) | ||
138 | { | ||
139 | SYS_DATA * psSysData; | ||
140 | PVRSRV_QUEUE_INFO * psQueue; | ||
141 | |||
142 | SysAcquireData(&psSysData); | ||
143 | |||
144 | if (!off) | ||
145 | return printAppend (buffer, size, 0, | ||
146 | "Command Queues\n" | ||
147 | "Queue CmdPtr Pid Command Size DevInd DSC SSC #Data ...\n"); | ||
148 | |||
149 | |||
150 | for (psQueue = psSysData->psQueueList; (((--off) > 0) && (psQueue != IMG_NULL)); psQueue = psQueue->psNextKM) | ||
151 | ; | ||
152 | |||
153 | return psQueue ? QueuePrintCommands (psQueue, buffer, size) : END_OF_FILE; | ||
154 | } | ||
155 | #endif | ||
156 | |||
157 | #define GET_SPACE_IN_CMDQ(psQueue) \ | ||
158 | ((((psQueue)->ui32ReadOffset - (psQueue)->ui32WriteOffset) \ | ||
159 | + ((psQueue)->ui32QueueSize - 1)) & ((psQueue)->ui32QueueSize - 1)) | ||
160 | |||
161 | #define UPDATE_QUEUE_WOFF(psQueue, ui32Size) \ | ||
162 | (psQueue)->ui32WriteOffset = ((psQueue)->ui32WriteOffset + (ui32Size)) \ | ||
163 | & ((psQueue)->ui32QueueSize - 1); | ||
164 | |||
165 | #define SYNCOPS_STALE(ui32OpsComplete, ui32OpsPending) \ | ||
166 | ((ui32OpsComplete) >= (ui32OpsPending)) | ||
167 | |||
168 | |||
169 | static IMG_VOID QueueDumpCmdComplete(COMMAND_COMPLETE_DATA *psCmdCompleteData, | ||
170 | IMG_UINT32 i, | ||
171 | IMG_BOOL bIsSrc) | ||
172 | { | ||
173 | PVRSRV_SYNC_OBJECT *psSyncObject; | ||
174 | |||
175 | psSyncObject = bIsSrc ? psCmdCompleteData->psSrcSync : psCmdCompleteData->psDstSync; | ||
176 | |||
177 | if (psCmdCompleteData->bInUse) | ||
178 | { | ||
179 | PVR_LOG(("\t%s %u: ROC DevVAddr:0x%X ROP:0x%x ROC:0x%x, WOC DevVAddr:0x%X WOP:0x%x WOC:0x%x", | ||
180 | bIsSrc ? "SRC" : "DEST", i, | ||
181 | psSyncObject[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr, | ||
182 | psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsPending, | ||
183 | psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete, | ||
184 | psSyncObject[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr, | ||
185 | psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsPending, | ||
186 | psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete)) | ||
187 | } | ||
188 | else | ||
189 | { | ||
190 | PVR_LOG(("\t%s %u: (Not in use)", bIsSrc ? "SRC" : "DEST", i)) | ||
191 | } | ||
192 | } | ||
193 | |||
194 | |||
195 | static IMG_VOID QueueDumpDebugInfo_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode) | ||
196 | { | ||
197 | if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY) | ||
198 | { | ||
199 | IMG_UINT32 i; | ||
200 | SYS_DATA *psSysData; | ||
201 | COMMAND_COMPLETE_DATA **ppsCmdCompleteData; | ||
202 | COMMAND_COMPLETE_DATA *psCmdCompleteData; | ||
203 | |||
204 | SysAcquireData(&psSysData); | ||
205 | |||
206 | ppsCmdCompleteData = psSysData->ppsCmdCompleteData[psDeviceNode->sDevId.ui32DeviceIndex]; | ||
207 | |||
208 | if (ppsCmdCompleteData != IMG_NULL) | ||
209 | { | ||
210 | psCmdCompleteData = ppsCmdCompleteData[DC_FLIP_COMMAND]; | ||
211 | |||
212 | PVR_LOG(("Command Complete Data for display device %u:", psDeviceNode->sDevId.ui32DeviceIndex)) | ||
213 | |||
214 | for (i = 0; i < psCmdCompleteData->ui32SrcSyncCount; i++) | ||
215 | { | ||
216 | QueueDumpCmdComplete(psCmdCompleteData, i, IMG_TRUE); | ||
217 | } | ||
218 | |||
219 | for (i = 0; i < psCmdCompleteData->ui32DstSyncCount; i++) | ||
220 | { | ||
221 | QueueDumpCmdComplete(psCmdCompleteData, i, IMG_FALSE); | ||
222 | } | ||
223 | } | ||
224 | else | ||
225 | { | ||
226 | PVR_LOG(("There is no Command Complete Data for display device %u", psDeviceNode->sDevId.ui32DeviceIndex)) | ||
227 | } | ||
228 | } | ||
229 | } | ||
230 | |||
231 | |||
232 | IMG_VOID QueueDumpDebugInfo(IMG_VOID) | ||
233 | { | ||
234 | SYS_DATA *psSysData; | ||
235 | SysAcquireData(&psSysData); | ||
236 | List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, &QueueDumpDebugInfo_ForEachCb); | ||
237 | } | ||
238 | |||
239 | |||
240 | static IMG_SIZE_T NearestPower2(IMG_SIZE_T ui32Value) | ||
241 | { | ||
242 | IMG_SIZE_T ui32Temp, ui32Result = 1; | ||
243 | |||
244 | if(!ui32Value) | ||
245 | return 0; | ||
246 | |||
247 | ui32Temp = ui32Value - 1; | ||
248 | while(ui32Temp) | ||
249 | { | ||
250 | ui32Result <<= 1; | ||
251 | ui32Temp >>= 1; | ||
252 | } | ||
253 | |||
254 | return ui32Result; | ||
255 | } | ||
256 | |||
257 | |||
258 | IMG_EXPORT | ||
259 | PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize, | ||
260 | PVRSRV_QUEUE_INFO **ppsQueueInfo) | ||
261 | { | ||
262 | PVRSRV_QUEUE_INFO *psQueueInfo; | ||
263 | IMG_SIZE_T ui32Power2QueueSize = NearestPower2(ui32QueueSize); | ||
264 | SYS_DATA *psSysData; | ||
265 | PVRSRV_ERROR eError; | ||
266 | IMG_HANDLE hMemBlock; | ||
267 | |||
268 | SysAcquireData(&psSysData); | ||
269 | |||
270 | |||
271 | eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
272 | sizeof(PVRSRV_QUEUE_INFO), | ||
273 | (IMG_VOID **)&psQueueInfo, &hMemBlock, | ||
274 | "Queue Info"); | ||
275 | if (eError != PVRSRV_OK) | ||
276 | { | ||
277 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue struct")); | ||
278 | goto ErrorExit; | ||
279 | } | ||
280 | OSMemSet(psQueueInfo, 0, sizeof(PVRSRV_QUEUE_INFO)); | ||
281 | |||
282 | psQueueInfo->hMemBlock[0] = hMemBlock; | ||
283 | psQueueInfo->ui32ProcessID = OSGetCurrentProcessIDKM(); | ||
284 | |||
285 | |||
286 | eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
287 | ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE, | ||
288 | &psQueueInfo->pvLinQueueKM, &hMemBlock, | ||
289 | "Command Queue"); | ||
290 | if (eError != PVRSRV_OK) | ||
291 | { | ||
292 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue buffer")); | ||
293 | goto ErrorExit; | ||
294 | } | ||
295 | |||
296 | psQueueInfo->hMemBlock[1] = hMemBlock; | ||
297 | psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM; | ||
298 | |||
299 | |||
300 | PVR_ASSERT(psQueueInfo->ui32ReadOffset == 0); | ||
301 | PVR_ASSERT(psQueueInfo->ui32WriteOffset == 0); | ||
302 | |||
303 | psQueueInfo->ui32QueueSize = ui32Power2QueueSize; | ||
304 | |||
305 | |||
306 | if (psSysData->psQueueList == IMG_NULL) | ||
307 | { | ||
308 | eError = OSCreateResource(&psSysData->sQProcessResource); | ||
309 | if (eError != PVRSRV_OK) | ||
310 | { | ||
311 | goto ErrorExit; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | |||
316 | eError = OSLockResource(&psSysData->sQProcessResource, | ||
317 | KERNEL_ID); | ||
318 | if (eError != PVRSRV_OK) | ||
319 | { | ||
320 | goto ErrorExit; | ||
321 | } | ||
322 | |||
323 | psQueueInfo->psNextKM = psSysData->psQueueList; | ||
324 | psSysData->psQueueList = psQueueInfo; | ||
325 | |||
326 | eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID); | ||
327 | if (eError != PVRSRV_OK) | ||
328 | { | ||
329 | goto ErrorExit; | ||
330 | } | ||
331 | |||
332 | *ppsQueueInfo = psQueueInfo; | ||
333 | |||
334 | return PVRSRV_OK; | ||
335 | |||
336 | ErrorExit: | ||
337 | |||
338 | if(psQueueInfo) | ||
339 | { | ||
340 | if(psQueueInfo->pvLinQueueKM) | ||
341 | { | ||
342 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
343 | psQueueInfo->ui32QueueSize, | ||
344 | psQueueInfo->pvLinQueueKM, | ||
345 | psQueueInfo->hMemBlock[1]); | ||
346 | psQueueInfo->pvLinQueueKM = IMG_NULL; | ||
347 | } | ||
348 | |||
349 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
350 | sizeof(PVRSRV_QUEUE_INFO), | ||
351 | psQueueInfo, | ||
352 | psQueueInfo->hMemBlock[0]); | ||
353 | |||
354 | } | ||
355 | |||
356 | return eError; | ||
357 | } | ||
358 | |||
359 | |||
360 | IMG_EXPORT | ||
361 | PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo) | ||
362 | { | ||
363 | PVRSRV_QUEUE_INFO *psQueue; | ||
364 | SYS_DATA *psSysData; | ||
365 | PVRSRV_ERROR eError; | ||
366 | IMG_BOOL bTimeout = IMG_TRUE; | ||
367 | |||
368 | SysAcquireData(&psSysData); | ||
369 | |||
370 | psQueue = psSysData->psQueueList; | ||
371 | |||
372 | |||
373 | LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) | ||
374 | { | ||
375 | if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset) | ||
376 | { | ||
377 | bTimeout = IMG_FALSE; | ||
378 | break; | ||
379 | } | ||
380 | OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT); | ||
381 | } END_LOOP_UNTIL_TIMEOUT(); | ||
382 | |||
383 | if (bTimeout) | ||
384 | { | ||
385 | |||
386 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyCommandQueueKM : Failed to empty queue")); | ||
387 | eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE; | ||
388 | goto ErrorExit; | ||
389 | } | ||
390 | |||
391 | |||
392 | eError = OSLockResource(&psSysData->sQProcessResource, | ||
393 | KERNEL_ID); | ||
394 | if (eError != PVRSRV_OK) | ||
395 | { | ||
396 | goto ErrorExit; | ||
397 | } | ||
398 | |||
399 | if(psQueue == psQueueInfo) | ||
400 | { | ||
401 | psSysData->psQueueList = psQueueInfo->psNextKM; | ||
402 | |||
403 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
404 | NearestPower2(psQueueInfo->ui32QueueSize) + PVRSRV_MAX_CMD_SIZE, | ||
405 | psQueueInfo->pvLinQueueKM, | ||
406 | psQueueInfo->hMemBlock[1]); | ||
407 | psQueueInfo->pvLinQueueKM = IMG_NULL; | ||
408 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
409 | sizeof(PVRSRV_QUEUE_INFO), | ||
410 | psQueueInfo, | ||
411 | psQueueInfo->hMemBlock[0]); | ||
412 | |||
413 | psQueueInfo = IMG_NULL; | ||
414 | } | ||
415 | else | ||
416 | { | ||
417 | while(psQueue) | ||
418 | { | ||
419 | if(psQueue->psNextKM == psQueueInfo) | ||
420 | { | ||
421 | psQueue->psNextKM = psQueueInfo->psNextKM; | ||
422 | |||
423 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
424 | psQueueInfo->ui32QueueSize, | ||
425 | psQueueInfo->pvLinQueueKM, | ||
426 | psQueueInfo->hMemBlock[1]); | ||
427 | psQueueInfo->pvLinQueueKM = IMG_NULL; | ||
428 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
429 | sizeof(PVRSRV_QUEUE_INFO), | ||
430 | psQueueInfo, | ||
431 | psQueueInfo->hMemBlock[0]); | ||
432 | |||
433 | psQueueInfo = IMG_NULL; | ||
434 | break; | ||
435 | } | ||
436 | psQueue = psQueue->psNextKM; | ||
437 | } | ||
438 | |||
439 | if(!psQueue) | ||
440 | { | ||
441 | eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID); | ||
442 | if (eError != PVRSRV_OK) | ||
443 | { | ||
444 | goto ErrorExit; | ||
445 | } | ||
446 | eError = PVRSRV_ERROR_INVALID_PARAMS; | ||
447 | goto ErrorExit; | ||
448 | } | ||
449 | } | ||
450 | |||
451 | |||
452 | eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID); | ||
453 | if (eError != PVRSRV_OK) | ||
454 | { | ||
455 | goto ErrorExit; | ||
456 | } | ||
457 | |||
458 | |||
459 | if (psSysData->psQueueList == IMG_NULL) | ||
460 | { | ||
461 | eError = OSDestroyResource(&psSysData->sQProcessResource); | ||
462 | if (eError != PVRSRV_OK) | ||
463 | { | ||
464 | goto ErrorExit; | ||
465 | } | ||
466 | } | ||
467 | |||
468 | ErrorExit: | ||
469 | |||
470 | return eError; | ||
471 | } | ||
472 | |||
473 | |||
474 | IMG_EXPORT | ||
475 | PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue, | ||
476 | IMG_SIZE_T ui32ParamSize, | ||
477 | IMG_VOID **ppvSpace) | ||
478 | { | ||
479 | IMG_BOOL bTimeout = IMG_TRUE; | ||
480 | |||
481 | |||
482 | ui32ParamSize = (ui32ParamSize+3) & 0xFFFFFFFC; | ||
483 | |||
484 | if (ui32ParamSize > PVRSRV_MAX_CMD_SIZE) | ||
485 | { | ||
486 | PVR_DPF((PVR_DBG_WARNING,"PVRSRVGetQueueSpace: max command size is %d bytes", PVRSRV_MAX_CMD_SIZE)); | ||
487 | return PVRSRV_ERROR_CMD_TOO_BIG; | ||
488 | } | ||
489 | |||
490 | |||
491 | LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) | ||
492 | { | ||
493 | if (GET_SPACE_IN_CMDQ(psQueue) > ui32ParamSize) | ||
494 | { | ||
495 | bTimeout = IMG_FALSE; | ||
496 | break; | ||
497 | } | ||
498 | OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT); | ||
499 | } END_LOOP_UNTIL_TIMEOUT(); | ||
500 | |||
501 | if (bTimeout == IMG_TRUE) | ||
502 | { | ||
503 | *ppvSpace = IMG_NULL; | ||
504 | |||
505 | return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE; | ||
506 | } | ||
507 | else | ||
508 | { | ||
509 | *ppvSpace = (IMG_VOID *)((IMG_UINTPTR_T)psQueue->pvLinQueueUM + psQueue->ui32WriteOffset); | ||
510 | } | ||
511 | |||
512 | return PVRSRV_OK; | ||
513 | } | ||
514 | |||
515 | |||
516 | IMG_EXPORT | ||
517 | PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue, | ||
518 | PVRSRV_COMMAND **ppsCommand, | ||
519 | IMG_UINT32 ui32DevIndex, | ||
520 | IMG_UINT16 CommandType, | ||
521 | IMG_UINT32 ui32DstSyncCount, | ||
522 | PVRSRV_KERNEL_SYNC_INFO *apsDstSync[], | ||
523 | IMG_UINT32 ui32SrcSyncCount, | ||
524 | PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[], | ||
525 | IMG_SIZE_T ui32DataByteSize ) | ||
526 | { | ||
527 | PVRSRV_ERROR eError; | ||
528 | PVRSRV_COMMAND *psCommand; | ||
529 | IMG_SIZE_T ui32CommandSize; | ||
530 | IMG_UINT32 i; | ||
531 | |||
532 | |||
533 | ui32DataByteSize = (ui32DataByteSize + 3UL) & ~3UL; | ||
534 | |||
535 | |||
536 | ui32CommandSize = sizeof(PVRSRV_COMMAND) | ||
537 | + ((ui32DstSyncCount + ui32SrcSyncCount) * sizeof(PVRSRV_SYNC_OBJECT)) | ||
538 | + ui32DataByteSize; | ||
539 | |||
540 | |||
541 | eError = PVRSRVGetQueueSpaceKM (psQueue, ui32CommandSize, (IMG_VOID**)&psCommand); | ||
542 | if(eError != PVRSRV_OK) | ||
543 | { | ||
544 | return eError; | ||
545 | } | ||
546 | |||
547 | psCommand->ui32ProcessID = OSGetCurrentProcessIDKM(); | ||
548 | |||
549 | |||
550 | psCommand->ui32CmdSize = ui32CommandSize; | ||
551 | psCommand->ui32DevIndex = ui32DevIndex; | ||
552 | psCommand->CommandType = CommandType; | ||
553 | psCommand->ui32DstSyncCount = ui32DstSyncCount; | ||
554 | psCommand->ui32SrcSyncCount = ui32SrcSyncCount; | ||
555 | |||
556 | |||
557 | psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand) + sizeof(PVRSRV_COMMAND)); | ||
558 | |||
559 | |||
560 | psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psDstSync) | ||
561 | + (ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT))); | ||
562 | |||
563 | psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psSrcSync) | ||
564 | + (ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT))); | ||
565 | psCommand->ui32DataSize = ui32DataByteSize; | ||
566 | |||
567 | |||
568 | for (i=0; i<ui32DstSyncCount; i++) | ||
569 | { | ||
570 | psCommand->psDstSync[i].psKernelSyncInfoKM = apsDstSync[i]; | ||
571 | psCommand->psDstSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsDstSync[i], IMG_FALSE); | ||
572 | psCommand->psDstSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE); | ||
573 | |||
574 | PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x", | ||
575 | i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr, | ||
576 | psCommand->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr, | ||
577 | psCommand->psDstSync[i].ui32ReadOpsPending, | ||
578 | psCommand->psDstSync[i].ui32WriteOpsPending)); | ||
579 | } | ||
580 | |||
581 | |||
582 | for (i=0; i<ui32SrcSyncCount; i++) | ||
583 | { | ||
584 | psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i]; | ||
585 | psCommand->psSrcSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE); | ||
586 | psCommand->psSrcSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE); | ||
587 | |||
588 | PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x", | ||
589 | i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr, | ||
590 | psCommand->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr, | ||
591 | psCommand->psSrcSync[i].ui32ReadOpsPending, | ||
592 | psCommand->psSrcSync[i].ui32WriteOpsPending)); | ||
593 | } | ||
594 | |||
595 | |||
596 | *ppsCommand = psCommand; | ||
597 | |||
598 | return PVRSRV_OK; | ||
599 | } | ||
600 | |||
601 | |||
602 | IMG_EXPORT | ||
603 | PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue, | ||
604 | PVRSRV_COMMAND *psCommand) | ||
605 | { | ||
606 | |||
607 | |||
608 | |||
609 | if (psCommand->ui32DstSyncCount > 0) | ||
610 | { | ||
611 | psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM) | ||
612 | + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)); | ||
613 | } | ||
614 | |||
615 | if (psCommand->ui32SrcSyncCount > 0) | ||
616 | { | ||
617 | psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM) | ||
618 | + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND) | ||
619 | + (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT))); | ||
620 | } | ||
621 | |||
622 | psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM) | ||
623 | + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND) | ||
624 | + (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)) | ||
625 | + (psCommand->ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT))); | ||
626 | |||
627 | |||
628 | UPDATE_QUEUE_WOFF(psQueue, psCommand->ui32CmdSize); | ||
629 | |||
630 | return PVRSRV_OK; | ||
631 | } | ||
632 | |||
633 | |||
634 | |||
635 | static | ||
636 | PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA *psSysData, | ||
637 | PVRSRV_COMMAND *psCommand, | ||
638 | IMG_BOOL bFlush) | ||
639 | { | ||
640 | PVRSRV_SYNC_OBJECT *psWalkerObj; | ||
641 | PVRSRV_SYNC_OBJECT *psEndObj; | ||
642 | IMG_UINT32 i; | ||
643 | COMMAND_COMPLETE_DATA *psCmdCompleteData; | ||
644 | PVRSRV_ERROR eError = PVRSRV_OK; | ||
645 | IMG_UINT32 ui32WriteOpsComplete; | ||
646 | IMG_UINT32 ui32ReadOpsComplete; | ||
647 | |||
648 | |||
649 | psWalkerObj = psCommand->psDstSync; | ||
650 | psEndObj = psWalkerObj + psCommand->ui32DstSyncCount; | ||
651 | while (psWalkerObj < psEndObj) | ||
652 | { | ||
653 | PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData; | ||
654 | |||
655 | ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete; | ||
656 | ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete; | ||
657 | |||
658 | if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending) | ||
659 | || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending)) | ||
660 | { | ||
661 | if (!bFlush || | ||
662 | !SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) || | ||
663 | !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending)) | ||
664 | { | ||
665 | return PVRSRV_ERROR_FAILED_DEPENDENCIES; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | psWalkerObj++; | ||
670 | } | ||
671 | |||
672 | |||
673 | psWalkerObj = psCommand->psSrcSync; | ||
674 | psEndObj = psWalkerObj + psCommand->ui32SrcSyncCount; | ||
675 | while (psWalkerObj < psEndObj) | ||
676 | { | ||
677 | PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData; | ||
678 | |||
679 | ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete; | ||
680 | ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete; | ||
681 | |||
682 | if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending) | ||
683 | || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending)) | ||
684 | { | ||
685 | if (!bFlush && | ||
686 | SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) && | ||
687 | SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending)) | ||
688 | { | ||
689 | PVR_DPF((PVR_DBG_WARNING, | ||
690 | "PVRSRVProcessCommand: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x", | ||
691 | (IMG_UINTPTR_T)psSyncData, ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending)); | ||
692 | } | ||
693 | |||
694 | if (!bFlush || | ||
695 | !SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) || | ||
696 | !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending)) | ||
697 | { | ||
698 | return PVRSRV_ERROR_FAILED_DEPENDENCIES; | ||
699 | } | ||
700 | } | ||
701 | psWalkerObj++; | ||
702 | } | ||
703 | |||
704 | |||
705 | if (psCommand->ui32DevIndex >= SYS_DEVICE_COUNT) | ||
706 | { | ||
707 | PVR_DPF((PVR_DBG_ERROR, | ||
708 | "PVRSRVProcessCommand: invalid DeviceType 0x%x", | ||
709 | psCommand->ui32DevIndex)); | ||
710 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
711 | } | ||
712 | |||
713 | |||
714 | psCmdCompleteData = psSysData->ppsCmdCompleteData[psCommand->ui32DevIndex][psCommand->CommandType]; | ||
715 | if (psCmdCompleteData->bInUse) | ||
716 | { | ||
717 | |||
718 | return PVRSRV_ERROR_FAILED_DEPENDENCIES; | ||
719 | } | ||
720 | |||
721 | |||
722 | psCmdCompleteData->bInUse = IMG_TRUE; | ||
723 | |||
724 | |||
725 | psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount; | ||
726 | for (i=0; i<psCommand->ui32DstSyncCount; i++) | ||
727 | { | ||
728 | psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i]; | ||
729 | |||
730 | PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x", | ||
731 | i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr, | ||
732 | psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr, | ||
733 | psCmdCompleteData->psDstSync[i].ui32ReadOpsPending, | ||
734 | psCmdCompleteData->psDstSync[i].ui32WriteOpsPending)); | ||
735 | } | ||
736 | |||
737 | |||
738 | |||
739 | psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount; | ||
740 | for (i=0; i<psCommand->ui32SrcSyncCount; i++) | ||
741 | { | ||
742 | psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i]; | ||
743 | |||
744 | PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x", | ||
745 | i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr, | ||
746 | psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr, | ||
747 | psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending, | ||
748 | psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending)); | ||
749 | } | ||
750 | |||
751 | |||
752 | |||
753 | |||
754 | |||
755 | |||
756 | |||
757 | |||
758 | |||
759 | |||
760 | |||
761 | if (psSysData->ppfnCmdProcList[psCommand->ui32DevIndex][psCommand->CommandType]((IMG_HANDLE)psCmdCompleteData, | ||
762 | psCommand->ui32DataSize, | ||
763 | psCommand->pvData) == IMG_FALSE) | ||
764 | { | ||
765 | |||
766 | |||
767 | |||
768 | psCmdCompleteData->bInUse = IMG_FALSE; | ||
769 | eError = PVRSRV_ERROR_CMD_NOT_PROCESSED; | ||
770 | } | ||
771 | |||
772 | return eError; | ||
773 | } | ||
774 | |||
775 | |||
776 | static IMG_VOID PVRSRVProcessQueues_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode) | ||
777 | { | ||
778 | if (psDeviceNode->bReProcessDeviceCommandComplete && | ||
779 | psDeviceNode->pfnDeviceCommandComplete != IMG_NULL) | ||
780 | { | ||
781 | (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode); | ||
782 | } | ||
783 | } | ||
784 | |||
785 | IMG_EXPORT | ||
786 | PVRSRV_ERROR PVRSRVProcessQueues(IMG_UINT32 ui32CallerID, | ||
787 | IMG_BOOL bFlush) | ||
788 | { | ||
789 | PVRSRV_QUEUE_INFO *psQueue; | ||
790 | SYS_DATA *psSysData; | ||
791 | PVRSRV_COMMAND *psCommand; | ||
792 | PVRSRV_ERROR eError; | ||
793 | |||
794 | SysAcquireData(&psSysData); | ||
795 | |||
796 | |||
797 | psSysData->bReProcessQueues = IMG_FALSE; | ||
798 | |||
799 | |||
800 | eError = OSLockResource(&psSysData->sQProcessResource, | ||
801 | ui32CallerID); | ||
802 | if(eError != PVRSRV_OK) | ||
803 | { | ||
804 | |||
805 | psSysData->bReProcessQueues = IMG_TRUE; | ||
806 | |||
807 | |||
808 | if(ui32CallerID == ISR_ID) | ||
809 | { | ||
810 | if (bFlush) | ||
811 | { | ||
812 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVProcessQueues: Couldn't acquire queue processing lock for FLUSH")); | ||
813 | } | ||
814 | else | ||
815 | { | ||
816 | PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVProcessQueues: Couldn't acquire queue processing lock")); | ||
817 | } | ||
818 | } | ||
819 | else | ||
820 | { | ||
821 | PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVProcessQueues: Queue processing lock-acquire failed when called from the Services driver.")); | ||
822 | PVR_DPF((PVR_DBG_MESSAGE," This is due to MISR queue processing being interrupted by the Services driver.")); | ||
823 | } | ||
824 | |||
825 | return PVRSRV_OK; | ||
826 | } | ||
827 | |||
828 | psQueue = psSysData->psQueueList; | ||
829 | |||
830 | if(!psQueue) | ||
831 | { | ||
832 | PVR_DPF((PVR_DBG_MESSAGE,"No Queues installed - cannot process commands")); | ||
833 | } | ||
834 | |||
835 | if (bFlush) | ||
836 | { | ||
837 | PVRSRVSetDCState(DC_STATE_FLUSH_COMMANDS); | ||
838 | } | ||
839 | |||
840 | while (psQueue) | ||
841 | { | ||
842 | while (psQueue->ui32ReadOffset != psQueue->ui32WriteOffset) | ||
843 | { | ||
844 | psCommand = (PVRSRV_COMMAND*)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + psQueue->ui32ReadOffset); | ||
845 | |||
846 | if (PVRSRVProcessCommand(psSysData, psCommand, bFlush) == PVRSRV_OK) | ||
847 | { | ||
848 | |||
849 | UPDATE_QUEUE_ROFF(psQueue, psCommand->ui32CmdSize) | ||
850 | |||
851 | if (bFlush) | ||
852 | { | ||
853 | continue; | ||
854 | } | ||
855 | } | ||
856 | |||
857 | break; | ||
858 | } | ||
859 | psQueue = psQueue->psNextKM; | ||
860 | } | ||
861 | |||
862 | if (bFlush) | ||
863 | { | ||
864 | PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS); | ||
865 | } | ||
866 | |||
867 | |||
868 | List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, | ||
869 | &PVRSRVProcessQueues_ForEachCb); | ||
870 | |||
871 | |||
872 | |||
873 | OSUnlockResource(&psSysData->sQProcessResource, ui32CallerID); | ||
874 | |||
875 | |||
876 | if(psSysData->bReProcessQueues) | ||
877 | { | ||
878 | return PVRSRV_ERROR_PROCESSING_BLOCKED; | ||
879 | } | ||
880 | |||
881 | return PVRSRV_OK; | ||
882 | } | ||
883 | |||
884 | #if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS) | ||
885 | IMG_INTERNAL | ||
886 | IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie, | ||
887 | IMG_BOOL bScheduleMISR) | ||
888 | { | ||
889 | COMMAND_COMPLETE_DATA *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie; | ||
890 | SYS_DATA *psSysData; | ||
891 | |||
892 | SysAcquireData(&psSysData); | ||
893 | |||
894 | |||
895 | psCmdCompleteData->bInUse = IMG_FALSE; | ||
896 | |||
897 | |||
898 | PVRSRVScheduleDeviceCallbacks(); | ||
899 | |||
900 | #if defined(SYS_USING_INTERRUPTS) | ||
901 | if(bScheduleMISR) | ||
902 | { | ||
903 | OSScheduleMISR(psSysData); | ||
904 | } | ||
905 | #else | ||
906 | PVR_UNREFERENCED_PARAMETER(bScheduleMISR); | ||
907 | #endif | ||
908 | } | ||
909 | |||
910 | #endif | ||
911 | |||
912 | |||
913 | IMG_EXPORT | ||
914 | IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie, | ||
915 | IMG_BOOL bScheduleMISR) | ||
916 | { | ||
917 | IMG_UINT32 i; | ||
918 | COMMAND_COMPLETE_DATA *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie; | ||
919 | SYS_DATA *psSysData; | ||
920 | |||
921 | SysAcquireData(&psSysData); | ||
922 | |||
923 | |||
924 | for (i=0; i<psCmdCompleteData->ui32DstSyncCount; i++) | ||
925 | { | ||
926 | psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete++; | ||
927 | |||
928 | PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x", | ||
929 | i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr, | ||
930 | psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr, | ||
931 | psCmdCompleteData->psDstSync[i].ui32ReadOpsPending, | ||
932 | psCmdCompleteData->psDstSync[i].ui32WriteOpsPending)); | ||
933 | } | ||
934 | |||
935 | |||
936 | for (i=0; i<psCmdCompleteData->ui32SrcSyncCount; i++) | ||
937 | { | ||
938 | psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete++; | ||
939 | |||
940 | PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x", | ||
941 | i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr, | ||
942 | psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr, | ||
943 | psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending, | ||
944 | psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending)); | ||
945 | } | ||
946 | |||
947 | |||
948 | psCmdCompleteData->bInUse = IMG_FALSE; | ||
949 | |||
950 | |||
951 | PVRSRVScheduleDeviceCallbacks(); | ||
952 | |||
953 | #if defined(SYS_USING_INTERRUPTS) | ||
954 | if(bScheduleMISR) | ||
955 | { | ||
956 | OSScheduleMISR(psSysData); | ||
957 | } | ||
958 | #else | ||
959 | PVR_UNREFERENCED_PARAMETER(bScheduleMISR); | ||
960 | #endif | ||
961 | } | ||
962 | |||
963 | |||
964 | |||
965 | |||
966 | IMG_EXPORT | ||
967 | PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex, | ||
968 | PFN_CMD_PROC *ppfnCmdProcList, | ||
969 | IMG_UINT32 ui32MaxSyncsPerCmd[][2], | ||
970 | IMG_UINT32 ui32CmdCount) | ||
971 | { | ||
972 | SYS_DATA *psSysData; | ||
973 | PVRSRV_ERROR eError; | ||
974 | IMG_UINT32 i; | ||
975 | IMG_SIZE_T ui32AllocSize; | ||
976 | PFN_CMD_PROC *ppfnCmdProc; | ||
977 | COMMAND_COMPLETE_DATA *psCmdCompleteData; | ||
978 | |||
979 | |||
980 | if(ui32DevIndex >= SYS_DEVICE_COUNT) | ||
981 | { | ||
982 | PVR_DPF((PVR_DBG_ERROR, | ||
983 | "PVRSRVRegisterCmdProcListKM: invalid DeviceType 0x%x", | ||
984 | ui32DevIndex)); | ||
985 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
986 | } | ||
987 | |||
988 | |||
989 | SysAcquireData(&psSysData); | ||
990 | |||
991 | |||
992 | eError = OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, | ||
993 | ui32CmdCount * sizeof(PFN_CMD_PROC), | ||
994 | (IMG_VOID **)&psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL, | ||
995 | "Internal Queue Info structure"); | ||
996 | if (eError != PVRSRV_OK) | ||
997 | { | ||
998 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc queue")); | ||
999 | return eError; | ||
1000 | } | ||
1001 | |||
1002 | |||
1003 | ppfnCmdProc = psSysData->ppfnCmdProcList[ui32DevIndex]; | ||
1004 | |||
1005 | |||
1006 | for (i=0; i<ui32CmdCount; i++) | ||
1007 | { | ||
1008 | ppfnCmdProc[i] = ppfnCmdProcList[i]; | ||
1009 | } | ||
1010 | |||
1011 | |||
1012 | ui32AllocSize = ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA*); | ||
1013 | eError = OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
1014 | ui32AllocSize, | ||
1015 | (IMG_VOID **)&psSysData->ppsCmdCompleteData[ui32DevIndex], IMG_NULL, | ||
1016 | "Array of Pointers for Command Store"); | ||
1017 | if (eError != PVRSRV_OK) | ||
1018 | { | ||
1019 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc CC data")); | ||
1020 | goto ErrorExit; | ||
1021 | } | ||
1022 | |||
1023 | for (i=0; i<ui32CmdCount; i++) | ||
1024 | { | ||
1025 | |||
1026 | |||
1027 | ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA) | ||
1028 | + ((ui32MaxSyncsPerCmd[i][0] | ||
1029 | + ui32MaxSyncsPerCmd[i][1]) | ||
1030 | * sizeof(PVRSRV_SYNC_OBJECT)); | ||
1031 | |||
1032 | eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
1033 | ui32AllocSize, | ||
1034 | (IMG_VOID **)&psSysData->ppsCmdCompleteData[ui32DevIndex][i], | ||
1035 | IMG_NULL, | ||
1036 | "Command Complete Data"); | ||
1037 | if (eError != PVRSRV_OK) | ||
1038 | { | ||
1039 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc cmd %d",i)); | ||
1040 | goto ErrorExit; | ||
1041 | } | ||
1042 | |||
1043 | |||
1044 | OSMemSet(psSysData->ppsCmdCompleteData[ui32DevIndex][i], 0x00, ui32AllocSize); | ||
1045 | |||
1046 | psCmdCompleteData = psSysData->ppsCmdCompleteData[ui32DevIndex][i]; | ||
1047 | |||
1048 | |||
1049 | psCmdCompleteData->psDstSync = (PVRSRV_SYNC_OBJECT*) | ||
1050 | (((IMG_UINTPTR_T)psCmdCompleteData) | ||
1051 | + sizeof(COMMAND_COMPLETE_DATA)); | ||
1052 | psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT*) | ||
1053 | (((IMG_UINTPTR_T)psCmdCompleteData->psDstSync) | ||
1054 | + (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[i][0])); | ||
1055 | |||
1056 | psCmdCompleteData->ui32AllocSize = ui32AllocSize; | ||
1057 | } | ||
1058 | |||
1059 | return PVRSRV_OK; | ||
1060 | |||
1061 | ErrorExit: | ||
1062 | |||
1063 | |||
1064 | |||
1065 | if(psSysData->ppsCmdCompleteData[ui32DevIndex] != IMG_NULL) | ||
1066 | { | ||
1067 | for (i=0; i<ui32CmdCount; i++) | ||
1068 | { | ||
1069 | if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] != IMG_NULL) | ||
1070 | { | ||
1071 | ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA) | ||
1072 | + ((ui32MaxSyncsPerCmd[i][0] | ||
1073 | + ui32MaxSyncsPerCmd[i][1]) | ||
1074 | * sizeof(PVRSRV_SYNC_OBJECT)); | ||
1075 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psSysData->ppsCmdCompleteData[ui32DevIndex][i], IMG_NULL); | ||
1076 | psSysData->ppsCmdCompleteData[ui32DevIndex][i] = IMG_NULL; | ||
1077 | } | ||
1078 | } | ||
1079 | ui32AllocSize = ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA*); | ||
1080 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psSysData->ppsCmdCompleteData[ui32DevIndex], IMG_NULL); | ||
1081 | psSysData->ppsCmdCompleteData[ui32DevIndex] = IMG_NULL; | ||
1082 | } | ||
1083 | |||
1084 | if(psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL) | ||
1085 | { | ||
1086 | ui32AllocSize = ui32CmdCount * sizeof(PFN_CMD_PROC); | ||
1087 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL); | ||
1088 | psSysData->ppfnCmdProcList[ui32DevIndex] = IMG_NULL; | ||
1089 | } | ||
1090 | |||
1091 | return eError; | ||
1092 | } | ||
1093 | |||
1094 | |||
1095 | IMG_EXPORT | ||
1096 | PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex, | ||
1097 | IMG_UINT32 ui32CmdCount) | ||
1098 | { | ||
1099 | SYS_DATA *psSysData; | ||
1100 | IMG_UINT32 i; | ||
1101 | |||
1102 | |||
1103 | if(ui32DevIndex >= SYS_DEVICE_COUNT) | ||
1104 | { | ||
1105 | PVR_DPF((PVR_DBG_ERROR, | ||
1106 | "PVRSRVRemoveCmdProcListKM: invalid DeviceType 0x%x", | ||
1107 | ui32DevIndex)); | ||
1108 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1109 | } | ||
1110 | |||
1111 | |||
1112 | SysAcquireData(&psSysData); | ||
1113 | |||
1114 | if(psSysData->ppsCmdCompleteData[ui32DevIndex] == IMG_NULL) | ||
1115 | { | ||
1116 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveCmdProcListKM: Invalid command array")); | ||
1117 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1118 | } | ||
1119 | else | ||
1120 | { | ||
1121 | for(i=0; i<ui32CmdCount; i++) | ||
1122 | { | ||
1123 | |||
1124 | if(psSysData->ppsCmdCompleteData[ui32DevIndex][i] != IMG_NULL) | ||
1125 | { | ||
1126 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
1127 | psSysData->ppsCmdCompleteData[ui32DevIndex][i]->ui32AllocSize, | ||
1128 | psSysData->ppsCmdCompleteData[ui32DevIndex][i], | ||
1129 | IMG_NULL); | ||
1130 | psSysData->ppsCmdCompleteData[ui32DevIndex][i] = IMG_NULL; | ||
1131 | } | ||
1132 | } | ||
1133 | |||
1134 | |||
1135 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
1136 | ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA*), | ||
1137 | psSysData->ppsCmdCompleteData[ui32DevIndex], | ||
1138 | IMG_NULL); | ||
1139 | psSysData->ppsCmdCompleteData[ui32DevIndex] = IMG_NULL; | ||
1140 | } | ||
1141 | |||
1142 | |||
1143 | if(psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL) | ||
1144 | { | ||
1145 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
1146 | ui32CmdCount * sizeof(PFN_CMD_PROC), | ||
1147 | psSysData->ppfnCmdProcList[ui32DevIndex], | ||
1148 | IMG_NULL); | ||
1149 | psSysData->ppfnCmdProcList[ui32DevIndex] = IMG_NULL; | ||
1150 | } | ||
1151 | |||
1152 | return PVRSRV_OK; | ||
1153 | } | ||
1154 | |||