]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
ENGR00277201-2 gpu: potential memory leak when umapping vg memory
[karo-tx-linux.git] / drivers / mxc / gpu-viv / hal / kernel / gc_hal_kernel_vg.c
1 /****************************************************************************
2 *
3 *    Copyright (C) 2005 - 2013 by Vivante Corp.
4 *
5 *    This program is free software; you can redistribute it and/or modify
6 *    it under the terms of the GNU General Public License as published by
7 *    the Free Software Foundation; either version 2 of the license, or
8 *    (at your option) any later version.
9 *
10 *    This program is distributed in the hope that it will be useful,
11 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 *    GNU General Public License for more details.
14 *
15 *    You should have received a copy of the GNU General Public License
16 *    along with this program; if not write to the Free Software
17 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *****************************************************************************/
20
21
22 #include "gc_hal_kernel_precomp.h"
23
24 #if gcdENABLE_VG
25
26 #define ENABLE_VG_TRY_VIRTUAL_MEMORY 0
27
28 #define _GC_OBJ_ZONE            gcvZONE_VG
29
30 /******************************************************************************\
31 ******************************* gckKERNEL API Code ******************************
32 \******************************************************************************/
33
34 /*******************************************************************************
35 **
36 **  gckKERNEL_Construct
37 **
38 **  Construct a new gckKERNEL object.
39 **
40 **  INPUT:
41 **
42 **      gckOS Os
43 **          Pointer to an gckOS object.
44 **
45 **      IN gctPOINTER Context
46 **          Pointer to a driver defined context.
47 **
48 **  OUTPUT:
49 **
50 **      gckKERNEL * Kernel
51 **          Pointer to a variable that will hold the pointer to the gckKERNEL
52 **          object.
53 */
54 gceSTATUS gckVGKERNEL_Construct(
55     IN gckOS Os,
56     IN gctPOINTER Context,
57     IN gckKERNEL  inKernel,
58     OUT gckVGKERNEL * Kernel
59     )
60 {
61     gceSTATUS status;
62     gckVGKERNEL kernel = gcvNULL;
63
64     gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
65     /* Verify the arguments. */
66     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
67     gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
68
69     do
70     {
71         /* Allocate the gckKERNEL object. */
72         gcmkERR_BREAK(gckOS_Allocate(
73             Os,
74             sizeof(struct _gckVGKERNEL),
75             (gctPOINTER *) &kernel
76             ));
77
78         /* Initialize the gckKERNEL object. */
79         kernel->object.type = gcvOBJ_KERNEL;
80         kernel->os          = Os;
81         kernel->context     = Context;
82         kernel->hardware    = gcvNULL;
83         kernel->interrupt   = gcvNULL;
84         kernel->command     = gcvNULL;
85         kernel->mmu         = gcvNULL;
86         kernel->kernel      = inKernel;
87
88         /* Construct the gckVGHARDWARE object. */
89         gcmkERR_BREAK(gckVGHARDWARE_Construct(
90             Os, &kernel->hardware
91             ));
92
93         /* Set pointer to gckKERNEL object in gckVGHARDWARE object. */
94         kernel->hardware->kernel = kernel;
95
96         /* Construct the gckVGINTERRUPT object. */
97         gcmkERR_BREAK(gckVGINTERRUPT_Construct(
98             kernel, &kernel->interrupt
99             ));
100
101         /* Construct the gckVGCOMMAND object. */
102         gcmkERR_BREAK(gckVGCOMMAND_Construct(
103             kernel, gcmKB2BYTES(8), gcmKB2BYTES(2), &kernel->command
104             ));
105
106         /* Construct the gckVGMMU object. */
107         gcmkERR_BREAK(gckVGMMU_Construct(
108             kernel, gcmKB2BYTES(32), &kernel->mmu
109             ));
110
111         /* Return pointer to the gckKERNEL object. */
112         *Kernel = kernel;
113
114         gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
115         /* Success. */
116         return gcvSTATUS_OK;
117     }
118     while (gcvFALSE);
119
120     /* Roll back. */
121     if (kernel != gcvNULL)
122     {
123         if (kernel->mmu != gcvNULL)
124         {
125             gcmkVERIFY_OK(gckVGMMU_Destroy(kernel->mmu));
126         }
127
128         if (kernel->command != gcvNULL)
129         {
130             gcmkVERIFY_OK(gckVGCOMMAND_Destroy(kernel->command));
131         }
132
133         if (kernel->interrupt != gcvNULL)
134         {
135             gcmkVERIFY_OK(gckVGINTERRUPT_Destroy(kernel->interrupt));
136         }
137
138         if (kernel->hardware != gcvNULL)
139         {
140             gcmkVERIFY_OK(gckVGHARDWARE_Destroy(kernel->hardware));
141         }
142
143         gcmkVERIFY_OK(gckOS_Free(Os, kernel));
144     }
145
146     gcmkFOOTER();
147     /* Return status. */
148     return status;
149 }
150
151 /*******************************************************************************
152 **
153 **  gckKERNEL_Destroy
154 **
155 **  Destroy an gckKERNEL object.
156 **
157 **  INPUT:
158 **
159 **      gckKERNEL Kernel
160 **          Pointer to an gckKERNEL object to destroy.
161 **
162 **  OUTPUT:
163 **
164 **      Nothing.
165 */
166 gceSTATUS gckVGKERNEL_Destroy(
167     IN gckVGKERNEL Kernel
168     )
169 {
170     gceSTATUS status;
171
172     gcmkHEADER_ARG("Kernel=0x%x", Kernel);
173
174     /* Verify the arguments. */
175     gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
176
177     do
178     {
179         /* Destroy the gckVGMMU object. */
180         if (Kernel->mmu != gcvNULL)
181         {
182             gcmkERR_BREAK(gckVGMMU_Destroy(Kernel->mmu));
183             Kernel->mmu = gcvNULL;
184         }
185
186         /* Destroy the gckVGCOMMAND object. */
187         if (Kernel->command != gcvNULL)
188         {
189             gcmkERR_BREAK(gckVGCOMMAND_Destroy(Kernel->command));
190             Kernel->command = gcvNULL;
191         }
192
193         /* Destroy the gckVGINTERRUPT object. */
194         if (Kernel->interrupt != gcvNULL)
195         {
196             gcmkERR_BREAK(gckVGINTERRUPT_Destroy(Kernel->interrupt));
197             Kernel->interrupt = gcvNULL;
198         }
199
200         /* Destroy the gckVGHARDWARE object. */
201         if (Kernel->hardware != gcvNULL)
202         {
203             gcmkERR_BREAK(gckVGHARDWARE_Destroy(Kernel->hardware));
204             Kernel->hardware = gcvNULL;
205         }
206
207         /* Mark the gckKERNEL object as unknown. */
208         Kernel->object.type = gcvOBJ_UNKNOWN;
209
210         /* Free the gckKERNEL object. */
211         gcmkERR_BREAK(gckOS_Free(Kernel->os, Kernel));
212     }
213     while (gcvFALSE);
214
215     gcmkFOOTER();
216
217     /* Return status. */
218     return status;
219 }
220
221 /*******************************************************************************
222 **
223 **  gckKERNEL_AllocateLinearMemory
224 **
225 **  Function walks all required memory pools and allocates the requested
226 **  amount of video memory.
227 **
228 **  INPUT:
229 **
230 **      gckKERNEL Kernel
231 **          Pointer to an gckKERNEL object.
232 **
233 **      gcePOOL * Pool
234 **          Pointer the desired memory pool.
235 **
236 **      gctSIZE_T Bytes
237 **          Number of bytes to allocate.
238 **
239 **      gctSIZE_T Alignment
240 **          Required buffer alignment.
241 **
242 **      gceSURF_TYPE Type
243 **          Surface type.
244 **
245 **  OUTPUT:
246 **
247 **      gcePOOL * Pool
248 **          Pointer to the actual pool where the memory was allocated.
249 **
250 **      gcuVIDMEM_NODE_PTR * Node
251 **          Allocated node.
252 */
253 gceSTATUS
254 gckKERNEL_AllocateLinearMemory(
255     IN gckKERNEL Kernel,
256     IN OUT gcePOOL * Pool,
257     IN gctSIZE_T Bytes,
258     IN gctSIZE_T Alignment,
259     IN gceSURF_TYPE Type,
260     OUT gcuVIDMEM_NODE_PTR * Node
261     )
262 {
263     gcePOOL pool;
264     gceSTATUS status;
265     gckVIDMEM videoMemory;
266
267     /* Get initial pool. */
268     switch (pool = *Pool)
269     {
270     case gcvPOOL_DEFAULT:
271     case gcvPOOL_LOCAL:
272         pool = gcvPOOL_LOCAL_INTERNAL;
273         break;
274
275     case gcvPOOL_UNIFIED:
276         pool = gcvPOOL_SYSTEM;
277         break;
278
279     default:
280         break;
281     }
282
283     do
284     {
285         /* Verify the number of bytes to allocate. */
286         if (Bytes == 0)
287         {
288             status = gcvSTATUS_INVALID_ARGUMENT;
289             break;
290         }
291
292         if (pool == gcvPOOL_VIRTUAL)
293         {
294             /* Create a gcuVIDMEM_NODE for virtual memory. */
295             gcmkERR_BREAK(gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Node));
296
297             /* Success. */
298             break;
299         }
300
301         else
302         {
303             /* Get pointer to gckVIDMEM object for pool. */
304             status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
305
306             if (status == gcvSTATUS_OK)
307             {
308                 /* Allocate memory. */
309                 status = gckVIDMEM_AllocateLinear(videoMemory,
310                                                   Bytes,
311                                                   Alignment,
312                                                   Type,
313                                                   Node);
314
315                 if (status == gcvSTATUS_OK)
316                 {
317                     /* Memory allocated. */
318                     break;
319                 }
320             }
321         }
322
323         if (pool == gcvPOOL_LOCAL_INTERNAL)
324         {
325             /* Advance to external memory. */
326             pool = gcvPOOL_LOCAL_EXTERNAL;
327         }
328         else if (pool == gcvPOOL_LOCAL_EXTERNAL)
329         {
330             /* Advance to contiguous system memory. */
331             pool = gcvPOOL_SYSTEM;
332         }
333         else if (pool == gcvPOOL_SYSTEM)
334         {
335             /* Advance to virtual memory. */
336 #if ENABLE_VG_TRY_VIRTUAL_MEMORY
337             pool = gcvPOOL_VIRTUAL;
338 #else
339             /*VG non-contiguous memory support is not ready yet, disable it temporary*/
340             status = gcvSTATUS_OUT_OF_MEMORY;
341             break;
342 #endif
343         }
344         else
345         {
346             /* Out of pools. */
347             status = gcvSTATUS_OUT_OF_MEMORY;
348             break;
349         }
350     }
351     /* Loop only for multiple selection pools. */
352     while ((*Pool == gcvPOOL_DEFAULT)
353     ||     (*Pool == gcvPOOL_LOCAL)
354     ||     (*Pool == gcvPOOL_UNIFIED)
355     );
356
357     if (gcmIS_SUCCESS(status))
358     {
359         /* Return pool used for allocation. */
360         *Pool = pool;
361     }
362
363     /* Return status. */
364     return status;
365 }
366
367 /*******************************************************************************
368 **
369 **  gckKERNEL_Dispatch
370 **
371 **  Dispatch a command received from the user HAL layer.
372 **
373 **  INPUT:
374 **
375 **      gckKERNEL Kernel
376 **          Pointer to an gckKERNEL object.
377 **
378 **      gcsHAL_INTERFACE * Interface
379 **          Pointer to a gcsHAL_INTERFACE structure that defines the command to
380 **          be dispatched.
381 **
382 **  OUTPUT:
383 **
384 **      gcsHAL_INTERFACE * Interface
385 **          Pointer to a gcsHAL_INTERFACE structure that receives any data to be
386 **          returned.
387 */
388 gceSTATUS gckVGKERNEL_Dispatch(
389     IN gckKERNEL Kernel,
390     IN gctBOOL FromUser,
391     IN OUT gcsHAL_INTERFACE * Interface
392     )
393 {
394     gceSTATUS status;
395     gcsHAL_INTERFACE * kernelInterface = Interface;
396     gcuVIDMEM_NODE_PTR node;
397     gctUINT32 processID;
398     gckKERNEL kernel = Kernel;
399     gctPOINTER info = gcvNULL;
400     gctPHYS_ADDR physical = gcvNULL;
401     gctPOINTER logical = gcvNULL;
402     gctSIZE_T bytes = 0;
403
404     gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface);
405
406     /* Verify the arguments. */
407     gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
408     gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
409
410     gcmkONERROR(gckOS_GetProcessID(&processID));
411
412     /* Dispatch on command. */
413     switch (Interface->command)
414     {
415     case gcvHAL_QUERY_VIDEO_MEMORY:
416         /* Query video memory size. */
417         gcmkERR_BREAK(gckKERNEL_QueryVideoMemory(
418             Kernel, kernelInterface
419             ));
420         break;
421
422     case gcvHAL_QUERY_CHIP_IDENTITY:
423         /* Query chip identity. */
424         gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity(
425             Kernel->vg->hardware,
426             &kernelInterface->u.QueryChipIdentity.chipModel,
427             &kernelInterface->u.QueryChipIdentity.chipRevision,
428             &kernelInterface->u.QueryChipIdentity.chipFeatures,
429             &kernelInterface->u.QueryChipIdentity.chipMinorFeatures,
430             &kernelInterface->u.QueryChipIdentity.chipMinorFeatures2
431             ));
432         break;
433
434     case gcvHAL_QUERY_COMMAND_BUFFER:
435         /* Query command buffer information. */
436         gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer(
437             Kernel,
438             &kernelInterface->u.QueryCommandBuffer.information
439             ));
440         break;
441     case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
442         bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
443         /* Allocate non-paged memory. */
444         gcmkERR_BREAK(gckOS_AllocateContiguous(
445             Kernel->os,
446             gcvTRUE,
447             &bytes,
448             &physical,
449             &logical
450             ));
451
452         kernelInterface->u.AllocateNonPagedMemory.bytes    = bytes;
453         kernelInterface->u.AllocateNonPagedMemory.logical  = gcmPTR_TO_UINT64(logical);
454         kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
455         break;
456
457     case gcvHAL_FREE_NON_PAGED_MEMORY:
458         physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
459
460         /* Unmap user logical out of physical memory first. */
461         gcmkERR_BREAK(gckOS_UnmapUserLogical(
462             Kernel->os,
463             physical,
464             (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
465             gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
466             ));
467
468         /* Free non-paged memory. */
469         gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
470             Kernel->os,
471             (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
472             physical,
473             gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
474             ));
475
476         gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
477         break;
478
479     case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
480         bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
481         /* Allocate contiguous memory. */
482         gcmkERR_BREAK(gckOS_AllocateContiguous(
483             Kernel->os,
484             gcvTRUE,
485             &bytes,
486             &physical,
487             &logical
488             ));
489
490         kernelInterface->u.AllocateNonPagedMemory.bytes    = bytes;
491         kernelInterface->u.AllocateNonPagedMemory.logical  = gcmPTR_TO_UINT64(logical);
492         kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
493         break;
494
495     case gcvHAL_FREE_CONTIGUOUS_MEMORY:
496         physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
497         /* Unmap user logical out of physical memory first. */
498         gcmkERR_BREAK(gckOS_UnmapUserLogical(
499             Kernel->os,
500             physical,
501             (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
502             gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
503             ));
504
505         /* Free contiguous memory. */
506         gcmkERR_BREAK(gckOS_FreeContiguous(
507             Kernel->os,
508             physical,
509             gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical),
510             (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes
511             ));
512
513         gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
514         break;
515
516     case gcvHAL_ALLOCATE_VIDEO_MEMORY:
517         {
518             gctSIZE_T bytes;
519             gctUINT32 bitsPerPixel;
520             gctUINT32 bits;
521
522             /* Align width and height to tiles. */
523             gcmkERR_BREAK(gckVGHARDWARE_AlignToTile(
524                 Kernel->vg->hardware,
525                 kernelInterface->u.AllocateVideoMemory.type,
526                 &kernelInterface->u.AllocateVideoMemory.width,
527                 &kernelInterface->u.AllocateVideoMemory.height
528                 ));
529
530             /* Convert format into bytes per pixel and bytes per tile. */
531             gcmkERR_BREAK(gckVGHARDWARE_ConvertFormat(
532                 Kernel->vg->hardware,
533                 kernelInterface->u.AllocateVideoMemory.format,
534                 &bitsPerPixel,
535                 gcvNULL
536                 ));
537
538             /* Compute number of bits for the allocation. */
539             bits
540                 = kernelInterface->u.AllocateVideoMemory.width
541                 * kernelInterface->u.AllocateVideoMemory.height
542                 * kernelInterface->u.AllocateVideoMemory.depth
543                 * bitsPerPixel;
544
545             /* Compute number of bytes for the allocation. */
546             bytes = gcmALIGN(bits, 8) / 8;
547
548             /* Allocate memory. */
549             gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
550                 Kernel,
551                 &kernelInterface->u.AllocateVideoMemory.pool,
552                 bytes,
553                 64,
554                 kernelInterface->u.AllocateVideoMemory.type,
555                 &node
556                 ));
557
558             kernelInterface->u.AllocateVideoMemory.node = gcmPTR_TO_UINT64(node);
559         }
560         break;
561
562     case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
563         /* Allocate memory. */
564         gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
565             Kernel,
566             &kernelInterface->u.AllocateLinearVideoMemory.pool,
567             kernelInterface->u.AllocateLinearVideoMemory.bytes,
568             kernelInterface->u.AllocateLinearVideoMemory.alignment,
569             kernelInterface->u.AllocateLinearVideoMemory.type,
570             &node
571             ));
572
573         gcmkERR_BREAK(gckKERNEL_AddProcessDB(Kernel,
574            processID, gcvDB_VIDEO_MEMORY,
575            node,
576            gcvNULL,
577            kernelInterface->u.AllocateLinearVideoMemory.bytes
578            ));
579
580         kernelInterface->u.AllocateLinearVideoMemory.node = gcmPTR_TO_UINT64(node);
581         break;
582
583     case gcvHAL_FREE_VIDEO_MEMORY:
584         node = gcmUINT64_TO_PTR(Interface->u.FreeVideoMemory.node);
585 #ifdef __QNXNTO__
586         /* Unmap the video memory */
587
588         if ((node->VidMem.memory->object.type == gcvOBJ_VIDMEM) &&
589             (node->VidMem.logical != gcvNULL))
590         {
591             gckKERNEL_UnmapVideoMemory(Kernel,
592                                        node->VidMem.logical,
593                                        processID,
594                                        node->VidMem.bytes);
595             node->VidMem.logical = gcvNULL;
596         }
597 #endif /* __QNXNTO__ */
598
599         /* Free video memory. */
600         gcmkERR_BREAK(gckVIDMEM_Free(
601             node
602             ));
603
604         gcmkERR_BREAK(gckKERNEL_RemoveProcessDB(
605             Kernel,
606             processID, gcvDB_VIDEO_MEMORY,
607             node
608             ));
609
610         break;
611
612     case gcvHAL_MAP_MEMORY:
613         /* Map memory. */
614         gcmkERR_BREAK(gckKERNEL_MapMemory(
615             Kernel,
616             gcmINT2PTR(kernelInterface->u.MapMemory.physical),
617             (gctSIZE_T) kernelInterface->u.MapMemory.bytes,
618             &logical
619             ));
620         kernelInterface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
621         break;
622
623     case gcvHAL_UNMAP_MEMORY:
624         /* Unmap memory. */
625         gcmkERR_BREAK(gckKERNEL_UnmapMemory(
626             Kernel,
627             gcmINT2PTR(kernelInterface->u.MapMemory.physical),
628             (gctSIZE_T) kernelInterface->u.MapMemory.bytes,
629             gcmUINT64_TO_PTR(kernelInterface->u.MapMemory.logical)
630             ));
631         break;
632
633     case gcvHAL_MAP_USER_MEMORY:
634         /* Map user memory to DMA. */
635         gcmkERR_BREAK(gckOS_MapUserMemory(
636             Kernel->os,
637             gcvCORE_VG,
638             gcmUINT64_TO_PTR(kernelInterface->u.MapUserMemory.memory),
639             kernelInterface->u.MapUserMemory.physical,
640             (gctSIZE_T) kernelInterface->u.MapUserMemory.size,
641             &info,
642             &kernelInterface->u.MapUserMemory.address
643             ));
644
645         kernelInterface->u.MapUserMemory.info = gcmPTR_TO_NAME(info);
646         break;
647
648     case gcvHAL_UNMAP_USER_MEMORY:
649         /* Unmap user memory. */
650         gcmkERR_BREAK(gckOS_UnmapUserMemory(
651             Kernel->os,
652             gcvCORE_VG,
653             gcmUINT64_TO_PTR(kernelInterface->u.UnmapUserMemory.memory),
654             (gctSIZE_T) kernelInterface->u.UnmapUserMemory.size,
655             gcmNAME_TO_PTR(kernelInterface->u.UnmapUserMemory.info),
656             kernelInterface->u.UnmapUserMemory.address
657             ));
658         gcmRELEASE_NAME(kernelInterface->u.UnmapUserMemory.info);
659         break;
660     case gcvHAL_LOCK_VIDEO_MEMORY:
661         node = gcmUINT64_TO_PTR(Interface->u.LockVideoMemory.node);
662
663         /* Lock video memory. */
664         gcmkERR_BREAK(
665             gckVIDMEM_Lock(Kernel,
666                            node,
667                                                    gcvFALSE,
668                            &Interface->u.LockVideoMemory.address));
669
670         if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
671         {
672             /* Map video memory address into user space. */
673 #ifdef __QNXNTO__
674         if (node->VidMem.logical == gcvNULL)
675         {
676             gcmkONERROR(
677                 gckKERNEL_MapVideoMemory(Kernel,
678                                          FromUser,
679                                          Interface->u.LockVideoMemory.address,
680                                          processID,
681                                          node->VidMem.bytes,
682                                          &node->VidMem.logical));
683         }
684
685         Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->VidMem.logical);
686 #else
687             gcmkERR_BREAK(
688                 gckKERNEL_MapVideoMemoryEx(Kernel,
689                                          gcvCORE_VG,
690                                          FromUser,
691                                          Interface->u.LockVideoMemory.address,
692                                          &logical));
693             Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(logical);
694 #endif
695         }
696         else
697         {
698             Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->Virtual.logical);
699
700             /* Success. */
701             status = gcvSTATUS_OK;
702         }
703
704 #if gcdSECURE_USER
705         /* Return logical address as physical address. */
706         Interface->u.LockVideoMemory.address =
707             (gctUINT32)(Interface->u.LockVideoMemory.memory);
708 #endif
709         gcmkERR_BREAK(
710             gckKERNEL_AddProcessDB(Kernel,
711                                    processID, gcvDB_VIDEO_MEMORY_LOCKED,
712                                    node,
713                                    gcvNULL,
714                                    0));
715         break;
716
717     case gcvHAL_UNLOCK_VIDEO_MEMORY:
718         /* Unlock video memory. */
719         node = gcmUINT64_TO_PTR(Interface->u.UnlockVideoMemory.node);
720
721 #if gcdSECURE_USER
722         /* Save node information before it disappears. */
723         if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
724         {
725             logical = gcvNULL;
726             bytes   = 0;
727         }
728         else
729         {
730             logical = node->Virtual.logical;
731             bytes   = node->Virtual.bytes;
732         }
733 #endif
734
735         /* Unlock video memory. */
736         gcmkERR_BREAK(
737             gckVIDMEM_Unlock(Kernel,
738                              node,
739                              Interface->u.UnlockVideoMemory.type,
740                              &Interface->u.UnlockVideoMemory.asynchroneous));
741
742 #if gcdSECURE_USER
743         /* Flush the translation cache for virtual surfaces. */
744         if (logical != gcvNULL)
745         {
746             gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
747                                                           cache,
748                                                           logical,
749                                                           bytes));
750         }
751 #endif
752
753         if (Interface->u.UnlockVideoMemory.asynchroneous == gcvFALSE)
754         {
755             /* There isn't a event to unlock this node, remove record now */
756             gcmkERR_BREAK(
757                     gckKERNEL_RemoveProcessDB(Kernel,
758                         processID, gcvDB_VIDEO_MEMORY_LOCKED,
759                         node));
760         }
761
762         break;
763     case gcvHAL_USER_SIGNAL:
764 #if !USE_NEW_LINUX_SIGNAL
765         /* Dispatch depends on the user signal subcommands. */
766         switch(Interface->u.UserSignal.command)
767         {
768         case gcvUSER_SIGNAL_CREATE:
769             /* Create a signal used in the user space. */
770             gcmkERR_BREAK(
771                 gckOS_CreateUserSignal(Kernel->os,
772                                        Interface->u.UserSignal.manualReset,
773                                        &Interface->u.UserSignal.id));
774
775             gcmkVERIFY_OK(
776                 gckKERNEL_AddProcessDB(Kernel,
777                                        processID, gcvDB_SIGNAL,
778                                        gcmINT2PTR(Interface->u.UserSignal.id),
779                                        gcvNULL,
780                                        0));
781             break;
782
783         case gcvUSER_SIGNAL_DESTROY:
784             /* Destroy the signal. */
785             gcmkERR_BREAK(
786                 gckOS_DestroyUserSignal(Kernel->os,
787                                         Interface->u.UserSignal.id));
788
789             gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
790                 Kernel,
791                 processID, gcvDB_SIGNAL,
792                 gcmINT2PTR(Interface->u.UserSignal.id)));
793             break;
794
795         case gcvUSER_SIGNAL_SIGNAL:
796             /* Signal the signal. */
797             gcmkERR_BREAK(
798                 gckOS_SignalUserSignal(Kernel->os,
799                                        Interface->u.UserSignal.id,
800                                        Interface->u.UserSignal.state));
801             break;
802
803         case gcvUSER_SIGNAL_WAIT:
804             /* Wait on the signal. */
805             status = gckOS_WaitUserSignal(Kernel->os,
806                                           Interface->u.UserSignal.id,
807                                           Interface->u.UserSignal.wait);
808             break;
809
810         default:
811             /* Invalid user signal command. */
812             gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
813         }
814 #endif
815         break;
816
817     case gcvHAL_COMMIT:
818         /* Commit a command and context buffer. */
819         gcmkERR_BREAK(gckVGCOMMAND_Commit(
820             Kernel->vg->command,
821             gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.context),
822             gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.queue),
823             kernelInterface->u.VGCommit.entryCount,
824             gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.taskTable)
825             ));
826         break;
827     case gcvHAL_VERSION:
828         kernelInterface->u.Version.major = gcvVERSION_MAJOR;
829         kernelInterface->u.Version.minor = gcvVERSION_MINOR;
830         kernelInterface->u.Version.patch = gcvVERSION_PATCH;
831         kernelInterface->u.Version.build = gcvVERSION_BUILD;
832         status = gcvSTATUS_OK;
833         break;
834
835     case gcvHAL_GET_BASE_ADDRESS:
836         /* Get base address. */
837         gcmkERR_BREAK(
838             gckOS_GetBaseAddress(Kernel->os,
839                                  &kernelInterface->u.GetBaseAddress.baseAddress));
840         break;
841     default:
842         /* Invalid command. */
843         status = gcvSTATUS_INVALID_ARGUMENT;
844     }
845
846 OnError:
847     /* Save status. */
848     kernelInterface->status = status;
849
850     gcmkFOOTER();
851
852     /* Return the status. */
853     return status;
854 }
855
856 /*******************************************************************************
857 **
858 **  gckKERNEL_QueryCommandBuffer
859 **
860 **  Query command buffer attributes.
861 **
862 **  INPUT:
863 **
864 **      gckKERNEL Kernel
865 **          Pointer to an gckVGHARDWARE object.
866 **
867 **  OUTPUT:
868 **
869 **      gcsCOMMAND_BUFFER_INFO_PTR Information
870 **          Pointer to the information structure to receive buffer attributes.
871 */
872 gceSTATUS
873 gckKERNEL_QueryCommandBuffer(
874     IN gckKERNEL Kernel,
875     OUT gcsCOMMAND_BUFFER_INFO_PTR Information
876     )
877 {
878     gceSTATUS status;
879
880     gcmkHEADER_ARG("Kernel=0x%x *Pool=0x%x",
881                    Kernel, Information);
882     /* Verify the arguments. */
883     gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
884
885     /* Get the information. */
886     status = gckVGCOMMAND_QueryCommandBuffer(Kernel->vg->command, Information);
887
888     gcmkFOOTER();
889     /* Return status. */
890     return status;
891 }
892
893 #endif /* gcdENABLE_VG */