910 lines
28 KiB
C
910 lines
28 KiB
C
/****************************************************************************
|
|
*
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2014 Vivante Corporation
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* The GPL License (GPL)
|
|
*
|
|
* Copyright (C) 2014 Vivante Corporation
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* Note: This software is released under dual MIT and GPL licenses. A
|
|
* recipient may use this file under the terms of either the MIT license or
|
|
* GPL License. If you wish to use only one license not the other, you can
|
|
* indicate your decision by deleting one of the above license notices in your
|
|
* version of this file.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
|
|
#include "gc_hal_kernel_precomp.h"
|
|
|
|
#if gcdENABLE_VG
|
|
|
|
#define _GC_OBJ_ZONE gcvZONE_VG
|
|
|
|
/******************************************************************************\
|
|
******************************* gckKERNEL API Code ******************************
|
|
\******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
**
|
|
** gckKERNEL_Construct
|
|
**
|
|
** Construct a new gckKERNEL object.
|
|
**
|
|
** INPUT:
|
|
**
|
|
** gckOS Os
|
|
** Pointer to an gckOS object.
|
|
**
|
|
** IN gctPOINTER Context
|
|
** Pointer to a driver defined context.
|
|
**
|
|
** OUTPUT:
|
|
**
|
|
** gckKERNEL * Kernel
|
|
** Pointer to a variable that will hold the pointer to the gckKERNEL
|
|
** object.
|
|
*/
|
|
gceSTATUS gckVGKERNEL_Construct(
|
|
IN gckOS Os,
|
|
IN gctPOINTER Context,
|
|
IN gckKERNEL inKernel,
|
|
OUT gckVGKERNEL * Kernel
|
|
)
|
|
{
|
|
gceSTATUS status;
|
|
gckVGKERNEL kernel = gcvNULL;
|
|
|
|
gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
|
|
/* Verify the arguments. */
|
|
gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
|
|
gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
|
|
|
|
do
|
|
{
|
|
/* Allocate the gckKERNEL object. */
|
|
gcmkERR_BREAK(gckOS_Allocate(
|
|
Os,
|
|
sizeof(struct _gckVGKERNEL),
|
|
(gctPOINTER *) &kernel
|
|
));
|
|
|
|
/* Initialize the gckKERNEL object. */
|
|
kernel->object.type = gcvOBJ_KERNEL;
|
|
kernel->os = Os;
|
|
kernel->context = Context;
|
|
kernel->hardware = gcvNULL;
|
|
kernel->interrupt = gcvNULL;
|
|
kernel->command = gcvNULL;
|
|
kernel->mmu = gcvNULL;
|
|
kernel->kernel = inKernel;
|
|
|
|
/* Construct the gckVGHARDWARE object. */
|
|
gcmkERR_BREAK(gckVGHARDWARE_Construct(
|
|
Os, &kernel->hardware
|
|
));
|
|
|
|
/* Set pointer to gckKERNEL object in gckVGHARDWARE object. */
|
|
kernel->hardware->kernel = kernel;
|
|
|
|
/* Construct the gckVGINTERRUPT object. */
|
|
gcmkERR_BREAK(gckVGINTERRUPT_Construct(
|
|
kernel, &kernel->interrupt
|
|
));
|
|
|
|
/* Construct the gckVGCOMMAND object. */
|
|
gcmkERR_BREAK(gckVGCOMMAND_Construct(
|
|
kernel, gcmKB2BYTES(8), gcmKB2BYTES(2), &kernel->command
|
|
));
|
|
|
|
/* Construct the gckVGMMU object. */
|
|
gcmkERR_BREAK(gckVGMMU_Construct(
|
|
kernel, gcmMB2BYTES(1), &kernel->mmu
|
|
));
|
|
|
|
/* Return pointer to the gckKERNEL object. */
|
|
*Kernel = kernel;
|
|
|
|
gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
|
|
/* Success. */
|
|
return gcvSTATUS_OK;
|
|
}
|
|
while (gcvFALSE);
|
|
|
|
/* Roll back. */
|
|
if (kernel != gcvNULL)
|
|
{
|
|
if (kernel->mmu != gcvNULL)
|
|
{
|
|
gcmkVERIFY_OK(gckVGMMU_Destroy(kernel->mmu));
|
|
}
|
|
|
|
if (kernel->command != gcvNULL)
|
|
{
|
|
gcmkVERIFY_OK(gckVGCOMMAND_Destroy(kernel->command));
|
|
}
|
|
|
|
if (kernel->interrupt != gcvNULL)
|
|
{
|
|
gcmkVERIFY_OK(gckVGINTERRUPT_Destroy(kernel->interrupt));
|
|
}
|
|
|
|
if (kernel->hardware != gcvNULL)
|
|
{
|
|
gcmkVERIFY_OK(gckVGHARDWARE_Destroy(kernel->hardware));
|
|
}
|
|
|
|
gcmkVERIFY_OK(gckOS_Free(Os, kernel));
|
|
}
|
|
|
|
gcmkFOOTER();
|
|
/* Return status. */
|
|
return status;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
**
|
|
** gckKERNEL_Destroy
|
|
**
|
|
** Destroy an gckKERNEL object.
|
|
**
|
|
** INPUT:
|
|
**
|
|
** gckKERNEL Kernel
|
|
** Pointer to an gckKERNEL object to destroy.
|
|
**
|
|
** OUTPUT:
|
|
**
|
|
** Nothing.
|
|
*/
|
|
gceSTATUS gckVGKERNEL_Destroy(
|
|
IN gckVGKERNEL Kernel
|
|
)
|
|
{
|
|
gceSTATUS status;
|
|
|
|
gcmkHEADER_ARG("Kernel=0x%x", Kernel);
|
|
|
|
/* Verify the arguments. */
|
|
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
|
|
|
|
do
|
|
{
|
|
/* Destroy the gckVGMMU object. */
|
|
if (Kernel->mmu != gcvNULL)
|
|
{
|
|
gcmkERR_BREAK(gckVGMMU_Destroy(Kernel->mmu));
|
|
Kernel->mmu = gcvNULL;
|
|
}
|
|
|
|
/* Destroy the gckVGCOMMAND object. */
|
|
if (Kernel->command != gcvNULL)
|
|
{
|
|
gcmkERR_BREAK(gckVGCOMMAND_Destroy(Kernel->command));
|
|
Kernel->command = gcvNULL;
|
|
}
|
|
|
|
/* Destroy the gckVGINTERRUPT object. */
|
|
if (Kernel->interrupt != gcvNULL)
|
|
{
|
|
gcmkERR_BREAK(gckVGINTERRUPT_Destroy(Kernel->interrupt));
|
|
Kernel->interrupt = gcvNULL;
|
|
}
|
|
|
|
/* Destroy the gckVGHARDWARE object. */
|
|
if (Kernel->hardware != gcvNULL)
|
|
{
|
|
gcmkERR_BREAK(gckVGHARDWARE_Destroy(Kernel->hardware));
|
|
Kernel->hardware = gcvNULL;
|
|
}
|
|
|
|
/* Mark the gckKERNEL object as unknown. */
|
|
Kernel->object.type = gcvOBJ_UNKNOWN;
|
|
|
|
/* Free the gckKERNEL object. */
|
|
gcmkERR_BREAK(gckOS_Free(Kernel->os, Kernel));
|
|
}
|
|
while (gcvFALSE);
|
|
|
|
gcmkFOOTER();
|
|
|
|
/* Return status. */
|
|
return status;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
**
|
|
** gckKERNEL_AllocateLinearMemory
|
|
**
|
|
** Function walks all required memory pools and allocates the requested
|
|
** amount of video memory.
|
|
**
|
|
** INPUT:
|
|
**
|
|
** gckKERNEL Kernel
|
|
** Pointer to an gckKERNEL object.
|
|
**
|
|
** gcePOOL * Pool
|
|
** Pointer the desired memory pool.
|
|
**
|
|
** gctSIZE_T Bytes
|
|
** Number of bytes to allocate.
|
|
**
|
|
** gctSIZE_T Alignment
|
|
** Required buffer alignment.
|
|
**
|
|
** gceSURF_TYPE Type
|
|
** Surface type.
|
|
**
|
|
** OUTPUT:
|
|
**
|
|
** gcePOOL * Pool
|
|
** Pointer to the actual pool where the memory was allocated.
|
|
**
|
|
** gcuVIDMEM_NODE_PTR * Node
|
|
** Allocated node.
|
|
*/
|
|
gceSTATUS
|
|
gckVGKERNEL_AllocateLinearMemory(
|
|
IN gckKERNEL Kernel,
|
|
IN OUT gcePOOL * Pool,
|
|
IN gctSIZE_T Bytes,
|
|
IN gctUINT32 Alignment,
|
|
IN gceSURF_TYPE Type,
|
|
OUT gcuVIDMEM_NODE_PTR * Node
|
|
)
|
|
{
|
|
gcePOOL pool;
|
|
gceSTATUS status;
|
|
gckVIDMEM videoMemory;
|
|
|
|
/* Get initial pool. */
|
|
switch (pool = *Pool)
|
|
{
|
|
case gcvPOOL_DEFAULT:
|
|
case gcvPOOL_LOCAL:
|
|
pool = gcvPOOL_LOCAL_INTERNAL;
|
|
break;
|
|
|
|
case gcvPOOL_UNIFIED:
|
|
pool = gcvPOOL_SYSTEM;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
do
|
|
{
|
|
/* Verify the number of bytes to allocate. */
|
|
if (Bytes == 0)
|
|
{
|
|
status = gcvSTATUS_INVALID_ARGUMENT;
|
|
break;
|
|
}
|
|
|
|
if (pool == gcvPOOL_VIRTUAL)
|
|
{
|
|
/* Create a gcuVIDMEM_NODE for virtual memory. */
|
|
gcmkERR_BREAK(gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Node));
|
|
|
|
/* Success. */
|
|
break;
|
|
}
|
|
|
|
else
|
|
{
|
|
/* Get pointer to gckVIDMEM object for pool. */
|
|
status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
|
|
|
|
if (status == gcvSTATUS_OK)
|
|
{
|
|
/* Allocate memory. */
|
|
status = gckVIDMEM_AllocateLinear(Kernel,
|
|
videoMemory,
|
|
Bytes,
|
|
Alignment,
|
|
Type,
|
|
(*Pool == gcvPOOL_SYSTEM),
|
|
Node);
|
|
|
|
if (status == gcvSTATUS_OK)
|
|
{
|
|
/* Memory allocated. */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pool == gcvPOOL_LOCAL_INTERNAL)
|
|
{
|
|
/* Advance to external memory. */
|
|
pool = gcvPOOL_LOCAL_EXTERNAL;
|
|
}
|
|
else if (pool == gcvPOOL_LOCAL_EXTERNAL)
|
|
{
|
|
/* Advance to contiguous system memory. */
|
|
pool = gcvPOOL_SYSTEM;
|
|
}
|
|
else if (pool == gcvPOOL_SYSTEM)
|
|
{
|
|
/* Advance to virtual memory. */
|
|
pool = gcvPOOL_VIRTUAL;
|
|
}
|
|
else
|
|
{
|
|
/* Out of pools. */
|
|
break;
|
|
}
|
|
}
|
|
/* Loop only for multiple selection pools. */
|
|
while ((*Pool == gcvPOOL_DEFAULT)
|
|
|| (*Pool == gcvPOOL_LOCAL)
|
|
|| (*Pool == gcvPOOL_UNIFIED)
|
|
);
|
|
|
|
if (gcmIS_SUCCESS(status))
|
|
{
|
|
/* Return pool used for allocation. */
|
|
*Pool = pool;
|
|
}
|
|
|
|
/* Return status. */
|
|
return status;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
**
|
|
** gckKERNEL_Dispatch
|
|
**
|
|
** Dispatch a command received from the user HAL layer.
|
|
**
|
|
** INPUT:
|
|
**
|
|
** gckKERNEL Kernel
|
|
** Pointer to an gckKERNEL object.
|
|
**
|
|
** gcsHAL_INTERFACE * Interface
|
|
** Pointer to a gcsHAL_INTERFACE structure that defines the command to
|
|
** be dispatched.
|
|
**
|
|
** OUTPUT:
|
|
**
|
|
** gcsHAL_INTERFACE * Interface
|
|
** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
|
|
** returned.
|
|
*/
|
|
gceSTATUS gckVGKERNEL_Dispatch(
|
|
IN gckKERNEL Kernel,
|
|
IN gctBOOL FromUser,
|
|
IN OUT gcsHAL_INTERFACE * Interface
|
|
)
|
|
{
|
|
gceSTATUS status;
|
|
gcsHAL_INTERFACE * kernelInterface = Interface;
|
|
gctUINT32 processID;
|
|
gckKERNEL kernel = Kernel;
|
|
gctPOINTER info = gcvNULL;
|
|
gctPHYS_ADDR physical = gcvNULL;
|
|
gctPOINTER logical = gcvNULL;
|
|
gctSIZE_T bytes = 0;
|
|
|
|
gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface);
|
|
|
|
/* Verify the arguments. */
|
|
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
|
|
gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
|
|
|
|
gcmkONERROR(gckOS_GetProcessID(&processID));
|
|
|
|
/* Dispatch on command. */
|
|
switch (Interface->command)
|
|
{
|
|
case gcvHAL_QUERY_VIDEO_MEMORY:
|
|
/* Query video memory size. */
|
|
gcmkERR_BREAK(gckKERNEL_QueryVideoMemory(
|
|
Kernel, kernelInterface
|
|
));
|
|
break;
|
|
|
|
case gcvHAL_QUERY_CHIP_IDENTITY:
|
|
/* Query chip identity. */
|
|
gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity(
|
|
Kernel->vg->hardware,
|
|
&kernelInterface->u.QueryChipIdentity.chipModel,
|
|
&kernelInterface->u.QueryChipIdentity.chipRevision,
|
|
&kernelInterface->u.QueryChipIdentity.chipFeatures,
|
|
&kernelInterface->u.QueryChipIdentity.chipMinorFeatures,
|
|
&kernelInterface->u.QueryChipIdentity.chipMinorFeatures2
|
|
));
|
|
break;
|
|
|
|
case gcvHAL_QUERY_COMMAND_BUFFER:
|
|
/* Query command buffer information. */
|
|
gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer(
|
|
Kernel,
|
|
&kernelInterface->u.QueryCommandBuffer.information
|
|
));
|
|
break;
|
|
case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
|
|
bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
|
|
/* Allocate non-paged memory. */
|
|
gcmkERR_BREAK(gckOS_AllocateNonPagedMemory(
|
|
Kernel->os,
|
|
gcvTRUE,
|
|
&bytes,
|
|
&physical,
|
|
&logical
|
|
));
|
|
|
|
kernelInterface->u.AllocateNonPagedMemory.bytes = bytes;
|
|
kernelInterface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
|
|
kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
|
|
break;
|
|
|
|
case gcvHAL_FREE_NON_PAGED_MEMORY:
|
|
physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
|
|
|
|
/* Unmap user logical out of physical memory first. */
|
|
gcmkERR_BREAK(gckOS_UnmapUserLogical(
|
|
Kernel->os,
|
|
physical,
|
|
(gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
|
|
gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
|
|
));
|
|
|
|
/* Free non-paged memory. */
|
|
gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
|
|
Kernel->os,
|
|
(gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
|
|
physical,
|
|
gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
|
|
));
|
|
|
|
gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
|
|
break;
|
|
|
|
case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
|
|
bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
|
|
/* Allocate contiguous memory. */
|
|
gcmkERR_BREAK(gckOS_AllocateContiguous(
|
|
Kernel->os,
|
|
gcvTRUE,
|
|
&bytes,
|
|
&physical,
|
|
&logical
|
|
));
|
|
|
|
kernelInterface->u.AllocateNonPagedMemory.bytes = bytes;
|
|
kernelInterface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
|
|
kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
|
|
break;
|
|
|
|
case gcvHAL_FREE_CONTIGUOUS_MEMORY:
|
|
physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
|
|
/* Unmap user logical out of physical memory first. */
|
|
gcmkERR_BREAK(gckOS_UnmapUserLogical(
|
|
Kernel->os,
|
|
physical,
|
|
(gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
|
|
gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
|
|
));
|
|
|
|
/* Free contiguous memory. */
|
|
gcmkERR_BREAK(gckOS_FreeContiguous(
|
|
Kernel->os,
|
|
physical,
|
|
gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical),
|
|
(gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes
|
|
));
|
|
|
|
gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
|
|
break;
|
|
|
|
case gcvHAL_ALLOCATE_VIDEO_MEMORY:
|
|
gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED);
|
|
break;
|
|
|
|
case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
|
|
/* Allocate memory. */
|
|
gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
|
|
Kernel, processID,
|
|
&kernelInterface->u.AllocateLinearVideoMemory.pool,
|
|
kernelInterface->u.AllocateLinearVideoMemory.bytes,
|
|
kernelInterface->u.AllocateLinearVideoMemory.alignment,
|
|
kernelInterface->u.AllocateLinearVideoMemory.type,
|
|
kernelInterface->u.AllocateLinearVideoMemory.flag,
|
|
&kernelInterface->u.AllocateLinearVideoMemory.node
|
|
));
|
|
|
|
break;
|
|
|
|
case gcvHAL_RELEASE_VIDEO_MEMORY:
|
|
/* Free video memory. */
|
|
gcmkERR_BREAK(gckKERNEL_ReleaseVideoMemory(
|
|
Kernel, processID,
|
|
(gctUINT32)kernelInterface->u.ReleaseVideoMemory.node
|
|
));
|
|
{
|
|
gckVIDMEM_NODE nodeObject;
|
|
|
|
/* Remove record from process db. */
|
|
gcmkERR_BREAK(
|
|
gckKERNEL_RemoveProcessDB(Kernel, processID, gcvDB_VIDEO_MEMORY_LOCKED, (gctPOINTER)kernelInterface->u.ReleaseVideoMemory.node));
|
|
|
|
gcmkERR_BREAK(
|
|
gckVIDMEM_HANDLE_Lookup(Kernel, processID, (gctUINT32)kernelInterface->u.ReleaseVideoMemory.node, &nodeObject));
|
|
|
|
gckVIDMEM_NODE_Dereference(Kernel, nodeObject);
|
|
}
|
|
|
|
break;
|
|
|
|
case gcvHAL_MAP_MEMORY:
|
|
/* Map memory. */
|
|
gcmkERR_BREAK(gckKERNEL_MapMemory(
|
|
Kernel,
|
|
gcmINT2PTR(kernelInterface->u.MapMemory.physical),
|
|
(gctSIZE_T) kernelInterface->u.MapMemory.bytes,
|
|
&logical
|
|
));
|
|
kernelInterface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
|
|
break;
|
|
|
|
case gcvHAL_UNMAP_MEMORY:
|
|
/* Unmap memory. */
|
|
gcmkERR_BREAK(gckKERNEL_UnmapMemory(
|
|
Kernel,
|
|
gcmINT2PTR(kernelInterface->u.MapMemory.physical),
|
|
(gctSIZE_T) kernelInterface->u.MapMemory.bytes,
|
|
gcmUINT64_TO_PTR(kernelInterface->u.MapMemory.logical)
|
|
));
|
|
break;
|
|
|
|
case gcvHAL_MAP_USER_MEMORY:
|
|
/* Map user memory to DMA. */
|
|
gcmkERR_BREAK(gckOS_MapUserMemory(
|
|
Kernel->os,
|
|
gcvCORE_VG,
|
|
gcmUINT64_TO_PTR(kernelInterface->u.MapUserMemory.memory),
|
|
kernelInterface->u.MapUserMemory.physical,
|
|
(gctSIZE_T) kernelInterface->u.MapUserMemory.size,
|
|
&info,
|
|
&kernelInterface->u.MapUserMemory.address
|
|
));
|
|
|
|
kernelInterface->u.MapUserMemory.info = gcmPTR_TO_NAME(info);
|
|
|
|
/* Clear temp storage. */
|
|
info = gcvNULL;
|
|
break;
|
|
|
|
case gcvHAL_UNMAP_USER_MEMORY:
|
|
/* Unmap user memory. */
|
|
gcmkERR_BREAK(gckOS_UnmapUserMemory(
|
|
Kernel->os,
|
|
gcvCORE_VG,
|
|
gcmUINT64_TO_PTR(kernelInterface->u.UnmapUserMemory.memory),
|
|
(gctSIZE_T) kernelInterface->u.UnmapUserMemory.size,
|
|
gcmNAME_TO_PTR(kernelInterface->u.UnmapUserMemory.info),
|
|
kernelInterface->u.UnmapUserMemory.address
|
|
));
|
|
|
|
gcmRELEASE_NAME(kernelInterface->u.UnmapUserMemory.info);
|
|
break;
|
|
|
|
case gcvHAL_LOCK_VIDEO_MEMORY:
|
|
gcmkONERROR(gckKERNEL_LockVideoMemory(Kernel, gcvCORE_VG, processID, FromUser, Interface));
|
|
break;
|
|
|
|
case gcvHAL_UNLOCK_VIDEO_MEMORY:
|
|
gcmkONERROR(gckKERNEL_UnlockVideoMemory(Kernel, processID, Interface));
|
|
break;
|
|
|
|
case gcvHAL_USER_SIGNAL:
|
|
#if !USE_NEW_LINUX_SIGNAL
|
|
/* Dispatch depends on the user signal subcommands. */
|
|
switch(Interface->u.UserSignal.command)
|
|
{
|
|
case gcvUSER_SIGNAL_CREATE:
|
|
/* Create a signal used in the user space. */
|
|
gcmkERR_BREAK(
|
|
gckOS_CreateUserSignal(Kernel->os,
|
|
Interface->u.UserSignal.manualReset,
|
|
&Interface->u.UserSignal.id));
|
|
|
|
gcmkVERIFY_OK(
|
|
gckKERNEL_AddProcessDB(Kernel,
|
|
processID, gcvDB_SIGNAL,
|
|
gcmINT2PTR(Interface->u.UserSignal.id),
|
|
gcvNULL,
|
|
0));
|
|
break;
|
|
|
|
case gcvUSER_SIGNAL_DESTROY:
|
|
gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
|
|
Kernel,
|
|
processID, gcvDB_SIGNAL,
|
|
gcmINT2PTR(Interface->u.UserSignal.id)));
|
|
|
|
/* Destroy the signal. */
|
|
gcmkERR_BREAK(
|
|
gckOS_DestroyUserSignal(Kernel->os,
|
|
Interface->u.UserSignal.id));
|
|
|
|
break;
|
|
|
|
case gcvUSER_SIGNAL_SIGNAL:
|
|
/* Signal the signal. */
|
|
gcmkERR_BREAK(
|
|
gckOS_SignalUserSignal(Kernel->os,
|
|
Interface->u.UserSignal.id,
|
|
Interface->u.UserSignal.state));
|
|
break;
|
|
|
|
case gcvUSER_SIGNAL_WAIT:
|
|
/* Wait on the signal. */
|
|
status = gckOS_WaitUserSignal(Kernel->os,
|
|
Interface->u.UserSignal.id,
|
|
Interface->u.UserSignal.wait);
|
|
break;
|
|
|
|
default:
|
|
/* Invalid user signal command. */
|
|
gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case gcvHAL_COMMIT:
|
|
/* Commit a command and context buffer. */
|
|
gcmkERR_BREAK(gckVGCOMMAND_Commit(
|
|
Kernel->vg->command,
|
|
gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.context),
|
|
gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.queue),
|
|
kernelInterface->u.VGCommit.entryCount,
|
|
gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.taskTable)
|
|
));
|
|
break;
|
|
case gcvHAL_VERSION:
|
|
kernelInterface->u.Version.major = gcvVERSION_MAJOR;
|
|
kernelInterface->u.Version.minor = gcvVERSION_MINOR;
|
|
kernelInterface->u.Version.patch = gcvVERSION_PATCH;
|
|
kernelInterface->u.Version.build = gcvVERSION_BUILD;
|
|
status = gcvSTATUS_OK;
|
|
break;
|
|
|
|
case gcvHAL_GET_BASE_ADDRESS:
|
|
/* Get base address. */
|
|
gcmkERR_BREAK(
|
|
gckOS_GetBaseAddress(Kernel->os,
|
|
&kernelInterface->u.GetBaseAddress.baseAddress));
|
|
break;
|
|
case gcvHAL_IMPORT_VIDEO_MEMORY:
|
|
gcmkONERROR(gckVIDMEM_NODE_Import(Kernel,
|
|
Interface->u.ImportVideoMemory.name,
|
|
&Interface->u.ImportVideoMemory.handle));
|
|
gcmkONERROR(gckKERNEL_AddProcessDB(Kernel,
|
|
processID, gcvDB_VIDEO_MEMORY,
|
|
gcmINT2PTR(Interface->u.ImportVideoMemory.handle),
|
|
gcvNULL,
|
|
0));
|
|
break;
|
|
|
|
case gcvHAL_NAME_VIDEO_MEMORY:
|
|
gcmkONERROR(gckVIDMEM_NODE_Name(Kernel,
|
|
Interface->u.NameVideoMemory.handle,
|
|
&Interface->u.NameVideoMemory.name));
|
|
break;
|
|
|
|
case gcvHAL_DATABASE:
|
|
gcmkONERROR(gckKERNEL_QueryDatabase(Kernel, processID, Interface));
|
|
break;
|
|
case gcvHAL_SHBUF:
|
|
{
|
|
gctSHBUF shBuf;
|
|
gctPOINTER uData;
|
|
gctUINT32 bytes;
|
|
|
|
switch (Interface->u.ShBuf.command)
|
|
{
|
|
case gcvSHBUF_CREATE:
|
|
bytes = Interface->u.ShBuf.bytes;
|
|
|
|
/* Create. */
|
|
gcmkONERROR(gckKERNEL_CreateShBuffer(Kernel, bytes, &shBuf));
|
|
|
|
Interface->u.ShBuf.id = gcmPTR_TO_UINT64(shBuf);
|
|
|
|
gcmkVERIFY_OK(
|
|
gckKERNEL_AddProcessDB(Kernel,
|
|
processID,
|
|
gcvDB_SHBUF,
|
|
shBuf,
|
|
gcvNULL,
|
|
0));
|
|
break;
|
|
|
|
case gcvSHBUF_DESTROY:
|
|
shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
|
|
|
|
/* Check db first to avoid illegal destroy in the process. */
|
|
gcmkONERROR(
|
|
gckKERNEL_RemoveProcessDB(Kernel,
|
|
processID,
|
|
gcvDB_SHBUF,
|
|
shBuf));
|
|
|
|
gcmkONERROR(gckKERNEL_DestroyShBuffer(Kernel, shBuf));
|
|
break;
|
|
|
|
case gcvSHBUF_MAP:
|
|
shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
|
|
|
|
/* Map for current process access. */
|
|
gcmkONERROR(gckKERNEL_MapShBuffer(Kernel, shBuf));
|
|
|
|
gcmkVERIFY_OK(
|
|
gckKERNEL_AddProcessDB(Kernel,
|
|
processID,
|
|
gcvDB_SHBUF,
|
|
shBuf,
|
|
gcvNULL,
|
|
0));
|
|
break;
|
|
|
|
case gcvSHBUF_WRITE:
|
|
shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
|
|
uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
|
|
bytes = Interface->u.ShBuf.bytes;
|
|
|
|
/* Write. */
|
|
gcmkONERROR(
|
|
gckKERNEL_WriteShBuffer(Kernel, shBuf, uData, bytes));
|
|
break;
|
|
|
|
case gcvSHBUF_READ:
|
|
shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
|
|
uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
|
|
bytes = Interface->u.ShBuf.bytes;
|
|
|
|
/* Read. */
|
|
gcmkONERROR(
|
|
gckKERNEL_ReadShBuffer(Kernel,
|
|
shBuf,
|
|
uData,
|
|
bytes,
|
|
&bytes));
|
|
|
|
/* Return copied size. */
|
|
Interface->u.ShBuf.bytes = bytes;
|
|
break;
|
|
|
|
default:
|
|
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case gcvHAL_READ_REGISTER:
|
|
#if gcdREGISTER_ACCESS_FROM_USER
|
|
/* Read a register. */
|
|
gcmkONERROR(gckOS_ReadRegisterEx(
|
|
Kernel->os,
|
|
Kernel->core,
|
|
Interface->u.ReadRegisterData.address,
|
|
&Interface->u.ReadRegisterData.data));
|
|
#else
|
|
/* No access from user land to read registers. */
|
|
Interface->u.ReadRegisterData.data = 0;
|
|
status = gcvSTATUS_NOT_SUPPORTED;
|
|
#endif
|
|
break;
|
|
|
|
case gcvHAL_WRITE_REGISTER:
|
|
#if gcdREGISTER_ACCESS_FROM_USER
|
|
/* Write a register. */
|
|
gcmkONERROR(
|
|
gckOS_WriteRegisterEx(Kernel->os,
|
|
Kernel->core,
|
|
Interface->u.WriteRegisterData.address,
|
|
Interface->u.WriteRegisterData.data));
|
|
#else
|
|
/* No access from user land to write registers. */
|
|
status = gcvSTATUS_NOT_SUPPORTED;
|
|
#endif
|
|
break;
|
|
|
|
|
|
default:
|
|
/* Invalid command. */
|
|
status = gcvSTATUS_INVALID_ARGUMENT;
|
|
}
|
|
|
|
OnError:
|
|
/* Save status. */
|
|
kernelInterface->status = status;
|
|
|
|
gcmkFOOTER();
|
|
|
|
/* Return the status. */
|
|
return status;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
**
|
|
** gckKERNEL_QueryCommandBuffer
|
|
**
|
|
** Query command buffer attributes.
|
|
**
|
|
** INPUT:
|
|
**
|
|
** gckKERNEL Kernel
|
|
** Pointer to an gckVGHARDWARE object.
|
|
**
|
|
** OUTPUT:
|
|
**
|
|
** gcsCOMMAND_BUFFER_INFO_PTR Information
|
|
** Pointer to the information structure to receive buffer attributes.
|
|
*/
|
|
gceSTATUS
|
|
gckKERNEL_QueryCommandBuffer(
|
|
IN gckKERNEL Kernel,
|
|
OUT gcsCOMMAND_BUFFER_INFO_PTR Information
|
|
)
|
|
{
|
|
gceSTATUS status;
|
|
|
|
gcmkHEADER_ARG("Kernel=0x%x *Pool=0x%x",
|
|
Kernel, Information);
|
|
/* Verify the arguments. */
|
|
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
|
|
|
|
/* Get the information. */
|
|
status = gckVGCOMMAND_QueryCommandBuffer(Kernel->vg->command, Information);
|
|
|
|
gcmkFOOTER();
|
|
/* Return status. */
|
|
return status;
|
|
}
|
|
|
|
#endif /* gcdENABLE_VG */
|