| /**************************************************************************** |
| * |
| * The MIT License (MIT) |
| * |
| * Copyright (c) 2014 - 2018 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 - 2018 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, gcmKB2BYTES(gcdGC355_VGMMU_MEMORY_SIZE_KB), &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_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; |
| gctPHYS_ADDR physical = gcvNULL; |
| gctPOINTER logical = gcvNULL; |
| gctSIZE_T bytes = 0; |
| gctBOOL powerMutexAcquired = gcvFALSE; |
| |
| 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_CHIP_IDENTITY: |
| /* Query chip identity. */ |
| gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity( |
| Kernel->vg->hardware, |
| &kernelInterface->u.QueryChipIdentity.chipModel, |
| &kernelInterface->u.QueryChipIdentity.chipRevision, |
| &kernelInterface->u.QueryChipIdentity.productID, |
| &kernelInterface->u.QueryChipIdentity.ecoID, |
| &kernelInterface->u.QueryChipIdentity.customerID, |
| &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.FreeNonPagedMemory.physical); |
| |
| /* Unmap user logical out of physical memory first. */ |
| gcmkERR_BREAK(gckOS_UnmapUserLogical( |
| Kernel->os, |
| physical, |
| (gctSIZE_T) kernelInterface->u.FreeNonPagedMemory.bytes, |
| gcmUINT64_TO_PTR(kernelInterface->u.FreeNonPagedMemory.logical))); |
| |
| |
| /* Free non-paged memory. */ |
| gcmkERR_BREAK(gckOS_FreeNonPagedMemory( |
| Kernel->os, |
| (gctSIZE_T) kernelInterface->u.FreeNonPagedMemory.bytes, |
| physical, |
| gcmUINT64_TO_PTR(kernelInterface->u.FreeNonPagedMemory.logical) |
| )); |
| |
| gcmRELEASE_NAME(kernelInterface->u.FreeNonPagedMemory.physical); |
| break; |
| |
| case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY: |
| bytes = (gctSIZE_T) kernelInterface->u.AllocateContiguousMemory.bytes; |
| /* Allocate contiguous memory. */ |
| gcmkERR_BREAK(gckOS_AllocateContiguous( |
| Kernel->os, |
| gcvTRUE, |
| &bytes, |
| &physical, |
| &logical |
| )); |
| |
| kernelInterface->u.AllocateContiguousMemory.bytes = bytes; |
| kernelInterface->u.AllocateContiguousMemory.logical = gcmPTR_TO_UINT64(logical); |
| kernelInterface->u.AllocateContiguousMemory.physical = gcmPTR_TO_NAME(physical); |
| break; |
| |
| case gcvHAL_FREE_CONTIGUOUS_MEMORY: |
| physical = gcmNAME_TO_PTR(kernelInterface->u.FreeContiguousMemory.physical); |
| /* Unmap user logical out of physical memory first. */ |
| gcmkERR_BREAK(gckOS_UnmapUserLogical( |
| Kernel->os, |
| physical, |
| (gctSIZE_T) kernelInterface->u.FreeContiguousMemory.bytes, |
| gcmUINT64_TO_PTR(kernelInterface->u.FreeContiguousMemory.logical) |
| )); |
| |
| /* Free contiguous memory. */ |
| gcmkERR_BREAK(gckOS_FreeContiguous( |
| Kernel->os, |
| physical, |
| gcmUINT64_TO_PTR(kernelInterface->u.FreeContiguousMemory.logical), |
| (gctSIZE_T) kernelInterface->u.FreeContiguousMemory.bytes |
| )); |
| |
| gcmRELEASE_NAME(kernelInterface->u.FreeContiguousMemory.physical); |
| break; |
| |
| case gcvHAL_ALLOCATE_VIDEO_MEMORY: |
| gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED); |
| 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), |
| processID |
| )); |
| break; |
| |
| case gcvHAL_MAP_USER_MEMORY: |
| |
| gcmkONERROR(gcvSTATUS_NOT_SUPPORTED); |
| |
| break; |
| |
| case gcvHAL_UNMAP_USER_MEMORY: |
| |
| gcmkONERROR(gcvSTATUS_NOT_SUPPORTED); |
| |
| break; |
| |
| case gcvHAL_LOCK_VIDEO_MEMORY: |
| gcmkONERROR(gckKERNEL_LockVideoMemory(Kernel, gcvCORE_VG, processID, FromUser, Interface)); |
| break; |
| |
| case gcvHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY: |
| gcmkERR_BREAK(gckKERNEL_BottomHalfUnlockVideoMemory(Kernel, processID, |
| kernelInterface->u.BottomHalfUnlockVideoMemory.node)); |
| 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_GET_BASE_ADDRESS: |
| /* Get base address. */ |
| gcmkONERROR( |
| gckOS_GetBaseAddress(Kernel->os, |
| &Interface->u.GetBaseAddress.baseAddress)); |
| break; |
| |
| case gcvHAL_EVENT_COMMIT: |
| gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED); |
| break; |
| case gcvHAL_READ_REGISTER: |
| #if gcdREGISTER_ACCESS_FROM_USER |
| { |
| gceCHIPPOWERSTATE power; |
| |
| gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->vg->hardware->powerMutex, gcvINFINITE)); |
| powerMutexAcquired = gcvTRUE; |
| gcmkONERROR(gckVGHARDWARE_QueryPowerManagementState(Kernel->vg->hardware, |
| &power)); |
| if (power == gcvPOWER_ON) |
| { |
| /* Read a register. */ |
| gcmkONERROR(gckOS_ReadRegisterEx( |
| Kernel->os, |
| Kernel->core, |
| Interface->u.ReadRegisterData.address, |
| &Interface->u.ReadRegisterData.data)); |
| } |
| else |
| { |
| /* Chip is in power-state. */ |
| Interface->u.ReadRegisterData.data = 0; |
| status = gcvSTATUS_CHIP_NOT_READY; |
| } |
| gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->vg->hardware->powerMutex)); |
| powerMutexAcquired = gcvFALSE; |
| } |
| #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 |
| { |
| gceCHIPPOWERSTATE power; |
| |
| gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->vg->hardware->powerMutex, gcvINFINITE)); |
| powerMutexAcquired = gcvTRUE; |
| gcmkONERROR(gckVGHARDWARE_QueryPowerManagementState(Kernel->vg->hardware, |
| &power)); |
| if (power == gcvPOWER_ON) |
| { |
| /* Write a register. */ |
| gcmkONERROR( |
| gckOS_WriteRegisterEx(Kernel->os, |
| Kernel->core, |
| Interface->u.WriteRegisterData.address, |
| Interface->u.WriteRegisterData.data)); |
| } |
| else |
| { |
| /* Chip is in power-state. */ |
| Interface->u.WriteRegisterData.data = 0; |
| status = gcvSTATUS_CHIP_NOT_READY; |
| } |
| gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->vg->hardware->powerMutex)); |
| powerMutexAcquired = gcvFALSE; |
| } |
| #else |
| /* No access from user land to write registers. */ |
| status = gcvSTATUS_NOT_SUPPORTED; |
| #endif |
| break; |
| default: |
| /* Invalid command, try gckKERNEL_Dispatch */ |
| status = gckKERNEL_Dispatch(Kernel, gcvNULL, gcvTRUE, Interface); |
| } |
| |
| OnError: |
| /* Save status. */ |
| kernelInterface->status = status; |
| if (powerMutexAcquired == gcvTRUE) |
| { |
| gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->vg->hardware->powerMutex)); |
| } |
| |
| 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 */ |