1 /****************************************************************************
3 * Copyright (C) 2005 - 2014 by Vivante Corp.
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.
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.
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.
19 *****************************************************************************/
22 #include "gc_hal_kernel_precomp.h"
26 #define _GC_OBJ_ZONE gcvZONE_VG
28 /******************************************************************************\
29 ******************************* gckKERNEL API Code ******************************
30 \******************************************************************************/
32 /*******************************************************************************
34 ** gckKERNEL_Construct
36 ** Construct a new gckKERNEL object.
41 ** Pointer to an gckOS object.
43 ** IN gctPOINTER Context
44 ** Pointer to a driver defined context.
49 ** Pointer to a variable that will hold the pointer to the gckKERNEL
52 gceSTATUS gckVGKERNEL_Construct(
54 IN gctPOINTER Context,
55 IN gckKERNEL inKernel,
56 OUT gckVGKERNEL * Kernel
60 gckVGKERNEL kernel = gcvNULL;
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);
69 /* Allocate the gckKERNEL object. */
70 gcmkERR_BREAK(gckOS_Allocate(
72 sizeof(struct _gckVGKERNEL),
73 (gctPOINTER *) &kernel
76 /* Initialize the gckKERNEL object. */
77 kernel->object.type = gcvOBJ_KERNEL;
79 kernel->context = Context;
80 kernel->hardware = gcvNULL;
81 kernel->interrupt = gcvNULL;
82 kernel->command = gcvNULL;
83 kernel->mmu = gcvNULL;
84 kernel->kernel = inKernel;
86 /* Construct the gckVGHARDWARE object. */
87 gcmkERR_BREAK(gckVGHARDWARE_Construct(
91 /* Set pointer to gckKERNEL object in gckVGHARDWARE object. */
92 kernel->hardware->kernel = kernel;
94 /* Construct the gckVGINTERRUPT object. */
95 gcmkERR_BREAK(gckVGINTERRUPT_Construct(
96 kernel, &kernel->interrupt
99 /* Construct the gckVGCOMMAND object. */
100 gcmkERR_BREAK(gckVGCOMMAND_Construct(
101 kernel, gcmKB2BYTES(8), gcmKB2BYTES(2), &kernel->command
104 /* Construct the gckVGMMU object. */
105 gcmkERR_BREAK(gckVGMMU_Construct(
106 kernel, gcmKB2BYTES(32), &kernel->mmu
109 /* Return pointer to the gckKERNEL object. */
112 gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
119 if (kernel != gcvNULL)
121 if (kernel->mmu != gcvNULL)
123 gcmkVERIFY_OK(gckVGMMU_Destroy(kernel->mmu));
126 if (kernel->command != gcvNULL)
128 gcmkVERIFY_OK(gckVGCOMMAND_Destroy(kernel->command));
131 if (kernel->interrupt != gcvNULL)
133 gcmkVERIFY_OK(gckVGINTERRUPT_Destroy(kernel->interrupt));
136 if (kernel->hardware != gcvNULL)
138 gcmkVERIFY_OK(gckVGHARDWARE_Destroy(kernel->hardware));
141 gcmkVERIFY_OK(gckOS_Free(Os, kernel));
149 /*******************************************************************************
153 ** Destroy an gckKERNEL object.
158 ** Pointer to an gckKERNEL object to destroy.
164 gceSTATUS gckVGKERNEL_Destroy(
165 IN gckVGKERNEL Kernel
170 gcmkHEADER_ARG("Kernel=0x%x", Kernel);
172 /* Verify the arguments. */
173 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
177 /* Destroy the gckVGMMU object. */
178 if (Kernel->mmu != gcvNULL)
180 gcmkERR_BREAK(gckVGMMU_Destroy(Kernel->mmu));
181 Kernel->mmu = gcvNULL;
184 /* Destroy the gckVGCOMMAND object. */
185 if (Kernel->command != gcvNULL)
187 gcmkERR_BREAK(gckVGCOMMAND_Destroy(Kernel->command));
188 Kernel->command = gcvNULL;
191 /* Destroy the gckVGINTERRUPT object. */
192 if (Kernel->interrupt != gcvNULL)
194 gcmkERR_BREAK(gckVGINTERRUPT_Destroy(Kernel->interrupt));
195 Kernel->interrupt = gcvNULL;
198 /* Destroy the gckVGHARDWARE object. */
199 if (Kernel->hardware != gcvNULL)
201 gcmkERR_BREAK(gckVGHARDWARE_Destroy(Kernel->hardware));
202 Kernel->hardware = gcvNULL;
205 /* Mark the gckKERNEL object as unknown. */
206 Kernel->object.type = gcvOBJ_UNKNOWN;
208 /* Free the gckKERNEL object. */
209 gcmkERR_BREAK(gckOS_Free(Kernel->os, Kernel));
219 /*******************************************************************************
221 ** gckKERNEL_AllocateLinearMemory
223 ** Function walks all required memory pools and allocates the requested
224 ** amount of video memory.
229 ** Pointer to an gckKERNEL object.
232 ** Pointer the desired memory pool.
235 ** Number of bytes to allocate.
237 ** gctSIZE_T Alignment
238 ** Required buffer alignment.
246 ** Pointer to the actual pool where the memory was allocated.
248 ** gcuVIDMEM_NODE_PTR * Node
252 gckVGKERNEL_AllocateLinearMemory(
254 IN OUT gcePOOL * Pool,
256 IN gctUINT32 Alignment,
257 IN gceSURF_TYPE Type,
258 OUT gcuVIDMEM_NODE_PTR * Node
263 gckVIDMEM videoMemory;
265 /* Get initial pool. */
266 switch (pool = *Pool)
268 case gcvPOOL_DEFAULT:
270 pool = gcvPOOL_LOCAL_INTERNAL;
273 case gcvPOOL_UNIFIED:
274 pool = gcvPOOL_SYSTEM;
283 /* Verify the number of bytes to allocate. */
286 status = gcvSTATUS_INVALID_ARGUMENT;
290 if (pool == gcvPOOL_VIRTUAL)
292 /* Create a gcuVIDMEM_NODE for virtual memory. */
293 gcmkERR_BREAK(gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Node));
301 /* Get pointer to gckVIDMEM object for pool. */
302 status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
304 if (status == gcvSTATUS_OK)
306 /* Allocate memory. */
307 status = gckVIDMEM_AllocateLinear(Kernel,
312 (*Pool == gcvPOOL_SYSTEM),
315 if (status == gcvSTATUS_OK)
317 /* Memory allocated. */
323 if (pool == gcvPOOL_LOCAL_INTERNAL)
325 /* Advance to external memory. */
326 pool = gcvPOOL_LOCAL_EXTERNAL;
328 else if (pool == gcvPOOL_LOCAL_EXTERNAL)
330 /* Advance to contiguous system memory. */
331 pool = gcvPOOL_SYSTEM;
333 else if (pool == gcvPOOL_SYSTEM)
335 /* Advance to virtual memory. */
336 pool = gcvPOOL_VIRTUAL;
344 /* Loop only for multiple selection pools. */
345 while ((*Pool == gcvPOOL_DEFAULT)
346 || (*Pool == gcvPOOL_LOCAL)
347 || (*Pool == gcvPOOL_UNIFIED)
350 if (gcmIS_SUCCESS(status))
352 /* Return pool used for allocation. */
360 /*******************************************************************************
362 ** gckKERNEL_Dispatch
364 ** Dispatch a command received from the user HAL layer.
369 ** Pointer to an gckKERNEL object.
371 ** gcsHAL_INTERFACE * Interface
372 ** Pointer to a gcsHAL_INTERFACE structure that defines the command to
377 ** gcsHAL_INTERFACE * Interface
378 ** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
381 gceSTATUS gckVGKERNEL_Dispatch(
384 IN OUT gcsHAL_INTERFACE * Interface
388 gcsHAL_INTERFACE * kernelInterface = Interface;
390 gckKERNEL kernel = Kernel;
391 gctPOINTER info = gcvNULL;
392 gctPHYS_ADDR physical = gcvNULL;
393 gctPOINTER logical = gcvNULL;
396 gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface);
398 /* Verify the arguments. */
399 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
400 gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
402 gcmkONERROR(gckOS_GetProcessID(&processID));
404 /* Dispatch on command. */
405 switch (Interface->command)
407 case gcvHAL_QUERY_VIDEO_MEMORY:
408 /* Query video memory size. */
409 gcmkERR_BREAK(gckKERNEL_QueryVideoMemory(
410 Kernel, kernelInterface
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
426 case gcvHAL_QUERY_COMMAND_BUFFER:
427 /* Query command buffer information. */
428 gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer(
430 &kernelInterface->u.QueryCommandBuffer.information
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(
444 kernelInterface->u.AllocateNonPagedMemory.bytes = bytes;
445 kernelInterface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
446 kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
449 case gcvHAL_FREE_NON_PAGED_MEMORY:
450 physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
452 /* Unmap user logical out of physical memory first. */
453 gcmkERR_BREAK(gckOS_UnmapUserLogical(
456 (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
457 gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
460 /* Free non-paged memory. */
461 gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
463 (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
465 gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
468 gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
471 case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
472 bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
473 /* Allocate contiguous memory. */
474 gcmkERR_BREAK(gckOS_AllocateContiguous(
482 kernelInterface->u.AllocateNonPagedMemory.bytes = bytes;
483 kernelInterface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
484 kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
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(
493 (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
494 gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
497 /* Free contiguous memory. */
498 gcmkERR_BREAK(gckOS_FreeContiguous(
501 gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical),
502 (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes
505 gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
508 case gcvHAL_ALLOCATE_VIDEO_MEMORY:
509 gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED);
512 case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
513 /* Allocate memory. */
514 gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
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
526 case gcvHAL_RELEASE_VIDEO_MEMORY:
527 /* Free video memory. */
528 gcmkERR_BREAK(gckKERNEL_ReleaseVideoMemory(
530 (gctUINT32)kernelInterface->u.ReleaseVideoMemory.node
535 case gcvHAL_MAP_MEMORY:
537 gcmkERR_BREAK(gckKERNEL_MapMemory(
539 gcmINT2PTR(kernelInterface->u.MapMemory.physical),
540 (gctSIZE_T) kernelInterface->u.MapMemory.bytes,
543 kernelInterface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
546 case gcvHAL_UNMAP_MEMORY:
548 gcmkERR_BREAK(gckKERNEL_UnmapMemory(
550 gcmINT2PTR(kernelInterface->u.MapMemory.physical),
551 (gctSIZE_T) kernelInterface->u.MapMemory.bytes,
552 gcmUINT64_TO_PTR(kernelInterface->u.MapMemory.logical)
556 case gcvHAL_MAP_USER_MEMORY:
557 /* Map user memory to DMA. */
558 gcmkERR_BREAK(gckOS_MapUserMemory(
561 gcmUINT64_TO_PTR(kernelInterface->u.MapUserMemory.memory),
562 kernelInterface->u.MapUserMemory.physical,
563 (gctSIZE_T) kernelInterface->u.MapUserMemory.size,
565 &kernelInterface->u.MapUserMemory.address
568 kernelInterface->u.MapUserMemory.info = gcmPTR_TO_NAME(info);
570 /* Clear temp storage. */
574 case gcvHAL_UNMAP_USER_MEMORY:
575 /* Unmap user memory. */
576 gcmkERR_BREAK(gckOS_UnmapUserMemory(
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
585 gcmRELEASE_NAME(kernelInterface->u.UnmapUserMemory.info);
588 case gcvHAL_LOCK_VIDEO_MEMORY:
589 gcmkONERROR(gckKERNEL_LockVideoMemory(Kernel, gcvCORE_VG, processID, FromUser, Interface));
592 case gcvHAL_UNLOCK_VIDEO_MEMORY:
593 gcmkONERROR(gckKERNEL_UnlockVideoMemory(Kernel, processID, Interface));
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)
601 case gcvUSER_SIGNAL_CREATE:
602 /* Create a signal used in the user space. */
604 gckOS_CreateUserSignal(Kernel->os,
605 Interface->u.UserSignal.manualReset,
606 &Interface->u.UserSignal.id));
609 gckKERNEL_AddProcessDB(Kernel,
610 processID, gcvDB_SIGNAL,
611 gcmINT2PTR(Interface->u.UserSignal.id),
616 case gcvUSER_SIGNAL_DESTROY:
617 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
619 processID, gcvDB_SIGNAL,
620 gcmINT2PTR(Interface->u.UserSignal.id)));
622 /* Destroy the signal. */
624 gckOS_DestroyUserSignal(Kernel->os,
625 Interface->u.UserSignal.id));
629 case gcvUSER_SIGNAL_SIGNAL:
630 /* Signal the signal. */
632 gckOS_SignalUserSignal(Kernel->os,
633 Interface->u.UserSignal.id,
634 Interface->u.UserSignal.state));
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);
645 /* Invalid user signal command. */
646 gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
652 /* Commit a command and context buffer. */
653 gcmkERR_BREAK(gckVGCOMMAND_Commit(
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)
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;
669 case gcvHAL_GET_BASE_ADDRESS:
670 /* Get base address. */
672 gckOS_GetBaseAddress(Kernel->os,
673 &kernelInterface->u.GetBaseAddress.baseAddress));
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),
686 case gcvHAL_NAME_VIDEO_MEMORY:
687 gcmkONERROR(gckVIDMEM_NODE_Name(Kernel,
688 Interface->u.NameVideoMemory.handle,
689 &Interface->u.NameVideoMemory.name));
692 case gcvHAL_DATABASE:
693 gcmkONERROR(gckKERNEL_QueryDatabase(Kernel, processID, Interface));
701 switch (Interface->u.ShBuf.command)
703 case gcvSHBUF_CREATE:
704 bytes = Interface->u.ShBuf.bytes;
707 gcmkONERROR(gckKERNEL_CreateShBuffer(Kernel, bytes, &shBuf));
709 Interface->u.ShBuf.id = gcmPTR_TO_UINT64(shBuf);
712 gckKERNEL_AddProcessDB(Kernel,
720 case gcvSHBUF_DESTROY:
721 shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
723 /* Check db first to avoid illegal destroy in the process. */
725 gckKERNEL_RemoveProcessDB(Kernel,
730 gcmkONERROR(gckKERNEL_DestroyShBuffer(Kernel, shBuf));
734 shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
736 /* Map for current process access. */
737 gcmkONERROR(gckKERNEL_MapShBuffer(Kernel, shBuf));
740 gckKERNEL_AddProcessDB(Kernel,
749 shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
750 uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
751 bytes = Interface->u.ShBuf.bytes;
755 gckKERNEL_WriteShBuffer(Kernel, shBuf, uData, bytes));
759 shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
760 uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
761 bytes = Interface->u.ShBuf.bytes;
765 gckKERNEL_ReadShBuffer(Kernel,
771 /* Return copied size. */
772 Interface->u.ShBuf.bytes = bytes;
776 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
782 /* Invalid command. */
783 status = gcvSTATUS_INVALID_ARGUMENT;
788 kernelInterface->status = status;
792 /* Return the status. */
796 /*******************************************************************************
798 ** gckKERNEL_QueryCommandBuffer
800 ** Query command buffer attributes.
805 ** Pointer to an gckVGHARDWARE object.
809 ** gcsCOMMAND_BUFFER_INFO_PTR Information
810 ** Pointer to the information structure to receive buffer attributes.
813 gckKERNEL_QueryCommandBuffer(
815 OUT gcsCOMMAND_BUFFER_INFO_PTR Information
820 gcmkHEADER_ARG("Kernel=0x%x *Pool=0x%x",
821 Kernel, Information);
822 /* Verify the arguments. */
823 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
825 /* Get the information. */
826 status = gckVGCOMMAND_QueryCommandBuffer(Kernel->vg->command, Information);
833 #endif /* gcdENABLE_VG */