]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
gpu: vivante: Update driver from Freescale 3.10.53-1.1-ga BSP
[karo-tx-linux.git] / drivers / mxc / gpu-viv / hal / kernel / gc_hal_kernel_vg.c
1 /****************************************************************************
2 *
3 *    Copyright (C) 2005 - 2014 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 _GC_OBJ_ZONE            gcvZONE_VG
27
28 /******************************************************************************\
29 ******************************* gckKERNEL API Code ******************************
30 \******************************************************************************/
31
32 /*******************************************************************************
33 **
34 **  gckKERNEL_Construct
35 **
36 **  Construct a new gckKERNEL object.
37 **
38 **  INPUT:
39 **
40 **      gckOS Os
41 **          Pointer to an gckOS object.
42 **
43 **      IN gctPOINTER Context
44 **          Pointer to a driver defined context.
45 **
46 **  OUTPUT:
47 **
48 **      gckKERNEL * Kernel
49 **          Pointer to a variable that will hold the pointer to the gckKERNEL
50 **          object.
51 */
52 gceSTATUS gckVGKERNEL_Construct(
53     IN gckOS Os,
54     IN gctPOINTER Context,
55     IN gckKERNEL  inKernel,
56     OUT gckVGKERNEL * Kernel
57     )
58 {
59     gceSTATUS status;
60     gckVGKERNEL kernel = gcvNULL;
61
62     gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
63     /* Verify the arguments. */
64     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
65     gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
66
67     do
68     {
69         /* Allocate the gckKERNEL object. */
70         gcmkERR_BREAK(gckOS_Allocate(
71             Os,
72             sizeof(struct _gckVGKERNEL),
73             (gctPOINTER *) &kernel
74             ));
75
76         /* Initialize the gckKERNEL object. */
77         kernel->object.type = gcvOBJ_KERNEL;
78         kernel->os          = Os;
79         kernel->context     = Context;
80         kernel->hardware    = gcvNULL;
81         kernel->interrupt   = gcvNULL;
82         kernel->command     = gcvNULL;
83         kernel->mmu         = gcvNULL;
84         kernel->kernel      = inKernel;
85
86         /* Construct the gckVGHARDWARE object. */
87         gcmkERR_BREAK(gckVGHARDWARE_Construct(
88             Os, &kernel->hardware
89             ));
90
91         /* Set pointer to gckKERNEL object in gckVGHARDWARE object. */
92         kernel->hardware->kernel = kernel;
93
94         /* Construct the gckVGINTERRUPT object. */
95         gcmkERR_BREAK(gckVGINTERRUPT_Construct(
96             kernel, &kernel->interrupt
97             ));
98
99         /* Construct the gckVGCOMMAND object. */
100         gcmkERR_BREAK(gckVGCOMMAND_Construct(
101             kernel, gcmKB2BYTES(8), gcmKB2BYTES(2), &kernel->command
102             ));
103
104         /* Construct the gckVGMMU object. */
105         gcmkERR_BREAK(gckVGMMU_Construct(
106             kernel, gcmKB2BYTES(32), &kernel->mmu
107             ));
108
109         /* Return pointer to the gckKERNEL object. */
110         *Kernel = kernel;
111
112         gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
113         /* Success. */
114         return gcvSTATUS_OK;
115     }
116     while (gcvFALSE);
117
118     /* Roll back. */
119     if (kernel != gcvNULL)
120     {
121         if (kernel->mmu != gcvNULL)
122         {
123             gcmkVERIFY_OK(gckVGMMU_Destroy(kernel->mmu));
124         }
125
126         if (kernel->command != gcvNULL)
127         {
128             gcmkVERIFY_OK(gckVGCOMMAND_Destroy(kernel->command));
129         }
130
131         if (kernel->interrupt != gcvNULL)
132         {
133             gcmkVERIFY_OK(gckVGINTERRUPT_Destroy(kernel->interrupt));
134         }
135
136         if (kernel->hardware != gcvNULL)
137         {
138             gcmkVERIFY_OK(gckVGHARDWARE_Destroy(kernel->hardware));
139         }
140
141         gcmkVERIFY_OK(gckOS_Free(Os, kernel));
142     }
143
144     gcmkFOOTER();
145     /* Return status. */
146     return status;
147 }
148
149 /*******************************************************************************
150 **
151 **  gckKERNEL_Destroy
152 **
153 **  Destroy an gckKERNEL object.
154 **
155 **  INPUT:
156 **
157 **      gckKERNEL Kernel
158 **          Pointer to an gckKERNEL object to destroy.
159 **
160 **  OUTPUT:
161 **
162 **      Nothing.
163 */
164 gceSTATUS gckVGKERNEL_Destroy(
165     IN gckVGKERNEL Kernel
166     )
167 {
168     gceSTATUS status;
169
170     gcmkHEADER_ARG("Kernel=0x%x", Kernel);
171
172     /* Verify the arguments. */
173     gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
174
175     do
176     {
177         /* Destroy the gckVGMMU object. */
178         if (Kernel->mmu != gcvNULL)
179         {
180             gcmkERR_BREAK(gckVGMMU_Destroy(Kernel->mmu));
181             Kernel->mmu = gcvNULL;
182         }
183
184         /* Destroy the gckVGCOMMAND object. */
185         if (Kernel->command != gcvNULL)
186         {
187             gcmkERR_BREAK(gckVGCOMMAND_Destroy(Kernel->command));
188             Kernel->command = gcvNULL;
189         }
190
191         /* Destroy the gckVGINTERRUPT object. */
192         if (Kernel->interrupt != gcvNULL)
193         {
194             gcmkERR_BREAK(gckVGINTERRUPT_Destroy(Kernel->interrupt));
195             Kernel->interrupt = gcvNULL;
196         }
197
198         /* Destroy the gckVGHARDWARE object. */
199         if (Kernel->hardware != gcvNULL)
200         {
201             gcmkERR_BREAK(gckVGHARDWARE_Destroy(Kernel->hardware));
202             Kernel->hardware = gcvNULL;
203         }
204
205         /* Mark the gckKERNEL object as unknown. */
206         Kernel->object.type = gcvOBJ_UNKNOWN;
207
208         /* Free the gckKERNEL object. */
209         gcmkERR_BREAK(gckOS_Free(Kernel->os, Kernel));
210     }
211     while (gcvFALSE);
212
213     gcmkFOOTER();
214
215     /* Return status. */
216     return status;
217 }
218
219 /*******************************************************************************
220 **
221 **  gckKERNEL_AllocateLinearMemory
222 **
223 **  Function walks all required memory pools and allocates the requested
224 **  amount of video memory.
225 **
226 **  INPUT:
227 **
228 **      gckKERNEL Kernel
229 **          Pointer to an gckKERNEL object.
230 **
231 **      gcePOOL * Pool
232 **          Pointer the desired memory pool.
233 **
234 **      gctSIZE_T Bytes
235 **          Number of bytes to allocate.
236 **
237 **      gctSIZE_T Alignment
238 **          Required buffer alignment.
239 **
240 **      gceSURF_TYPE Type
241 **          Surface type.
242 **
243 **  OUTPUT:
244 **
245 **      gcePOOL * Pool
246 **          Pointer to the actual pool where the memory was allocated.
247 **
248 **      gcuVIDMEM_NODE_PTR * Node
249 **          Allocated node.
250 */
251 gceSTATUS
252 gckVGKERNEL_AllocateLinearMemory(
253     IN gckKERNEL Kernel,
254     IN OUT gcePOOL * Pool,
255     IN gctSIZE_T Bytes,
256     IN gctUINT32 Alignment,
257     IN gceSURF_TYPE Type,
258     OUT gcuVIDMEM_NODE_PTR * Node
259     )
260 {
261     gcePOOL pool;
262     gceSTATUS status;
263     gckVIDMEM videoMemory;
264
265     /* Get initial pool. */
266     switch (pool = *Pool)
267     {
268     case gcvPOOL_DEFAULT:
269     case gcvPOOL_LOCAL:
270         pool = gcvPOOL_LOCAL_INTERNAL;
271         break;
272
273     case gcvPOOL_UNIFIED:
274         pool = gcvPOOL_SYSTEM;
275         break;
276
277     default:
278         break;
279     }
280
281     do
282     {
283         /* Verify the number of bytes to allocate. */
284         if (Bytes == 0)
285         {
286             status = gcvSTATUS_INVALID_ARGUMENT;
287             break;
288         }
289
290         if (pool == gcvPOOL_VIRTUAL)
291         {
292             /* Create a gcuVIDMEM_NODE for virtual memory. */
293             gcmkERR_BREAK(gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Node));
294
295             /* Success. */
296             break;
297         }
298
299         else
300         {
301             /* Get pointer to gckVIDMEM object for pool. */
302             status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
303
304             if (status == gcvSTATUS_OK)
305             {
306                 /* Allocate memory. */
307                 status = gckVIDMEM_AllocateLinear(Kernel,
308                                                   videoMemory,
309                                                   Bytes,
310                                                   Alignment,
311                                                   Type,
312                                                   (*Pool == gcvPOOL_SYSTEM),
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             pool = gcvPOOL_VIRTUAL;
337         }
338         else
339         {
340             /* Out of pools. */
341             break;
342         }
343     }
344     /* Loop only for multiple selection pools. */
345     while ((*Pool == gcvPOOL_DEFAULT)
346     ||     (*Pool == gcvPOOL_LOCAL)
347     ||     (*Pool == gcvPOOL_UNIFIED)
348     );
349
350     if (gcmIS_SUCCESS(status))
351     {
352         /* Return pool used for allocation. */
353         *Pool = pool;
354     }
355
356     /* Return status. */
357     return status;
358 }
359
360 /*******************************************************************************
361 **
362 **  gckKERNEL_Dispatch
363 **
364 **  Dispatch a command received from the user HAL layer.
365 **
366 **  INPUT:
367 **
368 **      gckKERNEL Kernel
369 **          Pointer to an gckKERNEL object.
370 **
371 **      gcsHAL_INTERFACE * Interface
372 **          Pointer to a gcsHAL_INTERFACE structure that defines the command to
373 **          be dispatched.
374 **
375 **  OUTPUT:
376 **
377 **      gcsHAL_INTERFACE * Interface
378 **          Pointer to a gcsHAL_INTERFACE structure that receives any data to be
379 **          returned.
380 */
381 gceSTATUS gckVGKERNEL_Dispatch(
382     IN gckKERNEL Kernel,
383     IN gctBOOL FromUser,
384     IN OUT gcsHAL_INTERFACE * Interface
385     )
386 {
387     gceSTATUS status;
388     gcsHAL_INTERFACE * kernelInterface = Interface;
389     gctUINT32 processID;
390     gckKERNEL kernel = Kernel;
391     gctPOINTER info = gcvNULL;
392     gctPHYS_ADDR physical = gcvNULL;
393     gctPOINTER logical = gcvNULL;
394     gctSIZE_T bytes = 0;
395
396     gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface);
397
398     /* Verify the arguments. */
399     gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
400     gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
401
402     gcmkONERROR(gckOS_GetProcessID(&processID));
403
404     /* Dispatch on command. */
405     switch (Interface->command)
406     {
407     case gcvHAL_QUERY_VIDEO_MEMORY:
408         /* Query video memory size. */
409         gcmkERR_BREAK(gckKERNEL_QueryVideoMemory(
410             Kernel, kernelInterface
411             ));
412         break;
413
414     case gcvHAL_QUERY_CHIP_IDENTITY:
415         /* Query chip identity. */
416         gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity(
417             Kernel->vg->hardware,
418             &kernelInterface->u.QueryChipIdentity.chipModel,
419             &kernelInterface->u.QueryChipIdentity.chipRevision,
420             &kernelInterface->u.QueryChipIdentity.chipFeatures,
421             &kernelInterface->u.QueryChipIdentity.chipMinorFeatures,
422             &kernelInterface->u.QueryChipIdentity.chipMinorFeatures2
423             ));
424         break;
425
426     case gcvHAL_QUERY_COMMAND_BUFFER:
427         /* Query command buffer information. */
428         gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer(
429             Kernel,
430             &kernelInterface->u.QueryCommandBuffer.information
431             ));
432         break;
433     case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
434         bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
435         /* Allocate non-paged memory. */
436         gcmkERR_BREAK(gckOS_AllocateNonPagedMemory(
437             Kernel->os,
438             gcvTRUE,
439             &bytes,
440             &physical,
441             &logical
442             ));
443
444         kernelInterface->u.AllocateNonPagedMemory.bytes    = bytes;
445         kernelInterface->u.AllocateNonPagedMemory.logical  = gcmPTR_TO_UINT64(logical);
446         kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
447         break;
448
449     case gcvHAL_FREE_NON_PAGED_MEMORY:
450         physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
451
452         /* Unmap user logical out of physical memory first. */
453         gcmkERR_BREAK(gckOS_UnmapUserLogical(
454             Kernel->os,
455             physical,
456             (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
457             gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
458             ));
459
460         /* Free non-paged memory. */
461         gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
462             Kernel->os,
463             (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
464             physical,
465             gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
466             ));
467
468         gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
469         break;
470
471     case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
472         bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
473         /* Allocate contiguous memory. */
474         gcmkERR_BREAK(gckOS_AllocateContiguous(
475             Kernel->os,
476             gcvTRUE,
477             &bytes,
478             &physical,
479             &logical
480             ));
481
482         kernelInterface->u.AllocateNonPagedMemory.bytes    = bytes;
483         kernelInterface->u.AllocateNonPagedMemory.logical  = gcmPTR_TO_UINT64(logical);
484         kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
485         break;
486
487     case gcvHAL_FREE_CONTIGUOUS_MEMORY:
488         physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
489         /* Unmap user logical out of physical memory first. */
490         gcmkERR_BREAK(gckOS_UnmapUserLogical(
491             Kernel->os,
492             physical,
493             (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
494             gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
495             ));
496
497         /* Free contiguous memory. */
498         gcmkERR_BREAK(gckOS_FreeContiguous(
499             Kernel->os,
500             physical,
501             gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical),
502             (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes
503             ));
504
505         gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
506         break;
507
508     case gcvHAL_ALLOCATE_VIDEO_MEMORY:
509         gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED);
510         break;
511
512     case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
513         /* Allocate memory. */
514         gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
515             Kernel, processID,
516             &kernelInterface->u.AllocateLinearVideoMemory.pool,
517             kernelInterface->u.AllocateLinearVideoMemory.bytes,
518             kernelInterface->u.AllocateLinearVideoMemory.alignment,
519             kernelInterface->u.AllocateLinearVideoMemory.type,
520             kernelInterface->u.AllocateLinearVideoMemory.flag,
521             &kernelInterface->u.AllocateLinearVideoMemory.node
522             ));
523
524         break;
525
526     case gcvHAL_RELEASE_VIDEO_MEMORY:
527         /* Free video memory. */
528         gcmkERR_BREAK(gckKERNEL_ReleaseVideoMemory(
529             Kernel, processID,
530             (gctUINT32)kernelInterface->u.ReleaseVideoMemory.node
531             ));
532
533         break;
534
535     case gcvHAL_MAP_MEMORY:
536         /* Map memory. */
537         gcmkERR_BREAK(gckKERNEL_MapMemory(
538             Kernel,
539             gcmINT2PTR(kernelInterface->u.MapMemory.physical),
540             (gctSIZE_T) kernelInterface->u.MapMemory.bytes,
541             &logical
542             ));
543         kernelInterface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
544         break;
545
546     case gcvHAL_UNMAP_MEMORY:
547         /* Unmap memory. */
548         gcmkERR_BREAK(gckKERNEL_UnmapMemory(
549             Kernel,
550             gcmINT2PTR(kernelInterface->u.MapMemory.physical),
551             (gctSIZE_T) kernelInterface->u.MapMemory.bytes,
552             gcmUINT64_TO_PTR(kernelInterface->u.MapMemory.logical)
553             ));
554         break;
555
556     case gcvHAL_MAP_USER_MEMORY:
557         /* Map user memory to DMA. */
558         gcmkERR_BREAK(gckOS_MapUserMemory(
559             Kernel->os,
560             gcvCORE_VG,
561             gcmUINT64_TO_PTR(kernelInterface->u.MapUserMemory.memory),
562             kernelInterface->u.MapUserMemory.physical,
563             (gctSIZE_T) kernelInterface->u.MapUserMemory.size,
564             &info,
565             &kernelInterface->u.MapUserMemory.address
566             ));
567
568         kernelInterface->u.MapUserMemory.info = gcmPTR_TO_NAME(info);
569
570         /* Clear temp storage. */
571         info = gcvNULL;
572         break;
573
574     case gcvHAL_UNMAP_USER_MEMORY:
575         /* Unmap user memory. */
576         gcmkERR_BREAK(gckOS_UnmapUserMemory(
577             Kernel->os,
578             gcvCORE_VG,
579             gcmUINT64_TO_PTR(kernelInterface->u.UnmapUserMemory.memory),
580             (gctSIZE_T) kernelInterface->u.UnmapUserMemory.size,
581             gcmNAME_TO_PTR(kernelInterface->u.UnmapUserMemory.info),
582             kernelInterface->u.UnmapUserMemory.address
583             ));
584
585         gcmRELEASE_NAME(kernelInterface->u.UnmapUserMemory.info);
586         break;
587
588     case gcvHAL_LOCK_VIDEO_MEMORY:
589         gcmkONERROR(gckKERNEL_LockVideoMemory(Kernel, gcvCORE_VG, processID, FromUser, Interface));
590         break;
591
592     case gcvHAL_UNLOCK_VIDEO_MEMORY:
593         gcmkONERROR(gckKERNEL_UnlockVideoMemory(Kernel, processID, Interface));
594         break;
595
596     case gcvHAL_USER_SIGNAL:
597 #if !USE_NEW_LINUX_SIGNAL
598         /* Dispatch depends on the user signal subcommands. */
599         switch(Interface->u.UserSignal.command)
600         {
601         case gcvUSER_SIGNAL_CREATE:
602             /* Create a signal used in the user space. */
603             gcmkERR_BREAK(
604                 gckOS_CreateUserSignal(Kernel->os,
605                                        Interface->u.UserSignal.manualReset,
606                                        &Interface->u.UserSignal.id));
607
608             gcmkVERIFY_OK(
609                 gckKERNEL_AddProcessDB(Kernel,
610                                        processID, gcvDB_SIGNAL,
611                                        gcmINT2PTR(Interface->u.UserSignal.id),
612                                        gcvNULL,
613                                        0));
614             break;
615
616         case gcvUSER_SIGNAL_DESTROY:
617             gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
618                 Kernel,
619                 processID, gcvDB_SIGNAL,
620                 gcmINT2PTR(Interface->u.UserSignal.id)));
621
622             /* Destroy the signal. */
623             gcmkERR_BREAK(
624                 gckOS_DestroyUserSignal(Kernel->os,
625                                         Interface->u.UserSignal.id));
626
627             break;
628
629         case gcvUSER_SIGNAL_SIGNAL:
630             /* Signal the signal. */
631             gcmkERR_BREAK(
632                 gckOS_SignalUserSignal(Kernel->os,
633                                        Interface->u.UserSignal.id,
634                                        Interface->u.UserSignal.state));
635             break;
636
637         case gcvUSER_SIGNAL_WAIT:
638             /* Wait on the signal. */
639             status = gckOS_WaitUserSignal(Kernel->os,
640                                           Interface->u.UserSignal.id,
641                                           Interface->u.UserSignal.wait);
642             break;
643
644         default:
645             /* Invalid user signal command. */
646             gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
647         }
648 #endif
649         break;
650
651     case gcvHAL_COMMIT:
652         /* Commit a command and context buffer. */
653         gcmkERR_BREAK(gckVGCOMMAND_Commit(
654             Kernel->vg->command,
655             gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.context),
656             gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.queue),
657             kernelInterface->u.VGCommit.entryCount,
658             gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.taskTable)
659             ));
660         break;
661     case gcvHAL_VERSION:
662         kernelInterface->u.Version.major = gcvVERSION_MAJOR;
663         kernelInterface->u.Version.minor = gcvVERSION_MINOR;
664         kernelInterface->u.Version.patch = gcvVERSION_PATCH;
665         kernelInterface->u.Version.build = gcvVERSION_BUILD;
666         status = gcvSTATUS_OK;
667         break;
668
669     case gcvHAL_GET_BASE_ADDRESS:
670         /* Get base address. */
671         gcmkERR_BREAK(
672             gckOS_GetBaseAddress(Kernel->os,
673                                  &kernelInterface->u.GetBaseAddress.baseAddress));
674         break;
675     case gcvHAL_IMPORT_VIDEO_MEMORY:
676         gcmkONERROR(gckVIDMEM_NODE_Import(Kernel,
677                                           Interface->u.ImportVideoMemory.name,
678                                             &Interface->u.ImportVideoMemory.handle));
679         gcmkONERROR(gckKERNEL_AddProcessDB(Kernel,
680                                     processID, gcvDB_VIDEO_MEMORY,
681                                     gcmINT2PTR(Interface->u.ImportVideoMemory.handle),
682                                     gcvNULL,
683                                     0));
684         break;
685
686     case gcvHAL_NAME_VIDEO_MEMORY:
687         gcmkONERROR(gckVIDMEM_NODE_Name(Kernel,
688                                          Interface->u.NameVideoMemory.handle,
689                                          &Interface->u.NameVideoMemory.name));
690         break;
691
692     case gcvHAL_DATABASE:
693         gcmkONERROR(gckKERNEL_QueryDatabase(Kernel, processID, Interface));
694         break;
695     case gcvHAL_SHBUF:
696         {
697             gctSHBUF shBuf;
698             gctPOINTER uData;
699             gctUINT32 bytes;
700
701             switch (Interface->u.ShBuf.command)
702             {
703             case gcvSHBUF_CREATE:
704                 bytes = Interface->u.ShBuf.bytes;
705
706                 /* Create. */
707                 gcmkONERROR(gckKERNEL_CreateShBuffer(Kernel, bytes, &shBuf));
708
709                 Interface->u.ShBuf.id = gcmPTR_TO_UINT64(shBuf);
710
711                 gcmkVERIFY_OK(
712                     gckKERNEL_AddProcessDB(Kernel,
713                                            processID,
714                                            gcvDB_SHBUF,
715                                            shBuf,
716                                            gcvNULL,
717                                            0));
718                 break;
719
720             case gcvSHBUF_DESTROY:
721                 shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
722
723                 /* Check db first to avoid illegal destroy in the process. */
724                 gcmkONERROR(
725                     gckKERNEL_RemoveProcessDB(Kernel,
726                                               processID,
727                                               gcvDB_SHBUF,
728                                               shBuf));
729
730                 gcmkONERROR(gckKERNEL_DestroyShBuffer(Kernel, shBuf));
731                 break;
732
733             case gcvSHBUF_MAP:
734                 shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
735
736                 /* Map for current process access. */
737                 gcmkONERROR(gckKERNEL_MapShBuffer(Kernel, shBuf));
738
739                 gcmkVERIFY_OK(
740                     gckKERNEL_AddProcessDB(Kernel,
741                                            processID,
742                                            gcvDB_SHBUF,
743                                            shBuf,
744                                            gcvNULL,
745                                            0));
746                 break;
747
748             case gcvSHBUF_WRITE:
749                 shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
750                 uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
751                 bytes = Interface->u.ShBuf.bytes;
752
753                 /* Write. */
754                 gcmkONERROR(
755                     gckKERNEL_WriteShBuffer(Kernel, shBuf, uData, bytes));
756                 break;
757
758             case gcvSHBUF_READ:
759                 shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
760                 uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
761                 bytes = Interface->u.ShBuf.bytes;
762
763                 /* Read. */
764                 gcmkONERROR(
765                     gckKERNEL_ReadShBuffer(Kernel,
766                                            shBuf,
767                                            uData,
768                                            bytes,
769                                            &bytes));
770
771                 /* Return copied size. */
772                 Interface->u.ShBuf.bytes = bytes;
773                 break;
774
775             default:
776                 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
777                 break;
778             }
779         }
780         break;
781     default:
782         /* Invalid command. */
783         status = gcvSTATUS_INVALID_ARGUMENT;
784     }
785
786 OnError:
787     /* Save status. */
788     kernelInterface->status = status;
789
790     gcmkFOOTER();
791
792     /* Return the status. */
793     return status;
794 }
795
796 /*******************************************************************************
797 **
798 **  gckKERNEL_QueryCommandBuffer
799 **
800 **  Query command buffer attributes.
801 **
802 **  INPUT:
803 **
804 **      gckKERNEL Kernel
805 **          Pointer to an gckVGHARDWARE object.
806 **
807 **  OUTPUT:
808 **
809 **      gcsCOMMAND_BUFFER_INFO_PTR Information
810 **          Pointer to the information structure to receive buffer attributes.
811 */
812 gceSTATUS
813 gckKERNEL_QueryCommandBuffer(
814     IN gckKERNEL Kernel,
815     OUT gcsCOMMAND_BUFFER_INFO_PTR Information
816     )
817 {
818     gceSTATUS status;
819
820     gcmkHEADER_ARG("Kernel=0x%x *Pool=0x%x",
821                    Kernel, Information);
822     /* Verify the arguments. */
823     gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
824
825     /* Get the information. */
826     status = gckVGCOMMAND_QueryCommandBuffer(Kernel->vg->command, Information);
827
828     gcmkFOOTER();
829     /* Return status. */
830     return status;
831 }
832
833 #endif /* gcdENABLE_VG */