]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00156850 gpu-viv: add gpu-viv driver source
authorRichard Zhao <richard.zhao@freescale.com>
Thu, 15 Sep 2011 08:42:04 +0000 (16:42 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:33:13 +0000 (08:33 +0200)
It's vivante driver 4.5.0 (Sep 5, 2011) with freescale changes.

Signed-off-by: Richard Zhao <richard.zhao@freescale.com>
Acked-by: Lily Zhang
57 files changed:
arch/arm/configs/imx6_defconfig
drivers/mxc/Kconfig
drivers/mxc/Makefile
drivers/mxc/gpu-viv/Kbuild [new file with mode: 0644]
drivers/mxc/gpu-viv/Kconfig [new file with mode: 0644]
drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.c [new file with mode: 0644]
drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.h [new file with mode: 0644]
drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c [new file with mode: 0644]
drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h [new file with mode: 0644]
drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c [new file with mode: 0644]
drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.h [new file with mode: 0644]
drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c [new file with mode: 0644]
drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h [new file with mode: 0644]
drivers/mxc/gpu-viv/config [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_cl.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h [new file with mode: 0644]

index 88f9e814cee4d3a10c3a2500bb699aea390a17d5..558d5bcfcad2a42e1caea6a2e5aa38d7d9a85181 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux/arm 2.6.38 Kernel Configuration
-# Mon Aug 29 18:28:10 2011
+# Thu Sep 15 18:47:42 2011
 #
 CONFIG_ARM=y
 CONFIG_HAVE_PWM=y
@@ -294,7 +294,6 @@ CONFIG_IMX_HAVE_PLATFORM_IMX_ASRC=y
 # CONFIG_ARCH_MX5 is not set
 CONFIG_ARCH_MX6=y
 CONFIG_FORCE_MAX_ZONEORDER=13
-CONFIG_DMA_ZONE_SIZE=184
 CONFIG_ARCH_MX6Q=y
 CONFIG_SOC_IMX6Q=y
 CONFIG_MACH_MX6Q_SABREAUTO=y
@@ -309,6 +308,7 @@ CONFIG_MXC_PWM=y
 CONFIG_ARCH_MXC_IOMUX_V3=y
 CONFIG_IRAM_ALLOC=y
 CONFIG_CLK_DEBUG=y
+CONFIG_DMA_ZONE_SIZE=184
 
 #
 # System MMU
@@ -440,7 +440,7 @@ CONFIG_CPU_FREQ_STAT=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
 # CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
 # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
-#CONFIG_CPU_FREQ_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_GOV_PERFORMANCE is not set
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 # CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
@@ -1350,6 +1350,7 @@ CONFIG_FB_MODE_HELPERS=y
 #
 # CONFIG_FB_UVESA is not set
 # CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_TMIO is not set
 # CONFIG_FB_UDL is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
@@ -1868,6 +1869,11 @@ CONFIG_MXC_ASRC=y
 # MXC GPU support
 #
 
+#
+# MXC GPU support
+#
+CONFIG_MXC_GPU_VIV=y
+
 #
 # ANATOP_THERMAL
 #
index 9a2fa0568e4cc9d3516e542090f2a5db58fd0078..ac7f92d7e66ef628ab838a6d374e8a4a09e985fb 100644 (file)
@@ -35,6 +35,7 @@ source "drivers/mxc/gps_ioctrl/Kconfig"
 source "drivers/mxc/mlb/Kconfig"
 source "drivers/mxc/adc/Kconfig"
 source "drivers/mxc/amd-gpu/Kconfig"
+source "drivers/mxc/gpu-viv/Kconfig"
 source "drivers/mxc/thermal/Kconfig"
 
 endmenu
index 70692832564d439597704f510eae0b38e2f7b80f..b70d4b7af2d1926310c36006b0202eed38f06046 100644 (file)
@@ -16,5 +16,5 @@ obj-$(CONFIG_GPS_IOCTRL)              += gps_ioctrl/
 obj-$(CONFIG_MXC_MLB)                   += mlb/
 obj-$(CONFIG_IMX_ADC)                   += adc/
 obj-$(CONFIG_MXC_AMD_GPU)              += amd-gpu/
+obj-$(CONFIG_MXC_GPU_VIV)              += gpu-viv/
 obj-$(CONFIG_ANATOP_THERMAL)            += thermal/
-
diff --git a/drivers/mxc/gpu-viv/Kbuild b/drivers/mxc/gpu-viv/Kbuild
new file mode 100644 (file)
index 0000000..13fd9b4
--- /dev/null
@@ -0,0 +1,215 @@
+##############################################################################
+#
+#    Copyright (C) 2005 - 2011 by Vivante Corp.
+#
+#    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+##############################################################################
+
+
+#
+# Linux build file for kernel HAL driver.
+#
+
+AQROOT := $(srctree)/drivers/mxc/gpu-viv
+AQARCH := $(AQROOT)/arch/XAQ2
+AQVGARCH := $(AQROOT)/arch/GC350
+
+include $(AQROOT)/config
+
+KERNEL_DIR ?= $(TOOL_DIR)/kernel
+
+OS_KERNEL_DIR   := hal/os/linux/kernel
+ARCH_KERNEL_DIR := arch/$(notdir $(AQARCH))/hal/kernel
+ARCH_VG_KERNEL_DIR := arch/$(notdir $(AQVGARCH))/hal/kernel
+HAL_KERNEL_DIR  := hal/kernel
+
+EXTRA_CFLAGS += -Werror
+
+OBJS := $(OS_KERNEL_DIR)/gc_hal_kernel_device.o \
+        $(OS_KERNEL_DIR)/gc_hal_kernel_driver.o \
+        $(OS_KERNEL_DIR)/gc_hal_kernel_linux.o \
+        $(OS_KERNEL_DIR)/gc_hal_kernel_math.o \
+        $(OS_KERNEL_DIR)/gc_hal_kernel_os.o
+
+ifeq ($(USE_3D_VG), 1)
+
+OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_db.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_debug.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_event.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o
+
+OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_context.o \
+        $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o
+
+ifeq ($(VIVANTE_ENABLE_VG), 1)
+OBJS +=\
+          $(HAL_KERNEL_DIR)/gc_hal_kernel_vg.o\
+          $(HAL_KERNEL_DIR)/gc_hal_kernel_command_vg.o\
+          $(HAL_KERNEL_DIR)/gc_hal_kernel_interrupt_vg.o\
+          $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu_vg.o\
+          $(ARCH_VG_KERNEL_DIR)/gc_hal_kernel_hardware_command_vg.o\
+          $(ARCH_VG_KERNEL_DIR)/gc_hal_kernel_hardware_vg.o
+endif
+else
+
+OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_interrupt.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o \
+        $(OS_KERNEL_DIR)/gc_hal_kernel_debug.o
+
+OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o \
+        $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware_command.o
+
+endif
+
+ifeq ($(KERNELRELEASE), )
+
+.PHONY: all clean install
+
+# Define targets.
+all:
+       @make V=$(V) ARCH=$(ARCH_TYPE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
+
+clean:
+       @rm -rf $(OBJS)
+       @rm -rf modules.order Module.symvers
+       @find $(AQROOT) -name ".gc_*.cmd" | xargs rm -f
+
+install: all
+       @mkdir -p $(SDK_DIR)/drivers
+
+else
+
+
+EXTRA_CFLAGS += -DLINUX -DDRIVER
+
+ifeq ($(ENUM_WORKAROUND), 1)
+EXTRA_CFLAGS += -DENUM_WORKAROUND=1
+else
+EXTRA_CFLAGS += -DENUM_WORKAROUND=0
+endif
+
+ifeq ($(FLAREON),1)
+EXTRA_CFLAGS += -DFLAREON
+endif
+
+ifeq ($(DEBUG), 1)
+EXTRA_CFLAGS += -DDBG=1 -DDEBUG -D_DEBUG
+else
+EXTRA_CFLAGS += -DDBG=0
+endif
+
+ifeq ($(NO_DMA_COHERENT), 1)
+EXTRA_CFLAGS += -DNO_DMA_COHERENT
+endif
+
+ifeq ($(CONFIG_DOVE_GPU), 1)
+EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
+endif
+
+ifeq ($(USE_POWER_MANAGEMENT), 1)
+EXTRA_CFLAGS += -DgcdPOWER_MANAGEMENT=1
+else
+EXTRA_CFLAGS += -DgcdPOWER_MANAGEMENT=0
+endif
+
+ifneq ($(USE_PLATFORM_DRIVER), 0)
+EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=1
+else
+EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=0
+endif
+
+ifeq ($(USE_PROFILER), 1)
+EXTRA_CFLAGS += -DVIVANTE_PROFILER=1
+else
+EXTRA_CFLAGS += -DVIVANTE_PROFILER=0
+endif
+
+ifeq ($(ANDROID), 1)
+EXTRA_CFLAGS += -DANDROID=1
+endif
+
+ifeq ($(ENABLE_GPU_CLOCK_BY_DRIVER), 1)
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=1
+else
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=0
+endif
+
+ifeq ($(USE_NEW_LINUX_SIGNAL), 1)
+EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=1
+else
+EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=0
+endif
+
+ifeq ($(NO_USER_DIRECT_ACCESS_FROM_KERNEL), 1)
+EXTRA_CFLAGS += -DNO_USER_DIRECT_ACCESS_FROM_KERNEL=1
+else
+EXTRA_CFLAGS += -DNO_USER_DIRECT_ACCESS_FROM_KERNEL=0
+endif
+
+ifeq ($(ENABLE_CACHED_VIDEO_MEMORY), 1)
+EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=1
+else
+EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=0
+endif
+
+ifeq ($(NONPAGED_MEMORY_CACHEABLE), 1)
+EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_CACHEABLE=1
+else
+EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_CACHEABLE=0
+endif
+
+ifeq ($(NONPAGED_MEMORY_BUFFERABLE), 1)
+EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_BUFFERABLE=1
+else
+EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_BUFFERABLE=0
+endif
+
+ifeq ($(CACHE_FUNCTION_UNIMPLEMENTED), 1)
+EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=1
+else
+EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=0
+endif
+
+ifeq ($(VIVANTE_ENABLE_VG), 1)
+EXTRA_CFLAGS += -DgcdENABLE_VG=1
+else
+EXTRA_CFLAGS += -DgcdENABLE_VG=0
+endif
+
+
+
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/hal/kernel
+EXTRA_CFLAGS += -I$(AQROOT)/hal/os/linux/kernel
+
+ifeq ($(VIVANTE_ENABLE_VG), 1)
+EXTRA_CFLAGS += -I$(AQVGARCH)/hal/kernel
+endif
+
+obj-$(CONFIG_MXC_GPU_VIV) += galcore.o
+
+galcore-objs  := $(OBJS)
+
+endif
diff --git a/drivers/mxc/gpu-viv/Kconfig b/drivers/mxc/gpu-viv/Kconfig
new file mode 100644 (file)
index 0000000..5ecbea3
--- /dev/null
@@ -0,0 +1,9 @@
+menu "MXC GPU support"
+
+config MXC_GPU_VIV
+       tristate "MXC GPU support"
+       depends on ARCH_MX6
+       ---help---
+         Say Y to get the GPU driver support.
+
+endmenu
diff --git a/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.c b/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.c
new file mode 100644 (file)
index 0000000..96ea0f1
--- /dev/null
@@ -0,0 +1,929 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+
+#if gcdENABLE_VG
+
+#include "gc_hal_kernel_hardware_command_vg.h"
+
+#define _GC_OBJ_ZONE    gcvZONE_COMMAND
+
+/******************************************************************************\
+****************************** gckVGCOMMAND API code *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckVGCOMMAND_InitializeInfo
+**
+**  Initialize architecture dependent command buffer information.
+**
+**  INPUT:
+**
+**      gckVGCOMMAND Command
+**          Pointer to the Command object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckVGCOMMAND_InitializeInfo(
+    IN gckVGCOMMAND Command
+    )
+{
+    gceSTATUS status;
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    do
+    {
+        /* Reset interrupts. */
+        Command->info.feBufferInt   = -1;
+        Command->info.tsOverflowInt = -1;
+
+        /* Set command buffer attributes. */
+        Command->info.addressAlignment = 64;
+        Command->info.commandAlignment = 8;
+
+        /* Determine command alignment address mask. */
+        Command->info.addressMask = ((((gctUINT32) (Command->info.addressAlignment - 1)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) ((gctUINT32) (0 ) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+
+        /* Query the number of bytes needed by the STATE command. */
+        gcmkERR_BREAK(gckVGCOMMAND_StateCommand(
+            Command, 0x0, gcvNULL, (gctUINT32)~0, 0,
+            &Command->info.stateCommandSize
+            ));
+
+        /* Query the number of bytes needed by the RESTART command. */
+        gcmkERR_BREAK(gckVGCOMMAND_RestartCommand(
+            Command, gcvNULL, (gctUINT32)~0, 0,
+            &Command->info.restartCommandSize
+            ));
+
+        /* Query the number of bytes needed by the FETCH command. */
+        gcmkERR_BREAK(gckVGCOMMAND_FetchCommand(
+            Command, gcvNULL, (gctUINT32)~0, 0,
+            &Command->info.fetchCommandSize
+            ));
+
+        /* Query the number of bytes needed by the CALL command. */
+        gcmkERR_BREAK(gckVGCOMMAND_CallCommand(
+            Command, gcvNULL, (gctUINT32)~0, 0,
+            &Command->info.callCommandSize
+            ));
+
+        /* Query the number of bytes needed by the RETURN command. */
+        gcmkERR_BREAK(gckVGCOMMAND_ReturnCommand(
+            Command, gcvNULL,
+            &Command->info.returnCommandSize
+            ));
+
+        /* Query the number of bytes needed by the EVENT command. */
+        gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
+            Command, gcvNULL, gcvBLOCK_PIXEL, -1,
+            &Command->info.eventCommandSize
+            ));
+
+        /* Query the number of bytes needed by the END command. */
+        gcmkERR_BREAK(gckVGCOMMAND_EndCommand(
+            Command, gcvNULL, -1,
+            &Command->info.endCommandSize
+            ));
+
+        /* Determine the tail reserve size. */
+        Command->info.staticTailSize = gcmMAX(
+            Command->info.fetchCommandSize,
+            gcmMAX(
+                Command->info.returnCommandSize,
+                Command->info.endCommandSize
+                )
+            );
+
+        /* Determine the maximum tail size. */
+        Command->info.dynamicTailSize
+            = Command->info.staticTailSize
+            + Command->info.eventCommandSize * gcvBLOCK_COUNT;
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return status. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVGCOMMAND_StateCommand
+**
+**  Append a STATE command at the specified location in the command buffer.
+**
+**  INPUT:
+**
+**      gckVGCOMMAND Command
+**          Pointer to an gckVGCOMMAND object.
+**
+**      gctUINT32 Pipe
+**          Harwdare destination pipe.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command buffer to append
+**          STATE command at or gcvNULL to query the size of the command.
+**
+**      gctUINT32 Address
+**          Starting register address of the state buffer.
+**          If 'Logical' is gcvNULL, this argument is ignored.
+**
+**      gctUINT32 Count
+**          Number of states in state buffer.
+**          If 'Logical' is gcvNULL, this argument is ignored.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the STATE command.
+**          If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the STATE command.  If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_StateCommand(
+    IN gckVGCOMMAND Command,
+    IN gctUINT32 Pipe,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Address,
+    IN gctSIZE_T Count,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gcmkHEADER_ARG("Command=0x%x Pipe=0x%x Logical=0x%x Address=0x%x Count=0x%x Bytes = 0x%x",
+                   Command, Pipe, Logical, Address, Count, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    if (Command->fe20)
+    {
+        if (Logical != gcvNULL)
+        {
+            gctUINT32_PTR buffer;
+
+            /* Cast the buffer pointer. */
+            buffer = (gctUINT32_PTR) Logical;
+
+            /* Append STATE. */
+            buffer[0]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:0) - (0 ? 11:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ? 11:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 11:0) - (0 ? 11:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ? 11:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:16) - (0 ? 27:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:16) - (0 ? 27:16) + 1))))))) << (0 ? 27:16))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 27:16) - (0 ? 27:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:16) - (0 ? 27:16) + 1))))))) << (0 ? 27:16)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12))) | (((gctUINT32) ((gctUINT32) (Pipe) & ((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12)));
+        }
+
+        if (Bytes != gcvNULL)
+        {
+            /* Return number of bytes required by the STATE command. */
+            *Bytes = 4 * (Count + 1);
+        }
+    }
+    else
+    {
+        if (Logical != gcvNULL)
+        {
+            gctUINT32_PTR buffer;
+
+            /* Cast the buffer pointer. */
+            buffer = (gctUINT32_PTR) Logical;
+
+            /* Append LOAD_STATE. */
+            buffer[0]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+        }
+
+        if (Bytes != gcvNULL)
+        {
+            /* Return number of bytes required by the STATE command. */
+            *Bytes = 4 * (Count + 1);
+        }
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGCOMMAND_RestartCommand
+**
+**  Form a RESTART command at the specified location in the command buffer.
+**
+**  INPUT:
+**
+**      gckVGCOMMAND Command
+**          Pointer to an gckVGCOMMAND object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command buffer to append
+**          RESTART command at or gcvNULL to query the size of the command.
+**
+**      gctUINT32 FetchAddress
+**          The address of another command buffer to be executed by this RESTART
+**          command.  If 'Logical' is gcvNULL, this argument is ignored.
+**
+**      gctUINT FetchCount
+**          The number of 64-bit data quantities in another command buffer to
+**          be executed by this RESTART command.  If 'Logical' is gcvNULL, this
+**          argument is ignored.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the RESTART command.
+**          If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the RESTART command.  If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_RestartCommand(
+    IN gckVGCOMMAND Command,
+    IN gctPOINTER Logical,
+    IN gctUINT32 FetchAddress,
+    IN gctUINT FetchCount,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
+                   Command, Logical, FetchAddress, FetchCount, Bytes);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    if (Command->fe20)
+    {
+        if (Logical != gcvNULL)
+        {
+            gctUINT32_PTR buffer;
+            gctUINT32 beginEndMark;
+
+            /* Cast the buffer pointer. */
+            buffer = (gctUINT32_PTR) Logical;
+
+            /* Determine Begin/End flag. */
+            beginEndMark = (FetchCount > 0)
+                ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24)))
+                : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24)));
+
+            /* Append RESTART. */
+            buffer[0]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x9 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0)))
+                | beginEndMark;
+
+            buffer[1]
+                = FetchAddress;
+        }
+
+        if (Bytes != gcvNULL)
+        {
+            /* Return number of bytes required by the RESTART command. */
+            *Bytes = 8;
+        }
+    }
+    else
+    {
+        return gcvSTATUS_NOT_SUPPORTED;
+    }
+
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGCOMMAND_FetchCommand
+**
+**  Form a FETCH command at the specified location in the command buffer.
+**
+**  INPUT:
+**
+**      gckVGCOMMAND Command
+**          Pointer to an gckVGCOMMAND object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command buffer to append
+**          FETCH command at or gcvNULL to query the size of the command.
+**
+**      gctUINT32 FetchAddress
+**          The address of another command buffer to be executed by this FETCH
+**          command.  If 'Logical' is gcvNULL, this argument is ignored.
+**
+**      gctUINT FetchCount
+**          The number of 64-bit data quantities in another command buffer to
+**          be executed by this FETCH command.  If 'Logical' is gcvNULL, this
+**          argument is ignored.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the FETCH command.
+**          If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the FETCH command.  If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_FetchCommand(
+    IN gckVGCOMMAND Command,
+    IN gctPOINTER Logical,
+    IN gctUINT32 FetchAddress,
+    IN gctUINT FetchCount,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
+                   Command, Logical, FetchAddress, FetchCount, Bytes);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    if (Command->fe20)
+    {
+        if (Logical != gcvNULL)
+        {
+            gctUINT32_PTR buffer;
+
+            /* Cast the buffer pointer. */
+            buffer = (gctUINT32_PTR) Logical;
+
+            /* Append FETCH. */
+            buffer[0]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x5 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0)));
+
+            buffer[1]
+                = gcmFIXADDRESS(FetchAddress);
+        }
+
+        if (Bytes != gcvNULL)
+        {
+            /* Return number of bytes required by the FETCH command. */
+            *Bytes = 8;
+        }
+    }
+    else
+    {
+        if (Logical != gcvNULL)
+        {
+            gctUINT32_PTR buffer;
+
+            /* Cast the buffer pointer. */
+            buffer = (gctUINT32_PTR) Logical;
+
+            /* Append LINK. */
+            buffer[0]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+            buffer[1]
+                = gcmFIXADDRESS(FetchAddress);
+        }
+
+        if (Bytes != gcvNULL)
+        {
+            /* Return number of bytes required by the LINK command. */
+            *Bytes = 8;
+        }
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGCOMMAND_CallCommand
+**
+**  Append a CALL command at the specified location in the command buffer.
+**
+**  INPUT:
+**
+**      gckVGCOMMAND Command
+**          Pointer to an gckVGCOMMAND object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command buffer to append
+**          CALL command at or gcvNULL to query the size of the command.
+**
+**      gctUINT32 FetchAddress
+**          The address of another command buffer to be executed by this CALL
+**          command.  If 'Logical' is gcvNULL, this argument is ignored.
+**
+**      gctUINT FetchCount
+**          The number of 64-bit data quantities in another command buffer to
+**          be executed by this CALL command.  If 'Logical' is gcvNULL, this
+**          argument is ignored.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the CALL command.
+**          If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the CALL command.  If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_CallCommand(
+    IN gckVGCOMMAND Command,
+    IN gctPOINTER Logical,
+    IN gctUINT32 FetchAddress,
+    IN gctUINT FetchCount,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
+                   Command, Logical, FetchAddress, FetchCount, Bytes);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    if (Command->fe20)
+    {
+        if (Logical != gcvNULL)
+        {
+            gctUINT32_PTR buffer;
+
+            /* Cast the buffer pointer. */
+            buffer = (gctUINT32_PTR) Logical;
+
+            /* Append CALL. */
+            buffer[0]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x6 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0)));
+
+            buffer[1]
+                = gcmFIXADDRESS(FetchAddress);
+        }
+
+        if (Bytes != gcvNULL)
+        {
+            /* Return number of bytes required by the CALL command. */
+            *Bytes = 8;
+        }
+    }
+    else
+    {
+        return gcvSTATUS_NOT_SUPPORTED;
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGCOMMAND_ReturnCommand
+**
+**  Append a RETURN command at the specified location in the command buffer.
+**
+**  INPUT:
+**
+**      gckVGCOMMAND Command
+**          Pointer to an gckVGCOMMAND object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command buffer to append
+**          RETURN command at or gcvNULL to query the size of the command.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the RETURN command.
+**          If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the RETURN command.  If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_ReturnCommand(
+    IN gckVGCOMMAND Command,
+    IN gctPOINTER Logical,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gcmkHEADER_ARG("Command=0x%x Logical=0x%x  Bytes = 0x%x",
+                   Command, Logical, Bytes);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    if (Command->fe20)
+    {
+        if (Logical != gcvNULL)
+        {
+            gctUINT32_PTR buffer;
+
+            /* Cast the buffer pointer. */
+            buffer = (gctUINT32_PTR) Logical;
+
+            /* Append RETURN. */
+            buffer[0]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x7 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)));
+        }
+
+        if (Bytes != gcvNULL)
+        {
+            /* Return number of bytes required by the RETURN command. */
+            *Bytes = 8;
+        }
+    }
+    else
+    {
+        gcmkFOOTER_NO();
+        return gcvSTATUS_NOT_SUPPORTED;
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGCOMMAND_EventCommand
+**
+**  Form an EVENT command at the specified location in the command buffer.
+**
+**  INPUT:
+**
+**      gckVGCOMMAND Command
+**          Pointer to the Command object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command buffer to append
+**          EVENT command at or gcvNULL to query the size of the command.
+**
+**      gctINT32 InterruptId
+**          The ID of the interrupt to generate.
+**          If 'Logical' is gcvNULL, this argument is ignored.
+**
+**      gceBLOCK Block
+**          Block that will generate the interrupt.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the EVENT command.
+**          If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the END command.  If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_EventCommand(
+    IN gckVGCOMMAND Command,
+    IN gctPOINTER Logical,
+    IN gceBLOCK Block,
+    IN gctINT32 InterruptId,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gcmkHEADER_ARG("Command=0x%x Logical=0x%x Block=0x%x InterruptId=0x%x Bytes = 0x%x",
+                   Command, Logical, Block, InterruptId, Bytes);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    if (Command->fe20)
+    {
+        typedef struct _gcsEVENTSTATES
+        {
+            /* Chips before VG21 use these values. */
+            gctUINT     eventFromFE;
+            gctUINT     eventFromPE;
+
+            /* VG21 chips and later use SOURCE field. */
+            gctUINT     eventSource;
+        }
+        gcsEVENTSTATES;
+
+        static gcsEVENTSTATES states[] =
+        {
+            /* gcvBLOCK_COMMAND */
+            {
+                (gctUINT)~0,
+                (gctUINT)~0,
+                (gctUINT)~0
+            },
+
+            /* gcvBLOCK_TESSELLATOR */
+            {
+                0x0,
+                0x1,
+                0x10
+            },
+
+            /* gcvBLOCK_TESSELLATOR2 */
+            {
+                0x0,
+                0x1,
+                0x12
+            },
+
+            /* gcvBLOCK_TESSELLATOR3 */
+            {
+                0x0,
+                0x1,
+                0x14
+            },
+
+            /* gcvBLOCK_RASTER */
+            {
+                0x0,
+                0x1,
+                0x07,
+            },
+
+            /* gcvBLOCK_VG */
+            {
+                0x0,
+                0x1,
+                0x0F
+            },
+
+            /* gcvBLOCK_VG2 */
+            {
+                0x0,
+                0x1,
+                0x11
+            },
+
+            /* gcvBLOCK_VG3 */
+            {
+                0x0,
+                0x1,
+                0x13
+            },
+
+            /* gcvBLOCK_PIXEL */
+            {
+                0x0,
+                0x1,
+                0x07
+            },
+        };
+
+        /* Verify block ID. */
+        gcmkVERIFY_ARGUMENT(gcmIS_VALID_INDEX(Block, states));
+
+        if (Logical != gcvNULL)
+        {
+            gctUINT32_PTR buffer;
+
+            /* Verify the event ID. */
+            gcmkVERIFY_ARGUMENT(InterruptId >= 0);
+            gcmkVERIFY_ARGUMENT(InterruptId <= ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))));
+
+            /* Cast the buffer pointer. */
+            buffer = (gctUINT32_PTR) Logical;
+
+            /* Append EVENT. */
+            buffer[0]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:0) - (0 ? 11:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ? 11:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 11:0) - (0 ? 11:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ? 11:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:16) - (0 ? 27:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:16) - (0 ? 27:16) + 1))))))) << (0 ? 27:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:16) - (0 ? 27:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:16) - (0 ? 27:16) + 1))))))) << (0 ? 27:16)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12)));
+
+            /* Determine chip version. */
+            if (Command->vg21)
+            {
+                /* Get the event source for the block. */
+                gctUINT eventSource = states[Block].eventSource;
+
+                /* Supported? */
+                if (eventSource == ~0)
+                {
+                    return gcvSTATUS_NOT_SUPPORTED;
+                }
+
+                buffer[1]
+                    = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+                    | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) ((gctUINT32) (eventSource) & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+            }
+            else
+            {
+                /* Get the event source for the block. */
+                gctUINT eventFromFE = states[Block].eventFromFE;
+                gctUINT eventFromPE = states[Block].eventFromPE;
+
+                /* Supported? */
+                if (eventFromFE == ~0)
+                {
+                    return gcvSTATUS_NOT_SUPPORTED;
+                }
+
+                buffer[1]
+                    = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+                    | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (eventFromFE) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)))
+                    | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) ((gctUINT32) (eventFromPE) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+            }
+        }
+
+        if (Bytes != gcvNULL)
+        {
+            /* Make sure the events are directly supported for the block. */
+            if (states[Block].eventSource == ~0)
+            {
+                return gcvSTATUS_NOT_SUPPORTED;
+            }
+
+            /* Return number of bytes required by the END command. */
+            *Bytes = 8;
+        }
+    }
+    else
+    {
+        if (Logical != gcvNULL)
+        {
+            gctUINT32_PTR buffer;
+
+            /* Verify the event ID. */
+            gcmkVERIFY_ARGUMENT(InterruptId >= 0);
+            gcmkVERIFY_ARGUMENT(InterruptId <= ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))));
+
+            /* Cast the buffer pointer. */
+            buffer = (gctUINT32_PTR) Logical;
+
+            /* Append EVENT. */
+            buffer[0]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+            /* Determine event source. */
+            if (Block == gcvBLOCK_COMMAND)
+            {
+                buffer[1]
+                    = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+                    | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+            }
+            else
+            {
+                buffer[1]
+                    = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+                    | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+            }
+        }
+
+        if (Bytes != gcvNULL)
+        {
+            /* Return number of bytes required by the EVENT and END commands. */
+            *Bytes = 8;
+        }
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGCOMMAND_EndCommand
+**
+**  Form an END command at the specified location in the command buffer.
+**
+**  INPUT:
+**
+**      gckVGCOMMAND Command
+**          Pointer to the Command object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command buffer to append
+**          END command at or gcvNULL to query the size of the command.
+**
+**      gctINT32 InterruptId
+**          The ID of the interrupt to generate.
+**          If 'Logical' is gcvNULL, this argument will be ignored.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the END command.
+**          If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the END command.  If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_EndCommand(
+    IN gckVGCOMMAND Command,
+    IN gctPOINTER Logical,
+    IN gctINT32 InterruptId,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gcmkHEADER_ARG("Command=0x%x Logical=0x%x InterruptId=0x%x Bytes = 0x%x",
+                   Command, Logical, InterruptId, Bytes);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    if (Command->fe20)
+    {
+        if (Logical != gcvNULL)
+        {
+            gctUINT32_PTR buffer;
+
+            /* Verify the event ID. */
+            gcmkVERIFY_ARGUMENT(InterruptId >= 0);
+
+            /* Cast the buffer pointer. */
+            buffer = (gctUINT32_PTR) Logical;
+
+            /* Append END. */
+            buffer[0]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
+        }
+
+        if (Bytes != gcvNULL)
+        {
+            /* Return number of bytes required by the END command. */
+            *Bytes = 8;
+        }
+    }
+    else
+    {
+        if (Logical != gcvNULL)
+        {
+            gctUINT32_PTR memory;
+
+            /* Verify the event ID. */
+            gcmkVERIFY_ARGUMENT(InterruptId >= 0);
+
+            /* Cast the buffer pointer. */
+            memory = (gctUINT32_PTR) Logical;
+
+            /* Append EVENT. */
+            memory[0]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+            memory[1]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+
+            /* Append END. */
+            memory[2]
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+        }
+
+        if (Bytes != gcvNULL)
+        {
+            /* Return number of bytes required by the EVENT and END commands. */
+            *Bytes = 16;
+        }
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+#endif /* gcdENABLE_VG */
+
diff --git a/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.h b/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.h
new file mode 100644 (file)
index 0000000..a3738fe
--- /dev/null
@@ -0,0 +1,316 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+
+
+#ifndef __gc_hal_kernel_hardware_command_vg_h_
+#define __gc_hal_kernel_hardware_command_vg_h_
+
+/******************************************************************************\
+******************* Task and Interrupt Management Structures. ******************
+\******************************************************************************/
+
+/* Task storage header. */
+typedef struct _gcsTASK_STORAGE * gcsTASK_STORAGE_PTR;
+typedef struct _gcsTASK_STORAGE
+{
+    /* Next allocated storage buffer. */
+    gcsTASK_STORAGE_PTR         next;
+}
+gcsTASK_STORAGE;
+
+/* Task container header. */
+typedef struct _gcsTASK_CONTAINER * gcsTASK_CONTAINER_PTR;
+typedef struct _gcsTASK_CONTAINER
+{
+    /* The number of tasks left to be processed in the container. */
+    gctINT                      referenceCount;
+
+    /* Size of the buffer. */
+    gctUINT                     size;
+
+    /* Link to the previous and the next allocated containers. */
+    gcsTASK_CONTAINER_PTR       allocPrev;
+    gcsTASK_CONTAINER_PTR       allocNext;
+
+    /* Link to the previous and the next containers in the free list. */
+    gcsTASK_CONTAINER_PTR       freePrev;
+    gcsTASK_CONTAINER_PTR       freeNext;
+}
+gcsTASK_CONTAINER;
+
+/* Kernel space task master table entry. */
+typedef struct _gcsBLOCK_TASK_ENTRY * gcsBLOCK_TASK_ENTRY_PTR;
+typedef struct _gcsBLOCK_TASK_ENTRY
+{
+    /* Pointer to the current task container for the block. */
+    gcsTASK_CONTAINER_PTR       container;
+
+    /* Pointer to the current task data within the container. */
+    gcsTASK_HEADER_PTR          task;
+
+    /* Pointer to the last link task within the container. */
+    gcsTASK_LINK_PTR            link;
+
+    /* Number of interrupts allocated for this block. */
+    gctUINT                     interruptCount;
+
+    /* The index of the current interrupt. */
+    gctUINT                     interruptIndex;
+
+    /* Interrupt semaphore. */
+    gctSEMAPHORE                interruptSemaphore;
+
+    /* Interrupt value array. */
+    gctINT32                    interruptArray[32];
+}
+gcsBLOCK_TASK_ENTRY;
+
+
+/******************************************************************************\
+********************* Command Queue Management Structures. *********************
+\******************************************************************************/
+
+/* Command queue kernel element pointer. */
+typedef struct _gcsKERNEL_CMDQUEUE * gcsKERNEL_CMDQUEUE_PTR;
+
+/* Command queue object handler function type. */
+typedef gceSTATUS (* gctOBJECT_HANDLER) (
+    gckVGKERNEL Kernel,
+    gcsKERNEL_CMDQUEUE_PTR Entry
+    );
+
+/* Command queue kernel element. */
+typedef struct _gcsKERNEL_CMDQUEUE
+{
+    /* The number of buffers in the queue. */
+    gcsCMDBUFFER_PTR            commandBuffer;
+
+    /* Pointer to the object handler function. */
+    gctOBJECT_HANDLER           handler;
+}
+gcsKERNEL_CMDQUEUE;
+
+/* Command queue header. */
+typedef struct _gcsKERNEL_QUEUE_HEADER * gcsKERNEL_QUEUE_HEADER_PTR;
+typedef struct _gcsKERNEL_QUEUE_HEADER
+{
+    /* The size of the buffer in bytes. */
+    gctUINT                     size;
+
+    /* The number of pending entries to be processed. */
+    volatile gctUINT            pending;
+
+    /* The current command queue entry. */
+    gcsKERNEL_CMDQUEUE_PTR      currentEntry;
+
+    /* Next buffer. */
+    gcsKERNEL_QUEUE_HEADER_PTR  next;
+}
+gcsKERNEL_QUEUE_HEADER;
+
+
+/******************************************************************************\
+******************************* gckVGCOMMAND Object *******************************
+\******************************************************************************/
+
+/* gckVGCOMMAND object. */
+struct _gckVGCOMMAND
+{
+    /***************************************************************************
+    ** Object data and pointers.
+    */
+
+    gcsOBJECT                   object;
+    gckVGKERNEL                 kernel;
+    gckOS                       os;
+    gckVGHARDWARE                   hardware;
+
+    /* Features. */
+    gctBOOL                     fe20;
+    gctBOOL                     vg20;
+    gctBOOL                     vg21;
+
+
+    /***************************************************************************
+    ** Enable command queue dumping.
+    */
+
+    gctBOOL                     enableDumping;
+
+
+    /***************************************************************************
+    ** Bus Error interrupt.
+    */
+
+    gctINT32                    busErrorInt;
+
+
+    /***************************************************************************
+    ** Command buffer information.
+    */
+
+    gcsCOMMAND_BUFFER_INFO      info;
+
+
+    /***************************************************************************
+    ** Synchronization objects.
+    */
+
+    gctPOINTER                  queueMutex;
+    gctPOINTER                  taskMutex;
+    gctPOINTER                  commitMutex;
+
+
+    /***************************************************************************
+    ** Task management.
+    */
+
+    /* The head of the storage buffer linked list. */
+    gcsTASK_STORAGE_PTR         taskStorage;
+
+    /* Allocation size. */
+    gctUINT                     taskStorageGranularity;
+    gctUINT                     taskStorageUsable;
+
+    /* The free container list. */
+    gcsTASK_CONTAINER_PTR       taskFreeHead;
+    gcsTASK_CONTAINER_PTR       taskFreeTail;
+
+    /* Task table */
+    gcsBLOCK_TASK_ENTRY         taskTable[gcvBLOCK_COUNT];
+
+
+    /***************************************************************************
+    ** Command queue.
+    */
+
+    /* Pointer to the allocated queue memory. */
+    gcsKERNEL_QUEUE_HEADER_PTR  queue;
+
+    /* Pointer to the current available queue from which new queue entries
+       will be allocated. */
+    gcsKERNEL_QUEUE_HEADER_PTR  queueHead;
+
+    /* If different from queueHead, points to the command queue which is
+       currently being executed by the hardware. */
+    gcsKERNEL_QUEUE_HEADER_PTR  queueTail;
+
+    /* Points to the queue to merge the tail with when the tail is processed. */
+    gcsKERNEL_QUEUE_HEADER_PTR  mergeQueue;
+
+    /* Queue overflow counter. */
+    gctUINT                     queueOverflow;
+
+
+    /***************************************************************************
+    ** Context.
+    */
+
+    /* Context counter used for unique ID. */
+    gctUINT64                   contextCounter;
+
+    /* Current context ID. */
+    gctUINT64                   currentContext;
+};
+
+/******************************************************************************\
+************************ gckVGCOMMAND Object Internal API. ***********************
+\******************************************************************************/
+
+/* Initialize architecture dependent command buffer information. */
+gceSTATUS
+gckVGCOMMAND_InitializeInfo(
+    IN gckVGCOMMAND Command
+    );
+
+/* Form a STATE command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_StateCommand(
+    IN gckVGCOMMAND Command,
+    IN gctUINT32 Pipe,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Address,
+    IN gctSIZE_T Count,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Form a RESTART command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_RestartCommand(
+    IN gckVGCOMMAND Command,
+    IN gctPOINTER Logical,
+    IN gctUINT32 FetchAddress,
+    IN gctUINT FetchCount,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Form a FETCH command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_FetchCommand(
+    IN gckVGCOMMAND Command,
+    IN gctPOINTER Logical,
+    IN gctUINT32 FetchAddress,
+    IN gctUINT FetchCount,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Form a CALL command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_CallCommand(
+    IN gckVGCOMMAND Command,
+    IN gctPOINTER Logical,
+    IN gctUINT32 FetchAddress,
+    IN gctUINT FetchCount,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Form a RETURN command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_ReturnCommand(
+    IN gckVGCOMMAND Command,
+    IN gctPOINTER Logical,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Form an EVENT command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_EventCommand(
+    IN gckVGCOMMAND Command,
+    IN gctPOINTER Logical,
+    IN gceBLOCK Block,
+    IN gctINT32 InterruptId,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Form an END command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_EndCommand(
+    IN gckVGCOMMAND Command,
+    IN gctPOINTER Logical,
+    IN gctINT32 InterruptId,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+#endif  /* __gc_hal_kernel_hardware_command_h_ */
+
diff --git a/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c b/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c
new file mode 100644 (file)
index 0000000..b5cd035
--- /dev/null
@@ -0,0 +1,1216 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+
+#if gcdENABLE_VG
+
+#define _GC_OBJ_ZONE    gcvZONE_HARDWARE
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+static gceSTATUS
+_IdentifyHardware(
+    IN gckOS Os,
+    OUT gceCHIPMODEL * ChipModel,
+    OUT gctUINT32 * ChipRevision,
+    OUT gctUINT32 * ChipFeatures,
+    OUT gctUINT32 * ChipMinorFeatures,
+    OUT gctUINT32 * ChipMinorFeatures2
+    )
+{
+    gceSTATUS status;
+    gctUINT32 chipIdentity;
+
+    do
+    {
+        /* Read chip identity register. */
+        gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG, 0x00018, &chipIdentity));
+
+        /* Special case for older graphic cores. */
+        if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
+        {
+            *ChipModel    = gcv500;
+            *ChipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
+        }
+
+        else
+        {
+            /* Read chip identity register. */
+            gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
+                                            0x00020,
+                                            (gctUINT32 *) ChipModel));
+
+            /* Read CHIP_REV register. */
+            gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
+                                            0x00024,
+                                            ChipRevision));
+        }
+
+        /* Read chip feature register. */
+        gcmkERR_BREAK(gckOS_ReadRegisterEx(
+            Os, gcvCORE_VG, 0x0001C, ChipFeatures
+            ));
+
+        /* Read chip minor feature register. */
+        gcmkERR_BREAK(gckOS_ReadRegisterEx(
+            Os, gcvCORE_VG, 0x00034, ChipMinorFeatures
+            ));
+
+        /* Read chip minor feature register #2. */
+        gcmkERR_BREAK(gckOS_ReadRegisterEx(
+            Os, gcvCORE_VG, 0x00074, ChipMinorFeatures2
+            ));
+
+        gcmkTRACE(
+            gcvLEVEL_VERBOSE,
+            "ChipModel=0x%08X\n"
+            "ChipRevision=0x%08X\n"
+            "ChipFeatures=0x%08X\n"
+            "ChipMinorFeatures=0x%08X\n"
+            "ChipMinorFeatures2=0x%08X\n",
+            *ChipModel,
+            *ChipRevision,
+            *ChipFeatures,
+            *ChipMinorFeatures,
+            *ChipMinorFeatures2
+            );
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    /* Return the status. */
+    return status;
+}
+
+/******************************************************************************\
+****************************** gckVGHARDWARE API code *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_Construct
+**
+**  Construct a new gckVGHARDWARE object.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an initialized gckOS object.
+**
+**  OUTPUT:
+**
+**      gckVGHARDWARE * Hardware
+**          Pointer to a variable that will hold the pointer to the gckVGHARDWARE
+**          object.
+*/
+gceSTATUS
+gckVGHARDWARE_Construct(
+    IN gckOS Os,
+    OUT gckVGHARDWARE * Hardware
+    )
+{
+    gckVGHARDWARE hardware;
+    gceSTATUS status;
+    gceCHIPMODEL chipModel;
+    gctUINT32 chipRevision;
+    gctUINT32 chipFeatures;
+    gctUINT32 chipMinorFeatures;
+    gctUINT32 chipMinorFeatures2;
+
+    gcmkHEADER_ARG("Os=0x%x Hardware=0x%x ", Os, Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
+
+    do
+    {
+        /* Identify the hardware. */
+        gcmkERR_BREAK(_IdentifyHardware(Os,
+            &chipModel, &chipRevision,
+            &chipFeatures, &chipMinorFeatures, &chipMinorFeatures2
+            ));
+
+        /* Allocate the gckVGHARDWARE object. */
+        gcmkERR_BREAK(gckOS_Allocate(Os,
+            gcmSIZEOF(struct _gckVGHARDWARE), (gctPOINTER *) &hardware
+            ));
+
+        /* Initialize the gckVGHARDWARE object. */
+        hardware->object.type = gcvOBJ_HARDWARE;
+        hardware->os = Os;
+
+        /* Set chip identity. */
+        hardware->chipModel          = chipModel;
+        hardware->chipRevision       = chipRevision;
+        hardware->chipFeatures       = chipFeatures;
+        hardware->chipMinorFeatures  = chipMinorFeatures;
+        hardware->chipMinorFeatures2 = chipMinorFeatures2;
+
+        /* Determine whether FE 2.0 is present. */
+        hardware->fe20 = ((((gctUINT32) (hardware->chipFeatures)) >> (0 ? 28:28) & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))) == (0x1  & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))));
+
+        /* Determine whether VG 2.0 is present. */
+        hardware->vg20 = ((((gctUINT32) (hardware->chipMinorFeatures)) >> (0 ? 13:13) & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1)))))) == (0x1  & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1)))))));
+
+        /* Determine whether VG 2.1 is present. */
+        hardware->vg21 = ((((gctUINT32) (hardware->chipMinorFeatures)) >> (0 ? 18:18) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))) == (0x1  & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))));
+
+        /* Set default event mask. */
+        hardware->eventMask = 0xFFFFFFFF;
+
+        /* Set fast clear to auto. */
+        gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(hardware, -1));
+
+        /* Return pointer to the gckVGHARDWARE object. */
+        *Hardware = hardware;
+
+        gcmkFOOTER_NO();
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return the status. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_Destroy
+**
+**  Destroy an gckVGHARDWARE object.
+**
+**  INPUT:
+**
+**      gckVGHARDWARE Hardware
+**          Pointer to the gckVGHARDWARE object that needs to be destroyed.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckVGHARDWARE_Destroy(
+    IN gckVGHARDWARE Hardware
+    )
+{
+    gceSTATUS status;
+    gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Mark the object as unknown. */
+    Hardware->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the object. */
+    status = gckOS_Free(Hardware->os, Hardware);
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_QueryMemory
+**
+**  Query the amount of memory available on the hardware.
+**
+**  INPUT:
+**
+**      gckVGHARDWARE Hardware
+**          Pointer to the gckVGHARDWARE object.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * InternalSize
+**          Pointer to a variable that will hold the size of the internal video
+**          memory in bytes.  If 'InternalSize' is gcvNULL, no information of the
+**          internal memory will be returned.
+**
+**      gctUINT32 * InternalBaseAddress
+**          Pointer to a variable that will hold the hardware's base address for
+**          the internal video memory.  This pointer cannot be gcvNULL if
+**          'InternalSize' is also non-gcvNULL.
+**
+**      gctUINT32 * InternalAlignment
+**          Pointer to a variable that will hold the hardware's base address for
+**          the internal video memory.  This pointer cannot be gcvNULL if
+**          'InternalSize' is also non-gcvNULL.
+**
+**      gctSIZE_T * ExternalSize
+**          Pointer to a variable that will hold the size of the external video
+**          memory in bytes.  If 'ExternalSize' is gcvNULL, no information of the
+**          external memory will be returned.
+**
+**      gctUINT32 * ExternalBaseAddress
+**          Pointer to a variable that will hold the hardware's base address for
+**          the external video memory.  This pointer cannot be gcvNULL if
+**          'ExternalSize' is also non-gcvNULL.
+**
+**      gctUINT32 * ExternalAlignment
+**          Pointer to a variable that will hold the hardware's base address for
+**          the external video memory.  This pointer cannot be gcvNULL if
+**          'ExternalSize' is also non-gcvNULL.
+**
+**      gctUINT32 * HorizontalTileSize
+**          Number of horizontal pixels per tile.  If 'HorizontalTileSize' is
+**          gcvNULL, no horizontal pixel per tile will be returned.
+**
+**      gctUINT32 * VerticalTileSize
+**          Number of vertical pixels per tile.  If 'VerticalTileSize' is
+**          gcvNULL, no vertical pixel per tile will be returned.
+*/
+gceSTATUS
+gckVGHARDWARE_QueryMemory(
+    IN gckVGHARDWARE Hardware,
+    OUT gctSIZE_T * InternalSize,
+    OUT gctUINT32 * InternalBaseAddress,
+    OUT gctUINT32 * InternalAlignment,
+    OUT gctSIZE_T * ExternalSize,
+    OUT gctUINT32 * ExternalBaseAddress,
+    OUT gctUINT32 * ExternalAlignment,
+    OUT gctUINT32 * HorizontalTileSize,
+    OUT gctUINT32 * VerticalTileSize
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x InternalSize=0x%x InternalBaseAddress=0x%x InternalAlignment=0x%x"
+        "ExternalSize=0x%x ExternalBaseAddress=0x%x ExternalAlignment=0x%x HorizontalTileSize=0x%x VerticalTileSize=0x%x",
+        Hardware, InternalSize, InternalBaseAddress, InternalAlignment,
+        ExternalSize, ExternalBaseAddress, ExternalAlignment, HorizontalTileSize, VerticalTileSize);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    if (InternalSize != gcvNULL)
+    {
+        /* No internal memory. */
+        *InternalSize = 0;
+    }
+
+    if (ExternalSize != gcvNULL)
+    {
+        /* No external memory. */
+        *ExternalSize = 0;
+    }
+
+    if (HorizontalTileSize != gcvNULL)
+    {
+        /* 4x4 tiles. */
+        *HorizontalTileSize = 4;
+    }
+
+    if (VerticalTileSize != gcvNULL)
+    {
+        /* 4x4 tiles. */
+        *VerticalTileSize = 4;
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_QueryChipIdentity
+**
+**  Query the identity of the hardware.
+**
+**  INPUT:
+**
+**      gckVGHARDWARE Hardware
+**          Pointer to the gckVGHARDWARE object.
+**
+**  OUTPUT:
+**
+**      gceCHIPMODEL * ChipModel
+**          If 'ChipModel' is not gcvNULL, the variable it points to will
+**          receive the model of the chip.
+**
+**      gctUINT32 * ChipRevision
+**          If 'ChipRevision' is not gcvNULL, the variable it points to will
+**          receive the revision of the chip.
+**
+**      gctUINT32 * ChipFeatures
+**          If 'ChipFeatures' is not gcvNULL, the variable it points to will
+**          receive the feature set of the chip.
+**
+**      gctUINT32 * ChipMinorFeatures
+**          If 'ChipMinorFeatures' is not gcvNULL, the variable it points to
+**          will receive the minor feature set of the chip.
+**
+**      gctUINT32 * ChipMinorFeatures2
+**          If 'ChipMinorFeatures2' is not gcvNULL, the variable it points to
+**          will receive the minor feature set of the chip.
+**
+*/
+gceSTATUS
+gckVGHARDWARE_QueryChipIdentity(
+    IN gckVGHARDWARE Hardware,
+    OUT gceCHIPMODEL * ChipModel,
+    OUT gctUINT32 * ChipRevision,
+    OUT gctUINT32* ChipFeatures,
+    OUT gctUINT32* ChipMinorFeatures,
+    OUT gctUINT32* ChipMinorFeatures2
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x ChipModel=0x%x ChipRevision=0x%x ChipFeatures = 0x%x ChipMinorFeatures = 0x%x ChipMinorFeatures2 = 0x%x",
+                   Hardware, ChipModel, ChipRevision, ChipFeatures, ChipMinorFeatures, ChipMinorFeatures2);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Return chip model. */
+    if (ChipModel != gcvNULL)
+    {
+        *ChipModel = Hardware->chipModel;
+    }
+
+    /* Return revision number. */
+    if (ChipRevision != gcvNULL)
+    {
+        *ChipRevision = Hardware->chipRevision;
+    }
+
+    /* Return feature set. */
+    if (ChipFeatures != gcvNULL)
+    {
+        gctUINT32 features = Hardware->chipFeatures;
+
+        if ((((((gctUINT32) (features)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+        {
+            features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (Hardware->allowFastClear) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+        }
+
+        /* Mark 2D pipe as available for GC500.0 since it did not have this *\
+        \* bit.                                                             */
+        if ((Hardware->chipModel == gcv500)
+        &&  (Hardware->chipRevision == 0)
+        )
+        {
+            features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
+        }
+
+        /* Mark 2D pipe as available for GC300 since it did not have this   *\
+        \* bit.                                                             */
+        if (Hardware->chipModel == gcv300)
+        {
+            features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
+        }
+
+        *ChipFeatures = features;
+    }
+
+    /* Return minor feature set. */
+    if (ChipMinorFeatures != gcvNULL)
+    {
+        *ChipMinorFeatures = Hardware->chipMinorFeatures;
+    }
+
+    /* Return minor feature set #2. */
+    if (ChipMinorFeatures2 != gcvNULL)
+    {
+        *ChipMinorFeatures2 = Hardware->chipMinorFeatures2;
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_ConvertFormat
+**
+**  Convert an API format to hardware parameters.
+**
+**  INPUT:
+**
+**      gckVGHARDWARE Hardware
+**          Pointer to the gckVGHARDWARE object.
+**
+**      gceSURF_FORMAT Format
+**          API format to convert.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * BitsPerPixel
+**          Pointer to a variable that will hold the number of bits per pixel.
+**
+**      gctUINT32 * BytesPerTile
+**          Pointer to a variable that will hold the number of bytes per tile.
+*/
+gceSTATUS
+gckVGHARDWARE_ConvertFormat(
+    IN gckVGHARDWARE Hardware,
+    IN gceSURF_FORMAT Format,
+    OUT gctUINT32 * BitsPerPixel,
+    OUT gctUINT32 * BytesPerTile
+    )
+{
+    gctUINT32 bitsPerPixel;
+    gctUINT32 bytesPerTile;
+
+    gcmkHEADER_ARG("Hardware=0x%x Format=0x%x BitsPerPixel=0x%x BytesPerTile = 0x%x",
+                   Hardware, Format, BitsPerPixel, BytesPerTile);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Dispatch on format. */
+    switch (Format)
+    {
+    case gcvSURF_A1:
+    case gcvSURF_L1:
+        /* 1-bpp format. */
+        bitsPerPixel  = 1;
+        bytesPerTile  = (1 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_A4:
+        /* 4-bpp format. */
+        bitsPerPixel  = 4;
+        bytesPerTile  = (4 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_INDEX8:
+    case gcvSURF_A8:
+    case gcvSURF_L8:
+        /* 8-bpp format. */
+        bitsPerPixel  = 8;
+        bytesPerTile  = (8 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_YV12:
+        /* 12-bpp planar YUV formats. */
+        bitsPerPixel  = 12;
+        bytesPerTile  = (12 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_NV12:
+        /* 12-bpp planar YUV formats. */
+        bitsPerPixel  = 12;
+        bytesPerTile  = (12 * 4 * 4) / 8;
+        break;
+
+    /* 4444 variations. */
+    case gcvSURF_X4R4G4B4:
+    case gcvSURF_A4R4G4B4:
+    case gcvSURF_R4G4B4X4:
+    case gcvSURF_R4G4B4A4:
+    case gcvSURF_B4G4R4X4:
+    case gcvSURF_B4G4R4A4:
+    case gcvSURF_X4B4G4R4:
+    case gcvSURF_A4B4G4R4:
+
+    /* 1555 variations. */
+    case gcvSURF_X1R5G5B5:
+    case gcvSURF_A1R5G5B5:
+    case gcvSURF_R5G5B5X1:
+    case gcvSURF_R5G5B5A1:
+    case gcvSURF_X1B5G5R5:
+    case gcvSURF_A1B5G5R5:
+    case gcvSURF_B5G5R5X1:
+    case gcvSURF_B5G5R5A1:
+
+    /* 565 variations. */
+    case gcvSURF_R5G6B5:
+    case gcvSURF_B5G6R5:
+
+    case gcvSURF_A8L8:
+    case gcvSURF_YUY2:
+    case gcvSURF_UYVY:
+    case gcvSURF_D16:
+        /* 16-bpp format. */
+        bitsPerPixel  = 16;
+        bytesPerTile  = (16 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_X8R8G8B8:
+    case gcvSURF_A8R8G8B8:
+    case gcvSURF_X8B8G8R8:
+    case gcvSURF_A8B8G8R8:
+    case gcvSURF_R8G8B8X8:
+    case gcvSURF_R8G8B8A8:
+    case gcvSURF_B8G8R8X8:
+    case gcvSURF_B8G8R8A8:
+    case gcvSURF_D32:
+        /* 32-bpp format. */
+        bitsPerPixel  = 32;
+        bytesPerTile  = (32 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_D24S8:
+        /* 24-bpp format. */
+        bitsPerPixel  = 32;
+        bytesPerTile  = (32 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_DXT1:
+    case gcvSURF_ETC1:
+        bitsPerPixel  = 4;
+        bytesPerTile  = (4 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_DXT2:
+    case gcvSURF_DXT3:
+    case gcvSURF_DXT4:
+    case gcvSURF_DXT5:
+        bitsPerPixel  = 8;
+        bytesPerTile  = (8 * 4 * 4) / 8;
+        break;
+
+    default:
+        /* Invalid format. */
+        return gcvSTATUS_INVALID_ARGUMENT;
+    }
+
+    /* Set the result. */
+    if (BitsPerPixel != gcvNULL)
+    {
+        * BitsPerPixel = bitsPerPixel;
+    }
+
+    if (BytesPerTile != gcvNULL)
+    {
+        * BytesPerTile = bytesPerTile;
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_SplitMemory
+**
+**  Split a hardware specific memory address into a pool and offset.
+**
+**  INPUT:
+**
+**      gckVGHARDWARE Hardware
+**          Pointer to the gckVGHARDWARE object.
+**
+**      gctUINT32 Address
+**          Address in hardware specific format.
+**
+**  OUTPUT:
+**
+**      gcePOOL * Pool
+**          Pointer to a variable that will hold the pool type for the address.
+**
+**      gctUINT32 * Offset
+**          Pointer to a variable that will hold the offset for the address.
+*/
+gceSTATUS
+gckVGHARDWARE_SplitMemory(
+    IN gckVGHARDWARE Hardware,
+    IN gctUINT32 Address,
+    OUT gcePOOL * Pool,
+    OUT gctUINT32 * Offset
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Pool=0x%x Offset = 0x%x",
+                   Hardware, Address, Pool, Offset);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
+
+    /* Dispatch on memory type. */
+    switch ((((((gctUINT32) (Address)) >> (0 ? 1:0)) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1)))))) ))
+    {
+    case 0x0:
+        /* System memory. */
+        *Pool = gcvPOOL_SYSTEM;
+        break;
+
+    case 0x2:
+        /* Virtual memory. */
+        *Pool = gcvPOOL_VIRTUAL;
+        break;
+
+    default:
+        /* Invalid memory type. */
+        return gcvSTATUS_INVALID_ARGUMENT;
+    }
+
+    /* Return offset of address. */
+    *Offset = ((((gctUINT32) (Address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_Execute
+**
+**  Kickstart the hardware's command processor with an initialized command
+**  buffer.
+**
+**  INPUT:
+**
+**      gckVGHARDWARE Hardware
+**          Pointer to the gckVGHARDWARE object.
+**
+**      gctUINT32 Address
+**          Address of the command buffer.
+**
+**      gctSIZE_T Count
+**          Number of command-sized data units to be executed.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckVGHARDWARE_Execute(
+    IN gckVGHARDWARE Hardware,
+    IN gctUINT32 Address,
+    IN gctSIZE_T Count
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Count=0x%x",
+                   Hardware, Address, Count);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    do
+    {
+        /* Enable all events. */
+        gcmkERR_BREAK(gckOS_WriteRegisterEx(
+            Hardware->os,
+            gcvCORE_VG,
+            0x00014,
+            Hardware->eventMask
+            ));
+
+        if (Hardware->fe20)
+        {
+            /* Write address register. */
+            gcmkERR_BREAK(gckOS_WriteRegisterEx(
+                Hardware->os,
+                gcvCORE_VG,
+                0x00500,
+                gcmFIXADDRESS(Address)
+                ));
+
+            /* Write control register. */
+            gcmkERR_BREAK(gckOS_WriteRegisterEx(
+                Hardware->os,
+                gcvCORE_VG,
+                0x00504,
+                Count
+                ));
+        }
+        else
+        {
+            /* Write address register. */
+            gcmkERR_BREAK(gckOS_WriteRegisterEx(
+                Hardware->os,
+                gcvCORE_VG,
+                0x00654,
+                gcmFIXADDRESS(Address)
+                ));
+
+            /* Write control register. */
+            gcmkERR_BREAK(gckOS_WriteRegisterEx(
+                Hardware->os,
+                gcvCORE_VG,
+                0x00658,
+                ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) |
+                ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+                ));
+        }
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+
+    gcmkFOOTER();
+    /* Return the status. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_AlignToTile
+**
+**  Align the specified width and height to tile boundaries.
+**
+**  INPUT:
+**
+**      gckVGHARDWARE Hardware
+**          Pointer to an gckVGHARDWARE object.
+**
+**      gceSURF_TYPE Type
+**          Type of alignment.
+**
+**      gctUINT32 * Width
+**          Pointer to the width to be aligned.  If 'Width' is gcvNULL, no width
+**          will be aligned.
+**
+**      gctUINT32 * Height
+**          Pointer to the height to be aligned.  If 'Height' is gcvNULL, no height
+**          will be aligned.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Width
+**          Pointer to a variable that will receive the aligned width.
+**
+**      gctUINT32 * Height
+**          Pointer to a variable that will receive the aligned height.
+*/
+gceSTATUS
+gckVGHARDWARE_AlignToTile(
+    IN gckVGHARDWARE Hardware,
+    IN gceSURF_TYPE Type,
+    IN OUT gctUINT32 * Width,
+    IN OUT gctUINT32 * Height
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x Type=0x%x Width=0x%x Height=0x%x",
+                   Hardware, Type, Width, Height);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    if (Width != gcvNULL)
+    {
+        /* Align the width. */
+        *Width = gcmALIGN(*Width, (Type == gcvSURF_TEXTURE) ? 4 : 16);
+    }
+
+    if (Height != gcvNULL)
+    {
+        /* Special case for VG images. */
+        if ((*Height == 0) && (Type == gcvSURF_IMAGE))
+        {
+            *Height = 4;
+        }
+        else
+        {
+            /* Align the height. */
+            *Height = gcmALIGN(*Height, 4);
+        }
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_ConvertLogical
+**
+**  Convert a logical system address into a hardware specific address.
+**
+**  INPUT:
+**
+**      gckVGHARDWARE Hardware
+**          Pointer to an gckVGHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Logical address to convert.
+**
+**      gctUINT32* Address
+**          Return hardware specific address.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckVGHARDWARE_ConvertLogical(
+    IN gckVGHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    OUT gctUINT32 * Address
+    )
+{
+    gctUINT32 address;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Address=0x%x",
+                   Hardware, Logical, Address);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    do
+    {
+        /* Convert logical address into a physical address. */
+        gcmkERR_BREAK(gckOS_GetPhysicalAddress(
+            Hardware->os, Logical, &address
+            ));
+
+        /* Return hardware specific address. */
+        *Address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return the status. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_QuerySystemMemory
+**
+**  Query the command buffer alignment and number of reserved bytes.
+**
+**  INPUT:
+**
+**      gckVGHARDWARE Harwdare
+**          Pointer to an gckVGHARDWARE object.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * SystemSize
+**          Pointer to a variable that receives the maximum size of the system
+**          memory.
+**
+**      gctUINT32 * SystemBaseAddress
+**          Poinetr to a variable that receives the base address for system
+**          memory.
+*/
+gceSTATUS gckVGHARDWARE_QuerySystemMemory(
+    IN gckVGHARDWARE Hardware,
+    OUT gctSIZE_T * SystemSize,
+    OUT gctUINT32 * SystemBaseAddress
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x SystemSize=0x%x SystemBaseAddress=0x%x",
+                   Hardware, SystemSize, SystemBaseAddress);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    if (SystemSize != gcvNULL)
+    {
+        /* Maximum system memory can be 2GB. */
+        *SystemSize = (gctSIZE_T)(1 << 31);
+    }
+
+    if (SystemBaseAddress != gcvNULL)
+    {
+        /* Set system memory base address. */
+        *SystemBaseAddress = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_SetMMU
+**
+**  Set the page table base address.
+**
+**  INPUT:
+**
+**      gckVGHARDWARE Harwdare
+**          Pointer to an gckVGHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Logical address of the page table.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS gckVGHARDWARE_SetMMU(
+    IN gckVGHARDWARE Hardware,
+    IN gctPOINTER Logical
+    )
+{
+    gceSTATUS status;
+    gctUINT32 address = 0;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x",
+                   Hardware, Logical);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+    do
+    {
+        /* Convert the logical address into an hardware address. */
+        gcmkERR_BREAK(gckVGHARDWARE_ConvertLogical(Hardware, Logical, &address) );
+
+        /* Write the AQMemoryFePageTable register. */
+        gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+                                      0x00400,
+                                      gcmFIXADDRESS(address)) );
+
+        /* Write the AQMemoryTxPageTable register. */
+        gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+                                      0x00404,
+                                      gcmFIXADDRESS(address)) );
+
+        /* Write the AQMemoryPePageTable register. */
+        gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+                                      0x00408,
+                                      gcmFIXADDRESS(address)) );
+
+        /* Write the AQMemoryPezPageTable register. */
+        gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+                                      0x0040C,
+                                      gcmFIXADDRESS(address)) );
+
+        /* Write the AQMemoryRaPageTable register. */
+        gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+                                      0x00410,
+                                      gcmFIXADDRESS(address)) );
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return the status. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_FlushMMU
+**
+**  Flush the page table.
+**
+**  INPUT:
+**
+**      gckVGHARDWARE Harwdare
+**          Pointer to an gckVGHARDWARE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS gckVGHARDWARE_FlushMMU(
+    IN gckVGHARDWARE Hardware
+    )
+{
+    gceSTATUS status;
+    gckVGCOMMAND command;
+
+    gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    do
+    {
+        gcsCMDBUFFER_PTR commandBuffer;
+        gctUINT32_PTR buffer;
+
+        /* Create a shortcut to the command buffer object. */
+        command = Hardware->kernel->command;
+
+        /* Allocate command buffer space. */
+        gcmkERR_BREAK(gckVGCOMMAND_Allocate(
+            Hardware->kernel->command, 8, &commandBuffer, (gctPOINTER *) &buffer
+            ));
+
+        buffer[0]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E04) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+        buffer[1]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+
+        gcmkERR_BREAK(gckVGCOMMAND_Execute(
+            Hardware->kernel->command,
+            commandBuffer
+            ));
+    }
+    while(gcvFALSE);
+    gcmkFOOTER();
+    /* Return the status. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVGHARDWARE_BuildVirtualAddress
+**
+**  Build a virtual address.
+**
+**  INPUT:
+**
+**      gckVGHARDWARE Harwdare
+**          Pointer to an gckVGHARDWARE object.
+**
+**      gctUINT32 Index
+**          Index into page table.
+**
+**      gctUINT32 Offset
+**          Offset into page.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Address
+**          Pointer to a variable receiving te hardware address.
+*/
+gceSTATUS gckVGHARDWARE_BuildVirtualAddress(
+    IN gckVGHARDWARE Hardware,
+    IN gctUINT32 Index,
+    IN gctUINT32 Offset,
+    OUT gctUINT32 * Address
+    )
+{
+    gctUINT32 address;
+
+    gcmkHEADER_ARG("Hardware=0x%x Index=0x%x Offset=0x%x Address=0x%x",
+                   Hardware, Index, Offset, Address);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    /* Build virtual address. */
+    address = (Index << 12) | Offset;
+
+    /* Set virtual type. */
+    address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+
+    /* Set the result. */
+    *Address = address;
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVGHARDWARE_GetIdle(
+    IN gckVGHARDWARE Hardware,
+    OUT gctUINT32 * Data
+    )
+{
+    gceSTATUS status;
+    gcmkHEADER_ARG("Hardware=0x%x Data=0x%x", Hardware, Data);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+    /* Read register and return. */
+    status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, Data);
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckVGHARDWARE_SetFastClear(
+    IN gckVGHARDWARE Hardware,
+    IN gctINT Enable
+    )
+{
+    gctUINT32 debug;
+    gceSTATUS status;
+
+    if (!(((((gctUINT32) (Hardware->chipFeatures)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+    {
+        return gcvSTATUS_OK;
+    }
+
+    do
+    {
+        if (Enable == -1)
+        {
+            Enable = (Hardware->chipModel > gcv500) ||
+                ((Hardware->chipModel == gcv500) && (Hardware->chipRevision >= 3));
+        }
+
+        gcmkERR_BREAK(gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
+                                        0x00414,
+                    &debug));
+
+        debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20)));
+
+#ifdef AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION
+        debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1) == 32) ? ~0 : (~(~0 << ((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1))))))) << (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1) == 32) ? ~0 : (~(~0 << ((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1))))))) << (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION)));
+#endif
+
+        gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+                                     0x00414,
+                     debug));
+
+        Hardware->allowFastClear = Enable;
+
+        status = gcvFALSE;
+    }
+    while (gcvFALSE);
+
+    return status;
+}
+
+gceSTATUS
+gckVGHARDWARE_ReadInterrupt(
+    IN gckVGHARDWARE Hardware,
+    OUT gctUINT32_PTR IDs
+    )
+{
+    gceSTATUS status;
+    gcmkHEADER_ARG("Hardware=0x%x IDs=0x%x", Hardware, IDs);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(IDs != gcvNULL);
+
+    /* Read AQIntrAcknowledge register. */
+    status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
+                              0x00010,
+                              IDs);
+    gcmkFOOTER();
+    return status;
+}
+
+#endif /* gcdENABLE_VG */
+
diff --git a/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h b/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h
new file mode 100644 (file)
index 0000000..f7300bb
--- /dev/null
@@ -0,0 +1,59 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+
+
+#ifndef __gc_hal_kernel_hardware_vg_h_
+#define __gc_hal_kernel_hardware_vg_h_
+
+/* gckHARDWARE object. */
+struct _gckVGHARDWARE
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gckKERNEL object. */
+    gckVGKERNEL                 kernel;
+
+    /* Pointer to gckOS object. */
+    gckOS                       os;
+
+    /* Chip characteristics. */
+    gceCHIPMODEL                chipModel;
+    gctUINT32                   chipRevision;
+    gctUINT32                   chipFeatures;
+    gctUINT32                   chipMinorFeatures;
+    gctUINT32                   chipMinorFeatures2;
+    gctBOOL                     allowFastClear;
+
+    /* Features. */
+    gctBOOL                     fe20;
+    gctBOOL                     vg20;
+    gctBOOL                     vg21;
+
+    /* Event mask. */
+    gctUINT32                   eventMask;
+};
+
+#endif /* __gc_hal_kernel_hardware_h_ */
+
diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c
new file mode 100644 (file)
index 0000000..2f0c982
--- /dev/null
@@ -0,0 +1,1538 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_context.h"
+#include "gc_hal_kernel_buffer.h"
+
+/******************************************************************************\
+******************************** Debugging Macro *******************************
+\******************************************************************************/
+
+/* Zone used for header/footer. */
+#define _GC_OBJ_ZONE    gcvZONE_HARDWARE
+
+
+/******************************************************************************\
+************************** Context State Buffer Helpers ************************
+\******************************************************************************/
+
+#define _STATE(reg)                                                            \
+    _State(\
+        Context, index, \
+        reg ## _Address >> 2, \
+        reg ## _ResetValue, \
+        reg ## _Count, \
+        gcvFALSE, gcvFALSE                                                     \
+        )
+
+#define _STATE_COUNT(reg, count)                                               \
+    _State(\
+        Context, index, \
+        reg ## _Address >> 2, \
+        reg ## _ResetValue, \
+        count, \
+        gcvFALSE, gcvFALSE                                                     \
+        )
+
+#define _STATE_COUNT_OFFSET(reg, offset, count)                                \
+    _State(\
+        Context, index, \
+        (reg ## _Address >> 2) + offset, \
+        reg ## _ResetValue, \
+        count, \
+        gcvFALSE, gcvFALSE                                                     \
+        )
+
+#define _STATE_HINT(reg)                                                       \
+    _State(\
+        Context, index, \
+        reg ## _Address >> 2, \
+        reg ## _ResetValue, \
+        reg ## _Count, \
+        gcvFALSE, gcvTRUE                                                      \
+        )
+
+#define _STATE_HINT_BLOCK(reg, block, count)                                   \
+    _State(\
+        Context, index, \
+        (reg ## _Address >> 2) + (block << reg ## _BLK), \
+        reg ## _ResetValue, \
+        count, \
+        gcvFALSE, gcvTRUE                                                      \
+        )
+
+#define _STATE_X(reg)                                                          \
+    _State(\
+        Context, index, \
+        reg ## _Address >> 2, \
+        reg ## _ResetValue, \
+        reg ## _Count, \
+        gcvTRUE, gcvFALSE                                                      \
+        )
+
+#define _CLOSE_RANGE()                                                         \
+    _TerminateStateBlock(Context, index)
+
+#define _ENABLE(reg, field)                                                    \
+    do                                                                         \
+    {                                                                          \
+        if (gcmVERIFYFIELDVALUE(data, reg, MASK_ ## field, ENABLED))           \
+        {                                                                      \
+            enable |= gcmFIELDMASK(reg, field);                                \
+        }                                                                      \
+    }                                                                          \
+    while (gcvFALSE)
+
+#define _BLOCK_COUNT(reg)                                                      \
+    ((reg ## _Count) >> (reg ## _BLK))
+
+
+/******************************************************************************\
+*********************** Support Functions and Definitions **********************
+\******************************************************************************/
+
+#define gcdSTATE_MASK \
+    (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | 0xC0FFEE)
+
+#if !defined(VIVANTE_NO_3D)
+static gctSIZE_T
+_TerminateStateBlock(
+    IN gckCONTEXT Context,
+    IN gctSIZE_T Index
+    )
+{
+    gctUINT32_PTR buffer;
+    gctSIZE_T align;
+
+    /* Determine if we need alignment. */
+    align = (Index & 1) ? 1 : 0;
+
+    /* Address correct index. */
+    buffer = (Context->buffer == gcvNULL)
+        ? gcvNULL
+        : Context->buffer->logical;
+
+    /* Flush the current state block; make sure no pairing with the states
+       to follow happens. */
+    if (align && (buffer != gcvNULL))
+    {
+        buffer[Index] = 0xDEADDEAD;
+    }
+
+    /* Reset last address. */
+    Context->lastAddress = ~0U;
+
+    /* Return alignment requirement. */
+    return align;
+}
+#endif
+
+
+static gctSIZE_T
+_FlushPipe(
+    IN gckCONTEXT Context,
+    IN gctSIZE_T Index,
+    IN gcePIPE_SELECT Pipe
+    )
+{
+    if (Context->buffer != gcvNULL)
+    {
+        gctUINT32_PTR buffer;
+
+        /* Address correct index. */
+        buffer = Context->buffer->logical + Index;
+
+        /* Flush the current pipe. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        *buffer++
+            = (Pipe == gcvPIPE_2D)
+                ?   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
+                :   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+                  | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+                  | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)));
+
+        /* Semaphore from FE to PE. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+        /* Stall from FE to PE. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+        *buffer
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+    }
+
+    /* Flushing 3D pipe takes 6 slots. */
+    return 6;
+}
+
+static gctSIZE_T
+_SwitchPipe(
+    IN gckCONTEXT Context,
+    IN gctSIZE_T Index,
+    IN gcePIPE_SELECT Pipe
+    )
+{
+    if (Context->buffer != gcvNULL)
+    {
+        gctUINT32_PTR buffer;
+
+        /* Address correct index. */
+        buffer = Context->buffer->logical + Index;
+
+        /* LoadState(AQPipeSelect, 1), pipe. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+        *buffer
+            = (Pipe == gcvPIPE_2D)
+                ? 0x1
+                : 0x0;
+    }
+
+    return 2;
+}
+
+#if !defined(VIVANTE_NO_3D)
+static gctSIZE_T
+_State(
+    IN gckCONTEXT Context,
+    IN gctSIZE_T Index,
+    IN gctUINT32 Address,
+    IN gctUINT32 Value,
+    IN gctSIZE_T Size,
+    IN gctBOOL FixedPoint,
+    IN gctBOOL Hinted
+    )
+{
+    gctUINT32_PTR buffer;
+    gctSIZE_T align, i;
+
+    /* Determine if we need alignment. */
+    align = (Index & 1) ? 1 : 0;
+
+    /* Address correct index. */
+    buffer = (Context->buffer == gcvNULL)
+        ? gcvNULL
+        : Context->buffer->logical;
+
+    if ((buffer == gcvNULL) && (Address + Size > Context->stateCount))
+    {
+        /* Determine maximum state. */
+        Context->stateCount = Address + Size;
+    }
+
+    /* Do we need a new entry? */
+    if ((Address != Context->lastAddress) || (FixedPoint != Context->lastFixed))
+    {
+        if (buffer != gcvNULL)
+        {
+            if (align)
+            {
+                /* Add filler. */
+                buffer[Index++] = 0xDEADDEAD;
+            }
+
+            /* LoadState(Address, Count). */
+            gcmkASSERT((Index & 1) == 0);
+
+            if (FixedPoint)
+            {
+                buffer[Index]
+                    = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                    | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) << (0 ? 26:26))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) << (0 ? 26:26)))
+                    | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Size) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+                    | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+            }
+            else
+            {
+                buffer[Index]
+                    = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                    | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) << (0 ? 26:26))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) << (0 ? 26:26)))
+                    | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Size) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+                    | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+            }
+
+            /* Walk all the states. */
+            for (i = 0; i < Size; i += 1)
+            {
+                /* Set state to uninitialized value. */
+                buffer[Index + 1 + i] = Value;
+
+                /* Set index in state mapping table. */
+                Context->map[Address + i].index = Index + 1 + i;
+
+#if gcdSECURE_USER
+                /* Save hint. */
+                if (Context->hint != gcvNULL)
+                {
+                    Context->hint[Address + i] = Hinted;
+                }
+#endif
+            }
+        }
+
+        /* Save information for this LoadState. */
+        Context->lastIndex   = Index;
+        Context->lastAddress = Address + Size;
+        Context->lastSize    = Size;
+        Context->lastFixed   = FixedPoint;
+
+        /* Return size for load state. */
+        return align + 1 + Size;
+    }
+
+    /* Append this state to the previous one. */
+    if (buffer != gcvNULL)
+    {
+        /* Update last load state. */
+        buffer[Context->lastIndex] =
+            ((((gctUINT32) (buffer[Context->lastIndex])) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Context->lastSize + Size) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+        /* Walk all the states. */
+        for (i = 0; i < Size; i += 1)
+        {
+            /* Set state to uninitialized value. */
+            buffer[Index + i] = Value;
+
+            /* Set index in state mapping table. */
+            Context->map[Address + i].index = Index + i;
+
+#if gcdSECURE_USER
+            /* Save hint. */
+            if (Context->hint != gcvNULL)
+            {
+                Context->hint[Address + i] = Hinted;
+            }
+#endif
+        }
+    }
+
+    /* Update last address and size. */
+    Context->lastAddress += Size;
+    Context->lastSize    += Size;
+
+    /* Return number of slots required. */
+    return Size;
+}
+#endif
+
+static gceSTATUS
+_InitializeContextBuffer(
+    IN gckCONTEXT Context
+    )
+{
+    gctUINT32_PTR buffer;
+    gctSIZE_T index;
+
+#if !defined(VIVANTE_NO_3D)
+    gctINT i;
+    gctUINT vertexUniforms, fragmentUniforms;
+    gctUINT fe2vsCount;
+#endif
+
+    /* Reset the buffer index. */
+    index = 0;
+
+    /* Reset the last state address. */
+    Context->lastAddress = ~0U;
+
+    /* Get the buffer pointer. */
+    buffer = (Context->buffer == gcvNULL)
+        ? gcvNULL
+        : Context->buffer->logical;
+
+
+    /**************************************************************************/
+    /* Build 2D states. *******************************************************/
+
+
+#if !defined(VIVANTE_NO_3D)
+    /**************************************************************************/
+    /* Build 3D states. *******************************************************/
+
+    /* Query shader support. */
+    gcmkVERIFY_OK(gckHARDWARE_QueryShaderCaps(
+        Context->hardware, &vertexUniforms, &fragmentUniforms, gcvNULL));
+
+    /* Store the 3D entry index. */
+    Context->entryOffset3D = index * gcmSIZEOF(gctUINT32);
+
+    /* Flush 2D pipe. */
+    index += _FlushPipe(Context, index, gcvPIPE_2D);
+
+    /* Switch to 3D pipe. */
+    index += _SwitchPipe(Context, index, gcvPIPE_3D);
+
+    /* Current context pointer. */
+#if gcdDEBUG && 1
+    index += _State(Context, index, 0x03850 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+#endif
+
+    /* Global states. */
+    index += _State(Context, index, 0x03814 >> 2, 0x00000001, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x03818 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x0381C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x03820 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x03828 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x0382C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    /* Front End states. */
+       fe2vsCount = 12;
+       if ((((((gctUINT32) (Context->hardware->chipMinorFeatures1)) >> (0 ? 23:23)) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1)))))) ))
+       {
+               fe2vsCount = 16;
+       }
+    index += _State(Context, index, 0x00600 >> 2, 0x00000000, fe2vsCount, gcvFALSE, gcvFALSE);
+    index += _CLOSE_RANGE();
+
+    index += _State(Context, index, 0x00644 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x00648 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x0064C >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x00650 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00680 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x006A0 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00670 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    /* Vertex Shader states. */
+    index += _State(Context, index, 0x00800 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00804 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00808 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x0080C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00810 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00820 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00830 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00838 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x04000 >> 2, 0x00000000, 1024, gcvFALSE, gcvFALSE);
+
+    index += _CLOSE_RANGE();
+    index += _State(Context, index, 0x05000 >> 2, 0x00000000, vertexUniforms * 4, gcvFALSE, gcvFALSE);
+
+    index += _State(Context, index, 0x00850 >> 2, 0x000003E8, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00854 >> 2, 0x00000100, 1, gcvFALSE, gcvFALSE);
+
+    /* Primitive Assembly states. */
+    index += _State(Context, index, 0x00A00 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+    index += _State(Context, index, 0x00A04 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+    index += _State(Context, index, 0x00A08 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00A0C >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+    index += _State(Context, index, 0x00A10 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+    index += _State(Context, index, 0x00A14 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00A18 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00A1C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00A28 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00A2C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00A30 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00A40 >> 2, 0x00000000, 10, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00A34 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    /* Setup states. */
+    index += _State(Context, index, 0x00C00 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+    index += _State(Context, index, 0x00C04 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+    index += _State(Context, index, 0x00C08 >> 2, 0x45000000, 1, gcvTRUE, gcvFALSE);
+    index += _State(Context, index, 0x00C0C >> 2, 0x45000000, 1, gcvTRUE, gcvFALSE);
+    index += _State(Context, index, 0x00C10 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00C14 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00C18 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    /* Raster states. */
+    index += _State(Context, index, 0x00E00 >> 2, 0x00000001, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00E10 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00E04 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00E40 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00E08 >> 2, 0x00000031, 1, gcvFALSE, gcvFALSE);
+
+    /* Pixel Shader states. */
+    index += _State(Context, index, 0x01000 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01004 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01008 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x0100C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01010 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01018 >> 2, 0x01000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x06000 >> 2, 0x00000000, 1024, gcvFALSE, gcvFALSE);
+
+    index += _CLOSE_RANGE();
+    index += _State(Context, index, 0x07000 >> 2, 0x00000000, fragmentUniforms * 4, gcvFALSE, gcvFALSE);
+
+    /* Texture states. */
+    index += _State(Context, index, 0x02000 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x02040 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x02080 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x020C0 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x02100 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x02140 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x02400 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x02440 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x02480 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x024C0 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x02500 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x02540 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x02580 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x025C0 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x02600 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x02640 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x02680 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x026C0 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x02700 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x02740 >> 2, 0x00000000, 12, gcvFALSE, gcvTRUE);
+    index += _CLOSE_RANGE();
+
+    if ((((((gctUINT32) (Context->hardware->chipMinorFeatures2)) >> (0 ? 11:11)) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1)))))) ))
+    {
+        /* New texture block. */
+        index += _State(Context, index, 0x10000 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10080 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10100 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10180 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10200 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10280 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10300 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10380 >> 2, 0x00321000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10400 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10480 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x12000 >> 2, 0x00000000, 256, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x12400 >> 2, 0x00000000, 256, gcvFALSE, gcvFALSE);
+
+        for (i = 0; i < (512 >> (4)); i += 1)
+        {
+            index += _State(Context, index, ((0x10800 >> 2) + (i << 4)), 0x00000000, 14, gcvFALSE, gcvTRUE);
+        }
+    }
+
+    /* YUV. */
+    index += _State(Context, index, 0x01678 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x0167C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01680 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x01684 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01688 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x0168C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01690 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x01694 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01698 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x0169C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _CLOSE_RANGE();
+
+    index += _State(Context, index, 0x016A4 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x016A8 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _CLOSE_RANGE();
+
+    /* Thread walker states. */
+    index += _State(Context, index, 0x00900 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00904 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00908 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x0090C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00910 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00914 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00918 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x0091C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _CLOSE_RANGE();
+
+       if (Context->hardware->instructionCount >= 2048)
+       {
+               /* New Shader instruction memory. */
+               index += _State(Context, index, 0x0085C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+               index += _State(Context, index, 0x0101C >> 2, 0x00000100, 1, gcvFALSE, gcvFALSE);
+               index += _State(Context, index, 0x00860 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+               index += _CLOSE_RANGE();
+
+               for (i = 0; i < 8192; i += 1024)
+               {
+                       index += _State(Context, index, (0x20000 >> 2) + i, 0x00000000, 1024, gcvFALSE, gcvFALSE);
+                       index += _CLOSE_RANGE();
+               }
+       }
+       else if (Context->hardware->instructionCount >= 1024)
+       {
+               /* VX instruction memory. */
+               for (i = 0; i < 4096; i += 1024)
+               {
+                       index += _State(Context, index, (0x0C000 >> 2) + i, 0x00000000, 1024, gcvFALSE, gcvFALSE);
+                       index += _CLOSE_RANGE();
+               }
+
+               for (i = 0; i < 4096; i += 1024)
+               {
+                       index += _State(Context, index, (0x08000 >> 2) + i, 0x00000000, 1024, gcvFALSE, gcvFALSE);
+                       index += _CLOSE_RANGE();
+               }
+       }
+
+    /* Store the index of the "XD" entry. */
+    Context->entryOffsetXDFrom3D = index * gcmSIZEOF(gctUINT32);
+
+    index += _FlushPipe(Context, index, gcvPIPE_3D);
+
+    /* Pixel Engine states. */
+    index += _State(Context, index, 0x01400 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01404 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01408 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x0140C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    index += _State(Context, index, 0x01414 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01418 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x0141C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01420 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01424 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01428 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x0142C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    /* Composition states. */
+    index += _State(Context, index, 0x03008 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    if (Context->hardware->pixelPipes == 1)
+    {
+        index += _State(Context, index, 0x01430 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+        index += _State(Context, index, 0x01410 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    }
+    else
+    {
+        index += _State(Context, index, ((0x01460 >> 2) + (0 << 3)), 0x00000000, Context->hardware->pixelPipes , gcvFALSE, gcvTRUE);
+
+        index += _State(Context, index, ((0x01480 >> 2) + (0 << 3)), 0x00000000, Context->hardware->pixelPipes , gcvFALSE, gcvTRUE);
+    }
+
+    index += _State(Context, index, 0x01434 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01454 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01458 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x0145C >> 2, 0x00000010, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x014A8 >> 2, 0xFFFFFFFF, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x014AC >> 2, 0xFFFFFFFF, 1, gcvFALSE, gcvFALSE);
+
+    /* Resolve states. */
+    index += _State(Context, index, 0x01604 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01608 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x0160C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01610 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x01614 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01620 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01630 >> 2, 0x00000000, 2, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x01640 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x0163C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x016A0 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _CLOSE_RANGE();
+
+    /* Tile status. */
+    index += _State(Context, index, 0x01654 >> 2, 0x00200000, 1, gcvFALSE, gcvFALSE);
+
+    index += _CLOSE_RANGE();
+    index += _State(Context, index, 0x01658 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+
+    index += _CLOSE_RANGE();
+    index += _State(Context, index, 0x0165C >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x01660 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    index += _CLOSE_RANGE();
+    index += _State(Context, index, 0x01664 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+
+    index += _CLOSE_RANGE();
+    index += _State(Context, index, 0x01668 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x0166C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _CLOSE_RANGE();
+#endif
+
+    /**************************************************************************/
+    /* Link to another address. ***********************************************/
+
+    Context->linkIndex3D = index;
+
+    if (buffer != gcvNULL)
+    {
+        buffer[index + 0]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        buffer[index + 1]
+            = 0;
+    }
+
+    index += 2;
+
+    /* Store the end of the context buffer. */
+    Context->bufferSize = index * gcmSIZEOF(gctUINT32);
+
+
+    /**************************************************************************/
+    /* Pipe switch for the case where neither 2D nor 3D are used. *************/
+
+    /* Store the 3D entry index. */
+    Context->entryOffsetXDFrom2D = index * gcmSIZEOF(gctUINT32);
+
+    /* Flush 2D pipe. */
+    index += _FlushPipe(Context, index, gcvPIPE_2D);
+
+    /* Switch to 3D pipe. */
+    index += _SwitchPipe(Context, index, gcvPIPE_3D);
+
+    /* Store the location of the link. */
+    Context->linkIndexXD = index;
+
+    if (buffer != gcvNULL)
+    {
+        buffer[index + 0]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        buffer[index + 1]
+            = 0;
+    }
+
+    index += 2;
+
+
+    /**************************************************************************/
+    /* Save size for buffer. **************************************************/
+
+    Context->totalSize = index * gcmSIZEOF(gctUINT32);
+
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_DestroyContext(
+    IN gckCONTEXT Context
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+
+    if (Context != gcvNULL)
+    {
+        gcsCONTEXT_PTR bufferHead;
+
+        /* Free context buffers. */
+        for (bufferHead = Context->buffer; Context->buffer != gcvNULL;)
+        {
+            /* Get a shortcut to the current buffer. */
+            gcsCONTEXT_PTR buffer = Context->buffer;
+
+            /* Get the next buffer. */
+            gcsCONTEXT_PTR next = buffer->next;
+
+            /* Last item? */
+            if (next == bufferHead)
+            {
+                next = gcvNULL;
+            }
+
+            /* Destroy the signal. */
+            if (buffer->signal != gcvNULL)
+            {
+                gcmkONERROR(gckOS_DestroySignal(
+                    Context->os, buffer->signal
+                    ));
+
+                buffer->signal = gcvNULL;
+            }
+
+            /* Free state delta map. */
+            if (buffer->logical != gcvNULL)
+            {
+                gcmkONERROR(gckOS_FreeContiguous(
+                    Context->os,
+                    buffer->physical,
+                    buffer->logical,
+                    Context->totalSize
+                    ));
+
+                buffer->logical = gcvNULL;
+            }
+
+            /* Free context buffer. */
+            gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, buffer));
+
+            /* Remove from the list. */
+            Context->buffer = next;
+        }
+
+#if gcdSECURE_USER
+        /* Free the hint array. */
+        if (Context->hint != gcvNULL)
+        {
+            gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->hint));
+        }
+#endif
+        /* Free record array copy. */
+        if (Context->recordArray != gcvNULL)
+        {
+            gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->recordArray));
+        }
+
+        /* Free the state mapping. */
+        if (Context->map != gcvNULL)
+        {
+            gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->map));
+        }
+
+        /* Mark the gckCONTEXT object as unknown. */
+        Context->object.type = gcvOBJ_UNKNOWN;
+
+        /* Free the gckCONTEXT object. */
+        gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context));
+    }
+
+OnError:
+    return status;
+}
+
+
+/******************************************************************************\
+**************************** Context Management API ****************************
+\******************************************************************************/
+
+/******************************************************************************\
+**
+**  gckCONTEXT_Construct
+**
+**  Construct a new gckCONTEXT object.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to gckOS object.
+**
+**      gctUINT32 ProcessID
+**          Current process ID.
+**
+**      gckHARDWARE Hardware
+**          Pointer to gckHARDWARE object.
+**
+**  OUTPUT:
+**
+**      gckCONTEXT * Context
+**          Pointer to a variable thet will receive the gckCONTEXT object
+**          pointer.
+*/
+gceSTATUS
+gckCONTEXT_Construct(
+    IN gckOS Os,
+    IN gckHARDWARE Hardware,
+    IN gctUINT32 ProcessID,
+    OUT gckCONTEXT * Context
+    )
+{
+    gceSTATUS status;
+    gckCONTEXT context = gcvNULL;
+    gctSIZE_T allocationSize;
+    gctUINT i;
+    gctPOINTER pointer = gcvNULL;
+
+    gcmkHEADER_ARG("Os=0x%08X Hardware=0x%08X", Os, Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Context != gcvNULL);
+
+
+    /**************************************************************************/
+    /* Allocate and initialize basic fields of gckCONTEXT. ********************/
+
+    /* The context object size. */
+    allocationSize = gcmSIZEOF(struct _gckCONTEXT);
+
+    /* Allocate the object. */
+    gcmkONERROR(gckOS_Allocate(
+        Os, allocationSize, &pointer
+        ));
+
+    context = pointer;
+
+    /* Reset the entire object. */
+    gcmkONERROR(gckOS_ZeroMemory(context, allocationSize));
+
+    /* Initialize the gckCONTEXT object. */
+    context->object.type = gcvOBJ_CONTEXT;
+    context->os          = Os;
+    context->hardware    = Hardware;
+
+
+#if defined(VIVANTE_NO_3D)
+    context->entryPipe = gcvPIPE_2D;
+    context->exitPipe  = gcvPIPE_2D;
+#elif gcdCMD_NO_2D_CONTEXT
+    context->entryPipe = gcvPIPE_3D;
+    context->exitPipe  = gcvPIPE_3D;
+#else
+    context->entryPipe
+        = (((((gctUINT32) (context->hardware->chipFeatures)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) )
+            ? gcvPIPE_2D
+            : gcvPIPE_3D;
+    context->exitPipe = gcvPIPE_3D;
+#endif
+
+    /* Get the command buffer requirements. */
+    gcmkONERROR(gckHARDWARE_QueryCommandBuffer(
+        Hardware,
+        &context->alignment,
+        &context->reservedHead,
+        &context->reservedTail
+        ));
+
+    /* Mark the context as dirty to force loading of the entire state table
+       the first time. */
+    context->dirty = gcvTRUE;
+
+
+    /**************************************************************************/
+    /* Get the size of the context buffer. ************************************/
+
+    gcmkONERROR(_InitializeContextBuffer(context));
+
+
+    /**************************************************************************/
+    /* Compute the size of the record array. **********************************/
+
+    context->recordArraySize
+        = gcmSIZEOF(gcsSTATE_DELTA_RECORD) * context->stateCount;
+
+
+    if (context->stateCount > 0)
+    {
+        /**************************************************************************/
+        /* Allocate and reset the state mapping table. ****************************/
+
+        /* Allocate the state mapping table. */
+        gcmkONERROR(gckOS_Allocate(
+            Os,
+            gcmSIZEOF(gcsSTATE_MAP) * context->stateCount,
+            &pointer
+            ));
+
+        context->map = pointer;
+
+        /* Zero the state mapping table. */
+        gcmkONERROR(gckOS_ZeroMemory(
+            context->map, gcmSIZEOF(gcsSTATE_MAP) * context->stateCount
+            ));
+
+
+        /**************************************************************************/
+        /* Allocate the hint array. ***********************************************/
+
+#if gcdSECURE_USER
+        /* Allocate hints. */
+        gcmkONERROR(gckOS_Allocate(
+            Os,
+            gcmSIZEOF(gctBOOL) * context->stateCount,
+            &pointer
+            ));
+
+        context->hint = pointer;
+#endif
+    }
+
+    /**************************************************************************/
+    /* Allocate the context and state delta buffers. **************************/
+
+    for (i = 0; i < gcdCONTEXT_BUFFER_COUNT; i += 1)
+    {
+        /* Allocate a context buffer. */
+        gcsCONTEXT_PTR buffer;
+
+        /* Allocate the context buffer structure. */
+        gcmkONERROR(gckOS_Allocate(
+            Os,
+            gcmSIZEOF(gcsCONTEXT),
+            &pointer
+            ));
+
+        buffer = pointer;
+
+        /* Reset the context buffer structure. */
+        gcmkVERIFY_OK(gckOS_ZeroMemory(
+            buffer, gcmSIZEOF(gcsCONTEXT)
+            ));
+
+        /* Append to the list. */
+        if (context->buffer == gcvNULL)
+        {
+            buffer->next    = buffer;
+            context->buffer = buffer;
+        }
+        else
+        {
+            buffer->next          = context->buffer->next;
+            context->buffer->next = buffer;
+        }
+
+        /* Set the number of delta in the order of creation. */
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+        buffer->num = i;
+#endif
+
+        /* Create the busy signal. */
+        gcmkONERROR(gckOS_CreateSignal(
+            Os, gcvFALSE, &buffer->signal
+            ));
+
+        /* Set the signal, buffer is currently not busy. */
+        gcmkONERROR(gckOS_Signal(
+            Os, buffer->signal, gcvTRUE
+            ));
+
+        /* Create a new physical context buffer. */
+        gcmkONERROR(gckOS_AllocateContiguous(
+            Os,
+            gcvFALSE,
+            &context->totalSize,
+            &buffer->physical,
+            &pointer
+            ));
+
+        buffer->logical = pointer;
+
+        /* Set gckEVENT object pointer. */
+        buffer->eventObj = Hardware->kernel->eventObj;
+
+        /* Set the pointers to the LINK commands. */
+        if (context->linkIndex2D != 0)
+        {
+            buffer->link2D = &buffer->logical[context->linkIndex2D];
+        }
+
+        if (context->linkIndex3D != 0)
+        {
+            buffer->link3D = &buffer->logical[context->linkIndex3D];
+        }
+
+        if (context->linkIndexXD != 0)
+        {
+            gctPOINTER xdLink;
+            gctUINT8_PTR xdEntryLogical;
+            gctSIZE_T xdEntrySize;
+            gctSIZE_T linkBytes;
+
+            /* Determine LINK parameters. */
+            xdLink
+                = &buffer->logical[context->linkIndexXD];
+
+            xdEntryLogical
+                = (gctUINT8_PTR) buffer->logical
+                + context->entryOffsetXDFrom3D;
+
+            xdEntrySize
+                = context->bufferSize
+                - context->entryOffsetXDFrom3D;
+
+            /* Query LINK size. */
+            gcmkONERROR(gckHARDWARE_Link(
+                Hardware, gcvNULL, gcvNULL, 0, &linkBytes
+                ));
+
+            /* Generate a LINK. */
+            gcmkONERROR(gckHARDWARE_Link(
+                Hardware,
+                xdLink,
+                xdEntryLogical,
+                xdEntrySize,
+                &linkBytes
+                ));
+        }
+    }
+
+
+    /**************************************************************************/
+    /* Initialize the context buffers. ****************************************/
+
+    /* Initialize the current context buffer. */
+    gcmkONERROR(_InitializeContextBuffer(context));
+
+    /* Make all created contexts equal. */
+    {
+        gcsCONTEXT_PTR currContext, tempContext;
+
+        /* Set the current context buffer. */
+        currContext = context->buffer;
+
+        /* Get the next context buffer. */
+        tempContext = currContext->next;
+
+        /* Loop through all buffers. */
+        while (tempContext != currContext)
+        {
+            if (tempContext == gcvNULL)
+            {
+                gcmkONERROR(gcvSTATUS_NOT_FOUND);
+            }
+
+            /* Copy the current context. */
+            gcmkONERROR(gckOS_MemCopy(
+                tempContext->logical,
+                currContext->logical,
+                context->totalSize
+                ));
+
+            /* Get the next context buffer. */
+            tempContext = tempContext->next;
+        }
+    }
+
+    /* Return pointer to the gckCONTEXT object. */
+    *Context = context;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Context=0x%08X", *Context);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back on error. */
+    gcmkVERIFY_OK(_DestroyContext(context));
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/******************************************************************************\
+**
+**  gckCONTEXT_Destroy
+**
+**  Destroy a gckCONTEXT object.
+**
+**  INPUT:
+**
+**      gckCONTEXT Context
+**          Pointer to an gckCONTEXT object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCONTEXT_Destroy(
+    IN gckCONTEXT Context
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Context=0x%08X", Context);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
+
+    /* Destroy the context and all related objects. */
+    status = _DestroyContext(Context);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return status;
+}
+
+/******************************************************************************\
+**
+**  gckCONTEXT_Update
+**
+**  Merge all pending state delta buffers into the current context buffer.
+**
+**  INPUT:
+**
+**      gckCONTEXT Context
+**          Pointer to an gckCONTEXT object.
+**
+**      gctUINT32 ProcessID
+**          Current process ID.
+**
+**      gcsSTATE_DELTA_PTR StateDelta
+**          Pointer to the state delta.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCONTEXT_Update(
+    IN gckCONTEXT Context,
+    IN gctUINT32 ProcessID,
+    IN gcsSTATE_DELTA_PTR StateDelta
+    )
+{
+#ifndef VIVANTE_NO_3D
+    gceSTATUS status = gcvSTATUS_OK;
+    static gcsSTATE_DELTA _stateDelta;
+    gckKERNEL kernel;
+    gcsCONTEXT_PTR buffer;
+    gcsSTATE_MAP_PTR map;
+    gctBOOL needCopy = gcvFALSE;
+    gcsSTATE_DELTA_PTR nDelta;
+    gcsSTATE_DELTA_PTR uDelta = gcvNULL;
+    gcsSTATE_DELTA_PTR kDelta = gcvNULL;
+    gcsSTATE_DELTA_RECORD_PTR record;
+    gcsSTATE_DELTA_RECORD_PTR recordArray = gcvNULL;
+    gctUINT elementCount;
+    gctUINT address;
+    gctUINT32 mask;
+    gctUINT32 data;
+    gctUINT index;
+    gctUINT i, j;
+
+#if gcdSECURE_USER
+    gcskSECURE_CACHE_PTR cache;
+#endif
+
+    gcmkHEADER_ARG(
+        "Context=0x%08X ProcessID=%d StateDelta=0x%08X",
+        Context, ProcessID, StateDelta
+        );
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
+
+    /* Get a shortcut to the kernel object. */
+    kernel = Context->hardware->kernel;
+
+    /* Check wehther we need to copy the structures or not. */
+    gcmkONERROR(gckOS_QueryNeedCopy(Context->os, ProcessID, &needCopy));
+
+    /* Allocate the copy buffer for the user record array. */
+    if (needCopy && (Context->recordArray == gcvNULL))
+    {
+        /* Allocate the buffer. */
+        gcmkONERROR(gckOS_Allocate(
+            Context->os,
+            Context->recordArraySize,
+            (gctPOINTER *) &Context->recordArray
+            ));
+    }
+
+    /* Get the current context buffer. */
+    buffer = Context->buffer;
+
+    /* Wait until the context buffer becomes available; this will
+       also reset the signal and mark the buffer as busy. */
+    gcmkONERROR(gckOS_WaitSignal(
+        Context->os, buffer->signal, gcvINFINITE
+        ));
+
+#if gcdSECURE_USER
+    /* Get the cache form the database. */
+    gcmkONERROR(gckKERNEL_GetProcessDBCache(kernel, ProcessID, &cache));
+#endif
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE) && 1 && !defined(VIVANTE_NO_3D)
+    /* Update current context token. */
+    buffer->logical[Context->map[0x0E14].index]
+        = gcmPTR2INT(Context);
+#endif
+
+    /* Are there any pending deltas? */
+    if (buffer->deltaCount != 0)
+    {
+        /* Get the state map. */
+        map = Context->map;
+
+        /* Get the first delta item. */
+        uDelta = buffer->delta;
+
+        /* Reset the vertex stream count. */
+        elementCount = 0;
+
+        /* Merge all pending deltas. */
+        for (i = 0; i < buffer->deltaCount; i += 1)
+        {
+            /* Get access to the state delta. */
+            gcmkONERROR(gckKERNEL_OpenUserData(
+                kernel, needCopy,
+                &_stateDelta,
+                uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+                (gctPOINTER *) &kDelta
+                ));
+
+            /* Get access to the state records. */
+            gcmkONERROR(gckKERNEL_OpenUserData(
+                kernel, needCopy,
+                Context->recordArray,
+                kDelta->recordArray, Context->recordArraySize,
+                (gctPOINTER *) &recordArray
+                ));
+
+            /* Merge all pending states. */
+            for (j = 0; j < kDelta->recordCount; j += 1)
+            {
+                /* Get the current state record. */
+                record = &recordArray[j];
+
+                /* Get the state address. */
+                address = record->address;
+
+                /* Make sure the state is a part of the mapping table. */
+                if (address >= Context->stateCount)
+                {
+                    gcmkTRACE(
+                        gcvLEVEL_ERROR,
+                        "%s(%d): State 0x%04X is not mapped.\n",
+                        __FUNCTION__, __LINE__,
+                        address
+                        );
+
+                    continue;
+                }
+
+                /* Get the state index. */
+                index = map[address].index;
+
+                /* Skip the state if not mapped. */
+                if (index == 0)
+                {
+                    continue;
+                }
+
+                /* Get the data mask. */
+                mask = record->mask;
+
+                /* Masked states that are being completly reset or regular states. */
+                if ((mask == 0) || (mask == ~0U))
+                {
+                    /* Get the new data value. */
+                    data = record->data;
+
+                    /* Process special states. */
+                    if (address == 0x0595)
+                    {
+                        /* Force auto-disable to be disabled. */
+                        data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+                        data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+                        data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1))))))) << (0 ? 13:13))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1))))))) << (0 ? 13:13)));
+                    }
+
+#if gcdSECURE_USER
+                    /* Do we need to convert the logical address? */
+                    if (Context->hint[address])
+                    {
+                        /* Map handle into physical address. */
+                        gcmkONERROR(gckKERNEL_MapLogicalToPhysical(
+                            kernel, cache, (gctPOINTER) &data
+                            ));
+                    }
+#endif
+
+                    /* Set new data. */
+                    buffer->logical[index] = data;
+                }
+
+                /* Masked states that are being set partially. */
+                else
+                {
+                    buffer->logical[index]
+                        = (~mask & buffer->logical[index])
+                        | (mask & record->data);
+                }
+            }
+
+            /* Get the element count. */
+            if (kDelta->elementCount != 0)
+            {
+                elementCount = kDelta->elementCount;
+            }
+
+            /* Dereference delta. */
+            kDelta->refCount -= 1;
+            gcmkASSERT(kDelta->refCount >= 0);
+
+            /* Get the next state delta. */
+            nDelta = kDelta->next;
+
+            /* Get access to the state records. */
+            gcmkONERROR(gckKERNEL_CloseUserData(
+                kernel, needCopy,
+                gcvFALSE,
+                kDelta->recordArray, Context->recordArraySize,
+                (gctPOINTER *) &recordArray
+                ));
+
+            /* Close access to the current state delta. */
+            gcmkONERROR(gckKERNEL_CloseUserData(
+                kernel, needCopy,
+                gcvTRUE,
+                uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+                (gctPOINTER *) &kDelta
+                ));
+
+            /* Update the user delta pointer. */
+            uDelta = nDelta;
+        }
+
+        /* Hardware disables all input streams when the stream 0 is programmed,
+           it then reenables those streams that were explicitely programmed by
+           the software. Because of this we cannot program the entire array of
+           values, otherwise we'll get all streams reenabled, but rather program
+           only those that are actully needed by the software. */
+        if (elementCount != 0)
+        {
+            gctUINT base;
+            gctUINT nopCount;
+            gctUINT32_PTR nop;
+            gctUINT fe2vsCount = 12;
+
+            if ((((((gctUINT32) (Context->hardware->chipMinorFeatures1)) >> (0 ? 23:23)) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1)))))) ))
+            {
+                fe2vsCount = 16;
+            }
+
+            /* Determine the base index of the vertex stream array. */
+            base = map[0x0180].index;
+
+            /* Set the proper state count. */
+            buffer->logical[base - 1]
+                = ((((gctUINT32) (buffer->logical[base - 1])) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (elementCount ) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+            /* Determine the number of NOP commands. */
+            nopCount
+                = (fe2vsCount / 2)
+                - (elementCount / 2);
+
+            /* Determine the location of the first NOP. */
+            nop = &buffer->logical[base + (elementCount | 1)];
+
+            /* Fill the unused space with NOPs. */
+            for (i = 0; i < nopCount; i += 1)
+            {
+                /* Generate a NOP command. */
+                *nop = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+                /* Advance. */
+                nop += 2;
+            }
+        }
+
+        /* Reset pending deltas. */
+        buffer->deltaCount = 0;
+        buffer->delta      = gcvNULL;
+    }
+
+    /* Set state delta user pointer. */
+    uDelta = StateDelta;
+
+    /* Get access to the state delta. */
+    gcmkONERROR(gckKERNEL_OpenUserData(
+        kernel, needCopy,
+        &_stateDelta,
+        uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+        (gctPOINTER *) &kDelta
+        ));
+
+    /* State delta cannot be attached to anything yet. */
+    if (kDelta->refCount != 0)
+    {
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): kDelta->refCount = %d (has to be 0).\n",
+            __FUNCTION__, __LINE__,
+            kDelta->refCount
+            );
+    }
+
+    /* Attach to all contexts. */
+    buffer = Context->buffer;
+
+    do
+    {
+        /* Attach to the context if nothing is attached yet. If a delta
+           is allready attached, all we need to do is to increment
+           the number of deltas in the context. */
+        if (buffer->delta == gcvNULL)
+        {
+            buffer->delta = uDelta;
+        }
+
+        /* Update reference count. */
+        kDelta->refCount += 1;
+
+        /* Update counters. */
+        buffer->deltaCount += 1;
+
+        /* Get the next context buffer. */
+        buffer = buffer->next;
+
+               if (buffer == gcvNULL)
+               {
+                       gcmkONERROR(gcvSTATUS_NOT_FOUND);
+               }
+    }
+    while (Context->buffer != buffer);
+
+    /* Close access to the current state delta. */
+    gcmkONERROR(gckKERNEL_CloseUserData(
+        kernel, needCopy,
+        gcvTRUE,
+        uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+        (gctPOINTER *) &kDelta
+        ));
+
+    /* Schedule an event to mark the context buffer as available. */
+    gcmkONERROR(gckEVENT_Signal(
+        buffer->eventObj, buffer->signal, gcvKERNEL_PIXEL
+        ));
+
+    /* Advance to the next context buffer. */
+    Context->buffer = buffer->next;
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Get access to the state records. */
+       if (kDelta != gcvNULL)
+       {
+        gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+            kernel, needCopy,
+            gcvFALSE,
+            kDelta->recordArray, Context->recordArraySize,
+            (gctPOINTER *) &recordArray
+            ));
+       }
+
+    /* Close access to the current state delta. */
+    gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+        kernel, needCopy,
+        gcvTRUE,
+        uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+        (gctPOINTER *) &kDelta
+        ));
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+#else
+    return gcvSTATUS_OK;
+#endif
+}
+
diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.h b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.h
new file mode 100644 (file)
index 0000000..a1b189a
--- /dev/null
@@ -0,0 +1,146 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_context_h_
+#define __gc_hal_kernel_context_h_
+
+#include "gc_hal_kernel_buffer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Maps state locations within the context buffer. */
+typedef struct _gcsSTATE_MAP * gcsSTATE_MAP_PTR;
+typedef struct _gcsSTATE_MAP
+{
+    /* Index of the state in the context buffer. */
+    gctUINT                     index;
+
+    /* State mask. */
+    gctUINT32                   mask;
+}
+gcsSTATE_MAP;
+
+/* Context buffer. */
+typedef struct _gcsCONTEXT * gcsCONTEXT_PTR;
+typedef struct _gcsCONTEXT
+{
+    /* For debugging: the number of context buffer in the order of creation. */
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+    gctUINT                     num;
+#endif
+
+    /* Pointer to gckEVENT object. */
+    gckEVENT                    eventObj;
+
+    /* Context busy signal. */
+    gctSIGNAL                   signal;
+
+    /* Physical address of the context buffer. */
+    gctPHYS_ADDR                physical;
+
+    /* Logical address of the context buffer. */
+    gctUINT32_PTR               logical;
+
+    /* Pointer to the LINK commands. */
+    gctPOINTER                  link2D;
+    gctPOINTER                  link3D;
+
+    /* The number of pending state deltas. */
+    gctUINT                     deltaCount;
+
+    /* Pointer to the first delta to be applied. */
+    gcsSTATE_DELTA_PTR          delta;
+
+    /* Next context buffer. */
+    gcsCONTEXT_PTR              next;
+}
+gcsCONTEXT;
+
+/* gckCONTEXT structure that hold the current context. */
+struct _gckCONTEXT
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gckOS object. */
+    gckOS                       os;
+
+    /* Pointer to gckHARDWARE object. */
+    gckHARDWARE                 hardware;
+
+    /* Command buffer alignment. */
+    gctSIZE_T                   alignment;
+    gctSIZE_T                   reservedHead;
+    gctSIZE_T                   reservedTail;
+
+    /* Context buffer metrics. */
+    gctSIZE_T                   stateCount;
+    gctSIZE_T                   totalSize;
+    gctSIZE_T                   bufferSize;
+    gctUINT32                   linkIndex2D;
+    gctUINT32                   linkIndex3D;
+    gctUINT32                   linkIndexXD;
+    gctUINT32                   entryOffset3D;
+    gctUINT32                   entryOffsetXDFrom2D;
+    gctUINT32                   entryOffsetXDFrom3D;
+
+    /* Dirty flags. */
+    gctBOOL                     dirty;
+    gctBOOL                     dirty2D;
+    gctBOOL                     dirty3D;
+    gcsCONTEXT_PTR              dirtyBuffer;
+
+    /* State mapping. */
+    gcsSTATE_MAP_PTR            map;
+
+    /* List of context buffers. */
+    gcsCONTEXT_PTR              buffer;
+
+    /* A copy of the user record array. */
+    gctUINT                     recordArraySize;
+    gcsSTATE_DELTA_RECORD_PTR   recordArray;
+
+    /* Requested pipe select for context. */
+    gcePIPE_SELECT              entryPipe;
+    gcePIPE_SELECT              exitPipe;
+
+    /* Variables used for building state buffer. */
+    gctUINT32                   lastAddress;
+    gctSIZE_T                   lastSize;
+    gctUINT32                   lastIndex;
+    gctBOOL                     lastFixed;
+
+    /* Hint array. */
+#if gcdSECURE_USER
+    gctBOOL_PTR                 hint;
+#endif
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_context_h_ */
+
diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
new file mode 100644 (file)
index 0000000..8ca8dfe
--- /dev/null
@@ -0,0 +1,5300 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+
+#define _GC_OBJ_ZONE    gcvZONE_HARDWARE
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+static gceSTATUS
+_ResetGPU(
+    IN gckOS Os,
+    IN gceCORE Core
+    );
+
+static gceSTATUS
+_IdentifyHardware(
+    IN gckOS Os,
+    IN gceCORE Core,
+    OUT gceCHIPMODEL * ChipModel,
+    OUT gctUINT32_PTR ChipRevision,
+    OUT gctUINT32_PTR ChipFeatures,
+    OUT gctUINT32_PTR ChipMinorFeatures0,
+    OUT gctUINT32_PTR ChipMinorFeatures1,
+    OUT gctUINT32_PTR ChipMinorFeatures2,
+    OUT gctUINT32_PTR ChipMinorFeatures3
+    )
+{
+    gceSTATUS status;
+    gctUINT32 chipIdentity;
+    gctUINT32 chipDate = 0xCCDDCCDD;
+    gctUINT32 chipTime = 0xCCDDCCDD;
+
+    gcmkHEADER_ARG("Os=0x%x", Os);
+
+    /* Read chip identity register. */
+    gcmkONERROR(
+        gckOS_ReadRegisterEx(Os, Core, 0x00018, &chipIdentity));
+
+    /* Special case for older graphic cores. */
+    if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
+    {
+        *ChipModel    = gcv500;
+        *ChipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
+    }
+
+    else
+    {
+        /* Read date and time registers. */
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Os, Core, 0x00028, &chipDate));
+
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Os, Core, 0x0002C, &chipTime));
+
+        /* Read chip identity register. */
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Os,
+                                 Core,
+                                 0x00020,
+                                 (gctUINT32_PTR) ChipModel));
+
+        /* !!!! HACK ALERT !!!! */
+        /* Because people change device IDs without letting software know
+        ** about it - here is the hack to make it all look the same.  Only
+        ** for GC400 family.  Next time - TELL ME!!! */
+        if ((*ChipModel & 0xFF00) == 0x0400)
+        {
+            *ChipModel &= 0x0400;
+        }
+
+        /* Read CHIP_REV register. */
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Os, Core, 0x00024, ChipRevision));
+
+        if ((*ChipModel    == gcv300)
+        &&  (*ChipRevision == 0x2201)
+        )
+        {
+            if ((chipDate == 0x20080814) && (chipTime == 0x12051100))
+            {
+                /* This IP has an ECO; put the correct revision in it. */
+                *ChipRevision = 0x1051;
+            }
+        }
+    }
+
+    /* Read chip feature register. */
+    gcmkONERROR(
+        gckOS_ReadRegisterEx(Os, Core, 0x0001C, ChipFeatures));
+
+#ifndef VIVANTE_NO_3D
+    /* Disable fast clear on GC700. */
+    if (*ChipModel == gcv700)
+    {
+        *ChipFeatures = ((((gctUINT32) (*ChipFeatures)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+    }
+#endif
+
+    if (((*ChipModel == gcv500) && (*ChipRevision < 2))
+    ||  ((*ChipModel == gcv300) && (*ChipRevision < 0x2000))
+    )
+    {
+        /* GC500 rev 1.x and GC300 rev < 2.0 doesn't have these registers. */
+        *ChipMinorFeatures0 = 0;
+        *ChipMinorFeatures1 = 0;
+        *ChipMinorFeatures2 = 0;
+        *ChipMinorFeatures3 = 0;
+    }
+    else
+    {
+        /* Read chip minor feature register #0. */
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Os,
+                                 Core,
+                                 0x00034,
+                                 ChipMinorFeatures0));
+
+        if (((((gctUINT32) (*ChipMinorFeatures0)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))))
+        )
+        {
+            /* Read chip minor featuress register #1. */
+            gcmkONERROR(
+                gckOS_ReadRegisterEx(Os,
+                                     Core,
+                                     0x00074,
+                                     ChipMinorFeatures1));
+
+            /* Disabling texture hAlignment until it's fully tested. */
+            *ChipMinorFeatures1 = *ChipMinorFeatures1 & ~(1 << 20);
+
+            /* Read chip minor featuress register #2. */
+            gcmkONERROR(
+                gckOS_ReadRegisterEx(Os,
+                                     Core,
+                                     0x00084,
+                                     ChipMinorFeatures2));
+
+                       /* Read chip minor featuress register #1. */
+                       gcmkONERROR(
+                               gckOS_ReadRegisterEx(Os,
+                                     Core,
+                                                                    0x00088,
+                                                                    ChipMinorFeatures3));
+        }
+        else
+        {
+            /* Chip doesn't has minor features register #1 or 2 or 3. */
+            *ChipMinorFeatures1 = 0;
+            *ChipMinorFeatures2 = 0;
+            *ChipMinorFeatures3 = 0;
+        }
+    }
+
+    /* Disable HIERARCHICAL_Z. */
+    *ChipMinorFeatures0 = ((((gctUINT32) (*ChipMinorFeatures0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27)));
+
+    /* Success. */
+    gcmkFOOTER_ARG("*ChipModel=%x *ChipRevision=%x *ChipFeatures=0x%08x "
+                   "*ChipMinorFeatures0=0x%08X *ChipMinorFeatures1=0x%08x "
+                   "*ChipMinorFeatures2=0x%08x  *ChipMinorFeatures3=0x%08x",
+                   *ChipModel, *ChipRevision, *ChipFeatures,
+                   *ChipMinorFeatures0, *ChipMinorFeatures1,
+                   *ChipMinorFeatures2, *ChipMinorFeatures3);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+static gceSTATUS
+_GetChipSpecs(
+    IN gckHARDWARE Hardware
+    )
+{
+    gctUINT32 streamCount = 0;
+    gctUINT32 registerMax = 0;
+    gctUINT32 threadCount = 0;
+    gctUINT32 shaderCoreCount = 0;
+    gctUINT32 vertexCacheSize = 0;
+    gctUINT32 vertexOutputBufferSize = 0;
+    gctUINT32 pixelPipes = 0;
+    gctUINT32 instructionCount = 0;
+    gctUINT32 numConstants = 0;
+    gctUINT32 bufferSize = 0;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    if (((((gctUINT32) (Hardware->chipMinorFeatures0)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))))
+    {
+        gctUINT32 specs, specs2;
+
+        /* Read gcChipSpecs register. */
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00048, &specs));
+
+        /* Handy macro to improve reading. */
+#define gcmSPEC_FIELD(field) \
+        (((((gctUINT32) (specs)) >> (0 ? GC_CHIP_SPECS_field)) & ((gctUINT32) ((((1 ? GC_CHIP_SPECS_field) - (0 ? GC_CHIP_SPECS_field) + 1) == 32) ? ~0 : (~(~0 << ((1 ? GC_CHIP_SPECS_field) - (0 ? GC_CHIP_SPECS_field) + 1)))))) )
+
+        /* Extract the fields. */
+        streamCount            = (((((gctUINT32) (specs)) >> (0 ? 3:0)) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1)))))) );
+        registerMax            = (((((gctUINT32) (specs)) >> (0 ? 7:4)) & ((gctUINT32) ((((1 ? 7:4) - (0 ? 7:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:4) - (0 ? 7:4) + 1)))))) );
+        threadCount            = (((((gctUINT32) (specs)) >> (0 ? 11:8)) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1)))))) );
+        shaderCoreCount        = (((((gctUINT32) (specs)) >> (0 ? 24:20)) & ((gctUINT32) ((((1 ? 24:20) - (0 ? 24:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:20) - (0 ? 24:20) + 1)))))) );
+        vertexCacheSize        = (((((gctUINT32) (specs)) >> (0 ? 16:12)) & ((gctUINT32) ((((1 ? 16:12) - (0 ? 16:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:12) - (0 ? 16:12) + 1)))))) );
+        vertexOutputBufferSize = (((((gctUINT32) (specs)) >> (0 ? 31:28)) & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1)))))) );
+        pixelPipes             = (((((gctUINT32) (specs)) >> (0 ? 27:25)) & ((gctUINT32) ((((1 ? 27:25) - (0 ? 27:25) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:25) - (0 ? 27:25) + 1)))))) );
+
+        /* Read gcChipSpecs2 register. */
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00080, &specs2));
+
+        /* Handy macro to improve reading. */
+#define gcmSPEC2_FIELD(field) \
+        (((((gctUINT32) (specs2)) >> (0 ? GC_CHIP_SPECS2_field)) & ((gctUINT32) ((((1 ? GC_CHIP_SPECS2_field) - (0 ? GC_CHIP_SPECS2_field) + 1) == 32) ? ~0 : (~(~0 << ((1 ? GC_CHIP_SPECS2_field) - (0 ? GC_CHIP_SPECS2_field) + 1)))))) )
+
+               instructionCount       = (((((gctUINT32) (specs2)) >> (0 ? 15:8)) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1)))))) );
+               numConstants           = (((((gctUINT32) (specs2)) >> (0 ? 31:16)) & ((gctUINT32) ((((1 ? 31:16) - (0 ? 31:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:16) - (0 ? 31:16) + 1)))))) );
+               bufferSize             = (((((gctUINT32) (specs2)) >> (0 ? 7:0)) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1)))))) );
+    }
+
+    /* Get the number of pixel pipes. */
+    Hardware->pixelPipes = gcmMAX(pixelPipes, 1);
+
+    /* Get the stream count. */
+    Hardware->streamCount = (streamCount != 0)
+                          ? streamCount
+                          : (Hardware->chipModel >= gcv1000) ? 4 : 1;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Specs: streamCount=%u%s",
+                   Hardware->streamCount,
+                   (streamCount == 0) ? " (default)" : "");
+
+    /* Get the vertex output buffer size. */
+    Hardware->vertexOutputBufferSize = (vertexOutputBufferSize != 0)
+                                     ? 1 << vertexOutputBufferSize
+                                     : (Hardware->chipModel == gcv400)
+                                       ? (Hardware->chipRevision < 0x4000) ? 512
+                                       : (Hardware->chipRevision < 0x4200) ? 256
+                                       : 128
+                                     : (Hardware->chipModel == gcv530)
+                                       ? (Hardware->chipRevision < 0x4200) ? 512
+                                       : 128
+                                     : 512;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Specs: vertexOutputBufferSize=%u%s",
+                   Hardware->vertexOutputBufferSize,
+                   (vertexOutputBufferSize == 0) ? " (default)" : "");
+
+    /* Get the maximum number of threads. */
+    Hardware->threadCount = (threadCount != 0)
+                          ? 1 << threadCount
+                          : (Hardware->chipModel == gcv400) ? 64
+                          : (Hardware->chipModel == gcv500) ? 128
+                          : (Hardware->chipModel == gcv530) ? 128
+                          : 256;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Specs: threadCount=%u%s",
+                   Hardware->threadCount,
+                   (threadCount == 0) ? " (default)" : "");
+
+    /* Get the number of shader cores. */
+    Hardware->shaderCoreCount = (shaderCoreCount != 0)
+                              ? shaderCoreCount
+                              : (Hardware->chipModel >= gcv1000) ? 2
+                              : 1;
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Specs: shaderCoreCount=%u%s",
+                   Hardware->shaderCoreCount,
+                   (shaderCoreCount == 0) ? " (default)" : "");
+
+    /* Get the vertex cache size. */
+    Hardware->vertexCacheSize = (vertexCacheSize != 0)
+                              ? vertexCacheSize
+                              : 8;
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Specs: vertexCacheSize=%u%s",
+                   Hardware->vertexCacheSize,
+                   (vertexCacheSize == 0) ? " (default)" : "");
+
+    /* Get the maximum number of temporary registers. */
+    Hardware->registerMax = (registerMax != 0)
+               /* Maximum of registerMax/4 registers are accessible to 1 shader */
+                          ? 1 << registerMax
+                          : (Hardware->chipModel == gcv400) ? 32
+                          : 64;
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Specs: registerMax=%u%s",
+                   Hardware->registerMax,
+                   (registerMax == 0) ? " (default)" : "");
+
+    /* Get the instruction count. */
+       Hardware->instructionCount = (instructionCount == 0) ? 256
+                               : (instructionCount == 1) ? 1024
+                               : (instructionCount == 2) ? 2048
+                                                          : 256;
+
+       gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Specs: instructionCount=%u%s",
+                   Hardware->instructionCount,
+                   (instructionCount == 0) ? " (default)" : "");
+
+    /* Get the number of constants. */
+       Hardware->numConstants = numConstants;
+
+       gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Specs: numConstants=%u%s",
+                   Hardware->numConstants,
+                   (numConstants == 0) ? " (default)" : "");
+
+    /* Get the buffer size. */
+       Hardware->bufferSize = bufferSize;
+
+       gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Specs: bufferSize=%u%s",
+                   Hardware->bufferSize,
+                   (bufferSize == 0) ? " (default)" : "");
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/******************************************************************************\
+****************************** gckHARDWARE API code *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckHARDWARE_Construct
+**
+**  Construct a new gckHARDWARE object.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an initialized gckOS object.
+**
+**      gceCORE Core
+**          Specified core.
+**
+**  OUTPUT:
+**
+**      gckHARDWARE * Hardware
+**          Pointer to a variable that will hold the pointer to the gckHARDWARE
+**          object.
+*/
+gceSTATUS
+gckHARDWARE_Construct(
+    IN gckOS Os,
+    IN gceCORE Core,
+    OUT gckHARDWARE * Hardware
+    )
+{
+    gckHARDWARE hardware = gcvNULL;
+    gceSTATUS status;
+    gceCHIPMODEL chipModel = gcv300;
+    gctUINT32 chipRevision = 0;
+    gctUINT32 chipFeatures = 0;
+    gctUINT32 chipMinorFeatures0 = 0;
+    gctUINT32 chipMinorFeatures1 = 0;
+    gctUINT32 chipMinorFeatures2 = 0;
+    gctUINT32 chipMinorFeatures3 = 0;
+    gctUINT16 data = 0xff00;
+    gctPOINTER pointer = gcvNULL;
+
+    gcmkHEADER_ARG("Os=0x%x", Os);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
+
+    /* Enable the GPU. */
+    gcmkONERROR(gckOS_SetGPUPower(Os, gcvTRUE, gcvTRUE));
+    gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00000, 0));
+
+    status = _ResetGPU(Os, Core);
+
+    if (status != gcvSTATUS_OK)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+            "_ResetGPU failed: status=%d\n", status);
+    }
+
+    /* Identify the hardware. */
+    gcmkONERROR(_IdentifyHardware(Os,
+                                  Core,
+                                  &chipModel,
+                                  &chipRevision,
+                                  &chipFeatures,
+                                  &chipMinorFeatures0,
+                                  &chipMinorFeatures1,
+                                  &chipMinorFeatures2,
+                                  &chipMinorFeatures3));
+
+    /* Allocate the gckHARDWARE object. */
+    gcmkONERROR(gckOS_Allocate(Os,
+                               gcmSIZEOF(struct _gckHARDWARE),
+                               &pointer));
+
+    hardware = pointer;
+
+    /* Initialize the gckHARDWARE object. */
+    hardware->object.type = gcvOBJ_HARDWARE;
+    hardware->os          = Os;
+
+    hardware->core        = Core;
+
+    /* Determine the hardware type */
+    switch (chipModel)
+    {
+    case gcv350:
+    case gcv355:
+        hardware->type = gcvHARDWARE_VG;
+        break;
+
+    case gcv300:
+    case gcv320:
+        hardware->type = gcvHARDWARE_2D;
+        break;
+
+    default:
+        hardware->type = gcvHARDWARE_3D;
+
+        if ((((((gctUINT32) (chipFeatures)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) ))
+        {
+            hardware->type |= gcvHARDWARE_2D;
+        }
+    }
+
+    /* Set chip identity. */
+    hardware->chipModel          = chipModel;
+    hardware->chipRevision       = chipRevision;
+    hardware->chipFeatures       = chipFeatures;
+    hardware->chipMinorFeatures0 = chipMinorFeatures0;
+    hardware->chipMinorFeatures1 = chipMinorFeatures1;
+    hardware->chipMinorFeatures2 = chipMinorFeatures2;
+    hardware->chipMinorFeatures3 = chipMinorFeatures3;
+    hardware->powerBaseAddress   = ((chipModel == gcv300)
+                                   && (chipRevision < 0x2000)
+                                   ) ? 0x100 : 0x00;
+    hardware->powerMutex         = gcvNULL;
+
+    hardware->mmuVersion         =
+                    (((((gctUINT32) (hardware->chipMinorFeatures1)) >> (0 ? 28:28)) & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))) );
+
+    /* Get chip specs. */
+    gcmkONERROR(_GetChipSpecs(hardware));
+
+    /* Determine whether bug fixes #1 are present. */
+    hardware->extraEventStates = ((((gctUINT32) (chipMinorFeatures1)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x0 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))));
+
+    /* Check if big endian */
+    hardware->bigEndian = (*(gctUINT8 *)&data == 0xff);
+
+    /* Initialize the fast clear. */
+    gcmkONERROR(gckHARDWARE_SetFastClear(hardware, -1, -1));
+
+#if !gcdENABLE_128B_MERGE && 1 && 1
+
+    if (((((gctUINT32) (hardware->chipMinorFeatures2)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1  & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))))
+    {
+        /* 128B merge is turned on by default. Disable it. */
+        gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00558, 0));
+    }
+
+#endif
+
+    /* Set power state to ON. */
+    hardware->chipPowerState  = gcvPOWER_ON;
+    hardware->clockState      = gcvTRUE;
+    hardware->powerState      = gcvTRUE;
+    hardware->lastWaitLink    = ~0U;
+    hardware->globalSemaphore = gcvNULL;
+
+    gcmkONERROR(gckOS_CreateMutex(Os, &hardware->powerMutex));
+    gcmkONERROR(gckOS_CreateSemaphore(Os, &hardware->globalSemaphore));
+
+#if gcdPOWEROFF_TIMEOUT
+    gcmkONERROR(gckOS_CreateMutex(Os, &hardware->powerOffSema));
+    gcmkONERROR(gckOS_AcquireMutex(Os, hardware->powerOffSema, gcvINFINITE));
+#endif
+
+    /* Return pointer to the gckHARDWARE object. */
+    *Hardware = hardware;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Hardware=0x%x", *Hardware);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (hardware != gcvNULL)
+    {
+        /* Turn off the power. */
+        gcmkVERIFY_OK(gckOS_SetGPUPower(Os, gcvFALSE, gcvFALSE));
+
+        if (hardware->globalSemaphore != gcvNULL)
+        {
+            /* Destroy the global semaphore. */
+            gcmkVERIFY_OK(gckOS_DestroySemaphore(Os,
+                                                 hardware->globalSemaphore));
+        }
+
+        if (hardware->powerMutex != gcvNULL)
+        {
+            /* Destroy the power mutex. */
+            gcmkVERIFY_OK(gckOS_DeleteMutex(Os, hardware->powerMutex));
+        }
+
+#if gcdPOWEROFF_TIMEOUT
+        if (hardware->powerOffSema != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(Os, &hardware->powerOffSema));
+        }
+#endif
+
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, hardware));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_Destroy
+**
+**  Destroy an gckHARDWARE object.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to the gckHARDWARE object that needs to be destroyed.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Destroy(
+    IN gckHARDWARE Hardware
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Turn off the power. */
+    gcmkVERIFY_OK(gckOS_SetGPUPower(Hardware->os, gcvFALSE, gcvFALSE));
+
+    /* Destroy the power semaphore. */
+    gcmkVERIFY_OK(gckOS_DestroySemaphore(Hardware->os,
+                                         Hardware->globalSemaphore));
+
+    /* Destroy the power mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Hardware->os, Hardware->powerMutex));
+
+#if gcdPOWEROFF_TIMEOUT
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Hardware->os, Hardware->powerOffSema));
+#endif
+
+    /* Mark the object as unknown. */
+    Hardware->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the object. */
+    gcmkONERROR(gcmkOS_SAFE_FREE(Hardware->os, Hardware));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_GetType
+**
+**  Get the hardware type.
+**
+**  INPUT:
+**
+**      gckHARDWARE Harwdare
+**          Pointer to an gckHARDWARE object.
+**
+**  OUTPUT:
+**
+**      gceHARDWARE_TYPE * Type
+**          Pointer to a variable that receives the type of hardware object.
+*/
+gceSTATUS
+gckHARDWARE_GetType(
+    IN gckHARDWARE Hardware,
+    OUT gceHARDWARE_TYPE * Type
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+    gcmkVERIFY_ARGUMENT(Type != gcvNULL);
+
+    *Type = Hardware->type;
+
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_InitializeHardware
+**
+**  Initialize the hardware.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to the gckHARDWARE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHARDWARE_InitializeHardware(
+    IN gckHARDWARE Hardware
+    )
+{
+    gceSTATUS status;
+    gctUINT32 baseAddress;
+    gctUINT32 chipRev;
+
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Read the chip revision register. */
+    gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                     Hardware->core,
+                                     0x00024,
+                                     &chipRev));
+
+    if (chipRev != Hardware->chipRevision)
+    {
+        /* Chip is not there! */
+        gcmkONERROR(gcvSTATUS_CONTEXT_LOSSED);
+    }
+
+    /* Disable isolate GPU bit. */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x00000,
+                                      ((((gctUINT32) (0x00000100)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)))));
+
+    /* Reset memory counters. */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x0003C,
+                                      ~0U));
+
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x0003C,
+                                      0));
+
+    /* Get the system's physical base address. */
+    gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
+
+    /* Program the base addesses. */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x0041C,
+                                      baseAddress));
+
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x00418,
+                                      baseAddress));
+
+#ifndef VIVANTE_NO_3D
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x00420,
+                                      baseAddress));
+
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x00428,
+                                      baseAddress));
+
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x00424,
+                                      baseAddress));
+#endif
+
+#if !VIVANTE_PROFILER && 1
+    {
+        gctUINT32 data;
+
+        gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                         Hardware->core,
+                                         Hardware->powerBaseAddress +
+                                         0x00100,
+                                         &data));
+
+        /* Enable clock gating. */
+        data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+        if ((Hardware->chipRevision == 0x4301)
+        ||  (Hardware->chipRevision == 0x4302)
+        )
+        {
+            /* Disable stall module level clock gating for 4.3.0.1 and 4.3.0.2
+            ** revisions. */
+            data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)));
+        }
+
+        gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                          Hardware->core,
+                                          Hardware->powerBaseAddress
+                                          + 0x00100,
+                                          data));
+
+#ifndef VIVANTE_NO_3D
+        /* Disable PE clock gating on revs < 5.0 when HZ is present without a
+        ** bug fix. */
+        if ((Hardware->chipRevision < 0x5000)
+        &&  ((((gctUINT32) (Hardware->chipMinorFeatures1)) >> (0 ? 9:9) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) == (0x0 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))))
+        &&  ((((gctUINT32) (Hardware->chipMinorFeatures0)) >> (0 ? 27:27) & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))))
+        )
+        {
+            gcmkONERROR(
+                gckOS_ReadRegisterEx(Hardware->os,
+                                     Hardware->core,
+                                     Hardware->powerBaseAddress
+                                     + 0x00104,
+                                     &data));
+
+            /* Disable PE clock gating. */
+            data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)));
+
+            gcmkONERROR(
+                gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      Hardware->powerBaseAddress
+                                      + 0x00104,
+                                      data));
+        }
+#endif
+    }
+#endif
+
+    /* Test if MMU is initialized. */
+    if ((Hardware->kernel      != gcvNULL)
+    &&  (Hardware->kernel->mmu != gcvNULL)
+    )
+    {
+        /* Reset MMU. */
+        gcmkONERROR(
+            gckHARDWARE_SetMMU(Hardware,
+                               Hardware->kernel->mmu->pageTableLogical));
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the error. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_QueryMemory
+**
+**  Query the amount of memory available on the hardware.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to the gckHARDWARE object.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * InternalSize
+**          Pointer to a variable that will hold the size of the internal video
+**          memory in bytes.  If 'InternalSize' is gcvNULL, no information of the
+**          internal memory will be returned.
+**
+**      gctUINT32 * InternalBaseAddress
+**          Pointer to a variable that will hold the hardware's base address for
+**          the internal video memory.  This pointer cannot be gcvNULL if
+**          'InternalSize' is also non-gcvNULL.
+**
+**      gctUINT32 * InternalAlignment
+**          Pointer to a variable that will hold the hardware's base address for
+**          the internal video memory.  This pointer cannot be gcvNULL if
+**          'InternalSize' is also non-gcvNULL.
+**
+**      gctSIZE_T * ExternalSize
+**          Pointer to a variable that will hold the size of the external video
+**          memory in bytes.  If 'ExternalSize' is gcvNULL, no information of the
+**          external memory will be returned.
+**
+**      gctUINT32 * ExternalBaseAddress
+**          Pointer to a variable that will hold the hardware's base address for
+**          the external video memory.  This pointer cannot be gcvNULL if
+**          'ExternalSize' is also non-gcvNULL.
+**
+**      gctUINT32 * ExternalAlignment
+**          Pointer to a variable that will hold the hardware's base address for
+**          the external video memory.  This pointer cannot be gcvNULL if
+**          'ExternalSize' is also non-gcvNULL.
+**
+**      gctUINT32 * HorizontalTileSize
+**          Number of horizontal pixels per tile.  If 'HorizontalTileSize' is
+**          gcvNULL, no horizontal pixel per tile will be returned.
+**
+**      gctUINT32 * VerticalTileSize
+**          Number of vertical pixels per tile.  If 'VerticalTileSize' is
+**          gcvNULL, no vertical pixel per tile will be returned.
+*/
+gceSTATUS
+gckHARDWARE_QueryMemory(
+    IN gckHARDWARE Hardware,
+    OUT gctSIZE_T * InternalSize,
+    OUT gctUINT32 * InternalBaseAddress,
+    OUT gctUINT32 * InternalAlignment,
+    OUT gctSIZE_T * ExternalSize,
+    OUT gctUINT32 * ExternalBaseAddress,
+    OUT gctUINT32 * ExternalAlignment,
+    OUT gctUINT32 * HorizontalTileSize,
+    OUT gctUINT32 * VerticalTileSize
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    if (InternalSize != gcvNULL)
+    {
+        /* No internal memory. */
+        *InternalSize = 0;
+    }
+
+    if (ExternalSize != gcvNULL)
+    {
+        /* No external memory. */
+        *ExternalSize = 0;
+    }
+
+    if (HorizontalTileSize != gcvNULL)
+    {
+        /* 4x4 tiles. */
+        *HorizontalTileSize = 4;
+    }
+
+    if (VerticalTileSize != gcvNULL)
+    {
+        /* 4x4 tiles. */
+        *VerticalTileSize = 4;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*InternalSize=%lu *InternalBaseAddress=0x%08x "
+                   "*InternalAlignment=0x%08x *ExternalSize=%lu "
+                   "*ExternalBaseAddress=0x%08x *ExtenalAlignment=0x%08x "
+                   "*HorizontalTileSize=%u *VerticalTileSize=%u",
+                   gcmOPT_VALUE(InternalSize),
+                   gcmOPT_VALUE(InternalBaseAddress),
+                   gcmOPT_VALUE(InternalAlignment),
+                   gcmOPT_VALUE(ExternalSize),
+                   gcmOPT_VALUE(ExternalBaseAddress),
+                   gcmOPT_VALUE(ExternalAlignment),
+                   gcmOPT_VALUE(HorizontalTileSize),
+                   gcmOPT_VALUE(VerticalTileSize));
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_QueryChipIdentity
+**
+**  Query the identity of the hardware.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to the gckHARDWARE object.
+**
+**  OUTPUT:
+**
+**      gceCHIPMODEL * ChipModel
+**          If 'ChipModel' is not gcvNULL, the variable it points to will
+**          receive the model of the chip.
+**
+**      gctUINT32 * ChipRevision
+**          If 'ChipRevision' is not gcvNULL, the variable it points to will
+**          receive the revision of the chip.
+**
+**      gctUINT32 * ChipFeatures
+**          If 'ChipFeatures' is not gcvNULL, the variable it points to will
+**          receive the feature set of the chip.
+**
+**      gctUINT32 * ChipMinorFeatures
+**          If 'ChipMinorFeatures' is not gcvNULL, the variable it points to
+**          will receive the minor feature set of the chip.
+**
+**      gctUINT32 * ChipMinorFeatures1
+**          If 'ChipMinorFeatures1' is not gcvNULL, the variable it points to
+**          will receive the minor feature set 1 of the chip.
+**
+**      gctUINT32 * ChipMinorFeatures2
+**          If 'ChipMinorFeatures2' is not gcvNULL, the variable it points to
+**          will receive the minor feature set 2 of the chip.
+**
+*/
+gceSTATUS
+gckHARDWARE_QueryChipIdentity(
+    IN gckHARDWARE Hardware,
+    OUT gceCHIPMODEL * ChipModel,
+    OUT gctUINT32 * ChipRevision,
+    OUT gctUINT32* ChipFeatures,
+    OUT gctUINT32* ChipMinorFeatures,
+    OUT gctUINT32* ChipMinorFeatures1,
+    OUT gctUINT32* ChipMinorFeatures2,
+    OUT gctUINT32* ChipMinorFeatures3
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Return chip model. */
+    if (ChipModel != gcvNULL)
+    {
+        *ChipModel = Hardware->chipModel;
+    }
+
+    /* Return revision number. */
+    if (ChipRevision != gcvNULL)
+    {
+        *ChipRevision = Hardware->chipRevision;
+    }
+
+    /* Return feature set. */
+    if (ChipFeatures != gcvNULL)
+    {
+        gctUINT32 features = Hardware->chipFeatures;
+
+        if ((((((gctUINT32) (features)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+        {
+            /* Override fast clear by command line. */
+            features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (Hardware->allowFastClear) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+        }
+
+        if ((((((gctUINT32) (features)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) ))
+        {
+            /* Override compression by command line. */
+            features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (Hardware->allowCompression) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+        }
+
+        /* Mark 2D pipe as available for GC500.0 through GC500.2 and GC300,
+        ** since they did not have this bit. */
+        if (((Hardware->chipModel == gcv500)
+            && (Hardware->chipRevision <= 2)
+            )
+        ||  (Hardware->chipModel == gcv300)
+        )
+        {
+            features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
+        }
+
+        *ChipFeatures = features;
+    }
+
+    /* Return minor feature set. */
+    if (ChipMinorFeatures != gcvNULL)
+    {
+        *ChipMinorFeatures = Hardware->chipMinorFeatures0;
+    }
+
+    /* Return minor feature set 1. */
+    if (ChipMinorFeatures1 != gcvNULL)
+    {
+        *ChipMinorFeatures1 = Hardware->chipMinorFeatures1;
+    }
+
+    /* Return minor feature set 2. */
+    if (ChipMinorFeatures2 != gcvNULL)
+    {
+        *ChipMinorFeatures2 = Hardware->chipMinorFeatures2;
+    }
+
+    /* Return minor feature set 3. */
+    if (ChipMinorFeatures3 != gcvNULL)
+    {
+        *ChipMinorFeatures3 = Hardware->chipMinorFeatures3;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*ChipModel=0x%x *ChipRevision=0x%x *ChipFeatures=0x%08x "
+                   "*ChipMinorFeatures=0x%08x *ChipMinorFeatures1=0x%08x "
+                   "*ChipMinorFeatures2=0x%08x  *ChipMinorFeatures3=0x%08x",
+                   gcmOPT_VALUE(ChipModel),
+                                  gcmOPT_VALUE(ChipRevision),
+                   gcmOPT_VALUE(ChipFeatures),
+                                  gcmOPT_VALUE(ChipMinorFeatures),
+                   gcmOPT_VALUE(ChipMinorFeatures1),
+                   gcmOPT_VALUE(ChipMinorFeatures2),
+                   gcmOPT_VALUE(ChipMinorFeatures3));
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_QueryChipSpecs(
+    IN gckHARDWARE Hardware,
+    OUT gctUINT32_PTR StreamCount,
+    OUT gctUINT32_PTR RegisterMax,
+    OUT gctUINT32_PTR ThreadCount,
+    OUT gctUINT32_PTR ShaderCoreCount,
+    OUT gctUINT32_PTR VertexCacheSize,
+    OUT gctUINT32_PTR VertexOutputBufferSize,
+    OUT gctUINT32_PTR PixelPipes,
+    OUT gctUINT32_PTR InstructionCount,
+    OUT gctUINT32_PTR NumConstants,
+    OUT gctUINT32_PTR BufferSize
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Return the number of streams. */
+    if (StreamCount != gcvNULL)
+    {
+        *StreamCount = Hardware->streamCount;
+    }
+
+    /* Return the number of temporary registers. */
+    if (RegisterMax != gcvNULL)
+    {
+        *RegisterMax = Hardware->registerMax;
+    }
+
+    /* Return the maximum number of thrteads. */
+    if (ThreadCount != gcvNULL)
+    {
+        *ThreadCount = Hardware->threadCount;
+    }
+
+    /* Return the number of shader cores. */
+    if (ShaderCoreCount != gcvNULL)
+    {
+        *ShaderCoreCount = Hardware->shaderCoreCount;
+    }
+
+    /* Return the number of entries in the vertex cache. */
+    if (VertexCacheSize != gcvNULL)
+    {
+        *VertexCacheSize = Hardware->vertexCacheSize;
+    }
+
+    /* Return the number of entries in the vertex output buffer. */
+    if (VertexOutputBufferSize != gcvNULL)
+    {
+        *VertexOutputBufferSize = Hardware->vertexOutputBufferSize;
+    }
+
+    /* Return the number of pixel pipes. */
+    if (PixelPipes != gcvNULL)
+    {
+        *PixelPipes = Hardware->pixelPipes;
+    }
+
+    /* Return the number of instructions. */
+    if (InstructionCount != gcvNULL)
+    {
+        *InstructionCount = Hardware->instructionCount;
+    }
+
+    /* Return the number of constants. */
+    if (NumConstants != gcvNULL)
+    {
+        *NumConstants = Hardware->numConstants;
+    }
+
+    /* Return the buffer size. */
+    if (BufferSize != gcvNULL)
+    {
+        *BufferSize = Hardware->bufferSize;
+    }
+
+       /* Success. */
+    gcmkFOOTER_ARG("*StreamCount=%u *RegisterMax=%u *ThreadCount=%u "
+                   "*ShaderCoreCount=%u *VertexCacheSize=%u "
+                   "*VertexOutputBufferSize=%u *PixelPipes=%u",
+                   "*InstructionCount=%u *NumConstants=%u *BufferSize=%u",
+                   gcmOPT_VALUE(StreamCount), gcmOPT_VALUE(RegisterMax),
+                   gcmOPT_VALUE(ThreadCount), gcmOPT_VALUE(ShaderCoreCount),
+                   gcmOPT_VALUE(VertexCacheSize),
+                   gcmOPT_VALUE(VertexOutputBufferSize),
+                                  gcmOPT_VALUE(PixelPipes),
+                                  gcmOPT_VALUE(InstructionCount),
+                                  gcmOPT_VALUE(NumConstants),
+                                  gcmOPT_VALUE(BufferSize));
+
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_ConvertFormat
+**
+**  Convert an API format to hardware parameters.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to the gckHARDWARE object.
+**
+**      gceSURF_FORMAT Format
+**          API format to convert.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * BitsPerPixel
+**          Pointer to a variable that will hold the number of bits per pixel.
+**
+**      gctUINT32 * BytesPerTile
+**          Pointer to a variable that will hold the number of bytes per tile.
+*/
+gceSTATUS
+gckHARDWARE_ConvertFormat(
+    IN gckHARDWARE Hardware,
+    IN gceSURF_FORMAT Format,
+    OUT gctUINT32 * BitsPerPixel,
+    OUT gctUINT32 * BytesPerTile
+    )
+{
+    gctUINT32 bitsPerPixel;
+    gctUINT32 bytesPerTile;
+
+    gcmkHEADER_ARG("Hardware=0x%x Format=%d", Hardware, Format);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Dispatch on format. */
+    switch (Format)
+    {
+    case gcvSURF_INDEX8:
+    case gcvSURF_A8:
+    case gcvSURF_L8:
+        /* 8-bpp format. */
+        bitsPerPixel  = 8;
+        bytesPerTile  = (8 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_YV12:
+    case gcvSURF_I420:
+    case gcvSURF_NV12:
+    case gcvSURF_NV21:
+        /* 12-bpp planar YUV formats. */
+        bitsPerPixel  = 12;
+        bytesPerTile  = (12 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_A8L8:
+    case gcvSURF_X4R4G4B4:
+    case gcvSURF_A4R4G4B4:
+    case gcvSURF_X1R5G5B5:
+    case gcvSURF_A1R5G5B5:
+    case gcvSURF_R5G5B5X1:
+    case gcvSURF_R4G4B4X4:
+    case gcvSURF_X4B4G4R4:
+    case gcvSURF_X1B5G5R5:
+    case gcvSURF_B4G4R4X4:
+    case gcvSURF_R5G6B5:
+    case gcvSURF_B5G5R5X1:
+    case gcvSURF_YUY2:
+    case gcvSURF_UYVY:
+    case gcvSURF_YVYU:
+    case gcvSURF_VYUY:
+    case gcvSURF_NV16:
+    case gcvSURF_NV61:
+    case gcvSURF_D16:
+        /* 16-bpp format. */
+        bitsPerPixel  = 16;
+        bytesPerTile  = (16 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_X8R8G8B8:
+    case gcvSURF_A8R8G8B8:
+    case gcvSURF_X8B8G8R8:
+    case gcvSURF_A8B8G8R8:
+    case gcvSURF_R8G8B8X8:
+    case gcvSURF_D32:
+        /* 32-bpp format. */
+        bitsPerPixel  = 32;
+        bytesPerTile  = (32 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_D24S8:
+    case gcvSURF_D24X8:
+        /* 24-bpp format. */
+        bitsPerPixel  = 32;
+        bytesPerTile  = (32 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_DXT1:
+    case gcvSURF_ETC1:
+        bitsPerPixel  = 4;
+        bytesPerTile  = (4 * 4 * 4) / 8;
+        break;
+
+    case gcvSURF_DXT2:
+    case gcvSURF_DXT3:
+    case gcvSURF_DXT4:
+    case gcvSURF_DXT5:
+        bitsPerPixel  = 8;
+        bytesPerTile  = (8 * 4 * 4) / 8;
+        break;
+
+    default:
+        /* Invalid format. */
+        gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+        return gcvSTATUS_INVALID_ARGUMENT;
+    }
+
+    /* Set the result. */
+    if (BitsPerPixel != gcvNULL)
+    {
+        * BitsPerPixel = bitsPerPixel;
+    }
+
+    if (BytesPerTile != gcvNULL)
+    {
+        * BytesPerTile = bytesPerTile;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*BitsPerPixel=%u *BytesPerTile=%u",
+                   gcmOPT_VALUE(BitsPerPixel), gcmOPT_VALUE(BytesPerTile));
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_SplitMemory
+**
+**  Split a hardware specific memory address into a pool and offset.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to the gckHARDWARE object.
+**
+**      gctUINT32 Address
+**          Address in hardware specific format.
+**
+**  OUTPUT:
+**
+**      gcePOOL * Pool
+**          Pointer to a variable that will hold the pool type for the address.
+**
+**      gctUINT32 * Offset
+**          Pointer to a variable that will hold the offset for the address.
+*/
+gceSTATUS
+gckHARDWARE_SplitMemory(
+    IN gckHARDWARE Hardware,
+    IN gctUINT32 Address,
+    OUT gcePOOL * Pool,
+    OUT gctUINT32 * Offset
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x Addres=0x%08x", Hardware, Address);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
+
+    /* Dispatch on memory type. */
+    switch ((((((gctUINT32) (Address)) >> (0 ? 31:31)) & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))) ))
+    {
+    case 0x0:
+        /* System memory. */
+        *Pool = gcvPOOL_SYSTEM;
+        break;
+
+    case 0x1:
+        /* Virtual memory. */
+        *Pool = gcvPOOL_VIRTUAL;
+        break;
+
+    default:
+        /* Invalid memory type. */
+        gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+        return gcvSTATUS_INVALID_ARGUMENT;
+    }
+
+    /* Return offset of address. */
+    *Offset = (((((gctUINT32) (Address)) >> (0 ? 30:0)) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1)))))) );
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Pool=%d *Offset=0x%08x", *Pool, *Offset);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_Execute
+**
+**  Kickstart the hardware's command processor with an initialized command
+**  buffer.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to the gckHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Logical address of command buffer.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes for the prefetch unit (until after the first LINK).
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Execute(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+#ifdef __QNXNTO__
+    IN gctPOINTER Physical,
+    IN gctBOOL PhysicalAddresses,
+#endif
+    IN gctSIZE_T Bytes
+    )
+{
+    gceSTATUS status;
+    gctUINT32 address = 0, control;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Bytes=%lu",
+                   Hardware, Logical, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+#ifdef __QNXNTO__
+    if (PhysicalAddresses)
+    {
+        /* Convert physical into hardware specific address. */
+        gcmkONERROR(
+            gckHARDWARE_ConvertPhysical(Hardware, Physical, &address));
+    }
+    else
+    {
+#endif
+    /* Convert logical into hardware specific address. */
+    gcmkONERROR(
+        gckHARDWARE_ConvertLogical(Hardware, Logical, &address));
+#ifdef __QNXNTO__
+    }
+#endif
+
+    /* Enable all events. */
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00014, ~0U));
+
+    /* Write address register. */
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00654, address));
+
+    /* Build control register. */
+    control = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) ((Bytes + 7) >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+    /* Set big endian */
+    if (Hardware->bigEndian)
+    {
+        control |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 21:20) - (0 ? 21:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:20) - (0 ? 21:20) + 1))))))) << (0 ? 21:20))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 21:20) - (0 ? 21:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:20) - (0 ? 21:20) + 1))))))) << (0 ? 21:20)));
+    }
+
+    /* Write control register. */
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00658, control));
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                  "Started command buffer @ 0x%08x",
+                  address);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_WaitLink
+**
+**  Append a WAIT/LINK command sequence at the specified location in the command
+**  queue.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command queue to append
+**          WAIT/LINK command sequence at or gcvNULL just to query the size of the
+**          WAIT/LINK command sequence.
+**
+**      gctUINT32 Offset
+**          Offset into command buffer required for alignment.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the WAIT/LINK command
+**          sequence.  If 'Logical' is gcvNULL, this argument will be ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          by the WAIT/LINK command sequence.  If 'Bytes' is gcvNULL, nothing will
+**          be returned.
+**
+**      gctUINT32 * WaitOffset
+**          Pointer to a variable that will receive the offset of the WAIT command
+**          from the specified logcial pointer.
+**          If 'WaitOffset' is gcvNULL nothing will be returned.
+**
+**      gctSIZE_T * WaitSize
+**          Pointer to a variable that will receive the number of bytes used by
+**          the WAIT command.  If 'LinkSize' is gcvNULL nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_WaitLink(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Offset,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctUINT32 * WaitOffset,
+    OUT gctSIZE_T * WaitSize
+    )
+{
+    static const gctUINT waitCount = 200;
+
+    gceSTATUS status;
+    gctUINT32 address;
+    gctUINT32_PTR logical;
+    gctSIZE_T bytes;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=0x%08x *Bytes=%lu",
+                   Hardware, Logical, Offset, gcmOPT_VALUE(Bytes));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
+
+    /* Compute number of bytes required. */
+#if gcd6000_SUPPORT
+    bytes = gcmALIGN(Offset + 96, 8) - Offset;
+#else
+    bytes = gcmALIGN(Offset + 16, 8) - Offset;
+#endif
+
+    /* Cast the input pointer. */
+    logical = (gctUINT32_PTR) Logical;
+
+    if (logical != gcvNULL)
+    {
+        /* Not enough space? */
+        if (*Bytes < bytes)
+        {
+            /* Command queue too small. */
+            gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+        }
+
+        /* Convert logical into hardware specific address. */
+        gcmkONERROR(gckHARDWARE_ConvertLogical(Hardware, logical, &address));
+
+        /* Store the WAIT/LINK address. */
+        Hardware->lastWaitLink = address;
+
+        /* Append WAIT(count). */
+        logical[0]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (waitCount) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+#if gcd6000_SUPPORT
+        /* Send FE-PE sempahore token. */
+        logical[2]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        logical[3]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+        /* Send FE-PE stall token. */
+        logical[4]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0F00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        logical[5]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+        /*************************************************************/
+        /* Enable chip ID 0. */
+        logical[6] =
+            ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | (1 << 0);
+
+        /* Send semaphore from FE to ChipID 1. */
+        logical[8] =
+              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        logical[9] =
+              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)));
+
+        /* Send semaphore from FE to ChipID 1. */
+        logical[10] =
+              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+        logical[11] =
+              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)));
+
+        /*************************************************************/
+        /* Enable chip ID 1. */
+        logical[12] =
+            ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | (1 << 1);
+
+        /* Send semaphore from FE to ChipID 1. */
+        logical[14] =
+              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        logical[15] =
+              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)));
+
+        /* Wait for semaphore from ChipID 0. */
+        logical[16] =
+              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+        logical[17] =
+              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)));
+
+        /*************************************************************/
+        /* Enable all chips. */
+        logical[18] =
+            ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | (0xFFFF);
+
+        /* LoadState(AQFlush, 1), flush. */
+        logical[20]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+        logical[21]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? AQ_FLUSH_L2_CACHE) - (0 ? AQ_FLUSH_L2_CACHE) + 1) == 32) ? ~0 : (~(~0 << ((1 ? AQ_FLUSH_L2_CACHE) - (0 ? AQ_FLUSH_L2_CACHE) + 1))))))) << (0 ? AQ_FLUSH_L2_CACHE))) | (((gctUINT32) (AQ_FLUSH_L2_CACHE_ENABLE & ((gctUINT32) ((((1 ? AQ_FLUSH_L2_CACHE) - (0 ? AQ_FLUSH_L2_CACHE) + 1) == 32) ? ~0 : (~(~0 << ((1 ? AQ_FLUSH_L2_CACHE) - (0 ? AQ_FLUSH_L2_CACHE) + 1))))))) << (0 ? AQ_FLUSH_L2_CACHE)));
+
+        /* Append LINK(2, address). */
+        logical[22]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        logical[23] = address;
+#else
+        /* Append LINK(2, address). */
+        logical[2]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        logical[3] = address;
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_HARDWARE,
+            "0x%08x: WAIT %u", address, waitCount
+            );
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_HARDWARE,
+            "0x%08x: LINK 0x%08x, #%lu",
+            address + 8, address, bytes
+            );
+#endif
+
+        if (WaitOffset != gcvNULL)
+        {
+            /* Return the offset pointer to WAIT command. */
+            *WaitOffset = 0;
+        }
+
+        if (WaitSize != gcvNULL)
+        {
+            /* Return number of bytes used by the WAIT command. */
+            *WaitSize = 8;
+        }
+    }
+
+    if (Bytes != gcvNULL)
+    {
+        /* Return number of bytes required by the WAIT/LINK command
+        ** sequence. */
+        *Bytes = bytes;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Bytes=%lu *WaitOffset=0x%x *WaitSize=%lu",
+                   gcmOPT_VALUE(Bytes), gcmOPT_VALUE(WaitOffset),
+                   gcmOPT_VALUE(WaitSize));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_End
+**
+**  Append an END command at the specified location in the command queue.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command queue to append
+**          END command at or gcvNULL just to query the size of the END command.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the END command.  If
+**          'Logical' is gcvNULL, this argument will be ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the END command.  If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_End(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
+                   Hardware, Logical, gcmOPT_VALUE(Bytes));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+    if (Logical != gcvNULL)
+    {
+        if (*Bytes < 8)
+        {
+            /* Command queue too small. */
+            gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+        }
+
+        /* Append END. */
+       logical[0] =
+            ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: END", Logical);
+
+        /* Make sure the CPU writes out the data to memory. */
+        gcmkONERROR(
+            gckOS_MemoryBarrier(Hardware->os, Logical));
+    }
+
+    if (Bytes != gcvNULL)
+    {
+        /* Return number of bytes required by the END command. */
+        *Bytes = 8;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_Nop
+**
+**  Append a NOP command at the specified location in the command queue.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command queue to append
+**          NOP command at or gcvNULL just to query the size of the NOP command.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the NOP command.  If
+**          'Logical' is gcvNULL, this argument will be ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the NOP command.  If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Nop(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
+                   Hardware, Logical, gcmOPT_VALUE(Bytes));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+    if (Logical != gcvNULL)
+    {
+        if (*Bytes < 8)
+        {
+            /* Command queue too small. */
+            gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+        }
+
+        /* Append NOP. */
+        logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: NOP", Logical);
+    }
+
+    if (Bytes != gcvNULL)
+    {
+        /* Return number of bytes required by the NOP command. */
+        *Bytes = 8;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_Wait
+**
+**  Append a WAIT command at the specified location in the command queue.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command queue to append
+**          WAIT command at or gcvNULL just to query the size of the WAIT command.
+**
+**      gctUINT32 Count
+**          Number of cycles to wait.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the WAIT command.  If
+**          'Logical' is gcvNULL, this argument will be ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the NOP command.  If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Wait(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Count,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gceSTATUS status;
+    gctUINT32_PTR logical;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Count=%u *Bytes=%lu",
+                   Hardware, Logical, Count, gcmOPT_VALUE(Bytes));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+    /* Cast the input pointer. */
+    logical = (gctUINT32_PTR) Logical;
+
+    if (Logical != gcvNULL)
+    {
+        if (*Bytes < 8)
+        {
+            /* Command queue too small. */
+            gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+        }
+
+        /* Append WAIT. */
+        logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                   | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+        {
+            gctUINT32 address;
+
+            /* Convert logical into hardware specific address. */
+            gcmkONERROR(gckHARDWARE_ConvertLogical(
+                Hardware, logical, &address
+                ));
+
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                "0x%08x: WAIT %u", address, Count
+                );
+        }
+#endif
+    }
+
+    if (Bytes != gcvNULL)
+    {
+        /* Return number of bytes required by the WAIT command. */
+        *Bytes = 8;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_Event
+**
+**  Append an EVENT command at the specified location in the command queue.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command queue to append
+**          the EVENT command at or gcvNULL just to query the size of the EVENT
+**          command.
+**
+**      gctUINT8 Event
+**          Event ID to program.
+**
+**      gceKERNEL_WHERE FromWhere
+**          Location of the pipe to send the event.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the EVENT command.  If
+**          'Logical' is gcvNULL, this argument will be ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the EVENT command.  If 'Bytes' is gcvNULL, nothing will be
+**          returned.
+*/
+gceSTATUS
+gckHARDWARE_Event(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gctUINT8 Event,
+    IN gceKERNEL_WHERE FromWhere,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gctUINT size;
+    gctUINT32 destination = 0;
+    gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Event=%u FromWhere=%d *Bytes=%lu",
+                   Hardware, Logical, Event, FromWhere, gcmOPT_VALUE(Bytes));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+    gcmkVERIFY_ARGUMENT(Event < 32);
+
+    /* Determine the size of the command. */
+    size = (Hardware->extraEventStates && (FromWhere == gcvKERNEL_PIXEL))
+         ? gcmALIGN(8 + (1 + 5) * 4, 8) /* EVENT + 5 STATES */
+         : 8;
+
+    if (Logical != gcvNULL)
+    {
+        if (*Bytes < size)
+        {
+            /* Command queue too small. */
+            gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+        }
+
+        switch (FromWhere)
+        {
+        case gcvKERNEL_COMMAND:
+            /* From command processor. */
+            destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+            break;
+
+        case gcvKERNEL_PIXEL:
+            /* From pixel engine. */
+            destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+            break;
+
+        default:
+            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+        }
+
+        /* Append EVENT(Event, destiantion). */
+        logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                   | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+                   | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+        logical[1] = ((((gctUINT32) (destination)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (Event) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
+
+        /* Make sure the event ID gets written out before GPU can access it. */
+        gcmkONERROR(
+            gckOS_MemoryBarrier(Hardware->os, logical + 1));
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+        {
+            gctUINT32 phys;
+            gckOS_GetPhysicalAddress(Hardware->os, Logical, &phys);
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                           "0x%08x: EVENT %d", phys, Event);
+        }
+#endif
+
+        /* Append the extra states. These are needed for the chips that do not
+        ** support back-to-back events due to the async interface. The extra
+        ** states add the necessary delay to ensure that event IDs do not
+        ** collide. */
+        if (size > 8)
+        {
+            logical[2] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                       | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0100) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+                       | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+            logical[3] = 0;
+            logical[4] = 0;
+            logical[5] = 0;
+            logical[6] = 0;
+            logical[7] = 0;
+        }
+    }
+
+    if (Bytes != gcvNULL)
+    {
+        /* Return number of bytes required by the EVENT command. */
+        *Bytes = size;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_PipeSelect
+**
+**  Append a PIPESELECT command at the specified location in the command queue.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command queue to append
+**          the PIPESELECT command at or gcvNULL just to query the size of the
+**          PIPESELECT command.
+**
+**      gcePIPE_SELECT Pipe
+**          Pipe value to select.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the PIPESELECT command.
+**          If 'Logical' is gcvNULL, this argument will be ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the PIPESELECT command.  If 'Bytes' is gcvNULL, nothing will be
+**          returned.
+*/
+gceSTATUS
+gckHARDWARE_PipeSelect(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gcePIPE_SELECT Pipe,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Pipe=%d *Bytes=%lu",
+                   Hardware, Logical, Pipe, gcmOPT_VALUE(Bytes));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+    /* Append a PipeSelect. */
+    if (Logical != gcvNULL)
+    {
+        gctUINT32 flush, stall;
+
+        if (*Bytes < 32)
+        {
+            /* Command queue too small. */
+            gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+        }
+
+        flush = (Pipe == gcvPIPE_2D)
+              ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+              | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+              : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)));
+
+        stall = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+              | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+        /* LoadState(AQFlush, 1), flush. */
+        logical[0]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+        logical[1]
+            = flush;
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "0x%x: FLUSH 0x%x", logical, flush);
+
+        /* LoadState(AQSempahore, 1), stall. */
+        logical[2]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        logical[3]
+            = stall;
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "0x%x: SEMAPHORE 0x%x", logical + 2, stall);
+
+        /* Stall, stall. */
+        logical[4] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+        logical[5] = stall;
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "0x%x: STALL 0x%x", logical + 4, stall);
+
+        /* LoadState(AQPipeSelect, 1), pipe. */
+        logical[6]
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+        logical[7] = (Pipe == gcvPIPE_2D)
+            ? 0x1
+            : 0x0;
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "0x%x: PIPE %d", logical + 6, Pipe);
+    }
+
+    if (Bytes != gcvNULL)
+    {
+        /* Return number of bytes required by the PIPESELECT command. */
+        *Bytes = 32;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_Link
+**
+**  Append a LINK command at the specified location in the command queue.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command queue to append
+**          the LINK command at or gcvNULL just to query the size of the LINK
+**          command.
+**
+**      gctPOINTER FetchAddress
+**          Logical address of destination of LINK.
+**
+**      gctSIZE_T FetchSize
+**          Number of bytes in destination of LINK.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the LINK command.  If
+**          'Logical' is gcvNULL, this argument will be ignored.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the number of bytes required
+**          for the LINK command.  If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Link(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gctPOINTER FetchAddress,
+    IN gctSIZE_T FetchSize,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gceSTATUS status;
+    gctSIZE_T bytes;
+    gctUINT32 address;
+    gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x FetchAddress=0x%x FetchSize=%lu "
+                   "*Bytes=%lu",
+                   Hardware, Logical, FetchAddress, FetchSize,
+                   gcmOPT_VALUE(Bytes));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+    if (Logical != gcvNULL)
+    {
+        if (*Bytes < 8)
+        {
+            /* Command queue too small. */
+            gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+        }
+
+        /* Convert logical address to hardware address. */
+        gcmkONERROR(
+            gckHARDWARE_ConvertLogical(Hardware, FetchAddress, &address));
+
+        logical[1] = address;
+
+        /* Make sure the address got written before the LINK command. */
+        gcmkONERROR(
+            gckOS_MemoryBarrier(Hardware->os, logical + 1));
+
+        /* Compute number of 64-byte aligned bytes to fetch. */
+        bytes = gcmALIGN(address + FetchSize, 64) - address;
+
+        /* Append LINK(bytes / 8), FetchAddress. */
+        logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                   | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        /* Memory barrier. */
+        gcmkONERROR(
+            gckOS_MemoryBarrier(Hardware->os, logical));
+    }
+
+    if (Bytes != gcvNULL)
+    {
+        /* Return number of bytes required by the LINK command. */
+        *Bytes = 8;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_AlignToTile
+**
+**  Align the specified width and height to tile boundaries.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gceSURF_TYPE Type
+**          Type of alignment.
+**
+**      gctUINT32 * Width
+**          Pointer to the width to be aligned.  If 'Width' is gcvNULL, no width
+**          will be aligned.
+**
+**      gctUINT32 * Height
+**          Pointer to the height to be aligned.  If 'Height' is gcvNULL, no height
+**          will be aligned.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Width
+**          Pointer to a variable that will receive the aligned width.
+**
+**      gctUINT32 * Height
+**          Pointer to a variable that will receive the aligned height.
+**
+**      gctBOOL_PTR SuperTiled
+**          Pointer to a variable that receives the super-tiling flag for the
+**          surface.
+*/
+gceSTATUS
+gckHARDWARE_AlignToTile(
+    IN gckHARDWARE Hardware,
+    IN gceSURF_TYPE Type,
+    IN OUT gctUINT32_PTR Width,
+    IN OUT gctUINT32_PTR Height,
+    OUT gctBOOL_PTR SuperTiled
+    )
+{
+    gctBOOL superTiled = gcvFALSE;
+    gctUINT32 xAlignment, yAlignment;
+    gctBOOL hAlignmentAvailable = gcvFALSE;
+
+    gcmkHEADER_ARG("Hardware=0x%x Type=%d *Width=%u *Height=%u",
+                   Hardware, Type, gcmOPT_VALUE(Width), gcmOPT_VALUE(Height));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Super tiling can be enabled for render targets and depth buffers. */
+    superTiled =
+        ((Type == gcvSURF_RENDER_TARGET)
+        || (Type == gcvSURF_DEPTH)
+        )
+        &&
+        /* Of course, hardware needs to support super tiles. */
+        ((((gctUINT32) (Hardware->chipMinorFeatures0)) >> (0 ? 12:12) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1)))))));
+
+    /* Textures can be better aligned. */
+    hAlignmentAvailable = ((((gctUINT32) (Hardware->chipMinorFeatures1)) >> (0 ? 20:20) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1)))))));
+
+    /* Compute alignment factors. */
+    xAlignment = superTiled ? 64
+               : ((Type == gcvSURF_TEXTURE) && !hAlignmentAvailable) ? 4
+               : 16;
+    yAlignment = superTiled ? (64 * Hardware->pixelPipes)
+               : (4 * Hardware->pixelPipes);
+
+    if (Width != gcvNULL)
+    {
+        /* Align the width. */
+        *Width = gcmALIGN(*Width, xAlignment);
+    }
+
+    if (Height != gcvNULL)
+    {
+        /* Align the height. */
+        *Height = gcmALIGN(*Height, yAlignment);
+    }
+
+    if (SuperTiled != gcvNULL)
+    {
+        /* Copy the super tiling. */
+        *SuperTiled = superTiled;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Width=%u *Height=%u *SuperTiled=%d",
+                   gcmOPT_VALUE(Width), gcmOPT_VALUE(Height),
+                   gcmOPT_VALUE(SuperTiled));
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_UpdateQueueTail
+**
+**  Update the tail of the command queue.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Logical address of the start of the command queue.
+**
+**      gctUINT32 Offset
+**          Offset into the command queue of the tail (last command).
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHARDWARE_UpdateQueueTail(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Offset
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=0x%08x",
+                   Hardware, Logical, Offset);
+
+    /* Verify the hardware. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Force a barrier. */
+    gcmkONERROR(
+        gckOS_MemoryBarrier(Hardware->os, Logical));
+
+    /* Notify gckKERNEL object of change. */
+    gcmkONERROR(
+        gckKERNEL_Notify(Hardware->kernel,
+                         gcvNOTIFY_COMMAND_QUEUE,
+                         gcvFALSE));
+
+    if (status == gcvSTATUS_CHIP_NOT_READY)
+    {
+        gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_ConvertLogical
+**
+**  Convert a logical system address into a hardware specific address.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Logical address to convert.
+**
+**      gctUINT32* Address
+**          Return hardware specific address.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ConvertLogical(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    OUT gctUINT32 * Address
+    )
+{
+    gctUINT32 address;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x", Hardware, Logical);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    /* Convert logical address into a physical address. */
+    gcmkONERROR(
+        gckOS_GetPhysicalAddress(Hardware->os, Logical, &address));
+
+    /* Return hardware specific address. */
+    *Address = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
+             | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (address) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)));
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Address=0x%08x", *Address);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_ConvertPhysical
+**
+**  Convert a physical address into a hardware specific address.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gctPHYS_ADDR Physical
+**          Physical address to convert.
+**
+**      gctUINT32* Address
+**          Return hardware specific address.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ConvertPhysical(
+    IN gckHARDWARE Hardware,
+    IN gctPHYS_ADDR Physical,
+    OUT gctUINT32 * Address
+    )
+{
+    gctUINT32 address;
+
+    gcmkHEADER_ARG("Hardware=0x%x Physical=0x%x", Hardware, Physical);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    address = gcmPTR2INT(Physical);
+
+    /* Return hardware specific address. */
+    *Address = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
+             | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (address) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)));
+
+    /* Return the status. */
+    gcmkFOOTER_ARG("*Address=0x%08x", *Address);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_Interrupt
+**
+**  Process an interrupt.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gctBOOL InterruptValid
+**          If gcvTRUE, this function will read the interrupt acknowledge
+**          register, stores the data, and return whether or not the interrupt
+**          is ours or not.  If gcvFALSE, this functions will read the interrupt
+**          acknowledge register and combine it with any stored value to handle
+**          the event notifications.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Interrupt(
+    IN gckHARDWARE Hardware,
+    IN gctBOOL InterruptValid
+    )
+{
+    gckEVENT eventObj;
+    gctUINT32 data;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x InterruptValid=%d", Hardware, InterruptValid);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Extract gckEVENT object. */
+    eventObj = Hardware->kernel->eventObj;
+    gcmkVERIFY_OBJECT(eventObj, gcvOBJ_EVENT);
+
+    if (InterruptValid)
+    {
+        /* Read AQIntrAcknowledge register. */
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Hardware->os,
+                                 Hardware->core,
+                                 0x00010,
+                                 &data));
+
+        if (data & 0x80000000)
+        {
+            gcmkONERROR(gckOS_Broadcast(Hardware->os,
+                                        Hardware,
+                                        gcvBROADCAST_AXI_BUS_ERROR));
+        }
+
+        if (data == 0)
+        {
+            /* Not our interrupt. */
+            status = gcvSTATUS_NOT_OUR_INTERRUPT;
+        }
+        else
+        {
+            /* Inform gckEVENT of the interrupt. */
+            status = gckEVENT_Interrupt(eventObj, data & 0x7FFFFFFF);
+        }
+    }
+    else
+    {
+        /* Handle events. */
+        status = gckEVENT_Notify(eventObj, 0);
+    }
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_QueryCommandBuffer
+**
+**  Query the command buffer alignment and number of reserved bytes.
+**
+**  INPUT:
+**
+**      gckHARDWARE Harwdare
+**          Pointer to an gckHARDWARE object.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Alignment
+**          Pointer to a variable receiving the alignment for each command.
+**
+**      gctSIZE_T * ReservedHead
+**          Pointer to a variable receiving the number of reserved bytes at the
+**          head of each command buffer.
+**
+**      gctSIZE_T * ReservedTail
+**          Pointer to a variable receiving the number of bytes reserved at the
+**          tail of each command buffer.
+*/
+gceSTATUS
+gckHARDWARE_QueryCommandBuffer(
+    IN gckHARDWARE Hardware,
+    OUT gctSIZE_T * Alignment,
+    OUT gctSIZE_T * ReservedHead,
+    OUT gctSIZE_T * ReservedTail
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    if (Alignment != gcvNULL)
+    {
+        /* Align every 8 bytes. */
+        *Alignment = 8;
+    }
+
+    if (ReservedHead != gcvNULL)
+    {
+        /* Reserve space for SelectPipe(). */
+        *ReservedHead = 32;
+    }
+
+    if (ReservedTail != gcvNULL)
+    {
+        /* Reserve space for Link(). */
+        *ReservedTail = 8;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Alignment=%lu *ReservedHead=%lu *ReservedTail=%lu",
+                   gcmOPT_VALUE(Alignment), gcmOPT_VALUE(ReservedHead),
+                   gcmOPT_VALUE(ReservedTail));
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_QuerySystemMemory
+**
+**  Query the command buffer alignment and number of reserved bytes.
+**
+**  INPUT:
+**
+**      gckHARDWARE Harwdare
+**          Pointer to an gckHARDWARE object.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * SystemSize
+**          Pointer to a variable that receives the maximum size of the system
+**          memory.
+**
+**      gctUINT32 * SystemBaseAddress
+**          Poinetr to a variable that receives the base address for system
+**          memory.
+*/
+gceSTATUS
+gckHARDWARE_QuerySystemMemory(
+    IN gckHARDWARE Hardware,
+    OUT gctSIZE_T * SystemSize,
+    OUT gctUINT32 * SystemBaseAddress
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    if (SystemSize != gcvNULL)
+    {
+        /* Maximum system memory can be 2GB. */
+        *SystemSize = 1U << 31;
+    }
+
+    if (SystemBaseAddress != gcvNULL)
+    {
+        /* Set system memory base address. */
+        *SystemBaseAddress = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)));
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*SystemSize=%lu *SystemBaseAddress=%lu",
+                   gcmOPT_VALUE(SystemSize), gcmOPT_VALUE(SystemBaseAddress));
+    return gcvSTATUS_OK;
+}
+
+#if !defined(VIVANTE_NO_3D)
+/*******************************************************************************
+**
+**  gckHARDWARE_QueryShaderCaps
+**
+**  Query the shader capabilities.
+**
+**  INPUT:
+**
+**      Nothing.
+**
+**  OUTPUT:
+**
+**      gctUINT * VertexUniforms
+**          Pointer to a variable receiving the number of uniforms in the vertex
+**          shader.
+**
+**      gctUINT * FragmentUniforms
+**          Pointer to a variable receiving the number of uniforms in the
+**          fragment shader.
+**
+**      gctUINT * Varyings
+**          Pointer to a variable receiving the maimum number of varyings.
+*/
+gceSTATUS
+gckHARDWARE_QueryShaderCaps(
+    IN gckHARDWARE Hardware,
+    OUT gctUINT * VertexUniforms,
+    OUT gctUINT * FragmentUniforms,
+    OUT gctUINT * Varyings
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x VertexUniforms=0x%x "
+                   "FragmentUniforms=0x%x Varyings=0x%x",
+                   Hardware, VertexUniforms,
+                   FragmentUniforms, Varyings);
+
+    if (VertexUniforms != gcvNULL)
+    {
+               /* Return the vs shader const count. */
+        if (Hardware->chipModel < gcv4000)
+        {
+            *VertexUniforms = 168;
+        }
+        else
+        {
+            *VertexUniforms = 256;
+        }
+    }
+
+    if (FragmentUniforms != gcvNULL)
+    {
+               /* Return the ps shader const count. */
+        if (Hardware->chipModel < gcv4000)
+        {
+            *FragmentUniforms = 64;
+        }
+        else
+        {
+            *FragmentUniforms = 256;
+        }
+    }
+
+    if (Varyings != gcvNULL)
+    {
+               /* Return the shader varyings count. */
+        if (((((gctUINT32) (Hardware->chipMinorFeatures1)) >> (0 ? 23:23) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))))
+        {
+                   *Varyings = 12;
+        }
+        else
+        {
+                   *Varyings = 8;
+        }
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+#endif
+
+/*******************************************************************************
+**
+**  gckHARDWARE_SetMMU
+**
+**  Set the page table base address.
+**
+**  INPUT:
+**
+**      gckHARDWARE Harwdare
+**          Pointer to an gckHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Logical address of the page table.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHARDWARE_SetMMU(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical
+    )
+{
+    gceSTATUS status;
+    gctUINT32 address = 0;
+    gctUINT32 baseAddress;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x", Hardware, Logical);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+    /* Convert the logical address into an hardware address. */
+    gcmkONERROR(
+        gckHARDWARE_ConvertLogical(Hardware, Logical, &address));
+
+    /* Also get the base address - we need a real physical address. */
+    gcmkONERROR(
+        gckOS_GetBaseAddress(Hardware->os, &baseAddress));
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Setting page table to 0x%08X",
+                   address + baseAddress);
+
+    /* Write the AQMemoryFePageTable register. */
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os,
+                              Hardware->core,
+                              0x00400,
+                              address + baseAddress));
+
+    /* Write the AQMemoryRaPageTable register. */
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os,
+                              Hardware->core,
+                              0x00410,
+                              address + baseAddress));
+
+#ifndef VIVANTE_NO_3D
+    /* Write the AQMemoryTxPageTable register. */
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os,
+                              Hardware->core,
+                              0x00404,
+                              address + baseAddress));
+#endif
+
+    /* Write the AQMemoryPePageTable register. */
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os,
+                              Hardware->core,
+                              0x00408,
+                              address + baseAddress));
+
+#ifndef VIVANTE_NO_3D
+    /* Write the AQMemoryPezPageTable register. */
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os,
+                              Hardware->core,
+                              0x0040C,
+                              address + baseAddress));
+#endif
+
+    /* Return the status. */
+    gcmkFOOTER_NO();
+    return status;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_FlushMMU
+**
+**  Flush the page table.
+**
+**  INPUT:
+**
+**      gckHARDWARE Harwdare
+**          Pointer to an gckHARDWARE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHARDWARE_FlushMMU(
+    IN gckHARDWARE Hardware
+    )
+{
+    gceSTATUS status;
+    gckCOMMAND command;
+    gctUINT32 reg, flush;
+    gctUINT32_PTR buffer;
+    gctSIZE_T bufferSize;
+    gctBOOL commitEntered = gcvFALSE;
+    gctPOINTER pointer = gcvNULL;
+
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Flush the memory controller. */
+    if (Hardware->mmuVersion == 0)
+    {
+        reg = 0x0E04;
+
+        flush = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+              | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+              | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
+              | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
+              | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+    }
+    else
+    {
+        reg = 0x0061;
+
+        flush = (((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) &  ((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) );
+    }
+
+    /* Verify the gckCOMMAND object pointer. */
+    command = Hardware->kernel->command;
+
+    /* Acquire the command queue. */
+    gcmkONERROR(gckCOMMAND_EnterCommit(command, gcvFALSE));
+    commitEntered = gcvTRUE;
+
+    gcmkONERROR(gckCOMMAND_Reserve(
+        command, 8, &pointer, &bufferSize
+        ));
+
+    buffer = pointer;
+
+    buffer[0]
+        = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (reg) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+    buffer[1] = flush;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+        "0x%x: FLUSH MMU(loadstate reg 0x%04x with 0x%08x)", buffer, reg, flush);
+
+    gcmkONERROR(gckCOMMAND_Execute(command, 8));
+
+    /* Release the command queue. */
+    gcmkONERROR(gckCOMMAND_ExitCommit(command, gcvFALSE));
+    commitEntered = gcvFALSE;
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (commitEntered)
+    {
+        /* Release the command queue mutex. */
+        gcmkVERIFY_OK(gckCOMMAND_ExitCommit(Hardware->kernel->command,
+                                            gcvFALSE));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_SetMMUv2
+**
+**  Set the page table base address.
+**
+**  INPUT:
+**
+**      gckHARDWARE Harwdare
+**          Pointer to an gckHARDWARE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHARDWARE_SetMMUv2(
+    IN gckHARDWARE Hardware,
+    IN gctBOOL Enable,
+    IN gctPOINTER MtlbAddress,
+    IN gceMMU_MODE Mode,
+    IN gctPOINTER SafeAddress
+    )
+{
+    gceSTATUS status;
+    gctUINT32 config, address;
+    gckCOMMAND command;
+    gctUINT32_PTR buffer;
+    gctSIZE_T bufferSize;
+    gctBOOL commitEntered = gcvFALSE;
+    gctPOINTER pointer = gcvNULL;
+
+    gcmkHEADER_ARG("Hardware=0x%x Enable=%d", Hardware, Enable);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Convert logical address into physical address. */
+    gcmkONERROR(
+        gckOS_GetPhysicalAddress(Hardware->os, MtlbAddress, &config));
+
+    gcmkONERROR(
+        gckOS_GetPhysicalAddress(Hardware->os, SafeAddress, &address));
+
+    if (address & 0x3F)
+    {
+        gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+    }
+
+    switch (Mode)
+    {
+    case gcvMMU_MODE_1K:
+        if (config & 0x3FF)
+        {
+            gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+        }
+
+        config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+        break;
+
+    case gcvMMU_MODE_4K:
+        if (config & 0xFFF)
+        {
+            gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+        }
+
+        config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+        break;
+
+    default:
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    /* Verify the gckCOMMAND object pointer. */
+    command = Hardware->kernel->command;
+
+    /* Acquire the command queue. */
+    gcmkONERROR(gckCOMMAND_EnterCommit(command, gcvFALSE));
+    commitEntered = gcvTRUE;
+
+    gcmkONERROR(gckCOMMAND_Reserve(
+        command, 16, &pointer, &bufferSize
+        ));
+
+    buffer = pointer;
+
+    buffer[0]
+        = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+    buffer[1] = config;
+
+    buffer[2]
+        = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0060) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+    buffer[3] = address;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+        "Setup MMU: config=%08x, Safe Address=%08x\n.", config, address);
+
+    gcmkONERROR(gckCOMMAND_Execute(command, 16));
+
+    /* Release the command queue. */
+    gcmkONERROR(gckCOMMAND_ExitCommit(command, gcvFALSE));
+    commitEntered = gcvFALSE;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+        "call gckCOMMAND_Stall to make sure the config is done.\n ");
+
+    gcmkONERROR(gckCOMMAND_Stall(command, gcvFALSE));
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+        "Enable MMU through GCREG_MMU_CONTROL.");
+
+    /* Enable MMU. */
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os,
+                              Hardware->core,
+                              0x0018C,
+                              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (Enable) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))));
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+        "call gckCOMMAND_Stall to check MMU available.\n");
+
+    gcmkONERROR(gckCOMMAND_Stall(command, gcvFALSE));
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+        "The MMU is available.\n");
+
+    /* Return the status. */
+    gcmkFOOTER_NO();
+    return status;
+
+OnError:
+    if (commitEntered)
+    {
+        /* Release the command queue mutex. */
+        gcmkVERIFY_OK(gckCOMMAND_ExitCommit(Hardware->kernel->command,
+                                            gcvFALSE));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_BuildVirtualAddress
+**
+**  Build a virtual address.
+**
+**  INPUT:
+**
+**      gckHARDWARE Harwdare
+**          Pointer to an gckHARDWARE object.
+**
+**      gctUINT32 Index
+**          Index into page table.
+**
+**      gctUINT32 Offset
+**          Offset into page.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Address
+**          Pointer to a variable receiving te hardware address.
+*/
+gceSTATUS
+gckHARDWARE_BuildVirtualAddress(
+    IN gckHARDWARE Hardware,
+    IN gctUINT32 Index,
+    IN gctUINT32 Offset,
+    OUT gctUINT32 * Address
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x Index=%u Offset=%u", Hardware, Index, Offset);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    /* Build virtual address. */
+    *Address = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
+             | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (Offset | (Index << 12)) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)));
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Address=0x%08x", *Address);
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_GetIdle(
+    IN gckHARDWARE Hardware,
+    IN gctBOOL Wait,
+    OUT gctUINT32 * Data
+    )
+{
+    gceSTATUS status;
+    gctUINT32 idle = 0;
+    gctINT retry, poll, pollCount;
+
+    gcmkHEADER_ARG("Hardware=0x%x Wait=%d", Hardware, Wait);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+
+    /* If we have to wait, try 100 polls per millisecond. */
+    pollCount = Wait ? 100 : 1;
+
+    /* At most, try for 1 second. */
+    for (retry = 0; retry < 1000; ++retry)
+    {
+        /* If we have to wait, try 100 polls per millisecond. */
+        for (poll = pollCount; poll > 0; --poll)
+        {
+            /* Read register. */
+            gcmkONERROR(
+                gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00004, &idle));
+
+            /* See if we have to wait for FE idle. */
+            if ((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+            {
+                /* FE is idle. */
+                break;
+            }
+        }
+
+        /* Check if we need to wait for FE and FE is busy. */
+        if (Wait && !(((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+        {
+            /* Wait a little. */
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                           "%s: Waiting for idle: 0x%08X",
+                           __FUNCTION__, idle);
+
+            gcmkVERIFY_OK(gckOS_Delay(Hardware->os, 1));
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    /* Return idle to caller. */
+    *Data = idle;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Data=0x%08x", *Data);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/* Flush the caches. */
+gceSTATUS
+gckHARDWARE_Flush(
+    IN gckHARDWARE Hardware,
+    IN gceKERNEL_FLUSH Flush,
+    IN gctPOINTER Logical,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gctUINT32 pipe;
+    gctUINT32 flush = 0;
+    gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x Flush=0x%x Logical=0x%x *Bytes=%lu",
+                   Hardware, Flush, Logical, gcmOPT_VALUE(Bytes));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Get current pipe. */
+    pipe = Hardware->kernel->command->pipeSelect;
+
+    /* Flush 3D color cache. */
+    if ((Flush & gcvFLUSH_COLOR) && (pipe == 0x0))
+    {
+        flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)));
+    }
+
+    /* Flush 3D depth cache. */
+    if ((Flush & gcvFLUSH_DEPTH) && (pipe == 0x0))
+    {
+        flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+    }
+
+    /* Flush 3D texture cache. */
+    if ((Flush & gcvFLUSH_TEXTURE) && (pipe == 0x0))
+    {
+        flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)));
+    }
+
+    /* Flush 2D cache. */
+    if ((Flush & gcvFLUSH_2D) && (pipe == 0x1))
+    {
+        flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)));
+    }
+
+    /* See if there is a valid flush. */
+    if (flush == 0)
+    {
+        if (Bytes != gcvNULL)
+        {
+            /* No bytes required. */
+            *Bytes = 0;
+        }
+    }
+
+    else
+    {
+        /* Copy to command queue. */
+        if (Logical != gcvNULL)
+        {
+            if (*Bytes < 8)
+            {
+                /* Command queue too small. */
+                gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+            }
+
+            /* Append LOAD_STATE to AQFlush. */
+            logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                       | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+                       | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+            logical[1] = flush;
+
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                           "0x%x: FLUSH 0x%x", logical, flush);
+        }
+
+        if (Bytes != gcvNULL)
+        {
+            /* 8 bytes required. */
+            *Bytes = 8;
+        }
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckHARDWARE_SetFastClear(
+    IN gckHARDWARE Hardware,
+    IN gctINT Enable,
+    IN gctINT Compression
+    )
+{
+#ifndef VIVANTE_NO_3D
+    gctUINT32 debug;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x Enable=%d Compression=%d",
+                   Hardware, Enable, Compression);
+
+    /* Only process if fast clear is available. */
+    if ((((((gctUINT32) (Hardware->chipFeatures)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+    {
+        if (Enable == -1)
+        {
+            /* Determine automatic value for fast clear. */
+            Enable = ((Hardware->chipModel    != gcv500)
+                     || (Hardware->chipRevision >= 3)
+                     ) ? 1 : 0;
+        }
+
+        if (Compression == -1)
+        {
+            /* Determine automatic value for compression. */
+            Compression = Enable
+                        & (((((gctUINT32) (Hardware->chipFeatures)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) );
+        }
+
+        /* Read AQMemoryDebug register. */
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00414, &debug));
+
+        /* Set fast clear bypass. */
+        debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20)));
+
+        /* Set compression bypass. */
+        debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))) << (0 ? 21:21))) | (((gctUINT32) ((gctUINT32) (Compression == 0) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))) << (0 ? 21:21)));
+
+        /* Write back AQMemoryDebug register. */
+        gcmkONERROR(
+            gckOS_WriteRegisterEx(Hardware->os,
+                                  Hardware->core,
+                                  0x00414,
+                                  debug));
+
+        /* Store fast clear and comprersison flags. */
+        Hardware->allowFastClear   = Enable;
+        Hardware->allowCompression = Compression;
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "FastClear=%d Compression=%d", Enable, Compression);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+#else
+    return gcvSTATUS_OK;
+#endif
+}
+
+typedef enum
+{
+    gcvPOWER_FLAG_INITIALIZE    = 1 << 0,
+    gcvPOWER_FLAG_STALL         = 1 << 1,
+    gcvPOWER_FLAG_STOP          = 1 << 2,
+    gcvPOWER_FLAG_START         = 1 << 3,
+    gcvPOWER_FLAG_RELEASE       = 1 << 4,
+    gcvPOWER_FLAG_DELAY         = 1 << 5,
+    gcvPOWER_FLAG_SAVE          = 1 << 6,
+    gcvPOWER_FLAG_ACQUIRE       = 1 << 7,
+    gcvPOWER_FLAG_POWER_OFF     = 1 << 8,
+    gcvPOWER_FLAG_CLOCK_OFF     = 1 << 9,
+    gcvPOWER_FLAG_CLOCK_ON      = 1 << 10,
+}
+gcePOWER_FLAGS;
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE) && gcdPOWER_MANAGEMENT
+static gctCONST_STRING
+_PowerEnum(gceCHIPPOWERSTATE State)
+{
+    const gctCONST_STRING states[] =
+    {
+        gcmSTRING(gcvPOWER_ON),
+        gcmSTRING(gcvPOWER_OFF),
+        gcmSTRING(gcvPOWER_IDLE),
+        gcmSTRING(gcvPOWER_SUSPEND),
+        gcmSTRING(gcvPOWER_SUSPEND_ATPOWERON),
+        gcmSTRING(gcvPOWER_OFF_ATPOWERON),
+        gcmSTRING(gcvPOWER_IDLE_BROADCAST),
+        gcmSTRING(gcvPOWER_SUSPEND_BROADCAST),
+        gcmSTRING(gcvPOWER_OFF_BROADCAST),
+        gcmSTRING(gcvPOWER_OFF_RECOVERY),
+        gcmSTRING(gcvPOWER_ON_AUTO)
+    };
+
+    if ((State >= gcvPOWER_ON) && (State <= gcvPOWER_ON_AUTO))
+    {
+        return states[State - gcvPOWER_ON];
+    }
+
+    return "unknown";
+}
+#endif
+
+/*******************************************************************************
+**
+**  gckHARDWARE_SetPowerManagementState
+**
+**  Set GPU to a specified power state.
+**
+**  INPUT:
+**
+**      gckHARDWARE Harwdare
+**          Pointer to an gckHARDWARE object.
+**
+**      gceCHIPPOWERSTATE State
+**          Power State.
+**
+*/
+gceSTATUS
+gckHARDWARE_SetPowerManagementState(
+    IN gckHARDWARE Hardware,
+    IN gceCHIPPOWERSTATE State
+    )
+{
+#if gcdPOWER_MANAGEMENT
+    gceSTATUS status;
+    gckCOMMAND command = gcvNULL;
+    gckOS os;
+    gctUINT flag, clock;
+    gctPOINTER buffer;
+    gctSIZE_T bytes, requested;
+    gctBOOL acquired = gcvFALSE;
+    gctBOOL mutexAcquired = gcvFALSE;
+    gctBOOL stall = gcvTRUE;
+    gctBOOL broadcast = gcvFALSE;
+#if gcdPOWEROFF_TIMEOUT
+    gctBOOL timeout = gcvFALSE;
+    gctBOOL isAfter = gcvFALSE;
+    gctUINT32 currentTime;
+#endif
+    gctUINT32 process, thread;
+    gctBOOL commitEntered = gcvFALSE;
+#if gcdENABLE_PROFILING
+    gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
+              initTime, offTime, startTime, totalTime;
+#endif
+    gctBOOL global = gcvFALSE;
+    gctBOOL globalAcquired = gcvFALSE;
+
+    /* State transition flags. */
+    static const gctUINT flags[4][4] =
+    {
+        /* gcvPOWER_ON           */
+        {   /* ON                */ 0,
+            /* OFF               */ gcvPOWER_FLAG_ACQUIRE   |
+                                    gcvPOWER_FLAG_STALL     |
+                                    gcvPOWER_FLAG_STOP      |
+                                    gcvPOWER_FLAG_POWER_OFF |
+                                    gcvPOWER_FLAG_CLOCK_OFF,
+            /* IDLE              */ gcvPOWER_FLAG_ACQUIRE   |
+                                    gcvPOWER_FLAG_STALL,
+            /* SUSPEND           */ gcvPOWER_FLAG_ACQUIRE   |
+                                    gcvPOWER_FLAG_STALL     |
+                                    gcvPOWER_FLAG_STOP      |
+                                    gcvPOWER_FLAG_CLOCK_OFF,
+        },
+
+        /* gcvPOWER_OFF          */
+        {   /* ON                */ gcvPOWER_FLAG_INITIALIZE |
+                                    gcvPOWER_FLAG_START      |
+                                    gcvPOWER_FLAG_RELEASE    |
+                                    gcvPOWER_FLAG_DELAY,
+            /* OFF               */ 0,
+            /* IDLE              */ gcvPOWER_FLAG_INITIALIZE |
+                                    gcvPOWER_FLAG_START      |
+                                    gcvPOWER_FLAG_DELAY,
+            /* SUSPEND           */ gcvPOWER_FLAG_INITIALIZE |
+                                    gcvPOWER_FLAG_CLOCK_OFF,
+        },
+
+        /* gcvPOWER_IDLE         */
+        {   /* ON                */ gcvPOWER_FLAG_RELEASE,
+            /* OFF               */ gcvPOWER_FLAG_STOP      |
+                                    gcvPOWER_FLAG_POWER_OFF |
+                                    gcvPOWER_FLAG_CLOCK_OFF,
+            /* IDLE              */ 0,
+            /* SUSPEND           */ gcvPOWER_FLAG_STOP      |
+                                    gcvPOWER_FLAG_CLOCK_OFF,
+        },
+
+        /* gcvPOWER_SUSPEND      */
+        {   /* ON                */ gcvPOWER_FLAG_START     |
+                                    gcvPOWER_FLAG_RELEASE   |
+                                    gcvPOWER_FLAG_DELAY     |
+                                    gcvPOWER_FLAG_CLOCK_ON,
+            /* OFF               */ gcvPOWER_FLAG_SAVE      |
+                                    gcvPOWER_FLAG_POWER_OFF |
+                                    gcvPOWER_FLAG_CLOCK_OFF,
+            /* IDLE              */ gcvPOWER_FLAG_START     |
+                                    gcvPOWER_FLAG_DELAY     |
+                                    gcvPOWER_FLAG_CLOCK_ON,
+            /* SUSPEND           */ 0,
+        },
+    };
+
+    /* Clocks. */
+    static const gctUINT clocks[4] =
+    {
+        /* gcvPOWER_ON */
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (64) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))),
+
+        /* gcvPOWER_OFF */
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))),
+
+        /* gcvPOWER_IDLE */
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))),
+
+        /* gcvPOWER_SUSPEND */
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))),
+    };
+
+    gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Switching to power state %d(%s)",
+                   State, _PowerEnum(State));
+#endif
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Get the gckOS object pointer. */
+    os = Hardware->os;
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+    /* Get the gckCOMMAND object pointer. */
+    gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
+    command = Hardware->kernel->command;
+    gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
+    /* Start profiler. */
+    gcmkPROFILE_INIT(freq, time);
+
+    /* Convert the broadcast power state. */
+    switch (State)
+    {
+    case gcvPOWER_SUSPEND_ATPOWERON:
+        /* Convert to SUSPEND and don't wait for STALL. */
+        State = gcvPOWER_SUSPEND;
+        stall = gcvFALSE;
+        break;
+
+    case gcvPOWER_OFF_ATPOWERON:
+        /* Convert to OFF and don't wait for STALL. */
+        State = gcvPOWER_OFF;
+        stall = gcvFALSE;
+        break;
+
+    case gcvPOWER_IDLE_BROADCAST:
+        /* Convert to IDLE and note we are inside broadcast. */
+        State     = gcvPOWER_IDLE;
+        broadcast = gcvTRUE;
+        break;
+
+    case gcvPOWER_SUSPEND_BROADCAST:
+        /* Convert to SUSPEND and note we are inside broadcast. */
+        State     = gcvPOWER_SUSPEND;
+        broadcast = gcvTRUE;
+        break;
+
+    case gcvPOWER_OFF_BROADCAST:
+        /* Convert to OFF and note we are inside broadcast. */
+        State     = gcvPOWER_OFF;
+        broadcast = gcvTRUE;
+        break;
+
+    case gcvPOWER_OFF_RECOVERY:
+        /* Convert to OFF and note we are inside recovery. */
+        State     = gcvPOWER_OFF;
+        stall     = gcvFALSE;
+        broadcast = gcvTRUE;
+        break;
+
+    case gcvPOWER_ON_AUTO:
+        /* Convert to ON and note we are inside recovery. */
+        State = gcvPOWER_ON;
+        break;
+
+    case gcvPOWER_ON:
+    case gcvPOWER_IDLE:
+    case gcvPOWER_SUSPEND:
+    case gcvPOWER_OFF:
+        /* Mark as global power management. */
+        global = gcvTRUE;
+        break;
+
+#if gcdPOWEROFF_TIMEOUT
+    case gcvPOWER_OFF_TIMEOUT:
+        /* Convert to OFF and note we are inside broadcast. */
+        State     = gcvPOWER_OFF;
+        broadcast = gcvTRUE;
+        /* Check time out */
+        timeout = gcvTRUE;
+        break;
+#endif
+
+    default:
+        break;
+    }
+
+    /* Get current process and thread IDs. */
+    gcmkONERROR(gckOS_GetProcessID(&process));
+    gcmkONERROR(gckOS_GetThreadID(&thread));
+
+    if (broadcast)
+    {
+        /* Try to acquire the power mutex. */
+        status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
+
+        if (status == gcvSTATUS_TIMEOUT)
+        {
+            /* Check if we already own this mutex. */
+            if ((Hardware->powerProcess == process)
+            &&  (Hardware->powerThread  == thread)
+            )
+            {
+                /* Bail out on recursive power management. */
+                gcmkFOOTER_NO();
+                return gcvSTATUS_OK;
+            }
+            else if (State == gcvPOWER_IDLE)
+            {
+                /* gcvPOWER_IDLE_BROADCAST is from IST,
+                ** so waiting here will cause deadlock,
+                ** if lock holder call gckCOMMAND_Stall() */
+                gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+            }
+            else
+            {
+                /* Acquire the power mutex. */
+                gcmkONERROR(gckOS_AcquireMutex(os,
+                                               Hardware->powerMutex,
+                                               gcvINFINITE));
+            }
+        }
+    }
+    else
+    {
+        /* Acquire the power mutex. */
+        gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
+    }
+
+    /* Get time until mtuex acquired. */
+    gcmkPROFILE_QUERY(time, mutexTime);
+
+    Hardware->powerProcess = process;
+    Hardware->powerThread  = thread;
+    mutexAcquired          = gcvTRUE;
+
+    /* Grab control flags and clock. */
+    flag  = flags[Hardware->chipPowerState][State];
+    clock = clocks[State];
+
+#if gcdPOWEROFF_TIMEOUT
+    if (timeout)
+    {
+        gcmkONERROR(gckOS_GetTicks(&currentTime));
+
+        gcmkONERROR(
+            gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
+
+        if (isAfter || Hardware->chipPowerState != gcvPOWER_IDLE)
+        {
+            /* Release the power mutex. */
+            gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+            /* No need to do anything. */
+            gcmkFOOTER_NO();
+            return gcvSTATUS_OK;
+        }
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "Power Off GPU at %i [supposed to be at %i]",
+                       currentTime, Hardware->powerOffTime);
+    }
+#endif
+
+    if (flag == 0)
+    {
+        /* Release the power mutex. */
+        gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+        /* No need to do anything. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+    /* If this is an internal power management, we have to check if we can grab
+    ** the global power semaphore. If we cannot, we have to wait until the
+    ** external world changes power management. */
+    if (!global)
+    {
+        /* Try to acquire the global semaphore. */
+        status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
+        if (status == gcvSTATUS_TIMEOUT)
+        {
+            /* Release the power mutex. */
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                           "Releasing the power mutex.");
+            gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+            mutexAcquired = gcvFALSE;
+
+            /* Wait for the semaphore. */
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                           "Waiting for global semaphore.");
+            gcmkONERROR(gckOS_AcquireSemaphore(os, Hardware->globalSemaphore));
+            globalAcquired = gcvTRUE;
+
+            /* Acquire the power mutex. */
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                           "Reacquiring the power mutex.");
+            gcmkONERROR(gckOS_AcquireMutex(os,
+                                           Hardware->powerMutex,
+                                           gcvINFINITE));
+            mutexAcquired = gcvTRUE;
+        }
+        else
+        {
+            /* Error. */
+            gcmkONERROR(status);
+        }
+
+        /* Release the global semaphore again. */
+        gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
+        globalAcquired = gcvFALSE;
+    }
+
+    if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
+    {
+        /* Turn on the power. */
+        gcmkONERROR(gckOS_SetGPUPower(os, gcvTRUE, gcvTRUE));
+
+        /* Mark clock and power as enabled. */
+        Hardware->clockState = gcvTRUE;
+        Hardware->powerState = gcvTRUE;
+    }
+
+    /* Get time until powered on. */
+    gcmkPROFILE_QUERY(time, onTime);
+
+    if ((flag & gcvPOWER_FLAG_STALL) && stall)
+    {
+        gctBOOL idle;
+        gctINT32 atomValue;
+
+        /* Check commit atom. */
+        gcmkONERROR(gckOS_AtomGet(os, command->atomCommit, &atomValue));
+
+        if (atomValue > 0)
+        {
+            /* Commits are pending - abort power management. */
+            status = broadcast ? gcvSTATUS_CHIP_NOT_READY
+                               : gcvSTATUS_MORE_DATA;
+            goto OnError;
+        }
+
+        if (broadcast)
+        {
+            /* Check for idle. */
+            gcmkONERROR(gckHARDWARE_QueryIdle(Hardware, &idle));
+
+            if (!idle)
+            {
+                status = gcvSTATUS_CHIP_NOT_READY;
+                goto OnError;
+            }
+        }
+
+        else
+        {
+            /* Acquire the command queue. */
+            gcmkONERROR(gckCOMMAND_EnterCommit(command, gcvTRUE));
+            commitEntered = gcvTRUE;
+
+            /* Get the size of the flush command. */
+            gcmkONERROR(gckHARDWARE_Flush(Hardware,
+                                          gcvFLUSH_ALL,
+                                          gcvNULL,
+                                          &requested));
+
+            /* Reserve space in the command queue. */
+            gcmkONERROR(gckCOMMAND_Reserve(command,
+                                           requested,
+                                           &buffer,
+                                           &bytes));
+
+            /* Append a flush. */
+            gcmkONERROR(gckHARDWARE_Flush(
+                Hardware, gcvFLUSH_ALL, buffer, &bytes
+                ));
+
+            /* Execute the command queue. */
+            gcmkONERROR(gckCOMMAND_Execute(command, requested));
+
+            /* Release the command queue. */
+            gcmkONERROR(gckCOMMAND_ExitCommit(command, gcvTRUE));
+            commitEntered = gcvFALSE;
+
+            /* Wait to finish all commands. */
+            gcmkONERROR(gckCOMMAND_Stall(command, gcvTRUE));
+        }
+    }
+
+    /* Get time until stalled. */
+    gcmkPROFILE_QUERY(time, stallTime);
+
+    if (flag & gcvPOWER_FLAG_ACQUIRE)
+    {
+        /* Acquire the power management semaphore. */
+        gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+        acquired = gcvTRUE;
+
+        if (global)
+        {
+            /* Acquire the global semaphore. */
+            gcmkONERROR(gckOS_AcquireSemaphore(os, Hardware->globalSemaphore));
+            globalAcquired = gcvTRUE;
+        }
+    }
+
+    if (flag & gcvPOWER_FLAG_STOP)
+    {
+        /* Stop the command parser. */
+        gcmkONERROR(gckCOMMAND_Stop(command));
+
+        /* Stop the Isr. */
+        gcmkONERROR(Hardware->stopIsr(Hardware->isrContext));
+   }
+
+    /* Get time until stopped. */
+    gcmkPROFILE_QUERY(time, stopTime);
+
+    /* Only process this when hardware is enabled. */
+    if (Hardware->clockState && Hardware->powerState)
+    {
+        /* Write the clock control register. */
+        gcmkONERROR(gckOS_WriteRegisterEx(os,
+                                          Hardware->core,
+                                          0x00000,
+                                          clock));
+
+        /* Done loading the frequency scaler. */
+        gcmkONERROR(gckOS_WriteRegisterEx(os,
+                                          Hardware->core,
+                                          0x00000,
+                                          ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
+    }
+
+    if (flag & gcvPOWER_FLAG_DELAY)
+    {
+        /* Wait for the specified amount of time to settle coming back from
+        ** power-off or suspend state. */
+        gcmkONERROR(gckOS_Delay(os, gcdPOWER_CONTROL_DELAY));
+    }
+
+    /* Get time until delayed. */
+    gcmkPROFILE_QUERY(time, delayTime);
+
+    if (flag & gcvPOWER_FLAG_INITIALIZE)
+    {
+        /* Initialize hardware. */
+        gcmkONERROR(gckHARDWARE_InitializeHardware(Hardware));
+
+        gcmkONERROR(gckHARDWARE_SetFastClear(Hardware,
+                                             Hardware->allowFastClear,
+                                             Hardware->allowCompression));
+
+        /* Force the command queue to reload the next context. */
+        command->currContext = gcvNULL;
+    }
+
+    /* Get time until initialized. */
+    gcmkPROFILE_QUERY(time, initTime);
+
+    if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
+    {
+        /* Turn off the GPU power. */
+        gcmkONERROR(
+            gckOS_SetGPUPower(os,
+                              (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
+                                                               : gcvTRUE,
+                              (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
+                                                               : gcvTRUE));
+
+        /* Save current hardware power and clock states. */
+        Hardware->clockState = (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
+                                                                : gcvTRUE;
+        Hardware->powerState = (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
+                                                                : gcvTRUE;
+    }
+
+    /* Get time until off. */
+    gcmkPROFILE_QUERY(time, offTime);
+
+    if (flag & gcvPOWER_FLAG_START)
+    {
+        /* Start the command processor. */
+        gcmkONERROR(gckCOMMAND_Start(command));
+
+        /* Start the Isr. */
+        gcmkONERROR(Hardware->startIsr(Hardware->isrContext));
+    }
+
+    /* Get time until started. */
+    gcmkPROFILE_QUERY(time, startTime);
+
+    if (flag & gcvPOWER_FLAG_RELEASE)
+    {
+        /* Release the power management semaphore. */
+        gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
+        acquired = gcvFALSE;
+
+        if (global)
+        {
+            /* Release the global semaphore. */
+            gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
+            globalAcquired = gcvFALSE;
+        }
+    }
+
+    /* Save the new power state. */
+    Hardware->chipPowerState = State;
+
+#if gcdPOWEROFF_TIMEOUT
+    /* Reset power off time */
+    gcmkONERROR(gckOS_GetTicks(&currentTime));
+
+    Hardware->powerOffTime = currentTime + gcdPOWEROFF_TIMEOUT;
+
+    if (State == gcvPOWER_IDLE)
+    {
+        gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerOffSema));
+    }
+#endif
+
+    /* Release the power mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+    /* Get total time. */
+    gcmkPROFILE_QUERY(time, totalTime);
+#if gcdENABLE_PROFILING
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "PROF(%llu): mutex:%llu on:%llu stall:%llu stop:%llu",
+                   freq, mutexTime, onTime, stallTime, stopTime);
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "  delay:%llu init:%llu off:%llu start:%llu total:%llu",
+                   delayTime, initTime, offTime, startTime, totalTime);
+#endif
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (commitEntered)
+    {
+        /* Release the command queue mutex. */
+        gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, gcvTRUE));
+    }
+
+    if (acquired)
+    {
+        /* Release semaphore. */
+        gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
+                                             command->powerSemaphore));
+    }
+
+    if (globalAcquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
+                                             Hardware->globalSemaphore));
+    }
+
+    if (mutexAcquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+#else /* gcdPOWER_MANAGEMENT */
+    /* Do nothing */
+    return gcvSTATUS_OK;
+#endif
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_QueryPowerManagementState
+**
+**  Get GPU power state.
+**
+**  INPUT:
+**
+**      gckHARDWARE Harwdare
+**          Pointer to an gckHARDWARE object.
+**
+**      gceCHIPPOWERSTATE* State
+**          Power State.
+**
+*/
+gceSTATUS
+gckHARDWARE_QueryPowerManagementState(
+    IN gckHARDWARE Hardware,
+    OUT gceCHIPPOWERSTATE* State
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(State != gcvNULL);
+
+    /* Return the statue. */
+    *State = Hardware->chipPowerState;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*State=%d", *State);
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_QueryIdle(
+    IN gckHARDWARE Hardware,
+    OUT gctBOOL_PTR IsIdle
+    )
+{
+    gceSTATUS status;
+    gctUINT32 idle, address;
+
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
+
+    /* We are idle when the power is not ON. */
+    if (Hardware->chipPowerState != gcvPOWER_ON)
+    {
+        *IsIdle = gcvTRUE;
+    }
+
+    else
+    {
+        /* Read idle register. */
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00004, &idle));
+
+        /* Pipe must be idle. */
+        if (((((((gctUINT32) (idle)) >> (0 ? 1:1)) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1)))))) ) != 1)
+        ||  ((((((gctUINT32) (idle)) >> (0 ? 3:3)) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) ) != 1)
+        ||  ((((((gctUINT32) (idle)) >> (0 ? 4:4)) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1)))))) ) != 1)
+        ||  ((((((gctUINT32) (idle)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) ) != 1)
+        ||  ((((((gctUINT32) (idle)) >> (0 ? 6:6)) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1)))))) ) != 1)
+        ||  ((((((gctUINT32) (idle)) >> (0 ? 7:7)) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1)))))) ) != 1)
+        ||  ((((((gctUINT32) (idle)) >> (0 ? 2:2)) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) ) != 1)
+        )
+        {
+            /* Something is busy. */
+            *IsIdle = gcvFALSE;
+        }
+
+        else
+        {
+            /* Read the current FE address. */
+            gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                             Hardware->core,
+                                             0x00664,
+                                             &address));
+
+            /* Test if address is inside the last WAIT/LINK sequence. */
+            if ((address >= Hardware->lastWaitLink)
+            &&  (address <= Hardware->lastWaitLink + 16)
+            )
+            {
+                /* FE is in last WAIT/LINK and the pipe is idle. */
+                *IsIdle = gcvTRUE;
+            }
+            else
+            {
+                /* FE is not in WAIT/LINK yet. */
+                *IsIdle = gcvFALSE;
+            }
+        }
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+** Handy macros that will help in reading those debug registers.
+*/
+
+#define gcmkREAD_DEBUG_REGISTER(control, block, index, data) \
+    gcmkONERROR(\
+        gckOS_WriteRegisterEx(Hardware->os, \
+                              Hardware->core, \
+                              GC_DEBUG_CONTROL##control##_Address, \
+                              gcmSETFIELD(0, \
+                                          GC_DEBUG_CONTROL##control, \
+                                          block, \
+                                          index))); \
+    gcmkONERROR(\
+        gckOS_ReadRegisterEx(Hardware->os, \
+                             Hardware->core, \
+                             GC_DEBUG_SIGNALS_##block##_Address, \
+                             &profiler->data))
+
+#define gcmkRESET_DEBUG_REGISTER(control, block) \
+    gcmkONERROR(\
+        gckOS_WriteRegisterEx(Hardware->os, \
+                              Hardware->core, \
+                              GC_DEBUG_CONTROL##control##_Address, \
+                              gcmSETFIELD(0, \
+                                          GC_DEBUG_CONTROL##control, \
+                                          block, \
+                                          15))); \
+    gcmkONERROR(\
+        gckOS_WriteRegisterEx(Hardware->os, \
+                              Hardware->core, \
+                              GC_DEBUG_CONTROL##control##_Address, \
+                              gcmSETFIELD(0, \
+                                          GC_DEBUG_CONTROL##control, \
+                                          block, \
+                                          0)))
+
+/*******************************************************************************
+**
+**  gckHARDWARE_ProfileEngine2D
+**
+**  Read the profile registers available in the 2D engine and sets them in the
+**  profile.  The function will also reset the pixelsRendered counter every time.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      OPTIONAL gcs2D_PROFILE_PTR Profile
+**          Pointer to a gcs2D_Profile structure.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ProfileEngine2D(
+    IN gckHARDWARE Hardware,
+    OPTIONAL gcs2D_PROFILE_PTR Profile
+    )
+{
+    gceSTATUS status;
+    gcs2D_PROFILE_PTR profiler = Profile;
+
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    if (Profile != gcvNULL)
+    {
+        /* Read the cycle count. */
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Hardware->os,
+                                 Hardware->core,
+                                 0x00438,
+                                 &Profile->cycleCount));
+
+        /* Read pixels rendered by 2D engine. */
+        gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->pixelsRendered));
+
+        /* Reset counter. */
+        gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16)))
+)));
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gckHARDWARE_QueryProfileRegisters(
+    IN gckHARDWARE Hardware,
+    OUT gcsPROFILER_COUNTERS * Counters
+    )
+{
+    gceSTATUS status;
+    gcsPROFILER_COUNTERS * profiler = Counters;
+
+    gcmkHEADER_ARG("Hardware=0x%x Counters=0x%x", Hardware, Counters);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Read the counters. */
+    gcmkONERROR(
+        gckOS_ReadRegisterEx(Hardware->os,
+                             Hardware->core,
+                             0x00040,
+                             &profiler->gpuTotalRead64BytesPerFrame));
+    gcmkONERROR(
+        gckOS_ReadRegisterEx(Hardware->os,
+                             Hardware->core,
+                             0x00044,
+                             &profiler->gpuTotalWrite64BytesPerFrame));
+    gcmkONERROR(
+        gckOS_ReadRegisterEx(Hardware->os,
+                             Hardware->core,
+                             0x00438,
+                             &profiler->gpuCyclesCounter));
+
+    /* Reset counters. */
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 0));
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00438, 0));
+
+    /* PE */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->pe_pixel_count_killed_by_color_pipe));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->pe_pixel_count_killed_by_depth_pipe));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->pe_pixel_count_drawn_by_color_pipe));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->pe_pixel_count_drawn_by_depth_pipe));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16)))
+)));
+
+    /* SH */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->ps_inst_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->rendered_pixel_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vs_inst_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->rendered_vertice_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vtx_branch_inst_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vtx_texld_inst_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_branch_inst_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_texld_inst_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)))
+)));
+
+    /* PA */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_vtx_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_prim_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_output_prim_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_depth_clipped_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_trivial_rejected_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_culled_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0)))
+)));
+
+    /* SE */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_triangle_count));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_lines_count));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8)))
+)));
+
+    /* RA */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_pixel_count));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_total_quad_count));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_quad_count_after_early_z));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_total_primitive_count));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_pipe_cache_miss_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_prefetch_cache_miss_counter));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16)))
+)));
+
+    /* TX */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_bilinear_requests));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_trilinear_requests));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_discarded_texture_requests));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_texture_requests));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_count));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_in_8B_count));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_count));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_hit_texel_count));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_texel_count));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)))
+)));
+
+    /* MC */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_pipeline));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_IP));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_write_req_8B_from_pipeline));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0)))
+)));
+
+    /* HI */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_read_request_stalled));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_request_stalled));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_data_stalled));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8)))
+)));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+#endif
+
+static gceSTATUS
+_ResetGPU(
+    IN gckOS Os,
+    IN gceCORE Core
+    )
+{
+    gctUINT32 control, idle;
+    gceSTATUS status;
+
+    /* Read register. */
+    gcmkONERROR(gckOS_ReadRegisterEx(Os,
+                                     Core,
+                                     0x00000,
+                                     &control));
+
+    for (;;)
+    {
+        /* Isolate the GPU. */
+        control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
+
+        gcmkONERROR(gckOS_WriteRegisterEx(Os,
+                                          Core,
+                                          0x00000,
+                                          control));
+
+        /* Set soft reset. */
+        gcmkONERROR(gckOS_WriteRegisterEx(Os,
+                                          Core,
+                                          0x00000,
+                                          ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
+
+        /* Wait for reset. */
+        gcmkONERROR(gckOS_Delay(Os, 1));
+
+        /* Reset soft reset bit. */
+        gcmkONERROR(gckOS_WriteRegisterEx(Os,
+                                          Core,
+                                          0x00000,
+                                          ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
+
+        /* Reset GPU isolation. */
+        control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
+
+        gcmkONERROR(gckOS_WriteRegisterEx(Os,
+                                          Core,
+                                          0x00000,
+                                          control));
+
+        /* Read idle register. */
+        gcmkONERROR(gckOS_ReadRegisterEx(Os,
+                                         Core,
+                                         0x00004,
+                                         &idle));
+
+        if ((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) == 0)
+        {
+            continue;
+        }
+
+        /* Read reset register. */
+        gcmkONERROR(gckOS_ReadRegisterEx(Os,
+                                         Core,
+                                         0x00000,
+                                         &control));
+
+        if (((((((gctUINT32) (control)) >> (0 ? 16:16)) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) ) == 0)
+        ||  ((((((gctUINT32) (control)) >> (0 ? 17:17)) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1)))))) ) == 0)
+        )
+        {
+            continue;
+        }
+
+        /* GPU is idle. */
+        break;
+    }
+
+    /* Success. */
+    return gcvSTATUS_OK;
+
+OnError:
+
+    /* Return the error. */
+    return status;
+}
+
+gceSTATUS
+gckHARDWARE_Reset(
+    IN gckHARDWARE Hardware
+    )
+{
+    gceSTATUS status;
+    gckCOMMAND command;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
+    command = Hardware->kernel->command;
+    gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
+    if (Hardware->chipRevision < 0x4600)
+    {
+        /* Not supported - we need the isolation bit. */
+        gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+    }
+
+    if (Hardware->chipPowerState == gcvPOWER_ON)
+    {
+        /* Acquire the power management semaphore. */
+        gcmkONERROR(
+            gckOS_AcquireSemaphore(Hardware->os, command->powerSemaphore));
+        acquired = gcvTRUE;
+    }
+
+    if ((Hardware->chipPowerState == gcvPOWER_ON)
+    ||  (Hardware->chipPowerState == gcvPOWER_IDLE)
+    )
+    {
+        /* Stop the command processor. */
+        gcmkONERROR(gckCOMMAND_Stop(command));
+    }
+
+    gcmkONERROR(_ResetGPU(Hardware->os, Hardware->core));
+
+    /* Force an OFF to ON power switch. */
+    Hardware->chipPowerState = gcvPOWER_OFF;
+    gcmkONERROR(gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the power management semaphore. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseSemaphore(Hardware->os, command->powerSemaphore));
+    }
+
+    /* Return the error. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckHARDWARE_GetBaseAddress(
+    IN gckHARDWARE Hardware,
+    OUT gctUINT32_PTR BaseAddress
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+    /* Test if we have a new Memory Controller. */
+    if (((((gctUINT32) (Hardware->chipMinorFeatures0)) >> (0 ? 22:22) & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))))
+    {
+        /* No base address required. */
+        *BaseAddress = 0;
+    }
+    else
+    {
+        /* Get the base address from the OS. */
+        gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, BaseAddress));
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckHARDWARE_NeedBaseAddress(
+    IN gckHARDWARE Hardware,
+    IN gctUINT32 State,
+    OUT gctBOOL_PTR NeedBase
+    )
+{
+    gctBOOL need = gcvFALSE;
+
+    gcmkHEADER_ARG("Hardware=0x%x State=0x%08x", Hardware, State);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(NeedBase != gcvNULL);
+
+    /* Make sure this is a load state. */
+    if (((((gctUINT32) (State)) >> (0 ? 31:27) & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))))
+    {
+#ifndef VIVANTE_NO_3D
+        /* Get the state address. */
+        switch ((((((gctUINT32) (State)) >> (0 ? 15:0)) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1)))))) ))
+        {
+        case 0x0596:
+        case 0x0597:
+        case 0x0599:
+        case 0x059A:
+        case 0x05A9:
+            /* These states need a TRUE physical address. */
+            need = gcvTRUE;
+            break;
+        }
+#else
+        /* 2D addresses don't need a base address. */
+#endif
+    }
+
+    /* Return the flag. */
+    *NeedBase = need;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*NeedBase=%d", *NeedBase);
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_SetIsrManager(
+   IN gckHARDWARE Hardware,
+   IN gctISRMANAGERFUNC StartIsr,
+   IN gctISRMANAGERFUNC StopIsr,
+   IN gctPOINTER Context
+   )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+
+    gcmkHEADER_ARG("Hardware=0x%x, StartIsr=0x%x, StopIsr=0x%x, Context=0x%x",
+                   Hardware, StartIsr, StopIsr, Context);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    if (StartIsr == gcvNULL ||
+        StopIsr == gcvNULL ||
+        Context == gcvNULL)
+    {
+        status = gcvSTATUS_INVALID_ARGUMENT;
+
+        gcmkFOOTER();
+        return status;
+    }
+
+    Hardware->startIsr = StartIsr;
+    Hardware->stopIsr = StopIsr;
+    Hardware->isrContext = Context;
+
+    /* Success. */
+    gcmkFOOTER();
+
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_Compose
+**
+**  Start a composition.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to the gckHARDWARE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Compose(
+    IN gckHARDWARE Hardware,
+    IN gctUINT32 ProcessID,
+    IN gctSIZE_T Size,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical,
+    IN gctUINT8 EventID
+    )
+{
+#ifndef VIVANTE_NO_3D
+    gceSTATUS status;
+    gctUINT32_PTR sizeState;
+    gctUINT32_PTR triggerState;
+    gctUINT32_PTR dummyState;
+    gctSIZE_T size;
+
+    gcmkHEADER_ARG("Hardware=0x%x Size=%d Physical=0x%x"
+                   " Logical=0x%x EventID=%d",
+                   Hardware, Size, Physical, Logical, EventID);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT((Size & 7) == 0);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+    /* Make total state buffer size 64B aligned. */
+    size = gcmALIGN(Size + 16, 64) - 8;
+
+    /* Program the size of the state buffer. */
+    sizeState = (gctUINT32_PTR) Logical;
+    sizeState[0] = 0xFFFFFFFF;
+    sizeState[1] = size >> 3;
+
+    /* Program the trigger state. */
+    triggerState = (gctUINT32_PTR) ((gctUINT8_PTR) Logical + Size);
+    triggerState[0] = 0x0C03;
+    triggerState[1]
+        = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)))
+        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:4) - (0 ? 5:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:4) - (0 ? 5:4) + 1))))))) << (0 ? 5:4))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 5:4) - (0 ? 5:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:4) - (0 ? 5:4) + 1))))))) << (0 ? 5:4)))
+        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8)))
+        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24)))
+        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))
+        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:16) - (0 ? 20:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:16) - (0 ? 20:16) + 1))))))) << (0 ? 20:16))) | (((gctUINT32) ((gctUINT32) (EventID) & ((gctUINT32) ((((1 ? 20:16) - (0 ? 20:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:16) - (0 ? 20:16) + 1))))))) << (0 ? 20:16)))
+        ;
+
+    /* Dummy state padding. */
+    dummyState = triggerState + 2;
+
+    while (Size < size)
+    {
+        dummyState[0] = 0xFFFFFFFF;
+        dummyState[1] = 0x00000000;
+
+        dummyState += 2;
+        Size       += 8;
+    }
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+    /* Flush the cache for the wait/link. */
+    gcmkONERROR(gckOS_CacheClean(
+        Hardware->os, ProcessID, gcvNULL, Physical, Logical, size
+        ));
+#endif
+
+    /* Start composition. */
+    gcmkONERROR(gckOS_WriteRegisterEx(
+        Hardware->os, Hardware->core, 0x00554,
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)))
+        ));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+#else
+    /* Return the status. */
+    return gcvSTATUS_NOT_SUPPORTED;
+#endif
+}
+
+/*******************************************************************************
+**
+**  gckHARDWARE_IsFeatureAvailable
+**
+**  Verifies whether the specified feature is available in hardware.
+**
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gceFEATURE Feature
+**          Feature to be verified.
+*/
+gceSTATUS
+gckHARDWARE_IsFeatureAvailable(
+    IN gckHARDWARE Hardware,
+    IN gceFEATURE Feature
+    )
+{
+    gctBOOL available;
+
+    gcmkHEADER_ARG("Hardware=0x%x Feature=%d", Hardware, Feature);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Only features needed by common kernel logic added here. */
+    switch (Feature)
+    {
+    case gcvFEATURE_END_EVENT:
+        /*available = gcmVERIFYFIELDVALUE(Hardware->chipMinorFeatures2,
+            GC_MINOR_FEATURES2, END_EVENT, AVAILABLE
+            );*/
+        available = gcvFALSE;
+        break;
+
+    default:
+        gcmkFATAL("Invalid feature has been requested.");
+        available = gcvFALSE;
+    }
+
+    /* Return result. */
+    gcmkFOOTER_ARG("%d", available ? gcvSTATUS_TRUE : gcvSTATUS_OK);
+    return available ? gcvSTATUS_TRUE : gcvSTATUS_OK;
+}
+
+#if gcdFRAME_DB
+static gceSTATUS
+gckHARDWARE_ReadPerformanceRegister(
+    IN gckHARDWARE Hardware,
+    IN gctUINT PerformanceAddress,
+    IN gctUINT IndexAddress,
+    IN gctUINT IndexShift,
+    IN gctUINT Index,
+    OUT gctUINT32_PTR Value
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x PerformanceAddress=0x%x IndexAddress=0x%x "
+                   "IndexShift=%u Index=%u",
+                   Hardware, PerformanceAddress, IndexAddress, IndexShift,
+                   Index);
+
+    /* Write the index. */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      IndexAddress,
+                                      Index << IndexShift));
+
+    /* Read the register. */
+    gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                     Hardware->core,
+                                     PerformanceAddress,
+                                     Value));
+
+    /* Test for reset. */
+    if (Index == 15)
+    {
+        /* Index another register to get out of reset. */
+        gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, IndexAddress, 0));
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Value=0x%x", *Value);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckHARDWARE_GetFrameInfo(
+    IN gckHARDWARE Hardware,
+    OUT gcsHAL_FRAME_INFO * FrameInfo
+    )
+{
+    gceSTATUS status;
+    gctUINT i, clock;
+    gcsHAL_FRAME_INFO info;
+#if gcdFRAME_DB_RESET
+       gctUINT reset;
+#endif
+
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Get profile tick. */
+    gcmkONERROR(gckOS_GetProfileTick(&info.ticks));
+
+    /* Read SH counters and reset them. */
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x0045C,
+        0x00470,
+        24,
+        4,
+        &info.shaderCycles));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x0045C,
+        0x00470,
+        24,
+        9,
+        &info.vsInstructionCount));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x0045C,
+        0x00470,
+        24,
+        12,
+        &info.vsTextureCount));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x0045C,
+        0x00470,
+        24,
+        7,
+        &info.psInstructionCount));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x0045C,
+        0x00470,
+        24,
+        14,
+        &info.psTextureCount));
+#if gcdFRAME_DB_RESET
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x0045C,
+        0x00470,
+        24,
+        15,
+        &reset));
+#endif
+
+    /* Read PA counters and reset them. */
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00460,
+        0x00474,
+        0,
+        3,
+        &info.vertexCount));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00460,
+        0x00474,
+        0,
+        4,
+        &info.primitiveCount));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00460,
+        0x00474,
+        0,
+        7,
+        &info.rejectedPrimitives));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00460,
+        0x00474,
+        0,
+        8,
+        &info.culledPrimitives));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00460,
+        0x00474,
+        0,
+        6,
+        &info.clippedPrimitives));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00460,
+        0x00474,
+        0,
+        5,
+        &info.outPrimitives));
+#if gcdFRAME_DB_RESET
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00460,
+        0x00474,
+        0,
+        15,
+        &reset));
+#endif
+
+    /* Read RA counters and reset them. */
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00448,
+        0x00474,
+        16,
+        3,
+        &info.inPrimitives));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00448,
+        0x00474,
+        16,
+        11,
+        &info.culledQuadCount));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00448,
+        0x00474,
+        16,
+        1,
+        &info.totalQuadCount));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00448,
+        0x00474,
+        16,
+        2,
+        &info.quadCount));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00448,
+        0x00474,
+        16,
+        0,
+        &info.totalPixelCount));
+#if gcdFRAME_DB_RESET
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00448,
+        0x00474,
+        16,
+        15,
+        &reset));
+#endif
+
+    /* Read TX counters and reset them. */
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x0044C,
+        0x00474,
+        24,
+        0,
+        &info.bilinearRequests));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x0044C,
+        0x00474,
+        24,
+        1,
+        &info.trilinearRequests));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x0044C,
+        0x00474,
+        24,
+        8,
+        &info.txHitCount));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x0044C,
+        0x00474,
+        24,
+        9,
+        &info.txMissCount));
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x0044C,
+        0x00474,
+        24,
+        6,
+        &info.txBytes8));
+#if gcdFRAME_DB_RESET
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x0044C,
+        0x00474,
+        24,
+        15,
+        &reset));
+#endif
+
+    /* Read clock control register. */
+    gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                     Hardware->core,
+                                     0x00000,
+                                     &clock));
+
+    /* Walk through all avaiable pixel pipes. */
+    for (i = 0; i < Hardware->pixelPipes; ++i)
+    {
+        /* Select proper pipe. */
+        gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                          Hardware->core,
+                                          0x00000,
+                                          ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20)))));
+
+        /* Read cycle registers. */
+        gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                         Hardware->core,
+                                         0x00078,
+                                         &info.cycles[i]));
+        gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                         Hardware->core,
+                                         0x0007C,
+                                         &info.idleCycles[i]));
+        gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                         Hardware->core,
+                                         0x00438,
+                                         &info.mcCycles[i]));
+
+        /* Read bandwidth registers. */
+        gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                         Hardware->core,
+                                         0x0005C,
+                                         &info.readRequests[i]));
+        gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                         Hardware->core,
+                                         0x00040,
+                                         &info.readBytes8[i]));
+        gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                         Hardware->core,
+                                         0x00050,
+                                         &info.writeRequests[i]));
+        gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                         Hardware->core,
+                                         0x00044,
+                                         &info.writeBytes8[i]));
+
+        /* Read PE counters. */
+        gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+            Hardware,
+            0x00454,
+            0x00470,
+            16,
+            0,
+            &info.colorKilled[i]));
+        gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+            Hardware,
+            0x00454,
+            0x00470,
+            16,
+            2,
+            &info.colorDrawn[i]));
+        gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+            Hardware,
+            0x00454,
+            0x00470,
+            16,
+            1,
+            &info.depthKilled[i]));
+        gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+            Hardware,
+            0x00454,
+            0x00470,
+            16,
+            3,
+            &info.depthDrawn[i]));
+    }
+
+    /* Zero out remaning reserved counters. */
+    for (; i < 8; ++i)
+    {
+        info.readBytes8[i]    = 0;
+        info.writeBytes8[i]   = 0;
+        info.cycles[i]        = 0;
+        info.idleCycles[i]    = 0;
+        info.mcCycles[i]      = 0;
+        info.readRequests[i]  = 0;
+        info.writeRequests[i] = 0;
+        info.colorKilled[i]   = 0;
+        info.colorDrawn[i]    = 0;
+        info.depthKilled[i]   = 0;
+        info.depthDrawn[i]    = 0;
+    }
+
+    /* Reset clock control register. */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x00000,
+                                      clock));
+
+    /* Reset cycle and bandwidth counters. */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x0003C,
+                                      1));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x0003C,
+                                      0));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x00078,
+                                      0));
+
+#if gcdFRAME_DB_RESET
+    /* Reset PE counters. */
+    gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+        Hardware,
+        0x00454,
+        0x00470,
+        16,
+        15,
+        &reset));
+#endif
+
+    /* Copy to user. */
+    gcmkONERROR(gckOS_CopyToUserData(Hardware->os,
+                                     &info,
+                                     FrameInfo,
+                                     gcmSIZEOF(info)));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+#endif
+
diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h
new file mode 100644 (file)
index 0000000..1f6beec
--- /dev/null
@@ -0,0 +1,126 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_hardware_h_
+#define __gc_hal_kernel_hardware_h_
+
+#if gcdENABLE_VG
+#include "gc_hal_kernel_hardware_vg.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* gckHARDWARE object. */
+struct _gckHARDWARE
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gctKERNEL object. */
+    gckKERNEL                   kernel;
+
+    /* Pointer to gctOS object. */
+    gckOS                       os;
+
+    /* Core */
+    gceCORE                     core;
+
+    /* Chip characteristics. */
+    gceCHIPMODEL                chipModel;
+    gctUINT32                   chipRevision;
+    gctUINT32                   chipFeatures;
+    gctUINT32                   chipMinorFeatures0;
+    gctUINT32                   chipMinorFeatures1;
+    gctUINT32                   chipMinorFeatures2;
+    gctUINT32                   chipMinorFeatures3;
+    gctBOOL                     allowFastClear;
+    gctBOOL                     allowCompression;
+    gctUINT32                   powerBaseAddress;
+    gctBOOL                     extraEventStates;
+
+    gctUINT32                   pixelPipes;
+    gctUINT32                   streamCount;
+    gctUINT32                   registerMax;
+    gctUINT32                   threadCount;
+    gctUINT32                   shaderCoreCount;
+    gctUINT32                   vertexCacheSize;
+    gctUINT32                   vertexOutputBufferSize;
+    gctUINT32                   instructionCount;
+    gctUINT32                   numConstants;
+    gctUINT32                   bufferSize;
+
+    /* Big endian */
+    gctBOOL                     bigEndian;
+
+    /* Chip status */
+    gctPOINTER                  powerMutex;
+    gctUINT32                   powerProcess;
+    gctUINT32                   powerThread;
+    gceCHIPPOWERSTATE           chipPowerState;
+    gctUINT32                   lastWaitLink;
+    gctBOOL                     clockState;
+    gctBOOL                     powerState;
+    gctPOINTER                  globalSemaphore;
+
+    gctISRMANAGERFUNC           startIsr;
+    gctISRMANAGERFUNC           stopIsr;
+    gctPOINTER                  isrContext;
+
+    gctUINT32                   mmuVersion;
+
+    /* Type */
+    gceHARDWARE_TYPE            type;
+
+#if gcdPOWEROFF_TIMEOUT
+    gctUINT32                   powerOffTime;
+    gctPOINTER                  powerOffSema;
+#endif
+};
+
+gceSTATUS
+gckHARDWARE_GetBaseAddress(
+    IN gckHARDWARE Hardware,
+    OUT gctUINT32_PTR BaseAddress
+    );
+
+gceSTATUS
+gckHARDWARE_NeedBaseAddress(
+    IN gckHARDWARE Hardware,
+    IN gctUINT32 State,
+    OUT gctBOOL_PTR NeedBase
+    );
+
+gceSTATUS
+gckHARDWARE_GetFrameInfo(
+    IN gckHARDWARE Hardware,
+    OUT gcsHAL_FRAME_INFO * FrameInfo
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_hardware_h_ */
+
diff --git a/drivers/mxc/gpu-viv/config b/drivers/mxc/gpu-viv/config
new file mode 100644 (file)
index 0000000..e406fad
--- /dev/null
@@ -0,0 +1,32 @@
+##############################################################################
+#
+#    Copyright (C) 2005 - 2011 by Vivante Corp.
+#
+#    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+##############################################################################
+
+
+ARCH_TYPE                         ?= arm
+SDK_DIR                           ?= $(AQROOT)/build/sdk
+USE_3D_VG      = 1
+USE_POWER_MANAGEMENT              ?= 1
+ENABLE_CACHED_VIDEO_MEMORY        ?= 0
+NONPAGED_MEMORY_CACHEABLE         ?= 0
+NONPAGED_MEMORY_BUFFERABLE        ?= 1
+CACHE_FUNCTION_UNIMPLEMENTED      ?= 0
+VIVANTE_ENABLE_VG                 ?= 1
+NO_USER_DIRECT_ACCESS_FROM_KERNEL ?= 1
+ENABLE_GPU_CLOCK_BY_DRIVER        = 1
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
new file mode 100644 (file)
index 0000000..967266a
--- /dev/null
@@ -0,0 +1,2642 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE    gcvZONE_KERNEL
+
+/*******************************************************************************
+***** Version Signature *******************************************************/
+
+#define _gcmTXT2STR(t) #t
+#define gcmTXT2STR(t) _gcmTXT2STR(t)
+const char * _VERSION = "\n\0$VERSION$"
+                        gcmTXT2STR(gcvVERSION_MAJOR) "."
+                        gcmTXT2STR(gcvVERSION_MINOR) "."
+                        gcmTXT2STR(gcvVERSION_PATCH) ":"
+                        gcmTXT2STR(gcvVERSION_BUILD) "$\n";
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+#define gcmDEFINE2TEXT(d) #d
+gctCONST_STRING _DispatchText[] =
+{
+    gcmDEFINE2TEXT(gcvHAL_QUERY_VIDEO_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_QUERY_CHIP_IDENTITY),
+    gcmDEFINE2TEXT(gcvHAL_ALLOCATE_NON_PAGED_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_FREE_NON_PAGED_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_FREE_CONTIGUOUS_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_ALLOCATE_VIDEO_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_FREE_VIDEO_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_MAP_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_UNMAP_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_MAP_USER_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_UNMAP_USER_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_LOCK_VIDEO_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_UNLOCK_VIDEO_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_EVENT_COMMIT),
+    gcmDEFINE2TEXT(gcvHAL_USER_SIGNAL),
+    gcmDEFINE2TEXT(gcvHAL_SIGNAL),
+    gcmDEFINE2TEXT(gcvHAL_WRITE_DATA),
+    gcmDEFINE2TEXT(gcvHAL_COMMIT),
+    gcmDEFINE2TEXT(gcvHAL_STALL),
+    gcmDEFINE2TEXT(gcvHAL_READ_REGISTER),
+    gcmDEFINE2TEXT(gcvHAL_WRITE_REGISTER),
+    gcmDEFINE2TEXT(gcvHAL_GET_PROFILE_SETTING),
+    gcmDEFINE2TEXT(gcvHAL_SET_PROFILE_SETTING),
+    gcmDEFINE2TEXT(gcvHAL_READ_ALL_PROFILE_REGISTERS),
+    gcmDEFINE2TEXT(gcvHAL_PROFILE_REGISTERS_2D),
+    gcmDEFINE2TEXT(gcvHAL_SET_POWER_MANAGEMENT_STATE),
+    gcmDEFINE2TEXT(gcvHAL_QUERY_POWER_MANAGEMENT_STATE),
+    gcmDEFINE2TEXT(gcvHAL_GET_BASE_ADDRESS),
+    gcmDEFINE2TEXT(gcvHAL_SET_IDLE),
+    gcmDEFINE2TEXT(gcvHAL_QUERY_KERNEL_SETTINGS),
+    gcmDEFINE2TEXT(gcvHAL_RESET),
+    gcmDEFINE2TEXT(gcvHAL_MAP_PHYSICAL),
+    gcmDEFINE2TEXT(gcvHAL_DEBUG),
+    gcmDEFINE2TEXT(gcvHAL_CACHE),
+    gcmDEFINE2TEXT(gcvHAL_TIMESTAMP),
+    gcmDEFINE2TEXT(gcvHAL_DATABASE),
+    gcmDEFINE2TEXT(gcvHAL_VERSION),
+    gcmDEFINE2TEXT(gcvHAL_ATTACH),
+    gcmDEFINE2TEXT(gcvHAL_DETACH)
+};
+#endif
+
+/*******************************************************************************
+**
+**  gckKERNEL_Construct
+**
+**  Construct a new gckKERNEL object.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gceCORE Core
+**          Specified core.
+**
+**      IN gctPOINTER Context
+**          Pointer to a driver defined context.
+**
+**      IN gckDB SharedDB,
+**          Pointer to a shared DB.
+**
+**  OUTPUT:
+**
+**      gckKERNEL * Kernel
+**          Pointer to a variable that will hold the pointer to the gckKERNEL
+**          object.
+*/
+#ifdef ANDROID
+#if gcdNEW_PROFILER_FILE
+#define DEFAULT_PROFILE_FILE_NAME   "/sdcard/vprofiler.vpd"
+#else
+#define DEFAULT_PROFILE_FILE_NAME   "/sdcard/vprofiler.xml"
+#endif
+#else
+#if gcdNEW_PROFILER_FILE
+#define DEFAULT_PROFILE_FILE_NAME   "vprofiler.vpd"
+#else
+#define DEFAULT_PROFILE_FILE_NAME   "vprofiler.xml"
+#endif
+#endif
+
+gceSTATUS
+gckKERNEL_Construct(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctPOINTER Context,
+    IN gckDB SharedDB,
+    OUT gckKERNEL * Kernel
+    )
+{
+    gckKERNEL kernel = gcvNULL;
+    gceSTATUS status;
+    gctSIZE_T i;
+    gctPOINTER pointer = gcvNULL;
+
+    gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
+
+    /* Allocate the gckKERNEL object. */
+    gcmkONERROR(gckOS_Allocate(Os,
+                               gcmSIZEOF(struct _gckKERNEL),
+                               &pointer));
+
+    kernel = pointer;
+
+    /* Zero the object pointers. */
+    kernel->hardware     = gcvNULL;
+    kernel->command      = gcvNULL;
+    kernel->eventObj     = gcvNULL;
+    kernel->mmu          = gcvNULL;
+
+    if (SharedDB == gcvNULL)
+    {
+        gcmkONERROR(gckOS_Allocate(Os,
+                                   gcmSIZEOF(struct _gckDB),
+                                   &pointer));
+
+        kernel->db               = pointer;
+        kernel->dbCreated        = gcvTRUE;
+        kernel->db->freeDatabase = gcvNULL;
+        kernel->db->freeRecord   = gcvNULL;
+        kernel->db->dbMutex      = gcvNULL;
+        kernel->db->lastDatabase = gcvNULL;
+        kernel->db->idleTime     = 0;
+        kernel->db->lastIdle     = 0;
+        kernel->db->lastSlowdown = 0;
+
+        for (i = 0; i < gcmCOUNTOF(kernel->db->db); ++i)
+        {
+            kernel->db->db[i] = gcvNULL;
+        }
+
+        /* Construct a database mutex. */
+        gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->dbMutex));
+    }
+    else
+    {
+        kernel->db               = SharedDB;
+        kernel->dbCreated        = gcvFALSE;
+    }
+
+    for (i = 0; i < gcmCOUNTOF(kernel->timers); ++i)
+    {
+        kernel->timers[i].startTime = 0;
+        kernel->timers[i].stopTime = 0;
+    }
+
+    kernel->timeOut      = gcdGPU_TIMEOUT;
+
+    /* Initialize the gckKERNEL object. */
+    kernel->object.type = gcvOBJ_KERNEL;
+    kernel->os          = Os;
+    kernel->core        = Core;
+
+    /* Save context. */
+    kernel->context = Context;
+
+    /* Construct atom holding number of clients. */
+    kernel->atomClients = gcvNULL;
+    gcmkONERROR(gckOS_AtomConstruct(Os, &kernel->atomClients));
+
+#if gcdENABLE_VG
+    kernel->vg = gcvNULL;
+
+    if (Core == gcvCORE_VG)
+    {
+        /* Construct the gckMMU object. */
+        gcmkONERROR(
+            gckVGKERNEL_Construct(Os, Context, kernel, &kernel->vg));
+    }
+    else
+#endif
+    {
+        /* Construct the gckHARDWARE object. */
+        gcmkONERROR(
+            gckHARDWARE_Construct(Os, kernel->core, &kernel->hardware));
+
+        /* Set pointer to gckKERNEL object in gckHARDWARE object. */
+        kernel->hardware->kernel = kernel;
+
+        /* Initialize the hardware. */
+        gcmkONERROR(
+            gckHARDWARE_InitializeHardware(kernel->hardware));
+
+        /* Construct the gckCOMMAND object. */
+        gcmkONERROR(
+            gckCOMMAND_Construct(kernel, &kernel->command));
+
+        /* Construct the gckEVENT object. */
+        gcmkONERROR(
+            gckEVENT_Construct(kernel, &kernel->eventObj));
+
+        /* Construct the gckMMU object. */
+        gcmkONERROR(
+            gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
+    }
+
+#if VIVANTE_PROFILER
+    /* Initialize profile setting */
+#if defined ANDROID
+    kernel->profileEnable = gcvFALSE;
+#else
+    kernel->profileEnable = gcvTRUE;
+#endif
+
+    gcmkVERIFY_OK(
+        gckOS_MemCopy(kernel->profileFileName,
+                      DEFAULT_PROFILE_FILE_NAME,
+                      gcmSIZEOF(DEFAULT_PROFILE_FILE_NAME) + 1));
+#endif
+
+    /* Return pointer to the gckKERNEL object. */
+    *Kernel = kernel;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (kernel != gcvNULL)
+    {
+#if gcdENABLE_VG
+        if (Core != gcvCORE_VG)
+#endif
+        {
+            if (kernel->eventObj != gcvNULL)
+            {
+                gcmkVERIFY_OK(gckEVENT_Destroy(kernel->eventObj));
+            }
+
+            if (kernel->command != gcvNULL)
+            {
+            gcmkVERIFY_OK(gckCOMMAND_Destroy(kernel->command));
+            }
+
+            if (kernel->hardware != gcvNULL)
+            {
+                gcmkVERIFY_OK(gckHARDWARE_Destroy(kernel->hardware));
+            }
+        }
+
+        if (kernel->atomClients != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_AtomDestroy(Os, kernel->atomClients));
+        }
+
+        if (kernel->dbCreated && kernel->db != gcvNULL)
+        {
+            if (kernel->db->dbMutex != gcvNULL)
+            {
+                /* Destroy the database mutex. */
+                gcmkVERIFY_OK(gckOS_DeleteMutex(Os, kernel->db->dbMutex));
+            }
+
+            gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, kernel->db));
+        }
+
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, kernel));
+    }
+
+    /* Return the error. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckKERNEL_Destroy
+**
+**  Destroy an gckKERNEL object.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object to destroy.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckKERNEL_Destroy(
+    IN gckKERNEL Kernel
+    )
+{
+    gctSIZE_T i;
+    gcsDATABASE_PTR database, databaseNext;
+    gcsDATABASE_RECORD_PTR record, recordNext;
+
+    gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+#if QNX_SINGLE_THREADED_DEBUGGING
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->debugMutex));
+#endif
+
+    /* Destroy the database. */
+    if (Kernel->dbCreated)
+    {
+        for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
+        {
+            if (Kernel->db->db[i] != gcvNULL)
+            {
+                gcmkVERIFY_OK(
+                    gckKERNEL_DestroyProcessDB(Kernel, Kernel->db->db[i]->processID));
+            }
+        }
+
+        /* Free all databases. */
+        for (database = Kernel->db->freeDatabase;
+             database != gcvNULL;
+             database = databaseNext)
+        {
+            databaseNext = database->next;
+            gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, database));
+        }
+
+        if (Kernel->db->lastDatabase != gcvNULL)
+        {
+            gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel->db->lastDatabase));
+        }
+
+        /* Free all database records. */
+        for (record = Kernel->db->freeRecord; record != gcvNULL; record = recordNext)
+        {
+            recordNext = record->next;
+            gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, record));
+        }
+
+        /* Destroy the database mutex. */
+        gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->dbMutex));
+    }
+
+#if gcdENABLE_VG
+    if (Kernel->vg)
+    {
+        gcmkVERIFY_OK(gckVGKERNEL_Destroy(Kernel->vg));
+    }
+    else
+#endif
+    {
+        /* Destroy the gckMMU object. */
+        gcmkVERIFY_OK(gckMMU_Destroy(Kernel->mmu));
+
+        /* Destroy the gckCOMMNAND object. */
+        gcmkVERIFY_OK(gckCOMMAND_Destroy(Kernel->command));
+
+        /* Destroy the gckEVENT object. */
+        gcmkVERIFY_OK(gckEVENT_Destroy(Kernel->eventObj));
+
+        /* Destroy the gckHARDWARE object. */
+        gcmkVERIFY_OK(gckHARDWARE_Destroy(Kernel->hardware));
+    }
+
+    /* Detsroy the client atom. */
+    gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Kernel->atomClients));
+
+    /* Mark the gckKERNEL object as unknown. */
+    Kernel->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the gckKERNEL object. */
+    gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+**  _AllocateMemory
+**
+**  Private function to walk all required memory pools to allocate the requested
+**  amount of video memory.
+**
+**  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.
+*/
+static gceSTATUS
+_AllocateMemory(
+    IN gckKERNEL Kernel,
+    IN OUT gcePOOL * Pool,
+    IN gctSIZE_T Bytes,
+    IN gctSIZE_T Alignment,
+    IN gceSURF_TYPE Type,
+    OUT gcuVIDMEM_NODE_PTR * Node
+    )
+{
+    gcePOOL pool;
+    gceSTATUS status;
+    gckVIDMEM videoMemory;
+    gctINT loopCount;
+    gcuVIDMEM_NODE_PTR node = gcvNULL;
+
+    gcmkHEADER_ARG("Kernel=0x%x *Pool=%d Bytes=%lu Alignment=%lu Type=%d",
+                   Kernel, *Pool, Bytes, Alignment, Type);
+
+    gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+
+    /* Get initial pool. */
+    switch (pool = *Pool)
+    {
+    case gcvPOOL_DEFAULT:
+    case gcvPOOL_LOCAL:
+        pool      = gcvPOOL_LOCAL_INTERNAL;
+        loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
+        break;
+
+    case gcvPOOL_UNIFIED:
+        pool      = gcvPOOL_SYSTEM;
+        loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
+        break;
+
+    case gcvPOOL_CONTIGUOUS:
+        loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
+        break;
+
+    default:
+        loopCount = 1;
+        break;
+    }
+
+    /* Verify the number of bytes to allocate. */
+    if (Bytes == 0)
+    {
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    while (loopCount-- > 0)
+    {
+        if (pool == gcvPOOL_VIRTUAL)
+        {
+            /* Create a gcuVIDMEM_NODE for virtual memory. */
+            gcmkONERROR(
+                gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, &node));
+
+            /* Success. */
+            break;
+        }
+
+        else
+        if (pool == gcvPOOL_CONTIGUOUS)
+        {
+            /* Create a gcuVIDMEM_NODE for contiguous memory. */
+            status = gckVIDMEM_ConstructVirtual(Kernel, gcvTRUE, Bytes, &node);
+            if (gcmIS_SUCCESS(status))
+            {
+                /* Memory allocated. */
+                break;
+            }
+        }
+
+        else
+        {
+            /* Get pointer to gckVIDMEM object for pool. */
+#if gcdUSE_VIDMEM_PER_PID
+            gctUINT32 pid;
+            gckOS_GetProcessID(&pid);
+
+            status = gckKERNEL_GetVideoMemoryPoolPid(Kernel, pool, pid, &videoMemory);
+            if (status == gcvSTATUS_NOT_FOUND)
+            {
+                /* Create VidMem pool for this process. */
+                status = gckKERNEL_CreateVideoMemoryPoolPid(Kernel, pool, pid, &videoMemory);
+            }
+#else
+            status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
+#endif
+
+            if (gcmIS_SUCCESS(status))
+            {
+                /* Allocate memory. */
+                status = gckVIDMEM_AllocateLinear(videoMemory,
+                                                  Bytes,
+                                                  Alignment,
+                                                  Type,
+                                                  &node);
+
+                if (gcmIS_SUCCESS(status))
+                {
+                    /* Memory allocated. */
+                    node->VidMem.pool = pool;
+                    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 contiguous memory. */
+            pool = gcvPOOL_CONTIGUOUS;
+        }
+
+        else
+        if ((pool == gcvPOOL_CONTIGUOUS)
+        &&  (Type != gcvSURF_TILE_STATUS)
+        )
+        {
+            /* Advance to virtual memory. */
+            pool = gcvPOOL_VIRTUAL;
+        }
+
+        else
+        {
+            /* Out of pools. */
+            gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+        }
+    }
+
+    if (node == gcvNULL)
+    {
+        /* Nothing allocated. */
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+
+    /* Return node and pool used for allocation. */
+    *Node = node;
+    *Pool = pool;
+
+    /* Return status. */
+    gcmkFOOTER_ARG("*Pool=%d *Node=0x%x", *Pool, *Node);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckKERNEL_Dispatch
+**
+**  Dispatch a command received from the user HAL layer.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctBOOL FromUser
+**          whether the call is from the user space.
+**
+**      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
+gckKERNEL_Dispatch(
+    IN gckKERNEL Kernel,
+    IN gctBOOL FromUser,
+    IN OUT gcsHAL_INTERFACE * Interface
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+    gctUINT32 bitsPerPixel;
+    gctSIZE_T bytes;
+    gcuVIDMEM_NODE_PTR node;
+    gctBOOL locked = gcvFALSE;
+    gctPHYS_ADDR physical = gcvNULL;
+    gctUINT32 address;
+    gctUINT32 processID;
+#if gcdSECURE_USER
+    gcskSECURE_CACHE_PTR cache;
+    gctPOINTER logical;
+#endif
+    gctBOOL asynchronous;
+    gctPOINTER paddr = gcvNULL;
+#if !USE_NEW_LINUX_SIGNAL
+    gctSIGNAL   signal;
+#endif
+
+    gcsDATABASE_RECORD record;
+    gctPOINTER    data;
+
+    gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
+                   Kernel, FromUser, Interface);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+                   "Dispatching command %d (%s)",
+                   Interface->command, _DispatchText[Interface->command]);
+#endif
+#if QNX_SINGLE_THREADED_DEBUGGING
+    gckOS_AcquireMutex(Kernel->os, Kernel->debugMutex, gcvINFINITE);
+#endif
+
+    /* Get the current process ID. */
+    gcmkONERROR(gckOS_GetProcessID(&processID));
+
+#ifdef UNDER_CE
+       if (!FromUser)
+       {
+        gcmkONERROR(gckOS_GetCurrentProcessID(&processID));
+       }
+#endif
+
+#if gcdSECURE_USER
+    gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
+#endif
+
+    /* Dispatch on command. */
+    switch (Interface->command)
+    {
+    case gcvHAL_GET_BASE_ADDRESS:
+        /* Get base address. */
+        gcmkONERROR(
+            gckOS_GetBaseAddress(Kernel->os,
+                                 &Interface->u.GetBaseAddress.baseAddress));
+        break;
+
+    case gcvHAL_QUERY_VIDEO_MEMORY:
+        /* Query video memory size. */
+        gcmkONERROR(gckKERNEL_QueryVideoMemory(Kernel, Interface));
+        break;
+
+    case gcvHAL_QUERY_CHIP_IDENTITY:
+        /* Query chip identity. */
+        gcmkONERROR(
+            gckHARDWARE_QueryChipIdentity(
+                Kernel->hardware,
+                &Interface->u.QueryChipIdentity.chipModel,
+                &Interface->u.QueryChipIdentity.chipRevision,
+                &Interface->u.QueryChipIdentity.chipFeatures,
+                &Interface->u.QueryChipIdentity.chipMinorFeatures,
+                &Interface->u.QueryChipIdentity.chipMinorFeatures1,
+                &Interface->u.QueryChipIdentity.chipMinorFeatures2,
+                &Interface->u.QueryChipIdentity.chipMinorFeatures3));
+
+        /* Query chip specifications. */
+        gcmkONERROR(
+            gckHARDWARE_QueryChipSpecs(
+                Kernel->hardware,
+                &Interface->u.QueryChipIdentity.streamCount,
+                &Interface->u.QueryChipIdentity.registerMax,
+                &Interface->u.QueryChipIdentity.threadCount,
+                &Interface->u.QueryChipIdentity.shaderCoreCount,
+                &Interface->u.QueryChipIdentity.vertexCacheSize,
+                &Interface->u.QueryChipIdentity.vertexOutputBufferSize,
+                &Interface->u.QueryChipIdentity.pixelPipes,
+                &Interface->u.QueryChipIdentity.instructionCount,
+                &Interface->u.QueryChipIdentity.numConstants,
+                &Interface->u.QueryChipIdentity.bufferSize));
+        break;
+
+    case gcvHAL_MAP_MEMORY:
+        physical = Interface->u.MapMemory.physical;
+
+        /* Map memory. */
+        gcmkONERROR(
+            gckKERNEL_MapMemory(Kernel,
+                                physical,
+                                Interface->u.MapMemory.bytes,
+                                &Interface->u.MapMemory.logical));
+        gcmkVERIFY_OK(
+            gckKERNEL_AddProcessDB(Kernel,
+                                   processID, gcvDB_MAP_MEMORY,
+                                   Interface->u.MapMemory.logical,
+                                   physical,
+                                   Interface->u.MapMemory.bytes));
+        break;
+
+    case gcvHAL_UNMAP_MEMORY:
+        physical = Interface->u.UnmapMemory.physical;
+
+        /* Unmap memory. */
+        gcmkONERROR(
+            gckKERNEL_UnmapMemory(Kernel,
+                                  physical,
+                                  Interface->u.UnmapMemory.bytes,
+                                  Interface->u.UnmapMemory.logical));
+        gcmkVERIFY_OK(
+            gckKERNEL_RemoveProcessDB(Kernel,
+                                      processID, gcvDB_MAP_MEMORY,
+                                      Interface->u.UnmapMemory.logical));
+        break;
+
+    case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
+        /* Allocate non-paged memory. */
+        gcmkONERROR(
+            gckOS_AllocateNonPagedMemory(
+                Kernel->os,
+                FromUser,
+                &Interface->u.AllocateNonPagedMemory.bytes,
+                &Interface->u.AllocateNonPagedMemory.physical,
+                &Interface->u.AllocateNonPagedMemory.logical));
+
+        gcmkVERIFY_OK(
+            gckKERNEL_AddProcessDB(Kernel,
+                                   processID, gcvDB_NON_PAGED,
+                                   Interface->u.AllocateNonPagedMemory.logical,
+                                   Interface->u.AllocateNonPagedMemory.physical,
+                                   Interface->u.AllocateNonPagedMemory.bytes));
+        break;
+
+    case gcvHAL_FREE_NON_PAGED_MEMORY:
+        physical = Interface->u.FreeNonPagedMemory.physical;
+
+        /* Free non-paged memory. */
+        gcmkONERROR(
+            gckOS_FreeNonPagedMemory(Kernel->os,
+                                     Interface->u.FreeNonPagedMemory.bytes,
+                                     physical,
+                                     Interface->u.FreeNonPagedMemory.logical));
+
+        gcmkVERIFY_OK(
+            gckKERNEL_RemoveProcessDB(Kernel,
+                                      processID, gcvDB_NON_PAGED,
+                                      Interface->u.FreeNonPagedMemory.logical));
+
+#if gcdSECURE_USER
+        gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+            Kernel,
+            cache,
+            Interface->u.FreeNonPagedMemory.logical,
+            Interface->u.FreeNonPagedMemory.bytes));
+#endif
+        break;
+
+    case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
+        /* Allocate contiguous memory. */
+        gcmkONERROR(gckOS_AllocateContiguous(
+            Kernel->os,
+            FromUser,
+            &Interface->u.AllocateContiguousMemory.bytes,
+            &Interface->u.AllocateContiguousMemory.physical,
+            &Interface->u.AllocateContiguousMemory.logical));
+
+        gcmkONERROR(gckHARDWARE_ConvertLogical(
+            Kernel->hardware,
+            Interface->u.AllocateContiguousMemory.logical,
+            &Interface->u.AllocateContiguousMemory.address));
+
+        gcmkVERIFY_OK(gckKERNEL_AddProcessDB(
+            Kernel,
+            processID, gcvDB_CONTIGUOUS,
+            Interface->u.AllocateContiguousMemory.logical,
+            Interface->u.AllocateContiguousMemory.physical,
+            Interface->u.AllocateContiguousMemory.bytes));
+        break;
+
+    case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+        physical = Interface->u.FreeContiguousMemory.physical;
+
+        /* Free contiguous memory. */
+        gcmkONERROR(
+            gckOS_FreeContiguous(Kernel->os,
+                                 physical,
+                                 Interface->u.FreeContiguousMemory.logical,
+                                 Interface->u.FreeContiguousMemory.bytes));
+
+        gcmkVERIFY_OK(
+            gckKERNEL_RemoveProcessDB(Kernel,
+                                      processID, gcvDB_CONTIGUOUS,
+                                      Interface->u.FreeNonPagedMemory.logical));
+
+#if gcdSECURE_USER
+        gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+            Kernel,
+            cache,
+            Interface->u.FreeContiguousMemory.logical,
+            Interface->u.FreeContiguousMemory.bytes));
+#endif
+        break;
+
+    case gcvHAL_ALLOCATE_VIDEO_MEMORY:
+        /* Align width and height to tiles. */
+        gcmkONERROR(
+            gckHARDWARE_AlignToTile(Kernel->hardware,
+                                    Interface->u.AllocateVideoMemory.type,
+                                    &Interface->u.AllocateVideoMemory.width,
+                                    &Interface->u.AllocateVideoMemory.height,
+                                    gcvNULL));
+
+        /* Convert format into bytes per pixel and bytes per tile. */
+        gcmkONERROR(
+            gckHARDWARE_ConvertFormat(Kernel->hardware,
+                                      Interface->u.AllocateVideoMemory.format,
+                                      &bitsPerPixel,
+                                      gcvNULL));
+
+        /* Compute number of bytes for the allocation. */
+        bytes = Interface->u.AllocateVideoMemory.width * bitsPerPixel
+              * Interface->u.AllocateVideoMemory.height
+              * Interface->u.AllocateVideoMemory.depth / 8;
+
+        /* Allocate memory. */
+        gcmkONERROR(
+            _AllocateMemory(Kernel,
+                            &Interface->u.AllocateVideoMemory.pool,
+                            bytes,
+                            64,
+                            Interface->u.AllocateVideoMemory.type,
+                            &Interface->u.AllocateVideoMemory.node));
+
+        /* Get actual size of node. */
+        node = Interface->u.AllocateLinearVideoMemory.node;
+        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+        {
+            bytes = node->VidMem.bytes;
+        }
+        else
+        {
+            bytes = node->Virtual.bytes;
+        }
+
+        gcmkONERROR(
+            gckKERNEL_AddProcessDB(Kernel,
+                                   processID, gcvDB_VIDEO_MEMORY,
+                                   Interface->u.AllocateVideoMemory.node,
+                                   gcvNULL,
+                                   bytes));
+        break;
+
+    case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
+        /* Allocate memory. */
+        gcmkONERROR(
+            _AllocateMemory(Kernel,
+                            &Interface->u.AllocateLinearVideoMemory.pool,
+                            Interface->u.AllocateLinearVideoMemory.bytes,
+                            Interface->u.AllocateLinearVideoMemory.alignment,
+                            Interface->u.AllocateLinearVideoMemory.type,
+                            &Interface->u.AllocateLinearVideoMemory.node));
+
+        /* Get actual size of node. */
+        node = Interface->u.AllocateLinearVideoMemory.node;
+        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+        {
+            bytes = node->VidMem.bytes;
+        }
+        else
+        {
+            bytes = node->Virtual.bytes;
+        }
+
+        gcmkONERROR(
+            gckKERNEL_AddProcessDB(Kernel,
+                                   processID, gcvDB_VIDEO_MEMORY,
+                                   Interface->u.AllocateLinearVideoMemory.node,
+                                   gcvNULL,
+                                   bytes));
+        break;
+
+    case gcvHAL_FREE_VIDEO_MEMORY:
+#ifdef __QNXNTO__
+        node = Interface->u.FreeVideoMemory.node;
+        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM
+         && node->VidMem.logical != gcvNULL)
+        {
+            gcmkONERROR(
+                    gckKERNEL_UnmapVideoMemory(Kernel,
+                                               node->VidMem.logical,
+                                               processID,
+                                               node->VidMem.bytes));
+            node->VidMem.logical = gcvNULL;
+        }
+#endif
+        /* Free video memory. */
+        gcmkONERROR(
+            gckVIDMEM_Free(Interface->u.FreeVideoMemory.node));
+
+        gcmkONERROR(
+            gckKERNEL_RemoveProcessDB(Kernel,
+                                      processID, gcvDB_VIDEO_MEMORY,
+                                      Interface->u.FreeVideoMemory.node));
+        break;
+
+    case gcvHAL_LOCK_VIDEO_MEMORY:
+        /* Lock video memory. */
+        gcmkONERROR(
+            gckVIDMEM_Lock(Kernel,
+                           Interface->u.LockVideoMemory.node,
+                           Interface->u.LockVideoMemory.cacheable,
+                           &Interface->u.LockVideoMemory.address));
+
+        locked = gcvTRUE;
+
+        node = Interface->u.LockVideoMemory.node;
+        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+        {
+            /* Map video memory address into user space. */
+#ifdef __QNXNTO__
+        if (node->VidMem.logical == gcvNULL)
+        {
+            gcmkONERROR(
+                gckKERNEL_MapVideoMemory(Kernel,
+                                         FromUser,
+                                         Interface->u.LockVideoMemory.address,
+                                         processID,
+                                         node->VidMem.bytes,
+                                         &node->VidMem.logical));
+        }
+        gcmkASSERT(node->VidMem.logical != gcvNULL);
+
+        Interface->u.LockVideoMemory.memory = node->VidMem.logical;
+#else
+            gcmkONERROR(
+                gckKERNEL_MapVideoMemory(Kernel,
+                                         FromUser,
+                                         Interface->u.LockVideoMemory.address,
+                                         &Interface->u.LockVideoMemory.memory));
+                       gckOS_ZeroMemory(Interface->u.LockVideoMemory.memory, node->VidMem.bytes);
+#endif
+        }
+        else
+        {
+            Interface->u.LockVideoMemory.memory = node->Virtual.logical;
+
+            /* Success. */
+            status = gcvSTATUS_OK;
+        }
+
+#if gcdSECURE_USER
+        /* Return logical address as physical address. */
+        Interface->u.LockVideoMemory.address =
+            gcmPTR2INT(Interface->u.LockVideoMemory.memory);
+#endif
+        gcmkONERROR(
+            gckKERNEL_AddProcessDB(Kernel,
+                                   processID, gcvDB_VIDEO_MEMORY_LOCKED,
+                                   Interface->u.LockVideoMemory.node,
+                                   gcvNULL,
+                                   0));
+
+        break;
+
+    case gcvHAL_UNLOCK_VIDEO_MEMORY:
+        /* Unlock video memory. */
+        node = Interface->u.UnlockVideoMemory.node;
+
+#if gcdSECURE_USER
+        /* Save node information before it disappears. */
+        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+        {
+            logical = gcvNULL;
+            bytes   = 0;
+        }
+        else
+        {
+            logical = node->Virtual.logical;
+            bytes   = node->Virtual.bytes;
+        }
+#endif
+
+        /* Unlock video memory. */
+        gcmkONERROR(
+            gckVIDMEM_Unlock(Kernel,
+                             node,
+                             Interface->u.UnlockVideoMemory.type,
+                             &Interface->u.UnlockVideoMemory.asynchroneous));
+
+#if gcdSECURE_USER
+        /* Flush the translation cache for virtual surfaces. */
+        if (logical != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
+                                                          cache,
+                                                          logical,
+                                                          bytes));
+        }
+#endif
+        if (Interface->u.UnlockVideoMemory.asynchroneous == gcvFALSE)
+        {
+            /* There isn't a event to unlock this node, remove record now */
+            gcmkONERROR(
+                gckKERNEL_RemoveProcessDB(Kernel,
+                                          processID, gcvDB_VIDEO_MEMORY_LOCKED,
+                                          Interface->u.UnlockVideoMemory.node));
+        }
+
+        break;
+
+    case gcvHAL_EVENT_COMMIT:
+        /* Commit an event queue. */
+        gcmkONERROR(
+            gckEVENT_Commit(Kernel->eventObj,
+                            Interface->u.Event.queue));
+        break;
+
+    case gcvHAL_COMMIT:
+        /* Commit a command and context buffer. */
+        gcmkONERROR(
+            gckCOMMAND_Commit(Kernel->command,
+                              Interface->u.Commit.context,
+                              Interface->u.Commit.commandBuffer,
+                              Interface->u.Commit.delta,
+                              Interface->u.Commit.queue,
+                              processID));
+        break;
+
+    case gcvHAL_STALL:
+        /* Stall the command queue. */
+        gcmkONERROR(gckCOMMAND_Stall(Kernel->command, gcvFALSE));
+        break;
+
+    case gcvHAL_MAP_USER_MEMORY:
+        /* Map user memory to DMA. */
+        gcmkONERROR(
+            gckOS_MapUserMemoryEx(Kernel->os,
+                                  Kernel->core,
+                                  Interface->u.MapUserMemory.memory,
+                                  Interface->u.MapUserMemory.size,
+                                  &Interface->u.MapUserMemory.info,
+                                  &Interface->u.MapUserMemory.address));
+        gcmkVERIFY_OK(
+            gckKERNEL_AddProcessDB(Kernel,
+                                   processID, gcvDB_MAP_USER_MEMORY,
+                                   Interface->u.MapUserMemory.memory,
+                                   Interface->u.MapUserMemory.info,
+                                   Interface->u.MapUserMemory.size));
+        break;
+
+    case gcvHAL_UNMAP_USER_MEMORY:
+        address = Interface->u.MapUserMemory.address;
+
+        /* Unmap user memory. */
+        gcmkONERROR(
+            gckOS_UnmapUserMemoryEx(Kernel->os,
+                                    Kernel->core,
+                                    Interface->u.UnmapUserMemory.memory,
+                                    Interface->u.UnmapUserMemory.size,
+                                    Interface->u.UnmapUserMemory.info,
+                                    address));
+
+#if gcdSECURE_USER
+        gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+            Kernel,
+            cache,
+            Interface->u.UnmapUserMemory.memory,
+            Interface->u.UnmapUserMemory.size));
+#endif
+        gcmkVERIFY_OK(
+            gckKERNEL_RemoveProcessDB(Kernel,
+                                      processID, gcvDB_MAP_USER_MEMORY,
+                                      Interface->u.UnmapUserMemory.memory));
+        break;
+
+#if !USE_NEW_LINUX_SIGNAL
+    case gcvHAL_USER_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. */
+            gcmkONERROR(
+                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:
+            /* Destroy the signal. */
+            gcmkONERROR(
+                gckOS_DestroyUserSignal(Kernel->os,
+                                        Interface->u.UserSignal.id));
+
+            gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+                Kernel,
+                processID, gcvDB_SIGNAL,
+                gcmINT2PTR(Interface->u.UserSignal.id)));
+            break;
+
+        case gcvUSER_SIGNAL_SIGNAL:
+            /* Signal the signal. */
+            gcmkONERROR(
+                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;
+
+        case gcvUSER_SIGNAL_MAP:
+            gcmkONERROR(
+                gckOS_MapSignal(Kernel->os,
+                               (gctSIGNAL)Interface->u.UserSignal.id,
+                               (gctHANDLE)processID,
+                               &signal));
+
+            gcmkVERIFY_OK(
+                gckKERNEL_AddProcessDB(Kernel,
+                                       processID, gcvDB_SIGNAL,
+                                       gcmINT2PTR(Interface->u.UserSignal.id),
+                                       gcvNULL,
+                                       0));
+            break;
+
+        case gcvUSER_SIGNAL_UNMAP:
+            /* Destroy the signal. */
+            gcmkONERROR(
+                gckOS_DestroyUserSignal(Kernel->os,
+                                        Interface->u.UserSignal.id));
+
+            gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+                Kernel,
+                processID, gcvDB_SIGNAL,
+                gcmINT2PTR(Interface->u.UserSignal.id)));
+            break;
+
+        default:
+            /* Invalid user signal command. */
+            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+        }
+        break;
+#endif
+
+    case gcvHAL_SET_POWER_MANAGEMENT_STATE:
+        /* Set the power management state. */
+        gcmkONERROR(
+            gckHARDWARE_SetPowerManagementState(
+                Kernel->hardware,
+                Interface->u.SetPowerManagement.state));
+        break;
+
+    case gcvHAL_QUERY_POWER_MANAGEMENT_STATE:
+        /* Chip is not idle. */
+        Interface->u.QueryPowerManagement.isIdle = gcvFALSE;
+
+        /* Query the power management state. */
+        gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
+            Kernel->hardware,
+            &Interface->u.QueryPowerManagement.state));
+
+        /* Query the idle state. */
+        gcmkONERROR(
+            gckHARDWARE_QueryIdle(Kernel->hardware,
+                                  &Interface->u.QueryPowerManagement.isIdle));
+        break;
+
+    case gcvHAL_READ_REGISTER:
+#if gcdREGISTER_ACCESS_FROM_USER
+        {
+            gceCHIPPOWERSTATE power;
+            gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->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;
+            }
+        }
+#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;
+
+    case gcvHAL_READ_ALL_PROFILE_REGISTERS:
+#if VIVANTE_PROFILER
+        /* Read all 3D profile registers. */
+        gcmkONERROR(
+            gckHARDWARE_QueryProfileRegisters(
+                Kernel->hardware,
+                &Interface->u.RegisterProfileData.counters));
+#else
+        status = gcvSTATUS_OK;
+#endif
+        break;
+
+    case gcvHAL_PROFILE_REGISTERS_2D:
+#if VIVANTE_PROFILER
+        /* Read all 2D profile registers. */
+        gcmkONERROR(
+            gckHARDWARE_ProfileEngine2D(
+                Kernel->hardware,
+                Interface->u.RegisterProfileData2D.hwProfile2D));
+#else
+        status = gcvSTATUS_OK;
+#endif
+        break;
+
+    case gcvHAL_GET_PROFILE_SETTING:
+#if VIVANTE_PROFILER
+        /* Get profile setting */
+        Interface->u.GetProfileSetting.enable = Kernel->profileEnable;
+
+        gcmkVERIFY_OK(
+            gckOS_MemCopy(Interface->u.GetProfileSetting.fileName,
+                          Kernel->profileFileName,
+                          gcdMAX_PROFILE_FILE_NAME));
+#endif
+
+        status = gcvSTATUS_OK;
+        break;
+
+    case gcvHAL_SET_PROFILE_SETTING:
+#if VIVANTE_PROFILER
+        /* Set profile setting */
+        Kernel->profileEnable = Interface->u.SetProfileSetting.enable;
+
+        gcmkVERIFY_OK(
+            gckOS_MemCopy(Kernel->profileFileName,
+                          Interface->u.SetProfileSetting.fileName,
+                          gcdMAX_PROFILE_FILE_NAME));
+#endif
+
+        status = gcvSTATUS_OK;
+        break;
+
+    case gcvHAL_QUERY_KERNEL_SETTINGS:
+        /* Get kernel settings. */
+        gcmkONERROR(
+            gckKERNEL_QuerySettings(Kernel,
+                                    &Interface->u.QueryKernelSettings.settings));
+        break;
+
+    case gcvHAL_RESET:
+        /* Reset the hardware. */
+        gcmkONERROR(
+            gckHARDWARE_Reset(Kernel->hardware));
+        break;
+
+    case gcvHAL_DEBUG:
+        /* Set debug level and zones. */
+        if (Interface->u.Debug.set)
+        {
+            gckOS_SetDebugLevel(Interface->u.Debug.level);
+            gckOS_SetDebugZones(Interface->u.Debug.zones,
+                                Interface->u.Debug.enable);
+        }
+
+        if (Interface->u.Debug.message[0] != '\0')
+        {
+            /* Print a message to the debugger. */
+            if (Interface->u.Debug.type == gcvMESSAGE_TEXT)
+            {
+               gckOS_CopyPrint(Interface->u.Debug.message);
+            }
+            else
+            {
+               gckOS_DumpBuffer(Kernel->os,
+                                Interface->u.Debug.message,
+                                Interface->u.Debug.messageSize,
+                                gceDUMP_BUFFER_FROM_USER,
+                                gcvTRUE);
+            }
+        }
+        status = gcvSTATUS_OK;
+        break;
+
+    case gcvHAL_CACHE:
+        if (Interface->u.Cache.node == gcvNULL)
+        {
+            /* FIXME Surface wrap some memory which is not allocated by us,
+            ** So we don't have physical address to handle outer cache, ignore it*/
+            status = gcvSTATUS_OK;
+            break;
+        }
+        else if (Interface->u.Cache.node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+        {
+            /* Video memory has no physical handles. */
+            physical = gcvNULL;
+        }
+        else
+        {
+            /* Grab physical handle. */
+            physical = Interface->u.Cache.node->Virtual.physical;
+        }
+
+        switch(Interface->u.Cache.operation)
+        {
+        case gcvCACHE_FLUSH:
+            /* Clean and invalidate the cache. */
+            status = gckOS_CacheFlush(Kernel->os,
+                                      processID,
+                                      physical,
+                                      paddr,
+                                      Interface->u.Cache.logical,
+                                      Interface->u.Cache.bytes);
+            break;
+        case gcvCACHE_CLEAN:
+            /* Clean the cache. */
+            status = gckOS_CacheClean(Kernel->os,
+                                      processID,
+                                      physical,
+                                      paddr,
+                                      Interface->u.Cache.logical,
+                                      Interface->u.Cache.bytes);
+            break;
+        case gcvCACHE_INVALIDATE:
+            /* Invalidate the cache. */
+            status = gckOS_CacheInvalidate(Kernel->os,
+                                           processID,
+                                           physical,
+                                           paddr,
+                                           Interface->u.Cache.logical,
+                                           Interface->u.Cache.bytes);
+            break;
+        default:
+            status = gcvSTATUS_INVALID_ARGUMENT;
+            break;
+        }
+        break;
+
+    case gcvHAL_TIMESTAMP:
+        /* Check for invalid timer. */
+        if ((Interface->u.TimeStamp.timer >= gcmCOUNTOF(Kernel->timers))
+        ||  (Interface->u.TimeStamp.request != 2))
+        {
+            Interface->u.TimeStamp.timeDelta = 0;
+            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+        }
+
+        /* Return timer results and reset timer. */
+        {
+            gcsTIMER_PTR timer = &(Kernel->timers[Interface->u.TimeStamp.timer]);
+            gctUINT64 timeDelta = 0;
+
+            if (timer->stopTime < timer->startTime )
+            {
+                Interface->u.TimeStamp.timeDelta = 0;
+                gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW);
+            }
+
+            timeDelta = timer->stopTime - timer->startTime;
+
+            /* Check truncation overflow. */
+            Interface->u.TimeStamp.timeDelta = (gctINT32) timeDelta;
+                       /*bit0~bit30 is available*/
+            if (timeDelta>>31)
+            {
+                Interface->u.TimeStamp.timeDelta = 0;
+                gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW);
+            }
+
+            status = gcvSTATUS_OK;
+        }
+        break;
+
+    case gcvHAL_DATABASE:
+        /* Query video memory. */
+        gcmkONERROR(
+            gckKERNEL_QueryProcessDB(Kernel,
+                                     Interface->u.Database.processID,
+                                     !Interface->u.Database.validProcessID,
+                                     gcvDB_VIDEO_MEMORY,
+                                     &Interface->u.Database.vidMem));
+
+        /* Query non-paged memory. */
+        gcmkONERROR(
+            gckKERNEL_QueryProcessDB(Kernel,
+                                     Interface->u.Database.processID,
+                                     !Interface->u.Database.validProcessID,
+                                     gcvDB_NON_PAGED,
+                                     &Interface->u.Database.nonPaged));
+
+        /* Query contiguous memory. */
+        gcmkONERROR(
+            gckKERNEL_QueryProcessDB(Kernel,
+                                     Interface->u.Database.processID,
+                                     !Interface->u.Database.validProcessID,
+                                     gcvDB_CONTIGUOUS,
+                                     &Interface->u.Database.contiguous));
+
+        /* Query GPU idle time. */
+        gcmkONERROR(
+            gckKERNEL_QueryProcessDB(Kernel,
+                                     Interface->u.Database.processID,
+                                     !Interface->u.Database.validProcessID,
+                                     gcvDB_IDLE,
+                                     &Interface->u.Database.gpuIdle));
+        break;
+
+    case gcvHAL_VERSION:
+        Interface->u.Version.major = gcvVERSION_MAJOR;
+        Interface->u.Version.minor = gcvVERSION_MINOR;
+        Interface->u.Version.patch = gcvVERSION_PATCH;
+        Interface->u.Version.build = gcvVERSION_BUILD;
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+                       "KERNEL version %d.%d.%d build %u %s %s",
+                       gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH,
+                       gcvVERSION_BUILD, gcvVERSION_DATE, gcvVERSION_TIME);
+#endif
+        break;
+
+    case gcvHAL_CHIP_INFO:
+        /* Only if not support multi-core */
+        Interface->u.ChipInfo.count = 1;
+        Interface->u.ChipInfo.types[0] = Kernel->hardware->type;
+        break;
+
+    case gcvHAL_ATTACH:
+        /* Attach user process. */
+        gcmkONERROR(
+            gckCOMMAND_Attach(Kernel->command,
+                              &Interface->u.Attach.context,
+                              &Interface->u.Attach.stateCount,
+                              processID));
+
+        gcmkVERIFY_OK(
+            gckKERNEL_AddProcessDB(Kernel,
+                                   processID, gcvDB_CONTEXT,
+                                   Interface->u.Attach.context,
+                                   gcvNULL,
+                                   0));
+        break;
+
+    case gcvHAL_DETACH:
+        /* Detach user process. */
+        gcmkONERROR(
+            gckCOMMAND_Detach(Kernel->command,
+                              Interface->u.Detach.context));
+
+        gcmkVERIFY_OK(
+            gckKERNEL_RemoveProcessDB(Kernel,
+                              processID, gcvDB_CONTEXT,
+                              Interface->u.Detach.context));
+        break;
+
+    case gcvHAL_COMPOSE:
+        /* Start composition. */
+        gcmkONERROR(
+            gckEVENT_Compose(Kernel->eventObj,
+                             &Interface->u.Compose));
+        break;
+
+    case gcvHAL_SET_TIMEOUT:
+         /* set timeOut value from user */
+         gckKERNEL_SetTimeOut(Kernel, Interface->u.SetTimeOut.timeOut);
+        break;
+
+#if gcdFRAME_DB
+    case gcvHAL_GET_FRAME_INFO:
+        gcmkONERROR(gckHARDWARE_GetFrameInfo(
+            Kernel->hardware,
+            Interface->u.GetFrameInfo.frameInfo));
+        break;
+#endif
+
+    case gcvHAL_GET_SHARED_INFO:
+        if (Interface->u.GetSharedInfo.dataId != 0)
+        {
+            gcmkONERROR(gckKERNEL_FindProcessDB(Kernel,
+                        Interface->u.GetSharedInfo.pid,
+                        0,
+                        gcvDB_SHARED_INFO,
+                        gcmINT2PTR(Interface->u.GetSharedInfo.dataId),
+                        &record));
+
+            /* find a record in db, check size */
+            if (record.bytes != Interface->u.GetSharedInfo.size)
+            {
+                /* Size change is not allowed */
+                gcmkONERROR(gcvSTATUS_INVALID_DATA);
+            }
+
+            /* fetch data */
+            gcmkONERROR(gckOS_CopyToUserData(
+                Kernel->os,
+                record.physical,
+                Interface->u.GetSharedInfo.data,
+                Interface->u.GetSharedInfo.size
+                ));
+
+        }
+
+        if ((node = Interface->u.GetSharedInfo.node) != gcvNULL)
+        {
+            if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+            {
+                data = &node->VidMem.sharedInfo;
+            }
+            else
+            {
+                data = &node->Virtual.sharedInfo;
+            }
+
+            gcmkONERROR(gckOS_CopyToUserData(
+                Kernel->os,
+                data,
+                Interface->u.GetSharedInfo.nodeData,
+                sizeof(gcsVIDMEM_NODE_SHARED_INFO)
+                ));
+        }
+
+        break;
+
+    case gcvHAL_SET_SHARED_INFO:
+        if (Interface->u.SetSharedInfo.dataId != 0)
+        {
+            status = gckKERNEL_FindProcessDB(Kernel, processID, 0,
+                        gcvDB_SHARED_INFO,
+                        gcmINT2PTR(Interface->u.SetSharedInfo.dataId),
+                        &record);
+
+            if (status == gcvSTATUS_INVALID_DATA)
+            {
+                /* private data has not been created yet */
+                /* Note: we count on DestoryProcessDB to free it */
+                gcmkONERROR(gckOS_AllocateMemory(
+                    Kernel->os,
+                    Interface->u.SetSharedInfo.size,
+                    &data
+                    ));
+
+                gcmkONERROR(
+                    gckKERNEL_AddProcessDB(Kernel, processID,
+                        gcvDB_SHARED_INFO,
+                        gcmINT2PTR(Interface->u.SetSharedInfo.dataId),
+                        data,
+                        Interface->u.SetSharedInfo.size
+                        ));
+            }
+            else
+            {
+                /* bail on other errors */
+                gcmkONERROR(status);
+
+                /* find a record in db, check size */
+                if (record.bytes != Interface->u.SetSharedInfo.size)
+                {
+                    /* Size change is not allowed */
+                    gcmkONERROR(gcvSTATUS_INVALID_DATA);
+                }
+
+                /* get storage address */
+                data = record.physical;
+            }
+
+            gcmkONERROR(gckOS_CopyFromUserData(
+                Kernel->os,
+                data,
+                Interface->u.SetSharedInfo.data,
+                Interface->u.SetSharedInfo.size
+                ));
+        }
+
+        if ((node = Interface->u.SetSharedInfo.node) != gcvNULL)
+        {
+            if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+            {
+                data = &node->VidMem.sharedInfo;
+            }
+            else
+            {
+                data = &node->Virtual.sharedInfo;
+            }
+
+            gcmkONERROR(gckOS_CopyFromUserData(
+                Kernel->os,
+                data,
+                Interface->u.SetSharedInfo.nodeData,
+                sizeof(gcsVIDMEM_NODE_SHARED_INFO)
+                ));
+        }
+
+        break;
+
+    default:
+        /* Invalid command. */
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+OnError:
+    /* Save status. */
+    Interface->status = status;
+
+    if (gcmIS_ERROR(status))
+    {
+        if (locked)
+        {
+            /* Roll back the lock. */
+            gcmkVERIFY_OK(
+                gckVIDMEM_Unlock(Kernel,
+                                 Interface->u.LockVideoMemory.node,
+                                 gcvSURF_TYPE_UNKNOWN,
+                                 &asynchronous));
+
+            if (gcvTRUE == asynchronous)
+            {
+                /* Bottom Half */
+                gcmkVERIFY_OK(
+                    gckVIDMEM_Unlock(Kernel,
+                                     Interface->u.LockVideoMemory.node,
+                                     gcvSURF_TYPE_UNKNOWN,
+                                     gcvNULL));
+            }
+        }
+    }
+
+#if QNX_SINGLE_THREADED_DEBUGGING
+    gckOS_ReleaseMutex(Kernel->os, Kernel->debugMutex);
+#endif
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckKERNEL_AttachProcess
+**
+**  Attach or detach a process.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctBOOL Attach
+**          gcvTRUE if a new process gets attached or gcFALSE when a process
+**          gets detatched.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckKERNEL_AttachProcess(
+    IN gckKERNEL Kernel,
+    IN gctBOOL Attach
+    )
+{
+    gceSTATUS status;
+    gctUINT32 processID;
+
+    gcmkHEADER_ARG("Kernel=0x%x Attach=%d", Kernel, Attach);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    /* Get current process ID. */
+    gcmkONERROR(gckOS_GetProcessID(&processID));
+
+    gcmkONERROR(gckKERNEL_AttachProcessEx(Kernel, Attach, processID));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckKERNEL_AttachProcessEx
+**
+**  Attach or detach a process with the given PID. Can be paired with gckKERNEL_AttachProcess
+**     provided the programmer is aware of the consequences.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctBOOL Attach
+**          gcvTRUE if a new process gets attached or gcFALSE when a process
+**          gets detatched.
+**
+**      gctUINT32 PID
+**          PID of the process to attach or detach.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckKERNEL_AttachProcessEx(
+    IN gckKERNEL Kernel,
+    IN gctBOOL Attach,
+    IN gctUINT32 PID
+    )
+{
+    gceSTATUS status;
+    gctINT32 old;
+
+    gcmkHEADER_ARG("Kernel=0x%x Attach=%d PID=%d", Kernel, Attach, PID);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    if (Attach)
+    {
+        /* Increment the number of clients attached. */
+        gcmkONERROR(
+            gckOS_AtomIncrement(Kernel->os, Kernel->atomClients, &old));
+
+        if (old == 0)
+        {
+#if gcdENABLE_VG
+            if (Kernel->vg == gcvNULL)
+#endif
+            {
+                gcmkONERROR(gckOS_Broadcast(Kernel->os,
+                                            Kernel->hardware,
+                                            gcvBROADCAST_FIRST_PROCESS));
+            }
+        }
+
+        if (Kernel->dbCreated)
+        {
+            /* Create the process database. */
+            gcmkONERROR(gckKERNEL_CreateProcessDB(Kernel, PID));
+        }
+    }
+    else
+    {
+        if (Kernel->dbCreated)
+        {
+            /* Clean up the process database. */
+            gcmkONERROR(gckKERNEL_DestroyProcessDB(Kernel, PID));
+
+            /* Save the last know process ID. */
+            Kernel->db->lastProcessID = PID;
+        }
+
+        /* Decrement the number of clients attached. */
+        gcmkONERROR(
+            gckOS_AtomDecrement(Kernel->os, Kernel->atomClients, &old));
+
+        if (old == 1)
+        {
+#if gcdENABLE_VG
+            if (Kernel->vg == gcvNULL)
+#endif
+            {
+                /* Last client detached, switch to SUSPEND power state. */
+                gcmkONERROR(gckOS_Broadcast(Kernel->os,
+                                            Kernel->hardware,
+                                            gcvBROADCAST_LAST_PROCESS));
+            }
+
+            /* Flush the debug cache. */
+            gcmkDEBUGFLUSH(~0U);
+        }
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+#if gcdSECURE_USER
+gceSTATUS
+gckKERNEL_MapLogicalToPhysical(
+    IN gckKERNEL Kernel,
+    IN gcskSECURE_CACHE_PTR Cache,
+    IN OUT gctPOINTER * Data
+    )
+{
+    gceSTATUS status;
+    static gctBOOL baseAddressValid = gcvFALSE;
+    static gctUINT32 baseAddress;
+    gctBOOL needBase;
+    gcskLOGICAL_CACHE_PTR slot;
+
+    gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x *Data=0x%x",
+                   Kernel, Cache, gcmOPT_POINTER(Data));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    if (!baseAddressValid)
+    {
+        /* Get base address. */
+        gcmkONERROR(gckHARDWARE_GetBaseAddress(Kernel->hardware, &baseAddress));
+
+        baseAddressValid = gcvTRUE;
+    }
+
+    /* Does this state load need a base address? */
+    gcmkONERROR(gckHARDWARE_NeedBaseAddress(Kernel->hardware,
+                                            ((gctUINT32_PTR) Data)[-1],
+                                            &needBase));
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
+    {
+        gcskLOGICAL_CACHE_PTR next;
+        gctINT i;
+
+        /* Walk all used cache slots. */
+        for (i = 1, slot = Cache->cache[0].next, next = gcvNULL;
+             (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+             ++i, slot = slot->next
+        )
+        {
+            if (slot->logical == *Data)
+            {
+                /* Bail out. */
+                next = slot;
+                break;
+            }
+        }
+
+        /* See if we had a miss. */
+        if (next == gcvNULL)
+        {
+            /* Use the tail of the cache. */
+            slot = Cache->cache[0].prev;
+
+            /* Initialize the cache line. */
+            slot->logical = *Data;
+
+            /* Map the logical address to a DMA address. */
+            gcmkONERROR(
+                gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
+        }
+
+        /* Move slot to head of list. */
+        if (slot != Cache->cache[0].next)
+        {
+            /* Unlink. */
+            slot->prev->next = slot->next;
+            slot->next->prev = slot->prev;
+
+            /* Move to head of chain. */
+            slot->prev       = &Cache->cache[0];
+            slot->next       = Cache->cache[0].next;
+            slot->prev->next = slot;
+            slot->next->prev = slot;
+        }
+    }
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
+    {
+        gctINT i;
+        gcskLOGICAL_CACHE_PTR next = gcvNULL;
+        gcskLOGICAL_CACHE_PTR oldestSlot = gcvNULL;
+        slot = gcvNULL;
+
+        if (Cache->cacheIndex != gcvNULL)
+        {
+            /* Walk the cache forwards. */
+            for (i = 1, slot = Cache->cacheIndex;
+                 (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+                 ++i, slot = slot->next)
+            {
+                if (slot->logical == *Data)
+                {
+                    /* Bail out. */
+                    next = slot;
+                    break;
+                }
+
+                /* Determine age of this slot. */
+                if ((oldestSlot       == gcvNULL)
+                ||  (oldestSlot->stamp > slot->stamp)
+                )
+                {
+                    oldestSlot = slot;
+                }
+            }
+
+            if (next == gcvNULL)
+            {
+                /* Walk the cache backwards. */
+                for (slot = Cache->cacheIndex->prev;
+                     (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+                     ++i, slot = slot->prev)
+                {
+                    if (slot->logical == *Data)
+                    {
+                        /* Bail out. */
+                        next = slot;
+                        break;
+                    }
+
+                    /* Determine age of this slot. */
+                    if ((oldestSlot       == gcvNULL)
+                    ||  (oldestSlot->stamp > slot->stamp)
+                    )
+                    {
+                        oldestSlot = slot;
+                    }
+                }
+            }
+        }
+
+        /* See if we had a miss. */
+        if (next == gcvNULL)
+        {
+            if (Cache->cacheFree != 0)
+            {
+                slot = &Cache->cache[Cache->cacheFree];
+                gcmkASSERT(slot->logical == gcvNULL);
+
+                ++ Cache->cacheFree;
+                if (Cache->cacheFree >= gcmCOUNTOF(Cache->cache))
+                {
+                    Cache->cacheFree = 0;
+                }
+            }
+            else
+            {
+                /* Use the oldest cache slot. */
+                gcmkASSERT(oldestSlot != gcvNULL);
+                slot = oldestSlot;
+
+                /* Unlink from the chain. */
+                slot->prev->next = slot->next;
+                slot->next->prev = slot->prev;
+
+                /* Append to the end. */
+                slot->prev       = Cache->cache[0].prev;
+                slot->next       = &Cache->cache[0];
+                slot->prev->next = slot;
+                slot->next->prev = slot;
+            }
+
+            /* Initialize the cache line. */
+            slot->logical = *Data;
+
+            /* Map the logical address to a DMA address. */
+            gcmkONERROR(
+                gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
+        }
+
+        /* Save time stamp. */
+        slot->stamp = ++ Cache->cacheStamp;
+
+        /* Save current slot for next lookup. */
+        Cache->cacheIndex = slot;
+    }
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+    {
+        gctINT i;
+        gctUINT32 data = gcmPTR2INT(*Data);
+        gctUINT32 key, index;
+        gcskLOGICAL_CACHE_PTR hash;
+
+        /* Generate a hash key. */
+        key   = (data >> 24) + (data >> 16) + (data >> 8) + data;
+        index = key % gcmCOUNTOF(Cache->hash);
+
+        /* Get the hash entry. */
+        hash = &Cache->hash[index];
+
+        for (slot = hash->nextHash, i = 0;
+             (slot != gcvNULL) && (i < gcdSECURE_CACHE_SLOTS);
+             slot = slot->nextHash, ++i
+        )
+        {
+            if (slot->logical == (*Data))
+            {
+                break;
+            }
+        }
+
+        if (slot == gcvNULL)
+        {
+            /* Grab from the tail of the cache. */
+            slot = Cache->cache[0].prev;
+
+            /* Unlink slot from any hash table it is part of. */
+            if (slot->prevHash != gcvNULL)
+            {
+                slot->prevHash->nextHash = slot->nextHash;
+            }
+            if (slot->nextHash != gcvNULL)
+            {
+                slot->nextHash->prevHash = slot->prevHash;
+            }
+
+            /* Initialize the cache line. */
+            slot->logical = *Data;
+
+            /* Map the logical address to a DMA address. */
+            gcmkONERROR(
+                gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
+
+            if (hash->nextHash != gcvNULL)
+            {
+                gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+                               "Hash Collision: logical=0x%x key=0x%08x",
+                               *Data, key);
+            }
+
+            /* Insert the slot at the head of the hash list. */
+            slot->nextHash     = hash->nextHash;
+            if (slot->nextHash != gcvNULL)
+            {
+                slot->nextHash->prevHash = slot;
+            }
+            slot->prevHash     = hash;
+            hash->nextHash     = slot;
+        }
+
+        /* Move slot to head of list. */
+        if (slot != Cache->cache[0].next)
+        {
+            /* Unlink. */
+            slot->prev->next = slot->next;
+            slot->next->prev = slot->prev;
+
+            /* Move to head of chain. */
+            slot->prev       = &Cache->cache[0];
+            slot->next       = Cache->cache[0].next;
+            slot->prev->next = slot;
+            slot->next->prev = slot;
+        }
+    }
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
+    {
+        gctUINT32 index = (gcmPTR2INT(*Data) % gcdSECURE_CACHE_SLOTS) + 1;
+
+        /* Get cache slot. */
+        slot = &Cache->cache[index];
+
+        /* Check for cache miss. */
+        if (slot->logical != *Data)
+        {
+            /* Initialize the cache line. */
+            slot->logical = *Data;
+
+            /* Map the logical address to a DMA address. */
+            gcmkONERROR(
+                gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
+        }
+    }
+#endif
+
+    /* Return DMA address. */
+    *Data = gcmINT2PTR(slot->dma + (needBase ? baseAddress : 0));
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Data=0x%08x", *Data);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckKERNEL_FlushTranslationCache(
+    IN gckKERNEL Kernel,
+    IN gcskSECURE_CACHE_PTR Cache,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    gctINT i;
+    gcskLOGICAL_CACHE_PTR slot;
+    gctUINT8_PTR ptr;
+
+    gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x Logical=0x%x Bytes=%lu",
+                   Kernel, Cache, Logical, Bytes);
+
+    /* Do we need to flush the entire cache? */
+    if (Logical == gcvNULL)
+    {
+        /* Clear all cache slots. */
+        for (i = 1; i <= gcdSECURE_CACHE_SLOTS; ++i)
+        {
+            Cache->cache[i].logical  = gcvNULL;
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+            Cache->cache[i].nextHash = gcvNULL;
+            Cache->cache[i].prevHash = gcvNULL;
+#endif
+}
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+        /* Zero the hash table. */
+        for (i = 0; i < gcmCOUNTOF(Cache->hash); ++i)
+        {
+            Cache->hash[i].nextHash = gcvNULL;
+        }
+#endif
+
+        /* Reset the cache functionality. */
+        Cache->cacheIndex = gcvNULL;
+        Cache->cacheFree  = 1;
+        Cache->cacheStamp = 0;
+    }
+
+    else
+    {
+        gctUINT8_PTR low  = (gctUINT8_PTR) Logical;
+        gctUINT8_PTR high = low + Bytes;
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
+        gcskLOGICAL_CACHE_PTR next;
+
+        /* Walk all used cache slots. */
+        for (i = 1, slot = Cache->cache[0].next;
+             (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+             ++i, slot = next
+        )
+        {
+            /* Save pointer to next slot. */
+            next = slot->next;
+
+            /* Test if this slot falls within the range to flush. */
+            ptr = (gctUINT8_PTR) slot->logical;
+            if ((ptr >= low) && (ptr < high))
+            {
+                /* Unlink slot. */
+                slot->prev->next = slot->next;
+                slot->next->prev = slot->prev;
+
+                /* Append slot to tail of cache. */
+                slot->prev       = Cache->cache[0].prev;
+                slot->next       = &Cache->cache[0];
+                slot->prev->next = slot;
+                slot->next->prev = slot;
+
+                /* Mark slot as empty. */
+                slot->logical = gcvNULL;
+            }
+        }
+
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
+        gcskLOGICAL_CACHE_PTR next;
+
+        for (i = 1, slot = Cache->cache[0].next;
+             (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+             ++i, slot = next)
+        {
+            /* Save pointer to next slot. */
+            next = slot->next;
+
+            /* Test if this slot falls within the range to flush. */
+            ptr = (gctUINT8_PTR) slot->logical;
+            if ((ptr >= low) && (ptr < high))
+            {
+                /* Test if this slot is the current slot. */
+                if (slot == Cache->cacheIndex)
+                {
+                    /* Move to next or previous slot. */
+                    Cache->cacheIndex = (slot->next->logical != gcvNULL)
+                                      ? slot->next
+                                      : (slot->prev->logical != gcvNULL)
+                                      ? slot->prev
+                                      : gcvNULL;
+                }
+
+                /* Unlink slot from cache. */
+                slot->prev->next = slot->next;
+                slot->next->prev = slot->prev;
+
+                /* Insert slot to head of cache. */
+                slot->prev       = &Cache->cache[0];
+                slot->next       = Cache->cache[0].next;
+                slot->prev->next = slot;
+                slot->next->prev = slot;
+
+                /* Mark slot as empty. */
+                slot->logical = gcvNULL;
+                slot->stamp   = 0;
+            }
+        }
+
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+        gctINT j;
+        gcskLOGICAL_CACHE_PTR hash, next;
+
+        /* Walk all hash tables. */
+        for (i = 0, hash = Cache->hash;
+             i < gcmCOUNTOF(Cache->hash);
+             ++i, ++hash)
+        {
+            /* Walk all slots in the hash. */
+            for (j = 0, slot = hash->nextHash;
+                 (j < gcdSECURE_CACHE_SLOTS) && (slot != gcvNULL);
+                 ++j, slot = next)
+            {
+                /* Save pointer to next slot. */
+                next = slot->next;
+
+                /* Test if this slot falls within the range to flush. */
+                ptr = (gctUINT8_PTR) slot->logical;
+                if ((ptr >= low) && (ptr < high))
+                {
+                    /* Unlink slot from hash table. */
+                    if (slot->prevHash == hash)
+                    {
+                        hash->nextHash = slot->nextHash;
+                    }
+                    else
+                    {
+                        slot->prevHash->nextHash = slot->nextHash;
+                    }
+
+                    if (slot->nextHash != gcvNULL)
+                    {
+                        slot->nextHash->prevHash = slot->prevHash;
+                    }
+
+                    /* Unlink slot from cache. */
+                    slot->prev->next = slot->next;
+                    slot->next->prev = slot->prev;
+
+                    /* Append slot to tail of cache. */
+                    slot->prev       = Cache->cache[0].prev;
+                    slot->next       = &Cache->cache[0];
+                    slot->prev->next = slot;
+                    slot->next->prev = slot;
+
+                    /* Mark slot as empty. */
+                    slot->logical  = gcvNULL;
+                    slot->prevHash = gcvNULL;
+                    slot->nextHash = gcvNULL;
+                }
+            }
+        }
+
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
+        gctUINT32 index;
+
+        /* Loop while inside the range. */
+        for (i = 1; (low < high) && (i <= gcdSECURE_CACHE_SLOTS); ++i)
+        {
+            /* Get index into cache for this range. */
+            index = (gcmPTR2INT(low) % gcdSECURE_CACHE_SLOTS) + 1;
+            slot  = &Cache->cache[index];
+
+            /* Test if this slot falls within the range to flush. */
+            ptr = (gctUINT8_PTR) slot->logical;
+            if ((ptr >= low) && (ptr < high))
+            {
+                /* Remove entry from cache. */
+                slot->logical = gcvNULL;
+            }
+
+            /* Next block. */
+            low += gcdSECURE_CACHE_SLOTS;
+        }
+#endif
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+#endif
+
+/*******************************************************************************
+**
+**  gckKERNEL_Recovery
+**
+**  Try to recover the GPU from a fatal error.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckKERNEL_Recovery(
+    IN gckKERNEL Kernel
+    )
+{
+#if gcdENABLE_RECOVERY
+    gceSTATUS status;
+    gckEVENT eventObj;
+    gckHARDWARE hardware;
+#if gcdSECURE_USER
+    gctUINT32 processID;
+    gcskSECURE_CACHE_PTR cache;
+#endif
+
+    gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+    /* Validate the arguemnts. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    /* Grab gckEVENT object. */
+    eventObj = Kernel->eventObj;
+    gcmkVERIFY_OBJECT(eventObj, gcvOBJ_EVENT);
+
+    /* Grab gckHARDWARE object. */
+    hardware = Kernel->hardware;
+    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+    /* Handle all outstanding events now. */
+    eventObj->pending = ~0U;
+    gcmkONERROR(gckEVENT_Notify(eventObj, 1));
+
+    /* Again in case more events got submitted. */
+    eventObj->pending = ~0U;
+    gcmkONERROR(gckEVENT_Notify(eventObj, 2));
+
+#if gcdSECURE_USER
+    /* Flush the secure mapping cache. */
+    gcmkONERROR(gckOS_GetProcessID(&processID));
+    gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
+    gcmkONERROR(gckKERNEL_FlushTranslationCache(Kernel, cache, gcvNULL, 0));
+#endif
+
+    /* Try issuing a soft reset for the GPU. */
+    status = gckHARDWARE_Reset(hardware);
+    if (status == gcvSTATUS_NOT_SUPPORTED)
+    {
+        /* Switch to OFF power.  The next submit should return the GPU to ON
+        ** state. */
+        gcmkONERROR(
+            gckHARDWARE_SetPowerManagementState(hardware,
+                                                gcvPOWER_OFF_RECOVERY));
+    }
+    else
+    {
+        /* Bail out on reset error. */
+        gcmkONERROR(status);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+#else
+    return gcvSTATUS_OK;
+#endif
+}
+
+/*******************************************************************************
+**
+**  gckKERNEL_OpenUserData
+**
+**  Get access to the user data.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctBOOL NeedCopy
+**          The flag indicating whether or not the data should be copied.
+**
+**      gctPOINTER StaticStorage
+**          Pointer to the kernel storage where the data is to be copied if
+**          NeedCopy is gcvTRUE.
+**
+**      gctPOINTER UserPointer
+**          User pointer to the data.
+**
+**      gctSIZE_T Size
+**          Size of the data.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * KernelPointer
+**          Pointer to the kernel pointer that will be pointing to the data.
+*/
+gceSTATUS
+gckKERNEL_OpenUserData(
+    IN gckKERNEL Kernel,
+    IN gctBOOL NeedCopy,
+    IN gctPOINTER StaticStorage,
+    IN gctPOINTER UserPointer,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * KernelPointer
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG(
+        "Kernel=0x%08X NeedCopy=%d StaticStorage=0x%08X "
+        "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
+        Kernel, NeedCopy, StaticStorage, UserPointer, Size, KernelPointer
+        );
+
+    /* Validate the arguemnts. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(!NeedCopy || (StaticStorage != gcvNULL));
+    gcmkVERIFY_ARGUMENT(UserPointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Size > 0);
+
+    if (NeedCopy)
+    {
+        /* Copy the user data to the static storage. */
+        gcmkONERROR(gckOS_CopyFromUserData(
+            Kernel->os, StaticStorage, UserPointer, Size
+            ));
+
+        /* Set the kernel pointer. */
+        * KernelPointer = StaticStorage;
+    }
+    else
+    {
+        gctPOINTER pointer = gcvNULL;
+
+        /* Map the user pointer. */
+        gcmkONERROR(gckOS_MapUserPointer(
+            Kernel->os, UserPointer, Size, &pointer
+            ));
+
+        /* Set the kernel pointer. */
+        * KernelPointer = pointer;
+    }
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckKERNEL_CloseUserData
+**
+**  Release resources associated with the user data connection opened by
+**  gckKERNEL_OpenUserData.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctBOOL NeedCopy
+**          The flag indicating whether or not the data should be copied.
+**
+**      gctBOOL FlushData
+**          If gcvTRUE, the data is written back to the user.
+**
+**      gctPOINTER UserPointer
+**          User pointer to the data.
+**
+**      gctSIZE_T Size
+**          Size of the data.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * KernelPointer
+**          Kernel pointer to the data.
+*/
+gceSTATUS
+gckKERNEL_CloseUserData(
+    IN gckKERNEL Kernel,
+    IN gctBOOL NeedCopy,
+    IN gctBOOL FlushData,
+    IN gctPOINTER UserPointer,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * KernelPointer
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+    gctPOINTER pointer;
+
+    gcmkHEADER_ARG(
+        "Kernel=0x%08X NeedCopy=%d FlushData=%d "
+        "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
+        Kernel, NeedCopy, FlushData, UserPointer, Size, KernelPointer
+        );
+
+    /* Validate the arguemnts. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(UserPointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Size > 0);
+
+    /* Get a shortcut to the kernel pointer. */
+    pointer = * KernelPointer;
+
+    if (pointer != gcvNULL)
+    {
+        if (NeedCopy)
+        {
+            if (FlushData)
+            {
+                gcmkONERROR(gckOS_CopyToUserData(
+                    Kernel->os, * KernelPointer, UserPointer, Size
+                    ));
+            }
+        }
+        else
+        {
+            /* Unmap record from kernel memory. */
+            gcmkONERROR(gckOS_UnmapUserPointer(
+                Kernel->os,
+                UserPointer,
+                Size,
+                * KernelPointer
+                ));
+        }
+
+        /* Reset the kernel pointer. */
+        * KernelPointer = gcvNULL;
+    }
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+void
+gckKERNEL_SetTimeOut(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 timeOut
+    )
+{
+    gcmkHEADER_ARG("Kernel=0x%x timeOut=%d", Kernel, timeOut);
+#if gcdGPU_TIMEOUT
+    Kernel->timeOut = timeOut;
+#endif
+    gcmkFOOTER_NO();
+}
+
+
+
+/*******************************************************************************
+***** Test Code ****************************************************************
+*******************************************************************************/
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
new file mode 100644 (file)
index 0000000..bd701b7
--- /dev/null
@@ -0,0 +1,745 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_h_
+#define __gc_hal_kernel_h_
+
+#include "gc_hal.h"
+#include "gc_hal_kernel_hardware.h"
+#include "gc_hal_driver.h"
+
+#if gcdENABLE_VG
+#include "gc_hal_kernel_vg.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+***** Process Secure Cache ****************************************************/
+
+#define gcdSECURE_CACHE_LRU         1
+#define gcdSECURE_CACHE_LINEAR      2
+#define gcdSECURE_CACHE_HASH        3
+#define gcdSECURE_CACHE_TABLE       4
+
+typedef struct _gcskLOGICAL_CACHE * gcskLOGICAL_CACHE_PTR;
+typedef struct _gcskLOGICAL_CACHE   gcskLOGICAL_CACHE;
+struct _gcskLOGICAL_CACHE
+{
+    /* Logical address. */
+    gctPOINTER                      logical;
+
+    /* DMAable address. */
+    gctUINT32                       dma;
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+    /* Pointer to the previous and next hash tables. */
+    gcskLOGICAL_CACHE_PTR           nextHash;
+    gcskLOGICAL_CACHE_PTR           prevHash;
+#endif
+
+#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
+    /* Pointer to the previous and next slot. */
+    gcskLOGICAL_CACHE_PTR           next;
+    gcskLOGICAL_CACHE_PTR           prev;
+#endif
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
+    /* Time stamp. */
+    gctUINT64                       stamp;
+#endif
+};
+
+typedef struct _gcskSECURE_CACHE * gcskSECURE_CACHE_PTR;
+typedef struct _gcskSECURE_CACHE
+{
+    /* Cache memory. */
+    gcskLOGICAL_CACHE               cache[1 + gcdSECURE_CACHE_SLOTS];
+
+    /* Last known index for LINEAR mode. */
+    gcskLOGICAL_CACHE_PTR           cacheIndex;
+
+    /* Current free slot for LINEAR mode. */
+    gctUINT32                       cacheFree;
+
+    /* Time stamp for LINEAR mode. */
+    gctUINT64                       cacheStamp;
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+    /* Hash table for HASH mode. */
+    gcskLOGICAL_CACHE              hash[256];
+#endif
+}
+gcskSECURE_CACHE;
+
+/*******************************************************************************
+***** Process Database Management *********************************************/
+
+typedef enum _gceDATABASE_TYPE
+{
+    gcvDB_VIDEO_MEMORY = 1,             /* Video memory created. */
+    gcvDB_NON_PAGED,                    /* Non paged memory. */
+    gcvDB_CONTIGUOUS,                   /* Contiguous memory. */
+    gcvDB_SIGNAL,                       /* Signal. */
+    gcvDB_VIDEO_MEMORY_LOCKED,          /* Video memory locked. */
+    gcvDB_CONTEXT,                      /* Context */
+    gcvDB_IDLE,                         /* GPU idle. */
+    gcvDB_MAP_MEMORY,                   /* Map memory */
+    gcvDB_SHARED_INFO,                 /* Private data */
+    gcvDB_MAP_USER_MEMORY               /* Map user memory */
+}
+gceDATABASE_TYPE;
+
+typedef struct _gcsDATABASE_RECORD *    gcsDATABASE_RECORD_PTR;
+typedef struct _gcsDATABASE_RECORD
+{
+    /* Pointer to kernel. */
+    gckKERNEL                           kernel;
+
+    /* Pointer to next database record. */
+    gcsDATABASE_RECORD_PTR              next;
+
+    /* Type of record. */
+    gceDATABASE_TYPE                    type;
+
+    /* Data for record. */
+    gctPOINTER                          data;
+    gctPHYS_ADDR                        physical;
+    gctSIZE_T                           bytes;
+}
+gcsDATABASE_RECORD;
+
+typedef struct _gcsDATABASE *           gcsDATABASE_PTR;
+typedef struct _gcsDATABASE
+{
+    /* Pointer to next entry is hash list. */
+    gcsDATABASE_PTR                     next;
+    gctSIZE_T                           slot;
+
+    /* Process ID. */
+    gctUINT32                           processID;
+
+    /* Sizes to query. */
+    gcsDATABASE_COUNTERS                vidMem;
+    gcsDATABASE_COUNTERS                nonPaged;
+    gcsDATABASE_COUNTERS                contiguous;
+    gcsDATABASE_COUNTERS                mapUserMemory;
+    gcsDATABASE_COUNTERS                mapMemory;
+
+    /* Idle time management. */
+    gctUINT64                           lastIdle;
+    gctUINT64                           idle;
+
+    /* Pointer to database. */
+    gcsDATABASE_RECORD_PTR              list;
+
+#if gcdSECURE_USER
+    /* Secure cache. */
+    gcskSECURE_CACHE                    cache;
+#endif
+}
+gcsDATABASE;
+
+/* Create a process database that will contain all its allocations. */
+gceSTATUS
+gckKERNEL_CreateProcessDB(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID
+    );
+
+/* Add a record to the process database. */
+gceSTATUS
+gckKERNEL_AddProcessDB(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gceDATABASE_TYPE Type,
+    IN gctPOINTER Pointer,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Size
+    );
+
+/* Remove a record to the process database. */
+gceSTATUS
+gckKERNEL_RemoveProcessDB(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gceDATABASE_TYPE Type,
+    IN gctPOINTER Pointer
+    );
+
+/* Destroy the process database. */
+gceSTATUS
+gckKERNEL_DestroyProcessDB(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID
+    );
+
+/* Find a record to the process database. */
+gceSTATUS
+gckKERNEL_FindProcessDB(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gctUINT32 ThreadID,
+    IN gceDATABASE_TYPE Type,
+    IN gctPOINTER Pointer,
+    OUT gcsDATABASE_RECORD_PTR Record
+    );
+
+/* Query the process database. */
+gceSTATUS
+gckKERNEL_QueryProcessDB(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gctBOOL LastProcessID,
+    IN gceDATABASE_TYPE Type,
+    OUT gcuDATABASE_INFO * Info
+    );
+
+#if gcdSECURE_USER
+/* Get secure cache from the process database. */
+gceSTATUS
+gckKERNEL_GetProcessDBCache(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    OUT gcskSECURE_CACHE_PTR * Cache
+    );
+#endif
+
+/*******************************************************************************
+********* Timer Management ****************************************************/
+typedef struct _gcsTIMER *           gcsTIMER_PTR;
+typedef struct _gcsTIMER
+{
+    /* Start and Stop time holders. */
+    gctUINT64                           startTime;
+    gctUINT64                           stopTime;
+}
+gcsTIMER;
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+/* gckDB object. */
+struct _gckDB
+{
+    /* Database management. */
+    gcsDATABASE_PTR             db[16];
+    gctPOINTER                  dbMutex;
+    gcsDATABASE_PTR             freeDatabase;
+    gcsDATABASE_RECORD_PTR      freeRecord;
+    gcsDATABASE_PTR             lastDatabase;
+    gctUINT32                   lastProcessID;
+    gctUINT64                   lastIdle;
+    gctUINT64                   idleTime;
+    gctUINT64                   lastSlowdown;
+    gctUINT64                   lastSlowdownIdle;
+};
+
+/* gckKERNEL object. */
+struct _gckKERNEL
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gckOS object. */
+    gckOS                       os;
+
+    /* Core */
+    gceCORE                     core;
+
+    /* Pointer to gckHARDWARE object. */
+    gckHARDWARE                 hardware;
+
+    /* Pointer to gckCOMMAND object. */
+    gckCOMMAND                  command;
+
+    /* Pointer to gckEVENT object. */
+    gckEVENT                    eventObj;
+
+    /* Pointer to context. */
+    gctPOINTER                  context;
+
+    /* Pointer to gckMMU object. */
+    gckMMU                      mmu;
+
+    /* Arom holding number of clients. */
+    gctPOINTER                  atomClients;
+
+#if VIVANTE_PROFILER
+    /* Enable profiling */
+    gctBOOL                     profileEnable;
+
+    /* The profile file name */
+    gctCHAR                     profileFileName[gcdMAX_PROFILE_FILE_NAME];
+#endif
+
+#ifdef QNX_SINGLE_THREADED_DEBUGGING
+    gctPOINTER                  debugMutex;
+#endif
+
+    /* Database management. */
+    gckDB                       db;
+    gctBOOL                     dbCreated;
+
+    /* Pointer to gckEVENT object. */
+    gcsTIMER                    timers[8];
+    gctUINT32                   timeOut;
+
+#if gcdENABLE_VG
+    gckVGKERNEL                 vg;
+#endif
+};
+
+/* gckCOMMAND object. */
+struct _gckCOMMAND
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to required object. */
+    gckKERNEL                   kernel;
+    gckOS                       os;
+
+    /* Number of bytes per page. */
+    gctSIZE_T                   pageSize;
+
+    /* Current pipe select. */
+    gcePIPE_SELECT              pipeSelect;
+
+    /* Command queue running flag. */
+    gctBOOL                     running;
+
+    /* Idle flag and commit stamp. */
+    gctBOOL                     idle;
+    gctUINT64                   commitStamp;
+
+    /* Command queue mutex. */
+    gctPOINTER                  mutexQueue;
+
+    /* Context switching mutex. */
+    gctPOINTER                  mutexContext;
+
+    /* Command queue power semaphore. */
+    gctPOINTER                  powerSemaphore;
+
+    /* Current command queue. */
+    struct _gcskCOMMAND_QUEUE
+    {
+        gctSIGNAL               signal;
+        gctPHYS_ADDR            physical;
+        gctPOINTER              logical;
+    }
+    queues[gcdCOMMAND_QUEUES];
+
+    gctPHYS_ADDR                physical;
+    gctPOINTER                  logical;
+    gctUINT32                   offset;
+    gctINT                      index;
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+    gctUINT                     wrapCount;
+#endif
+
+    /* The command queue is new. */
+    gctBOOL                     newQueue;
+
+    /* Context management. */
+    gckCONTEXT                  currContext;
+
+    /* Pointer to last WAIT command. */
+    gctPHYS_ADDR                waitPhysical;
+    gctPOINTER                  waitLogical;
+    gctSIZE_T                   waitSize;
+
+    /* Command buffer alignment. */
+    gctSIZE_T                   alignment;
+    gctSIZE_T                   reservedHead;
+    gctSIZE_T                   reservedTail;
+
+    /* Commit counter. */
+    gctPOINTER                  atomCommit;
+
+    /* Kernel process ID. */
+    gctUINT32                   kernelProcessID;
+
+    /* End Event signal. */
+    gctSIGNAL                   endEventSignal;
+
+#if gcdSECURE_USER
+    /* Hint array copy buffer. */
+    gctBOOL                     hintArrayAllocated;
+    gctUINT                     hintArraySize;
+    gctUINT32_PTR               hintArray;
+#endif
+};
+
+typedef struct _gcsEVENT *      gcsEVENT_PTR;
+
+/* Structure holding one event to be processed. */
+typedef struct _gcsEVENT
+{
+    /* Pointer to next event in queue. */
+    gcsEVENT_PTR                next;
+
+    /* Event information. */
+    gcsHAL_INTERFACE            info;
+
+    /* Process ID owning the event. */
+    gctUINT32                   processID;
+
+#ifdef __QNXNTO__
+    /* Kernel. */
+    gckKERNEL                   kernel;
+#endif
+}
+gcsEVENT;
+
+/* Structure holding a list of events to be processed by an interrupt. */
+typedef struct _gcsEVENT_QUEUE * gcsEVENT_QUEUE_PTR;
+typedef struct _gcsEVENT_QUEUE
+{
+    /* Time stamp. */
+    gctUINT64                   stamp;
+
+    /* Source of the event. */
+    gceKERNEL_WHERE             source;
+
+    /* Pointer to head of event queue. */
+    gcsEVENT_PTR                head;
+
+    /* Pointer to tail of event queue. */
+    gcsEVENT_PTR                tail;
+
+    /* Next list of events. */
+    gcsEVENT_QUEUE_PTR          next;
+}
+gcsEVENT_QUEUE;
+
+/*
+    gcdREPO_LIST_COUNT defines the maximum number of event queues with different
+    hardware module sources that may coexist at the same time. Only two sources
+    are supported - gcvKERNEL_COMMAND and gcvKERNEL_PIXEL. gcvKERNEL_COMMAND
+    source is used only for managing the kernel command queue and is only issued
+    when the current command queue gets full. Since we commit event queues every
+    time we commit command buffers, in the worst case we can have up to three
+    pending event queues:
+        - gcvKERNEL_PIXEL
+        - gcvKERNEL_COMMAND (queue overflow)
+        - gcvKERNEL_PIXEL
+*/
+#define gcdREPO_LIST_COUNT      3
+
+/* gckEVENT object. */
+struct _gckEVENT
+{
+    /* The object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to required objects. */
+    gckOS                       os;
+    gckKERNEL                   kernel;
+
+    /* Time stamp. */
+    gctUINT64                   stamp;
+    gctUINT64                   lastCommitStamp;
+
+    /* Queue mutex. */
+    gctPOINTER                  eventQueueMutex;
+
+    /* Array of event queues. */
+    gcsEVENT_QUEUE              queues[31];
+    gctUINT8                    lastID;
+    gctPOINTER                  freeAtom;
+
+    /* Pending events. */
+    volatile gctUINT            pending;
+
+    /* List of free event structures and its mutex. */
+    gcsEVENT_PTR                freeEventList;
+    gctSIZE_T                   freeEventCount;
+    gctPOINTER                  freeEventMutex;
+
+    /* Event queues. */
+    gcsEVENT_QUEUE_PTR          queueHead;
+    gcsEVENT_QUEUE_PTR          queueTail;
+    gcsEVENT_QUEUE_PTR          freeList;
+    gcsEVENT_QUEUE              repoList[gcdREPO_LIST_COUNT];
+    gctPOINTER                  eventListMutex;
+};
+
+/* Free all events belonging to a process. */
+gceSTATUS
+gckEVENT_FreeProcess(
+    IN gckEVENT Event,
+    IN gctUINT32 ProcessID
+    );
+
+gceSTATUS
+gckEVENT_Stop(
+    IN gckEVENT Event,
+    IN gctUINT32 ProcessID,
+    IN gctPHYS_ADDR Handle,
+    IN gctPOINTER Logical,
+    IN gctSIGNAL Signal,
+       IN OUT gctSIZE_T * waitSize
+    );
+
+/* gcuVIDMEM_NODE structure. */
+typedef union _gcuVIDMEM_NODE
+{
+    /* Allocated from gckVIDMEM. */
+    struct _gcsVIDMEM_NODE_VIDMEM
+    {
+        /* Owner of this node. */
+        gckVIDMEM               memory;
+
+        /* Dual-linked list of nodes. */
+        gcuVIDMEM_NODE_PTR      next;
+        gcuVIDMEM_NODE_PTR      prev;
+
+        /* Dual linked list of free nodes. */
+        gcuVIDMEM_NODE_PTR      nextFree;
+        gcuVIDMEM_NODE_PTR      prevFree;
+
+        /* Information for this node. */
+        gctUINT32               offset;
+        gctSIZE_T               bytes;
+        gctUINT32               alignment;
+
+#ifdef __QNXNTO__
+        /* Client/server vaddr (mapped using mmap_join). */
+        gctPOINTER              logical;
+#endif
+
+        /* Locked counter. */
+        gctINT32                locked;
+
+        /* Memory pool. */
+        gcePOOL                 pool;
+        gctUINT32               physical;
+
+        /* Process ID owning this memory. */
+        gctUINT32               processID;
+
+        /* Prevent compositor from freeing until client unlocks. */
+        gctBOOL                 freePending;
+
+        /* */
+        gcsVIDMEM_NODE_SHARED_INFO sharedInfo;
+    }
+    VidMem;
+
+    /* Allocated from gckOS. */
+    struct _gcsVIDMEM_NODE_VIRTUAL
+    {
+        /* Pointer to gckKERNEL object. */
+        gckKERNEL               kernel;
+
+        /* Information for this node. */
+        /* Contiguously allocated? */
+        gctBOOL                 contiguous;
+        /* mdl record pointer... a kmalloc address. Process agnostic. */
+        gctPHYS_ADDR            physical;
+        gctSIZE_T               bytes;
+        /* do_mmap_pgoff address... mapped per-process. */
+        gctPOINTER              logical;
+
+        /* Page table information. */
+        /* Used only when node is not contiguous */
+        gctSIZE_T               pageCount;
+
+        /* Used only when node is not contiguous */
+        gctPOINTER              pageTables[gcdCORE_COUNT];
+        /* Pointer to gckKERNEL object who lock this. */
+        gckKERNEL               lockKernels[gcdCORE_COUNT];
+        /* Actual physical address */
+        gctUINT32               addresses[gcdCORE_COUNT];
+
+        /* Mutex. */
+        gctPOINTER              mutex;
+
+        /* Locked counter. */
+        gctINT32                lockeds[gcdCORE_COUNT];
+
+#ifdef __QNXNTO__
+        /* Single linked list of nodes. */
+        gcuVIDMEM_NODE_PTR      next;
+
+        /* Unlock pending flag. */
+        gctBOOL                 unlockPendings[gcdCORE_COUNT];
+
+        /* Free pending flag. */
+        gctBOOL                 freePending;
+#endif
+
+        /* Process ID owning this memory. */
+        gctUINT32               processID;
+
+        /* Owner process sets freed to true
+         * when it trys to free a locked
+         * node */
+        gctBOOL                 freed;
+
+        /* */
+        gcsVIDMEM_NODE_SHARED_INFO sharedInfo;
+    }
+    Virtual;
+}
+gcuVIDMEM_NODE;
+
+/* gckVIDMEM object. */
+struct _gckVIDMEM
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gckOS object. */
+    gckOS                       os;
+
+    /* Information for this video memory heap. */
+    gctUINT32                   baseAddress;
+    gctSIZE_T                   bytes;
+    gctSIZE_T                   freeBytes;
+
+    /* Mapping for each type of surface. */
+    gctINT                      mapping[gcvSURF_NUM_TYPES];
+
+    /* Sentinel nodes for up to 8 banks. */
+    gcuVIDMEM_NODE              sentinel[8];
+
+    /* Allocation threshold. */
+    gctSIZE_T                   threshold;
+
+    /* The heap mutex. */
+    gctPOINTER                  mutex;
+
+#if gcdUSE_VIDMEM_PER_PID
+    /* The Pid this VidMem belongs to. */
+    gctUINT32                   pid;
+
+    struct _gckVIDMEM*          next;
+#endif
+};
+
+/* gckMMU object. */
+struct _gckMMU
+{
+    /* The object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gckOS object. */
+    gckOS                       os;
+
+    /* Pointer to gckHARDWARE object. */
+    gckHARDWARE                 hardware;
+
+    /* The page table mutex. */
+    gctPOINTER                  pageTableMutex;
+
+    /* Page table information. */
+    gctSIZE_T                   pageTableSize;
+    gctPHYS_ADDR                pageTablePhysical;
+    gctUINT32_PTR               pageTableLogical;
+    gctUINT32                   pageTableEntries;
+
+    /* Free entries. */
+    gctUINT32                   heapList;
+    gctBOOL                     freeNodes;
+
+    gctPOINTER                  staticSTLB;
+    gctBOOL                     enabled;
+
+#ifdef __QNXNTO__
+    /* Single linked list of all allocated nodes. */
+    gctPOINTER                  nodeMutex;
+    gcuVIDMEM_NODE_PTR          nodeList;
+#endif
+};
+
+gceSTATUS
+gckKERNEL_AttachProcess(
+    IN gckKERNEL Kernel,
+    IN gctBOOL Attach
+    );
+
+gceSTATUS
+gckKERNEL_AttachProcessEx(
+    IN gckKERNEL Kernel,
+    IN gctBOOL Attach,
+    IN gctUINT32 PID
+    );
+
+#if gcdSECURE_USER
+gceSTATUS
+gckKERNEL_MapLogicalToPhysical(
+    IN gckKERNEL Kernel,
+    IN gcskSECURE_CACHE_PTR Cache,
+    IN OUT gctPOINTER * Data
+    );
+
+gceSTATUS
+gckKERNEL_FlushTranslationCache(
+    IN gckKERNEL Kernel,
+    IN gcskSECURE_CACHE_PTR Cache,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    );
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryIdle(
+    IN gckHARDWARE Hardware,
+    OUT gctBOOL_PTR IsIdle
+    );
+
+/******************************************************************************\
+******************************* gckCONTEXT Object *******************************
+\******************************************************************************/
+
+gceSTATUS
+gckCONTEXT_Construct(
+    IN gckOS Os,
+    IN gckHARDWARE Hardware,
+    IN gctUINT32 ProcessID,
+    OUT gckCONTEXT * Context
+    );
+
+gceSTATUS
+gckCONTEXT_Destroy(
+    IN gckCONTEXT Context
+    );
+
+gceSTATUS
+gckCONTEXT_Update(
+    IN gckCONTEXT Context,
+    IN gctUINT32 ProcessID,
+    IN gcsSTATE_DELTA_PTR StateDelta
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
new file mode 100644 (file)
index 0000000..d49742f
--- /dev/null
@@ -0,0 +1,2556 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+#include "gc_hal_kernel_context.h"
+
+#ifdef __QNXNTO__
+#include <sys/slog.h>
+#endif
+
+#define _GC_OBJ_ZONE            gcvZONE_COMMAND
+
+/* When enabled, extra messages needed by the dump parser are left out. */
+#define gcdSIMPLE_COMMAND_DUMP  1
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  _NewQueue
+**
+**  Allocate a new command queue.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to an gckCOMMAND object.
+**
+**  OUTPUT:
+**
+**      gckCOMMAND Command
+**          gckCOMMAND object has been updated with a new command queue.
+*/
+static gceSTATUS
+_NewQueue(
+    IN OUT gckCOMMAND Command
+    )
+{
+    gceSTATUS status;
+    gctINT currentIndex, newIndex;
+
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Switch to the next command buffer. */
+    currentIndex = Command->index;
+    newIndex     = (currentIndex + 1) % gcdCOMMAND_QUEUES;
+
+    /* Wait for availability. */
+#if gcdDUMP_COMMAND && !gcdSIMPLE_COMMAND_DUMP
+    gcmkPRINT("@[kernel.waitsignal]");
+#endif
+
+    gcmkONERROR(gckOS_WaitSignal(
+        Command->os,
+        Command->queues[newIndex].signal,
+        gcvINFINITE
+        ));
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+    if (newIndex < currentIndex)
+    {
+        Command->wrapCount += 1;
+
+        gcmkTRACE_ZONE_N(
+            gcvLEVEL_INFO, gcvZONE_COMMAND,
+            2 * 4,
+            "%s(%d): queue array wrapped around.\n",
+            __FUNCTION__, __LINE__
+            );
+    }
+
+    gcmkTRACE_ZONE_N(
+        gcvLEVEL_INFO, gcvZONE_COMMAND,
+        3 * 4,
+        "%s(%d): total queue wrap arounds %d.\n",
+        __FUNCTION__, __LINE__, Command->wrapCount
+        );
+
+    gcmkTRACE_ZONE_N(
+        gcvLEVEL_INFO, gcvZONE_COMMAND,
+        3 * 4,
+        "%s(%d): switched to queue %d.\n",
+        __FUNCTION__, __LINE__, newIndex
+        );
+#endif
+
+    /* Update gckCOMMAND object with new command queue. */
+    Command->index    = newIndex;
+    Command->newQueue = gcvTRUE;
+    Command->logical  = Command->queues[newIndex].logical;
+    Command->offset   = 0;
+
+    gcmkONERROR(
+        gckOS_GetPhysicalAddress(
+            Command->os,
+            Command->logical,
+            (gctUINT32 *) &Command->physical
+            ));
+
+    if (currentIndex != -1)
+    {
+        /* Mark the command queue as available. */
+        gcmkONERROR(gckEVENT_Signal(
+            Command->kernel->eventObj,
+            Command->queues[currentIndex].signal,
+            gcvKERNEL_COMMAND
+            ));
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("Command->index=%d", Command->index);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+static gceSTATUS
+_IncrementCommitAtom(
+    IN gckCOMMAND Command,
+    IN gctBOOL Increment
+    )
+{
+    gceSTATUS status;
+    gckHARDWARE hardware;
+    gctINT32 atomValue;
+    gctBOOL powerAcquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Extract the gckHARDWARE and gckEVENT objects. */
+    hardware = Command->kernel->hardware;
+    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+    /* Grab the power mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(
+        Command->os, hardware->powerMutex, gcvINFINITE
+        ));
+    powerAcquired = gcvTRUE;
+
+    /* Increment the commit atom. */
+    if (Increment)
+    {
+        gcmkONERROR(gckOS_AtomIncrement(
+            Command->os, Command->atomCommit, &atomValue
+            ));
+    }
+    else
+    {
+        gcmkONERROR(gckOS_AtomDecrement(
+            Command->os, Command->atomCommit, &atomValue
+            ));
+    }
+
+    /* Release the power mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(
+        Command->os, hardware->powerMutex
+        ));
+    powerAcquired = gcvFALSE;
+
+    /* Success. */
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (powerAcquired)
+    {
+        /* Release the power mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(
+            Command->os, hardware->powerMutex
+            ));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+#if gcdSECURE_USER
+static gceSTATUS
+_ProcessHints(
+    IN gckCOMMAND Command,
+    IN gctUINT32 ProcessID,
+    IN gcoCMDBUF CommandBuffer
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+    gckKERNEL kernel;
+    gctBOOL needCopy = gcvFALSE;
+    gcskSECURE_CACHE_PTR cache;
+    gctUINT8_PTR commandBufferLogical;
+    gctUINT8_PTR hintedData;
+    gctUINT32_PTR hintArray;
+    gctUINT i, hintCount;
+
+    gcmkHEADER_ARG(
+        "Command=0x%08X ProcessID=%d CommandBuffer=0x%08X",
+        Command, ProcessID, CommandBuffer
+        );
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    /* Reset state array pointer. */
+    hintArray = gcvNULL;
+
+    /* Get the kernel object. */
+    kernel = Command->kernel;
+
+    /* Get the cache form the database. */
+    gcmkONERROR(gckKERNEL_GetProcessDBCache(kernel, ProcessID, &cache));
+
+    /* Determine the start of the command buffer. */
+    commandBufferLogical
+        = (gctUINT8_PTR) CommandBuffer->logical
+        +                CommandBuffer->startOffset;
+
+    /* Determine the number of records in the state array. */
+    hintCount = CommandBuffer->hintArrayTail - CommandBuffer->hintArray;
+
+    /* Check wehther we need to copy the structures or not. */
+    gcmkONERROR(gckOS_QueryNeedCopy(Command->os, ProcessID, &needCopy));
+
+    /* Get access to the state array. */
+    if (needCopy)
+    {
+        gctUINT copySize;
+
+        if (Command->hintArrayAllocated &&
+            (Command->hintArraySize < CommandBuffer->hintArraySize))
+        {
+            gcmkONERROR(gcmkOS_SAFE_FREE(Command->os, Command->hintArray));
+            Command->hintArraySize = gcvFALSE;
+        }
+
+        if (!Command->hintArrayAllocated)
+        {
+            gctPOINTER pointer = gcvNULL;
+
+            gcmkONERROR(gckOS_Allocate(
+                Command->os,
+                CommandBuffer->hintArraySize,
+                &pointer
+                ));
+
+            Command->hintArray          = pointer;
+            Command->hintArrayAllocated = gcvTRUE;
+            Command->hintArraySize      = CommandBuffer->hintArraySize;
+        }
+
+        hintArray = Command->hintArray;
+        copySize   = hintCount * gcmSIZEOF(gctUINT32);
+
+        gcmkONERROR(gckOS_CopyFromUserData(
+            Command->os,
+            hintArray,
+            CommandBuffer->hintArray,
+            copySize
+            ));
+    }
+    else
+    {
+        gctPOINTER pointer = gcvNULL;
+
+        gcmkONERROR(gckOS_MapUserPointer(
+            Command->os,
+            CommandBuffer->hintArray,
+            CommandBuffer->hintArraySize,
+            &pointer
+            ));
+
+        hintArray = pointer;
+    }
+
+    /* Scan through the buffer. */
+    for (i = 0; i < hintCount; i += 1)
+    {
+        /* Determine the location of the hinted data. */
+        hintedData = commandBufferLogical + hintArray[i];
+
+        /* Map handle into physical address. */
+        gcmkONERROR(gckKERNEL_MapLogicalToPhysical(
+            kernel, cache, (gctPOINTER) hintedData
+            ));
+    }
+
+OnError:
+    /* Get access to the state array. */
+    if (!needCopy && (hintArray != gcvNULL))
+    {
+        gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+            Command->os,
+            CommandBuffer->hintArray,
+            CommandBuffer->hintArraySize,
+            hintArray
+            ));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+#endif
+
+
+/******************************************************************************\
+****************************** gckCOMMAND API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckCOMMAND_Construct
+**
+**  Construct a new gckCOMMAND object.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**  OUTPUT:
+**
+**      gckCOMMAND * Command
+**          Pointer to a variable that will hold the pointer to the gckCOMMAND
+**          object.
+*/
+gceSTATUS
+gckCOMMAND_Construct(
+    IN gckKERNEL Kernel,
+    OUT gckCOMMAND * Command
+    )
+{
+    gckOS os;
+    gckCOMMAND command = gcvNULL;
+    gceSTATUS status;
+    gctINT i;
+    gctPOINTER pointer = gcvNULL;
+
+    gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Command != gcvNULL);
+
+    /* Extract the gckOS object. */
+    os = Kernel->os;
+
+    /* Allocate the gckCOMMAND structure. */
+    gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckCOMMAND), &pointer));
+    command = pointer;
+
+    /* Reset the entire object. */
+    gcmkONERROR(gckOS_ZeroMemory(command, gcmSIZEOF(struct _gckCOMMAND)));
+
+    /* Initialize the gckCOMMAND object.*/
+    command->object.type    = gcvOBJ_COMMAND;
+    command->kernel         = Kernel;
+    command->os             = os;
+
+    /* Get the command buffer requirements. */
+    gcmkONERROR(gckHARDWARE_QueryCommandBuffer(
+        Kernel->hardware,
+        &command->alignment,
+        &command->reservedHead,
+        &command->reservedTail
+        ));
+
+    /* Create the command queue mutex. */
+    gcmkONERROR(gckOS_CreateMutex(os, &command->mutexQueue));
+
+    /* Create the context switching mutex. */
+    gcmkONERROR(gckOS_CreateMutex(os, &command->mutexContext));
+
+    /* Create the power management semaphore. */
+    gcmkONERROR(gckOS_CreateSemaphore(os, &command->powerSemaphore));
+
+    /* Create the commit atom. */
+    gcmkONERROR(gckOS_AtomConstruct(os, &command->atomCommit));
+
+    /* Get the page size from teh OS. */
+    gcmkONERROR(gckOS_GetPageSize(os, &command->pageSize));
+
+    /* Get process ID. */
+    gcmkONERROR(gckOS_GetProcessID(&command->kernelProcessID));
+
+    /* Set hardware to pipe 0. */
+    command->pipeSelect = gcvPIPE_INVALID;
+
+    /* Pre-allocate the command queues. */
+    for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+    {
+        gcmkONERROR(gckOS_AllocateNonPagedMemory(
+            os,
+            gcvFALSE,
+            &command->pageSize,
+            &command->queues[i].physical,
+            &command->queues[i].logical
+            ));
+
+        gcmkONERROR(gckOS_CreateSignal(
+            os, gcvFALSE, &command->queues[i].signal
+            ));
+
+        gcmkONERROR(gckOS_Signal(
+            os, command->queues[i].signal, gcvTRUE
+            ));
+    }
+
+    /* No command queue in use yet. */
+    command->index    = -1;
+    command->logical  = gcvNULL;
+    command->newQueue = gcvFALSE;
+
+    /* Command is not yet running. */
+    command->running = gcvFALSE;
+
+    /* Command queue is idle. */
+    command->idle = gcvTRUE;
+
+    /* Commit stamp is zero. */
+    command->commitStamp = 0;
+
+    /* END event signal not created. */
+    command->endEventSignal = gcvNULL;
+
+    /* Return pointer to the gckCOMMAND object. */
+    *Command = command;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Command=0x%x", *Command);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (command != gcvNULL)
+    {
+        if (command->atomCommit != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_AtomDestroy(os, command->atomCommit));
+        }
+
+        if (command->powerSemaphore != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_DestroySemaphore(os, command->powerSemaphore));
+        }
+
+        if (command->mutexContext != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(os, command->mutexContext));
+        }
+
+        if (command->mutexQueue != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(os, command->mutexQueue));
+        }
+
+        for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+        {
+            if (command->queues[i].signal != gcvNULL)
+            {
+                gcmkVERIFY_OK(gckOS_DestroySignal(
+                    os, command->queues[i].signal
+                    ));
+            }
+
+            if (command->queues[i].logical != gcvNULL)
+            {
+                gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+                    os,
+                    command->pageSize,
+                    command->queues[i].physical,
+                    command->queues[i].logical
+                    ));
+            }
+        }
+
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, command));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_Destroy
+**
+**  Destroy an gckCOMMAND object.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to an gckCOMMAND object to destroy.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Destroy(
+    IN gckCOMMAND Command
+    )
+{
+    gctINT i;
+
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    /* Stop the command queue. */
+    gcmkVERIFY_OK(gckCOMMAND_Stop(Command));
+
+    for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+    {
+        gcmkASSERT(Command->queues[i].signal != gcvNULL);
+        gcmkVERIFY_OK(gckOS_DestroySignal(
+            Command->os, Command->queues[i].signal
+            ));
+
+        gcmkASSERT(Command->queues[i].logical != gcvNULL);
+        gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+            Command->os,
+            Command->pageSize,
+            Command->queues[i].physical,
+            Command->queues[i].logical
+            ));
+    }
+
+    /* END event signal. */
+    if (Command->endEventSignal != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckOS_DestroySignal(
+            Command->os, Command->endEventSignal
+            ));
+    }
+
+    /* Delete the context switching mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexContext));
+
+    /* Delete the command queue mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexQueue));
+
+    /* Destroy the power management semaphore. */
+    gcmkVERIFY_OK(gckOS_DestroySemaphore(Command->os, Command->powerSemaphore));
+
+    /* Destroy the commit atom. */
+    gcmkVERIFY_OK(gckOS_AtomDestroy(Command->os, Command->atomCommit));
+
+#if gcdSECURE_USER
+    /* Free state array. */
+    if (Command->hintArrayAllocated)
+    {
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Command->os, Command->hintArray));
+        Command->hintArrayAllocated = gcvFALSE;
+    }
+#endif
+
+    /* Mark object as unknown. */
+    Command->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the gckCOMMAND object. */
+    gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Command->os, Command));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_EnterCommit
+**
+**  Acquire command queue synchronization objects.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to an gckCOMMAND object to destroy.
+**
+**      gctBOOL FromPower
+**          Determines whether the call originates from inside the power
+**          management or not.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCOMMAND_EnterCommit(
+    IN gckCOMMAND Command,
+    IN gctBOOL FromPower
+    )
+{
+    gceSTATUS status;
+    gckHARDWARE hardware;
+    gctBOOL atomIncremented = gcvFALSE;
+    gctBOOL semaAcquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Extract the gckHARDWARE and gckEVENT objects. */
+    hardware = Command->kernel->hardware;
+    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+    if (!FromPower)
+    {
+        /* Increment COMMIT atom to let power management know that a commit is
+        ** in progress. */
+        gcmkONERROR(_IncrementCommitAtom(Command, gcvTRUE));
+        atomIncremented = gcvTRUE;
+
+        /* Notify the system the GPU has a commit. */
+        gcmkONERROR(gckOS_Broadcast(Command->os,
+                                    hardware,
+                                    gcvBROADCAST_GPU_COMMIT));
+
+        /* Acquire the power management semaphore. */
+        gcmkONERROR(gckOS_AcquireSemaphore(Command->os,
+                                           Command->powerSemaphore));
+        semaAcquired = gcvTRUE;
+    }
+
+    /* Grab the conmmand queue mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(Command->os,
+                                   Command->mutexQueue,
+                                   gcvINFINITE));
+
+    /* Success. */
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (semaAcquired)
+    {
+        /* Release the power management semaphore. */
+        gcmkVERIFY_OK(gckOS_ReleaseSemaphore(
+            Command->os, Command->powerSemaphore
+            ));
+    }
+
+    if (atomIncremented)
+    {
+        /* Decrement the commit atom. */
+        gcmkVERIFY_OK(_IncrementCommitAtom(
+            Command, gcvFALSE
+            ));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_ExitCommit
+**
+**  Release command queue synchronization objects.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to an gckCOMMAND object to destroy.
+**
+**      gctBOOL FromPower
+**          Determines whether the call originates from inside the power
+**          management or not.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCOMMAND_ExitCommit(
+    IN gckCOMMAND Command,
+    IN gctBOOL FromPower
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Release the power mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+
+    if (!FromPower)
+    {
+        /* Release the power management semaphore. */
+        gcmkONERROR(gckOS_ReleaseSemaphore(Command->os,
+                                           Command->powerSemaphore));
+
+        /* Decrement the commit atom. */
+        gcmkONERROR(_IncrementCommitAtom(Command, gcvFALSE));
+    }
+
+    /* Success. */
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_Start
+**
+**  Start up the command queue.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to an gckCOMMAND object to start.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Start(
+    IN gckCOMMAND Command
+    )
+{
+    gceSTATUS status;
+    gckHARDWARE hardware;
+    gctUINT32 waitOffset;
+    gctSIZE_T waitLinkBytes;
+
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    if (Command->running)
+    {
+        /* Command queue already running. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+    /* Extract the gckHARDWARE object. */
+    hardware = Command->kernel->hardware;
+    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+    if (Command->logical == gcvNULL)
+    {
+        /* Start at beginning of a new queue. */
+        gcmkONERROR(_NewQueue(Command));
+    }
+
+    /* Start at beginning of page. */
+    Command->offset = 0;
+
+    /* Set abvailable number of bytes for WAIT/LINK command sequence. */
+    waitLinkBytes = Command->pageSize;
+
+    /* Append WAIT/LINK. */
+    gcmkONERROR(gckHARDWARE_WaitLink(
+        hardware,
+        Command->logical,
+        0,
+        &waitLinkBytes,
+        &waitOffset,
+        &Command->waitSize
+        ));
+
+    Command->waitLogical  = (gctUINT8_PTR) Command->logical  + waitOffset;
+    Command->waitPhysical = (gctUINT8_PTR) Command->physical + waitOffset;
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+    /* Flush the cache for the wait/link. */
+    gcmkONERROR(gckOS_CacheClean(
+        Command->os,
+        Command->kernelProcessID,
+        gcvNULL,
+        Command->physical,
+        Command->logical,
+        waitLinkBytes
+        ));
+#endif
+
+    /* Adjust offset. */
+    Command->offset   = waitLinkBytes;
+    Command->newQueue = gcvFALSE;
+
+    /* Enable command processor. */
+#ifdef __QNXNTO__
+    gcmkONERROR(gckHARDWARE_Execute(
+        hardware,
+        Command->logical,
+        Command->physical,
+        gcvTRUE,
+        waitLinkBytes
+        ));
+#else
+    gcmkONERROR(gckHARDWARE_Execute(
+        hardware,
+        Command->logical,
+        waitLinkBytes
+        ));
+#endif
+
+    /* Command queue is running. */
+    Command->running = gcvTRUE;
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_Stop
+**
+**  Stop the command queue.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to an gckCOMMAND object to stop.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Stop(
+    IN gckCOMMAND Command
+    )
+{
+    gckHARDWARE hardware;
+    gceSTATUS status;
+    gctUINT32 idle;
+
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    if (!Command->running)
+    {
+        /* Command queue is not running. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+    /* Extract the gckHARDWARE object. */
+    hardware = Command->kernel->hardware;
+    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+    if (gckHARDWARE_IsFeatureAvailable(hardware,
+                                       gcvFEATURE_END_EVENT) == gcvSTATUS_TRUE)
+    {
+        /* Allocate the signal. */
+        if (Command->endEventSignal == gcvNULL)
+        {
+            gcmkONERROR(gckOS_CreateSignal(Command->os,
+                                           gcvTRUE,
+                                           &Command->endEventSignal));
+        }
+
+        /* Append the END EVENT command to trigger the signal. */
+        gcmkONERROR(gckEVENT_Stop(Command->kernel->eventObj,
+                                  Command->kernelProcessID,
+                                  Command->waitPhysical,
+                                  Command->waitLogical,
+                                  Command->endEventSignal,
+                                                                 &Command->waitSize));
+    }
+    else
+    {
+        /* Replace last WAIT with END. */
+        gcmkONERROR(gckHARDWARE_End(
+            hardware, Command->waitLogical, &Command->waitSize
+            ));
+
+        /* Update queue tail pointer. */
+        gcmkONERROR(gckHARDWARE_UpdateQueueTail(Command->kernel->hardware,
+                                                Command->logical,
+                                                Command->offset));
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+        /* Flush the cache for the END. */
+        gcmkONERROR(gckOS_CacheClean(
+            Command->os,
+            Command->kernelProcessID,
+            gcvNULL,
+            Command->waitPhysical,
+            Command->waitLogical,
+            Command->waitSize
+            ));
+#endif
+
+        /* Wait for idle. */
+        gcmkONERROR(gckHARDWARE_GetIdle(hardware, gcvTRUE, &idle));
+    }
+
+    /* Command queue is no longer running. */
+    Command->running = gcvFALSE;
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_Commit
+**
+**  Commit a command buffer to the command queue.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to a gckCOMMAND object.
+**
+**      gckCONTEXT Context
+**          Pointer to a gckCONTEXT object.
+**
+**      gcoCMDBUF CommandBuffer
+**          Pointer to a gcoCMDBUF object.
+**
+**      gcsSTATE_DELTA_PTR StateDelta
+**          Pointer to the state delta.
+**
+**      gctUINT32 ProcessID
+**          Current process ID.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Commit(
+    IN gckCOMMAND Command,
+    IN gckCONTEXT Context,
+    IN gcoCMDBUF CommandBuffer,
+    IN gcsSTATE_DELTA_PTR StateDelta,
+    IN gcsQUEUE_PTR EventQueue,
+    IN gctUINT32 ProcessID
+    )
+{
+#if gcdNULL_DRIVER
+    /* Context switch required? */
+    if ((Context != gcvNULL) && (Command->currContext != Context))
+    {
+        /* Yes, merge in the deltas. */
+        gckCONTEXT_Update(Context, ProcessID, StateDelta);
+
+               /* Update the current context. */
+               Command->currContext = Context;
+       }
+
+    /* Do nothing with infinite hardware. */
+    return gcvSTATUS_OK;
+#else
+    gceSTATUS status;
+    gckHARDWARE hardware;
+    gcsCONTEXT_PTR contextBuffer;
+
+    gctBOOL needCopy = gcvFALSE;
+
+    struct _gcoCMDBUF _commandBufferObject;
+    gcoCMDBUF commandBufferObject = gcvNULL;
+    gctBOOL commandBufferMapped = gcvFALSE;
+    gctPHYS_ADDR commandBufferPhysical;
+    gctUINT8_PTR commandBufferLogical;
+    gctUINT8_PTR commandBufferLink;
+    gctUINT commandBufferSize;
+
+    gctBOOL commitEntered = gcvFALSE;
+    gctBOOL contextAcquired = gcvFALSE;
+
+    gctSIZE_T nopBytes;
+    gctSIZE_T pipeBytes;
+    gctSIZE_T linkBytes;
+    gctSIZE_T bytes;
+    gctUINT32 offset;
+
+    gctPHYS_ADDR entryPhysical;
+    gctPOINTER entryLogical;
+    gctSIZE_T entryBytes;
+
+    gctPHYS_ADDR exitPhysical;
+    gctPOINTER exitLogical;
+    gctSIZE_T exitBytes;
+
+    gctPHYS_ADDR waitLinkPhysical;
+    gctPOINTER waitLinkLogical;
+    gctSIZE_T waitLinkBytes;
+
+    gctPHYS_ADDR waitPhysical;
+    gctPOINTER waitLogical;
+    gctUINT32 waitOffset;
+    gctSIZE_T waitSize;
+
+    gcsQUEUE _eventRecord;
+    gcsQUEUE_PTR eventRecord = gcvNULL;
+    gcsQUEUE_PTR nextEventRecord;
+
+#if gcdDUMP_COMMAND
+    gctPOINTER contextDumpLogical = gcvNULL;
+    gctSIZE_T contextDumpBytes = 0;
+
+    gctPOINTER bufferDumpLogical = gcvNULL;
+    gctSIZE_T bufferDumpBytes = 0;
+#endif
+
+    gctPOINTER pointer = gcvNULL;
+
+    gcmkHEADER_ARG(
+        "Command=0x%x CommandBuffer=0x%x ProcessID=%d",
+        Command, CommandBuffer, ProcessID
+        );
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    /* Acquire the command queue. */
+    gcmkONERROR(gckCOMMAND_EnterCommit(Command, gcvFALSE));
+    commitEntered = gcvTRUE;
+
+    /* Acquire the context switching mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(
+        Command->os, Command->mutexContext, gcvINFINITE
+        ));
+    contextAcquired = gcvTRUE;
+
+    /* Extract the gckHARDWARE and gckEVENT objects. */
+    hardware = Command->kernel->hardware;
+
+    /* Check wehther we need to copy the structures or not. */
+    gcmkONERROR(gckOS_QueryNeedCopy(Command->os, ProcessID, &needCopy));
+
+    if (needCopy)
+    {
+        commandBufferObject = &_commandBufferObject;
+
+        gcmkONERROR(gckOS_CopyFromUserData(
+            Command->os,
+            commandBufferObject,
+            CommandBuffer,
+            gcmSIZEOF(struct _gcoCMDBUF)
+            ));
+
+        gcmkVERIFY_OBJECT(commandBufferObject, gcvOBJ_COMMANDBUFFER);
+    }
+    else
+    {
+        gcmkONERROR(gckOS_MapUserPointer(
+            Command->os,
+            CommandBuffer,
+            gcmSIZEOF(struct _gcoCMDBUF),
+            &pointer
+            ));
+
+        commandBufferObject = pointer;
+
+        gcmkVERIFY_OBJECT(commandBufferObject, gcvOBJ_COMMANDBUFFER);
+        commandBufferMapped = gcvTRUE;
+    }
+
+    /* Query the size of NOP command. */
+    gcmkONERROR(gckHARDWARE_Nop(
+        hardware, gcvNULL, &nopBytes
+        ));
+
+    /* Query the size of pipe select command sequence. */
+    gcmkONERROR(gckHARDWARE_PipeSelect(
+        hardware, gcvNULL, gcvPIPE_3D, &pipeBytes
+        ));
+
+    /* Query the size of LINK command. */
+    gcmkONERROR(gckHARDWARE_Link(
+        hardware, gcvNULL, gcvNULL, 0, &linkBytes
+        ));
+
+    /* Compute the command buffer entry and the size. */
+    commandBufferLogical
+        = (gctUINT8_PTR) commandBufferObject->logical
+        +                commandBufferObject->startOffset;
+
+    gcmkONERROR(gckOS_GetPhysicalAddress(
+        Command->os,
+        commandBufferLogical,
+        (gctUINT32_PTR)&commandBufferPhysical
+        ));
+
+    commandBufferSize
+        = commandBufferObject->offset
+        + Command->reservedTail
+        - commandBufferObject->startOffset;
+
+    /* Context switch required? */
+    if (Context == gcvNULL)
+    {
+        /* See if we have to switch pipes for the command buffer. */
+        if (commandBufferObject->entryPipe == Command->pipeSelect)
+        {
+            /* Skip pipe switching sequence. */
+            offset = pipeBytes;
+        }
+        else
+        {
+            /* The current hardware and the entry command buffer pipes
+            ** are different, switch to the correct pipe. */
+            gcmkONERROR(gckHARDWARE_PipeSelect(
+                Command->kernel->hardware,
+                commandBufferLogical,
+                commandBufferObject->entryPipe,
+                &pipeBytes
+                ));
+
+            /* Do not skip pipe switching sequence. */
+            offset = 0;
+        }
+
+        /* Compute the entry. */
+        entryPhysical = (gctUINT8_PTR) commandBufferPhysical + offset;
+        entryLogical  =                commandBufferLogical  + offset;
+        entryBytes    =                commandBufferSize     - offset;
+    }
+    else if (Command->currContext != Context)
+    {
+        /* Temporary disable context length oprimization. */
+        Context->dirty = gcvTRUE;
+
+        /* Get the current context buffer. */
+        contextBuffer = Context->buffer;
+
+        /* Yes, merge in the deltas. */
+        gcmkONERROR(gckCONTEXT_Update(Context, ProcessID, StateDelta));
+
+        /* Determine context entry and exit points. */
+        if (0)
+        {
+            /* Reset 2D dirty flag. */
+            Context->dirty2D = gcvFALSE;
+
+            if (Context->dirty || commandBufferObject->using3D)
+            {
+                /***************************************************************
+                ** SWITCHING CONTEXT: 2D and 3D are used.
+                */
+
+                /* Reset 3D dirty flag. */
+                Context->dirty3D = gcvFALSE;
+
+                /* Compute the entry. */
+                if (Command->pipeSelect == gcvPIPE_2D)
+                {
+                    entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
+                    entryLogical  = (gctUINT8_PTR) contextBuffer->logical  + pipeBytes;
+                    entryBytes    =                Context->bufferSize     - pipeBytes;
+                }
+                else
+                {
+                    entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
+                    entryLogical  = (gctUINT8_PTR) contextBuffer->logical;
+                    entryBytes    =                Context->bufferSize;
+                }
+
+                /* See if we have to switch pipes between the context
+                   and command buffers. */
+                if (commandBufferObject->entryPipe == gcvPIPE_3D)
+                {
+                    /* Skip pipe switching sequence. */
+                    offset = pipeBytes;
+                }
+                else
+                {
+                    /* The current hardware and the initial context pipes are
+                       different, switch to the correct pipe. */
+                    gcmkONERROR(gckHARDWARE_PipeSelect(
+                        Command->kernel->hardware,
+                        commandBufferLogical,
+                        commandBufferObject->entryPipe,
+                        &pipeBytes
+                        ));
+
+                    /* Do not skip pipe switching sequence. */
+                    offset = 0;
+                }
+
+                /* Ensure the NOP between 2D and 3D is in place so that the
+                   execution falls through from 2D to 3D. */
+                gcmkONERROR(gckHARDWARE_Nop(
+                    hardware,
+                    contextBuffer->link2D,
+                    &nopBytes
+                    ));
+
+                /* Generate a LINK from the context buffer to
+                   the command buffer. */
+                gcmkONERROR(gckHARDWARE_Link(
+                    hardware,
+                    contextBuffer->link3D,
+                    commandBufferLogical + offset,
+                    commandBufferSize    - offset,
+                    &linkBytes
+                    ));
+
+                /* Mark context as not dirty. */
+                Context->dirty = gcvFALSE;
+            }
+            else
+            {
+                /***************************************************************
+                ** SWITCHING CONTEXT: 2D only command buffer.
+                */
+
+                /* Mark 3D as dirty. */
+                Context->dirty3D = gcvTRUE;
+
+                /* Compute the entry. */
+                if (Command->pipeSelect == gcvPIPE_2D)
+                {
+                    entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
+                    entryLogical  = (gctUINT8_PTR) contextBuffer->logical  + pipeBytes;
+                    entryBytes    =                Context->entryOffset3D  - pipeBytes;
+                }
+                else
+                {
+                    entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
+                    entryLogical  = (gctUINT8_PTR) contextBuffer->logical;
+                    entryBytes    =                Context->entryOffset3D;
+                }
+
+                /* Store the current context buffer. */
+                Context->dirtyBuffer = contextBuffer;
+
+                /* See if we have to switch pipes between the context
+                   and command buffers. */
+                if (commandBufferObject->entryPipe == gcvPIPE_2D)
+                {
+                    /* Skip pipe switching sequence. */
+                    offset = pipeBytes;
+                }
+                else
+                {
+                    /* The current hardware and the initial context pipes are
+                       different, switch to the correct pipe. */
+                    gcmkONERROR(gckHARDWARE_PipeSelect(
+                        Command->kernel->hardware,
+                        commandBufferLogical,
+                        commandBufferObject->entryPipe,
+                        &pipeBytes
+                        ));
+
+                    /* Do not skip pipe switching sequence. */
+                    offset = 0;
+                }
+
+                /* 3D is not used, generate a LINK from the end of 2D part of
+                   the context buffer to the command buffer. */
+                gcmkONERROR(gckHARDWARE_Link(
+                    hardware,
+                    contextBuffer->link2D,
+                    commandBufferLogical + offset,
+                    commandBufferSize    - offset,
+                    &linkBytes
+                    ));
+            }
+        }
+
+        /* Not using 2D. */
+        else
+        {
+            /* Mark 2D as dirty. */
+            Context->dirty2D = gcvTRUE;
+
+            /* Store the current context buffer. */
+            Context->dirtyBuffer = contextBuffer;
+
+            if (Context->dirty || commandBufferObject->using3D)
+            {
+                /***************************************************************
+                ** SWITCHING CONTEXT: 3D only command buffer.
+                */
+
+                /* Reset 3D dirty flag. */
+                Context->dirty3D = gcvFALSE;
+
+                /* Determine context buffer entry offset. */
+                offset = (Command->pipeSelect == gcvPIPE_3D)
+
+                    /* Skip pipe switching sequence. */
+                    ? Context->entryOffset3D + pipeBytes
+
+                    /* Do not skip pipe switching sequence. */
+                    : Context->entryOffset3D;
+
+                /* Compute the entry. */
+                entryPhysical = (gctUINT8_PTR) contextBuffer->physical + offset;
+                entryLogical  = (gctUINT8_PTR) contextBuffer->logical  + offset;
+                entryBytes    =                Context->bufferSize     - offset;
+
+                /* See if we have to switch pipes between the context
+                   and command buffers. */
+                if (commandBufferObject->entryPipe == gcvPIPE_3D)
+                {
+                    /* Skip pipe switching sequence. */
+                    offset = pipeBytes;
+                }
+                else
+                {
+                    /* The current hardware and the initial context pipes are
+                       different, switch to the correct pipe. */
+                    gcmkONERROR(gckHARDWARE_PipeSelect(
+                        Command->kernel->hardware,
+                        commandBufferLogical,
+                        commandBufferObject->entryPipe,
+                        &pipeBytes
+                        ));
+
+                    /* Do not skip pipe switching sequence. */
+                    offset = 0;
+                }
+
+                /* Generate a LINK from the context buffer to
+                   the command buffer. */
+                gcmkONERROR(gckHARDWARE_Link(
+                    hardware,
+                    contextBuffer->link3D,
+                    commandBufferLogical + offset,
+                    commandBufferSize    - offset,
+                    &linkBytes
+                    ));
+            }
+            else
+            {
+                /***************************************************************
+                ** SWITCHING CONTEXT: "XD" command buffer - neither 2D nor 3D.
+                */
+
+                /* Mark 3D as dirty. */
+                Context->dirty3D = gcvTRUE;
+
+                /* Compute the entry. */
+                if (Command->pipeSelect == gcvPIPE_3D)
+                {
+                    entryPhysical
+                        = (gctUINT8_PTR) contextBuffer->physical
+                        + Context->entryOffsetXDFrom3D;
+
+                    entryLogical
+                        = (gctUINT8_PTR) contextBuffer->logical
+                        + Context->entryOffsetXDFrom3D;
+
+                    entryBytes
+                        = Context->bufferSize
+                        - Context->entryOffsetXDFrom3D;
+                }
+                else
+                {
+                    entryPhysical
+                        = (gctUINT8_PTR) contextBuffer->physical
+                        + Context->entryOffsetXDFrom2D;
+
+                    entryLogical
+                        = (gctUINT8_PTR) contextBuffer->logical
+                        + Context->entryOffsetXDFrom2D;
+
+                    entryBytes
+                        = Context->totalSize
+                        - Context->entryOffsetXDFrom2D;
+                }
+
+                /* See if we have to switch pipes between the context
+                   and command buffers. */
+                if (commandBufferObject->entryPipe == gcvPIPE_3D)
+                {
+                    /* Skip pipe switching sequence. */
+                    offset = pipeBytes;
+                }
+                else
+                {
+                    /* The current hardware and the initial context pipes are
+                       different, switch to the correct pipe. */
+                    gcmkONERROR(gckHARDWARE_PipeSelect(
+                        Command->kernel->hardware,
+                        commandBufferLogical,
+                        commandBufferObject->entryPipe,
+                        &pipeBytes
+                        ));
+
+                    /* Do not skip pipe switching sequence. */
+                    offset = 0;
+                }
+
+                /* Generate a LINK from the context buffer to
+                   the command buffer. */
+                gcmkONERROR(gckHARDWARE_Link(
+                    hardware,
+                    contextBuffer->link3D,
+                    commandBufferLogical + offset,
+                    commandBufferSize    - offset,
+                    &linkBytes
+                    ));
+            }
+        }
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+        /* Flush the context buffer cache. */
+        gcmkONERROR(gckOS_CacheClean(
+            Command->os,
+            Command->kernelProcessID,
+            gcvNULL,
+            entryPhysical,
+            entryLogical,
+            entryBytes
+            ));
+#endif
+
+        /* Update the current context. */
+        Command->currContext = Context;
+
+#if gcdDUMP_COMMAND
+        contextDumpLogical = entryLogical;
+        contextDumpBytes   = entryBytes;
+#endif
+    }
+
+    /* Same context. */
+    else
+    {
+        /* Determine context entry and exit points. */
+        if (commandBufferObject->using2D && Context->dirty2D)
+        {
+            /* Reset 2D dirty flag. */
+            Context->dirty2D = gcvFALSE;
+
+            /* Get the "dirty" context buffer. */
+            contextBuffer = Context->dirtyBuffer;
+
+            if (commandBufferObject->using3D && Context->dirty3D)
+            {
+                /* Reset 3D dirty flag. */
+                Context->dirty3D = gcvFALSE;
+
+                /* Compute the entry. */
+                if (Command->pipeSelect == gcvPIPE_2D)
+                {
+                    entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
+                    entryLogical  = (gctUINT8_PTR) contextBuffer->logical  + pipeBytes;
+                    entryBytes    =                Context->bufferSize     - pipeBytes;
+                }
+                else
+                {
+                    entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
+                    entryLogical  = (gctUINT8_PTR) contextBuffer->logical;
+                    entryBytes    =                Context->bufferSize;
+                }
+
+                /* See if we have to switch pipes between the context
+                   and command buffers. */
+                if (commandBufferObject->entryPipe == gcvPIPE_3D)
+                {
+                    /* Skip pipe switching sequence. */
+                    offset = pipeBytes;
+                }
+                else
+                {
+                    /* The current hardware and the initial context pipes are
+                       different, switch to the correct pipe. */
+                    gcmkONERROR(gckHARDWARE_PipeSelect(
+                        Command->kernel->hardware,
+                        commandBufferLogical,
+                        commandBufferObject->entryPipe,
+                        &pipeBytes
+                        ));
+
+                    /* Do not skip pipe switching sequence. */
+                    offset = 0;
+                }
+
+                /* Ensure the NOP between 2D and 3D is in place so that the
+                   execution falls through from 2D to 3D. */
+                gcmkONERROR(gckHARDWARE_Nop(
+                    hardware,
+                    contextBuffer->link2D,
+                    &nopBytes
+                    ));
+
+                /* Generate a LINK from the context buffer to
+                   the command buffer. */
+                gcmkONERROR(gckHARDWARE_Link(
+                    hardware,
+                    contextBuffer->link3D,
+                    commandBufferLogical + offset,
+                    commandBufferSize    - offset,
+                    &linkBytes
+                    ));
+            }
+            else
+            {
+                /* Compute the entry. */
+                if (Command->pipeSelect == gcvPIPE_2D)
+                {
+                    entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
+                    entryLogical  = (gctUINT8_PTR) contextBuffer->logical  + pipeBytes;
+                    entryBytes    =                Context->entryOffset3D  - pipeBytes;
+                }
+                else
+                {
+                    entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
+                    entryLogical  = (gctUINT8_PTR) contextBuffer->logical;
+                    entryBytes    =                Context->entryOffset3D;
+                }
+
+                /* See if we have to switch pipes between the context
+                   and command buffers. */
+                if (commandBufferObject->entryPipe == gcvPIPE_2D)
+                {
+                    /* Skip pipe switching sequence. */
+                    offset = pipeBytes;
+                }
+                else
+                {
+                    /* The current hardware and the initial context pipes are
+                       different, switch to the correct pipe. */
+                    gcmkONERROR(gckHARDWARE_PipeSelect(
+                        Command->kernel->hardware,
+                        commandBufferLogical,
+                        commandBufferObject->entryPipe,
+                        &pipeBytes
+                        ));
+
+                    /* Do not skip pipe switching sequence. */
+                    offset = 0;
+                }
+
+                /* 3D is not used, generate a LINK from the end of 2D part of
+                   the context buffer to the command buffer. */
+                gcmkONERROR(gckHARDWARE_Link(
+                    hardware,
+                    contextBuffer->link2D,
+                    commandBufferLogical + offset,
+                    commandBufferSize    - offset,
+                    &linkBytes
+                    ));
+            }
+        }
+        else
+        {
+            if (commandBufferObject->using3D && Context->dirty3D)
+            {
+                /* Reset 3D dirty flag. */
+                Context->dirty3D = gcvFALSE;
+
+                /* Get the "dirty" context buffer. */
+                contextBuffer = Context->dirtyBuffer;
+
+                /* Determine context buffer entry offset. */
+                offset = (Command->pipeSelect == gcvPIPE_3D)
+
+                    /* Skip pipe switching sequence. */
+                    ? Context->entryOffset3D + pipeBytes
+
+                    /* Do not skip pipe switching sequence. */
+                    : Context->entryOffset3D;
+
+                /* Compute the entry. */
+                entryPhysical = (gctUINT8_PTR) contextBuffer->physical + offset;
+                entryLogical  = (gctUINT8_PTR) contextBuffer->logical  + offset;
+                entryBytes    =                Context->bufferSize     - offset;
+
+                /* See if we have to switch pipes between the context
+                   and command buffers. */
+                if (commandBufferObject->entryPipe == gcvPIPE_3D)
+                {
+                    /* Skip pipe switching sequence. */
+                    offset = pipeBytes;
+                }
+                else
+                {
+                    /* The current hardware and the initial context pipes are
+                       different, switch to the correct pipe. */
+                    gcmkONERROR(gckHARDWARE_PipeSelect(
+                        Command->kernel->hardware,
+                        commandBufferLogical,
+                        commandBufferObject->entryPipe,
+                        &pipeBytes
+                        ));
+
+                    /* Do not skip pipe switching sequence. */
+                    offset = 0;
+                }
+
+                /* Generate a LINK from the context buffer to
+                   the command buffer. */
+                gcmkONERROR(gckHARDWARE_Link(
+                    hardware,
+                    contextBuffer->link3D,
+                    commandBufferLogical + offset,
+                    commandBufferSize    - offset,
+                    &linkBytes
+                    ));
+            }
+            else
+            {
+                /* See if we have to switch pipes for the command buffer. */
+                if (commandBufferObject->entryPipe == Command->pipeSelect)
+                {
+                    /* Skip pipe switching sequence. */
+                    offset = pipeBytes;
+                }
+                else
+                {
+                    /* The current hardware and the entry command buffer pipes
+                    ** are different, switch to the correct pipe. */
+                    gcmkONERROR(gckHARDWARE_PipeSelect(
+                        Command->kernel->hardware,
+                        commandBufferLogical,
+                        commandBufferObject->entryPipe,
+                        &pipeBytes
+                        ));
+
+                    /* Do not skip pipe switching sequence. */
+                    offset = 0;
+                }
+
+                /* Compute the entry. */
+                entryPhysical = (gctUINT8_PTR) commandBufferPhysical + offset;
+                entryLogical  =                commandBufferLogical  + offset;
+                entryBytes    =                commandBufferSize     - offset;
+            }
+        }
+    }
+
+#if gcdDUMP_COMMAND
+    bufferDumpLogical = commandBufferLogical + offset;
+    bufferDumpBytes   = commandBufferSize    - offset;
+#endif
+
+#if gcdSECURE_USER
+    /* Process user hints. */
+    gcmkONERROR(_ProcessHints(Command, ProcessID, commandBufferObject));
+#endif
+
+    /* Get the current offset. */
+    offset = Command->offset;
+
+    /* Compute number of bytes left in current kernel command queue. */
+    bytes = Command->pageSize - offset;
+
+    /* Query the size of WAIT/LINK command sequence. */
+    gcmkONERROR(gckHARDWARE_WaitLink(
+        hardware,
+        gcvNULL,
+        offset,
+        &waitLinkBytes,
+        gcvNULL,
+        gcvNULL
+        ));
+
+    /* Is there enough space in the current command queue? */
+    if (bytes < waitLinkBytes)
+    {
+        /* No, create a new one. */
+        gcmkONERROR(_NewQueue(Command));
+
+        /* Get the new current offset. */
+        offset = Command->offset;
+
+        /* Recompute the number of bytes in the new kernel command queue. */
+        bytes = Command->pageSize - offset;
+        gcmkASSERT(bytes >= waitLinkBytes);
+    }
+
+    /* Compute the location if WAIT/LINK command sequence. */
+    waitLinkPhysical = (gctUINT8_PTR) Command->physical + offset;
+    waitLinkLogical  = (gctUINT8_PTR) Command->logical  + offset;
+
+    /* Determine the location to jump to for the command buffer being
+    ** scheduled. */
+    if (Command->newQueue)
+    {
+        /* New command queue, jump to the beginning of it. */
+        exitPhysical = Command->physical;
+        exitLogical  = Command->logical;
+        exitBytes    = Command->offset + waitLinkBytes;
+    }
+    else
+    {
+        /* Still within the preexisting command queue, jump to the new
+           WAIT/LINK command sequence. */
+        exitPhysical = waitLinkPhysical;
+        exitLogical  = waitLinkLogical;
+        exitBytes    = waitLinkBytes;
+    }
+
+    /* Add a new WAIT/LINK command sequence. When the command buffer which is
+       currently being scheduled is fully executed by the GPU, the FE will
+       jump to this WAIT/LINK sequence. */
+    gcmkONERROR(gckHARDWARE_WaitLink(
+        hardware,
+        waitLinkLogical,
+        offset,
+        &waitLinkBytes,
+        &waitOffset,
+        &waitSize
+        ));
+
+    /* Compute the location if WAIT command. */
+    waitPhysical = (gctUINT8_PTR) waitLinkPhysical + waitOffset;
+    waitLogical  = (gctUINT8_PTR) waitLinkLogical  + waitOffset;
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+    /* Flush the command queue cache. */
+    gcmkONERROR(gckOS_CacheClean(
+        Command->os,
+        Command->kernelProcessID,
+        gcvNULL,
+        exitPhysical,
+        exitLogical,
+        exitBytes
+        ));
+#endif
+
+    /* Determine the location of the LINK command in the command buffer. */
+    commandBufferLink
+        = (gctUINT8_PTR) commandBufferObject->logical
+        +                commandBufferObject->offset;
+
+    /* Generate a LINK from the end of the command buffer being scheduled
+       back to the kernel command queue. */
+    gcmkONERROR(gckHARDWARE_Link(
+        hardware,
+        commandBufferLink,
+        exitLogical,
+        exitBytes,
+        &linkBytes
+        ));
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+    /* Flush the command buffer cache. */
+    gcmkONERROR(gckOS_CacheClean(
+        Command->os,
+        ProcessID,
+        gcvNULL,
+        commandBufferPhysical,
+        commandBufferLogical,
+        commandBufferSize
+        ));
+#endif
+
+    /* Generate a LINK from the previous WAIT/LINK command sequence to the
+       entry determined above (either the context or the command buffer).
+       This LINK replaces the WAIT instruction from the previous WAIT/LINK
+       pair, therefore we use WAIT metrics for generation of this LINK.
+       This action will execute the entire sequence. */
+    gcmkONERROR(gckHARDWARE_Link(
+        hardware,
+        Command->waitLogical,
+        entryLogical,
+        entryBytes,
+        &Command->waitSize
+        ));
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+    /* Flush the cache for the link. */
+    gcmkONERROR(gckOS_CacheClean(
+        Command->os,
+        Command->kernelProcessID,
+        gcvNULL,
+        Command->waitPhysical,
+        Command->waitLogical,
+        Command->waitSize
+        ));
+#endif
+
+    gcmkDUMPCOMMAND(
+        Command->os,
+        Command->waitLogical,
+        Command->waitSize,
+        gceDUMP_BUFFER_LINK,
+        gcvFALSE
+        );
+
+    gcmkDUMPCOMMAND(
+        Command->os,
+        contextDumpLogical,
+        contextDumpBytes,
+        gceDUMP_BUFFER_CONTEXT,
+        gcvFALSE
+        );
+
+    gcmkDUMPCOMMAND(
+        Command->os,
+        bufferDumpLogical,
+        bufferDumpBytes,
+        gceDUMP_BUFFER_USER,
+        gcvFALSE
+        );
+
+    gcmkDUMPCOMMAND(
+        Command->os,
+        waitLinkLogical,
+        waitLinkBytes,
+        gceDUMP_BUFFER_WAITLINK,
+        gcvFALSE
+        );
+
+    /* Update the current pipe. */
+    Command->pipeSelect = commandBufferObject->exitPipe;
+
+    /* Update command queue offset. */
+    Command->offset  += waitLinkBytes;
+    Command->newQueue = gcvFALSE;
+
+    /* Update address of last WAIT. */
+    Command->waitPhysical = waitPhysical;
+    Command->waitLogical  = waitLogical;
+    Command->waitSize     = waitSize;
+
+    /* Update queue tail pointer. */
+    gcmkONERROR(gckHARDWARE_UpdateQueueTail(
+        hardware, Command->logical, Command->offset
+        ));
+
+#if gcdDUMP_COMMAND && !gcdSIMPLE_COMMAND_DUMP
+    gcmkPRINT("@[kernel.commit]");
+#endif
+
+    /* Release the context switching mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+    contextAcquired = gcvFALSE;
+
+    /* Release the command queue. */
+    gcmkONERROR(gckCOMMAND_ExitCommit(Command, gcvFALSE));
+    commitEntered = gcvFALSE;
+
+    /* Loop while there are records in the queue. */
+    while (EventQueue != gcvNULL)
+    {
+        if (needCopy)
+        {
+            /* Point to stack record. */
+            eventRecord = &_eventRecord;
+
+            /* Copy the data from the client. */
+            gcmkONERROR(gckOS_CopyFromUserData(
+                Command->os, eventRecord, EventQueue, gcmSIZEOF(gcsQUEUE)
+                ));
+        }
+        else
+        {
+            /* Map record into kernel memory. */
+            gcmkONERROR(gckOS_MapUserPointer(Command->os,
+                                             EventQueue,
+                                             gcmSIZEOF(gcsQUEUE),
+                                             &pointer));
+
+            eventRecord = pointer;
+        }
+
+        /* Append event record to event queue. */
+        gcmkONERROR(gckEVENT_AddList(
+            Command->kernel->eventObj, &eventRecord->iface, gcvKERNEL_PIXEL, gcvTRUE
+            ));
+
+        /* Next record in the queue. */
+        nextEventRecord = eventRecord->next;
+
+        if (!needCopy)
+        {
+            /* Unmap record from kernel memory. */
+            gcmkONERROR(gckOS_UnmapUserPointer(
+                Command->os, EventQueue, gcmSIZEOF(gcsQUEUE), (gctPOINTER *) eventRecord
+                ));
+
+            eventRecord = gcvNULL;
+        }
+
+        EventQueue = nextEventRecord;
+    }
+
+    /* Submit events. */
+    gcmkONERROR(gckEVENT_Submit(Command->kernel->eventObj, gcvTRUE, gcvFALSE));
+
+    /* Unmap the command buffer pointer. */
+    if (commandBufferMapped)
+    {
+        gcmkONERROR(gckOS_UnmapUserPointer(
+            Command->os,
+            CommandBuffer,
+            gcmSIZEOF(struct _gcoCMDBUF),
+            commandBufferObject
+            ));
+
+        commandBufferMapped = gcvFALSE;
+    }
+
+    /* Return status. */
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
+    if ((eventRecord != gcvNULL) && !needCopy)
+    {
+        /* Roll back. */
+        gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+            Command->os,
+            EventQueue,
+            gcmSIZEOF(gcsQUEUE),
+            (gctPOINTER *) eventRecord
+            ));
+    }
+
+    if (contextAcquired)
+    {
+        /* Release the context switching mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+    }
+
+    if (commitEntered)
+    {
+        /* Release the command queue mutex. */
+        gcmkVERIFY_OK(gckCOMMAND_ExitCommit(Command, gcvFALSE));
+    }
+
+    /* Unmap the command buffer pointer. */
+    if (commandBufferMapped)
+    {
+        gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+            Command->os,
+            CommandBuffer,
+            gcmSIZEOF(struct _gcoCMDBUF),
+            commandBufferObject
+            ));
+    }
+
+    /* Return status. */
+    gcmkFOOTER();
+    return status;
+#endif
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_Reserve
+**
+**  Reserve space in the command queue.  Also acquire the command queue mutex.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to an gckCOMMAND object.
+**
+**      gctSIZE_T RequestedBytes
+**          Number of bytes previously reserved.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Buffer
+**          Pointer to a variable that will receive the address of the reserved
+**          space.
+**
+**      gctSIZE_T * BufferSize
+**          Pointer to a variable that will receive the number of bytes
+**          available in the command queue.
+*/
+gceSTATUS
+gckCOMMAND_Reserve(
+    IN gckCOMMAND Command,
+    IN gctSIZE_T RequestedBytes,
+    OUT gctPOINTER * Buffer,
+    OUT gctSIZE_T * BufferSize
+    )
+{
+    gceSTATUS status;
+    gctSIZE_T bytes;
+    gctSIZE_T requiredBytes;
+    gctUINT32 requestedAligned;
+
+    gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    /* Compute aligned number of reuested bytes. */
+    requestedAligned = gcmALIGN(RequestedBytes, Command->alignment);
+
+    /* Another WAIT/LINK command sequence will have to be appended after
+       the requested area being reserved. Compute the number of bytes
+       required for WAIT/LINK at the location after the reserved area. */
+    gcmkONERROR(gckHARDWARE_WaitLink(
+        Command->kernel->hardware,
+        gcvNULL,
+        Command->offset + requestedAligned,
+        &requiredBytes,
+        gcvNULL,
+        gcvNULL
+        ));
+
+    /* Compute total number of bytes required. */
+    requiredBytes += requestedAligned;
+
+    /* Compute number of bytes available in command queue. */
+    bytes = Command->pageSize - Command->offset;
+
+    /* Is there enough space in the current command queue? */
+    if (bytes < requiredBytes)
+    {
+        /* Create a new command queue. */
+        gcmkONERROR(_NewQueue(Command));
+
+        /* Recompute the number of bytes in the new kernel command queue. */
+        bytes = Command->pageSize - Command->offset;
+
+        /* Still not enough space? */
+        if (bytes < requiredBytes)
+        {
+            /* Rare case, not enough room in command queue. */
+            gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+        }
+    }
+
+    /* Return pointer to empty slot command queue. */
+    *Buffer = (gctUINT8 *) Command->logical + Command->offset;
+
+    /* Return number of bytes left in command queue. */
+    *BufferSize = bytes;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Buffer=0x%x *BufferSize=%lu", *Buffer, *BufferSize);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_Execute
+**
+**  Execute a previously reserved command queue by appending a WAIT/LINK command
+**  sequence after it and modifying the last WAIT into a LINK command.  The
+**  command FIFO mutex will be released whether this function succeeds or not.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to an gckCOMMAND object.
+**
+**      gctSIZE_T RequestedBytes
+**          Number of bytes previously reserved.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Execute(
+    IN gckCOMMAND Command,
+    IN gctSIZE_T RequestedBytes
+    )
+{
+    gceSTATUS status;
+
+    gctPHYS_ADDR waitLinkPhysical;
+    gctUINT8_PTR waitLinkLogical;
+    gctUINT32 waitLinkOffset;
+    gctSIZE_T waitLinkBytes;
+
+    gctPHYS_ADDR waitPhysical;
+    gctPOINTER waitLogical;
+    gctUINT32 waitOffset;
+    gctSIZE_T waitBytes;
+
+    gctPHYS_ADDR execPhysical;
+    gctPOINTER execLogical;
+    gctSIZE_T execBytes;
+
+    gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    /* Compute offset for WAIT/LINK. */
+    waitLinkOffset = Command->offset + RequestedBytes;
+
+    /* Compute number of bytes left in command queue. */
+    waitLinkBytes = Command->pageSize - waitLinkOffset;
+
+    /* Compute the location if WAIT/LINK command sequence. */
+    waitLinkPhysical = (gctUINT8_PTR) Command->physical + waitLinkOffset;
+    waitLinkLogical  = (gctUINT8_PTR) Command->logical  + waitLinkOffset;
+
+    /* Append WAIT/LINK in command queue. */
+    gcmkONERROR(gckHARDWARE_WaitLink(
+        Command->kernel->hardware,
+        waitLinkLogical,
+        waitLinkOffset,
+        &waitLinkBytes,
+        &waitOffset,
+        &waitBytes
+        ));
+
+    /* Compute the location if WAIT command. */
+    waitPhysical = (gctUINT8_PTR) waitLinkPhysical + waitOffset;
+    waitLogical  =                waitLinkLogical  + waitOffset;
+
+    /* Determine the location to jump to for the command buffer being
+    ** scheduled. */
+    if (Command->newQueue)
+    {
+        /* New command queue, jump to the beginning of it. */
+        execPhysical = Command->physical;
+        execLogical  = Command->logical;
+        execBytes    = waitLinkOffset + waitLinkBytes;
+    }
+    else
+    {
+        /* Still within the preexisting command queue, jump directly to the
+           reserved area. */
+        execPhysical = (gctUINT8 *) Command->physical + Command->offset;
+        execLogical  = (gctUINT8 *) Command->logical  + Command->offset;
+        execBytes    = RequestedBytes + waitLinkBytes;
+    }
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+    /* Flush the cache. */
+    gcmkONERROR(gckOS_CacheClean(
+        Command->os,
+        Command->kernelProcessID,
+        gcvNULL,
+        execPhysical,
+        execLogical,
+        execBytes
+        ));
+#endif
+
+    /* Convert the last WAIT into a LINK. */
+    gcmkONERROR(gckHARDWARE_Link(
+        Command->kernel->hardware,
+        Command->waitLogical,
+        execLogical,
+        execBytes,
+        &Command->waitSize
+        ));
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+    /* Flush the cache. */
+    gcmkONERROR(gckOS_CacheClean(
+        Command->os,
+        Command->kernelProcessID,
+        gcvNULL,
+        Command->waitPhysical,
+        Command->waitLogical,
+        Command->waitSize
+        ));
+#endif
+
+    gcmkDUMPCOMMAND(
+        Command->os,
+        Command->waitLogical,
+        Command->waitSize,
+        gceDUMP_BUFFER_LINK,
+        gcvFALSE
+        );
+
+    gcmkDUMPCOMMAND(
+        Command->os,
+        execLogical,
+        execBytes,
+        gceDUMP_BUFFER_KERNEL,
+        gcvFALSE
+        );
+
+    /* Update the pointer to the last WAIT. */
+    Command->waitPhysical = waitPhysical;
+    Command->waitLogical  = waitLogical;
+    Command->waitSize     = waitBytes;
+
+    /* Update the command queue. */
+    Command->offset  += RequestedBytes + waitLinkBytes;
+    Command->newQueue = gcvFALSE;
+
+    /* Update queue tail pointer. */
+    gcmkONERROR(gckHARDWARE_UpdateQueueTail(
+        Command->kernel->hardware, Command->logical, Command->offset
+        ));
+
+#if gcdDUMP_COMMAND && !gcdSIMPLE_COMMAND_DUMP
+    gcmkPRINT("@[kernel.execute]");
+#endif
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_Stall
+**
+**  The calling thread will be suspended until the command queue has been
+**  completed.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to an gckCOMMAND object.
+**
+**      gctBOOL FromPower
+**          Determines whether the call originates from inside the power
+**          management or not.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Stall(
+    IN gckCOMMAND Command,
+    IN gctBOOL FromPower
+    )
+{
+#if gcdNULL_DRIVER
+    /* Do nothing with infinite hardware. */
+    return gcvSTATUS_OK;
+#else
+    gckOS os;
+    gckHARDWARE hardware;
+    gckEVENT eventObject;
+    gceSTATUS status;
+    gctSIGNAL signal = gcvNULL;
+    gctUINT timer = 0;
+
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    /* Extract the gckOS object pointer. */
+    os = Command->os;
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+    /* Extract the gckHARDWARE object pointer. */
+    hardware = Command->kernel->hardware;
+    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+    /* Extract the gckEVENT object pointer. */
+    eventObject = Command->kernel->eventObj;
+    gcmkVERIFY_OBJECT(eventObject, gcvOBJ_EVENT);
+
+    /* Allocate the signal. */
+    gcmkONERROR(gckOS_CreateSignal(os, gcvTRUE, &signal));
+
+    /* Append the EVENT command to trigger the signal. */
+    gcmkONERROR(gckEVENT_Signal(eventObject, signal, gcvKERNEL_PIXEL));
+
+    /* Submit the event queue. */
+    gcmkONERROR(gckEVENT_Submit(eventObject, gcvTRUE, FromPower));
+
+#if gcdDUMP_COMMAND && !gcdSIMPLE_COMMAND_DUMP
+    gcmkPRINT("@[kernel.stall]");
+#endif
+
+    if (status == gcvSTATUS_CHIP_NOT_READY)
+    {
+        /* Error. */
+        goto OnError;
+    }
+
+    do
+    {
+        /* Wait for the signal. */
+        status = gckOS_WaitSignal(os, signal, gcdGPU_ADVANCETIMER);
+
+        if (status == gcvSTATUS_TIMEOUT)
+        {
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+            gctUINT32 idle;
+
+            /* Read idle register. */
+            gcmkVERIFY_OK(gckHARDWARE_GetIdle(
+                hardware, gcvFALSE, &idle
+                ));
+
+            gcmkTRACE(
+                gcvLEVEL_ERROR,
+                "%s(%d): idle=%08x",
+                __FUNCTION__, __LINE__, idle
+                );
+
+            gcmkONERROR(gckOS_MemoryBarrier(os, gcvNULL));
+
+#ifdef __QNXNTO__
+            gctUINT32 reg_cmdbuf_fetch;
+            gctUINT32 reg_intr;
+
+            gcmkVERIFY_OK(gckOS_ReadRegisterEx(
+                Command->kernel->hardware->os, Command->kernel->core, 0x0664, &reg_cmdbuf_fetch
+                ));
+
+            if (idle == 0x7FFFFFFE)
+            {
+                /*
+                 * GPU is idle so there should not be pending interrupts.
+                 * Just double check.
+                 *
+                 * Note that reading interrupt register clears it.
+                 * That's why we don't read it in all cases.
+                 */
+                gcmkVERIFY_OK(gckOS_ReadRegisterEx(
+                    Command->kernel->hardware->os, Command->kernel->core, 0x10, &reg_intr
+                    ));
+
+                slogf(
+                    _SLOG_SETCODE(1, 0),
+                    _SLOG_CRITICAL,
+                    "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X, interrupt = 0x%X)",
+                    idle, reg_cmdbuf_fetch, reg_intr
+                    );
+            }
+            else
+            {
+                slogf(
+                    _SLOG_SETCODE(1, 0),
+                    _SLOG_CRITICAL,
+                    "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X)",
+                    idle, reg_cmdbuf_fetch
+                    );
+            }
+#endif
+#endif
+            /* Advance timer. */
+            timer += gcdGPU_ADVANCETIMER;
+        }
+    }
+    while (gcmIS_ERROR(status)
+#if gcdGPU_TIMEOUT
+           && (timer < Command->kernel->timeOut)
+#endif
+           );
+
+    /* Bail out on timeout. */
+    if (gcmIS_ERROR(status))
+    {
+        /* Broadcast the stuck GPU. */
+        gcmkONERROR(gckOS_Broadcast(
+            os, hardware, gcvBROADCAST_GPU_STUCK
+            ));
+
+        gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
+    }
+
+    /* Delete the signal. */
+    gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (signal != gcvNULL)
+    {
+        /* Free the signal. */
+        gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+#endif
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_Attach
+**
+**  Attach user process.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to a gckCOMMAND object.
+**
+**      gctUINT32 ProcessID
+**          Current process ID.
+**
+**  OUTPUT:
+**
+**      gckCONTEXT * Context
+**          Pointer to a variable that will receive a pointer to a new
+**          gckCONTEXT object.
+**
+**      gctSIZE_T * StateCount
+**          Pointer to a variable that will receive the number of states
+**          in the context buffer.
+*/
+gceSTATUS
+gckCOMMAND_Attach(
+    IN gckCOMMAND Command,
+    OUT gckCONTEXT * Context,
+    OUT gctSIZE_T * StateCount,
+    IN gctUINT32 ProcessID
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    /* Acquire the context switching mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(
+        Command->os, Command->mutexContext, gcvINFINITE
+        ));
+    acquired = gcvTRUE;
+
+    /* Construct a gckCONTEXT object. */
+    gcmkONERROR(gckCONTEXT_Construct(
+        Command->os,
+        Command->kernel->hardware,
+        ProcessID,
+        Context
+        ));
+
+    /* Return the number of states in the context. */
+    * StateCount = (* Context)->stateCount;
+
+    /* Release the context switching mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+    acquired = gcvFALSE;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Context=0x%x", *Context);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Release mutex. */
+    if (acquired)
+    {
+        /* Release the context switching mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+        acquired = gcvFALSE;
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_Detach
+**
+**  Detach user process.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to a gckCOMMAND object.
+**
+**      gckCONTEXT Context
+**          Pointer to a gckCONTEXT object to be destroyed.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Detach(
+    IN gckCOMMAND Command,
+    IN gckCONTEXT Context
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Command=0x%x Context=0x%x", Command, Context);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    /* Acquire the context switching mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(
+        Command->os, Command->mutexContext, gcvINFINITE
+        ));
+    acquired = gcvTRUE;
+
+    /* Construct a gckCONTEXT object. */
+    gcmkONERROR(gckCONTEXT_Destroy(Context));
+
+    /* Release the context switching mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+    acquired = gcvFALSE;
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Release mutex. */
+    if (acquired)
+    {
+        /* Release the context switching mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+        acquired = gcvFALSE;
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
new file mode 100644 (file)
index 0000000..68b2d60
--- /dev/null
@@ -0,0 +1,3479 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdENABLE_VG
+
+#include "gc_hal_kernel_hardware_command_vg.h"
+
+#define _GC_OBJ_ZONE            gcvZONE_COMMAND
+
+/******************************************************************************\
+*********************************** Debugging **********************************
+\******************************************************************************/
+
+#define gcvDISABLE_TIMEOUT      1
+#define gcvDUMP_COMMAND_BUFFER  0
+#define gcvDUMP_COMMAND_LINES   0
+
+
+#if gcvDEBUG || defined(EMULATOR) || gcvDISABLE_TIMEOUT
+#   define gcvQUEUE_TIMEOUT ~0
+#else
+#   define gcvQUEUE_TIMEOUT 10
+#endif
+
+
+/******************************************************************************\
+********************************** Definitions *********************************
+\******************************************************************************/
+
+/* Minimum buffer size. */
+#define gcvMINUMUM_BUFFER \
+    gcmSIZEOF(gcsKERNEL_QUEUE_HEADER) + \
+    gcmSIZEOF(gcsKERNEL_CMDQUEUE) * 2
+
+#define gcmDECLARE_INTERRUPT_HANDLER(Block, Number) \
+    static gceSTATUS \
+    _EventHandler_##Block##_##Number( \
+        IN gckVGKERNEL Kernel \
+        )
+
+#define gcmDEFINE_INTERRUPT_HANDLER(Block, Number) \
+    gcmDECLARE_INTERRUPT_HANDLER(Block, Number) \
+    { \
+        return _EventHandler_Block( \
+            Kernel, \
+            &Kernel->command->taskTable[gcvBLOCK_##Block], \
+            gcvFALSE \
+            ); \
+    }
+
+#define gcmDEFINE_INTERRUPT_HANDLER_ENTRY(Block, Number) \
+    { gcvBLOCK_##Block, _EventHandler_##Block##_##Number }
+
+/* Block interrupt handling table entry. */
+typedef struct _gcsBLOCK_INTERRUPT_HANDLER * gcsBLOCK_INTERRUPT_HANDLER_PTR;
+typedef struct _gcsBLOCK_INTERRUPT_HANDLER
+{
+    gceBLOCK                block;
+    gctINTERRUPT_HANDLER    handler;
+}
+gcsBLOCK_INTERRUPT_HANDLER;
+
+/* Queue control functions. */
+typedef struct _gcsQUEUE_UPDATE_CONTROL * gcsQUEUE_UPDATE_CONTROL_PTR;
+typedef struct _gcsQUEUE_UPDATE_CONTROL
+{
+    gctOBJECT_HANDLER       execute;
+    gctOBJECT_HANDLER       update;
+    gctOBJECT_HANDLER       lastExecute;
+    gctOBJECT_HANDLER       lastUpdate;
+}
+gcsQUEUE_UPDATE_CONTROL;
+
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+static gceSTATUS
+_WaitForIdle(
+    IN gckVGCOMMAND Command,
+    IN gcsKERNEL_QUEUE_HEADER_PTR Queue
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+    gctUINT32 idle;
+    gctUINT timeout = 0;
+
+    /* Loop while not idle. */
+    while (Queue->pending)
+    {
+        /* Did we reach the timeout limit? */
+        if (timeout == gcvQUEUE_TIMEOUT)
+        {
+            /* Hardware is probably dead... */
+            return gcvSTATUS_TIMEOUT;
+        }
+
+        /* Sleep for 100ms. */
+        gcmkERR_BREAK(gckOS_Delay(Command->os, 100));
+
+        /* Not the first loop? */
+        if (timeout > 0)
+        {
+            /* Read IDLE register. */
+            gcmkVERIFY_OK(gckVGHARDWARE_GetIdle(Command->hardware, &idle));
+
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_COMMAND,
+                "%s: timeout, IDLE=%08X\n",
+                __FUNCTION__, idle
+                );
+        }
+
+        /* Increment the timeout counter. */
+        timeout += 1;
+    }
+
+    /* Return status. */
+    return status;
+}
+
+static gctINT32
+_GetNextInterrupt(
+    IN gckVGCOMMAND Command,
+    IN gceBLOCK Block
+    )
+{
+    gctUINT index;
+    gcsBLOCK_TASK_ENTRY_PTR entry;
+    gctINT32 interrupt;
+
+    /* Get the block entry. */
+    entry = &Command->taskTable[Block];
+
+    /* Make sure we have initialized interrupts. */
+    gcmkASSERT(entry->interruptCount > 0);
+
+    /* Decrement the interrupt usage semaphore. */
+    gcmkVERIFY_OK(gckOS_DecrementSemaphore(
+        Command->os, entry->interruptSemaphore
+        ));
+
+    /* Get the value index. */
+    index = entry->interruptIndex;
+
+    /* Get the interrupt value. */
+    interrupt = entry->interruptArray[index];
+
+    /* Must be a valid value. */
+    gcmkASSERT((interrupt >= 0) && (interrupt <= 31));
+
+    /* Advance the index to the next value. */
+    index += 1;
+
+    /* Set the new index. */
+    entry->interruptIndex = (index == entry->interruptCount)
+        ? 0
+        : index;
+
+    /* Return interrupt value. */
+    return interrupt;
+}
+
+
+/******************************************************************************\
+***************************** Task Storage Management **************************
+\******************************************************************************/
+
+/* Minimum task buffer size. */
+#define gcvMIN_TASK_BUFFER \
+( \
+    gcmSIZEOF(gcsTASK_CONTAINER) + 128 \
+)
+
+/* Free list terminator. */
+#define gcvFREE_TASK_TERMINATOR \
+( \
+    (gcsTASK_CONTAINER_PTR) gcmINT2PTR(~0) \
+)
+
+
+/*----------------------------------------------------------------------------*/
+/*------------------- Allocated Task Buffer List Management ------------------*/
+
+static void
+_InsertTaskBuffer(
+    IN gcsTASK_CONTAINER_PTR AddAfter,
+    IN gcsTASK_CONTAINER_PTR Buffer
+    )
+{
+    gcsTASK_CONTAINER_PTR addBefore;
+
+    /* Cannot add before the first buffer. */
+    gcmkASSERT(AddAfter != gcvNULL);
+
+    /* Create a shortcut to the next buffer. */
+    addBefore = AddAfter->allocNext;
+
+    /* Initialize the links. */
+    Buffer->allocPrev = AddAfter;
+    Buffer->allocNext = addBefore;
+
+    /* Link to the previous buffer. */
+    AddAfter->allocNext = Buffer;
+
+    /* Link to the next buffer. */
+    if (addBefore != gcvNULL)
+    {
+        addBefore->allocPrev = Buffer;
+    }
+}
+
+static void
+_RemoveTaskBuffer(
+    IN gcsTASK_CONTAINER_PTR Buffer
+    )
+{
+    gcsTASK_CONTAINER_PTR prev;
+    gcsTASK_CONTAINER_PTR next;
+
+    /* Cannot remove the first buffer. */
+    gcmkASSERT(Buffer->allocPrev != gcvNULL);
+
+    /* Create shortcuts to the previous and next buffers. */
+    prev = Buffer->allocPrev;
+    next = Buffer->allocNext;
+
+    /* Tail buffer? */
+    if (next == gcvNULL)
+    {
+        /* Remove from the list. */
+        prev->allocNext = gcvNULL;
+    }
+
+    /* Buffer from the middle. */
+    else
+    {
+        prev->allocNext = next;
+        next->allocPrev = prev;
+    }
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*--------------------- Free Task Buffer List Management ---------------------*/
+
+static void
+_AppendToFreeList(
+    IN gckVGCOMMAND Command,
+    IN gcsTASK_CONTAINER_PTR Buffer
+    )
+{
+    /* Cannot be a part of the free list already. */
+    gcmkASSERT(Buffer->freePrev == gcvNULL);
+    gcmkASSERT(Buffer->freeNext == gcvNULL);
+
+    /* First buffer to add? */
+    if (Command->taskFreeHead == gcvNULL)
+    {
+        /* Terminate the links. */
+        Buffer->freePrev = gcvFREE_TASK_TERMINATOR;
+        Buffer->freeNext = gcvFREE_TASK_TERMINATOR;
+
+        /* Initialize the list pointer. */
+        Command->taskFreeHead = Command->taskFreeTail = Buffer;
+    }
+
+    /* Not the first, add after the tail. */
+    else
+    {
+        /* Initialize the new tail buffer. */
+        Buffer->freePrev = Command->taskFreeTail;
+        Buffer->freeNext = gcvFREE_TASK_TERMINATOR;
+
+        /* Add after the tail. */
+        Command->taskFreeTail->freeNext = Buffer;
+        Command->taskFreeTail = Buffer;
+    }
+}
+
+static void
+_RemoveFromFreeList(
+    IN gckVGCOMMAND Command,
+    IN gcsTASK_CONTAINER_PTR Buffer
+    )
+{
+    /* Has to be a part of the free list. */
+    gcmkASSERT(Buffer->freePrev != gcvNULL);
+    gcmkASSERT(Buffer->freeNext != gcvNULL);
+
+    /* Head buffer? */
+    if (Buffer->freePrev == gcvFREE_TASK_TERMINATOR)
+    {
+        /* Tail buffer as well? */
+        if (Buffer->freeNext == gcvFREE_TASK_TERMINATOR)
+        {
+            /* Reset the list pointer. */
+            Command->taskFreeHead = Command->taskFreeTail = gcvNULL;
+        }
+
+        /* No, just the head. */
+        else
+        {
+            /* Update the head. */
+            Command->taskFreeHead = Buffer->freeNext;
+
+            /* Terminate the next buffer. */
+            Command->taskFreeHead->freePrev = gcvFREE_TASK_TERMINATOR;
+        }
+    }
+
+    /* Not the head. */
+    else
+    {
+        /* Tail buffer? */
+        if (Buffer->freeNext == gcvFREE_TASK_TERMINATOR)
+        {
+            /* Update the tail. */
+            Command->taskFreeTail = Buffer->freePrev;
+
+            /* Terminate the previous buffer. */
+            Command->taskFreeTail->freeNext = gcvFREE_TASK_TERMINATOR;
+        }
+
+        /* A buffer in the middle. */
+        else
+        {
+            /* Remove the buffer from the list. */
+            Buffer->freePrev->freeNext = Buffer->freeNext;
+            Buffer->freeNext->freePrev = Buffer->freePrev;
+        }
+    }
+
+    /* Reset free list pointers. */
+    Buffer->freePrev = gcvNULL;
+    Buffer->freeNext = gcvNULL;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*-------------------------- Task Buffer Allocation --------------------------*/
+
+static void
+_SplitTaskBuffer(
+    IN gckVGCOMMAND Command,
+    IN gcsTASK_CONTAINER_PTR Buffer,
+    IN gctUINT Size
+    )
+{
+    /* Determine the size of the new buffer. */
+    gctINT splitBufferSize = Buffer->size - Size;
+    gcmkASSERT(splitBufferSize >= 0);
+
+    /* Is the split buffer big enough to become a separate buffer? */
+    if (splitBufferSize >= gcvMIN_TASK_BUFFER)
+    {
+        /* Place the new path data. */
+        gcsTASK_CONTAINER_PTR splitBuffer = (gcsTASK_CONTAINER_PTR)
+        (
+            (gctUINT8_PTR) Buffer + Size
+        );
+
+        /* Set the trimmed buffer size. */
+        Buffer->size = Size;
+
+        /* Initialize the split buffer. */
+        splitBuffer->referenceCount = 0;
+        splitBuffer->size           = splitBufferSize;
+        splitBuffer->freePrev       = gcvNULL;
+        splitBuffer->freeNext       = gcvNULL;
+
+        /* Link in. */
+        _InsertTaskBuffer(Buffer, splitBuffer);
+        _AppendToFreeList(Command, splitBuffer);
+    }
+}
+
+static gceSTATUS
+_AllocateTaskContainer(
+    IN gckVGCOMMAND Command,
+    IN gctUINT Size,
+    OUT gcsTASK_CONTAINER_PTR * Buffer
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Command=0x%x Size=0x%x, Buffer ==0x%x", Command, Size, Buffer);
+
+    /* Verify arguments. */
+    gcmkVERIFY_ARGUMENT(Buffer != gcvNULL);
+
+    do
+    {
+        gcsTASK_STORAGE_PTR storage;
+        gcsTASK_CONTAINER_PTR buffer;
+
+        /* Adjust the size. */
+        Size += gcmSIZEOF(gcsTASK_CONTAINER);
+
+        /* Adjust the allocation size if not big enough. */
+        if (Size > Command->taskStorageUsable)
+        {
+            Command->taskStorageGranularity
+                = gcmALIGN(Size + gcmSIZEOF(gcsTASK_STORAGE), 1024);
+
+            Command->taskStorageUsable
+                = Command->taskStorageGranularity - gcmSIZEOF(gcsTASK_STORAGE);
+        }
+
+        /* Is there a free buffer available? */
+        else if (Command->taskFreeHead != gcvNULL)
+        {
+            /* Set the initial free buffer. */
+            gcsTASK_CONTAINER_PTR buffer = Command->taskFreeHead;
+
+            do
+            {
+                /* Is the buffer big enough? */
+                if (buffer->size >= Size)
+                {
+                    /* Remove the buffer from the free list. */
+                    _RemoveFromFreeList(Command, buffer);
+
+                    /* Split the buffer. */
+                    _SplitTaskBuffer(Command, buffer, Size);
+
+                    /* Set the result. */
+                    * Buffer = buffer;
+
+                    /* Success. */
+                    return gcvSTATUS_OK;
+                }
+
+                /* Get the next free buffer. */
+                buffer = buffer->freeNext;
+            }
+            while (buffer != gcvFREE_TASK_TERMINATOR);
+        }
+
+        /* Allocate a container. */
+        gcmkERR_BREAK(gckOS_Allocate(
+            Command->os,
+            Command->taskStorageGranularity,
+            (gctPOINTER *) &storage
+            ));
+
+        /* Link in the storage buffer. */
+        storage->next = Command->taskStorage;
+        Command->taskStorage = storage;
+
+        /* Place the task buffer. */
+        buffer = (gcsTASK_CONTAINER_PTR) (storage + 1);
+
+        /* Determine the size of the buffer. */
+        buffer->size
+            = Command->taskStorageGranularity
+            - gcmSIZEOF(gcsTASK_STORAGE);
+
+        /* Initialize the task buffer. */
+        buffer->referenceCount = 0;
+        buffer->allocPrev      = gcvNULL;
+        buffer->allocNext      = gcvNULL;
+        buffer->freePrev       = gcvNULL;
+        buffer->freeNext       = gcvNULL;
+
+        /* Split the buffer. */
+        _SplitTaskBuffer(Command, buffer, Size);
+
+        /* Set the result. */
+        * Buffer = buffer;
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return status. */
+    return status;
+}
+
+static void
+_FreeTaskContainer(
+    IN gckVGCOMMAND Command,
+    IN gcsTASK_CONTAINER_PTR Buffer
+    )
+{
+    gcsTASK_CONTAINER_PTR prev;
+    gcsTASK_CONTAINER_PTR next;
+    gcsTASK_CONTAINER_PTR merged;
+
+    gctSIZE_T mergedSize;
+
+    /* Verify arguments. */
+    gcmkASSERT(Buffer != gcvNULL);
+    gcmkASSERT(Buffer->freePrev == gcvNULL);
+    gcmkASSERT(Buffer->freeNext == gcvNULL);
+
+    /* Get shortcuts to the previous and next path data buffers. */
+    prev = Buffer->allocPrev;
+    next = Buffer->allocNext;
+
+    /* Is the previous path data buffer already free? */
+    if (prev && prev->freeNext)
+    {
+        /* The previous path data buffer is the one that remains. */
+        merged = prev;
+
+        /* Is the next path data buffer already free? */
+        if (next && next->freeNext)
+        {
+            /* Merge all three path data buffers into the previous. */
+            mergedSize = prev->size + Buffer->size + next->size;
+
+            /* Remove the next path data buffer. */
+            _RemoveFromFreeList(Command, next);
+            _RemoveTaskBuffer(next);
+        }
+        else
+        {
+            /* Merge the current path data buffer into the previous. */
+            mergedSize = prev->size + Buffer->size;
+        }
+
+        /* Delete the current path data buffer. */
+        _RemoveTaskBuffer(Buffer);
+
+        /* Set new size. */
+        merged->size = mergedSize;
+    }
+    else
+    {
+        /* The current path data buffer is the one that remains. */
+        merged = Buffer;
+
+        /* Is the next buffer already free? */
+        if (next && next->freeNext)
+        {
+            /* Merge the next into the current. */
+            mergedSize = Buffer->size + next->size;
+
+            /* Remove the next buffer. */
+            _RemoveFromFreeList(Command, next);
+            _RemoveTaskBuffer(next);
+
+            /* Set new size. */
+            merged->size = mergedSize;
+        }
+
+        /* Add the current buffer into the free list. */
+        _AppendToFreeList(Command, merged);
+    }
+}
+
+
+/******************************************************************************\
+********************************* Task Scheduling ******************************
+\******************************************************************************/
+
+static gceSTATUS
+_ScheduleTasks(
+    IN gckVGCOMMAND Command,
+    IN gcsTASK_MASTER_TABLE_PTR TaskTable,
+    IN gctUINT8_PTR PreviousEnd
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        gctINT block;
+        gcsTASK_CONTAINER_PTR container;
+        gcsTASK_MASTER_ENTRY_PTR userTaskEntry;
+        gcsBLOCK_TASK_ENTRY_PTR kernelTaskEntry;
+        gcsTASK_PTR userTask;
+        gctUINT8_PTR kernelTask;
+        gctINT32 interrupt;
+        gctUINT8_PTR eventCommand;
+
+        /* Nothing to schedule? */
+        if (TaskTable->size == 0)
+        {
+            status = gcvSTATUS_OK;
+            break;
+        }
+
+        /* Acquire the mutex. */
+        gcmkERR_BREAK(gckOS_AcquireMutex(
+            Command->os,
+            Command->taskMutex,
+            gcvINFINITE
+            ));
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+            "%s(%d)\n",
+            __FUNCTION__, __LINE__
+            );
+
+        do
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+                "  number of tasks scheduled   = %d\n"
+                "  size of event data in bytes = %d\n",
+                TaskTable->count,
+                TaskTable->size
+                );
+
+            /* Allocate task buffer. */
+            gcmkERR_BREAK(_AllocateTaskContainer(
+                Command,
+                TaskTable->size,
+                &container
+                ));
+
+            /* Determine the task data pointer. */
+            kernelTask = (gctUINT8_PTR) (container + 1);
+
+            /* Initialize the reference count. */
+            container->referenceCount = TaskTable->count;
+
+            /* Process tasks. */
+            for (block = gcvBLOCK_COUNT - 1; block >= 0; block -= 1)
+            {
+                /* Get the current user table entry. */
+                userTaskEntry = &TaskTable->table[block];
+
+                /* Are there tasks scheduled? */
+                if (userTaskEntry->head == gcvNULL)
+                {
+                    /* No, skip to the next block. */
+                    continue;
+                }
+
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+                    "  processing tasks for block %d\n",
+                    block
+                    );
+
+                /* Get the current kernel table entry. */
+                kernelTaskEntry = &Command->taskTable[block];
+
+                /* Are there tasks for the current block scheduled? */
+                if (kernelTaskEntry->container == gcvNULL)
+                {
+                    gcmkTRACE_ZONE(
+                        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+                        "  first task container for the block added\n",
+                        block
+                        );
+
+                    /* Nothing yet, set the container buffer pointer. */
+                    kernelTaskEntry->container = container;
+                    kernelTaskEntry->task      = (gcsTASK_HEADER_PTR) kernelTask;
+                }
+
+                /* Yes, append to the end. */
+                else
+                {
+                    kernelTaskEntry->link->cotainer = container;
+                    kernelTaskEntry->link->task     = (gcsTASK_HEADER_PTR) kernelTask;
+                }
+
+                /* Set initial task. */
+                userTask = userTaskEntry->head;
+
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+                    "  copying user tasks over to the kernel\n"
+                    );
+
+                /* Copy tasks. */
+                do
+                {
+                    gcmkTRACE_ZONE(
+                        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+                        "    task ID = %d, size = %d\n",
+                        ((gcsTASK_HEADER_PTR) (userTask + 1))->id,
+                        userTask->size
+                        );
+
+                    /* Copy the task data. */
+                    gcmkVERIFY_OK(gckOS_MemCopy(
+                        kernelTask, userTask + 1, userTask->size
+                        ));
+
+                    /* Advance to the next task. */
+                    kernelTask += userTask->size;
+                    userTask    = userTask->next;
+                }
+                while (userTask != gcvNULL);
+
+                /* Update link pointer in the header. */
+                kernelTaskEntry->link = (gcsTASK_LINK_PTR) kernelTask;
+
+                /* Initialize link task. */
+                kernelTaskEntry->link->id       = gcvTASK_LINK;
+                kernelTaskEntry->link->cotainer = gcvNULL;
+                kernelTaskEntry->link->task     = gcvNULL;
+
+                /* Advance the task data pointer. */
+                kernelTask += gcmSIZEOF(gcsTASK_LINK);
+            }
+        }
+        while (gcvFALSE);
+
+        /* Release the mutex. */
+        gcmkERR_BREAK(gckOS_ReleaseMutex(
+            Command->os,
+            Command->taskMutex
+            ));
+
+        /* Assign interrupts to the blocks. */
+        eventCommand = PreviousEnd;
+
+        for (block = gcvBLOCK_COUNT - 1; block >= 0; block -= 1)
+        {
+            /* Get the current user table entry. */
+            userTaskEntry = &TaskTable->table[block];
+
+            /* Are there tasks scheduled? */
+            if (userTaskEntry->head == gcvNULL)
+            {
+                /* No, skip to the next block. */
+                continue;
+            }
+
+            /* Get the interrupt number. */
+            interrupt = _GetNextInterrupt(Command, block);
+
+            gcmkTRACE_ZONE(
+                gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+                "%s(%d): block = %d interrupt = %d\n",
+                __FUNCTION__, __LINE__,
+                block, interrupt
+                );
+
+            /* Determine the command position. */
+            eventCommand -= Command->info.eventCommandSize;
+
+            /* Append an EVENT command. */
+            gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
+                Command, eventCommand, block, interrupt, gcvNULL
+                ));
+        }
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+
+/******************************************************************************\
+******************************** Memory Management *****************************
+\******************************************************************************/
+
+static gceSTATUS
+_HardwareToKernel(
+    IN gckOS Os,
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctUINT32 Address,
+    OUT gctPOINTER * KernelPointer
+    )
+{
+    gceSTATUS status;
+    gckVIDMEM memory;
+    gctUINT32 offset;
+
+    /* Assume a non-virtual node and get the pool manager object. */
+    memory = Node->VidMem.memory;
+
+    /* Determine the header offset within the pool it is allocated in. */
+    offset = Address - memory->baseAddress;
+
+    /* Translate the offset into the kernel side pointer. */
+    status = gckOS_GetKernelLogicalEx(
+        Os,
+        gcvCORE_VG,
+        offset,
+        KernelPointer
+        );
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_ConvertUserCommandBufferPointer(
+    IN gckVGCOMMAND Command,
+    IN gcsCMDBUFFER_PTR UserCommandBuffer,
+    OUT gcsCMDBUFFER_PTR * KernelCommandBuffer
+    )
+{
+    gceSTATUS status, last;
+    gcsCMDBUFFER_PTR mappedUserCommandBuffer = gcvNULL;
+
+    do
+    {
+        gctUINT32 headerAddress;
+
+        /* Map the command buffer structure into the kernel space. */
+        gcmkERR_BREAK(gckOS_MapUserPointer(
+            Command->os,
+            UserCommandBuffer,
+            gcmSIZEOF(gcsCMDBUFFER),
+            (gctPOINTER *) &mappedUserCommandBuffer
+            ));
+
+        /* Determine the address of the header. */
+        headerAddress
+            = mappedUserCommandBuffer->address
+            - mappedUserCommandBuffer->bufferOffset;
+
+        /* Translate the logical address to the kernel space. */
+        gcmkERR_BREAK(_HardwareToKernel(
+            Command->os,
+            mappedUserCommandBuffer->node,
+            headerAddress,
+            (gctPOINTER *) KernelCommandBuffer
+            ));
+    }
+    while (gcvFALSE);
+
+    /* Unmap the user command buffer. */
+    if (mappedUserCommandBuffer != gcvNULL)
+    {
+        gcmkCHECK_STATUS(gckOS_UnmapUserPointer(
+            Command->os,
+            UserCommandBuffer,
+            gcmSIZEOF(gcsCMDBUFFER),
+            mappedUserCommandBuffer
+            ));
+    }
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_AllocateLinear(
+    IN gckVGCOMMAND Command,
+    IN gctUINT Size,
+    IN gctUINT Alignment,
+    OUT gcuVIDMEM_NODE_PTR * Node,
+    OUT gctUINT32 * Address,
+    OUT gctPOINTER * Logical
+    )
+{
+    gceSTATUS status, last;
+    gcuVIDMEM_NODE_PTR node = gcvNULL;
+    gctUINT32 address = (gctUINT32)~0;
+
+    do
+    {
+        gcePOOL pool;
+        gctPOINTER logical;
+
+        /* Allocate from the system pool. */
+        pool = gcvPOOL_SYSTEM;
+
+        /* Allocate memory. */
+        gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
+            Command->kernel->kernel, &pool,
+            Size, Alignment,
+            gcvSURF_TYPE_UNKNOWN,
+            &node
+            ));
+
+        /* Do not accept virtual pools for now because we don't handle the
+           kernel pointer translation at the moment. */
+        if (pool == gcvPOOL_VIRTUAL)
+        {
+            status = gcvSTATUS_OUT_OF_MEMORY;
+            break;
+        }
+
+        /* Lock the command buffer. */
+        gcmkERR_BREAK(gckVIDMEM_Lock(
+            Command->kernel->kernel,
+            node,
+            gcvFALSE,
+            &address
+            ));
+
+        /* Translate the logical address to the kernel space. */
+        gcmkERR_BREAK(_HardwareToKernel(
+            Command->os,
+            node,
+            address,
+            &logical
+            ));
+
+        /* Set return values. */
+        * Node    = node;
+        * Address = address;
+        * Logical = logical;
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    /* Roll back. */
+    if (node != gcvNULL)
+    {
+        /* Unlock the command buffer. */
+        if (address != ~0)
+        {
+            gcmkCHECK_STATUS(gckVIDMEM_Unlock(
+                Command->kernel->kernel, node, gcvSURF_TYPE_UNKNOWN, gcvNULL
+                ));
+        }
+
+        /* Free the command buffer. */
+        gcmkCHECK_STATUS(gckVIDMEM_Free(
+            node
+            ));
+    }
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_FreeLinear(
+    IN gckVGKERNEL Kernel,
+    IN gcuVIDMEM_NODE_PTR Node
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Unlock the linear buffer. */
+        gcmkERR_BREAK(gckVIDMEM_Unlock(Kernel->kernel, Node, gcvSURF_TYPE_UNKNOWN, gcvNULL));
+
+        /* Free the linear buffer. */
+        gcmkERR_BREAK(gckVIDMEM_Free(Node));
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+gceSTATUS
+_AllocateCommandBuffer(
+    IN gckVGCOMMAND Command,
+    IN gctSIZE_T Size,
+    OUT gcsCMDBUFFER_PTR * CommandBuffer
+    )
+{
+    gceSTATUS status, last;
+    gcuVIDMEM_NODE_PTR node = gcvNULL;
+
+    do
+    {
+        gctUINT alignedHeaderSize;
+        gctUINT requestedSize;
+        gctUINT allocationSize;
+        gctUINT32 address = 0;
+        gcsCMDBUFFER_PTR commandBuffer;
+        gctUINT8_PTR endCommand;
+
+        /* Determine the aligned header size. */
+        alignedHeaderSize
+            = gcmALIGN(gcmSIZEOF(gcsCMDBUFFER), Command->info.addressAlignment);
+
+        /* Align the requested size. */
+        requestedSize
+            = gcmALIGN(Size, Command->info.commandAlignment);
+
+        /* Determine the size of the buffer to allocate. */
+        allocationSize
+            = alignedHeaderSize
+            + requestedSize
+            + Command->info.staticTailSize;
+
+        /* Allocate the command buffer. */
+        gcmkERR_BREAK(_AllocateLinear(
+            Command,
+            allocationSize,
+            Command->info.addressAlignment,
+            &node,
+            &address,
+            (gctPOINTER *) &commandBuffer
+            ));
+
+        /* Initialize the structure. */
+        commandBuffer->completion    = gcvVACANT_BUFFER;
+        commandBuffer->node          = node;
+        commandBuffer->address       = address + alignedHeaderSize;
+        commandBuffer->bufferOffset  = alignedHeaderSize;
+        commandBuffer->size          = requestedSize;
+        commandBuffer->offset        = requestedSize;
+        commandBuffer->nextAllocated = gcvNULL;
+        commandBuffer->nextSubBuffer = gcvNULL;
+
+        /* Determine the data count. */
+        commandBuffer->dataCount
+            = (requestedSize + Command->info.staticTailSize)
+            / Command->info.commandAlignment;
+
+        /* Determine the location of the END command. */
+        endCommand
+            = (gctUINT8_PTR) commandBuffer
+            + alignedHeaderSize
+            + requestedSize;
+
+        /* Append an END command. */
+        gcmkERR_BREAK(gckVGCOMMAND_EndCommand(
+            Command,
+            endCommand,
+            Command->info.feBufferInt,
+            gcvNULL
+            ));
+
+        /* Set the return pointer. */
+        * CommandBuffer = commandBuffer;
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    /* Roll back. */
+    if (node != gcvNULL)
+    {
+        /* Free the command buffer. */
+        gcmkCHECK_STATUS(_FreeLinear(Command->kernel, node));
+    }
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_FreeCommandBuffer(
+    IN gckVGKERNEL Kernel,
+    IN gcsCMDBUFFER_PTR CommandBuffer
+    )
+{
+    gceSTATUS status;
+
+    /* Free the buffer. */
+    status = _FreeLinear(Kernel, CommandBuffer->node);
+
+    /* Return status. */
+    return status;
+}
+
+
+/******************************************************************************\
+****************************** TS Overflow Handler *****************************
+\******************************************************************************/
+
+static gceSTATUS
+_EventHandler_TSOverflow(
+    IN gckVGKERNEL Kernel
+    )
+{
+    gcmkTRACE(
+        gcvLEVEL_ERROR,
+        "%s(%d): **** TS OVERFLOW ENCOUNTERED ****\n",
+        __FUNCTION__, __LINE__
+        );
+
+    return gcvSTATUS_OK;
+}
+
+
+/******************************************************************************\
+****************************** Bus Error Handler *******************************
+\******************************************************************************/
+
+static gceSTATUS
+_EventHandler_BusError(
+    IN gckVGKERNEL Kernel
+    )
+{
+    gcmkTRACE(
+        gcvLEVEL_ERROR,
+        "%s(%d): **** BUS ERROR ENCOUNTERED ****\n",
+        __FUNCTION__, __LINE__
+        );
+
+    return gcvSTATUS_OK;
+}
+
+
+/******************************************************************************\
+******************************** Task Routines *********************************
+\******************************************************************************/
+
+typedef gceSTATUS (* gctTASKROUTINE) (
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    );
+
+static gceSTATUS
+_TaskLink(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    );
+
+static gceSTATUS
+_TaskCluster(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    );
+
+static gceSTATUS
+_TaskIncrement(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    );
+
+static gceSTATUS
+_TaskDecrement(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    );
+
+static gceSTATUS
+_TaskSignal(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    );
+
+static gceSTATUS
+_TaskLockdown(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    );
+
+static gceSTATUS
+_TaskUnlockVideoMemory(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    );
+
+static gceSTATUS
+_TaskFreeVideoMemory(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    );
+
+static gceSTATUS
+_TaskFreeContiguousMemory(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    );
+
+static gceSTATUS
+_TaskUnmapUserMemory(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    );
+
+static gceSTATUS
+_TaskUnmapMemory(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    );
+
+static gctTASKROUTINE _taskRoutine[] =
+{
+    _TaskLink,                  /* gcvTASK_LINK                   */
+    _TaskCluster,               /* gcvTASK_CLUSTER                */
+    _TaskIncrement,             /* gcvTASK_INCREMENT              */
+    _TaskDecrement,             /* gcvTASK_DECREMENT              */
+    _TaskSignal,                /* gcvTASK_SIGNAL                 */
+    _TaskLockdown,              /* gcvTASK_LOCKDOWN               */
+    _TaskUnlockVideoMemory,     /* gcvTASK_UNLOCK_VIDEO_MEMORY    */
+    _TaskFreeVideoMemory,       /* gcvTASK_FREE_VIDEO_MEMORY      */
+    _TaskFreeContiguousMemory,  /* gcvTASK_FREE_CONTIGUOUS_MEMORY */
+    _TaskUnmapUserMemory,       /* gcvTASK_UNMAP_USER_MEMORY      */
+    _TaskUnmapMemory,           /* gcvTASK_UNMAP_MEMORY           */
+};
+
+static gceSTATUS
+_TaskLink(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    )
+{
+    /* Cast the task pointer. */
+    gcsTASK_LINK_PTR task = (gcsTASK_LINK_PTR) TaskHeader->task;
+
+    /* Save the pointer to the container. */
+    gcsTASK_CONTAINER_PTR container = TaskHeader->container;
+
+    /* No more tasks in the list? */
+    if (task->task == gcvNULL)
+    {
+        /* Reset the entry. */
+        TaskHeader->container = gcvNULL;
+        TaskHeader->task      = gcvNULL;
+        TaskHeader->link      = gcvNULL;
+    }
+    else
+    {
+        /* Update the entry. */
+        TaskHeader->container = task->cotainer;
+        TaskHeader->task      = task->task;
+    }
+
+    /* Decrement the task buffer reference. */
+    gcmkASSERT(container->referenceCount >= 0);
+    if (container->referenceCount == 0)
+    {
+        /* Free the container. */
+        _FreeTaskContainer(Command, container);
+    }
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_TaskCluster(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+
+    /* Cast the task pointer. */
+    gcsTASK_CLUSTER_PTR cluster = (gcsTASK_CLUSTER_PTR) TaskHeader->task;
+
+    /* Get the number of tasks. */
+    gctUINT taskCount = cluster->taskCount;
+
+    /* Advance to the next task. */
+    TaskHeader->task = (gcsTASK_HEADER_PTR) (cluster + 1);
+
+    /* Perform all tasks in the cluster. */
+    while (taskCount)
+    {
+        /* Perform the current task. */
+        gcmkERR_BREAK(_taskRoutine[TaskHeader->task->id](
+            Command,
+            TaskHeader
+            ));
+
+        /* Update the task count. */
+        taskCount -= 1;
+    }
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_TaskIncrement(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Cast the task pointer. */
+        gcsTASK_INCREMENT_PTR task = (gcsTASK_INCREMENT_PTR) TaskHeader->task;
+
+        /* Convert physical into logical address. */
+        gctUINT32_PTR logical;
+        gcmkERR_BREAK(gckOS_MapPhysical(
+            Command->os,
+            task->address,
+            gcmSIZEOF(gctUINT32),
+            (gctPOINTER *) &logical
+            ));
+
+        /* Increment data. */
+        (* logical) += 1;
+
+        /* Unmap the physical memory. */
+        gcmkERR_BREAK(gckOS_UnmapPhysical(
+            Command->os,
+            logical,
+            gcmSIZEOF(gctUINT32)
+            ));
+
+        /* Update the reference counter. */
+        TaskHeader->container->referenceCount -= 1;
+
+        /* Update the task pointer. */
+        TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_TaskDecrement(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Cast the task pointer. */
+        gcsTASK_DECREMENT_PTR task = (gcsTASK_DECREMENT_PTR) TaskHeader->task;
+
+        /* Convert physical into logical address. */
+        gctUINT32_PTR logical;
+        gcmkERR_BREAK(gckOS_MapPhysical(
+            Command->os,
+            task->address,
+            gcmSIZEOF(gctUINT32),
+            (gctPOINTER *) &logical
+            ));
+
+        /* Decrement data. */
+        (* logical) -= 1;
+
+        /* Unmap the physical memory. */
+        gcmkERR_BREAK(gckOS_UnmapPhysical(
+            Command->os,
+            logical,
+            gcmSIZEOF(gctUINT32)
+            ));
+
+        /* Update the reference counter. */
+        TaskHeader->container->referenceCount -= 1;
+
+        /* Update the task pointer. */
+        TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_TaskSignal(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Cast the task pointer. */
+        gcsTASK_SIGNAL_PTR task = (gcsTASK_SIGNAL_PTR) TaskHeader->task;
+
+        /* Map the signal into kernel space. */
+        gcmkERR_BREAK(gckOS_UserSignal(
+            Command->os, task->signal, task->process
+            ));
+        /* Update the reference counter. */
+        TaskHeader->container->referenceCount -= 1;
+
+        /* Update the task pointer. */
+        TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_TaskLockdown(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    )
+{
+    gceSTATUS status;
+    gctUINT32_PTR userCounter   = gcvNULL;
+    gctUINT32_PTR kernelCounter = gcvNULL;
+    gctSIGNAL signal            = gcvNULL;
+
+    do
+    {
+        /* Cast the task pointer. */
+        gcsTASK_LOCKDOWN_PTR task = (gcsTASK_LOCKDOWN_PTR) TaskHeader->task;
+
+        /* Convert physical addresses into logical. */
+        gcmkERR_BREAK(gckOS_MapPhysical(
+            Command->os,
+            task->userCounter,
+            gcmSIZEOF(gctUINT32),
+            (gctPOINTER *) &userCounter
+            ));
+
+        gcmkERR_BREAK(gckOS_MapPhysical(
+            Command->os,
+            task->kernelCounter,
+            gcmSIZEOF(gctUINT32),
+            (gctPOINTER *) &kernelCounter
+            ));
+
+        /* Update the kernel counter. */
+        (* kernelCounter) += 1;
+
+        /* Are the counters equal? */
+        if ((* userCounter) == (* kernelCounter))
+        {
+            /* Map the signal into kernel space. */
+            gcmkERR_BREAK(gckOS_MapSignal(
+                Command->os, task->signal, task->process, &signal
+                ));
+
+            if (signal == gcvNULL)
+            {
+                /* Signal. */
+                gcmkERR_BREAK(gckOS_Signal(
+                    Command->os, task->signal, gcvTRUE
+                    ));
+            }
+            else
+            {
+                /* Signal. */
+                gcmkERR_BREAK(gckOS_Signal(
+                    Command->os, signal, gcvTRUE
+                    ));
+            }
+        }
+
+        /* Update the reference counter. */
+        TaskHeader->container->referenceCount -= 1;
+
+        /* Update the task pointer. */
+        TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+    }
+    while (gcvFALSE);
+
+    /* Destroy the mapped signal. */
+    if (signal != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckOS_DestroySignal(
+            Command->os, signal
+            ));
+    }
+
+    /* Unmap the physical memory. */
+    if (kernelCounter != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckOS_UnmapPhysical(
+            Command->os,
+            kernelCounter,
+            gcmSIZEOF(gctUINT32)
+            ));
+    }
+
+    if (userCounter != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckOS_UnmapPhysical(
+            Command->os,
+            userCounter,
+            gcmSIZEOF(gctUINT32)
+            ));
+    }
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_TaskUnlockVideoMemory(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Cast the task pointer. */
+        gcsTASK_UNLOCK_VIDEO_MEMORY_PTR task
+            = (gcsTASK_UNLOCK_VIDEO_MEMORY_PTR) TaskHeader->task;
+
+        /* Unlock video memory. */
+        gcmkERR_BREAK(gckVIDMEM_Unlock(
+            Command->kernel->kernel,
+            task->node,
+            gcvSURF_TYPE_UNKNOWN,
+            gcvNULL));
+
+        /* Update the reference counter. */
+        TaskHeader->container->referenceCount -= 1;
+
+        /* Update the task pointer. */
+        TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_TaskFreeVideoMemory(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Cast the task pointer. */
+        gcsTASK_FREE_VIDEO_MEMORY_PTR task
+            = (gcsTASK_FREE_VIDEO_MEMORY_PTR) TaskHeader->task;
+
+        /* Free video memory. */
+        gcmkERR_BREAK(gckVIDMEM_Free(task->node));
+
+        /* Update the reference counter. */
+        TaskHeader->container->referenceCount -= 1;
+
+        /* Update the task pointer. */
+        TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_TaskFreeContiguousMemory(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Cast the task pointer. */
+        gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR task
+            = (gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR) TaskHeader->task;
+
+        /* Free contiguous memory. */
+        gcmkERR_BREAK(gckOS_FreeContiguous(
+            Command->os, task->physical, task->logical, task->bytes
+            ));
+
+        /* Update the reference counter. */
+        TaskHeader->container->referenceCount -= 1;
+
+        /* Update the task pointer. */
+        TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_TaskUnmapUserMemory(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Cast the task pointer. */
+        gcsTASK_UNMAP_USER_MEMORY_PTR task
+            = (gcsTASK_UNMAP_USER_MEMORY_PTR) TaskHeader->task;
+
+        /* Unmap the user memory. */
+        gcmkERR_BREAK(gckOS_UnmapUserMemoryEx(
+            Command->os, gcvCORE_VG, task->memory, task->size, task->info, task->address
+            ));
+
+        /* Update the reference counter. */
+        TaskHeader->container->referenceCount -= 1;
+
+        /* Update the task pointer. */
+        TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_TaskUnmapMemory(
+    gckVGCOMMAND Command,
+    gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Cast the task pointer. */
+        gcsTASK_UNMAP_MEMORY_PTR task
+            = (gcsTASK_UNMAP_MEMORY_PTR) TaskHeader->task;
+
+        /* Unmap memory. */
+        gcmkERR_BREAK(gckKERNEL_UnmapMemory(
+            Command->kernel->kernel, task->physical, task->bytes, task->logical
+            ));
+
+        /* Update the reference counter. */
+        TaskHeader->container->referenceCount -= 1;
+
+        /* Update the task pointer. */
+        TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+
+/******************************************************************************\
+************ Hardware Block Interrupt Handlers For Scheduled Events ************
+\******************************************************************************/
+
+static gceSTATUS
+_EventHandler_Block(
+    IN gckVGKERNEL Kernel,
+    IN gcsBLOCK_TASK_ENTRY_PTR TaskHeader,
+    IN gctBOOL ProcessAll
+    )
+{
+    gceSTATUS status, last;
+
+    gcmkHEADER_ARG("Kernel=0x%x TaskHeader=0x%x ProcessAll=0x%x", Kernel, TaskHeader, ProcessAll);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    do
+    {
+        gckVGCOMMAND command;
+
+        /* Get the command buffer object. */
+        command = Kernel->command;
+
+        /* Increment the interrupt usage semaphore. */
+        gcmkERR_BREAK(gckOS_IncrementSemaphore(
+            command->os, TaskHeader->interruptSemaphore
+            ));
+
+        /* Acquire the mutex. */
+        gcmkERR_BREAK(gckOS_AcquireMutex(
+            command->os,
+            command->taskMutex,
+            gcvINFINITE
+            ));
+
+        /* Verify inputs. */
+        gcmkASSERT(TaskHeader            != gcvNULL);
+        gcmkASSERT(TaskHeader->container != gcvNULL);
+        gcmkASSERT(TaskHeader->task      != gcvNULL);
+        gcmkASSERT(TaskHeader->link      != gcvNULL);
+
+        /* Process tasks. */
+        do
+        {
+            /* Process the current task. */
+            gcmkERR_BREAK(_taskRoutine[TaskHeader->task->id](
+                command,
+                TaskHeader
+                ));
+
+            /* Is the next task is LINK? */
+            if (TaskHeader->task->id == gcvTASK_LINK)
+            {
+                gcmkERR_BREAK(_taskRoutine[TaskHeader->task->id](
+                    command,
+                    TaskHeader
+                    ));
+
+                /* Done. */
+                break;
+            }
+        }
+        while (ProcessAll);
+
+        /* Release the mutex. */
+        gcmkCHECK_STATUS(gckOS_ReleaseMutex(
+            command->os,
+            command->taskMutex
+            ));
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return status. */
+    return status;
+}
+
+gcmDECLARE_INTERRUPT_HANDLER(COMMAND, 0)
+{
+    gceSTATUS status, last;
+
+    gcmkHEADER_ARG("Kernel=0x%x ", Kernel);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    do
+    {
+        gckVGCOMMAND command;
+        gcsKERNEL_QUEUE_HEADER_PTR mergeQueue;
+        gcsKERNEL_QUEUE_HEADER_PTR queueTail;
+        gcsKERNEL_CMDQUEUE_PTR entry;
+        gctUINT entryCount;
+
+        /* Get the command buffer object. */
+        command = Kernel->command;
+
+        /* Acquire the mutex. */
+        gcmkERR_BREAK(gckOS_AcquireMutex(
+            command->os,
+            command->queueMutex,
+            gcvINFINITE
+            ));
+
+        /* Get the current queue. */
+        queueTail = command->queueTail;
+
+        /* Get the current queue entry. */
+        entry = queueTail->currentEntry;
+
+        /* Get the number of entries in the queue. */
+        entryCount = queueTail->pending;
+
+        /* Process all entries. */
+        while (gcvTRUE)
+        {
+            /* Call post-execution function. */
+            status = entry->handler(Kernel, entry);
+
+            /* Failed? */
+            if (gcmkIS_ERROR(status))
+            {
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_ERROR,
+                    gcvZONE_COMMAND,
+                    "[%s] line %d: post action failed.\n",
+                    __FUNCTION__, __LINE__
+                    );
+            }
+
+            /* Executed the next buffer? */
+            if (status == gcvSTATUS_EXECUTED)
+            {
+                /* Update the queue. */
+                queueTail->pending      = entryCount;
+                queueTail->currentEntry = entry;
+
+                /* Success. */
+                status = gcvSTATUS_OK;
+
+                /* Break out of the loop. */
+                break;
+            }
+
+            /* Advance to the next entry. */
+            entry      += 1;
+            entryCount -= 1;
+
+            /* Last entry? */
+            if (entryCount == 0)
+            {
+                /* Reset the queue to idle. */
+                queueTail->pending = 0;
+
+                /* Get a shortcut to the queue to merge with. */
+                mergeQueue = command->mergeQueue;
+
+                /* Merge the queues if necessary. */
+                if (mergeQueue != queueTail)
+                {
+                    gcmkASSERT(mergeQueue < queueTail);
+                    gcmkASSERT(mergeQueue->next == queueTail);
+
+                    mergeQueue->size
+                        += gcmSIZEOF(gcsKERNEL_QUEUE_HEADER)
+                        + queueTail->size;
+
+                    mergeQueue->next = queueTail->next;
+                }
+
+                /* Advance to the next queue. */
+                queueTail = queueTail->next;
+
+                /* Did it wrap around? */
+                if (command->queue == queueTail)
+                {
+                    /* Reset merge queue. */
+                    command->mergeQueue = queueTail;
+                }
+
+                /* Set new queue. */
+                command->queueTail = queueTail;
+
+                /* Is the next queue scheduled? */
+                if (queueTail->pending > 0)
+                {
+                    gcsCMDBUFFER_PTR commandBuffer;
+
+                    /* The first entry must be a command buffer. */
+                    commandBuffer = queueTail->currentEntry->commandBuffer;
+
+                    /* Start the command processor. */
+                    status = gckVGHARDWARE_Execute(
+                        command->hardware,
+                        commandBuffer->address,
+                        commandBuffer->dataCount
+                        );
+
+                    /* Failed? */
+                    if (gcmkIS_ERROR(status))
+                    {
+                        gcmkTRACE_ZONE(
+                            gcvLEVEL_ERROR,
+                            gcvZONE_COMMAND,
+                            "[%s] line %d: failed to start the next queue.\n",
+                            __FUNCTION__, __LINE__
+                            );
+                    }
+                }
+
+                /* Break out of the loop. */
+                break;
+            }
+        }
+
+        /* Release the mutex. */
+        gcmkCHECK_STATUS(gckOS_ReleaseMutex(
+            command->os,
+            command->queueMutex
+            ));
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return status. */
+    return status;
+}
+
+/* Define standard block interrupt handlers. */
+gcmDEFINE_INTERRUPT_HANDLER(TESSELLATOR, 0)
+gcmDEFINE_INTERRUPT_HANDLER(VG,          0)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL,       0)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL,       1)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL,       2)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL,       3)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL,       4)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL,       5)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL,       6)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL,       7)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL,       8)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL,       9)
+
+/* The entries in the array are arranged by event priority. */
+static gcsBLOCK_INTERRUPT_HANDLER _blockHandlers[] =
+{
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(TESSELLATOR, 0),
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(VG,          0),
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL,       0),
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL,       1),
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL,       2),
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL,       3),
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL,       4),
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL,       5),
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL,       6),
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL,       7),
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL,       8),
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL,       9),
+    gcmDEFINE_INTERRUPT_HANDLER_ENTRY(COMMAND,     0),
+};
+
+
+/******************************************************************************\
+************************* Static Command Buffer Handlers ***********************
+\******************************************************************************/
+
+static gceSTATUS
+_UpdateStaticCommandBuffer(
+    IN gckVGKERNEL Kernel,
+    IN gcsKERNEL_CMDQUEUE_PTR Entry
+    )
+{
+    gcmkTRACE_ZONE(
+        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+        "%s(%d)\n",
+        __FUNCTION__, __LINE__
+        );
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_ExecuteStaticCommandBuffer(
+    IN gckVGKERNEL Kernel,
+    IN gcsKERNEL_CMDQUEUE_PTR Entry
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        gcsCMDBUFFER_PTR commandBuffer;
+
+        /* Cast the command buffer header. */
+        commandBuffer = Entry->commandBuffer;
+
+        /* Set to update the command buffer next time. */
+        Entry->handler = _UpdateStaticCommandBuffer;
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+            "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
+            __FUNCTION__, __LINE__,
+            commandBuffer->address,
+            commandBuffer->dataCount
+            );
+
+        /* Start the command processor. */
+        gcmkERR_BREAK(gckVGHARDWARE_Execute(
+            Kernel->hardware,
+            commandBuffer->address,
+            commandBuffer->dataCount
+            ));
+
+        /* Success. */
+        return gcvSTATUS_EXECUTED;
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_UpdateLastStaticCommandBuffer(
+    IN gckVGKERNEL Kernel,
+    IN gcsKERNEL_CMDQUEUE_PTR Entry
+    )
+{
+#if gcvDEBUG || gcdFORCE_MESSAGES
+    /* Get the command buffer header. */
+    gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+    /* Validate the command buffer. */
+    gcmkASSERT(commandBuffer->completion != gcvNULL);
+    gcmkASSERT(commandBuffer->completion != gcvVACANT_BUFFER);
+
+#endif
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+        "%s(%d): processing all tasks scheduled for FE.\n",
+        __FUNCTION__, __LINE__
+        );
+
+    /* Perform scheduled tasks. */
+    return _EventHandler_Block(
+        Kernel,
+        &Kernel->command->taskTable[gcvBLOCK_COMMAND],
+        gcvTRUE
+        );
+}
+
+static gceSTATUS
+_ExecuteLastStaticCommandBuffer(
+    IN gckVGKERNEL Kernel,
+    IN gcsKERNEL_CMDQUEUE_PTR Entry
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Cast the command buffer header. */
+        gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+        /* Set to update the command buffer next time. */
+        Entry->handler = _UpdateLastStaticCommandBuffer;
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+            "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
+            __FUNCTION__, __LINE__,
+            commandBuffer->address,
+            commandBuffer->dataCount
+            );
+
+        /* Start the command processor. */
+        gcmkERR_BREAK(gckVGHARDWARE_Execute(
+            Kernel->hardware,
+            commandBuffer->address,
+            commandBuffer->dataCount
+            ));
+
+        /* Success. */
+        return gcvSTATUS_EXECUTED;
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+
+/******************************************************************************\
+************************* Dynamic Command Buffer Handlers **********************
+\******************************************************************************/
+
+static gceSTATUS
+_UpdateDynamicCommandBuffer(
+    IN gckVGKERNEL Kernel,
+    IN gcsKERNEL_CMDQUEUE_PTR Entry
+    )
+{
+    gcmkTRACE_ZONE(
+        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+        "%s(%d)\n",
+        __FUNCTION__, __LINE__
+        );
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_ExecuteDynamicCommandBuffer(
+    IN gckVGKERNEL Kernel,
+    IN gcsKERNEL_CMDQUEUE_PTR Entry
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Cast the command buffer header. */
+        gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+        /* Set to update the command buffer next time. */
+        Entry->handler = _UpdateDynamicCommandBuffer;
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+            "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
+            __FUNCTION__, __LINE__,
+            commandBuffer->address,
+            commandBuffer->dataCount
+            );
+
+        /* Start the command processor. */
+        gcmkERR_BREAK(gckVGHARDWARE_Execute(
+            Kernel->hardware,
+            commandBuffer->address,
+            commandBuffer->dataCount
+            ));
+
+        /* Success. */
+        return gcvSTATUS_EXECUTED;
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_UpdateLastDynamicCommandBuffer(
+    IN gckVGKERNEL Kernel,
+    IN gcsKERNEL_CMDQUEUE_PTR Entry
+    )
+{
+#if gcvDEBUG || gcdFORCE_MESSAGES
+    /* Get the command buffer header. */
+    gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+    /* Validate the command buffer. */
+    gcmkASSERT(commandBuffer->completion != gcvNULL);
+    gcmkASSERT(commandBuffer->completion != gcvVACANT_BUFFER);
+
+#endif
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+        "%s(%d): processing all tasks scheduled for FE.\n",
+        __FUNCTION__, __LINE__
+        );
+
+    /* Perform scheduled tasks. */
+    return _EventHandler_Block(
+        Kernel,
+        &Kernel->command->taskTable[gcvBLOCK_COMMAND],
+        gcvTRUE
+        );
+}
+
+static gceSTATUS
+_ExecuteLastDynamicCommandBuffer(
+    IN gckVGKERNEL Kernel,
+    IN gcsKERNEL_CMDQUEUE_PTR Entry
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Cast the command buffer header. */
+        gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+        /* Set to update the command buffer next time. */
+        Entry->handler = _UpdateLastDynamicCommandBuffer;
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+            "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
+            __FUNCTION__, __LINE__,
+            commandBuffer->address,
+            commandBuffer->dataCount
+            );
+
+        /* Start the command processor. */
+        gcmkERR_BREAK(gckVGHARDWARE_Execute(
+            Kernel->hardware,
+            commandBuffer->address,
+            commandBuffer->dataCount
+            ));
+
+        /* Success. */
+        return gcvSTATUS_EXECUTED;
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+
+/******************************************************************************\
+********************************* Other Handlers *******************************
+\******************************************************************************/
+
+static gceSTATUS
+_FreeKernelCommandBuffer(
+    IN gckVGKERNEL Kernel,
+    IN gcsKERNEL_CMDQUEUE_PTR Entry
+    )
+{
+    gceSTATUS status;
+
+    /* Free the command buffer. */
+    status = _FreeCommandBuffer(Kernel, Entry->commandBuffer);
+
+    /* Return status. */
+    return status;
+}
+
+
+/******************************************************************************\
+******************************* Queue Management *******************************
+\******************************************************************************/
+
+#if gcvDUMP_COMMAND_BUFFER
+static void
+_DumpCommandQueue(
+    IN gckVGCOMMAND Command,
+    IN gcsKERNEL_QUEUE_HEADER_PTR QueueHeader,
+    IN gctUINT EntryCount
+    )
+{
+    gcsKERNEL_CMDQUEUE_PTR entry;
+    gctUINT queueIndex;
+
+#if defined(gcvCOMMAND_BUFFER_NAME)
+    static gctUINT arrayCount = 0;
+#endif
+
+    /* Is dumpinng enabled? */
+    if (!Commad->enableDumping)
+    {
+        return;
+    }
+
+#if !defined(gcvCOMMAND_BUFFER_NAME)
+    gcmkTRACE_ZONE(
+        gcvLEVEL_INFO, gcvZONE_COMMAND,
+        "COMMAND QUEUE DUMP: %d entries\n", EntryCount
+        );
+#endif
+
+    /* Get the pointer to the first entry. */
+    entry = QueueHeader->currentEntry;
+
+    /* Iterate through the queue. */
+    for (queueIndex = 0; queueIndex < EntryCount; queueIndex += 1)
+    {
+        gcsCMDBUFFER_PTR buffer;
+        gctUINT bufferCount;
+        gctUINT bufferIndex;
+        gctUINT i, count;
+        gctUINT size;
+        gctUINT32_PTR data;
+
+#if gcvDUMP_COMMAND_LINES
+        gctUINT lineNumber;
+#endif
+
+#if !defined(gcvCOMMAND_BUFFER_NAME)
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_COMMAND,
+            "ENTRY %d\n", queueIndex
+            );
+#endif
+
+        /* Reset the count. */
+        bufferCount = 0;
+
+        /* Set the initial buffer. */
+        buffer = entry->commandBuffer;
+
+        /* Loop through all subbuffers. */
+        while (buffer)
+        {
+            /* Update the count. */
+            bufferCount += 1;
+
+            /* Advance to the next subbuffer. */
+            buffer = buffer->nextSubBuffer;
+        }
+
+#if !defined(gcvCOMMAND_BUFFER_NAME)
+        if (bufferCount > 1)
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO,
+                gcvZONE_COMMAND,
+                "  COMMAND BUFFER SET: %d buffers.\n",
+                bufferCount
+                );
+        }
+#endif
+
+        /* Reset the buffer index. */
+        bufferIndex = 0;
+
+        /* Set the initial buffer. */
+        buffer = entry->commandBuffer;
+
+        /* Loop through all subbuffers. */
+        while (buffer)
+        {
+            /* Determine the size of the buffer. */
+            size = buffer->dataCount * Command->info.commandAlignment;
+
+#if !defined(gcvCOMMAND_BUFFER_NAME)
+            /* A single buffer? */
+            if (bufferCount == 1)
+            {
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_INFO,
+                    gcvZONE_COMMAND,
+                    "  COMMAND BUFFER: count=%d (0x%X), size=%d bytes @ %08X.\n",
+                    buffer->dataCount,
+                    buffer->dataCount,
+                    size,
+                    buffer->address
+                    );
+            }
+            else
+            {
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_INFO,
+                    gcvZONE_COMMAND,
+                    "  COMMAND BUFFER %d: count=%d (0x%X), size=%d bytes @ %08X\n",
+                    bufferIndex,
+                    buffer->dataCount,
+                    buffer->dataCount,
+                    size,
+                    buffer->address
+                    );
+            }
+#endif
+
+            /* Determine the number of double words to print. */
+            count = size / 4;
+
+            /* Determine the buffer location. */
+            data = (gctUINT32_PTR)
+            (
+                (gctUINT8_PTR) buffer + buffer->bufferOffset
+            );
+
+#if defined(gcvCOMMAND_BUFFER_NAME)
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO,
+                gcvZONE_COMMAND,
+                "unsigned int _" gcvCOMMAND_BUFFER_NAME "_%d[] =\n",
+                arrayCount
+                );
+
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO,
+                gcvZONE_COMMAND,
+                "{\n"
+                );
+
+            arrayCount += 1;
+#endif
+
+#if gcvDUMP_COMMAND_LINES
+            /* Reset the line number. */
+            lineNumber = 0;
+#endif
+
+#if defined(gcvCOMMAND_BUFFER_NAME)
+            count -= 2;
+#endif
+
+            for (i = 0; i < count; i += 1)
+            {
+                if ((i % 8) == 0)
+                {
+#if defined(gcvCOMMAND_BUFFER_NAME)
+                    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "\t");
+#else
+                    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "    ");
+#endif
+                }
+
+#if gcvDUMP_COMMAND_LINES
+                if (lineNumber == gcvDUMP_COMMAND_LINES)
+                {
+                    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, " . . . . . . . . .\n");
+                    break;
+                }
+#endif
+                gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "0x%08X", data[i]);
+
+                if (i + 1 == count)
+                {
+                    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "\n");
+
+#if gcvDUMP_COMMAND_LINES
+                    lineNumber += 1;
+#endif
+                }
+                else
+                {
+                    if (((i + 1) % 8) == 0)
+                    {
+                        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, ",\n");
+
+#if gcvDUMP_COMMAND_LINES
+                        lineNumber += 1;
+#endif
+                    }
+                    else
+                    {
+                        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, ", ");
+                    }
+                }
+            }
+
+#if defined(gcvCOMMAND_BUFFER_NAME)
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO,
+                gcvZONE_COMMAND,
+                "};\n\n"
+                );
+#endif
+
+            /* Advance to the next subbuffer. */
+            buffer = buffer->nextSubBuffer;
+            bufferIndex += 1;
+        }
+
+        /* Advance to the next entry. */
+        entry += 1;
+    }
+}
+#endif
+
+static gceSTATUS
+_LockCurrentQueue(
+    IN gckVGCOMMAND Command,
+    OUT gcsKERNEL_CMDQUEUE_PTR * Entries,
+    OUT gctUINT_PTR EntryCount
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        gcsKERNEL_QUEUE_HEADER_PTR queueHead;
+
+        /* Get a shortcut to the head of the queue. */
+        queueHead = Command->queueHead;
+
+        /* Is the head buffer still being worked on? */
+        if (queueHead->pending)
+        {
+            /* Increment overflow count. */
+            Command->queueOverflow += 1;
+
+            /* Wait until the head becomes idle. */
+            gcmkERR_BREAK(_WaitForIdle(Command, queueHead));
+        }
+
+        /* Acquire the mutex. */
+        gcmkERR_BREAK(gckOS_AcquireMutex(
+            Command->os,
+            Command->queueMutex,
+            gcvINFINITE
+            ));
+
+        /* Determine the first queue entry. */
+        queueHead->currentEntry = (gcsKERNEL_CMDQUEUE_PTR)
+        (
+            (gctUINT8_PTR) queueHead + gcmSIZEOF(gcsKERNEL_QUEUE_HEADER)
+        );
+
+        /* Set the pointer to the first entry. */
+        * Entries = queueHead->currentEntry;
+
+        /* Determine the number of available entries. */
+        * EntryCount = queueHead->size / gcmSIZEOF(gcsKERNEL_CMDQUEUE);
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+static gceSTATUS
+_UnlockCurrentQueue(
+    IN gckVGCOMMAND Command,
+    IN gctUINT EntryCount
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+#if !gcdENABLE_INFINITE_SPEED_HW
+        gcsKERNEL_QUEUE_HEADER_PTR queueTail;
+        gcsKERNEL_QUEUE_HEADER_PTR queueHead;
+        gcsKERNEL_QUEUE_HEADER_PTR queueNext;
+        gctUINT queueSize;
+        gctUINT newSize;
+        gctUINT unusedSize;
+
+        /* Get shortcut to the head and to the tail of the queue. */
+        queueTail = Command->queueTail;
+        queueHead = Command->queueHead;
+
+        /* Dump the command buffer. */
+#if gcvDUMP_COMMAND_BUFFER
+        _DumpCommandQueue(Command, queueHead, EntryCount);
+#endif
+
+        /* Get a shortcut to the current queue size. */
+        queueSize = queueHead->size;
+
+        /* Determine the new queue size. */
+        newSize = EntryCount * gcmSIZEOF(gcsKERNEL_CMDQUEUE);
+        gcmkASSERT(newSize <= queueSize);
+
+        /* Determine the size of the unused area. */
+        unusedSize = queueSize - newSize;
+
+        /* Is the unused area big enough to become a buffer? */
+        if (unusedSize >= gcvMINUMUM_BUFFER)
+        {
+            gcsKERNEL_QUEUE_HEADER_PTR nextHead;
+
+            /* Place the new header. */
+            nextHead = (gcsKERNEL_QUEUE_HEADER_PTR)
+            (
+                (gctUINT8_PTR) queueHead
+                    + gcmSIZEOF(gcsKERNEL_QUEUE_HEADER)
+                    + newSize
+            );
+
+            /* Initialize the buffer. */
+            nextHead->size    = unusedSize - gcmSIZEOF(gcsKERNEL_QUEUE_HEADER);
+            nextHead->pending = 0;
+
+            /* Link the buffer in. */
+            nextHead->next  = queueHead->next;
+            queueHead->next = nextHead;
+            queueNext       = nextHead;
+
+            /* Update the size of the current buffer. */
+            queueHead->size = newSize;
+        }
+
+        /* Not big enough. */
+        else
+        {
+            /* Determine the next queue. */
+            queueNext = queueHead->next;
+        }
+
+        /* Mark the buffer as busy. */
+        queueHead->pending = EntryCount;
+
+        /* Advance to the next buffer. */
+        Command->queueHead = queueNext;
+
+        /* Start the command processor if the queue was empty. */
+        if (queueTail == queueHead)
+        {
+            gcsCMDBUFFER_PTR commandBuffer;
+
+            /* The first entry must be a command buffer. */
+            commandBuffer = queueTail->currentEntry->commandBuffer;
+
+            /* Start the command processor. */
+            gcmkERR_BREAK(gckVGHARDWARE_Execute(
+                Command->hardware,
+                commandBuffer->address,
+                commandBuffer->dataCount
+                ));
+        }
+
+        /* The queue was not empty. */
+        else
+        {
+            /* Advance the merge buffer if needed. */
+            if (queueHead == Command->mergeQueue)
+            {
+                Command->mergeQueue = queueNext;
+            }
+        }
+#endif
+
+        /* Release the mutex. */
+        gcmkERR_BREAK(gckOS_ReleaseMutex(
+            Command->os,
+            Command->queueMutex
+            ));
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+
+/******************************************************************************\
+****************************** gckVGCOMMAND API Code *****************************
+\******************************************************************************/
+
+gceSTATUS
+gckVGCOMMAND_Construct(
+    IN gckVGKERNEL Kernel,
+    IN gctUINT TaskGranularity,
+    IN gctUINT QueueSize,
+    OUT gckVGCOMMAND * Command
+    )
+{
+    gceSTATUS status, last;
+    gckVGCOMMAND command = gcvNULL;
+    gcsKERNEL_QUEUE_HEADER_PTR queue;
+    gctUINT i, j;
+
+    gcmkHEADER_ARG("Kernel=0x%x TaskGranularity=0x%x QueueSize=0x%x Command=0x%x",
+        Kernel, TaskGranularity, QueueSize, Command);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(QueueSize >= gcvMINUMUM_BUFFER);
+    gcmkVERIFY_ARGUMENT(Command != gcvNULL);
+
+    do
+    {
+        /***********************************************************************
+        ** Generic object initialization.
+        */
+
+        /* Allocate the gckVGCOMMAND structure. */
+        gcmkERR_BREAK(gckOS_Allocate(
+            Kernel->os,
+            gcmSIZEOF(struct _gckVGCOMMAND),
+            (gctPOINTER *) &command
+            ));
+
+        /* Initialize the object. */
+        command->object.type = gcvOBJ_COMMAND;
+
+        /* Set the object pointers. */
+        command->kernel      = Kernel;
+        command->os          = Kernel->os;
+        command->hardware    = Kernel->hardware;
+
+        /* Reset pointers. */
+        command->queue       = gcvNULL;
+        command->queueMutex  = gcvNULL;
+        command->taskMutex   = gcvNULL;
+        command->commitMutex = gcvNULL;
+
+        /* Reset context states. */
+        command->contextCounter = 0;
+        command->currentContext = 0;
+
+        /* Enable command buffer dumping. */
+        command->enableDumping = gcvTRUE;
+
+        /* Set features. */
+        command->fe20 = Kernel->hardware->fe20;
+        command->vg20 = Kernel->hardware->vg20;
+        command->vg21 = Kernel->hardware->vg21;
+
+        /* Reset task table .*/
+        gcmkVERIFY_OK(gckOS_ZeroMemory(
+            command->taskTable, gcmSIZEOF(command->taskTable)
+            ));
+
+        /* Query command buffer attributes. */
+        gcmkERR_BREAK(gckVGCOMMAND_InitializeInfo(command));
+
+        /* Create the control mutexes. */
+        gcmkERR_BREAK(gckOS_CreateMutex(Kernel->os, &command->queueMutex));
+        gcmkERR_BREAK(gckOS_CreateMutex(Kernel->os, &command->taskMutex));
+        gcmkERR_BREAK(gckOS_CreateMutex(Kernel->os, &command->commitMutex));
+
+
+        /***********************************************************************
+        ** Command queue initialization.
+        */
+
+        /* Allocate the command queue. */
+        gcmkERR_BREAK(gckOS_Allocate(
+            Kernel->os,
+            QueueSize,
+            (gctPOINTER *) &command->queue
+            ));
+
+        /* Initialize the command queue. */
+        queue = command->queue;
+
+        queue->size    = QueueSize - gcmSIZEOF(gcsKERNEL_QUEUE_HEADER);
+        queue->pending = 0;
+        queue->next    = queue;
+
+        command->queueHead  =
+        command->queueTail  =
+        command->mergeQueue = command->queue;
+
+        command->queueOverflow = 0;
+
+
+        /***********************************************************************
+        ** Enable TS overflow interrupt.
+        */
+
+        gcmkERR_BREAK(gckVGINTERRUPT_Enable(
+            Kernel->interrupt,
+            &command->info.tsOverflowInt,
+            _EventHandler_TSOverflow
+            ));
+
+        /* Mask out the interrupt. */
+        Kernel->hardware->eventMask &= ~(1 << command->info.tsOverflowInt);
+
+
+        /***********************************************************************
+        ** Enable Bus Error interrupt.
+        */
+
+        /* Hardwired to bit 31. */
+        command->busErrorInt = 31;
+
+        /* Enable the interrupt. */
+        gcmkERR_BREAK(gckVGINTERRUPT_Enable(
+            Kernel->interrupt,
+            &command->busErrorInt,
+            _EventHandler_BusError
+            ));
+
+
+        /***********************************************************************
+        ** Task management initialization.
+        */
+
+        command->taskStorage            = gcvNULL;
+        command->taskStorageGranularity = TaskGranularity;
+        command->taskStorageUsable      = TaskGranularity - gcmSIZEOF(gcsTASK_STORAGE);
+
+        command->taskFreeHead = gcvNULL;
+        command->taskFreeTail = gcvNULL;
+
+        /* Enable block handlers. */
+        for (i = 0; i < gcmCOUNTOF(_blockHandlers); i += 1)
+        {
+            /* Get the target hardware block. */
+            gceBLOCK block = _blockHandlers[i].block;
+
+            /* Get the interrupt array entry. */
+            gcsBLOCK_TASK_ENTRY_PTR entry = &command->taskTable[block];
+
+            /* Determine the interrupt value index. */
+            gctUINT index = entry->interruptCount;
+
+            /* Create the block semaphore. */
+            if (entry->interruptSemaphore == gcvNULL)
+            {
+                gcmkERR_BREAK(gckOS_CreateSemaphoreVG(
+                    command->os, &entry->interruptSemaphore
+                    ));
+            }
+
+            /* Enable auto-detection. */
+            entry->interruptArray[index] = -1;
+
+            /* Enable interrupt for the block. */
+            gcmkERR_BREAK(gckVGINTERRUPT_Enable(
+                Kernel->interrupt,
+                &entry->interruptArray[index],
+                _blockHandlers[i].handler
+                ));
+
+            /* Update the number of registered interrupts. */
+            entry->interruptCount += 1;
+
+            /* Inrement the semaphore to allow the usage of the registered
+               interrupt. */
+            gcmkERR_BREAK(gckOS_IncrementSemaphore(
+                command->os, entry->interruptSemaphore
+                ));
+
+        }
+
+        /* Error? */
+        if (gcmkIS_ERROR(status))
+        {
+            break;
+        }
+
+        /* Get the FE interrupt. */
+        command->info.feBufferInt
+            = command->taskTable[gcvBLOCK_COMMAND].interruptArray[0];
+
+        /* Return gckVGCOMMAND object pointer. */
+        *Command = command;
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    /* Roll back. */
+    if (command != gcvNULL)
+    {
+        /* Disable block handlers. */
+        for (i = 0; i < gcvBLOCK_COUNT; i += 1)
+        {
+            /* Get the task table entry. */
+            gcsBLOCK_TASK_ENTRY_PTR entry = &command->taskTable[i];
+
+            /* Destroy the semaphore. */
+            if (entry->interruptSemaphore != gcvNULL)
+            {
+                gcmkCHECK_STATUS(gckOS_DestroySemaphore(
+                    command->os, entry->interruptSemaphore
+                    ));
+            }
+
+            /* Disable all enabled interrupts. */
+            for (j = 0; j < entry->interruptCount; j += 1)
+            {
+                /* Must be a valid value. */
+                gcmkASSERT(entry->interruptArray[j] >= 0);
+                gcmkASSERT(entry->interruptArray[j] <= 31);
+
+                /* Disable the interrupt. */
+                gcmkCHECK_STATUS(gckVGINTERRUPT_Disable(
+                    Kernel->interrupt,
+                    entry->interruptArray[j]
+                    ));
+            }
+        }
+
+        /* Disable the bus error interrupt. */
+        gcmkCHECK_STATUS(gckVGINTERRUPT_Disable(
+            Kernel->interrupt,
+            command->busErrorInt
+            ));
+
+        /* Disable TS overflow interrupt. */
+        if (command->info.tsOverflowInt != -1)
+        {
+            gcmkCHECK_STATUS(gckVGINTERRUPT_Disable(
+                Kernel->interrupt,
+                command->info.tsOverflowInt
+                ));
+        }
+
+        /* Delete the commit mutex. */
+        if (command->commitMutex != gcvNULL)
+        {
+            gcmkCHECK_STATUS(gckOS_DeleteMutex(
+                Kernel->os, command->commitMutex
+                ));
+        }
+
+        /* Delete the command queue mutex. */
+        if (command->taskMutex != gcvNULL)
+        {
+            gcmkCHECK_STATUS(gckOS_DeleteMutex(
+                Kernel->os, command->taskMutex
+                ));
+        }
+
+        /* Delete the command queue mutex. */
+        if (command->queueMutex != gcvNULL)
+        {
+            gcmkCHECK_STATUS(gckOS_DeleteMutex(
+                Kernel->os, command->queueMutex
+                ));
+        }
+
+        /* Delete the command queue. */
+        if (command->queue != gcvNULL)
+        {
+            gcmkCHECK_STATUS(gckOS_Free(
+                Kernel->os, command->queue
+                ));
+        }
+
+        /* Free the gckVGCOMMAND structure. */
+        gcmkCHECK_STATUS(gckOS_Free(
+            Kernel->os, command
+            ));
+    }
+
+    gcmkFOOTER();
+    /* Return the error. */
+    return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_Destroy(
+    OUT gckVGCOMMAND Command
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    do
+    {
+        gctUINT i;
+        gcsTASK_STORAGE_PTR nextStorage;
+
+        if (Command->queueHead != gcvNULL)
+        {
+            /* Wait until the head becomes idle. */
+            gcmkERR_BREAK(_WaitForIdle(Command, Command->queueHead));
+        }
+
+        /* Disable block handlers. */
+        for (i = 0; i < gcvBLOCK_COUNT; i += 1)
+        {
+            /* Get the interrupt array entry. */
+            gcsBLOCK_TASK_ENTRY_PTR entry = &Command->taskTable[i];
+
+            /* Determine the index of the last interrupt in the array. */
+            gctINT index = entry->interruptCount - 1;
+
+            /* Destroy the semaphore. */
+            if (entry->interruptSemaphore != gcvNULL)
+            {
+                gcmkERR_BREAK(gckOS_DestroySemaphore(
+                    Command->os, entry->interruptSemaphore
+                    ));
+            }
+
+            /* Disable all enabled interrupts. */
+            while (index >= 0)
+            {
+                /* Must be a valid value. */
+                gcmkASSERT(entry->interruptArray[index] >= 0);
+                gcmkASSERT(entry->interruptArray[index] <= 31);
+
+                /* Disable the interrupt. */
+                gcmkERR_BREAK(gckVGINTERRUPT_Disable(
+                    Command->kernel->interrupt,
+                    entry->interruptArray[index]
+                    ));
+
+                /* Update to the next interrupt. */
+                index                 -= 1;
+                entry->interruptCount -= 1;
+            }
+
+            /* Error? */
+            if (gcmkIS_ERROR(status))
+            {
+                break;
+            }
+        }
+
+        /* Error? */
+        if (gcmkIS_ERROR(status))
+        {
+            break;
+        }
+
+        /* Disable the bus error interrupt. */
+        gcmkERR_BREAK(gckVGINTERRUPT_Disable(
+            Command->kernel->interrupt,
+            Command->busErrorInt
+            ));
+
+        /* Disable TS overflow interrupt. */
+        if (Command->info.tsOverflowInt != -1)
+        {
+            gcmkERR_BREAK(gckVGINTERRUPT_Disable(
+                Command->kernel->interrupt,
+                Command->info.tsOverflowInt
+                ));
+
+            Command->info.tsOverflowInt = -1;
+        }
+
+        /* Delete the commit mutex. */
+        if (Command->commitMutex != gcvNULL)
+        {
+            gcmkERR_BREAK(gckOS_DeleteMutex(
+                Command->os, Command->commitMutex
+                ));
+
+            Command->commitMutex = gcvNULL;
+        }
+
+        /* Delete the command queue mutex. */
+        if (Command->taskMutex != gcvNULL)
+        {
+            gcmkERR_BREAK(gckOS_DeleteMutex(
+                Command->os, Command->taskMutex
+                ));
+
+            Command->taskMutex = gcvNULL;
+        }
+
+        /* Delete the command queue mutex. */
+        if (Command->queueMutex != gcvNULL)
+        {
+            gcmkERR_BREAK(gckOS_DeleteMutex(
+                Command->os, Command->queueMutex
+                ));
+
+            Command->queueMutex = gcvNULL;
+        }
+
+        if (Command->queue != gcvNULL)
+        {
+            /* Delete the command queue. */
+            gcmkERR_BREAK(gckOS_Free(
+                Command->os, Command->queue
+                ));
+        }
+
+        /* Destroy all allocated buffers. */
+        while (Command->taskStorage)
+        {
+            /* Copy the buffer pointer. */
+            nextStorage = Command->taskStorage->next;
+
+            /* Free the current container. */
+            gcmkERR_BREAK(gckOS_Free(
+                Command->os, Command->taskStorage
+                ));
+
+            /* Advance to the next one. */
+            Command->taskStorage = nextStorage;
+        }
+
+        /* Error? */
+        if (gcmkIS_ERROR(status))
+        {
+            break;
+        }
+
+        /* Mark the object as unknown. */
+        Command->object.type = gcvOBJ_UNKNOWN;
+
+        /* Free the gckVGCOMMAND structure. */
+        gcmkERR_BREAK(gckOS_Free(Command->os, Command));
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    /* Restore the object type if failed. */
+    Command->object.type = gcvOBJ_COMMAND;
+
+    gcmkFOOTER();
+    /* Return the error. */
+    return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_QueryCommandBuffer(
+    IN gckVGCOMMAND Command,
+    OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+    )
+{
+    gcmkHEADER_ARG("Command=0x%x Information=0x%x", Command, Information);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+    gcmkVERIFY_ARGUMENT(Information != gcvNULL);
+
+    /* Copy the information. */
+    gcmkVERIFY_OK(gckOS_MemCopy(
+        Information, &Command->info, sizeof(gcsCOMMAND_BUFFER_INFO)
+        ));
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVGCOMMAND_Allocate(
+    IN gckVGCOMMAND Command,
+    IN gctSIZE_T Size,
+    OUT gcsCMDBUFFER_PTR * CommandBuffer,
+    OUT gctPOINTER * Data
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Command=0x%x Size=0x%x CommandBuffer=0x%x Data=0x%x",
+        Command, Size, CommandBuffer, Data);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+    gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+    do
+    {
+        /* Allocate the buffer. */
+        gcmkERR_BREAK(_AllocateCommandBuffer(Command, Size, CommandBuffer));
+
+        /* Determine the data pointer. */
+        * Data = (gctUINT8_PTR) CommandBuffer + (* CommandBuffer)->bufferOffset;
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return status. */
+    return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_Free(
+    IN gckVGCOMMAND Command,
+    IN gcsCMDBUFFER_PTR CommandBuffer
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x",
+        Command, CommandBuffer);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+    gcmkVERIFY_ARGUMENT(CommandBuffer != gcvNULL);
+
+    /* Free command buffer. */
+    status = _FreeCommandBuffer(Command->kernel, CommandBuffer);
+
+    gcmkFOOTER();
+    /* Return status. */
+    return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_Execute(
+    IN gckVGCOMMAND Command,
+    IN gcsCMDBUFFER_PTR CommandBuffer
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x",
+        Command, CommandBuffer);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+    gcmkVERIFY_ARGUMENT(CommandBuffer != gcvNULL);
+
+    do
+    {
+        gctUINT queueLength;
+        gcsKERNEL_CMDQUEUE_PTR kernelEntry;
+
+        /* Lock the current queue. */
+        gcmkERR_BREAK(_LockCurrentQueue(
+            Command, &kernelEntry, &queueLength
+            ));
+
+        /* Set the buffer. */
+        kernelEntry->commandBuffer = CommandBuffer;
+        kernelEntry->handler = _FreeKernelCommandBuffer;
+
+        /* Lock the current queue. */
+        gcmkERR_BREAK(_UnlockCurrentQueue(
+            Command, 1
+            ));
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return status. */
+    return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_Commit(
+    IN gckVGCOMMAND Command,
+    IN gcsVGCONTEXT_PTR Context,
+    IN gcsVGCMDQUEUE_PTR Queue,
+    IN gctUINT EntryCount,
+    IN gcsTASK_MASTER_TABLE_PTR TaskTable
+    )
+{
+    /*
+        The first buffer is executed through a direct gckVGHARDWARE_Execute call,
+        therefore only an update is needed after the execution is over. All
+        consequent buffers need to be executed upon the first update call from
+        the FE interrupt handler.
+    */
+
+    static gcsQUEUE_UPDATE_CONTROL _dynamicBuffer[] =
+    {
+        {
+            _UpdateDynamicCommandBuffer,
+            _UpdateDynamicCommandBuffer,
+            _UpdateLastDynamicCommandBuffer,
+            _UpdateLastDynamicCommandBuffer
+        },
+        {
+            _ExecuteDynamicCommandBuffer,
+            _UpdateDynamicCommandBuffer,
+            _ExecuteLastDynamicCommandBuffer,
+            _UpdateLastDynamicCommandBuffer
+        }
+    };
+
+    static gcsQUEUE_UPDATE_CONTROL _staticBuffer[] =
+    {
+        {
+            _UpdateStaticCommandBuffer,
+            _UpdateStaticCommandBuffer,
+            _UpdateLastStaticCommandBuffer,
+            _UpdateLastStaticCommandBuffer
+        },
+        {
+            _ExecuteStaticCommandBuffer,
+            _UpdateStaticCommandBuffer,
+            _ExecuteLastStaticCommandBuffer,
+            _UpdateLastStaticCommandBuffer
+        }
+    };
+
+    gceSTATUS status, last;
+
+    gcmkHEADER_ARG("Command=0x%x Context=0x%x Queue=0x%x EntryCount=0x%x TaskTable=0x%x",
+        Command, Context, Queue, EntryCount, TaskTable);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+    gcmkVERIFY_ARGUMENT(Context != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
+    gcmkVERIFY_ARGUMENT(EntryCount > 1);
+
+    do
+    {
+        gctBOOL haveFETasks;
+        gctUINT queueSize;
+        gcsVGCMDQUEUE_PTR mappedQueue;
+        gcsVGCMDQUEUE_PTR userEntry;
+        gcsKERNEL_CMDQUEUE_PTR kernelEntry;
+        gcsQUEUE_UPDATE_CONTROL_PTR queueControl;
+        gctUINT currentLength;
+        gctUINT queueLength;
+        gctUINT entriesQueued;
+        gctUINT8_PTR previousEnd;
+        gctBOOL previousDynamic;
+        gctBOOL previousExecuted;
+        gctUINT controlIndex;
+
+        /* Acquire the mutex. */
+        gcmkERR_BREAK(gckOS_AcquireMutex(
+            Command->os,
+            Command->commitMutex,
+            gcvINFINITE
+            ));
+
+        do
+        {
+            /* Assign a context ID if not yet assigned. */
+            if (Context->id == 0)
+            {
+                /* Assign the next context number. */
+                Context->id = ++ Command->contextCounter;
+
+                /* See if we overflowed. */
+                if (Command->contextCounter == 0)
+                {
+                    /* We actually did overflow, wow... */
+                    status = gcvSTATUS_OUT_OF_RESOURCES;
+                    break;
+                }
+            }
+
+            /* The first entry in the queue is always the context buffer.
+               Verify whether the user context is the same as the current
+               context and if that's the case, skip the first entry. */
+            if (Context->id == Command->currentContext)
+            {
+                /* Same context as before, skip the first entry. */
+                EntryCount -= 1;
+                Queue      += 1;
+
+                /* Set the signal to avoid user waiting. */
+                gcmkERR_BREAK(gckOS_UserSignal(
+                    Command->os, Context->signal, Context->process
+                    ));
+            }
+            else
+            {
+                /* Different user context - keep the first entry.
+                   Set the user context as the current one. */
+                Command->currentContext = Context->id;
+            }
+
+            /* Reset pointers. */
+            queueControl = gcvNULL;
+            previousEnd  = gcvNULL;
+
+            /* Determine whether there are FE tasks to be performed. */
+            haveFETasks = (TaskTable->table[gcvBLOCK_COMMAND].head != gcvNULL);
+
+            /* Determine the size of the queue. */
+            queueSize = EntryCount * gcmSIZEOF(gcsVGCMDQUEUE);
+
+            /* Map the command queue into the kernel space. */
+            gcmkERR_BREAK(gckOS_MapUserPointer(
+                Command->os,
+                Queue,
+                queueSize,
+                (gctPOINTER *) &mappedQueue
+                ));
+
+            /* Set the first entry. */
+            userEntry = mappedQueue;
+
+            /* Process the command queue. */
+            while (EntryCount)
+            {
+                /* Lock the current queue. */
+                gcmkERR_BREAK(_LockCurrentQueue(
+                    Command, &kernelEntry, &queueLength
+                    ));
+
+                /* Determine the number of entries to process. */
+                currentLength = (queueLength < EntryCount)
+                    ? queueLength
+                    : EntryCount;
+
+                /* Update the number of the entries left to process. */
+                EntryCount -= currentLength;
+
+                /* Reset previous flags. */
+                previousDynamic  = gcvFALSE;
+                previousExecuted = gcvFALSE;
+
+                /* Set the initial control index. */
+                controlIndex = 0;
+
+                /* Process entries. */
+                for (entriesQueued = 0; entriesQueued < currentLength; entriesQueued += 1)
+                {
+                    /* Get the kernel pointer to the command buffer header. */
+                    gcsCMDBUFFER_PTR commandBuffer;
+                    gcmkERR_BREAK(_ConvertUserCommandBufferPointer(
+                        Command,
+                        userEntry->commandBuffer,
+                        &commandBuffer
+                        ));
+
+                    /* Is it a dynamic command buffer? */
+                    if (userEntry->dynamic)
+                    {
+                        /* Select dynamic buffer control functions. */
+                        queueControl = &_dynamicBuffer[controlIndex];
+                    }
+
+                    /* No, a static command buffer. */
+                    else
+                    {
+                        /* Select static buffer control functions. */
+                        queueControl = &_staticBuffer[controlIndex];
+                    }
+
+                    /* Set the command buffer pointer to the entry. */
+                    kernelEntry->commandBuffer = commandBuffer;
+
+                    /* If the previous entry was a dynamic command buffer,
+                       link it to the current. */
+                    if (previousDynamic)
+                    {
+                        gcmkERR_BREAK(gckVGCOMMAND_FetchCommand(
+                            Command,
+                            previousEnd,
+                            commandBuffer->address,
+                            commandBuffer->dataCount,
+                            gcvNULL
+                            ));
+
+                        /* The buffer will be auto-executed, only need to
+                           update it after it has been executed. */
+                        kernelEntry->handler = queueControl->update;
+
+                        /* The buffer is only being updated. */
+                        previousExecuted = gcvFALSE;
+                    }
+                    else
+                    {
+                        /* Set the buffer up for execution. */
+                        kernelEntry->handler = queueControl->execute;
+
+                        /* The buffer is being updated. */
+                        previousExecuted = gcvTRUE;
+                    }
+
+                    /* The current buffer's END command becomes the last END. */
+                    previousEnd
+                        = ((gctUINT8_PTR) commandBuffer)
+                        + commandBuffer->bufferOffset
+                        + commandBuffer->dataCount * Command->info.commandAlignment
+                        - Command->info.staticTailSize;
+
+                    /* Update the last entry info. */
+                    previousDynamic = userEntry->dynamic;
+
+                    /* Advance entries. */
+                    userEntry   += 1;
+                    kernelEntry += 1;
+
+                    /* Update the control index. */
+                    controlIndex = 1;
+                }
+
+                /* If the previous entry was a dynamic command buffer,
+                   terminate it with an END. */
+                if (previousDynamic)
+                {
+                    gcmkERR_BREAK(gckVGCOMMAND_EndCommand(
+                        Command,
+                        previousEnd,
+                        Command->info.feBufferInt,
+                        gcvNULL
+                        ));
+                }
+
+                /* Last buffer? */
+                if (EntryCount == 0)
+                {
+                    /* Modify the last command buffer's routines to handle
+                       tasks if any.*/
+                    if (haveFETasks)
+                    {
+                        if (previousExecuted)
+                        {
+                            kernelEntry[-1].handler = queueControl->lastExecute;
+                        }
+                        else
+                        {
+                            kernelEntry[-1].handler = queueControl->lastUpdate;
+                        }
+                    }
+
+                    /* Release the mutex. */
+                    gcmkERR_BREAK(gckOS_ReleaseMutex(
+                        Command->os,
+                        Command->queueMutex
+                        ));
+                    /* Schedule tasks. */
+                    gcmkERR_BREAK(_ScheduleTasks(Command, TaskTable, previousEnd));
+
+                    /* Acquire the mutex. */
+                    gcmkERR_BREAK(gckOS_AcquireMutex(
+                        Command->os,
+                        Command->queueMutex,
+                        gcvINFINITE
+                        ));
+                }
+
+                /* Unkock and schedule the current queue for execution. */
+                gcmkERR_BREAK(_UnlockCurrentQueue(
+                    Command, currentLength
+                    ));
+            }
+
+            /* Unmap the user command buffer. */
+            gcmkERR_BREAK(gckOS_UnmapUserPointer(
+                Command->os,
+                Queue,
+                queueSize,
+                mappedQueue
+                ));
+        }
+        while (gcvFALSE);
+
+        /* Release the mutex. */
+        gcmkCHECK_STATUS(gckOS_ReleaseMutex(
+            Command->os,
+            Command->commitMutex
+            ));
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return status. */
+    return status;
+}
+
+#endif /* gcdENABLE_VG */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
new file mode 100644 (file)
index 0000000..a394b8e
--- /dev/null
@@ -0,0 +1,1425 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE    gcvZONE_DATABASE
+
+/*******************************************************************************
+***** Private fuctions ********************************************************/
+
+/*******************************************************************************
+**  gckKERNEL_NewDatabase
+**
+**  Create a new database structure and insert it to the head of the hash list.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gctUINT32 ProcessID
+**          ProcessID that identifies the database.
+**
+**  OUTPUT:
+**
+**      gcsDATABASE_PTR * Database
+**          Pointer to a variable receiving the database structure pointer on
+**          success.
+*/
+static gceSTATUS
+gckKERNEL_NewDatabase(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    OUT gcsDATABASE_PTR * Database
+    )
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database;
+    gctBOOL acquired = gcvFALSE;
+    gctSIZE_T slot;
+
+    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+    /* Acquire the database mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    if (Kernel->db->freeDatabase != gcvNULL)
+    {
+        /* Allocate a database from the free list. */
+        database             = Kernel->db->freeDatabase;
+        Kernel->db->freeDatabase = database->next;
+    }
+    else
+    {
+        gctPOINTER pointer = gcvNULL;
+
+        /* Allocate a new database from the heap. */
+        gcmkONERROR(gckOS_Allocate(Kernel->os,
+                                   gcmSIZEOF(gcsDATABASE),
+                                   &pointer));
+
+        database = pointer;
+    }
+
+    /* Compute the hash for the database. */
+    slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
+
+    /* Insert the database into the hash. */
+    database->next   = Kernel->db->db[slot];
+    Kernel->db->db[slot] = database;
+
+    /* Save the hash slot. */
+    database->slot = slot;
+
+    /* Release the database mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+    /* Return the database. */
+    *Database = database;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Database=0x%x", *Database);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the database mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckKERNEL_FindDatabase
+**
+**  Find a database identified by a process ID and move it to the head of the
+**  hash list.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gctUINT32 ProcessID
+**          ProcessID that identifies the database.
+**
+**      gctBOOL LastProcessID
+**          gcvTRUE if searching for the last known process ID.  gcvFALSE if
+**          we need to search for the process ID specified by the ProcessID
+**          argument.
+**
+**  OUTPUT:
+**
+**      gcsDATABASE_PTR * Database
+**          Pointer to a variable receiving the database structure pointer on
+**          success.
+*/
+static gceSTATUS
+gckKERNEL_FindDatabase(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gctBOOL LastProcessID,
+    OUT gcsDATABASE_PTR * Database
+    )
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database, previous;
+    gctSIZE_T slot;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d LastProcessID=%d",
+                   Kernel, ProcessID, LastProcessID);
+
+    /* Compute the hash for the database. */
+    slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
+
+    /* Acquire the database mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Check whether we are getting the last known database. */
+    if (LastProcessID)
+    {
+        /* Use last database. */
+        database = Kernel->db->lastDatabase;
+
+        if (database == gcvNULL)
+        {
+            /* Database not found. */
+            gcmkONERROR(gcvSTATUS_INVALID_DATA);
+        }
+    }
+    else
+    {
+        /* Walk the hash list. */
+        for (previous = gcvNULL, database = Kernel->db->db[slot];
+             database != gcvNULL;
+             database = database->next)
+        {
+            if (database->processID == ProcessID)
+            {
+                /* Found it! */
+                break;
+            }
+
+            previous = database;
+        }
+
+        if (database == gcvNULL)
+        {
+            /* Database not found. */
+            gcmkONERROR(gcvSTATUS_INVALID_DATA);
+        }
+
+        if (previous != gcvNULL)
+        {
+            /* Move database to the head of the hash list. */
+            previous->next   = database->next;
+            database->next   = Kernel->db->db[slot];
+            Kernel->db->db[slot] = database;
+        }
+    }
+
+    /* Release the database mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+    /* Return the database. */
+    *Database = database;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Database=0x%x", *Database);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the database mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckKERNEL_DeleteDatabase
+**
+**  Remove a database from the hash list and delete its structure.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gcsDATABASE_PTR Database
+**          Pointer to the database structure to remove.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+static gceSTATUS
+gckKERNEL_DeleteDatabase(
+    IN gckKERNEL Kernel,
+    IN gcsDATABASE_PTR Database
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gcsDATABASE_PTR database;
+
+    gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);
+
+    /* Acquire the database mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Check slot value. */
+    gcmkVERIFY_ARGUMENT(Database->slot < gcmCOUNTOF(Kernel->db->db));
+
+    if (Database->slot < gcmCOUNTOF(Kernel->db->db))
+    {
+        /* Check if database if the head of the hash list. */
+        if (Kernel->db->db[Database->slot] == Database)
+        {
+            /* Remove the database from the hash list. */
+            Kernel->db->db[Database->slot] = Database->next;
+        }
+        else
+        {
+            /* Walk the has list to find the database. */
+            for (database = Kernel->db->db[Database->slot];
+                 database != gcvNULL;
+                 database = database->next
+            )
+            {
+                /* Check if the next list entry is this database. */
+                if (database->next == Database)
+                {
+                    /* Remove the database from the hash list. */
+                    database->next = Database->next;
+                    break;
+                }
+            }
+
+            if (database == gcvNULL)
+            {
+                /* Ouch!  Something got corrupted. */
+                gcmkONERROR(gcvSTATUS_INVALID_DATA);
+            }
+        }
+    }
+
+    if (Kernel->db->lastDatabase != gcvNULL)
+    {
+        /* Insert database to the free list. */
+        Kernel->db->lastDatabase->next = Kernel->db->freeDatabase;
+        Kernel->db->freeDatabase       = Kernel->db->lastDatabase;
+    }
+
+    /* Keep database as the last database. */
+    Kernel->db->lastDatabase = Database;
+
+    /* Release the database mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the database mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckKERNEL_NewRecord
+**
+**  Create a new database record structure and insert it to the head of the
+**  database.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gcsDATABASE_PTR Database
+**          Pointer to a database structure.
+**
+**  OUTPUT:
+**
+**      gcsDATABASE_RECORD_PTR * Record
+**          Pointer to a variable receiving the database record structure
+**          pointer on success.
+*/
+static gceSTATUS
+gckKERNEL_NewRecord(
+    IN gckKERNEL Kernel,
+    IN gcsDATABASE_PTR Database,
+    OUT gcsDATABASE_RECORD_PTR * Record
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gcsDATABASE_RECORD_PTR record = gcvNULL;
+
+    gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);
+
+    /* Acquire the database mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    if (Kernel->db->freeRecord != gcvNULL)
+    {
+        /* Allocate the record from the free list. */
+        record             = Kernel->db->freeRecord;
+        Kernel->db->freeRecord = record->next;
+    }
+    else
+    {
+        gctPOINTER pointer = gcvNULL;
+
+        /* Allocate the record from the heap. */
+        gcmkONERROR(gckOS_Allocate(Kernel->os,
+                                   gcmSIZEOF(gcsDATABASE_RECORD),
+                                   &pointer));
+
+        record = pointer;
+    }
+
+    /* Insert the record in the database. */
+    record->next   = Database->list;
+    Database->list = record;
+
+    /* Release the database mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+    /* Return the record. */
+    *Record = record;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Record=0x%x", *Record);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the database mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+    }
+    if (record != gcvNULL)
+    {
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, record));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckKERNEL_DeleteRecord
+**
+**  Remove a database record from the database and delete its structure.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gcsDATABASE_PTR Database
+**          Pointer to a database structure.
+**
+**      gceDATABASE_TYPE Type
+**          Type of the record to remove.
+**
+**      gctPOINTER Data
+**          Data of the record to remove.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T_PTR Bytes
+**          Pointer to a variable that receives the size of the record deleted.
+**          Can be gcvNULL if the size is not required.
+*/
+static gceSTATUS
+gckKERNEL_DeleteRecord(
+    IN gckKERNEL Kernel,
+    IN gcsDATABASE_PTR Database,
+    IN gceDATABASE_TYPE Type,
+    IN gctPOINTER Data,
+    OUT gctSIZE_T_PTR Bytes OPTIONAL
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gcsDATABASE_RECORD_PTR record, previous;
+
+    gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
+                   Kernel, Database, Type, Data);
+
+    /* Acquire the database mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Scan the database for this record. */
+    for (record = Database->list, previous = gcvNULL;
+         record != gcvNULL;
+         record = record->next
+    )
+    {
+        if ((record->type == Type)
+        &&  (record->data == Data)
+        )
+        {
+            /* Found it! */
+            break;
+        }
+
+        previous = record;
+    }
+
+    if (record == gcvNULL)
+    {
+        /* Ouch!  This record is not found? */
+        gcmkONERROR(gcvSTATUS_INVALID_DATA);
+    }
+
+    if (Bytes != gcvNULL)
+    {
+        /* Return size of record. */
+        *Bytes = record->bytes;
+    }
+
+    /* Remove record from database. */
+    if (previous == gcvNULL)
+    {
+        Database->list = record->next;
+    }
+    else
+    {
+        previous->next = record->next;
+    }
+
+    /* Insert record in free list. */
+    record->next       = Kernel->db->freeRecord;
+    Kernel->db->freeRecord = record;
+
+    /* Release the database mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the database mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckKERNEL_FindRecord
+**
+**  Find a database record from the database.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gcsDATABASE_PTR Database
+**          Pointer to a database structure.
+**
+**      gceDATABASE_TYPE Type
+**          Type of the record to remove.
+**
+**      gctPOINTER Data
+**          Data of the record to remove.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T_PTR Bytes
+**          Pointer to a variable that receives the size of the record deleted.
+**          Can be gcvNULL if the size is not required.
+*/
+static gceSTATUS
+gckKERNEL_FindRecord(
+    IN gckKERNEL Kernel,
+    IN gcsDATABASE_PTR Database,
+    IN gceDATABASE_TYPE Type,
+    IN gctPOINTER Data,
+    OUT gcsDATABASE_RECORD_PTR Record
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gcsDATABASE_RECORD_PTR record, previous;
+
+    gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
+                   Kernel, Database, Type, Data);
+
+    /* Acquire the database mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Scan the database for this record. */
+    for (record = Database->list, previous = gcvNULL;
+         record != gcvNULL;
+         record = record->next
+    )
+    {
+        if ((record->type == Type)
+        &&  (record->data == Data)
+        )
+        {
+            /* Found it! */
+            break;
+        }
+
+        previous = record;
+    }
+
+    if (record == gcvNULL)
+    {
+        /* Ouch!  This record is not found? */
+        gcmkONERROR(gcvSTATUS_INVALID_DATA);
+    }
+
+    if (Record != gcvNULL)
+    {
+        /* Return information of record. */
+        gcmkONERROR(
+            gckOS_MemCopy(Record, record, sizeof(gcsDATABASE_RECORD)));
+    }
+
+    /* Release the database mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+    /* Success. */
+    gcmkFOOTER_ARG("Record=0x%x", Record);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the database mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+
+/*******************************************************************************
+***** Public API **************************************************************/
+
+/*******************************************************************************
+**  gckKERNEL_CreateProcessDB
+**
+**  Create a new process database.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gctUINT32 ProcessID
+**          Process ID used to identify the database.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckKERNEL_CreateProcessDB(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID
+    )
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database = gcvNULL;
+
+    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    /* Create a new database. */
+    gcmkONERROR(gckKERNEL_NewDatabase(Kernel, ProcessID, &database));
+
+    /* Initialize the database. */
+    database->processID             = ProcessID;
+    database->vidMem.bytes          = 0;
+    database->vidMem.maxBytes       = 0;
+    database->vidMem.totalBytes     = 0;
+    database->nonPaged.bytes        = 0;
+    database->nonPaged.maxBytes     = 0;
+    database->nonPaged.totalBytes   = 0;
+    database->contiguous.bytes      = 0;
+    database->contiguous.maxBytes   = 0;
+    database->contiguous.totalBytes = 0;
+    database->mapMemory.bytes          = 0;
+    database->mapMemory.maxBytes       = 0;
+    database->mapMemory.totalBytes     = 0;
+    database->mapUserMemory.bytes      = 0;
+    database->mapUserMemory.maxBytes   = 0;
+    database->mapUserMemory.totalBytes = 0;
+    database->list                  = gcvNULL;
+
+#if gcdSECURE_USER
+    {
+        gctINT slot;
+        gcskSECURE_CACHE * cache = &database->cache;
+
+        /* Setup the linked list of cache nodes. */
+        for (slot = 1; slot <= gcdSECURE_CACHE_SLOTS; ++slot)
+        {
+            cache->cache[slot].logical = gcvNULL;
+
+#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
+            cache->cache[slot].prev = &cache->cache[slot - 1];
+            cache->cache[slot].next = &cache->cache[slot + 1];
+#   endif
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+            cache->cache[slot].nextHash = gcvNULL;
+            cache->cache[slot].prevHash = gcvNULL;
+#   endif
+        }
+
+#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
+        /* Setup the head and tail of the cache. */
+        cache->cache[0].next    = &cache->cache[1];
+        cache->cache[0].prev    = &cache->cache[gcdSECURE_CACHE_SLOTS];
+        cache->cache[0].logical = gcvNULL;
+
+        /* Fix up the head and tail pointers. */
+        cache->cache[0].next->prev = &cache->cache[0];
+        cache->cache[0].prev->next = &cache->cache[0];
+#   endif
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+        /* Zero out the hash table. */
+        for (slot = 0; slot < gcmCOUNTOF(cache->hash); ++slot)
+        {
+            cache->hash[slot].logical  = gcvNULL;
+            cache->hash[slot].nextHash = gcvNULL;
+        }
+#   endif
+
+        /* Initialize cache index. */
+        cache->cacheIndex = gcvNULL;
+        cache->cacheFree  = 1;
+        cache->cacheStamp = 0;
+    }
+#endif
+
+    /* Reset idle timer. */
+    Kernel->db->lastIdle = 0;
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckKERNEL_AddProcessDB
+**
+**  Add a record to a process database.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gctUINT32 ProcessID
+**          Process ID used to identify the database.
+**
+**      gceDATABASE_TYPE TYPE
+**          Type of the record to add.
+**
+**      gctPOINTER Pointer
+**          Data of the record to add.
+**
+**      gctPHYS_ADDR Physical
+**          Physical address of the record to add.
+**
+**      gctSIZE_T Size
+**          Size of the record to add.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckKERNEL_AddProcessDB(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gceDATABASE_TYPE Type,
+    IN gctPOINTER Pointer,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Size
+    )
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database;
+    gcsDATABASE_RECORD_PTR record = gcvNULL;
+    gcsDATABASE_COUNTERS * count;
+
+    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x "
+                   "Physical=0x%x Size=%lu",
+                   Kernel, ProcessID, Type, Pointer, Physical, Size);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    /* Special case the idle record. */
+    if (Type == gcvDB_IDLE)
+    {
+        gctUINT64 time;
+
+        /* Get the current profile time. */
+        gcmkONERROR(gckOS_GetProfileTick(&time));
+
+        if ((ProcessID == 0) && (Kernel->db->lastIdle != 0))
+        {
+            /* Out of idle, adjust time it was idle. */
+            Kernel->db->idleTime += time - Kernel->db->lastIdle;
+            Kernel->db->lastIdle  = 0;
+        }
+        else if (ProcessID == 1)
+        {
+            /* Save current idle time. */
+            Kernel->db->lastIdle = time;
+        }
+
+#if gcdDYNAMIC_SPEED
+        {
+            /* Test for first call. */
+            if (Kernel->db->lastSlowdown == 0)
+            {
+                /* Save milliseconds. */
+                Kernel->db->lastSlowdown     = time;
+                Kernel->db->lastSlowdownIdle = Kernel->db->idleTime;
+            }
+            else
+            {
+                /* Compute ellapsed time in milliseconds. */
+                gctUINT delta = gckOS_ProfileToMS(time - Kernel->db->lastSlowdown);
+
+                /* Test for end of period. */
+                if (delta >= gcdDYNAMIC_SPEED)
+                {
+                    /* Compute number of idle milliseconds. */
+                    gctUINT idle = gckOS_ProfileToMS(
+                        Kernel->db->idleTime  - Kernel->db->lastSlowdownIdle);
+
+                    /* Broadcast to slow down the GPU. */
+                    gcmkONERROR(gckOS_BroadcastCalibrateSpeed(Kernel->os,
+                                                              Kernel->hardware,
+                                                              idle,
+                                                              delta));
+
+                    /* Save current time. */
+                    Kernel->db->lastSlowdown     = time;
+                    Kernel->db->lastSlowdownIdle = Kernel->db->idleTime;
+                }
+            }
+        }
+#endif
+
+        /* Success. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+
+    /* Find the database. */
+    gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+    /* Create a new record in the database. */
+    gcmkONERROR(gckKERNEL_NewRecord(Kernel, database, &record));
+
+    /* Initialize the record. */
+    record->kernel   = Kernel;
+    record->type     = Type;
+    record->data     = Pointer;
+    record->physical = Physical;
+    record->bytes    = Size;
+
+    /* Get pointer to counters. */
+    switch (Type)
+    {
+    case gcvDB_VIDEO_MEMORY:
+        count = &database->vidMem;
+        break;
+
+    case gcvDB_NON_PAGED:
+        count = &database->nonPaged;
+        break;
+
+    case gcvDB_CONTIGUOUS:
+        count = &database->contiguous;
+        break;
+
+    case gcvDB_MAP_MEMORY:
+        count = &database->mapMemory;
+        break;
+
+    case gcvDB_MAP_USER_MEMORY:
+        count = &database->mapUserMemory;
+        break;
+
+    default:
+        count = gcvNULL;
+        break;
+    }
+
+    if (count != gcvNULL)
+    {
+        /* Adjust counters. */
+        count->totalBytes += Size;
+        count->bytes      += Size;
+
+        if (count->bytes > count->maxBytes)
+        {
+            count->maxBytes = count->bytes;
+        }
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckKERNEL_RemoveProcessDB
+**
+**  Remove a record from a process database.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gctUINT32 ProcessID
+**          Process ID used to identify the database.
+**
+**      gceDATABASE_TYPE TYPE
+**          Type of the record to remove.
+**
+**      gctPOINTER Pointer
+**          Data of the record to remove.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckKERNEL_RemoveProcessDB(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gceDATABASE_TYPE Type,
+    IN gctPOINTER Pointer
+    )
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database;
+    gctSIZE_T bytes = 0;
+
+    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
+                   Kernel, ProcessID, Type, Pointer);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+
+    /* Find the database. */
+    gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+    /* Delete the record. */
+    gcmkONERROR(
+        gckKERNEL_DeleteRecord(Kernel, database, Type, Pointer, &bytes));
+
+    /* Update counters. */
+    switch (Type)
+    {
+    case gcvDB_VIDEO_MEMORY:
+        database->vidMem.bytes -= bytes;
+        break;
+
+    case gcvDB_NON_PAGED:
+        database->nonPaged.bytes -= bytes;
+        break;
+
+    case gcvDB_CONTIGUOUS:
+        database->contiguous.bytes -= bytes;
+        break;
+
+    case gcvDB_MAP_MEMORY:
+        database->mapMemory.bytes -= bytes;
+        break;
+
+    case gcvDB_MAP_USER_MEMORY:
+        database->mapUserMemory.bytes -= bytes;
+        break;
+
+    default:
+        break;
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckKERNEL_FindProcessDB
+**
+**  Find a record from a process database.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gctUINT32 ProcessID
+**          Process ID used to identify the database.
+**
+**      gceDATABASE_TYPE TYPE
+**          Type of the record to remove.
+**
+**      gctPOINTER Pointer
+**          Data of the record to remove.
+**
+**  OUTPUT:
+**
+**      gcsDATABASE_RECORD_PTR Record
+**          Copy of record.
+*/
+gceSTATUS
+gckKERNEL_FindProcessDB(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gctUINT32 ThreadID,
+    IN gceDATABASE_TYPE Type,
+    IN gctPOINTER Pointer,
+    OUT gcsDATABASE_RECORD_PTR Record
+    )
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database;
+
+    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
+                   Kernel, ProcessID, ThreadID, Type, Pointer);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+
+    /* Find the database. */
+    gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+    /* Find the record. */
+    gcmkONERROR(
+        gckKERNEL_FindRecord(Kernel, database, Type, Pointer, Record));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckKERNEL_DestroyProcessDB
+**
+**  Destroy a process database.  If the database contains any records, the data
+**  inside those records will be deleted as well.  This aids in the cleanup if
+**  a process has died unexpectedly or has memory leaks.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gctUINT32 ProcessID
+**          Process ID used to identify the database.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckKERNEL_DestroyProcessDB(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID
+    )
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database;
+    gcsDATABASE_RECORD_PTR record, next;
+    gctBOOL asynchronous;
+
+    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    /* Find the database. */
+    gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+                   "DB(%d): VidMem: total=%lu max=%lu",
+                   ProcessID, database->vidMem.totalBytes,
+                   database->vidMem.maxBytes);
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+                   "DB(%d): NonPaged: total=%lu max=%lu",
+                   ProcessID, database->nonPaged.totalBytes,
+                   database->nonPaged.maxBytes);
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+                   "DB(%d): Contiguous: total=%lu max=%lu",
+                   ProcessID, database->contiguous.totalBytes,
+                   database->contiguous.maxBytes);
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+                   "DB(%d): Idle time=%llu",
+                   ProcessID, Kernel->db->idleTime);
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+                   "DB(%d): Map: total=%lu max=%lu",
+                   ProcessID, database->mapMemory.totalBytes,
+                   database->mapMemory.maxBytes);
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+                   "DB(%d): Map: total=%lu max=%lu",
+                   ProcessID, database->mapUserMemory.totalBytes,
+                   database->mapUserMemory.maxBytes);
+
+    if (database->list != gcvNULL)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+                       "Process %d has entries in its database:",
+                       ProcessID);
+    }
+
+    /* Walk all records. */
+    for (record = database->list; record != gcvNULL; record = next)
+    {
+        /* Next next record. */
+        next = record->next;
+
+        /* Dispatch on record type. */
+        switch (record->type)
+        {
+        case gcvDB_VIDEO_MEMORY:
+            /* Free the video memory. */
+            status = gckVIDMEM_Free(record->data);
+
+            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+                           "DB: VIDEO_MEMORY 0x%x (status=%d)",
+                           record->data, status);
+            break;
+
+        case gcvDB_NON_PAGED:
+            /* Free the non paged memory. */
+            status = gckOS_FreeNonPagedMemory(Kernel->os,
+                                              record->bytes,
+                                              record->physical,
+                                              record->data);
+
+            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+                           "DB: NON_PAGED 0x%x, bytes=%lu (status=%d)",
+                           record->data, record->bytes, status);
+            break;
+
+        case gcvDB_CONTIGUOUS:
+            /* Free the contiguous memory. */
+            status = gckOS_FreeContiguous(Kernel->os,
+                                          record->physical,
+                                          record->data,
+                                          record->bytes);
+
+            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+                           "DB: CONTIGUOUS 0x%x bytes=%lu (status=%d)",
+                           record->data, record->bytes, status);
+            break;
+
+        case gcvDB_SIGNAL:
+#if USE_NEW_LINUX_SIGNAL
+            status = gcvSTATUS_NOT_SUPPORTED;
+#else
+            /* Free the user signal. */
+            status = gckOS_DestroyUserSignal(Kernel->os,
+                                             gcmPTR2INT(record->data));
+#endif /* USE_NEW_LINUX_SIGNAL */
+
+            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+                           "DB: SIGNAL %d (status=%d)",
+                           (gctINT) record->data, status);
+            break;
+
+        case gcvDB_VIDEO_MEMORY_LOCKED:
+            /* Unlock what we still locked */
+            status = gckVIDMEM_Unlock(record->kernel,
+                                      record->data,
+                                      gcvSURF_TYPE_UNKNOWN,
+                                      &asynchronous);
+
+            if (gcmIS_SUCCESS(status) && (gcvTRUE == asynchronous))
+            {
+                /* TODO: we maybe need to schedule a event here */
+                status = gckVIDMEM_Unlock(record->kernel,
+                                          record->data,
+                                          gcvSURF_TYPE_UNKNOWN,
+                                          gcvNULL);
+            }
+
+            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+                           "DB: VIDEO_MEMORY_LOCKED 0x%x (status=%d)",
+                           record->data, status);
+            break;
+
+        case gcvDB_CONTEXT:
+            /* TODO: Free the context */
+            status = gckCOMMAND_Detach(Kernel->command, record->data);
+
+            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+                           "DB: CONTEXT 0x%x (status=%d)",
+                           record->data, status);
+            break;
+
+        case gcvDB_MAP_MEMORY:
+            /* Unmap memory. */
+            status = gckKERNEL_UnmapMemory(Kernel,
+                                           record->physical,
+                                           record->bytes,
+                                           record->data);
+
+            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+                           "DB: MAP MEMORY %d (status=%d)",
+                           gcmPTR2INT(record->data), status);
+            break;
+
+        case gcvDB_MAP_USER_MEMORY:
+            /* TODO: Unmap user memory. */
+            status = gckOS_UnmapUserMemoryEx(Kernel->os,
+                                             Kernel->core,
+                                             record->data,
+                                             record->bytes,
+                                             record->physical,
+                                             0);
+
+            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+                           "DB: MAP USER MEMORY %d (status=%d)",
+                           gcmPTR2INT(record->data), status);
+            break;
+
+                    case gcvDB_SHARED_INFO:
+                        status = gckOS_FreeMemory(Kernel->os, record->physical);
+                        break;
+
+        default:
+            gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DATABASE,
+                           "DB: Correcupted record=0x%08x type=%d",
+                           record, record->type);
+            break;
+        }
+
+        /* Delete the record. */
+        gcmkONERROR(gckKERNEL_DeleteRecord(Kernel,
+                                           database,
+                                           record->type,
+                                           record->data,
+                                           gcvNULL));
+    }
+
+    /* Delete the database. */
+    gcmkONERROR(gckKERNEL_DeleteDatabase(Kernel, database));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckKERNEL_QueryProcessDB
+**
+**  Query a process database for the current usage of a particular record type.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gctUINT32 ProcessID
+**          Process ID used to identify the database.
+**
+**      gctBOOL LastProcessID
+**          gcvTRUE if searching for the last known process ID.  gcvFALSE if
+**          we need to search for the process ID specified by the ProcessID
+**          argument.
+**
+**      gceDATABASE_TYPE Type
+**          Type of the record to query.
+**
+**  OUTPUT:
+**
+**      gcuDATABASE_INFO * Info
+**          Pointer to a variable that receives the requested information.
+*/
+gceSTATUS
+gckKERNEL_QueryProcessDB(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gctBOOL LastProcessID,
+    IN gceDATABASE_TYPE Type,
+    OUT gcuDATABASE_INFO * Info
+    )
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database;
+
+    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Info=0x%x",
+                   Kernel, ProcessID, Type, Info);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+
+    /* Find the database. */
+    gcmkONERROR(
+        gckKERNEL_FindDatabase(Kernel, ProcessID, LastProcessID, &database));
+
+    /* Get pointer to counters. */
+    switch (Type)
+    {
+    case gcvDB_VIDEO_MEMORY:
+        gcmkONERROR(gckOS_MemCopy(&Info->counters,
+                                  &database->vidMem,
+                                  gcmSIZEOF(database->vidMem)));
+        break;
+
+    case gcvDB_NON_PAGED:
+        gcmkONERROR(gckOS_MemCopy(&Info->counters,
+                                  &database->nonPaged,
+                                  gcmSIZEOF(database->vidMem)));
+        break;
+
+    case gcvDB_CONTIGUOUS:
+        gcmkONERROR(gckOS_MemCopy(&Info->counters,
+                                  &database->contiguous,
+                                  gcmSIZEOF(database->vidMem)));
+        break;
+
+    case gcvDB_IDLE:
+        Info->time           = Kernel->db->idleTime;
+        Kernel->db->idleTime = 0;
+        break;
+
+    case gcvDB_MAP_MEMORY:
+        gcmkONERROR(gckOS_MemCopy(&Info->counters,
+                                  &database->mapMemory,
+                                  gcmSIZEOF(database->mapMemory)));
+        break;
+
+    case gcvDB_MAP_USER_MEMORY:
+        gcmkONERROR(gckOS_MemCopy(&Info->counters,
+                                  &database->mapUserMemory,
+                                  gcmSIZEOF(database->mapUserMemory)));
+        break;
+
+    default:
+        break;
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+#if gcdSECURE_USER
+/*******************************************************************************
+**  gckKERNEL_GetProcessDBCache
+**
+**  Get teh secure cache from a process database.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to a gckKERNEL object.
+**
+**      gctUINT32 ProcessID
+**          Process ID used to identify the database.
+**
+**  OUTPUT:
+**
+**      gcskSECURE_CACHE_PTR * Cache
+**          Pointer to a variable that receives the secure cache pointer.
+*/
+gceSTATUS
+gckKERNEL_GetProcessDBCache(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    OUT gcskSECURE_CACHE_PTR * Cache
+    )
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database;
+
+    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Cache != gcvNULL);
+
+    /* Find the database. */
+    gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+    /* Return the pointer to the cache. */
+    *Cache = &database->cache;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Cache=0x%x", *Cache);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c
new file mode 100644 (file)
index 0000000..0836e0d
--- /dev/null
@@ -0,0 +1,2534 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+#include <gc_hal_kernel_debug.h>
+
+/******************************************************************************\
+******************************** Debug Variables *******************************
+\******************************************************************************/
+
+static gceSTATUS _lastError  = gcvSTATUS_OK;
+static gctUINT32 _debugLevel = gcvLEVEL_ERROR;
+static gctUINT32 _debugZones = gcvZONE_ALL;
+
+/******************************************************************************\
+********************************* Debug Switches *******************************
+\******************************************************************************/
+
+/*
+    gcdBUFFERED_OUTPUT
+
+    When set to non-zero, all output is collected into a buffer with the
+    specified size.  Once the buffer gets full, the debug buffer will be
+    printed to the console. gcdBUFFERED_SIZE determines the size of the buffer.
+*/
+#define gcdBUFFERED_OUTPUT  0
+
+/*
+    gcdBUFFERED_SIZE
+
+    When set to non-zero, all output is collected into a buffer with the
+    specified size.  Once the buffer gets full, the debug buffer will be
+    printed to the console.
+*/
+#define gcdBUFFERED_SIZE    (1024 * 1024 * 2)
+
+/*
+    gcdDMA_BUFFER_COUNT
+
+    If greater then zero, the debugger will attempt to find the command buffer
+    where DMA is currently executing and then print this buffer and
+    (gcdDMA_BUFFER_COUNT - 1) buffers before the current one. If set to zero
+    or the current buffer is not found, all buffers are printed.
+*/
+#define gcdDMA_BUFFER_COUNT 0
+
+/*
+    gcdTHREAD_BUFFERS
+
+    When greater then one, will accumulate messages from the specified number
+    of threads in separate output buffers.
+*/
+#define gcdTHREAD_BUFFERS   1
+
+/*
+    gcdENABLE_OVERFLOW
+
+    When set to non-zero, and the output buffer gets full, instead of being
+    printed, it will be allowed to overflow removing the oldest messages.
+*/
+#define gcdENABLE_OVERFLOW  1
+
+/*
+    gcdSHOW_LINE_NUMBER
+
+    When enabledm each print statement will be preceeded with the current
+    line number.
+*/
+#define gcdSHOW_LINE_NUMBER 0
+
+/*
+    gcdSHOW_PROCESS_ID
+
+    When enabledm each print statement will be preceeded with the current
+    process ID.
+*/
+#define gcdSHOW_PROCESS_ID  0
+
+/*
+    gcdSHOW_THREAD_ID
+
+    When enabledm each print statement will be preceeded with the current
+    thread ID.
+*/
+#define gcdSHOW_THREAD_ID   0
+
+/*
+    gcdSHOW_TIME
+
+    When enabled each print statement will be preceeded with the current
+    high-resolution time.
+*/
+#define gcdSHOW_TIME        0
+
+
+/******************************************************************************\
+****************************** Miscellaneous Macros ****************************
+\******************************************************************************/
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+#   define gcmDBGASSERT(Expression, Format, Value) \
+        if (!(Expression)) \
+        { \
+            _DirectPrint( \
+                "*** gcmDBGASSERT ***************************\n" \
+                "    function     : %s\n" \
+                "    line         : %d\n" \
+                "    expression   : " #Expression "\n" \
+                "    actual value : " Format "\n", \
+                __FUNCTION__, __LINE__, Value \
+                ); \
+        }
+#else
+#   define gcmDBGASSERT(Expression, Format, Value)
+#endif
+
+#define gcmPTRALIGNMENT(Pointer, Alignemnt) \
+( \
+    gcmALIGN(gcmPTR2INT(Pointer), Alignemnt) - gcmPTR2INT(Pointer) \
+)
+
+#if gcdALIGNBYSIZE
+#   define gcmISALIGNED(Offset, Alignment) \
+        (((Offset) & ((Alignment) - 1)) == 0)
+
+#   define gcmkALIGNPTR(Type, Pointer, Alignment) \
+        Pointer = (Type) gcmINT2PTR(gcmALIGN(gcmPTR2INT(Pointer), Alignment))
+#else
+#   define gcmISALIGNED(Offset, Alignment) \
+        gcvTRUE
+
+#   define gcmkALIGNPTR(Type, Pointer, Alignment)
+#endif
+
+#define gcmALIGNSIZE(Offset, Size) \
+    ((Size - Offset) + Size)
+
+#define gcdHAVEPREFIX \
+( \
+       gcdSHOW_TIME \
+    || gcdSHOW_LINE_NUMBER \
+    || gcdSHOW_PROCESS_ID \
+    || gcdSHOW_THREAD_ID \
+)
+
+#if gcdHAVEPREFIX
+
+#   define gcdOFFSET                    0
+
+#if gcdSHOW_TIME
+#if gcmISALIGNED(gcdOFFSET, 8)
+#           define gcdTIMESIZE          gcmSIZEOF(gctUINT64)
+#       elif gcdOFFSET == 4
+#           define gcdTIMESIZE          gcmALIGNSIZE(4, gcmSIZEOF(gctUINT64))
+#       else
+#           error "Unexpected offset value."
+#       endif
+#       undef  gcdOFFSET
+#       define gcdOFFSET                8
+#if !defined(gcdPREFIX_LEADER)
+#           define gcdPREFIX_LEADER     gcmSIZEOF(gctUINT64)
+#           define gcdTIMEFORMAT        "0x%016llX"
+#       else
+#           define gcdTIMEFORMAT        ", 0x%016llX"
+#       endif
+#   else
+#       define gcdTIMESIZE              0
+#       define gcdTIMEFORMAT
+#   endif
+
+#if gcdSHOW_LINE_NUMBER
+#if gcmISALIGNED(gcdOFFSET, 8)
+#           define gcdNUMSIZE           gcmSIZEOF(gctUINT64)
+#       elif gcdOFFSET == 4
+#           define gcdNUMSIZE           gcmALIGNSIZE(4, gcmSIZEOF(gctUINT64))
+#       else
+#           error "Unexpected offset value."
+#       endif
+#       undef  gcdOFFSET
+#       define gcdOFFSET                8
+#if !defined(gcdPREFIX_LEADER)
+#           define gcdPREFIX_LEADER     gcmSIZEOF(gctUINT64)
+#           define gcdNUMFORMAT         "%8llu"
+#       else
+#           define gcdNUMFORMAT         ", %8llu"
+#       endif
+#   else
+#       define gcdNUMSIZE               0
+#       define gcdNUMFORMAT
+#   endif
+
+#if gcdSHOW_PROCESS_ID
+#if gcmISALIGNED(gcdOFFSET, 4)
+#           define gcdPIDSIZE           gcmSIZEOF(gctUINT32)
+#       else
+#           error "Unexpected offset value."
+#       endif
+#       undef  gcdOFFSET
+#       define gcdOFFSET                4
+#if !defined(gcdPREFIX_LEADER)
+#           define gcdPREFIX_LEADER     gcmSIZEOF(gctUINT32)
+#           define gcdPIDFORMAT         "pid=0x%04X"
+#       else
+#           define gcdPIDFORMAT         ", pid=0x%04X"
+#       endif
+#   else
+#       define gcdPIDSIZE               0
+#       define gcdPIDFORMAT
+#   endif
+
+#if gcdSHOW_THREAD_ID
+#if gcmISALIGNED(gcdOFFSET, 4)
+#           define gcdTIDSIZE           gcmSIZEOF(gctUINT32)
+#       else
+#           error "Unexpected offset value."
+#       endif
+#       undef  gcdOFFSET
+#       define gcdOFFSET                4
+#if !defined(gcdPREFIX_LEADER)
+#           define gcdPREFIX_LEADER     gcmSIZEOF(gctUINT32)
+#           define gcdTIDFORMAT         "tid=0x%04X"
+#       else
+#           define gcdTIDFORMAT         ", tid=0x%04X"
+#       endif
+#   else
+#       define gcdTIDSIZE               0
+#       define gcdTIDFORMAT
+#   endif
+
+#   define gcdPREFIX_SIZE \
+    ( \
+          gcdTIMESIZE \
+        + gcdNUMSIZE  \
+        + gcdPIDSIZE  \
+        + gcdTIDSIZE  \
+    )
+
+    static const char * _prefixFormat =
+    "["
+        gcdTIMEFORMAT
+        gcdNUMFORMAT
+        gcdPIDFORMAT
+        gcdTIDFORMAT
+    "] ";
+
+#else
+
+#   define gcdPREFIX_LEADER             gcmSIZEOF(gctUINT32)
+#   define gcdPREFIX_SIZE               0
+
+#endif
+
+/* Assumed largest variable argument leader size. */
+#define gcdVARARG_LEADER                gcmSIZEOF(gctUINT64)
+
+/* Alignnments. */
+#if gcdALIGNBYSIZE
+#   define gcdPREFIX_ALIGNMENT gcdPREFIX_LEADER
+#   define gcdVARARG_ALIGNMENT gcdVARARG_LEADER
+#else
+#   define gcdPREFIX_ALIGNMENT 0
+#   define gcdVARARG_ALIGNMENT 0
+#endif
+
+#if gcdBUFFERED_OUTPUT
+#   define gcdOUTPUTPREFIX _AppendPrefix
+#   define gcdOUTPUTSTRING _AppendString
+#   define gcdOUTPUTCOPY   _AppendCopy
+#   define gcdOUTPUTBUFFER _AppendBuffer
+#else
+#   define gcdOUTPUTPREFIX _PrintPrefix
+#   define gcdOUTPUTSTRING _PrintString
+#   define gcdOUTPUTCOPY   _PrintString
+#   define gcdOUTPUTBUFFER _PrintBuffer
+#endif
+
+/******************************************************************************\
+****************************** Private Structures ******************************
+\******************************************************************************/
+
+typedef enum _gceBUFITEM
+{
+    gceBUFITEM_NONE,
+    gcvBUFITEM_PREFIX,
+    gcvBUFITEM_STRING,
+    gcvBUFITEM_COPY,
+    gcvBUFITEM_BUFFER
+}
+gceBUFITEM;
+
+/* Common item head/buffer terminator. */
+typedef struct _gcsBUFITEM_HEAD * gcsBUFITEM_HEAD_PTR;
+typedef struct _gcsBUFITEM_HEAD
+{
+    gceBUFITEM              type;
+}
+gcsBUFITEM_HEAD;
+
+/* String prefix (for ex. [     1,tid=0x019A]) */
+typedef struct _gcsBUFITEM_PREFIX * gcsBUFITEM_PREFIX_PTR;
+typedef struct _gcsBUFITEM_PREFIX
+{
+    gceBUFITEM              type;
+#if gcdHAVEPREFIX
+    gctPOINTER              prefixData;
+#endif
+}
+gcsBUFITEM_PREFIX;
+
+/* Buffered string. */
+typedef struct _gcsBUFITEM_STRING * gcsBUFITEM_STRING_PTR;
+typedef struct _gcsBUFITEM_STRING
+{
+    gceBUFITEM              type;
+    gctINT                  indent;
+    gctCONST_STRING         message;
+    gctPOINTER              messageData;
+    gctUINT                 messageDataSize;
+}
+gcsBUFITEM_STRING;
+
+/* Buffered string (copy of the string is included with the record). */
+typedef struct _gcsBUFITEM_COPY * gcsBUFITEM_COPY_PTR;
+typedef struct _gcsBUFITEM_COPY
+{
+    gceBUFITEM              type;
+    gctINT                  indent;
+    gctPOINTER              messageData;
+    gctUINT                 messageDataSize;
+}
+gcsBUFITEM_COPY;
+
+/* Memory buffer. */
+typedef struct _gcsBUFITEM_BUFFER * gcsBUFITEM_BUFFER_PTR;
+typedef struct _gcsBUFITEM_BUFFER
+{
+    gceBUFITEM              type;
+    gctINT                  indent;
+    gceDUMP_BUFFER          bufferType;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+    gctUINT32               dmaAddress;
+#endif
+
+    gctUINT                 dataSize;
+    gctUINT32               address;
+#if gcdHAVEPREFIX
+    gctPOINTER              prefixData;
+#endif
+}
+gcsBUFITEM_BUFFER;
+
+typedef struct _gcsBUFFERED_OUTPUT * gcsBUFFERED_OUTPUT_PTR;
+typedef struct _gcsBUFFERED_OUTPUT
+{
+#if gcdTHREAD_BUFFERS > 1
+    gctUINT32               threadID;
+#endif
+
+#if gcdSHOW_LINE_NUMBER
+    gctUINT64               lineNumber;
+#endif
+
+    gctINT                  indent;
+
+#if gcdBUFFERED_OUTPUT
+    gctINT                  start;
+    gctINT                  index;
+    gctINT                  count;
+    gctUINT8                buffer[gcdBUFFERED_SIZE];
+#endif
+
+    gcsBUFFERED_OUTPUT_PTR  prev;
+    gcsBUFFERED_OUTPUT_PTR  next;
+}
+gcsBUFFERED_OUTPUT;
+
+typedef gctUINT (* gcfPRINTSTRING) (
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gcsBUFITEM_HEAD_PTR Item
+    );
+
+typedef gctINT (* gcfGETITEMSIZE) (
+    IN gcsBUFITEM_HEAD_PTR Item
+    );
+
+/******************************************************************************\
+******************************* Private Variables ******************************
+\******************************************************************************/
+
+static gcsBUFFERED_OUTPUT     _outputBuffer[gcdTHREAD_BUFFERS];
+static gcsBUFFERED_OUTPUT_PTR _outputBufferHead = gcvNULL;
+static gcsBUFFERED_OUTPUT_PTR _outputBufferTail = gcvNULL;
+
+/******************************************************************************\
+****************************** Item Size Functions *****************************
+\******************************************************************************/
+
+#if gcdBUFFERED_OUTPUT
+static gctINT
+_GetTerminatorItemSize(
+    IN gcsBUFITEM_HEAD_PTR Item
+    )
+{
+    return gcmSIZEOF(gcsBUFITEM_HEAD);
+}
+
+static gctINT
+_GetPrefixItemSize(
+    IN gcsBUFITEM_HEAD_PTR Item
+    )
+{
+#if gcdHAVEPREFIX
+    gcsBUFITEM_PREFIX_PTR item = (gcsBUFITEM_PREFIX_PTR) Item;
+    gctUINT vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
+    return vlen + gcdPREFIX_SIZE;
+#else
+    return gcmSIZEOF(gcsBUFITEM_PREFIX);
+#endif
+}
+
+static gctINT
+_GetStringItemSize(
+    IN gcsBUFITEM_HEAD_PTR Item
+    )
+{
+    gcsBUFITEM_STRING_PTR item = (gcsBUFITEM_STRING_PTR) Item;
+    gctUINT vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
+    return vlen + item->messageDataSize;
+}
+
+static gctINT
+_GetCopyItemSize(
+    IN gcsBUFITEM_HEAD_PTR Item
+    )
+{
+    gcsBUFITEM_COPY_PTR item = (gcsBUFITEM_COPY_PTR) Item;
+    gctUINT vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
+    return vlen + item->messageDataSize;
+}
+
+static gctINT
+_GetBufferItemSize(
+    IN gcsBUFITEM_HEAD_PTR Item
+    )
+{
+#if gcdHAVEPREFIX
+    gcsBUFITEM_BUFFER_PTR item = (gcsBUFITEM_BUFFER_PTR) Item;
+    gctUINT vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
+    return vlen + gcdPREFIX_SIZE + item->dataSize;
+#else
+    gcsBUFITEM_BUFFER_PTR item = (gcsBUFITEM_BUFFER_PTR) Item;
+    return gcmSIZEOF(gcsBUFITEM_BUFFER) + item->dataSize;
+#endif
+}
+
+static gcfGETITEMSIZE _itemSize[] =
+{
+    _GetTerminatorItemSize,
+    _GetPrefixItemSize,
+    _GetStringItemSize,
+    _GetCopyItemSize,
+    _GetBufferItemSize
+};
+#endif
+
+/******************************************************************************\
+******************************* Printing Functions *****************************
+\******************************************************************************/
+
+#if gcdDEBUG || gcdBUFFERED_OUTPUT
+static void
+_DirectPrint(
+    gctCONST_STRING Message,
+    ...
+    )
+{
+    gctINT len;
+    char buffer[768];
+    gctARGUMENTS arguments;
+
+    gcmkARGUMENTS_START(arguments, Message);
+    len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), Message, arguments);
+    gcmkARGUMENTS_END(arguments);
+
+    buffer[len] = '\0';
+    gcmkOUTPUT_STRING(buffer);
+}
+#endif
+
+static int
+_AppendIndent(
+    IN gctINT Indent,
+    IN char * Buffer,
+    IN int BufferSize
+    )
+{
+    gctINT i;
+
+    gctINT len    = 0;
+    gctINT indent = Indent % 40;
+
+    for (i = 0; i < indent; i += 1)
+    {
+        Buffer[len++] = ' ';
+    }
+
+    if (indent != Indent)
+    {
+        len += gcmkSPRINTF(
+            Buffer + len, BufferSize - len, " <%d> ", Indent
+            );
+
+        Buffer[len] = '\0';
+    }
+
+    return len;
+}
+
+#if gcdHAVEPREFIX
+static void
+_PrintPrefix(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gctPOINTER Data
+    )
+{
+    char buffer[768];
+    gctINT len;
+
+    /* Format the string. */
+    len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), _prefixFormat, Data);
+    buffer[len] = '\0';
+
+    /* Print the string. */
+    gcmkOUTPUT_STRING(buffer);
+}
+#endif
+
+static void
+_PrintString(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gctINT Indent,
+    IN gctCONST_STRING Message,
+    IN gctUINT ArgumentSize,
+    IN gctPOINTER Data
+    )
+{
+    char buffer[768];
+    gctINT len;
+
+    /* Append the indent string. */
+    len = _AppendIndent(Indent, buffer, gcmSIZEOF(buffer));
+
+    /* Format the string. */
+    len += gcmkVSPRINTF(buffer + len, gcmSIZEOF(buffer) - len, Message, Data);
+    buffer[len] = '\0';
+
+    /* Add end-of-line if missing. */
+    if (buffer[len - 1] != '\n')
+    {
+        buffer[len++] = '\n';
+        buffer[len] = '\0';
+    }
+
+    /* Print the string. */
+    gcmkOUTPUT_STRING(buffer);
+}
+
+static void
+_PrintBuffer(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gctINT Indent,
+    IN gctPOINTER PrefixData,
+    IN gctPOINTER Data,
+    IN gctUINT Address,
+    IN gctUINT DataSize,
+    IN gceDUMP_BUFFER Type,
+    IN gctUINT32 DmaAddress
+    )
+{
+    static gctCONST_STRING _titleString[] =
+    {
+        "CONTEXT BUFFER",
+        "USER COMMAND BUFFER",
+        "KERNEL COMMAND BUFFER",
+        "LINK BUFFER",
+        "WAIT LINK BUFFER",
+        ""
+    };
+
+    static const gctINT COLUMN_COUNT = 8;
+
+    gctUINT i, count, column, address;
+    gctUINT32_PTR data;
+    gctCHAR buffer[768];
+    gctUINT indent, len;
+    gctBOOL command;
+
+    /* Append space for the prefix. */
+#if gcdHAVEPREFIX
+    indent = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), _prefixFormat, PrefixData);
+    buffer[indent] = '\0';
+#else
+    indent = 0;
+#endif
+
+    /* Append the indent string. */
+    indent += _AppendIndent(
+        Indent, buffer + indent, gcmSIZEOF(buffer) - indent
+        );
+
+    switch (Type)
+    {
+    case gceDUMP_BUFFER_CONTEXT:
+    case gceDUMP_BUFFER_USER:
+    case gceDUMP_BUFFER_KERNEL:
+    case gceDUMP_BUFFER_LINK:
+    case gceDUMP_BUFFER_WAITLINK:
+        /* Form and print the title string. */
+        gcmkSPRINTF2(
+            buffer + indent, gcmSIZEOF(buffer) - indent,
+            "%s%s\n", _titleString[Type],
+            ((DmaAddress >= Address) && (DmaAddress < Address + DataSize))
+                ? " (CURRENT)" : ""
+            );
+
+        gcmkOUTPUT_STRING(buffer);
+
+        /* Terminate the string. */
+        buffer[indent] = '\0';
+
+        /* This is a command buffer. */
+        command = gcvTRUE;
+        break;
+
+    case gceDUMP_BUFFER_FROM_USER:
+        /* This is not a command buffer. */
+        command = gcvFALSE;
+
+        /* No title. */
+        break;
+
+    default:
+        gcmDBGASSERT(gcvFALSE, "%s", "invalid buffer type");
+
+        /* This is not a command buffer. */
+        command = gcvFALSE;
+    }
+
+    /* Overwrite the prefix with spaces. */
+    for (i = 0; i < indent; i += 1)
+    {
+        buffer[i] = ' ';
+    }
+
+    /* Form and print the opening string. */
+    if (command)
+    {
+        gcmkSPRINTF2(
+            buffer + indent, gcmSIZEOF(buffer) - indent,
+            "@[kernel.command %08X %08X\n", Address, DataSize
+            );
+
+        gcmkOUTPUT_STRING(buffer);
+
+        /* Terminate the string. */
+        buffer[indent] = '\0';
+    }
+
+    /* Get initial address. */
+    address = Address;
+
+    /* Cast the data pointer. */
+    data = (gctUINT32_PTR) Data;
+
+    /* Compute the number of double words. */
+    count = DataSize / gcmSIZEOF(gctUINT32);
+
+    /* Print the buffer. */
+    for (i = 0, len = indent, column = 0; i < count; i += 1)
+    {
+        /* Append the address. */
+        if (column == 0)
+        {
+            len += gcmkSPRINTF(
+                buffer + len, gcmSIZEOF(buffer) - len, "0x%08X:", address
+                );
+        }
+
+        /* Append the data value. */
+        len += gcmkSPRINTF2(
+            buffer + len, gcmSIZEOF(buffer) - len, "%c%08X",
+            (address == DmaAddress)? '>' : ' ', data[i]
+            );
+
+        buffer[len] = '\0';
+
+        /* Update the address. */
+        address += gcmSIZEOF(gctUINT32);
+
+        /* Advance column count. */
+        column += 1;
+
+        /* End of line? */
+        if ((column % COLUMN_COUNT) == 0)
+        {
+            /* Append EOL. */
+            gcmkSTRCAT(buffer + len, gcmSIZEOF(buffer) - len, "\n");
+
+            /* Print the string. */
+            gcmkOUTPUT_STRING(buffer);
+
+            /* Reset. */
+            len    = indent;
+            column = 0;
+        }
+    }
+
+    /* Print the last partial string. */
+    if (column != 0)
+    {
+        /* Append EOL. */
+        gcmkSTRCAT(buffer + len, gcmSIZEOF(buffer) - len, "\n");
+
+        /* Print the string. */
+        gcmkOUTPUT_STRING(buffer);
+    }
+
+    /* Form and print the opening string. */
+    if (command)
+    {
+        buffer[indent] = '\0';
+        gcmkSTRCAT(buffer, gcmSIZEOF(buffer), "] -- command\n");
+        gcmkOUTPUT_STRING(buffer);
+    }
+}
+
+#if gcdBUFFERED_OUTPUT
+static gctUINT
+_PrintNone(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gcsBUFITEM_HEAD_PTR Item
+    )
+{
+    /* Return the size of the node. */
+    return gcmSIZEOF(gcsBUFITEM_HEAD);
+}
+
+static gctUINT
+_PrintPrefixWrapper(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gcsBUFITEM_HEAD_PTR Item
+    )
+{
+#if gcdHAVEPREFIX
+    gcsBUFITEM_PREFIX_PTR item;
+    gctUINT vlen;
+
+    /* Get access to the data. */
+    item = (gcsBUFITEM_PREFIX_PTR) Item;
+
+    /* Print the message. */
+    _PrintPrefix(OutputBuffer, item->prefixData);
+
+    /* Compute the size of the variable portion of the structure. */
+    vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
+
+    /* Return the size of the node. */
+    return vlen + gcdPREFIX_SIZE;
+#else
+    return gcmSIZEOF(gcsBUFITEM_PREFIX);
+#endif
+}
+
+static gctUINT
+_PrintStringWrapper(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gcsBUFITEM_HEAD_PTR Item
+    )
+{
+    gcsBUFITEM_STRING_PTR item;
+    gctUINT vlen;
+
+    /* Get access to the data. */
+    item = (gcsBUFITEM_STRING_PTR) Item;
+
+    /* Print the message. */
+    _PrintString(
+        OutputBuffer,
+        item->indent, item->message, item->messageDataSize, item->messageData
+        );
+
+    /* Compute the size of the variable portion of the structure. */
+    vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
+
+    /* Return the size of the node. */
+    return vlen + item->messageDataSize;
+}
+
+static gctUINT
+_PrintCopyWrapper(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gcsBUFITEM_HEAD_PTR Item
+    )
+{
+    gcsBUFITEM_COPY_PTR item;
+    gctCONST_STRING message;
+    gctUINT vlen;
+
+    /* Get access to the data. */
+    item = (gcsBUFITEM_COPY_PTR) Item;
+
+    /* Determine the string pointer. */
+    message = (gctCONST_STRING) (item + 1);
+
+    /* Print the message. */
+    _PrintString(
+        OutputBuffer,
+        item->indent, message, item->messageDataSize, item->messageData
+        );
+
+    /* Compute the size of the variable portion of the structure. */
+    vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
+
+    /* Return the size of the node. */
+    return vlen + item->messageDataSize;
+}
+
+static gctUINT
+_PrintBufferWrapper(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gcsBUFITEM_HEAD_PTR Item
+    )
+{
+#if gcdHAVEPREFIX
+    gctUINT32 dmaAddress;
+    gcsBUFITEM_BUFFER_PTR item;
+    gctPOINTER data;
+    gctUINT vlen;
+
+    /* Get access to the data. */
+    item = (gcsBUFITEM_BUFFER_PTR) Item;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+    dmaAddress = item->dmaAddress;
+#else
+    dmaAddress = 0xFFFFFFFF;
+#endif
+
+    if (dmaAddress != 0)
+    {
+        /* Compute the data address. */
+        data = ((gctUINT8_PTR) item->prefixData) + gcdPREFIX_SIZE;
+
+        /* Print buffer. */
+        _PrintBuffer(
+            OutputBuffer,
+            item->indent, item->prefixData,
+            data, item->address, item->dataSize,
+            item->bufferType, dmaAddress
+            );
+    }
+
+    /* Compute the size of the variable portion of the structure. */
+    vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
+
+    /* Return the size of the node. */
+    return vlen + gcdPREFIX_SIZE + item->dataSize;
+#else
+    gctUINT32 dmaAddress;
+    gcsBUFITEM_BUFFER_PTR item;
+
+    /* Get access to the data. */
+    item = (gcsBUFITEM_BUFFER_PTR) Item;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+    dmaAddress = item->dmaAddress;
+#else
+    dmaAddress = 0xFFFFFFFF;
+#endif
+
+    if (dmaAddress != 0)
+    {
+        /* Print buffer. */
+        _PrintBuffer(
+            OutputBuffer,
+            item->indent, gcvNULL,
+            item + 1, item->address, item->dataSize,
+            item->bufferType, dmaAddress
+            );
+    }
+
+    /* Return the size of the node. */
+    return gcmSIZEOF(gcsBUFITEM_BUFFER) + item->dataSize;
+#endif
+}
+
+static gcfPRINTSTRING _printArray[] =
+{
+    _PrintNone,
+    _PrintPrefixWrapper,
+    _PrintStringWrapper,
+    _PrintCopyWrapper,
+    _PrintBufferWrapper
+};
+#endif
+
+/******************************************************************************\
+******************************* Private Functions ******************************
+\******************************************************************************/
+
+#if gcdBUFFERED_OUTPUT
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+static gcsBUFITEM_BUFFER_PTR
+_FindCurrentDMABuffer(
+    gctUINT32 DmaAddress
+    )
+{
+    gctINT i, skip;
+    gcsBUFITEM_HEAD_PTR item;
+    gcsBUFITEM_BUFFER_PTR dmaCurrent;
+
+    /* Reset the current buffer. */
+    dmaCurrent = gcvNULL;
+
+    /* Get the first stored item. */
+    item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
+
+    /* Run through all items. */
+    for (i = 0; i < _outputBufferHead->count; i += 1)
+    {
+        /* Buffer item? */
+        if (item->type == gcvBUFITEM_BUFFER)
+        {
+            gcsBUFITEM_BUFFER_PTR buffer = (gcsBUFITEM_BUFFER_PTR) item;
+
+            if ((DmaAddress >= buffer->address) &&
+                (DmaAddress <  buffer->address + buffer->dataSize))
+            {
+                dmaCurrent = buffer;
+            }
+        }
+
+        /* Get the item size and skip it. */
+        skip = (* _itemSize[item->type]) (item);
+        item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+        /* End of the buffer? Wrap around. */
+        if (item->type == gceBUFITEM_NONE)
+        {
+            item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
+        }
+    }
+
+    /* Return result. */
+    return dmaCurrent;
+}
+
+static void
+_EnableAllDMABuffers(
+    void
+    )
+{
+    gctINT i, skip;
+    gcsBUFITEM_HEAD_PTR item;
+
+    /* Get the first stored item. */
+    item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
+
+    /* Run through all items. */
+    for (i = 0; i < _outputBufferHead->count; i += 1)
+    {
+        /* Buffer item? */
+        if (item->type == gcvBUFITEM_BUFFER)
+        {
+            gcsBUFITEM_BUFFER_PTR buffer = (gcsBUFITEM_BUFFER_PTR) item;
+
+            /* Enable the buffer. */
+            buffer->dmaAddress = ~0U;
+        }
+
+        /* Get the item size and skip it. */
+        skip = (* _itemSize[item->type]) (item);
+        item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+        /* End of the buffer? Wrap around. */
+        if (item->type == gceBUFITEM_NONE)
+        {
+            item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
+        }
+    }
+}
+
+static void
+_EnableDMABuffers(
+    gctUINT32 DmaAddress,
+    gcsBUFITEM_BUFFER_PTR CurrentDMABuffer
+    )
+{
+    gctINT i, skip, index;
+    gcsBUFITEM_HEAD_PTR item;
+    gcsBUFITEM_BUFFER_PTR buffers[gcdDMA_BUFFER_COUNT];
+
+    /* Reset buffer pointers. */
+    gckOS_ZeroMemory(buffers, gcmSIZEOF(buffers));
+
+    /* Set the current buffer index. */
+    index = -1;
+
+    /* Get the first stored item. */
+    item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
+
+    /* Run through all items until the current DMA buffer is found. */
+    for (i = 0; i < _outputBufferHead->count; i += 1)
+    {
+        /* Buffer item? */
+        if (item->type == gcvBUFITEM_BUFFER)
+        {
+            /* Advance the index. */
+            index = (index + 1) % gcdDMA_BUFFER_COUNT;
+
+            /* Add to the buffer array. */
+            buffers[index] = (gcsBUFITEM_BUFFER_PTR) item;
+
+            /* Stop if this is the current DMA buffer. */
+            if ((gcsBUFITEM_BUFFER_PTR) item == CurrentDMABuffer)
+            {
+                break;
+            }
+        }
+
+        /* Get the item size and skip it. */
+        skip = (* _itemSize[item->type]) (item);
+        item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+        /* End of the buffer? Wrap around. */
+        if (item->type == gceBUFITEM_NONE)
+        {
+            item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
+        }
+    }
+
+    /* Enable the found buffers. */
+    gcmDBGASSERT(index != -1, "%d", index);
+
+    for (i = 0; i < gcdDMA_BUFFER_COUNT; i += 1)
+    {
+        if (buffers[index] == gcvNULL)
+        {
+            break;
+        }
+
+        buffers[index]->dmaAddress = DmaAddress;
+
+        index -= 1;
+
+        if (index == -1)
+        {
+            index = gcdDMA_BUFFER_COUNT - 1;
+        }
+    }
+}
+#endif
+
+static void
+_Flush(
+    gctUINT32 DmaAddress
+    )
+{
+    gctINT i, skip;
+    gcsBUFITEM_HEAD_PTR item;
+
+    gcsBUFFERED_OUTPUT_PTR outputBuffer = _outputBufferHead;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+    if ((outputBuffer != gcvNULL) && (outputBuffer->count != 0))
+    {
+        /* Find the current DMA buffer. */
+        gcsBUFITEM_BUFFER_PTR dmaCurrent = _FindCurrentDMABuffer(DmaAddress);
+
+        /* Was the current buffer found? */
+        if (dmaCurrent == gcvNULL)
+        {
+            /* No, print all buffers. */
+            _EnableAllDMABuffers();
+        }
+        else
+        {
+            /* Yes, enable only specified number of buffers. */
+            _EnableDMABuffers(DmaAddress, dmaCurrent);
+        }
+    }
+#endif
+
+    while (outputBuffer != gcvNULL)
+    {
+        if (outputBuffer->count != 0)
+        {
+            _DirectPrint("********************************************************************************\n");
+            _DirectPrint("FLUSHING DEBUG OUTPUT BUFFER (%d elements).\n", outputBuffer->count);
+            _DirectPrint("********************************************************************************\n");
+
+            item = (gcsBUFITEM_HEAD_PTR) &outputBuffer->buffer[outputBuffer->start];
+
+            for (i = 0; i < outputBuffer->count; i += 1)
+            {
+                skip = (* _printArray[item->type]) (outputBuffer, item);
+
+                item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+                if (item->type == gceBUFITEM_NONE)
+                {
+                    item = (gcsBUFITEM_HEAD_PTR) outputBuffer->buffer;
+                }
+            }
+
+            outputBuffer->start = 0;
+            outputBuffer->index = 0;
+            outputBuffer->count = 0;
+        }
+
+        outputBuffer = outputBuffer->next;
+    }
+}
+
+static gcsBUFITEM_HEAD_PTR
+_AllocateItem(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gctINT Size
+    )
+{
+    gctINT skip;
+    gcsBUFITEM_HEAD_PTR item, next;
+
+#if gcdENABLE_OVERFLOW
+    if (
+            (OutputBuffer->index + Size >= gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
+            ||
+            (
+                (OutputBuffer->index        <  OutputBuffer->start) &&
+                (OutputBuffer->index + Size >= OutputBuffer->start)
+            )
+    )
+    {
+        if (OutputBuffer->index + Size >= gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
+        {
+            if (OutputBuffer->index < OutputBuffer->start)
+            {
+                item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->start];
+
+                while (item->type != gceBUFITEM_NONE)
+                {
+                    skip = (* _itemSize[item->type]) (item);
+
+                    OutputBuffer->start += skip;
+                    OutputBuffer->count -= 1;
+
+                    item->type = gceBUFITEM_NONE;
+                    item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+                }
+
+                OutputBuffer->start = 0;
+            }
+
+            OutputBuffer->index = 0;
+        }
+
+        item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->start];
+
+        while (OutputBuffer->start - OutputBuffer->index <= Size)
+        {
+            skip = (* _itemSize[item->type]) (item);
+
+            OutputBuffer->start += skip;
+            OutputBuffer->count -= 1;
+
+            item->type = gceBUFITEM_NONE;
+            item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+            if (item->type == gceBUFITEM_NONE)
+            {
+                OutputBuffer->start = 0;
+                break;
+            }
+        }
+    }
+#else
+    if (OutputBuffer->index + Size > gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
+    {
+        _DirectPrint("\nMessage buffer full; forcing message flush.\n\n");
+        _Flush(~0U);
+    }
+#endif
+
+    item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->index];
+
+    OutputBuffer->index += Size;
+    OutputBuffer->count += 1;
+
+    next = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + Size);
+    next->type = gceBUFITEM_NONE;
+
+    return item;
+}
+
+#if gcdALIGNBYSIZE
+static void
+_FreeExtraSpace(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gctPOINTER Item,
+    IN gctINT ItemSize,
+    IN gctINT FreeSize
+    )
+{
+    gcsBUFITEM_HEAD_PTR next;
+
+    OutputBuffer->index -= FreeSize;
+
+    next = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) Item + ItemSize);
+    next->type = gceBUFITEM_NONE;
+}
+#endif
+
+#if gcdHAVEPREFIX
+static void
+_AppendPrefix(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gctPOINTER Data
+    )
+{
+    gctUINT8_PTR prefixData;
+    gcsBUFITEM_PREFIX_PTR item;
+    gctINT allocSize;
+
+#if gcdALIGNBYSIZE
+    gctUINT alignment;
+    gctINT size, freeSize;
+#endif
+
+    gcmDBGASSERT(Data != gcvNULL, "%p", Data);
+
+    /* Determine the maximum item size. */
+    allocSize
+        = gcmSIZEOF(gcsBUFITEM_PREFIX)
+        + gcdPREFIX_SIZE
+        + gcdPREFIX_ALIGNMENT;
+
+    /* Allocate prefix item. */
+    item = (gcsBUFITEM_PREFIX_PTR) _AllocateItem(OutputBuffer, allocSize);
+
+    /* Compute the initial prefix data pointer. */
+    prefixData = (gctUINT8_PTR) (item + 1);
+
+    /* Align the data pointer as necessary. */
+#if gcdALIGNBYSIZE
+    alignment = gcmPTRALIGNMENT(prefixData, gcdPREFIX_ALIGNMENT);
+    prefixData += alignment;
+#endif
+
+    /* Set item data. */
+    item->type       = gcvBUFITEM_PREFIX;
+    item->prefixData = prefixData;
+
+    /* Copy argument value. */
+    memcpy(prefixData, Data, gcdPREFIX_SIZE);
+
+#if gcdALIGNBYSIZE
+    /* Compute the actual node size. */
+    size = gcmSIZEOF(gcsBUFITEM_PREFIX) + gcdPREFIX_SIZE + alignment;
+
+    /* Free extra memory if any. */
+    freeSize = allocSize - size;
+    if (freeSize != 0)
+    {
+        _FreeExtraSpace(OutputBuffer, item, size, freeSize);
+    }
+#endif
+}
+#endif
+
+static void
+_AppendString(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gctINT Indent,
+    IN gctCONST_STRING Message,
+    IN gctUINT ArgumentSize,
+    IN gctPOINTER Data
+    )
+{
+    gctUINT8_PTR messageData;
+    gcsBUFITEM_STRING_PTR item;
+    gctINT allocSize;
+
+#if gcdALIGNBYSIZE
+    gctUINT alignment;
+    gctINT size, freeSize;
+#endif
+
+    /* Determine the maximum item size. */
+    allocSize
+        = gcmSIZEOF(gcsBUFITEM_STRING)
+        + ArgumentSize
+        + gcdVARARG_ALIGNMENT;
+
+    /* Allocate prefix item. */
+    item = (gcsBUFITEM_STRING_PTR) _AllocateItem(OutputBuffer, allocSize);
+
+    /* Compute the initial message data pointer. */
+    messageData = (gctUINT8_PTR) (item + 1);
+
+    /* Align the data pointer as necessary. */
+#if gcdALIGNBYSIZE
+    alignment = gcmPTRALIGNMENT(messageData, gcdVARARG_ALIGNMENT);
+    messageData += alignment;
+#endif
+
+    /* Set item data. */
+    item->type            = gcvBUFITEM_STRING;
+    item->indent          = Indent;
+    item->message         = Message;
+    item->messageData     = messageData;
+    item->messageDataSize = ArgumentSize;
+
+    /* Copy argument value. */
+    if (ArgumentSize != 0)
+    {
+        memcpy(messageData, Data, ArgumentSize);
+    }
+
+#if gcdALIGNBYSIZE
+    /* Compute the actual node size. */
+    size = gcmSIZEOF(gcsBUFITEM_STRING) + ArgumentSize + alignment;
+
+    /* Free extra memory if any. */
+    freeSize = allocSize - size;
+    if (freeSize != 0)
+    {
+        _FreeExtraSpace(OutputBuffer, item, size, freeSize);
+    }
+#endif
+}
+
+static void
+_AppendCopy(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gctINT Indent,
+    IN gctCONST_STRING Message,
+    IN gctUINT ArgumentSize,
+    IN gctPOINTER Data
+    )
+{
+    gctUINT8_PTR messageData;
+    gcsBUFITEM_COPY_PTR item;
+    gctINT allocSize;
+    gctINT messageLength;
+    gctCONST_STRING message;
+
+#if gcdALIGNBYSIZE
+    gctUINT alignment;
+    gctINT size, freeSize;
+#endif
+
+    /* Get the length of the string. */
+    messageLength = strlen(Message) + 1;
+
+    /* Determine the maximum item size. */
+    allocSize
+        = gcmSIZEOF(gcsBUFITEM_COPY)
+        + messageLength
+        + ArgumentSize
+        + gcdVARARG_ALIGNMENT;
+
+    /* Allocate prefix item. */
+    item = (gcsBUFITEM_COPY_PTR) _AllocateItem(OutputBuffer, allocSize);
+
+    /* Determine the message placement. */
+    message = (gctCONST_STRING) (item + 1);
+
+    /* Compute the initial message data pointer. */
+    messageData = (gctUINT8_PTR) message + messageLength;
+
+    /* Align the data pointer as necessary. */
+#if gcdALIGNBYSIZE
+    if (ArgumentSize == 0)
+    {
+        alignment = 0;
+    }
+    else
+    {
+        alignment = gcmPTRALIGNMENT(messageData, gcdVARARG_ALIGNMENT);
+        messageData += alignment;
+    }
+#endif
+
+    /* Set item data. */
+    item->type            = gcvBUFITEM_COPY;
+    item->indent          = Indent;
+    item->messageData     = messageData;
+    item->messageDataSize = ArgumentSize;
+
+    /* Copy the message. */
+    memcpy((gctPOINTER) message, Message, messageLength);
+
+    /* Copy argument value. */
+    if (ArgumentSize != 0)
+    {
+        memcpy(messageData, Data, ArgumentSize);
+    }
+
+#if gcdALIGNBYSIZE
+    /* Compute the actual node size. */
+    size
+        = gcmSIZEOF(gcsBUFITEM_COPY)
+        + messageLength
+        + ArgumentSize
+        + alignment;
+
+    /* Free extra memory if any. */
+    freeSize = allocSize - size;
+    if (freeSize != 0)
+    {
+        _FreeExtraSpace(OutputBuffer, item, size, freeSize);
+    }
+#endif
+}
+
+static void
+_AppendBuffer(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gctINT Indent,
+    IN gctPOINTER PrefixData,
+    IN gctPOINTER Data,
+    IN gctUINT Address,
+    IN gctUINT DataSize,
+    IN gceDUMP_BUFFER Type,
+    IN gctUINT32 DmaAddress
+    )
+{
+#if gcdHAVEPREFIX
+    gctUINT8_PTR prefixData;
+    gcsBUFITEM_BUFFER_PTR item;
+    gctINT allocSize;
+    gctPOINTER data;
+
+#if gcdALIGNBYSIZE
+    gctUINT alignment;
+    gctINT size, freeSize;
+#endif
+
+    gcmDBGASSERT(DataSize != 0, "%d", DataSize);
+    gcmDBGASSERT(Data != gcvNULL, "%p", Data);
+
+    /* Determine the maximum item size. */
+    allocSize
+        = gcmSIZEOF(gcsBUFITEM_BUFFER)
+        + gcdPREFIX_SIZE
+        + gcdPREFIX_ALIGNMENT
+        + DataSize;
+
+    /* Allocate prefix item. */
+    item = (gcsBUFITEM_BUFFER_PTR) _AllocateItem(OutputBuffer, allocSize);
+
+    /* Compute the initial prefix data pointer. */
+    prefixData = (gctUINT8_PTR) (item + 1);
+
+#if gcdALIGNBYSIZE
+    /* Align the data pointer as necessary. */
+    alignment = gcmPTRALIGNMENT(prefixData, gcdPREFIX_ALIGNMENT);
+    prefixData += alignment;
+#endif
+
+    /* Set item data. */
+    item->type       = gcvBUFITEM_BUFFER;
+    item->indent     = Indent;
+    item->bufferType = Type;
+    item->dataSize   = DataSize;
+    item->address    = Address;
+    item->prefixData = prefixData;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+    item->dmaAddress = DmaAddress;
+#endif
+
+    /* Copy prefix data. */
+    memcpy(prefixData, PrefixData, gcdPREFIX_SIZE);
+
+    /* Compute the data pointer. */
+    data = prefixData + gcdPREFIX_SIZE;
+
+    /* Copy argument value. */
+    memcpy(data, Data, DataSize);
+
+#if gcdALIGNBYSIZE
+    /* Compute the actual node size. */
+    size
+        = gcmSIZEOF(gcsBUFITEM_BUFFER)
+        + gcdPREFIX_SIZE
+        + alignment
+        + DataSize;
+
+    /* Free extra memory if any. */
+    freeSize = allocSize - size;
+    if (freeSize != 0)
+    {
+        _FreeExtraSpace(OutputBuffer, item, size, freeSize);
+    }
+#endif
+#else
+    gcsBUFITEM_BUFFER_PTR item;
+    gctINT size;
+
+    gcmDBGASSERT(DataSize != 0, "%d", DataSize);
+    gcmDBGASSERT(Data != gcvNULL, "%p", Data);
+
+    /* Determine the maximum item size. */
+    size = gcmSIZEOF(gcsBUFITEM_BUFFER) + DataSize;
+
+    /* Allocate prefix item. */
+    item = (gcsBUFITEM_BUFFER_PTR) _AllocateItem(OutputBuffer, size);
+
+    /* Set item data. */
+    item->type     = gcvBUFITEM_BUFFER;
+    item->indent   = Indent;
+    item->dataSize = DataSize;
+    item->address  = Address;
+
+    /* Copy argument value. */
+    memcpy(item + 1, Data, DataSize);
+#endif
+}
+#endif
+
+static gcmINLINE void
+_InitBuffers(
+    void
+    )
+{
+    int i;
+
+    if (_outputBufferHead == gcvNULL)
+    {
+        for (i = 0; i < gcdTHREAD_BUFFERS; i += 1)
+        {
+            if (_outputBufferTail == gcvNULL)
+            {
+                _outputBufferHead = &_outputBuffer[i];
+            }
+            else
+            {
+                _outputBufferTail->next = &_outputBuffer[i];
+            }
+
+#if gcdTHREAD_BUFFERS > 1
+            _outputBuffer[i].threadID = ~0U;
+#endif
+
+            _outputBuffer[i].prev = _outputBufferTail;
+            _outputBuffer[i].next =  gcvNULL;
+
+            _outputBufferTail = &_outputBuffer[i];
+        }
+    }
+}
+
+static gcmINLINE gcsBUFFERED_OUTPUT_PTR
+_GetOutputBuffer(
+    void
+    )
+{
+    gcsBUFFERED_OUTPUT_PTR outputBuffer;
+
+#if gcdTHREAD_BUFFERS > 1
+    /* Get the current thread ID. */
+    gctUINT32 threadID = gcmkGETTHREADID();
+
+    /* Locate the output buffer for the thread. */
+    outputBuffer = _outputBufferHead;
+
+    while (outputBuffer != gcvNULL)
+    {
+        if (outputBuffer->threadID == ThreadID)
+        {
+            break;
+        }
+
+        outputBuffer = outputBuffer->next;
+    }
+
+    /* No matching buffer found? */
+    if (outputBuffer == gcvNULL)
+    {
+        /* Get the tail for the buffer. */
+        outputBuffer = _outputBufferTail;
+
+        /* Move it to the head. */
+        _outputBufferTail       = _outputBufferTail->prev;
+        _outputBufferTail->next = gcvNULL;
+
+        outputBuffer->prev = gcvNULL;
+        outputBuffer->next = _outputBufferHead;
+
+        _outputBufferHead->prev = outputBuffer;
+        _outputBufferHead       = outputBuffer;
+
+        /* Reset the buffer. */
+        outputBuffer->threadID   = ThreadID;
+        outputBuffer->start      = 0;
+        outputBuffer->index      = 0;
+        outputBuffer->count      = 0;
+        outputBuffer->lineNumber = 0;
+    }
+#else
+    outputBuffer = _outputBufferHead;
+#endif
+
+    return outputBuffer;
+}
+
+static gcmINLINE int _GetArgumentSize(
+    IN gctCONST_STRING Message
+    )
+{
+    int i, count;
+
+    gcmDBGASSERT(Message != gcvNULL, "%p", Message);
+
+    for (i = 0, count = 0; Message[i]; i += 1)
+    {
+        if (Message[i] == '%')
+        {
+            count += 1;
+        }
+    }
+
+    return count * gcmSIZEOF(gctUINT32);
+}
+
+#if gcdHAVEPREFIX
+static void
+_InitPrefixData(
+    IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+    IN gctPOINTER Data
+    )
+{
+    gctUINT8_PTR data  = (gctUINT8_PTR) Data;
+
+#if gcdSHOW_TIME
+    {
+        gctUINT64 time;
+        gckOS_GetProfileTick(&time);
+        gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT64));
+        * ((gctUINT64_PTR) data) = time;
+        data += gcmSIZEOF(gctUINT64);
+    }
+#endif
+
+#if gcdSHOW_LINE_NUMBER
+    {
+        gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT64));
+        * ((gctUINT64_PTR) data) = OutputBuffer->lineNumber;
+        data += gcmSIZEOF(gctUINT64);
+    }
+#endif
+
+#if gcdSHOW_PROCESS_ID
+    {
+        gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT32));
+        * ((gctUINT32_PTR) data) = gcmkGETPROCESSID();
+        data += gcmSIZEOF(gctUINT32);
+    }
+#endif
+
+#if gcdSHOW_THREAD_ID
+    {
+        gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT32));
+        * ((gctUINT32_PTR) data) = gcmkGETTHREADID();
+    }
+#endif
+}
+#endif
+
+static void
+_Print(
+    IN gctUINT ArgumentSize,
+    IN gctBOOL CopyMessage,
+    IN gctCONST_STRING Message,
+    IN gctARGUMENTS Arguments
+    )
+{
+    gcsBUFFERED_OUTPUT_PTR outputBuffer;
+    gcmkDECLARE_LOCK(lockHandle);
+
+    gcmkLOCKSECTION(lockHandle);
+
+    /* Initialize output buffer list. */
+    _InitBuffers();
+
+    /* Locate the proper output buffer. */
+    outputBuffer = _GetOutputBuffer();
+
+    /* Update the line number. */
+#if gcdSHOW_LINE_NUMBER
+    outputBuffer->lineNumber += 1;
+#endif
+
+    /* Print prefix. */
+#if gcdHAVEPREFIX
+    {
+        gctUINT8_PTR alignedPrefixData;
+        gctUINT8 prefixData[gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT];
+
+        /* Compute aligned pointer. */
+        alignedPrefixData = prefixData;
+        gcmkALIGNPTR(gctUINT8_PTR, alignedPrefixData, gcdPREFIX_ALIGNMENT);
+
+        /* Initialize the prefix data. */
+        _InitPrefixData(outputBuffer, alignedPrefixData);
+
+        /* Print the prefix. */
+        gcdOUTPUTPREFIX(outputBuffer, alignedPrefixData);
+    }
+#endif
+
+    /* Form the indent string. */
+    if (strncmp(Message, "--", 2) == 0)
+    {
+        outputBuffer->indent -= 2;
+    }
+
+    /* Print the message. */
+    if (CopyMessage)
+    {
+        gcdOUTPUTCOPY(
+            outputBuffer, outputBuffer->indent,
+            Message, ArgumentSize, * (gctPOINTER *) &Arguments
+            );
+    }
+    else
+    {
+        gcdOUTPUTSTRING(
+            outputBuffer, outputBuffer->indent,
+            Message, ArgumentSize, * (gctPOINTER *) &Arguments
+            );
+    }
+
+    /* Check increasing indent. */
+    if (strncmp(Message, "++", 2) == 0)
+    {
+        outputBuffer->indent += 2;
+    }
+
+    gcmkUNLOCKSECTION(lockHandle);
+}
+
+
+/******************************************************************************\
+********************************* Debug Macros *********************************
+\******************************************************************************/
+
+#define gcmDEBUGPRINT(ArgumentSize, CopyMessage, Message) \
+{ \
+    gctARGUMENTS __arguments__; \
+    gcmkARGUMENTS_START(__arguments__, Message); \
+    _Print(ArgumentSize, CopyMessage, Message, __arguments__); \
+    gcmkARGUMENTS_END(__arguments__); \
+}
+
+
+/******************************************************************************\
+********************************** Debug Code **********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckOS_Print
+**
+**  Send a message to the debugger.
+**
+**  INPUT:
+**
+**      gctCONST_STRING Message
+**          Pointer to message.
+**
+**      ...
+**          Optional arguments.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_Print(
+    IN gctCONST_STRING Message,
+    ...
+    )
+{
+    gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+**  gckOS_PrintN
+**
+**  Send a message to the debugger.
+**
+**  INPUT:
+**
+**      gctUINT ArgumentSize
+**          The size of the optional arguments in bytes.
+**
+**      gctCONST_STRING Message
+**          Pointer to message.
+**
+**      ...
+**          Optional arguments.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_PrintN(
+    IN gctUINT ArgumentSize,
+    IN gctCONST_STRING Message,
+    ...
+    )
+{
+    gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+**  gckOS_CopyPrint
+**
+**  Send a message to the debugger. If in buffered output mode, the entire
+**  message will be copied into the buffer instead of using the pointer to
+**  the string.
+**
+**  INPUT:
+**
+**      gctCONST_STRING Message
+**          Pointer to message.
+**
+**      ...
+**          Optional arguments.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_CopyPrint(
+    IN gctCONST_STRING Message,
+    ...
+    )
+{
+    gcmDEBUGPRINT(_GetArgumentSize(Message), gcvTRUE, Message);
+}
+
+/*******************************************************************************
+**
+**  gckOS_DumpBuffer
+**
+**  Print the contents of the specified buffer.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to gckOS object.
+**
+**      gctPOINTER Buffer
+**          Pointer to the buffer to print.
+**
+**      gctUINT Size
+**          Size of the buffer.
+**
+**      gceDUMP_BUFFER Type
+**          Buffer type.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_DumpBuffer(
+    IN gckOS Os,
+    IN gctPOINTER Buffer,
+    IN gctUINT Size,
+    IN gceDUMP_BUFFER Type,
+    IN gctBOOL CopyMessage
+    )
+{
+    gctUINT32 address;
+    gcsBUFFERED_OUTPUT_PTR outputBuffer;
+    static gctBOOL userLocked;
+    gctCHAR *buffer = (gctCHAR*)Buffer;
+
+    gcmkDECLARE_LOCK(lockHandle);
+
+    /* Request lock when not coming from user,
+       or coming from user and not yet locked
+          and message is starting with @[. */
+    if (Type == gceDUMP_BUFFER_FROM_USER)
+    {
+        if ((Size > 2)
+        && (buffer[0] == '@')
+        && (buffer[1] == '['))
+        {
+            /* Beginning of a user dump. */
+            gcmkLOCKSECTION(lockHandle);
+            userLocked = gcvTRUE;
+        }
+        /* Else, let it pass through. */
+    }
+    else
+    {
+        gcmkLOCKSECTION(lockHandle);
+        userLocked = gcvFALSE;
+    }
+
+    if (Buffer != gcvNULL)
+    {
+        /* Initialize output buffer list. */
+        _InitBuffers();
+
+        /* Locate the proper output buffer. */
+        outputBuffer = _GetOutputBuffer();
+
+        /* Update the line number. */
+#if gcdSHOW_LINE_NUMBER
+        outputBuffer->lineNumber += 1;
+#endif
+
+        /* Get the physical address of the buffer. */
+        if (Type != gceDUMP_BUFFER_FROM_USER)
+        {
+            gcmkVERIFY_OK(gckOS_GetPhysicalAddress(Os, Buffer, &address));
+        }
+        else
+        {
+            address = 0;
+        }
+
+#if gcdHAVEPREFIX
+        {
+            gctUINT8_PTR alignedPrefixData;
+            gctUINT8 prefixData[gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT];
+
+            /* Compute aligned pointer. */
+            alignedPrefixData = prefixData;
+            gcmkALIGNPTR(gctUINT8_PTR, alignedPrefixData, gcdPREFIX_ALIGNMENT);
+
+            /* Initialize the prefix data. */
+            _InitPrefixData(outputBuffer, alignedPrefixData);
+
+            /* Print/schedule the buffer. */
+            gcdOUTPUTBUFFER(
+                outputBuffer, outputBuffer->indent,
+                alignedPrefixData, Buffer, address, Size, Type, 0
+                );
+        }
+#else
+        /* Print/schedule the buffer. */
+        if (Type == gceDUMP_BUFFER_FROM_USER)
+        {
+            gcdOUTPUTSTRING(
+                outputBuffer, outputBuffer->indent,
+                Buffer, 0, gcvNULL
+                );
+        }
+        else
+        {
+            gcdOUTPUTBUFFER(
+                outputBuffer, outputBuffer->indent,
+                gcvNULL, Buffer, address, Size, Type, 0
+                );
+        }
+#endif
+    }
+
+    /* Unlock when not coming from user,
+       or coming from user and not yet locked. */
+    if (userLocked)
+    {
+        if ((Size > 4)
+        && (buffer[0] == ']')
+        && (buffer[1] == ' ')
+        && (buffer[2] == '-')
+        && (buffer[3] == '-'))
+        {
+            /* End of a user dump. */
+            gcmkUNLOCKSECTION(lockHandle);
+            userLocked = gcvFALSE;
+        }
+        /* Else, let it pass through, don't unlock. */
+    }
+    else
+    {
+        gcmkUNLOCKSECTION(lockHandle);
+    }
+}
+
+/*******************************************************************************
+**
+**  gckOS_DebugTrace
+**
+**  Send a leveled message to the debugger.
+**
+**  INPUT:
+**
+**      gctUINT32 Level
+**          Debug level of message.
+**
+**      gctCONST_STRING Message
+**          Pointer to message.
+**
+**      ...
+**          Optional arguments.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_DebugTrace(
+    IN gctUINT32 Level,
+    IN gctCONST_STRING Message,
+    ...
+    )
+{
+    if (Level > _debugLevel)
+    {
+        return;
+    }
+
+    gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+**  gckOS_DebugTraceN
+**
+**  Send a leveled message to the debugger.
+**
+**  INPUT:
+**
+**      gctUINT32 Level
+**          Debug level of message.
+**
+**      gctUINT ArgumentSize
+**          The size of the optional arguments in bytes.
+**
+**      gctCONST_STRING Message
+**          Pointer to message.
+**
+**      ...
+**          Optional arguments.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_DebugTraceN(
+    IN gctUINT32 Level,
+    IN gctUINT ArgumentSize,
+    IN gctCONST_STRING Message,
+    ...
+    )
+{
+    if (Level > _debugLevel)
+    {
+        return;
+    }
+
+    gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+**  gckOS_DebugTraceZone
+**
+**  Send a leveled and zoned message to the debugger.
+**
+**  INPUT:
+**
+**      gctUINT32 Level
+**          Debug level for message.
+**
+**      gctUINT32 Zone
+**          Debug zone for message.
+**
+**      gctCONST_STRING Message
+**          Pointer to message.
+**
+**      ...
+**          Optional arguments.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_DebugTraceZone(
+    IN gctUINT32 Level,
+    IN gctUINT32 Zone,
+    IN gctCONST_STRING Message,
+    ...
+    )
+{
+    if ((Level > _debugLevel) || !(Zone & _debugZones))
+    {
+        return;
+    }
+
+    gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+**  gckOS_DebugTraceZoneN
+**
+**  Send a leveled and zoned message to the debugger.
+**
+**  INPUT:
+**
+**      gctUINT32 Level
+**          Debug level for message.
+**
+**      gctUINT32 Zone
+**          Debug zone for message.
+**
+**      gctUINT ArgumentSize
+**          The size of the optional arguments in bytes.
+**
+**      gctCONST_STRING Message
+**          Pointer to message.
+**
+**      ...
+**          Optional arguments.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_DebugTraceZoneN(
+    IN gctUINT32 Level,
+    IN gctUINT32 Zone,
+    IN gctUINT ArgumentSize,
+    IN gctCONST_STRING Message,
+    ...
+    )
+{
+    if ((Level > _debugLevel) || !(Zone & _debugZones))
+    {
+        return;
+    }
+
+    gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+**  gckOS_DebugBreak
+**
+**  Break into the debugger.
+**
+**  INPUT:
+**
+**      Nothing.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+void
+gckOS_DebugBreak(
+    void
+    )
+{
+    gckOS_DebugTrace(gcvLEVEL_ERROR, "%s(%d)", __FUNCTION__, __LINE__);
+}
+
+/*******************************************************************************
+**
+**  gckOS_DebugFatal
+**
+**  Send a message to the debugger and break into the debugger.
+**
+**  INPUT:
+**
+**      gctCONST_STRING Message
+**          Pointer to message.
+**
+**      ...
+**          Optional arguments.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+void
+gckOS_DebugFatal(
+    IN gctCONST_STRING Message,
+    ...
+    )
+{
+    gcmkPRINT_VERSION();
+    gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
+
+    /* Break into the debugger. */
+    gckOS_DebugBreak();
+}
+
+/*******************************************************************************
+**
+**  gckOS_SetDebugLevel
+**
+**  Set the debug level.
+**
+**  INPUT:
+**
+**      gctUINT32 Level
+**          New debug level.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_SetDebugLevel(
+    IN gctUINT32 Level
+    )
+{
+    _debugLevel = Level;
+}
+
+/*******************************************************************************
+**
+**  gckOS_SetDebugZone
+**
+**  Set the debug zone.
+**
+**  INPUT:
+**
+**      gctUINT32 Zone
+**          New debug zone.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+void
+gckOS_SetDebugZone(
+    IN gctUINT32 Zone
+    )
+{
+    _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+**  gckOS_SetDebugLevelZone
+**
+**  Set the debug level and zone.
+**
+**  INPUT:
+**
+**      gctUINT32 Level
+**          New debug level.
+**
+**      gctUINT32 Zone
+**          New debug zone.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_SetDebugLevelZone(
+    IN gctUINT32 Level,
+    IN gctUINT32 Zone
+    )
+{
+    _debugLevel = Level;
+    _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+**  gckOS_SetDebugZones
+**
+**  Enable or disable debug zones.
+**
+**  INPUT:
+**
+**      gctUINT32 Zones
+**          Debug zones to enable or disable.
+**
+**      gctBOOL Enable
+**          Set to gcvTRUE to enable the zones (or the Zones with the current
+**          zones) or gcvFALSE to disable the specified Zones.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_SetDebugZones(
+    IN gctUINT32 Zones,
+    IN gctBOOL Enable
+    )
+{
+    if (Enable)
+    {
+        /* Enable the zones. */
+        _debugZones |= Zones;
+    }
+    else
+    {
+        /* Disable the zones. */
+        _debugZones &= ~Zones;
+    }
+}
+
+/*******************************************************************************
+**
+**  gckOS_Verify
+**
+**  Called to verify the result of a function call.
+**
+**  INPUT:
+**
+**      gceSTATUS Status
+**          Function call result.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_Verify(
+    IN gceSTATUS Status
+    )
+{
+    _lastError = Status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_DebugFlush
+**
+**  Force messages to be flushed out.
+**
+**  INPUT:
+**
+**      gctCONST_STRING CallerName
+**          Name of the caller function.
+**
+**      gctUINT LineNumber
+**          Line number of the caller.
+**
+**      gctUINT32 DmaAddress
+**          The current DMA address or ~0U to ignore.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+void
+gckOS_DebugFlush(
+    gctCONST_STRING CallerName,
+    gctUINT LineNumber,
+    gctUINT32 DmaAddress
+    )
+{
+#if gcdBUFFERED_OUTPUT
+    _DirectPrint("\nFlush requested by %s(%d).\n\n", CallerName, LineNumber);
+    _Flush(DmaAddress);
+#endif
+}
+gctCONST_STRING
+gckOS_DebugStatus2Name(
+       gceSTATUS status
+       )
+{
+       switch (status)
+       {
+       case gcvSTATUS_OK:
+               return "gcvSTATUS_OK";
+       case gcvSTATUS_TRUE:
+               return "gcvSTATUS_TRUE";
+       case gcvSTATUS_NO_MORE_DATA:
+               return "gcvSTATUS_NO_MORE_DATA";
+       case gcvSTATUS_CACHED:
+               return "gcvSTATUS_CACHED";
+       case gcvSTATUS_MIPMAP_TOO_LARGE:
+               return "gcvSTATUS_MIPMAP_TOO_LARGE";
+       case gcvSTATUS_NAME_NOT_FOUND:
+               return "gcvSTATUS_NAME_NOT_FOUND";
+       case gcvSTATUS_NOT_OUR_INTERRUPT:
+               return "gcvSTATUS_NOT_OUR_INTERRUPT";
+       case gcvSTATUS_MISMATCH:
+               return "gcvSTATUS_MISMATCH";
+       case gcvSTATUS_MIPMAP_TOO_SMALL:
+               return "gcvSTATUS_MIPMAP_TOO_SMALL";
+       case gcvSTATUS_LARGER:
+               return "gcvSTATUS_LARGER";
+       case gcvSTATUS_SMALLER:
+               return "gcvSTATUS_SMALLER";
+       case gcvSTATUS_CHIP_NOT_READY:
+               return "gcvSTATUS_CHIP_NOT_READY";
+       case gcvSTATUS_NEED_CONVERSION:
+               return "gcvSTATUS_NEED_CONVERSION";
+       case gcvSTATUS_SKIP:
+               return "gcvSTATUS_SKIP";
+       case gcvSTATUS_DATA_TOO_LARGE:
+               return "gcvSTATUS_DATA_TOO_LARGE";
+       case gcvSTATUS_INVALID_CONFIG:
+               return "gcvSTATUS_INVALID_CONFIG";
+       case gcvSTATUS_CHANGED:
+               return "gcvSTATUS_CHANGED";
+       case gcvSTATUS_NOT_SUPPORT_DITHER:
+               return "gcvSTATUS_NOT_SUPPORT_DITHER";
+
+       case gcvSTATUS_INVALID_ARGUMENT:
+               return "gcvSTATUS_INVALID_ARGUMENT";
+       case gcvSTATUS_INVALID_OBJECT:
+               return "gcvSTATUS_INVALID_OBJECT";
+       case gcvSTATUS_OUT_OF_MEMORY:
+               return "gcvSTATUS_OUT_OF_MEMORY";
+       case gcvSTATUS_MEMORY_LOCKED:
+               return "gcvSTATUS_MEMORY_LOCKED";
+       case gcvSTATUS_MEMORY_UNLOCKED:
+               return "gcvSTATUS_MEMORY_UNLOCKED";
+       case gcvSTATUS_HEAP_CORRUPTED:
+               return "gcvSTATUS_HEAP_CORRUPTED";
+       case gcvSTATUS_GENERIC_IO:
+               return "gcvSTATUS_GENERIC_IO";
+       case gcvSTATUS_INVALID_ADDRESS:
+               return "gcvSTATUS_INVALID_ADDRESS";
+       case gcvSTATUS_CONTEXT_LOSSED:
+               return "gcvSTATUS_CONTEXT_LOSSED";
+       case gcvSTATUS_TOO_COMPLEX:
+               return "gcvSTATUS_TOO_COMPLEX";
+       case gcvSTATUS_BUFFER_TOO_SMALL:
+               return "gcvSTATUS_BUFFER_TOO_SMALL";
+       case gcvSTATUS_INTERFACE_ERROR:
+               return "gcvSTATUS_INTERFACE_ERROR";
+       case gcvSTATUS_NOT_SUPPORTED:
+               return "gcvSTATUS_NOT_SUPPORTED";
+       case gcvSTATUS_MORE_DATA:
+               return "gcvSTATUS_MORE_DATA";
+       case gcvSTATUS_TIMEOUT:
+               return "gcvSTATUS_TIMEOUT";
+       case gcvSTATUS_OUT_OF_RESOURCES:
+               return "gcvSTATUS_OUT_OF_RESOURCES";
+       case gcvSTATUS_INVALID_DATA:
+               return "gcvSTATUS_INVALID_DATA";
+       case gcvSTATUS_INVALID_MIPMAP:
+               return "gcvSTATUS_INVALID_MIPMAP";
+       case gcvSTATUS_NOT_FOUND:
+               return "gcvSTATUS_NOT_FOUND";
+       case gcvSTATUS_NOT_ALIGNED:
+               return "gcvSTATUS_NOT_ALIGNED";
+       case gcvSTATUS_INVALID_REQUEST:
+               return "gcvSTATUS_INVALID_REQUEST";
+       case gcvSTATUS_GPU_NOT_RESPONDING:
+               return "gcvSTATUS_GPU_NOT_RESPONDING";
+       case gcvSTATUS_TIMER_OVERFLOW:
+               return "gcvSTATUS_TIMER_OVERFLOW";
+       case gcvSTATUS_VERSION_MISMATCH:
+               return "gcvSTATUS_VERSION_MISMATCH";
+       case gcvSTATUS_LOCKED:
+               return "gcvSTATUS_LOCKED";
+
+    /* Linker errors. */
+       case gcvSTATUS_GLOBAL_TYPE_MISMATCH:
+               return "gcvSTATUS_GLOBAL_TYPE_MISMATCH";
+       case gcvSTATUS_TOO_MANY_ATTRIBUTES:
+               return "gcvSTATUS_TOO_MANY_ATTRIBUTES";
+       case gcvSTATUS_TOO_MANY_UNIFORMS:
+               return "gcvSTATUS_TOO_MANY_UNIFORMS";
+       case gcvSTATUS_TOO_MANY_VARYINGS:
+               return "gcvSTATUS_TOO_MANY_VARYINGS";
+       case gcvSTATUS_UNDECLARED_VARYING:
+               return "gcvSTATUS_UNDECLARED_VARYING";
+       case gcvSTATUS_VARYING_TYPE_MISMATCH:
+               return "gcvSTATUS_VARYING_TYPE_MISMATCH";
+       case gcvSTATUS_MISSING_MAIN:
+               return "gcvSTATUS_MISSING_MAIN";
+       case gcvSTATUS_NAME_MISMATCH:
+               return "gcvSTATUS_NAME_MISMATCH";
+       case gcvSTATUS_INVALID_INDEX:
+               return "gcvSTATUS_INVALID_INDEX";
+       default:
+               return "nil";
+       }
+}
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
new file mode 100644 (file)
index 0000000..e9050f1
--- /dev/null
@@ -0,0 +1,2590 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*    Copyright (C) 2011 Freescale Semiconductor, Inc. 
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+#include "gc_hal_kernel_buffer.h"
+
+#ifdef __QNXNTO__
+#include <atomic.h>
+#include "gc_hal_kernel_qnx.h"
+#endif
+
+#ifdef LINUX
+#include <asm/atomic.h>
+#endif
+
+#define _GC_OBJ_ZONE                    gcvZONE_EVENT
+
+#define gcdEVENT_ALLOCATION_COUNT       (4096 / gcmSIZEOF(gcsHAL_INTERFACE))
+#define gcdEVENT_MIN_THRESHOLD          4
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+static gceSTATUS
+gckEVENT_AllocateQueue(
+    IN gckEVENT Event,
+    OUT gcsEVENT_QUEUE_PTR * Queue
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Event=0x%x", Event);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
+
+    /* Do we have free queues? */
+    if (Event->freeList == gcvNULL)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+    }
+
+    /* Move one free queue from the free list. */
+    * Queue = Event->freeList;
+    Event->freeList = Event->freeList->next;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Queue=0x%x", gcmOPT_POINTER(Queue));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+static gceSTATUS
+gckEVENT_FreeQueue(
+    IN gckEVENT Event,
+    OUT gcsEVENT_QUEUE_PTR Queue
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+
+    gcmkHEADER_ARG("Event=0x%x", Event);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
+
+    /* Move one free queue from the free list. */
+    Queue->next = Event->freeList;
+    Event->freeList = Queue;
+
+    /* Success. */
+    gcmkFOOTER();
+    return status;
+}
+
+static gceSTATUS
+gckEVENT_FreeRecord(
+    IN gckEVENT Event,
+    IN gcsEVENT_PTR Record
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+    /* Acquire the mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(Event->os,
+                                   Event->freeEventMutex,
+                                   gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Push the record on the free list. */
+    Record->next           = Event->freeEventList;
+    Event->freeEventList   = Record;
+    Event->freeEventCount += 1;
+
+    /* Release the mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+}
+
+#ifndef __QNXNTO__
+
+static gceSTATUS
+gckEVENT_IsEmpty(
+    IN gckEVENT Event,
+    OUT gctBOOL_PTR IsEmpty
+    )
+{
+    gceSTATUS status;
+    gctSIZE_T i;
+
+    gcmkHEADER_ARG("Event=0x%x", Event);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(IsEmpty != gcvNULL);
+
+    /* Assume the event queue is empty. */
+    *IsEmpty = gcvTRUE;
+
+    /* Walk the event queue. */
+    for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+    {
+        /* Check whether this event is in use. */
+        if (Event->queues[i].head != gcvNULL)
+        {
+            /* The event is in use, hence the queue is not empty. */
+            *IsEmpty = gcvFALSE;
+            break;
+        }
+    }
+
+    /* Try acquiring the mutex. */
+    status = gckOS_AcquireMutex(Event->os, Event->eventQueueMutex, 0);
+    if (status == gcvSTATUS_TIMEOUT)
+    {
+        /* Timeout - queue is no longer empty. */
+        *IsEmpty = gcvFALSE;
+    }
+    else
+    {
+        /* Bail out on error. */
+        gcmkONERROR(status);
+
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*IsEmpty=%d", gcmOPT_VALUE(IsEmpty));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+#endif
+
+static gceSTATUS
+__RemoveRecordFromProcessDB(
+    IN gckEVENT Event,
+    IN gcsEVENT_PTR Record
+    )
+{
+    gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
+    gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+    while (Record != gcvNULL)
+    {
+        switch (Record->info.command)
+        {
+        case gcvHAL_FREE_NON_PAGED_MEMORY:
+            gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+                Event->kernel,
+                Record->processID,
+                gcvDB_NON_PAGED,
+                Record->info.u.FreeNonPagedMemory.logical));
+            break;
+
+        case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+            gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+                Event->kernel,
+                Record->processID,
+                gcvDB_CONTIGUOUS,
+                Record->info.u.FreeContiguousMemory.logical));
+            break;
+
+        case gcvHAL_FREE_VIDEO_MEMORY:
+            gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+                Event->kernel,
+                Record->processID,
+                gcvDB_VIDEO_MEMORY,
+                Record->info.u.FreeVideoMemory.node));
+            break;
+
+        case gcvHAL_UNLOCK_VIDEO_MEMORY:
+            gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+                Event->kernel,
+                Record->processID,
+                gcvDB_VIDEO_MEMORY_LOCKED,
+                Record->info.u.UnlockVideoMemory.node));
+            break;
+
+        default:
+            break;
+        }
+
+        Record = Record->next;
+    }
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_IsEmpty(
+    IN gckEVENT Event,
+    OUT gctBOOL_PTR IsEmpty
+    )
+{
+    gceSTATUS status;
+    gctSIZE_T i;
+
+    gcmkHEADER_ARG("Event=0x%x", Event);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(IsEmpty != gcvNULL);
+
+    /* Assume the event queue is empty. */
+    *IsEmpty = gcvTRUE;
+
+    /* Walk the event queue. */
+    for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+    {
+        /* Check whether this event is in use. */
+        if (Event->queues[i].head != gcvNULL)
+        {
+            /* The event is in use, hence the queue is not empty. */
+            *IsEmpty = gcvFALSE;
+            break;
+        }
+    }
+
+    /* Try acquiring the mutex. */
+    status = gckOS_AcquireMutex(Event->os, Event->eventQueueMutex, 0);
+    if (status == gcvSTATUS_TIMEOUT)
+    {
+        /* Timeout - queue is no longer empty. */
+        *IsEmpty = gcvFALSE;
+    }
+    else
+    {
+        /* Bail out on error. */
+        gcmkONERROR(status);
+
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*IsEmpty=%d", gcmOPT_VALUE(IsEmpty));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/******************************************************************************\
+******************************* gckEVENT API Code *******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckEVENT_Construct
+**
+**  Construct a new gckEVENT object.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**  OUTPUT:
+**
+**      gckEVENT * Event
+**          Pointer to a variable that receives the gckEVENT object pointer.
+*/
+gceSTATUS
+gckEVENT_Construct(
+    IN gckKERNEL Kernel,
+    OUT gckEVENT * Event
+    )
+{
+    gckOS os;
+    gceSTATUS status;
+    gckEVENT eventObj = gcvNULL;
+    int i;
+    gcsEVENT_PTR record;
+    gctPOINTER pointer = gcvNULL;
+
+    gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Event != gcvNULL);
+
+    /* Extract the pointer to the gckOS object. */
+    os = Kernel->os;
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+    /* Allocate the gckEVENT object. */
+    gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckEVENT), &pointer));
+
+    eventObj = pointer;
+
+    /* Reset the object. */
+    gcmkVERIFY_OK(gckOS_ZeroMemory(eventObj, gcmSIZEOF(struct _gckEVENT)));
+
+    /* Initialize the gckEVENT object. */
+    eventObj->object.type = gcvOBJ_EVENT;
+    eventObj->kernel      = Kernel;
+    eventObj->os          = os;
+
+    /* Create the mutexes. */
+    gcmkONERROR(gckOS_CreateMutex(os, &eventObj->eventQueueMutex));
+    gcmkONERROR(gckOS_CreateMutex(os, &eventObj->freeEventMutex));
+    gcmkONERROR(gckOS_CreateMutex(os, &eventObj->eventListMutex));
+
+    /* Create a bunch of event reccords. */
+    for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; i += 1)
+    {
+        /* Allocate an event record. */
+        gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsEVENT), &pointer));
+
+        record = pointer;
+
+        /* Push it on the free list. */
+        record->next              = eventObj->freeEventList;
+        eventObj->freeEventList   = record;
+        eventObj->freeEventCount += 1;
+    }
+
+    /* Initialize the free list of event queues. */
+    for (i = 0; i < gcdREPO_LIST_COUNT; i += 1)
+    {
+        eventObj->repoList[i].next = eventObj->freeList;
+        eventObj->freeList = &eventObj->repoList[i];
+    }
+
+    /* Construct the atom. */
+    gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->freeAtom));
+    gcmkONERROR(gckOS_AtomSet(os,
+                              eventObj->freeAtom,
+                              gcmCOUNTOF(eventObj->queues)));
+
+    /* Return pointer to the gckEVENT object. */
+    *Event = eventObj;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Event=0x%x", *Event);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (eventObj != gcvNULL)
+    {
+        if (eventObj->eventQueueMutex != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->eventQueueMutex));
+        }
+
+        if (eventObj->freeEventMutex != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->freeEventMutex));
+        }
+
+        if (eventObj->eventListMutex != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->eventListMutex));
+        }
+
+        while (eventObj->freeEventList != gcvNULL)
+        {
+            record = eventObj->freeEventList;
+            eventObj->freeEventList = record->next;
+
+            gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, record));
+        }
+
+        if (eventObj->freeAtom != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->freeAtom));
+        }
+
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, eventObj));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_Destroy
+**
+**  Destroy an gckEVENT object.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckEVENT_Destroy(
+    IN gckEVENT Event
+    )
+{
+    gcsEVENT_PTR record;
+    gcsEVENT_QUEUE_PTR queue;
+
+    gcmkHEADER_ARG("Event=0x%x", Event);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+    /* Delete the queue mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->eventQueueMutex));
+
+    /* Free all free events. */
+    while (Event->freeEventList != gcvNULL)
+    {
+        record = Event->freeEventList;
+        Event->freeEventList = record->next;
+
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, record));
+    }
+
+    /* Delete the free mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->freeEventMutex));
+
+    /* Free all pending queues. */
+    while (Event->queueHead != gcvNULL)
+    {
+        /* Get the current queue. */
+        queue = Event->queueHead;
+
+        /* Free all pending events. */
+        while (queue->head != gcvNULL)
+        {
+            record      = queue->head;
+            queue->head = record->next;
+
+            gcmkTRACE_ZONE_N(
+                gcvLEVEL_WARNING, gcvZONE_EVENT,
+                gcmSIZEOF(record) + gcmSIZEOF(queue->source),
+                "Event record 0x%x is still pending for %d.",
+                record, queue->source
+                );
+
+            gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, record));
+        }
+
+        /* Remove the top queue from the list. */
+        if (Event->queueHead == Event->queueTail)
+        {
+            Event->queueHead =
+            Event->queueTail = gcvNULL;
+        }
+        else
+        {
+            Event->queueHead = Event->queueHead->next;
+        }
+
+        /* Free the queue. */
+        gcmkVERIFY_OK(gckEVENT_FreeQueue(Event, queue));
+    }
+
+    /* Delete the list mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->eventListMutex));
+
+    /* Delete the atom. */
+    gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->freeAtom));
+
+    /* Mark the gckEVENT object as unknown. */
+    Event->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the gckEVENT object. */
+    gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, Event));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_GetEvent
+**
+**  Reserve the next available hardware event.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gctBOOL Wait
+**          Set to gcvTRUE to force the function to wait if no events are
+**          immediately available.
+**
+**      gceKERNEL_WHERE Source
+**          Source of the event.
+**
+**  OUTPUT:
+**
+**      gctUINT8 * EventID
+**          Reserved event ID.
+*/
+gceSTATUS
+gckEVENT_GetEvent(
+    IN gckEVENT Event,
+    IN gctBOOL Wait,
+    OUT gctUINT8 * EventID,
+    IN gceKERNEL_WHERE Source
+    )
+{
+    gctINT i, id;
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gctBOOL suspended = gcvFALSE;
+    gctINT32 free;
+
+#if gcdGPU_TIMEOUT
+    gctUINT32 timer = 0;
+#endif
+
+    gcmkHEADER_ARG("Event=0x%x Source=%d", Event, Source);
+
+    while (gcvTRUE)
+    {
+        /* Grab the queue mutex. */
+        gcmkONERROR(gckOS_AcquireMutex(Event->os,
+                                       Event->eventQueueMutex,
+                                       gcvINFINITE));
+        acquired = gcvTRUE;
+
+        /* Walk through all events. */
+        id = Event->lastID;
+        for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+        {
+            gctINT nextID = gckMATH_ModuloInt((id + 1),
+                                              gcmCOUNTOF(Event->queues));
+
+            if (Event->queues[id].head == gcvNULL)
+            {
+                *EventID = (gctUINT8) id;
+
+                Event->lastID = (gctUINT8) nextID;
+
+                /* Save time stamp of event. */
+                Event->queues[id].stamp  = ++(Event->stamp);
+                Event->queues[id].source = Source;
+
+                gcmkONERROR(gckOS_AtomDecrement(Event->os,
+                                                Event->freeAtom,
+                                                &free));
+#if gcdDYNAMIC_SPEED
+                if (free <= gcdDYNAMIC_EVENT_THRESHOLD)
+                {
+                    gcmkONERROR(gckOS_BroadcastHurry(
+                        Event->os,
+                        Event->kernel->hardware,
+                        gcdDYNAMIC_EVENT_THRESHOLD - free));
+                }
+#endif
+
+                /* Release the queue mutex. */
+                gcmkONERROR(gckOS_ReleaseMutex(Event->os,
+                                               Event->eventQueueMutex));
+
+                /* Success. */
+                gcmkTRACE_ZONE_N(
+                    gcvLEVEL_INFO, gcvZONE_EVENT,
+                    gcmSIZEOF(id),
+                    "Using id=%d",
+                    id
+                    );
+
+                gcmkFOOTER_ARG("*EventID=%u", *EventID);
+                return gcvSTATUS_OK;
+            }
+
+            id = nextID;
+        }
+
+#if gcdDYNAMIC_SPEED
+        /* No free events, speed up the GPU right now! */
+        gcmkONERROR(gckOS_BroadcastHurry(Event->os,
+                                         Event->kernel->hardware,
+                                         gcdDYNAMIC_EVENT_THRESHOLD));
+#endif
+
+        /* Release the queue mutex. */
+        gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+        acquired = gcvFALSE;
+
+        /* Fail if wait is not requested. */
+        if (!Wait)
+        {
+            /* Out of resources. */
+            gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+        }
+
+        /* Delay a while. */
+        gcmkONERROR(gckOS_Delay(Event->os, 1));
+
+#if gcdGPU_TIMEOUT
+        /* Increment the wait timer. */
+        timer += 1;
+
+        if (timer == gcdGPU_TIMEOUT)
+        {
+            /* Suspend interrupts. */
+            gcmkONERROR(gckOS_SuspendInterrupt(Event->os));
+            suspended = gcvTRUE;
+
+            /* Try to call any outstanding events. */
+            gcmkONERROR(gckHARDWARE_Interrupt(Event->kernel->hardware,
+                                              gcvTRUE));
+
+            /* Resume interrupts. */
+            gcmkONERROR(gckOS_ResumeInterrupt(Event->os));
+            suspended = gcvFALSE;
+
+        }
+        else if (timer > gcdGPU_TIMEOUT)
+        {
+            gcmkTRACE_N(
+                gcvLEVEL_ERROR,
+                gcmSIZEOF(gctCONST_STRING) + gcmSIZEOF(gctINT),
+                "%s(%d): no available events\n",
+                __FUNCTION__, __LINE__
+                );
+
+            /* Broadcast GPU stuck. */
+            gcmkONERROR(gckOS_Broadcast(Event->os,
+                                        Event->kernel->hardware,
+                                        gcvBROADCAST_GPU_STUCK));
+
+            /* Bail out. */
+            gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
+        }
+#endif
+    }
+
+OnError:
+    if (acquired)
+    {
+        /* Release the queue mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+    }
+    
+    if (suspended)
+    {
+        /* Resume interrupts. */
+        gcmkVERIFY_OK(gckOS_ResumeInterrupt(Event->os));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_AllocateRecord
+**
+**  Allocate a record for the new event.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gctBOOL AllocateAllowed
+**          State for allocation if out of free events.
+**
+**  OUTPUT:
+**
+**      gcsEVENT_PTR * Record
+**          Allocated event record.
+*/
+gceSTATUS
+gckEVENT_AllocateRecord(
+    IN gckEVENT Event,
+    IN gctBOOL AllocateAllowed,
+    OUT gcsEVENT_PTR * Record
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gctINT i;
+    gcsEVENT_PTR record;
+    gctPOINTER pointer = gcvNULL;
+
+    gcmkHEADER_ARG("Event=0x%x AllocateAllowed=%d", Event, AllocateAllowed);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+    /* Test if we are below the allocation threshold. */
+    if (AllocateAllowed && (Event->freeEventCount < gcdEVENT_MIN_THRESHOLD))
+    {
+        /* Allocate a bunch of records. */
+        for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; i += 1)
+        {
+            /* Allocate an event record. */
+            gcmkONERROR(gckOS_Allocate(Event->os,
+                                       gcmSIZEOF(gcsEVENT),
+                                       &pointer));
+
+            record = pointer;
+
+            /* Acquire the mutex. */
+            gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeEventMutex, gcvINFINITE));
+            acquired = gcvTRUE;
+
+            /* Push it on the free list. */
+            record->next           = Event->freeEventList;
+            Event->freeEventList   = record;
+            Event->freeEventCount += 1;
+
+            /* Release the mutex. */
+            gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+            acquired = gcvFALSE;
+        }
+    }
+
+    /* Acquire the mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeEventMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    *Record                = Event->freeEventList;
+    Event->freeEventList   = Event->freeEventList->next;
+    Event->freeEventCount -= 1;
+
+    /* Release the mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+    acquired = gcvFALSE;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Record=0x%x", gcmOPT_POINTER(Record));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_AddList
+**
+**  Add a new event to the list of events.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gcsHAL_INTERFACE_PTR Interface
+**          Pointer to the interface for the event to be added.
+**
+**      gceKERNEL_WHERE FromWhere
+**          Place in the pipe where the event needs to be generated.
+**
+**      gctBOOL AllocateAllowed
+**          State for allocation if out of free events.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckEVENT_AddList(
+    IN gckEVENT Event,
+    IN gcsHAL_INTERFACE_PTR Interface,
+    IN gceKERNEL_WHERE FromWhere,
+    IN gctBOOL AllocateAllowed
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gcsEVENT_PTR record = gcvNULL;
+    gcsEVENT_QUEUE_PTR queue;
+
+    gcmkHEADER_ARG("Event=0x%x Interface=0x%x FromWhere=%d AllocateAllowed=%d",
+                   Event, Interface, FromWhere, AllocateAllowed);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+    /* Verify the event command. */
+    gcmkASSERT
+        (  (Interface->command == gcvHAL_FREE_NON_PAGED_MEMORY)
+        || (Interface->command == gcvHAL_FREE_CONTIGUOUS_MEMORY)
+        || (Interface->command == gcvHAL_FREE_VIDEO_MEMORY)
+        || (Interface->command == gcvHAL_WRITE_DATA)
+        || (Interface->command == gcvHAL_UNLOCK_VIDEO_MEMORY)
+        || (Interface->command == gcvHAL_SIGNAL)
+        || (Interface->command == gcvHAL_UNMAP_USER_MEMORY)
+        || (Interface->command == gcvHAL_TIMESTAMP)
+        );
+
+    /* Validate the source. */
+    if ((FromWhere != gcvKERNEL_COMMAND) && (FromWhere != gcvKERNEL_PIXEL))
+    {
+        /* Invalid argument. */
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    /* Allocate a free record. */
+    gcmkONERROR(gckEVENT_AllocateRecord(Event, AllocateAllowed, &record));
+
+    /* Termninate the record. */
+    record->next = gcvNULL;
+
+    /* Copy the event interface into the record. */
+    gcmkONERROR(gckOS_MemCopy(&record->info, Interface, gcmSIZEOF(record->info)));
+
+    /* Get process ID. */
+    gcmkONERROR(gckOS_GetProcessID(&record->processID));
+
+#ifdef __QNXNTO__
+    record->kernel = Event->kernel;
+#endif
+
+    /* Acquire the mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->eventListMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Do we need to allocate a new queue? */
+    if ((Event->queueTail == gcvNULL) || (Event->queueTail->source != FromWhere))
+    {
+        /* Allocate a new queue. */
+        gcmkONERROR(gckEVENT_AllocateQueue(Event, &queue));
+
+        /* Initialize the queue. */
+        queue->source = FromWhere;
+        queue->head   = gcvNULL;
+        queue->next   = gcvNULL;
+
+        /* Attach it to the list of alloicated queues. */
+        if (Event->queueTail == gcvNULL)
+        {
+            Event->queueHead =
+            Event->queueTail = queue;
+        }
+        else
+        {
+            Event->queueTail->next = queue;
+            Event->queueTail       = queue;
+        }
+    }
+    else
+    {
+        queue = Event->queueTail;
+    }
+
+    /* Attach the record to the queue. */
+    if (queue->head == gcvNULL)
+    {
+        queue->head = record;
+        queue->tail = record;
+    }
+    else
+    {
+        queue->tail->next = record;
+        queue->tail       = record;
+    }
+
+    /* Release the mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+    }
+
+    if (record != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_Unlock
+**
+**  Schedule an event to unlock virtual memory.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gceKERNEL_WHERE FromWhere
+**          Place in the pipe where the event needs to be generated.
+**
+**      gcuVIDMEM_NODE_PTR Node
+**          Pointer to a gcuVIDMEM_NODE union that specifies the virtual memory
+**          to unlock.
+**
+**      gceSURF_TYPE Type
+**          Type of surface to unlock.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckEVENT_Unlock(
+    IN gckEVENT Event,
+    IN gceKERNEL_WHERE FromWhere,
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gceSURF_TYPE Type
+    )
+{
+    gceSTATUS status;
+    gcsHAL_INTERFACE iface;
+
+    gcmkHEADER_ARG("Event=0x%x FromWhere=%d Node=0x%x Type=%d",
+                   Event, FromWhere, Node, Type);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+    /* Mark the event as an unlock. */
+    iface.command                           = gcvHAL_UNLOCK_VIDEO_MEMORY;
+    iface.u.UnlockVideoMemory.node          = Node;
+    iface.u.UnlockVideoMemory.type          = Type;
+    iface.u.UnlockVideoMemory.asynchroneous = 0;
+
+    /* Append it to the queue. */
+    gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_FreeVideoMemory
+**
+**  Schedule an event to free video memory.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gcuVIDMEM_NODE_PTR VideoMemory
+**          Pointer to a gcuVIDMEM_NODE object to free.
+**
+**      gceKERNEL_WHERE FromWhere
+**          Place in the pipe where the event needs to be generated.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckEVENT_FreeVideoMemory(
+    IN gckEVENT Event,
+    IN gcuVIDMEM_NODE_PTR VideoMemory,
+    IN gceKERNEL_WHERE FromWhere
+    )
+{
+    gceSTATUS status;
+    gcsHAL_INTERFACE iface;
+
+    gcmkHEADER_ARG("Event=0x%x VideoMemory=0x%x FromWhere=%d",
+                   Event, VideoMemory, FromWhere);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(VideoMemory != gcvNULL);
+
+    /* Create an event. */
+    iface.command = gcvHAL_FREE_VIDEO_MEMORY;
+    iface.u.FreeVideoMemory.node = VideoMemory;
+
+    /* Append it to the queue. */
+    gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_FreeNonPagedMemory
+**
+**  Schedule an event to free non-paged memory.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes of non-paged memory to free.
+**
+**      gctPHYS_ADDR Physical
+**          Physical address of non-paged memory to free.
+**
+**      gctPOINTER Logical
+**          Logical address of non-paged memory to free.
+**
+**      gceKERNEL_WHERE FromWhere
+**          Place in the pipe where the event needs to be generated.
+*/
+gceSTATUS
+gckEVENT_FreeNonPagedMemory(
+    IN gckEVENT Event,
+    IN gctSIZE_T Bytes,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical,
+    IN gceKERNEL_WHERE FromWhere
+    )
+{
+    gceSTATUS status;
+    gcsHAL_INTERFACE iface;
+
+    gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
+                   "FromWhere=%d",
+                   Event, Bytes, Physical, Logical, FromWhere);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+    /* Create an event. */
+    iface.command = gcvHAL_FREE_NON_PAGED_MEMORY;
+    iface.u.FreeNonPagedMemory.bytes    = Bytes;
+    iface.u.FreeNonPagedMemory.physical = Physical;
+    iface.u.FreeNonPagedMemory.logical  = Logical;
+
+    /* Append it to the queue. */
+    gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_FreeContigiuousMemory
+**
+**  Schedule an event to free contiguous memory.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes of contiguous memory to free.
+**
+**      gctPHYS_ADDR Physical
+**          Physical address of contiguous memory to free.
+**
+**      gctPOINTER Logical
+**          Logical address of contiguous memory to free.
+**
+**      gceKERNEL_WHERE FromWhere
+**          Place in the pipe where the event needs to be generated.
+*/
+gceSTATUS
+gckEVENT_FreeContiguousMemory(
+    IN gckEVENT Event,
+    IN gctSIZE_T Bytes,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical,
+    IN gceKERNEL_WHERE FromWhere
+    )
+{
+    gceSTATUS status;
+    gcsHAL_INTERFACE iface;
+
+    gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
+                   "FromWhere=%d",
+                   Event, Bytes, Physical, Logical, FromWhere);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+    /* Create an event. */
+    iface.command = gcvHAL_FREE_CONTIGUOUS_MEMORY;
+    iface.u.FreeContiguousMemory.bytes    = Bytes;
+    iface.u.FreeContiguousMemory.physical = Physical;
+    iface.u.FreeContiguousMemory.logical  = Logical;
+
+    /* Append it to the queue. */
+    gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_Signal
+**
+**  Schedule an event to trigger a signal.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gctSIGNAL Signal
+**          Pointer to the signal to trigger.
+**
+**      gceKERNEL_WHERE FromWhere
+**          Place in the pipe where the event needs to be generated.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckEVENT_Signal(
+    IN gckEVENT Event,
+    IN gctSIGNAL Signal,
+    IN gceKERNEL_WHERE FromWhere
+    )
+{
+    gceSTATUS status;
+    gcsHAL_INTERFACE iface;
+
+    gcmkHEADER_ARG("Event=0x%x Signal=0x%x FromWhere=%d",
+                   Event, Signal, FromWhere);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+    /* Mark the event as a signal. */
+    iface.command            = gcvHAL_SIGNAL;
+    iface.u.Signal.signal    = Signal;
+#ifdef __QNXNTO__
+    iface.u.Signal.coid      = 0;
+    iface.u.Signal.rcvid     = 0;
+#endif
+    iface.u.Signal.auxSignal = gcvNULL;
+    iface.u.Signal.process   = gcvNULL;
+
+    /* Append it to the queue. */
+    gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_Submit
+**
+**  Submit the current event queue to the GPU.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gctBOOL Wait
+**          Submit requires one vacant event; if Wait is set to not zero,
+**          and there are no vacant events at this time, the function will
+**          wait until an event becomes vacant so that submission of the
+**          queue is successful.
+**
+**      gctBOOL FromPower
+**          Determines whether the call originates from inside the power
+**          management or not.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckEVENT_Submit(
+    IN gckEVENT Event,
+    IN gctBOOL Wait,
+    IN gctBOOL FromPower
+    )
+{
+    gceSTATUS status;
+    gctUINT8 id = 0xFF;
+    gcsEVENT_QUEUE_PTR queue;
+    gctBOOL acquired = gcvFALSE;
+
+#if !gcdNULL_DRIVER
+    gctSIZE_T bytes;
+    gctPOINTER buffer;
+    gckCOMMAND command = gcvNULL;
+    gctBOOL commitEntered = gcvFALSE;
+#endif
+
+    gcmkHEADER_ARG("Event=0x%x Wait=%d", Event, Wait);
+
+#if !gcdNULL_DRIVER
+    /* Get gckCOMMAND object. */
+    command = Event->kernel->command;
+#endif
+
+    /* Are there event queues? */
+    if (Event->queueHead != gcvNULL)
+    {
+#if !gcdNULL_DRIVER
+        /* Acquire the command queue. */
+        gcmkONERROR(gckCOMMAND_EnterCommit(command, FromPower));
+        commitEntered = gcvTRUE;
+#endif
+
+        /* Process all queues. */
+        while (Event->queueHead != gcvNULL)
+        {
+            /* Acquire the list mutex. */
+            gcmkONERROR(gckOS_AcquireMutex(Event->os,
+                                           Event->eventListMutex,
+                                           gcvINFINITE));
+            acquired = gcvTRUE;
+
+            /* Get the current queue. */
+            queue = Event->queueHead;
+
+            /* Allocate an event ID. */
+            gcmkONERROR(gckEVENT_GetEvent(Event, Wait, &id, queue->source));
+
+            /* Copy event list to event ID queue. */
+            Event->queues[id].source = queue->source;
+            Event->queues[id].head   = queue->head;
+
+            /* Remove the top queue from the list. */
+            if (Event->queueHead == Event->queueTail)
+            {
+                Event->queueHead = gcvNULL;
+                Event->queueTail = gcvNULL;
+            }
+            else
+            {
+                Event->queueHead = Event->queueHead->next;
+            }
+
+            /* Free the queue. */
+            gcmkONERROR(gckEVENT_FreeQueue(Event, queue));
+
+            /* Release the list mutex. */
+            gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+            acquired = gcvFALSE;
+
+            gcmkONERROR(__RemoveRecordFromProcessDB(Event,
+                Event->queues[id].head));
+
+#if gcdNULL_DRIVER
+            /* Notify immediately on infinite hardware. */
+            gcmkONERROR(gckEVENT_Interrupt(Event, 1 << id));
+
+            gcmkONERROR(gckEVENT_Notify(Event, 0));
+#else
+            /* Get the size of the hardware event. */
+            gcmkONERROR(gckHARDWARE_Event(Event->kernel->hardware,
+                                          gcvNULL,
+                                          id,
+                                          gcvKERNEL_PIXEL,
+                                          &bytes));
+
+            /* Reserve space in the command queue. */
+            gcmkONERROR(gckCOMMAND_Reserve(command,
+                                           bytes,
+                                           &buffer,
+                                           &bytes));
+
+            /* Set the hardware event in the command queue. */
+            gcmkONERROR(gckHARDWARE_Event(Event->kernel->hardware,
+                                          buffer,
+                                          id,
+                                          Event->queues[id].source,
+                                          &bytes));
+
+            /* Execute the hardware event. */
+            gcmkONERROR(gckCOMMAND_Execute(command, bytes));
+#endif
+        }
+
+#if !gcdNULL_DRIVER
+        /* Release the command queue. */
+        gcmkONERROR(gckCOMMAND_ExitCommit(command, FromPower));
+        commitEntered = gcvFALSE;
+#endif
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+#if !gcdNULL_DRIVER
+    if (commitEntered)
+    {
+        /* Release the command queue mutex. */
+        gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, FromPower));
+    }
+#endif
+
+    if (acquired)
+    {
+        /* Need to unroll the mutex acquire. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+    }
+
+    if (id != 0xFF)
+    {
+        /* Need to unroll the event allocation. */
+        Event->queues[id].head = gcvNULL;
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_Commit
+**
+**  Commit an event queue from the user.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gcsQUEUE_PTR Queue
+**          User event queue.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckEVENT_Commit(
+    IN gckEVENT Event,
+    IN gcsQUEUE_PTR Queue
+    )
+{
+    gceSTATUS status;
+    gcsQUEUE_PTR record = gcvNULL, next;
+    gctUINT32 processID;
+    gctBOOL needCopy = gcvFALSE;
+
+    gcmkHEADER_ARG("Event=0x%x Queue=0x%x", Event, Queue);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+    /* Get the current process ID. */
+    gcmkONERROR(gckOS_GetProcessID(&processID));
+
+    /* Query if we need to copy the client data. */
+    gcmkONERROR(gckOS_QueryNeedCopy(Event->os, processID, &needCopy));
+
+    /* Loop while there are records in the queue. */
+    while (Queue != gcvNULL)
+    {
+        gcsQUEUE queue;
+
+        if (needCopy)
+        {
+            /* Point to stack record. */
+            record = &queue;
+
+            /* Copy the data from the client. */
+            gcmkONERROR(gckOS_CopyFromUserData(Event->os,
+                                               record,
+                                               Queue,
+                                               gcmSIZEOF(gcsQUEUE)));
+        }
+        else
+        {
+            gctPOINTER pointer = gcvNULL;
+
+            /* Map record into kernel memory. */
+            gcmkONERROR(gckOS_MapUserPointer(Event->os,
+                                             Queue,
+                                             gcmSIZEOF(gcsQUEUE),
+                                             &pointer));
+
+            record = pointer;
+        }
+
+        /* Append event record to event queue. */
+        gcmkONERROR(
+            gckEVENT_AddList(Event, &record->iface, gcvKERNEL_PIXEL, gcvTRUE));
+
+        /* Next record in the queue. */
+        next = record->next;
+
+        if (!needCopy)
+        {
+            /* Unmap record from kernel memory. */
+            gcmkONERROR(
+                gckOS_UnmapUserPointer(Event->os,
+                                       Queue,
+                                       gcmSIZEOF(gcsQUEUE),
+                                       (gctPOINTER *) record));
+            record = gcvNULL;
+        }
+
+        Queue = next;
+    }
+
+    /* Submit the event list. */
+    gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE));
+
+    /* Success */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if ((record != gcvNULL) && !needCopy)
+    {
+        /* Roll back. */
+        gcmkVERIFY_OK(gckOS_UnmapUserPointer(Event->os,
+                                             Queue,
+                                             gcmSIZEOF(gcsQUEUE),
+                                             (gctPOINTER *) record));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_Compose
+**
+**  Schedule a composition event and start a composition.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gcsHAL_COMPOSE_PTR Info
+**          Pointer to the composition structure.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckEVENT_Compose(
+    IN gckEVENT Event,
+    IN gcsHAL_COMPOSE_PTR Info
+    )
+{
+    gceSTATUS status;
+    gcsEVENT_PTR headRecord;
+    gcsEVENT_PTR tailRecord;
+    gcsEVENT_PTR tempRecord;
+    gctUINT8 id = 0xFF;
+    gctUINT32 processID;
+
+    gcmkHEADER_ARG("Event=0x%x Info=0x%x", Event, Info);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+    gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+
+    /* Allocate an event ID. */
+    gcmkONERROR(gckEVENT_GetEvent(Event, gcvTRUE, &id, gcvKERNEL_PIXEL));
+
+    /* Get process ID. */
+    gcmkONERROR(gckOS_GetProcessID(&processID));
+
+    /* Allocate a record. */
+    gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
+    headRecord = tailRecord = tempRecord;
+
+    /* Initialize the record. */
+    tempRecord->info.command            = gcvHAL_SIGNAL;
+    tempRecord->info.u.Signal.process   = Info->process;
+#ifdef __QNXNTO__
+    tempRecord->info.u.Signal.coid      = Info->coid;
+    tempRecord->info.u.Signal.rcvid     = Info->rcvid;
+#endif
+    tempRecord->info.u.Signal.signal    = Info->signal;
+    tempRecord->info.u.Signal.auxSignal = gcvNULL;
+    tempRecord->next = gcvNULL;
+    tempRecord->processID = processID;
+
+    /* Allocate another record for user signal #1. */
+    if (Info->userSignal1 != gcvNULL)
+    {
+        /* Allocate a record. */
+        gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
+        tailRecord->next = tempRecord;
+        tailRecord = tempRecord;
+
+        /* Initialize the record. */
+        tempRecord->info.command            = gcvHAL_SIGNAL;
+        tempRecord->info.u.Signal.process   = Info->userProcess;
+#ifdef __QNXNTO__
+        tempRecord->info.u.Signal.coid      = Info->coid;
+        tempRecord->info.u.Signal.rcvid     = Info->rcvid;
+#endif
+        tempRecord->info.u.Signal.signal    = Info->userSignal1;
+        tempRecord->info.u.Signal.auxSignal = gcvNULL;
+        tempRecord->next = gcvNULL;
+        tempRecord->processID = processID;
+    }
+
+    /* Allocate another record for user signal #2. */
+    if (Info->userSignal2 != gcvNULL)
+    {
+        /* Allocate a record. */
+        gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
+        tailRecord->next = tempRecord;
+        tailRecord = tempRecord;
+
+        /* Initialize the record. */
+        tempRecord->info.command            = gcvHAL_SIGNAL;
+        tempRecord->info.u.Signal.process   = Info->userProcess;
+#ifdef __QNXNTO__
+        tempRecord->info.u.Signal.coid      = Info->coid;
+        tempRecord->info.u.Signal.rcvid     = Info->rcvid;
+#endif
+        tempRecord->info.u.Signal.signal    = Info->userSignal2;
+        tempRecord->info.u.Signal.auxSignal = gcvNULL;
+        tempRecord->next = gcvNULL;
+        tempRecord->processID = processID;
+    }
+
+       /* Set the event list. */
+    Event->queues[id].head = headRecord;
+
+    /* Start composition. */
+    gcmkONERROR(gckHARDWARE_Compose(
+        Event->kernel->hardware, processID,
+        Info->size, Info->physical, Info->logical, id
+        ));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_Interrupt
+**
+**  Called by the interrupt service routine to store the triggered interrupt
+**  mask to be later processed by gckEVENT_Notify.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gctUINT32 Data
+**          Mask for the 32 interrupts.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckEVENT_Interrupt(
+    IN gckEVENT Event,
+    IN gctUINT32 Data
+    )
+{
+    gcmkHEADER_ARG("Event=0x%x Data=0x%x", Event, Data);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+    /* Combine current interrupt status with pending flags. */
+#ifdef __QNXNTO__
+    atomic_set(&Event->pending, Data);
+#else
+#ifdef LINUX
+    {
+        gctUINT32 oldVal,newVal;
+        do{
+            oldVal = Event->pending;
+            newVal = oldVal| Data;
+        }while(atomic_cmpxchg((atomic_t *)&Event->pending,oldVal,newVal)!=oldVal);    
+    }
+#else
+    Event->pending |= Data;
+#endif
+#endif
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckEVENT_Notify
+**
+**  Process all triggered interrupts.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckEVENT_Notify(
+    IN gckEVENT Event,
+    IN gctUINT32 IDs
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+    gctINT i;
+    gcsEVENT_QUEUE * queue;
+    gctUINT mask = 0;
+    gctBOOL acquired = gcvFALSE;
+#ifdef __QNXNTO__
+    gcuVIDMEM_NODE_PTR node;
+#endif
+    gctUINT pending;
+    gctBOOL suspended = gcvFALSE;
+#ifndef __QNXNTO__
+    gctBOOL empty = gcvFALSE, idle = gcvFALSE;
+#endif
+    gcmDEBUG_ONLY(gctINT eventNumber = 0;)
+    gctINT32 free;
+#if gcdSECURE_USER
+    gcskSECURE_CACHE_PTR cache;
+#endif
+
+    gcmkHEADER_ARG("Event=0x%x IDs=0x%x", Event, IDs);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+    gcmDEBUG_ONLY(
+        if (IDs != 0)
+        {
+            for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+            {
+                if (Event->queues[i].head != gcvNULL)
+                {
+                    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+                                   "Queue(%d): stamp=%llu source=%d",
+                                   i,
+                                   Event->queues[i].stamp,
+                                   Event->queues[i].source);
+                }
+            }
+        }
+    );
+
+    for (;;)
+    {
+        /* Suspend interrupts. */
+        gcmkONERROR(gckOS_SuspendInterruptEx(Event->os, Event->kernel->core));
+        suspended = gcvTRUE;
+
+        /* Get current interrupts. */
+        pending = Event->pending;
+
+        /* Resume interrupts. */
+        gcmkONERROR(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
+        suspended = gcvFALSE;
+
+        if (pending == 0)
+        {
+            /* No more pending interrupts - done. */
+            break;
+        }
+
+        gcmkTRACE_ZONE_N(
+            gcvLEVEL_INFO, gcvZONE_EVENT,
+            gcmSIZEOF(pending),
+            "Pending interrupts 0x%x",
+            pending
+            );
+
+        queue = gcvNULL;
+
+        gcmDEBUG_ONLY(
+            if (IDs == 0)
+            {
+                for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+                {
+                    if (Event->queues[i].head != gcvNULL)
+                    {
+                        gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+                                       "Queue(%d): stamp=%llu source=%d",
+                                       i,
+                                       Event->queues[i].stamp,
+                                       Event->queues[i].source);
+                    }
+                }
+            }
+        );
+
+        /* Find the oldest pending interrupt. */
+        for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+        {
+            if ((Event->queues[i].head != gcvNULL)
+            &&  (pending & (1 << i))
+            )
+            {
+                if ((queue == gcvNULL)
+                ||  (Event->queues[i].stamp < queue->stamp)
+                )
+                {
+                    queue = &Event->queues[i];
+                    mask  = 1 << i;
+                    gcmDEBUG_ONLY(eventNumber = i);
+                }
+            }
+        }
+
+        if (queue == gcvNULL)
+        {
+            gcmkTRACE_ZONE_N(
+                gcvLEVEL_ERROR, gcvZONE_EVENT,
+                gcmSIZEOF(pending),
+                "Interrupts 0x%x are not pending.",
+                pending
+                );
+
+            /* Suspend interrupts. */
+            gcmkONERROR(gckOS_SuspendInterruptEx(Event->os, Event->kernel->core));
+            suspended = gcvTRUE;
+
+            /* Mark pending interrupts as handled. */
+#ifdef __QNXNTO__
+            atomic_clr(&Event->pending, pending);
+#else
+#ifdef LINUX
+            {
+                gctUINT32 oldVal,newVal;
+                do{
+                    oldVal = Event->pending;
+                    newVal = oldVal & (~pending);
+                }while(atomic_cmpxchg((atomic_t *)&Event->pending,oldVal,newVal)!=oldVal);    
+            }
+#else
+            Event->pending &= ~pending;
+#endif
+#endif
+
+            /* Resume interrupts. */
+            gcmkONERROR(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
+            suspended = gcvFALSE;
+
+            break;
+        }
+
+        /* Check whether there is a missed interrupt. */
+        for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+        {
+            if ((Event->queues[i].head != gcvNULL)
+            &&  (Event->queues[i].stamp < queue->stamp)
+            &&  (Event->queues[i].source == queue->source)
+            )
+            {
+                gcmkTRACE_N(
+                    gcvLEVEL_ERROR,
+                    gcmSIZEOF(i) + gcmSIZEOF(Event->queues[i].stamp),
+                    "Event %d lost (stamp %llu)",
+                    i, Event->queues[i].stamp
+                    );
+
+                /* Use this event instead. */
+                queue = &Event->queues[i];
+                mask  = 0;
+            }
+        }
+
+        if (mask != 0)
+        {
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+            gcmkTRACE_ZONE_N(
+                gcvLEVEL_INFO, gcvZONE_EVENT,
+                gcmSIZEOF(eventNumber),
+                "Processing interrupt %d",
+                eventNumber
+                );
+#endif
+        }
+
+        /* Walk all events for this interrupt. */
+        while (1)
+        {
+            gcsEVENT_PTR record,record_next;
+#ifndef __QNXNTO__
+            gctPOINTER logical;
+#endif
+#if gcdSECURE_USER
+            gctSIZE_T bytes;
+#endif
+
+            /* Grab the mutex queue. */
+            gcmkONERROR(gckOS_AcquireMutex(Event->os,
+                                           Event->eventQueueMutex,
+                                           gcvINFINITE));
+            acquired = gcvTRUE;
+
+            /* Grab the event head. */
+            record = queue->head;
+            record_next = gcvNULL;
+            if (record != gcvNULL)
+            {
+                record_next = record->next;
+                queue->head = record_next;
+            }
+
+            /* Release the mutex queue. */
+            gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+            acquired = gcvFALSE;
+
+            /* Dispatch on event type. */
+            if (record != gcvNULL)
+            {
+#ifdef __QNXNTO__
+                /* Assign record->processID as the pid for this galcore thread.
+                 * Used in OS calls like gckOS_UnlockMemory() which do not take a pid.
+                 */
+                drv_thread_specific_key_assign(record->processID, 0);
+#endif
+
+#if gcdSECURE_USER
+                /* Get the cache that belongs to this process. */
+                gcmkONERROR(gckKERNEL_GetProcessDBCache(Event->kernel,
+                            record->processID,
+                            &cache));
+#endif
+
+                gcmkTRACE_ZONE_N(
+                    gcvLEVEL_INFO, gcvZONE_EVENT,
+                    gcmSIZEOF(record->info.command),
+                    "Processing event type: %d",
+                    record->info.command
+                    );
+
+                switch (record->info.command)
+                {
+                case gcvHAL_FREE_NON_PAGED_MEMORY:
+                    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+                                   "gcvHAL_FREE_NON_PAGED_MEMORY: 0x%x",
+                                   record->info.u.FreeNonPagedMemory.physical);
+
+                    /* Free non-paged memory. */
+                    status = gckOS_FreeNonPagedMemory(
+                                Event->os,
+                                record->info.u.FreeNonPagedMemory.bytes,
+                                record->info.u.FreeNonPagedMemory.physical,
+                                record->info.u.FreeNonPagedMemory.logical);
+
+                    if (gcmIS_SUCCESS(status))
+                    {
+#if gcdSECURE_USER
+                        gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+                            Event->kernel,
+                            cache,
+                            record->event.u.FreeNonPagedMemory.logical,
+                            record->event.u.FreeNonPagedMemory.bytes));
+#endif
+                    }
+                    break;
+
+                case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+                    gcmkTRACE_ZONE(
+                        gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+                        "gcvHAL_FREE_CONTIGUOUS_MEMORY: 0x%x",
+                        record->info.u.FreeContiguousMemory.physical);
+
+                    /* Unmap the user memory. */
+                    status = gckOS_FreeContiguous(
+                                Event->os,
+                                record->info.u.FreeContiguousMemory.physical,
+                                record->info.u.FreeContiguousMemory.logical,
+                                record->info.u.FreeContiguousMemory.bytes);
+
+                    if (gcmIS_SUCCESS(status))
+                    {
+#if gcdSECURE_USER
+                        gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+                            Event->kernel,
+                            cache,
+                            event->event.u.FreeContiguousMemory.logical,
+                            event->event.u.FreeContiguousMemory.bytes));
+#endif
+                    }
+                    break;
+
+                case gcvHAL_FREE_VIDEO_MEMORY:
+                    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+                                   "gcvHAL_FREE_VIDEO_MEMORY: 0x%x",
+                                   record->info.u.FreeVideoMemory.node);
+
+#ifdef __QNXNTO__
+                    node = record->info.u.FreeVideoMemory.node;
+#if gcdUSE_VIDMEM_PER_PID
+                    /* Check if the VidMem object still exists. */
+                    if (gckKERNEL_GetVideoMemoryPoolPid(record->kernel,
+                                                        gcvPOOL_SYSTEM,
+                                                        record->processID,
+                                                        gcvNULL) == gcvSTATUS_NOT_FOUND)
+                    {
+                        /*printf("Vidmem not found for process:%d\n", queue->processID);*/
+                        status = gcvSTATUS_OK;
+                        break;
+                    }
+#else
+                    if ((node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+                    &&  (node->VidMem.logical != gcvNULL)
+                    )
+                    {
+                        gcmkERR_BREAK(
+                            gckKERNEL_UnmapVideoMemory(record->kernel,
+                                                       node->VidMem.logical,
+                                                       record->processID,
+                                                       node->VidMem.bytes));
+                        node->VidMem.logical = gcvNULL;
+                    }
+#endif
+#endif
+
+                    /* Free video memory. */
+                    status =
+                        gckVIDMEM_Free(record->info.u.FreeVideoMemory.node);
+
+                    break;
+
+                case gcvHAL_WRITE_DATA:
+#ifndef __QNXNTO__
+                    /* Convert physical into logical address. */
+                    gcmkERR_BREAK(
+                        gckOS_MapPhysical(Event->os,
+                                          record->info.u.WriteData.address,
+                                          gcmSIZEOF(gctUINT32),
+                                          &logical));
+
+                    /* Write data. */
+                    gcmkERR_BREAK(
+                        gckOS_WriteMemory(Event->os,
+                                          logical,
+                                          record->info.u.WriteData.data));
+
+                    /* Unmap the physical memory. */
+                    gcmkERR_BREAK(
+                        gckOS_UnmapPhysical(Event->os,
+                                            logical,
+                                            gcmSIZEOF(gctUINT32)));
+#else
+                    /* Write data. */
+                    gcmkERR_BREAK(
+                        gckOS_WriteMemory(Event->os,
+                                          (gctPOINTER)
+                                              record->info.u.WriteData.address,
+                                          record->info.u.WriteData.data));
+#endif
+                    break;
+
+                case gcvHAL_UNLOCK_VIDEO_MEMORY:
+                    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+                                   "gcvHAL_UNLOCK_VIDEO_MEMORY: 0x%x",
+                                   record->info.u.UnlockVideoMemory.node);
+
+                    /* Save node information before it disappears. */
+#if gcdSECURE_USER
+                    node = event->event.u.UnlockVideoMemory.node;
+                    if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+                    {
+                        logical = gcvNULL;
+                        bytes   = 0;
+                    }
+                    else
+                    {
+                        logical = node->Virtual.logical;
+                        bytes   = node->Virtual.bytes;
+                    }
+#endif
+
+                    /* Unlock. */
+                    status = gckVIDMEM_Unlock(
+                        Event->kernel,
+                        record->info.u.UnlockVideoMemory.node,
+                        record->info.u.UnlockVideoMemory.type,
+                        gcvNULL);
+
+#if gcdSECURE_USER
+                    if (gcmIS_SUCCESS(status) && (logical != gcvNULL))
+                    {
+                        gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+                            Event->kernel,
+                            cache,
+                            logical,
+                            bytes));
+                    }
+#endif
+                    break;
+
+                case gcvHAL_SIGNAL:
+                    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+                                   "gcvHAL_SIGNAL: 0x%x",
+                                   record->info.u.Signal.signal);
+
+#ifdef __QNXNTO__
+                    if ((record->info.u.Signal.coid == 0)
+                    &&  (record->info.u.Signal.rcvid == 0)
+                    )
+                    {
+                        /* Kernel signal. */
+                        gcmkERR_BREAK(
+                            gckOS_Signal(Event->os,
+                                         record->info.u.Signal.signal,
+                                         gcvTRUE));
+                    }
+                    else
+                    {
+                        /* User signal. */
+                        gcmkERR_BREAK(
+                            gckOS_UserSignal(Event->os,
+                                             record->info.u.Signal.signal,
+                                             record->info.u.Signal.rcvid,
+                                             record->info.u.Signal.coid));
+                    }
+#else
+                    /* Set signal. */
+                    if (record->info.u.Signal.process == gcvNULL)
+                    {
+                        /* Kernel signal. */
+                        gcmkERR_BREAK(
+                            gckOS_Signal(Event->os,
+                                         record->info.u.Signal.signal,
+                                         gcvTRUE));
+                    }
+                    else
+                    {
+                        /* User signal. */
+                        gcmkERR_BREAK(
+                            gckOS_UserSignal(Event->os,
+                                             record->info.u.Signal.signal,
+                                             record->info.u.Signal.process));
+                    }
+
+                    gcmkASSERT(record->info.u.Signal.auxSignal == gcvNULL);
+#endif
+                    break;
+
+                case gcvHAL_UNMAP_USER_MEMORY:
+                    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+                                   "gcvHAL_UNMAP_USER_MEMORY: 0x%x",
+                                   record->info.u.UnmapUserMemory.info);
+
+                    /* Unmap the user memory. */
+                    status = gckOS_UnmapUserMemoryEx(
+                        Event->os,
+                        Event->kernel->core,
+                        record->info.u.UnmapUserMemory.memory,
+                        record->info.u.UnmapUserMemory.size,
+                        record->info.u.UnmapUserMemory.info,
+                        record->info.u.UnmapUserMemory.address);
+
+#if gcdSECURE_USER
+                    if (gcmIS_SUCCESS(status))
+                    {
+                        gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+                            Event->kernel,
+                            cache,
+                            event->event.u.UnmapUserMemory.memory,
+                            event->event.u.UnmapUserMemory.size));
+                    }
+#endif
+                    gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+                            Event->kernel,
+                            record->processID, gcvDB_MAP_USER_MEMORY,
+                            record->info.u.UnmapUserMemory.memory));
+                    break;
+
+                case gcvHAL_TIMESTAMP:
+                    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+                                   "gcvHAL_TIMESTAMP: %d %d",
+                                   record->info.u.TimeStamp.timer,
+                                   record->info.u.TimeStamp.request);
+
+                    /* Process the timestamp. */
+                    switch (record->info.u.TimeStamp.request)
+                    {
+                    case 0:
+                        status = gckOS_GetTime(&Event->kernel->timers[
+                                               record->info.u.TimeStamp.timer].
+                                               stopTime);
+                        break;
+
+                    case 1:
+                        status = gckOS_GetTime(&Event->kernel->timers[
+                                               record->info.u.TimeStamp.timer].
+                                               startTime);
+                        break;
+
+                    default:
+                        gcmkTRACE_ZONE_N(
+                            gcvLEVEL_ERROR, gcvZONE_EVENT,
+                            gcmSIZEOF(record->info.u.TimeStamp.request),
+                            "Invalid timestamp request: %d",
+                            record->info.u.TimeStamp.request
+                            );
+
+                        status = gcvSTATUS_INVALID_ARGUMENT;
+                        break;
+                    }
+                    break;
+
+                default:
+                    /* Invalid argument. */
+                    gcmkTRACE_ZONE_N(
+                        gcvLEVEL_ERROR, gcvZONE_EVENT,
+                        gcmSIZEOF(record->info.command),
+                        "Unknown event type: %d",
+                        record->info.command
+                        );
+
+                    status = gcvSTATUS_INVALID_ARGUMENT;
+                    break;
+                }
+
+                /* Make sure there are no errors generated. */
+                if (gcmIS_ERROR(status))
+                {
+                    gcmkTRACE_ZONE_N(
+                        gcvLEVEL_WARNING, gcvZONE_EVENT,
+                        gcmSIZEOF(status),
+                        "Event produced status: %d(%s)",
+                        status, gckOS_DebugStatus2Name(status));
+                }
+
+                /* Free the event. */
+                gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
+            }
+
+            //Can't use queue->head to check, as the value may be updated while it equals to NULL.
+            //So use the shadow value to check.
+            if(record_next == gcvNULL)
+                break;
+
+        }
+
+        /* Increase the number of free events. */
+        gcmkONERROR(gckOS_AtomIncrement(Event->os, Event->freeAtom, &free));
+
+        gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+                       "Handled interrupt 0x%x", mask);
+
+        /* Suspend interrupts. */
+        gcmkONERROR(gckOS_SuspendInterruptEx(Event->os, Event->kernel->core));
+        suspended = gcvTRUE;
+
+        /* Mark pending interrupt as handled. */
+#ifdef LINUX
+        {
+            gctUINT32 oldVal,newVal;
+            do{
+                oldVal = Event->pending;
+                newVal = oldVal & (~mask);
+            }while(atomic_cmpxchg((atomic_t *)&Event->pending,oldVal,newVal)!=oldVal);    
+        }
+#elif defined __QNXNTO__
+        atomic_clr(&Event->pending, mask);
+#else
+        Event->pending &= ~mask;
+#endif
+
+        /* Resume interrupts. */
+        gcmkONERROR(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
+        suspended = gcvFALSE;
+    }
+
+#ifndef __QNXNTO__
+
+    /* Check whether the event queue is empty. */
+    gcmkONERROR(gckEVENT_IsEmpty(Event, &empty));
+
+    if (empty && (IDs == 0))
+    {
+        /* Query whether the hardware is idle. */
+        gcmkONERROR(gckHARDWARE_QueryIdle(Event->kernel->hardware, &idle));
+
+        if (idle)
+        {
+            /* Inform the system of idle GPU. */
+            gcmkONERROR(gckOS_Broadcast(Event->os,
+                                        Event->kernel->hardware,
+                                        gcvBROADCAST_GPU_IDLE));
+        }
+    }
+#endif
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+    }
+
+    if (suspended)
+    {
+        /* Resume interrupts. */
+        gcmkVERIFY_OK(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckEVENT_FreeProcess
+**
+**  Free all events owned by a particular process ID.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gctUINT32 ProcessID
+**          Process ID of the process to be freed up.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckEVENT_FreeProcess(
+    IN gckEVENT Event,
+    IN gctUINT32 ProcessID
+    )
+{
+    gctSIZE_T i;
+    gctBOOL acquired = gcvFALSE;
+    gcsEVENT_PTR record, next;
+    gceSTATUS status;
+    gcsEVENT_PTR deleteHead, deleteTail;
+    gctBOOL empty, idle;
+
+    gcmkHEADER_ARG("Event=0x%x ProcessID=%d", Event, ProcessID);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+    /* Walk through all queues. */
+    for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+    {
+        if (Event->queues[i].head != gcvNULL)
+        {
+            /* Grab the event queue mutex. */
+            gcmkONERROR(gckOS_AcquireMutex(Event->os,
+                                           Event->eventQueueMutex,
+                                           gcvINFINITE));
+            acquired = gcvTRUE;
+
+            /* Grab the mutex head. */
+            record                = Event->queues[i].head;
+            Event->queues[i].head = gcvNULL;
+            Event->queues[i].tail = gcvNULL;
+            deleteHead            = gcvNULL;
+            deleteTail            = gcvNULL;
+
+            while (record != gcvNULL)
+            {
+                next = record->next;
+                if (record->processID == ProcessID)
+                {
+                    if (deleteHead == gcvNULL)
+                    {
+                        deleteHead = record;
+                    }
+                    else
+                    {
+                        deleteTail->next = record;
+                    }
+
+                    deleteTail = record;
+                }
+                else
+                {
+                    if (Event->queues[i].head == gcvNULL)
+                    {
+                        Event->queues[i].head = record;
+                    }
+                    else
+                    {
+                        Event->queues[i].tail->next = record;
+                    }
+
+                    Event->queues[i].tail = record;
+                }
+
+                record->next = gcvNULL;
+                record = next;
+            }
+
+            /* Release the mutex queue. */
+            gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+            acquired = gcvFALSE;
+
+            /* Loop through the entire list of events. */
+            for (record = deleteHead; record != gcvNULL; record = next)
+            {
+                /* Get the next event record. */
+                next = record->next;
+
+                /* Free the event record. */
+                gcmkONERROR(gckEVENT_FreeRecord(Event, record));
+            }
+        }
+    }
+
+    /*Check whether the event queue is empty.*/
+    gcmkONERROR(_IsEmpty(Event, &empty));
+
+    if (empty)
+    {
+        /* Query whether the hardware is idle. */
+        gcmkONERROR(gckHARDWARE_QueryIdle(Event->kernel->hardware, &idle));
+
+        if (idle)
+        {
+            /* Inform the system of idle GPU. */
+            gcmkONERROR(gckOS_Broadcast(Event->os,
+                                        Event->kernel->hardware,
+                                        gcvBROADCAST_GPU_IDLE));
+        }
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Release the event queue mutex. */
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**  gckEVENT_Stop
+**
+**  Stop the hardware using the End event mechanism.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**      gctUINT32 ProcessID
+**          Process ID Logical belongs.
+**
+**      gctPHYS_ADDR Handle
+**          Physical address handle.  If gcvNULL it is video memory.
+**
+**      gctPOINTER Logical
+**          Logical address to flush.
+**
+**      gctSIGNAL Signal
+**          Pointer to the signal to trigger.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckEVENT_Stop(
+    IN gckEVENT Event,
+    IN gctUINT32 ProcessID,
+    IN gctPHYS_ADDR Handle,
+    IN gctPOINTER Logical,
+    IN gctSIGNAL Signal,
+       IN OUT gctSIZE_T * waitSize
+    )
+{
+    gceSTATUS status;
+   /* gctSIZE_T waitSize;*/
+    gcsEVENT_PTR record;
+    gctUINT8 id = 0xFF;
+
+    gcmkHEADER_ARG("Event=0x%x ProcessID=%u Handle=0x%x Logical=0x%x "
+                   "Signal=0x%x",
+                   Event, ProcessID, Handle, Logical, Signal);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+    /* Submit the current event queue. */
+    gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE));
+
+    gcmkONERROR(gckEVENT_GetEvent(Event, gcvTRUE, &id, gcvKERNEL_PIXEL));
+
+    /* Allocate a record. */
+    gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &record));
+
+    /* Initialize the record. */
+    record->next = gcvNULL;
+    record->processID               = ProcessID;
+    record->info.command            = gcvHAL_SIGNAL;
+    record->info.u.Signal.signal    = Signal;
+#ifdef __QNXNTO__
+    record->info.u.Signal.coid      = 0;
+    record->info.u.Signal.rcvid     = 0;
+#endif
+    record->info.u.Signal.auxSignal = gcvNULL;
+    record->info.u.Signal.process   = gcvNULL;
+
+    /* Append the record. */
+    Event->queues[id].head      = record;
+
+    /* Replace last WAIT with END. */
+    gcmkONERROR(gckHARDWARE_End(
+        Event->kernel->hardware, Logical, waitSize
+        ));
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+    /* Flush the cache for the END. */
+    gcmkONERROR(gckOS_CacheClean(
+        Event->os,
+        ProcessID,
+        gcvNULL,
+        Handle,
+        Logical,
+        *waitSize
+        ));
+#endif
+
+    /* Wait for the signal. */
+    gcmkONERROR(gckOS_WaitSignal(Event->os, Signal, gcvINFINITE));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c
new file mode 100644 (file)
index 0000000..597c979
--- /dev/null
@@ -0,0 +1,861 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+/**
+**  @file
+**  gckHEAP object for kernel HAL layer.  The heap implemented here is an arena-
+**  based memory allocation.  An arena-based memory heap allocates data quickly
+**  from specified arenas and reduces memory fragmentation.
+**
+*/
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE            gcvZONE_HEAP
+
+/*******************************************************************************
+***** Structures ***************************************************************
+*******************************************************************************/
+
+#define gcdIN_USE               ((gcskNODE_PTR) ~0)
+
+typedef struct _gcskNODE *      gcskNODE_PTR;
+typedef struct _gcskNODE
+{
+    /* Number of byets in node. */
+    gctSIZE_T                   bytes;
+
+    /* Pointer to next free node, or gcvNULL to mark the node as freed, or
+    ** gcdIN_USE to mark the node as used. */
+    gcskNODE_PTR                next;
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+    /* Time stamp of allocation. */
+    gctUINT64                   timeStamp;
+#endif
+}
+gcskNODE;
+
+typedef struct _gcskHEAP    *   gcskHEAP_PTR;
+typedef struct _gcskHEAP
+{
+    /* Linked list. */
+    gcskHEAP_PTR                next;
+    gcskHEAP_PTR                prev;
+
+    /* Heap size. */
+    gctSIZE_T                   size;
+
+    /* Free list. */
+    gcskNODE_PTR                freeList;
+}
+gcskHEAP;
+
+struct _gckHEAP
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to a gckOS object. */
+    gckOS                       os;
+
+    /* Locking mutex. */
+    gctPOINTER                  mutex;
+
+    /* Allocation parameters. */
+    gctSIZE_T                   allocationSize;
+
+    /* Heap list. */
+    gcskHEAP_PTR                heap;
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+    gctUINT64                   timeStamp;
+#endif
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+    /* Profile information. */
+    gctUINT32                   allocCount;
+    gctUINT64                   allocBytes;
+    gctUINT64                   allocBytesMax;
+    gctUINT64                   allocBytesTotal;
+    gctUINT32                   heapCount;
+    gctUINT32                   heapCountMax;
+    gctUINT64                   heapMemory;
+    gctUINT64                   heapMemoryMax;
+#endif
+};
+
+/*******************************************************************************
+***** Static Support Functions *************************************************
+*******************************************************************************/
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+static gctSIZE_T
+_DumpHeap(
+    IN gcskHEAP_PTR Heap
+    )
+{
+    gctPOINTER p;
+    gctSIZE_T leaked = 0;
+
+    /* Start at first node. */
+    for (p = Heap + 1;;)
+    {
+        /* Convert the pointer. */
+        gcskNODE_PTR node = (gcskNODE_PTR) p;
+
+        /* Check if this is a used node. */
+        if (node->next == gcdIN_USE)
+        {
+            /* Print the leaking node. */
+            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_HEAP,
+                           "Detected leaking: node=0x%x bytes=%lu timeStamp=%llu "
+                           "(%08X %c%c%c%c)",
+                           node, node->bytes, node->timeStamp,
+                           ((gctUINT32_PTR) (node + 1))[0],
+                           gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[0]),
+                           gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[1]),
+                           gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[2]),
+                           gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[3]));
+
+            /* Add leaking byte count. */
+            leaked += node->bytes;
+        }
+
+        /* Test for end of heap. */
+        if (node->bytes == 0)
+        {
+            break;
+        }
+
+        else
+        {
+            /* Move to next node. */
+            p = (gctUINT8_PTR) node + node->bytes;
+        }
+    }
+
+    /* Return the number of leaked bytes. */
+    return leaked;
+}
+#endif
+
+static gceSTATUS
+_CompactKernelHeap(
+    IN gckHEAP Heap
+    )
+{
+    gcskHEAP_PTR heap, next;
+    gctPOINTER p;
+    gcskHEAP_PTR freeList = gcvNULL;
+
+    gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+    /* Walk all the heaps. */
+    for (heap = Heap->heap; heap != gcvNULL; heap = next)
+    {
+        gcskNODE_PTR lastFree = gcvNULL;
+
+        /* Zero out the free list. */
+        heap->freeList = gcvNULL;
+
+        /* Start at the first node. */
+        for (p = (gctUINT8_PTR) (heap + 1);;)
+        {
+            /* Convert the pointer. */
+            gcskNODE_PTR node = (gcskNODE_PTR) p;
+
+            gcmkASSERT(p <= (gctPOINTER) ((gctUINT8_PTR) (heap + 1) + heap->size));
+
+            /* Test if this node not used. */
+            if (node->next != gcdIN_USE)
+            {
+                /* Test if this is the end of the heap. */
+                if (node->bytes == 0)
+                {
+                    break;
+                }
+
+                /* Test of this is the first free node. */
+                else if (lastFree == gcvNULL)
+                {
+                    /* Initialzie the free list. */
+                    heap->freeList = node;
+                    lastFree       = node;
+                }
+
+                else
+                {
+                    /* Test if this free node is contiguous with the previous
+                    ** free node. */
+                    if ((gctUINT8_PTR) lastFree + lastFree->bytes == p)
+                    {
+                        /* Just increase the size of the previous free node. */
+                        lastFree->bytes += node->bytes;
+                    }
+                    else
+                    {
+                        /* Add to linked list. */
+                        lastFree->next = node;
+                        lastFree       = node;
+                    }
+                }
+            }
+
+            /* Move to next node. */
+            p = (gctUINT8_PTR) node + node->bytes;
+        }
+
+        /* Mark the end of the chain. */
+        if (lastFree != gcvNULL)
+        {
+            lastFree->next = gcvNULL;
+        }
+
+        /* Get next heap. */
+        next = heap->next;
+
+        /* Check if the entire heap is free. */
+        if ((heap->freeList != gcvNULL)
+        &&  (heap->freeList->bytes == heap->size - gcmSIZEOF(gcskNODE))
+        )
+        {
+            /* Remove the heap from the linked list. */
+            if (heap->prev == gcvNULL)
+            {
+                Heap->heap = next;
+            }
+            else
+            {
+                heap->prev->next = next;
+            }
+
+            if (heap->next != gcvNULL)
+            {
+                heap->next->prev = heap->prev;
+            }
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+            /* Update profiling. */
+            Heap->heapCount  -= 1;
+            Heap->heapMemory -= heap->size + gcmSIZEOF(gcskHEAP);
+#endif
+
+            /* Add this heap to the list of heaps that need to be freed. */
+            heap->next = freeList;
+            freeList   = heap;
+        }
+    }
+
+    if (freeList != gcvNULL)
+    {
+        /* Release the mutex, remove any chance for a dead lock. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+        /* Free all heaps in the free list. */
+        for (heap = freeList; heap != gcvNULL; heap = next)
+        {
+            /* Get pointer to the next heap. */
+            next = heap->next;
+
+            /* Free the heap. */
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
+                           "Freeing heap 0x%x (%lu bytes)",
+                           heap, heap->size + gcmSIZEOF(gcskHEAP));
+            gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
+        }
+
+        /* Acquire the mutex again. */
+        gcmkVERIFY_OK(
+            gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+***** gckHEAP API Code *********************************************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckHEAP_Construct
+**
+**  Construct a new gckHEAP object.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**      gctSIZE_T AllocationSize
+**          Minimum size per arena.
+**
+**  OUTPUT:
+**
+**      gckHEAP * Heap
+**          Pointer to a variable that will hold the pointer to the gckHEAP
+**          object.
+*/
+gceSTATUS
+gckHEAP_Construct(
+    IN gckOS Os,
+    IN gctSIZE_T AllocationSize,
+    OUT gckHEAP * Heap
+    )
+{
+    gceSTATUS status;
+    gckHEAP heap = gcvNULL;
+    gctPOINTER pointer = gcvNULL;
+
+    gcmkHEADER_ARG("Os=0x%x AllocationSize=%lu", Os, AllocationSize);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Heap != gcvNULL);
+
+    /* Allocate the gckHEAP object. */
+    gcmkONERROR(gckOS_AllocateMemory(Os,
+                                     gcmSIZEOF(struct _gckHEAP),
+                                     &pointer));
+
+    heap = pointer;
+
+    /* Initialize the gckHEAP object. */
+    heap->object.type    = gcvOBJ_HEAP;
+    heap->os             = Os;
+    heap->allocationSize = AllocationSize;
+    heap->heap           = gcvNULL;
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+    heap->timeStamp      = 0;
+#endif
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+    /* Zero the counters. */
+    heap->allocCount      = 0;
+    heap->allocBytes      = 0;
+    heap->allocBytesMax   = 0;
+    heap->allocBytesTotal = 0;
+    heap->heapCount       = 0;
+    heap->heapCountMax    = 0;
+    heap->heapMemory      = 0;
+    heap->heapMemoryMax   = 0;
+#endif
+
+    /* Create the mutex. */
+    gcmkONERROR(gckOS_CreateMutex(Os, &heap->mutex));
+
+    /* Return the pointer to the gckHEAP object. */
+    *Heap = heap;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Heap=0x%x", *Heap);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (heap != gcvNULL)
+    {
+        /* Free the heap structure. */
+        gcmkVERIFY_OK(gckOS_FreeMemory(Os, heap));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHEAP_Destroy
+**
+**  Destroy a gckHEAP object.
+**
+**  INPUT:
+**
+**      gckHEAP Heap
+**          Pointer to a gckHEAP object to destroy.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckHEAP_Destroy(
+    IN gckHEAP Heap
+    )
+{
+    gcskHEAP_PTR heap;
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+    gctSIZE_T leaked = 0;
+#endif
+
+    gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+    for (heap = Heap->heap; heap != gcvNULL; heap = Heap->heap)
+    {
+        /* Unlink heap from linked list. */
+        Heap->heap = heap->next;
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+        /* Check for leaked memory. */
+        leaked += _DumpHeap(heap);
+#endif
+
+        /* Free the heap. */
+        gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
+    }
+
+    /* Free the mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Heap->os, Heap->mutex));
+
+    /* Free the heap structure. */
+    gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, Heap));
+
+    /* Success. */
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+    gcmkFOOTER_ARG("leaked=%lu", leaked);
+#else
+    gcmkFOOTER_NO();
+#endif
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckHEAP_Allocate
+**
+**  Allocate data from the heap.
+**
+**  INPUT:
+**
+**      gckHEAP Heap
+**          Pointer to a gckHEAP object.
+**
+**      IN gctSIZE_T Bytes
+**          Number of byte to allocate.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Memory
+**          Pointer to a variable that will hold the address of the allocated
+**          memory.
+*/
+gceSTATUS
+gckHEAP_Allocate(
+    IN gckHEAP Heap,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Memory
+    )
+{
+    gctBOOL acquired = gcvFALSE;
+    gcskHEAP_PTR heap;
+    gceSTATUS status;
+    gctSIZE_T bytes;
+    gcskNODE_PTR node, used, prevFree = gcvNULL;
+    gctPOINTER memory = gcvNULL;
+
+    gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+    /* Determine number of bytes required for a node. */
+    bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8);
+
+    /* Acquire the mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+    acquired = gcvTRUE;
+
+    /* Check if this allocation is bigger than the default allocation size. */
+    if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP) - gcmSIZEOF(gcskNODE))
+    {
+        /* Adjust allocation size. */
+        Heap->allocationSize = bytes * 2;
+    }
+
+    else if (Heap->heap != gcvNULL)
+    {
+        gctINT i;
+
+        /* 2 retries, since we might need to compact. */
+        for (i = 0; i < 2; ++i)
+        {
+            /* Walk all the heaps. */
+            for (heap = Heap->heap; heap != gcvNULL; heap = heap->next)
+            {
+                /* Check if this heap has enough bytes to hold the request. */
+                if (bytes <= heap->size - gcmSIZEOF(gcskNODE))
+                {
+                    prevFree = gcvNULL;
+
+                    /* Walk the chain of free nodes. */
+                    for (node = heap->freeList;
+                         node != gcvNULL;
+                         node = node->next
+                    )
+                    {
+                        gcmkASSERT(node->next != gcdIN_USE);
+
+                        /* Check if this free node has enough bytes. */
+                        if (node->bytes >= bytes)
+                        {
+                            /* Use the node. */
+                            goto UseNode;
+                        }
+
+                        /* Save current free node for linked list management. */
+                        prevFree = node;
+                    }
+                }
+            }
+
+            if (i == 0)
+            {
+                /* Compact the heap. */
+                gcmkVERIFY_OK(_CompactKernelHeap(Heap));
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+                               "===== KERNEL HEAP =====");
+                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+                               "Number of allocations           : %12u",
+                               Heap->allocCount);
+                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+                               "Number of bytes allocated       : %12llu",
+                               Heap->allocBytes);
+                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+                               "Maximum allocation size         : %12llu",
+                               Heap->allocBytesMax);
+                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+                               "Total number of bytes allocated : %12llu",
+                               Heap->allocBytesTotal);
+                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+                               "Number of heaps                 : %12u",
+                               Heap->heapCount);
+                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+                               "Heap memory in bytes            : %12llu",
+                               Heap->heapMemory);
+                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+                               "Maximum number of heaps         : %12u",
+                               Heap->heapCountMax);
+                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+                               "Maximum heap memory in bytes    : %12llu",
+                               Heap->heapMemoryMax);
+#endif
+            }
+        }
+    }
+
+    /* Release the mutex. */
+    gcmkONERROR(
+        gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+    acquired = gcvFALSE;
+
+    /* Allocate a new heap. */
+    gcmkONERROR(
+        gckOS_AllocateMemory(Heap->os,
+                             Heap->allocationSize,
+                             &memory));
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
+                   "Allocated heap 0x%x (%lu bytes)",
+                   memory, Heap->allocationSize);
+
+    /* Acquire the mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+    acquired = gcvTRUE;
+
+    /* Use the allocated memory as the heap. */
+    heap = (gcskHEAP_PTR) memory;
+
+    /* Insert this heap to the head of the chain. */
+    heap->next = Heap->heap;
+    heap->prev = gcvNULL;
+    heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP);
+
+    if (heap->next != gcvNULL)
+    {
+        heap->next->prev = heap;
+    }
+    Heap->heap = heap;
+
+    /* Mark the end of the heap. */
+    node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap
+                          + Heap->allocationSize
+                          - gcmSIZEOF(gcskNODE)
+                          );
+    node->bytes = 0;
+    node->next  = gcvNULL;
+
+    /* Create a free list. */
+    node           = (gcskNODE_PTR) (heap + 1);
+    heap->freeList = node;
+
+    /* Initialize the free list. */
+    node->bytes = heap->size - gcmSIZEOF(gcskNODE);
+    node->next  = gcvNULL;
+
+    /* No previous free. */
+    prevFree = gcvNULL;
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+    /* Update profiling. */
+    Heap->heapCount  += 1;
+    Heap->heapMemory += Heap->allocationSize;
+
+    if (Heap->heapCount > Heap->heapCountMax)
+    {
+        Heap->heapCountMax = Heap->heapCount;
+    }
+    if (Heap->heapMemory > Heap->heapMemoryMax)
+    {
+        Heap->heapMemoryMax = Heap->heapMemory;
+    }
+#endif
+
+UseNode:
+    /* Verify some stuff. */
+    gcmkASSERT(heap != gcvNULL);
+    gcmkASSERT(node != gcvNULL);
+    gcmkASSERT(node->bytes >= bytes);
+
+    if (heap->prev != gcvNULL)
+    {
+        /* Unlink the heap from the linked list. */
+        heap->prev->next = heap->next;
+        if (heap->next != gcvNULL)
+        {
+            heap->next->prev = heap->prev;
+        }
+
+        /* Move the heap to the front of the list. */
+        heap->next       = Heap->heap;
+        heap->prev       = gcvNULL;
+        Heap->heap       = heap;
+        heap->next->prev = heap;
+    }
+
+    /* Check if there is enough free space left after usage for another free
+    ** node. */
+    if (node->bytes - bytes >= gcmSIZEOF(gcskNODE))
+    {
+        /* Allocated used space from the back of the free list. */
+        used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes);
+
+        /* Adjust the number of free bytes. */
+        node->bytes -= bytes;
+        gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE));
+    }
+    else
+    {
+        /* Remove this free list from the chain. */
+        if (prevFree == gcvNULL)
+        {
+            heap->freeList = node->next;
+        }
+        else
+        {
+            prevFree->next = node->next;
+        }
+
+        /* Consume the entire free node. */
+        used  = (gcskNODE_PTR) node;
+        bytes = node->bytes;
+    }
+
+    /* Mark node as used. */
+    used->bytes     = bytes;
+    used->next      = gcdIN_USE;
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+    used->timeStamp = ++Heap->timeStamp;
+#endif
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+    /* Update profile counters. */
+    Heap->allocCount      += 1;
+    Heap->allocBytes      += bytes;
+    Heap->allocBytesMax    = gcmMAX(Heap->allocBytes, Heap->allocBytesMax);
+    Heap->allocBytesTotal += bytes;
+#endif
+
+    /* Release the mutex. */
+    gcmkVERIFY_OK(
+        gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+    /* Return pointer to memory. */
+    *Memory = used + 1;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+    }
+
+    if (memory != gcvNULL)
+    {
+        /* Free the heap memory. */
+        gckOS_FreeMemory(Heap->os, memory);
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckHEAP_Free
+**
+**  Free allocated memory from the heap.
+**
+**  INPUT:
+**
+**      gckHEAP Heap
+**          Pointer to a gckHEAP object.
+**
+**      IN gctPOINTER Memory
+**          Pointer to memory to free.
+**
+**  OUTPUT:
+**
+**      NOTHING.
+*/
+gceSTATUS
+gckHEAP_Free(
+    IN gckHEAP Heap,
+    IN gctPOINTER Memory
+    )
+{
+    gcskNODE_PTR node;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Heap=0x%x Memory=0x%x", Heap, Memory);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+    /* Acquire the mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+    /* Pointer to structure. */
+    node = (gcskNODE_PTR) Memory - 1;
+
+    /* Mark the node as freed. */
+    node->next = gcvNULL;
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+    /* Update profile counters. */
+    Heap->allocBytes -= node->bytes;
+#endif
+
+    /* Release the mutex. */
+    gcmkVERIFY_OK(
+        gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gckHEAP_ProfileStart(
+    IN gckHEAP Heap
+    )
+{
+    gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+
+    /* Zero the counters. */
+    Heap->allocCount      = 0;
+    Heap->allocBytes      = 0;
+    Heap->allocBytesMax   = 0;
+    Heap->allocBytesTotal = 0;
+    Heap->heapCount       = 0;
+    Heap->heapCountMax    = 0;
+    Heap->heapMemory      = 0;
+    Heap->heapMemoryMax   = 0;
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHEAP_ProfileEnd(
+    IN gckHEAP Heap,
+    IN gctCONST_STRING Title
+    )
+{
+    gcmkHEADER_ARG("Heap=0x%x Title=0x%x", Heap, Title);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+    gcmkVERIFY_ARGUMENT(Title != gcvNULL);
+
+    gcmkPRINT("");
+    gcmkPRINT("=====[ HEAP - %s ]=====", Title);
+    gcmkPRINT("Number of allocations           : %12u",   Heap->allocCount);
+    gcmkPRINT("Number of bytes allocated       : %12llu", Heap->allocBytes);
+    gcmkPRINT("Maximum allocation size         : %12llu", Heap->allocBytesMax);
+    gcmkPRINT("Total number of bytes allocated : %12llu", Heap->allocBytesTotal);
+    gcmkPRINT("Number of heaps                 : %12u",   Heap->heapCount);
+    gcmkPRINT("Heap memory in bytes            : %12llu", Heap->heapMemory);
+    gcmkPRINT("Maximum number of heaps         : %12u",   Heap->heapCountMax);
+    gcmkPRINT("Maximum heap memory in bytes    : %12llu", Heap->heapMemoryMax);
+    gcmkPRINT("==============================================");
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+#endif /* VIVANTE_PROFILER */
+
+/*******************************************************************************
+***** Test Code ****************************************************************
+*******************************************************************************/
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c
new file mode 100644 (file)
index 0000000..cbc921a
--- /dev/null
@@ -0,0 +1,854 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdENABLE_VG
+
+/******************************************************************************\
+*********************** Support Functions and Definitions **********************
+\******************************************************************************/
+
+/* Interruot statistics will be accumulated if not zero. */
+#define gcmENABLE_INTERRUPT_STATISTICS 0
+
+#define _GC_OBJ_ZONE    gcvZONE_INTERRUPT
+
+/* Object structure. */
+struct _gckVGINTERRUPT
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* gckVGKERNEL pointer. */
+    gckVGKERNEL                 kernel;
+
+    /* gckOS pointer. */
+    gckOS                       os;
+
+    /* Interrupt handlers. */
+    gctINTERRUPT_HANDLER        handlers[32];
+
+    /* Main interrupt handler thread. */
+    gctTHREAD                   handler;
+    gctBOOL                     terminate;
+
+    /* Interrupt FIFO. */
+    gctSEMAPHORE                fifoValid;
+    gctUINT32                   fifo[256];
+    gctUINT                     fifoItems;
+    gctUINT8                    head;
+    gctUINT8                    tail;
+
+    /* Interrupt statistics. */
+#if gcmENABLE_INTERRUPT_STATISTICS
+    gctUINT                     maxFifoItems;
+    gctUINT                     fifoOverflow;
+    gctUINT                     maxSimultaneous;
+    gctUINT                     multipleCount;
+#endif
+};
+
+
+/*******************************************************************************
+**
+**  _ProcessInterrupt
+**
+**  The interrupt processor.
+**
+**  INPUT:
+**
+**      ThreadParameter
+**          Pointer to the gckVGINTERRUPT object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+#if gcmENABLE_INTERRUPT_STATISTICS
+static void
+_ProcessInterrupt(
+    gckVGINTERRUPT Interrupt,
+    gctUINT_PTR TriggeredCount
+    )
+#else
+static void
+_ProcessInterrupt(
+    gckVGINTERRUPT Interrupt
+    )
+#endif
+{
+    gceSTATUS status;
+    gctUINT32 triggered;
+    gctUINT i;
+
+    /* Advance to the next entry. */
+    Interrupt->tail      += 1;
+    Interrupt->fifoItems -= 1;
+
+    /* Get the interrupt value. */
+    triggered = Interrupt->fifo[Interrupt->tail];
+    gcmkASSERT(triggered != 0);
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+        "%s: triggered=0x%08X\n",
+        __FUNCTION__,
+        triggered
+        );
+
+    /* Walk through all possible interrupts. */
+    for (i = 0; i < gcmSIZEOF(Interrupt->handlers); i += 1)
+    {
+        /* Test if interrupt happened. */
+        if ((triggered & 1) == 1)
+        {
+#if gcmENABLE_INTERRUPT_STATISTICS
+            if (TriggeredCount != gcvNULL)
+            {
+                (* TriggeredCount) += 1;
+            }
+#endif
+
+            /* Make sure we have valid handler. */
+            if (Interrupt->handlers[i] == gcvNULL)
+            {
+                gcmkTRACE(
+                    gcvLEVEL_ERROR,
+                    "%s: Interrupt %d isn't registered.\n",
+                    __FUNCTION__, i
+                    );
+            }
+            else
+            {
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+                    "%s: interrupt=%d\n",
+                    __FUNCTION__,
+                    i
+                    );
+
+                /* Call the handler. */
+                status = Interrupt->handlers[i] (Interrupt->kernel);
+
+                if (gcmkIS_ERROR(status))
+                {
+                    /* Failed to signal the semaphore. */
+                    gcmkTRACE(
+                        gcvLEVEL_ERROR,
+                        "%s: Error %d incrementing the semaphore #%d.\n",
+                        __FUNCTION__, status, i
+                        );
+                }
+            }
+        }
+
+        /* Next interrupt. */
+        triggered >>= 1;
+
+        /* No more interrupts to handle? */
+        if (triggered == 0)
+        {
+            break;
+        }
+    }
+}
+
+
+/*******************************************************************************
+**
+**  _MainInterruptHandler
+**
+**  The main interrupt thread serves the interrupt FIFO and calls registered
+**  handlers for the interrupts that occured. The handlers are called in the
+**  sequence interrupts occured with the exception when multiple interrupts
+**  occured at the same time. In that case the handler calls are "sorted" by
+**  the interrupt number therefore giving the interrupts with lower numbers
+**  higher priority.
+**
+**  INPUT:
+**
+**      ThreadParameter
+**          Pointer to the gckVGINTERRUPT object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+static gctTHREADFUNCRESULT gctTHREADFUNCTYPE
+_MainInterruptHandler(
+    gctTHREADFUNCPARAMETER ThreadParameter
+    )
+{
+    gceSTATUS status;
+    gckVGINTERRUPT interrupt;
+
+#if gcmENABLE_INTERRUPT_STATISTICS
+    gctUINT count;
+#endif
+
+    /* Cast the object. */
+    interrupt = (gckVGINTERRUPT) ThreadParameter;
+
+    /* Enter the loop. */
+    while (gcvTRUE)
+    {
+        /* Wait for an interrupt. */
+        status = gckOS_DecrementSemaphore(interrupt->os, interrupt->fifoValid);
+
+        /* Error? */
+        if (gcmkIS_ERROR(status))
+        {
+            break;
+        }
+
+        /* System termination request? */
+        if (status == gcvSTATUS_TERMINATE)
+        {
+            break;
+        }
+
+        /* Driver is shutting down? */
+        if (interrupt->terminate)
+        {
+            break;
+        }
+
+#if gcmENABLE_INTERRUPT_STATISTICS
+        /* Reset triggered count. */
+        count = 0;
+
+        /* Process the interrupt. */
+        _ProcessInterrupt(interrupt, &count);
+
+        /* Update conters. */
+        if (count > interrupt->maxSimultaneous)
+        {
+            interrupt->maxSimultaneous = count;
+        }
+
+        if (count > 1)
+        {
+            interrupt->multipleCount += 1;
+        }
+#else
+        /* Process the interrupt. */
+        _ProcessInterrupt(interrupt);
+#endif
+    }
+
+    return 0;
+}
+
+
+/*******************************************************************************
+**
+**  _StartInterruptHandler / _StopInterruptHandler
+**
+**  Main interrupt handler routine control.
+**
+**  INPUT:
+**
+**      ThreadParameter
+**          Pointer to the gckVGINTERRUPT object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+static gceSTATUS
+_StartInterruptHandler(
+    gckVGINTERRUPT Interrupt
+    )
+{
+    gceSTATUS status, last;
+
+    do
+    {
+        /* Objects must not be already created. */
+        gcmkASSERT(Interrupt->fifoValid == gcvNULL);
+        gcmkASSERT(Interrupt->handler   == gcvNULL);
+
+        /* Reset the termination request. */
+        Interrupt->terminate = gcvFALSE;
+
+#if !gcdENABLE_INFINITE_SPEED_HW
+        /* Construct the fifo semaphore. */
+        gcmkERR_BREAK(gckOS_CreateSemaphoreVG(
+            Interrupt->os, &Interrupt->fifoValid
+            ));
+
+        /* Start the interrupt handler thread. */
+        gcmkERR_BREAK(gckOS_StartThread(
+            Interrupt->os,
+            _MainInterruptHandler,
+            Interrupt,
+            &Interrupt->handler
+            ));
+#endif
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    /* Roll back. */
+    if (Interrupt->fifoValid != gcvNULL)
+    {
+        gcmkCHECK_STATUS(gckOS_DestroySemaphore(
+            Interrupt->os, Interrupt->fifoValid
+            ));
+
+        Interrupt->fifoValid = gcvNULL;
+    }
+
+    /* Return the status. */
+    return status;
+}
+
+static gceSTATUS
+_StopInterruptHandler(
+    gckVGINTERRUPT Interrupt
+    )
+{
+    gceSTATUS status;
+
+    do
+    {
+        /* Does the thread exist? */
+        if (Interrupt->handler == gcvNULL)
+        {
+            /* The semaphore must be NULL as well. */
+            gcmkASSERT(Interrupt->fifoValid == gcvNULL);
+
+            /* Success. */
+            status = gcvSTATUS_OK;
+            break;
+        }
+
+        /* The semaphore must exist as well. */
+        gcmkASSERT(Interrupt->fifoValid != gcvNULL);
+
+        /* Set the termination request. */
+        Interrupt->terminate = gcvTRUE;
+
+        /* Unlock the thread. */
+        gcmkERR_BREAK(gckOS_IncrementSemaphore(
+            Interrupt->os, Interrupt->fifoValid
+            ));
+
+        /* Wait until the thread quits. */
+        gcmkERR_BREAK(gckOS_StopThread(
+            Interrupt->os,
+            Interrupt->handler
+            ));
+
+        /* Destroy the semaphore. */
+        gcmkERR_BREAK(gckOS_DestroySemaphore(
+            Interrupt->os, Interrupt->fifoValid
+            ));
+
+        /* Reset handles. */
+        Interrupt->handler   = gcvNULL;
+        Interrupt->fifoValid = gcvNULL;
+    }
+    while (gcvFALSE);
+
+    /* Return the status. */
+    return status;
+}
+
+
+/******************************************************************************\
+***************************** Interrupt Object API *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckVGINTERRUPT_Construct
+**
+**  Construct an interrupt object.
+**
+**  INPUT:
+**
+**      Kernel
+**          Pointer to the gckVGKERNEL object.
+**
+**  OUTPUT:
+**
+**      Interrupt
+**          Pointer to the new gckVGINTERRUPT object.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Construct(
+    IN gckVGKERNEL Kernel,
+    OUT gckVGINTERRUPT * Interrupt
+    )
+{
+    gceSTATUS status;
+    gckVGINTERRUPT interrupt = gcvNULL;
+
+    gcmkHEADER_ARG("Kernel=0x%x Interrupt=0x%x", Kernel, Interrupt);
+
+    /* Verify argeuments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Interrupt != gcvNULL);
+
+    do
+    {
+        /* Allocate the gckVGINTERRUPT structure. */
+        gcmkERR_BREAK(gckOS_Allocate(
+            Kernel->os,
+            gcmSIZEOF(struct _gckVGINTERRUPT),
+            (gctPOINTER *) &interrupt
+            ));
+
+        /* Reset the object data. */
+        gcmkVERIFY_OK(gckOS_ZeroMemory(
+            interrupt, gcmSIZEOF(struct _gckVGINTERRUPT)
+            ));
+
+        /* Initialize the object. */
+        interrupt->object.type = gcvOBJ_INTERRUPT;
+
+        /* Initialize the object pointers. */
+        interrupt->kernel = Kernel;
+        interrupt->os     = Kernel->os;
+
+        /* Initialize the current FIFO position. */
+        interrupt->head = (gctUINT8)~0;
+        interrupt->tail = (gctUINT8)~0;
+
+        /* Start the thread. */
+        gcmkERR_BREAK(_StartInterruptHandler(interrupt));
+
+        /* Return interrupt object. */
+        *Interrupt = interrupt;
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    /* Roll back. */
+    if (interrupt != gcvNULL)
+    {
+        /* Free the gckVGINTERRUPT structure. */
+        gcmkVERIFY_OK(gckOS_Free(interrupt->os, interrupt));
+    }
+
+    /* Return the status. */
+    return status;
+}
+
+
+/*******************************************************************************
+**
+**  gckVGINTERRUPT_Destroy
+**
+**  Destroy an interrupt object.
+**
+**  INPUT:
+**
+**      Interrupt
+**          Pointer to the gckVGINTERRUPT object to destroy.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Destroy(
+    IN gckVGINTERRUPT Interrupt
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+
+    do
+    {
+        /* Stop the interrupt thread. */
+        gcmkERR_BREAK(_StopInterruptHandler(Interrupt));
+
+        /* Mark the object as unknown. */
+        Interrupt->object.type = gcvOBJ_UNKNOWN;
+
+        /* Free the gckVGINTERRUPT structure. */
+        gcmkERR_BREAK(gckOS_Free(Interrupt->os, Interrupt));
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+
+    /* Return the status. */
+    return status;
+}
+
+
+/*******************************************************************************
+**
+**  gckVGINTERRUPT_DumpState
+**
+**  Print the current state of the interrupt manager.
+**
+**  INPUT:
+**
+**      Interrupt
+**          Pointer to a gckVGINTERRUPT object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+#if gcvDEBUG
+gceSTATUS
+gckVGINTERRUPT_DumpState(
+    IN gckVGINTERRUPT Interrupt
+    )
+{
+    gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+
+    /* Print the header. */
+    gcmkTRACE_ZONE(
+        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+        "%s: INTERRUPT OBJECT STATUS\n",
+        __FUNCTION__
+        );
+
+    /* Print statistics. */
+#if gcmENABLE_INTERRUPT_STATISTICS
+    gcmkTRACE_ZONE(
+        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+        "  Maximum number of FIFO items accumulated at a single time: %d\n",
+        Interrupt->maxFifoItems
+        );
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+        "  Interrupt FIFO overflow happened times: %d\n",
+        Interrupt->fifoOverflow
+        );
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+        "  Maximum number of interrupts simultaneously generated: %d\n",
+        Interrupt->maxSimultaneous
+        );
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+        "  Number of times when there were multiple interrupts generated: %d\n",
+        Interrupt->multipleCount
+        );
+#endif
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+        "  The current number of entries in the FIFO: %d\n",
+        Interrupt->fifoItems
+        );
+
+    /* Print the FIFO contents. */
+    if (Interrupt->fifoItems != 0)
+    {
+        gctUINT8 index;
+        gctUINT8 last;
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+            "  FIFO current contents:\n"
+            );
+
+        /* Get the current pointers. */
+        index = Interrupt->tail;
+        last  = Interrupt->head;
+
+        while (index != last)
+        {
+            /* Advance to the next entry. */
+            index += 1;
+
+            gcmkTRACE_ZONE(
+                gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+                "    %d: 0x%08X\n",
+                index, Interrupt->fifo[index]
+                );
+        }
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+#endif
+
+
+/*******************************************************************************
+**
+**  gckVGINTERRUPT_Enable
+**
+**  Enable the specified interrupt.
+**
+**  INPUT:
+**
+**      Interrupt
+**          Pointer to a gckVGINTERRUPT object.
+**
+**      Id
+**          Pointer to the variable that holds the interrupt number to be
+**          registered in range 0..31.
+**          If the value is less then 0, gckVGINTERRUPT_Enable will attempt
+**          to find an unused interrupt. If such interrupt is found, the number
+**          will be assigned to the variable if the functuion call succeedes.
+**
+**      Handler
+**          Pointer to the handler to register for the interrupt.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Enable(
+    IN gckVGINTERRUPT Interrupt,
+    IN OUT gctINT32_PTR Id,
+    IN gctINTERRUPT_HANDLER Handler
+    )
+{
+    gceSTATUS status;
+    gctINT32 i;
+
+    gcmkHEADER_ARG("Interrupt=0x%x Id=0x%x Handler=0x%x", Interrupt, Id, Handler);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+    gcmkVERIFY_ARGUMENT(Id != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Handler != gcvNULL);
+
+    do
+    {
+        /* See if we need to allocate an ID. */
+        if (*Id < 0)
+        {
+            /* Find the first unused interrupt handler. */
+            for (i = 0; i < gcmCOUNTOF(Interrupt->handlers); ++i)
+            {
+                if (Interrupt->handlers[i] == gcvNULL)
+                {
+                    break;
+                }
+            }
+
+            /* No unused innterrupts? */
+            if (i == gcmCOUNTOF(Interrupt->handlers))
+            {
+                status = gcvSTATUS_OUT_OF_RESOURCES;
+                break;
+            }
+
+            /* Update the interrupt ID. */
+            *Id = i;
+        }
+
+        /* Make sure the ID is in range. */
+        else if (*Id >= gcmCOUNTOF(Interrupt->handlers))
+        {
+            status = gcvSTATUS_INVALID_ARGUMENT;
+            break;
+        }
+
+        /* Set interrupt handler. */
+        Interrupt->handlers[*Id] = Handler;
+
+        /* Success. */
+        status = gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return the status. */
+    return status;
+}
+
+
+/*******************************************************************************
+**
+**  gckVGINTERRUPT_Disable
+**
+**  Disable the specified interrupt.
+**
+**  INPUT:
+**
+**      Interrupt
+**          Pointer to a gckVGINTERRUPT object.
+**
+**      Id
+**          Interrupt number to be disabled in range 0..31.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Disable(
+    IN gckVGINTERRUPT Interrupt,
+    IN gctINT32 Id
+    )
+{
+    gcmkHEADER_ARG("Interrupt=0x%x Id=0x%x", Interrupt, Id);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+    gcmkVERIFY_ARGUMENT((Id >= 0) && (Id < gcmCOUNTOF(Interrupt->handlers)));
+
+    /* Reset interrupt handler. */
+    Interrupt->handlers[Id] = gcvNULL;
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+**  gckVGINTERRUPT_Enque
+**
+**  Read the interrupt status register and put the value in the interrupt FIFO.
+**
+**  INPUT:
+**
+**      Interrupt
+**          Pointer to a gckVGINTERRUPT object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Enque(
+    IN gckVGINTERRUPT Interrupt
+    )
+{
+    gceSTATUS status;
+    gctUINT32 triggered;
+
+    gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+
+    do
+    {
+        /* Read interrupt status register. */
+        gcmkERR_BREAK(gckVGHARDWARE_ReadInterrupt(
+            Interrupt->kernel->hardware, &triggered
+            ));
+
+        /* No interrupts to process? */
+        if (triggered == 0)
+        {
+            status = gcvSTATUS_NOT_OUR_INTERRUPT;
+            break;
+        }
+
+        /* FIFO overflow? */
+        if (Interrupt->fifoItems == gcmCOUNTOF(Interrupt->fifo))
+        {
+#if gcmENABLE_INTERRUPT_STATISTICS
+            Interrupt->fifoOverflow += 1;
+#endif
+
+            /* OR the interrupt with the last value in the FIFO. */
+            Interrupt->fifo[Interrupt->head] |= triggered;
+
+            /* Success (kind of). */
+            status = gcvSTATUS_OK;
+        }
+        else
+        {
+            /* Advance to the next entry. */
+            Interrupt->head      += 1;
+            Interrupt->fifoItems += 1;
+
+#if gcmENABLE_INTERRUPT_STATISTICS
+            if (Interrupt->fifoItems > Interrupt->maxFifoItems)
+            {
+                Interrupt->maxFifoItems = Interrupt->fifoItems;
+            }
+#endif
+
+            /* Set the new value. */
+            Interrupt->fifo[Interrupt->head] = triggered;
+
+            /* Increment the FIFO semaphore. */
+            gcmkERR_BREAK(gckOS_IncrementSemaphore(
+                Interrupt->os, Interrupt->fifoValid
+                ));
+
+            /* Windows kills our threads prematurely when the application
+               exists. Verify here that the thread is still alive. */
+            status = gckOS_VerifyThread(Interrupt->os, Interrupt->handler);
+
+            /* Has the thread been prematurely terminated? */
+            if (status != gcvSTATUS_OK)
+            {
+                /* Process all accumulated interrupts. */
+                while (Interrupt->head != Interrupt->tail)
+                {
+#if gcmENABLE_INTERRUPT_STATISTICS
+                    /* Process the interrupt. */
+                    _ProcessInterrupt(Interrupt, gcvNULL);
+#else
+                    /* Process the interrupt. */
+                    _ProcessInterrupt(Interrupt);
+#endif
+                }
+
+                /* Set success. */
+                status = gcvSTATUS_OK;
+            }
+        }
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return status. */
+    return status;
+}
+
+#endif /* gcdENABLE_VG */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
new file mode 100644 (file)
index 0000000..7ef8835
--- /dev/null
@@ -0,0 +1,1364 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE    gcvZONE_MMU
+
+typedef enum _gceMMU_TYPE
+{
+    gcvMMU_USED = 0,
+    gcvMMU_SINGLE,
+    gcvMMU_FREE,
+}
+gceMMU_TYPE;
+
+#define gcdMMU_TABLE_DUMP       0
+
+#define gcdMMU_MTLB_SHIFT           22
+#define gcdMMU_STLB_4K_SHIFT        12
+#define gcdMMU_STLB_64K_SHIFT       16
+
+#define gcdMMU_MTLB_BITS            (32 - gcdMMU_MTLB_SHIFT)
+#define gcdMMU_PAGE_4K_BITS         gcdMMU_STLB_4K_SHIFT
+#define gcdMMU_STLB_4K_BITS         (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_4K_BITS)
+#define gcdMMU_PAGE_64K_BITS        gcdMMU_STLB_64K_SHIFT
+#define gcdMMU_STLB_64K_BITS        (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_64K_BITS)
+
+#define gcdMMU_MTLB_ENTRY_NUM       (1 << gcdMMU_MTLB_BITS)
+#define gcdMMU_MTLB_SIZE            (gcdMMU_MTLB_ENTRY_NUM << 2)
+#define gcdMMU_STLB_4K_ENTRY_NUM    (1 << gcdMMU_STLB_4K_BITS)
+#define gcdMMU_STLB_4K_SIZE         (gcdMMU_STLB_4K_ENTRY_NUM << 2)
+#define gcdMMU_PAGE_4K_SIZE         (1 << gcdMMU_STLB_4K_SHIFT)
+#define gcdMMU_STLB_64K_ENTRY_NUM   (1 << gcdMMU_STLB_64K_BITS)
+#define gcdMMU_STLB_64K_SIZE        (gcdMMU_STLB_64K_ENTRY_NUM << 2)
+#define gcdMMU_PAGE_64K_SIZE        (1 << gcdMMU_STLB_64K_SHIFT)
+
+#define gcdMMU_MTLB_MASK            (~((1U << gcdMMU_MTLB_SHIFT)-1))
+#define gcdMMU_STLB_4K_MASK         ((~0U << gcdMMU_STLB_4K_SHIFT) ^ gcdMMU_MTLB_MASK)
+#define gcdMMU_PAGE_4K_MASK         (gcdMMU_PAGE_4K_SIZE - 1)
+#define gcdMMU_STLB_64K_MASK        ((~((1U << gcdMMU_STLB_64K_SHIFT)-1)) ^ gcdMMU_MTLB_MASK)
+#define gcdMMU_PAGE_64K_MASK        (gcdMMU_PAGE_64K_SIZE - 1)
+
+typedef struct _gcsMMU_STLB *gcsMMU_STLB_PTR;
+
+typedef struct _gcsMMU_STLB
+{
+    gctPHYS_ADDR    physical;
+    gctUINT32_PTR   logical;
+    gctSIZE_T       size;
+    gctUINT32       physBase;
+    gctSIZE_T       pageCount;
+    gctUINT32       mtlbIndex;
+    gctUINT32       mtlbEntryNum;
+    gcsMMU_STLB_PTR next;
+} gcsMMU_STLB;
+
+#define gcvMMU_STLB_SIZE gcmALIGN(sizeof(gcsMMU_STLB), 4)
+
+static gceSTATUS
+_Link(
+    IN gckMMU Mmu,
+    IN gctUINT32 Index,
+    IN gctUINT32 Next
+    )
+{
+    if (Index >= Mmu->pageTableEntries)
+    {
+        /* Just move heap pointer. */
+        Mmu->heapList = Next;
+    }
+    else
+    {
+        /* Address page table. */
+        gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+
+        /* Dispatch on node type. */
+        switch (pageTable[Index] & 0xFF)
+        {
+        case gcvMMU_SINGLE:
+            /* Set single index. */
+            pageTable[Index] = (Next << 8) | gcvMMU_SINGLE;
+            break;
+
+        case gcvMMU_FREE:
+            /* Set index. */
+            pageTable[Index + 1] = Next;
+            break;
+
+        default:
+            gcmkFATAL("MMU table correcupted at index %u!", Index);
+            return gcvSTATUS_HEAP_CORRUPTED;
+        }
+    }
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_AddFree(
+    IN gckMMU Mmu,
+    IN gctUINT32 Index,
+    IN gctUINT32 Node,
+    IN gctUINT32 Count
+    )
+{
+    gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+
+    if (Count == 1)
+    {
+        /* Initialize a single page node. */
+        pageTable[Node] = (~((1U<<8)-1)) | gcvMMU_SINGLE;
+    }
+    else
+    {
+        /* Initialize the node. */
+        pageTable[Node + 0] = (Count << 8) | gcvMMU_FREE;
+        pageTable[Node + 1] = ~0U;
+    }
+
+    /* Append the node. */
+    return _Link(Mmu, Index, Node);
+}
+
+static gceSTATUS
+_Collect(
+    IN gckMMU Mmu
+    )
+{
+    gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+    gceSTATUS status;
+    gctUINT32 i, previous, start = 0, count = 0;
+
+    /* Flush the MMU cache. */
+    gcmkONERROR(
+        gckHARDWARE_FlushMMU(Mmu->hardware));
+
+    previous = Mmu->heapList = ~0U;
+    Mmu->freeNodes = gcvFALSE;
+
+    /* Walk the entire page table. */
+    for (i = 0; i < Mmu->pageTableEntries; ++i)
+    {
+        /* Dispatch based on type of page. */
+        switch (pageTable[i] & 0xFF)
+        {
+        case gcvMMU_USED:
+            /* Used page, so close any open node. */
+            if (count > 0)
+            {
+                /* Add the node. */
+                gcmkONERROR(_AddFree(Mmu, previous, start, count));
+
+                /* Reset the node. */
+                previous = start;
+                count    = 0;
+            }
+            break;
+
+        case gcvMMU_SINGLE:
+            /* Single free node. */
+            if (count++ == 0)
+            {
+                /* Start a new node. */
+                start = i;
+            }
+            break;
+
+        case gcvMMU_FREE:
+            /* A free node. */
+            if (count == 0)
+            {
+                /* Start a new node. */
+                start = i;
+            }
+
+            /* Advance the count. */
+            count += pageTable[i] >> 8;
+
+            /* Advance the index into the page table. */
+            i     += (pageTable[i] >> 8) - 1;
+            break;
+
+        default:
+            gcmkFATAL("MMU page table correcupted at index %u!", i);
+            return gcvSTATUS_HEAP_CORRUPTED;
+        }
+    }
+
+    /* See if we have an open node left. */
+    if (count > 0)
+    {
+        /* Add the node to the list. */
+        gcmkONERROR(_AddFree(Mmu, previous, start, count));
+    }
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_MMU,
+                   "Performed a garbage collection of the MMU heap.");
+
+    /* Success. */
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the staus. */
+    return status;
+}
+
+static gceSTATUS
+_GetStlb(
+    IN gckMMU Mmu,
+    IN gctSIZE_T PageCount,
+    OUT gcsMMU_STLB_PTR *Stlb
+    )
+{
+    gceSTATUS status;
+    gcsMMU_STLB_PTR stlb = gcvNULL;
+    gctPHYS_ADDR physical;
+    gctPOINTER logical = gcvNULL;
+    gctSIZE_T size = (PageCount << 2) + gcvMMU_STLB_SIZE;
+    gctUINT32 address;
+
+    gcmkONERROR(
+            gckOS_AllocateContiguous(Mmu->os,
+                                     gcvFALSE,
+                                     &size,
+                                     &physical,
+                                     &logical));
+
+    gcmkONERROR(gckOS_ZeroMemory(logical, size));
+
+    /* Convert logical address into a physical address. */
+    gcmkONERROR(
+        gckOS_GetPhysicalAddress(Mmu->os, logical, &address));
+
+    stlb = (gcsMMU_STLB_PTR)logical;
+    stlb->pageCount = PageCount;
+    stlb->logical = logical;
+    stlb->physical = physical;
+    stlb->physBase = address;
+    stlb->size = size;
+    stlb->mtlbIndex = ~0U;
+    stlb->mtlbEntryNum = 0;
+    stlb->next = gcvNULL;
+
+    *Stlb = stlb;
+
+    return gcvSTATUS_OK;
+
+OnError:
+
+    if (logical != gcvNULL)
+    {
+        gckOS_FreeContiguous(
+            Mmu->os,
+            physical,
+            logical,
+            size
+            );
+    }
+
+    return status;
+}
+
+static gceSTATUS
+_PutStlb(
+    IN gckMMU Mmu,
+    IN gcsMMU_STLB_PTR Stlb
+    )
+{
+    gcmkASSERT(Stlb->logical == (gctPOINTER)Stlb);
+
+    return gckOS_FreeContiguous(
+            Mmu->os,
+            Stlb->physical,
+            Stlb,
+            Stlb->size
+            );
+}
+
+static gctUINT32
+_SetPage(gctUINT32 PageAddress)
+{
+    return PageAddress
+           /* writable */
+           | (1 << 2)
+           /* Ignore exception */
+           | (0 << 1)
+           /* Present */
+           | (1 << 0);
+}
+
+static gceSTATUS
+_FillFlatMapping(
+    IN gckMMU Mmu,
+    IN gctUINT32 PhysBase,
+    OUT gctSIZE_T Size
+    )
+{
+    gceSTATUS status;
+    gctBOOL mutex = gcvFALSE;
+    gcsMMU_STLB_PTR head = gcvNULL, pre = gcvNULL;
+    gctUINT32 start = PhysBase & (~gcdMMU_PAGE_64K_MASK);
+    gctUINT32 end = (PhysBase + Size - 1) & (~gcdMMU_PAGE_64K_MASK);
+    gctUINT32 mStart = start >> gcdMMU_MTLB_SHIFT;
+    gctUINT32 mEnd = end >> gcdMMU_MTLB_SHIFT;
+    gctUINT32 sStart = (start & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
+    gctUINT32 sEnd = (end & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
+
+    /* Grab the mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+    mutex = gcvTRUE;
+
+    while (mStart <= mEnd)
+    {
+        gcmkASSERT(mStart < gcdMMU_MTLB_ENTRY_NUM);
+        if (*(Mmu->pageTableLogical + mStart) == 0)
+        {
+            gcsMMU_STLB_PTR stlb;
+            gctPOINTER pointer = gcvNULL;
+            gctUINT32 last = (mStart == mEnd) ? sEnd : (gcdMMU_STLB_64K_ENTRY_NUM - 1);
+
+            gcmkONERROR(gckOS_Allocate(Mmu->os, sizeof(struct _gcsMMU_STLB), &pointer));
+            stlb = pointer;
+
+            stlb->mtlbEntryNum = 0;
+            stlb->next = gcvNULL;
+            stlb->physical = gcvNULL;
+            stlb->logical = gcvNULL;
+            stlb->size = gcdMMU_STLB_64K_SIZE;
+            stlb->pageCount = 0;
+
+            if (pre == gcvNULL)
+            {
+                pre = head = stlb;
+            }
+            else
+            {
+                gcmkASSERT(pre->next == gcvNULL);
+                pre->next = stlb;
+                pre = stlb;
+            }
+
+            gcmkONERROR(
+                    gckOS_AllocateContiguous(Mmu->os,
+                                             gcvFALSE,
+                                             &stlb->size,
+                                             &stlb->physical,
+                                             (gctPOINTER)&stlb->logical));
+
+            gcmkONERROR(gckOS_ZeroMemory(stlb->logical, stlb->size));
+
+            gcmkONERROR(gckOS_GetPhysicalAddress(
+                Mmu->os,
+                stlb->logical,
+                &stlb->physBase));
+
+            if (stlb->physBase & (gcdMMU_STLB_64K_SIZE - 1))
+            {
+                gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+            }
+
+            *(Mmu->pageTableLogical + mStart)
+                      = stlb->physBase
+                        /* 64KB page size */
+                        | (1 << 2)
+                        /* Ignore exception */
+                        | (0 << 1)
+                        /* Present */
+                        | (1 << 0);
+#if gcdMMU_TABLE_DUMP
+            gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
+                __FUNCTION__, __LINE__,
+                mStart,
+                *(Mmu->pageTableLogical + mStart));
+#endif
+
+            stlb->mtlbIndex = mStart;
+            stlb->mtlbEntryNum = 1;
+#if gcdMMU_TABLE_DUMP
+            gckOS_Print("%s(%d): STLB: logical:%08x -> physical:%08x\n",
+                    __FUNCTION__, __LINE__,
+                    stlb->logical,
+                    stlb->physBase);
+#endif
+
+            while (sStart <= last)
+            {
+                gcmkASSERT(!(start & gcdMMU_PAGE_64K_MASK));
+                *(stlb->logical + sStart) = _SetPage(start);
+#if gcdMMU_TABLE_DUMP
+                gckOS_Print("%s(%d): insert STLB[%d]: %08x\n",
+                    __FUNCTION__, __LINE__,
+                    sStart,
+                    *(stlb->logical + sStart));
+#endif
+                /* next page. */
+                start += gcdMMU_PAGE_64K_SIZE;
+                sStart++;
+                stlb->pageCount++;
+            }
+
+            sStart = 0;
+            ++mStart;
+        }
+        else
+        {
+            gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+        }
+    }
+
+    /* Insert the stlb into staticSTLB. */
+    if (Mmu->staticSTLB == gcvNULL)
+    {
+        Mmu->staticSTLB = head;
+    }
+    else
+    {
+               gcmkASSERT(pre == gcvNULL);
+        gcmkASSERT(pre->next == gcvNULL);
+        pre->next = Mmu->staticSTLB;
+        Mmu->staticSTLB = head;
+    }
+
+    /* Release the mutex. */
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+
+    return gcvSTATUS_OK;
+
+OnError:
+
+    /* Roll back. */
+    while (head != gcvNULL)
+    {
+        pre = head;
+        head = head->next;
+
+        if (pre->physical != gcvNULL)
+        {
+            gcmkVERIFY_OK(
+                gckOS_FreeContiguous(Mmu->os,
+                    pre->physical,
+                    pre->logical,
+                    pre->size));
+        }
+
+        if (pre->mtlbEntryNum != 0)
+        {
+            gcmkASSERT(pre->mtlbEntryNum == 1);
+            *(Mmu->pageTableLogical + pre->mtlbIndex) = 0;
+        }
+
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
+    }
+
+    if (mutex)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckMMU_Construct
+**
+**  Construct a new gckMMU object.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctSIZE_T MmuSize
+**          Number of bytes for the page table.
+**
+**  OUTPUT:
+**
+**      gckMMU * Mmu
+**          Pointer to a variable that receives the gckMMU object pointer.
+*/
+gceSTATUS
+gckMMU_Construct(
+    IN gckKERNEL Kernel,
+    IN gctSIZE_T MmuSize,
+    OUT gckMMU * Mmu
+    )
+{
+    gckOS os;
+    gckHARDWARE hardware;
+    gceSTATUS status;
+    gckMMU mmu = gcvNULL;
+    gctUINT32_PTR pageTable;
+    gctPOINTER pointer = gcvNULL;
+
+    gcmkHEADER_ARG("Kernel=0x%x MmuSize=%lu", Kernel, MmuSize);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(MmuSize > 0);
+    gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
+
+    /* Extract the gckOS object pointer. */
+    os = Kernel->os;
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+    /* Extract the gckHARDWARE object pointer. */
+    hardware = Kernel->hardware;
+    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+    /* Allocate memory for the gckMMU object. */
+    gcmkONERROR(gckOS_Allocate(os, sizeof(struct _gckMMU), &pointer));
+
+    mmu = pointer;
+
+    /* Initialize the gckMMU object. */
+    mmu->object.type      = gcvOBJ_MMU;
+    mmu->os               = os;
+    mmu->hardware         = hardware;
+    mmu->pageTableMutex   = gcvNULL;
+    mmu->pageTableLogical = gcvNULL;
+    mmu->staticSTLB       = gcvNULL;
+    mmu->enabled          = gcvFALSE;
+#ifdef __QNXNTO__
+    mmu->nodeList         = gcvNULL;
+    mmu->nodeMutex        = gcvNULL;
+#endif
+
+    /* Create the page table mutex. */
+    gcmkONERROR(gckOS_CreateMutex(os, &mmu->pageTableMutex));
+
+#ifdef __QNXNTO__
+    /* Create the node list mutex. */
+    gcmkONERROR(gckOS_CreateMutex(os, &mmu->nodeMutex));
+#endif
+
+    if (hardware->mmuVersion == 0)
+    {
+        /* Allocate the page table (not more than 256 kB). */
+        mmu->pageTableSize = gcmMIN(MmuSize, 256 << 10);
+        gcmkONERROR(
+            gckOS_AllocateContiguous(os,
+                                     gcvFALSE,
+                                     &mmu->pageTableSize,
+                                     &mmu->pageTablePhysical,
+                                     &pointer));
+
+        mmu->pageTableLogical = pointer;
+
+        /* Compute number of entries in page table. */
+        mmu->pageTableEntries = mmu->pageTableSize / sizeof(gctUINT32);
+
+        /* Mark all pages as free. */
+        pageTable      = mmu->pageTableLogical;
+        pageTable[0]   = (mmu->pageTableEntries << 8) | gcvMMU_FREE;
+        pageTable[1]   = ~0U;
+        mmu->heapList  = 0;
+        mmu->freeNodes = gcvFALSE;
+
+        /* Set page table address. */
+        gcmkONERROR(
+            gckHARDWARE_SetMMU(hardware, (gctPOINTER) mmu->pageTableLogical));
+    }
+    else
+    {
+        /* Allocate the 4K mode MTLB table. */
+        mmu->pageTableSize = gcdMMU_MTLB_SIZE + 64;
+
+        gcmkONERROR(
+            gckOS_AllocateContiguous(os,
+                                     gcvFALSE,
+                                     &mmu->pageTableSize,
+                                     &mmu->pageTablePhysical,
+                                     &pointer));
+
+        mmu->pageTableLogical = pointer;
+
+        /* Invalid all the entries. */
+        gcmkONERROR(
+            gckOS_ZeroMemory(pointer, mmu->pageTableSize));
+    }
+
+    /* Return the gckMMU object pointer. */
+    *Mmu = mmu;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Mmu=0x%x", *Mmu);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (mmu != gcvNULL)
+    {
+        if (mmu->pageTableLogical != gcvNULL)
+        {
+            /* Free the page table. */
+            gcmkVERIFY_OK(
+                gckOS_FreeContiguous(os,
+                                     mmu->pageTablePhysical,
+                                     (gctPOINTER) mmu->pageTableLogical,
+                                     mmu->pageTableSize));
+        }
+
+        if (mmu->pageTableMutex != gcvNULL)
+        {
+            /* Delete the mutex. */
+            gcmkVERIFY_OK(
+                gckOS_DeleteMutex(os, mmu->pageTableMutex));
+        }
+
+#ifdef __QNXNTO__
+        if (mmu->nodeMutex != gcvNULL)
+        {
+            /* Delete the mutex. */
+            gcmkVERIFY_OK(
+                gckOS_DeleteMutex(os, mmu->nodeMutex));
+        }
+#endif
+
+        /* Mark the gckMMU object as unknown. */
+        mmu->object.type = gcvOBJ_UNKNOWN;
+
+        /* Free the allocates memory. */
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, mmu));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckMMU_Destroy
+**
+**  Destroy a gckMMU object.
+**
+**  INPUT:
+**
+**      gckMMU Mmu
+**          Pointer to an gckMMU object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckMMU_Destroy(
+    IN gckMMU Mmu
+    )
+{
+#ifdef __QNXNTO__
+    gcuVIDMEM_NODE_PTR node, next;
+#endif
+
+    gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+#ifdef __QNXNTO__
+    /* Free all associated virtual memory. */
+    for (node = Mmu->nodeList; node != gcvNULL; node = next)
+    {
+        next = node->Virtual.next;
+        gcmkVERIFY_OK(gckVIDMEM_Free(node));
+    }
+#endif
+
+    while (Mmu->staticSTLB != gcvNULL)
+    {
+        gcsMMU_STLB_PTR pre = Mmu->staticSTLB;
+        Mmu->staticSTLB = pre->next;
+
+        if (pre->physical != gcvNULL)
+        {
+            gcmkVERIFY_OK(
+                gckOS_FreeContiguous(Mmu->os,
+                    pre->physical,
+                    pre->logical,
+                    pre->size));
+        }
+
+        if (pre->mtlbEntryNum != 0)
+        {
+            gcmkASSERT(pre->mtlbEntryNum == 1);
+            *(Mmu->pageTableLogical + pre->mtlbIndex) = 0;
+#if gcdMMU_TABLE_DUMP
+            gckOS_Print("%s(%d): clean MTLB[%d]\n",
+                __FUNCTION__, __LINE__,
+                pre->mtlbIndex);
+#endif
+        }
+
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
+    }
+
+    /* Free the page table. */
+    gcmkVERIFY_OK(
+        gckOS_FreeContiguous(Mmu->os,
+                             Mmu->pageTablePhysical,
+                             (gctPOINTER) Mmu->pageTableLogical,
+                             Mmu->pageTableSize));
+
+#ifdef __QNXNTO__
+    /* Delete the node list mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->nodeMutex));
+#endif
+
+    /* Delete the page table mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->pageTableMutex));
+
+    /* Mark the gckMMU object as unknown. */
+    Mmu->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the gckMMU object. */
+    gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, Mmu));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckMMU_AllocatePages
+**
+**  Allocate pages inside the page table.
+**
+**  INPUT:
+**
+**      gckMMU Mmu
+**          Pointer to an gckMMU object.
+**
+**      gctSIZE_T PageCount
+**          Number of pages to allocate.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * PageTable
+**          Pointer to a variable that receives the base address of the page
+**          table.
+**
+**      gctUINT32 * Address
+**          Pointer to a variable that receives the hardware specific address.
+*/
+gceSTATUS
+gckMMU_AllocatePages(
+    IN gckMMU Mmu,
+    IN gctSIZE_T PageCount,
+    OUT gctPOINTER * PageTable,
+    OUT gctUINT32 * Address
+    )
+{
+    gceSTATUS status;
+    gctBOOL mutex = gcvFALSE;
+    gctUINT32 index = 0, previous = ~0U, left;
+    gctUINT32_PTR pageTable;
+    gctBOOL gotIt;
+    gctUINT32 address;
+
+    gcmkHEADER_ARG("Mmu=0x%x PageCount=%lu", Mmu, PageCount);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+    gcmkVERIFY_ARGUMENT(PageCount > 0);
+    gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+
+    if (Mmu->hardware->mmuVersion == 0)
+    {
+        if (PageCount > Mmu->pageTableEntries)
+        {
+            /* Not enough pages avaiable. */
+            gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+        }
+
+        /* Grab the mutex. */
+        gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+        mutex = gcvTRUE;
+
+        /* Cast pointer to page table. */
+        for (pageTable = Mmu->pageTableLogical, gotIt = gcvFALSE; !gotIt;)
+        {
+            /* Walk the heap list. */
+            for (index = Mmu->heapList; !gotIt && (index < Mmu->pageTableEntries);)
+            {
+                /* Check the node type. */
+                switch (pageTable[index] & 0xFF)
+                {
+                case gcvMMU_SINGLE:
+                    /* Single odes are valid if we only need 1 page. */
+                    if (PageCount == 1)
+                    {
+                        gotIt = gcvTRUE;
+                    }
+                    else
+                    {
+                        /* Move to next node. */
+                        previous = index;
+                        index    = pageTable[index] >> 8;
+                    }
+                    break;
+
+                case gcvMMU_FREE:
+                    /* Test if the node has enough space. */
+                    if (PageCount <= (pageTable[index] >> 8))
+                    {
+                        gotIt = gcvTRUE;
+                    }
+                    else
+                    {
+                        /* Move to next node. */
+                        previous = index;
+                        index    = pageTable[index + 1];
+                    }
+                    break;
+
+                default:
+                    gcmkFATAL("MMU table correcupted at index %u!", index);
+                    gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+                }
+            }
+
+            /* Test if we are out of memory. */
+            if (index >= Mmu->pageTableEntries)
+            {
+                if (Mmu->freeNodes)
+                {
+                    /* Time to move out the trash! */
+                    gcmkONERROR(_Collect(Mmu));
+                }
+                else
+                {
+                    /* Out of resources. */
+                    gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+                }
+            }
+        }
+
+        switch (pageTable[index] & 0xFF)
+        {
+        case gcvMMU_SINGLE:
+            /* Unlink single node from free list. */
+            gcmkONERROR(
+                _Link(Mmu, previous, pageTable[index] >> 8));
+            break;
+
+        case gcvMMU_FREE:
+            /* Check how many pages will be left. */
+            left = (pageTable[index] >> 8) - PageCount;
+            switch (left)
+            {
+            case 0:
+                /* The entire node is consumed, just unlink it. */
+                gcmkONERROR(
+                    _Link(Mmu, previous, pageTable[index + 1]));
+                break;
+
+            case 1:
+                /* One page will remain.  Convert the node to a single node and
+                ** advance the index. */
+                pageTable[index] = (pageTable[index + 1] << 8) | gcvMMU_SINGLE;
+                index ++;
+                break;
+
+            default:
+                /* Enough pages remain for a new node.  However, we will just adjust
+                ** the size of the current node and advance the index. */
+                pageTable[index] = (left << 8) | gcvMMU_FREE;
+                index += left;
+                break;
+            }
+            break;
+        }
+
+        /* Mark node as used. */
+        pageTable[index] = gcvMMU_USED;
+
+        /* Return pointer to page table. */
+        *PageTable = &pageTable[index];
+
+        /* Build virtual address. */
+        gcmkONERROR(
+            gckHARDWARE_BuildVirtualAddress(Mmu->hardware, index, 0, &address));
+
+        if (Address != gcvNULL)
+        {
+            *Address = address;
+        }
+
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+
+        /* Success. */
+        gcmkFOOTER_ARG("*PageTable=0x%x *Address=%08x",
+                       *PageTable, gcmOPT_VALUE(Address));
+        return gcvSTATUS_OK;
+    }
+    else
+    {
+        gctUINT i, j;
+        gctUINT32 addr;
+        gctBOOL succeed = gcvFALSE;
+        gcsMMU_STLB_PTR stlb = gcvNULL;
+        gctUINT nMtlbEntry =
+            gcmALIGN(PageCount, gcdMMU_STLB_4K_ENTRY_NUM) / gcdMMU_STLB_4K_ENTRY_NUM;
+
+        if (Mmu->enabled == gcvFALSE)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_MMU,
+                "gckMMU_AllocatePages(New MMU): failed by the MMU not enabled");
+
+            gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+        }
+
+        /* Grab the mutex. */
+        gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+        mutex = gcvTRUE;
+
+        for (i = 0; i < gcdMMU_MTLB_ENTRY_NUM; i++)
+        {
+            if (*(Mmu->pageTableLogical + i) == 0)
+            {
+                succeed = gcvTRUE;
+
+                for (j = 1; j < nMtlbEntry; j++)
+                {
+                    if (*(Mmu->pageTableLogical + i + j) != 0)
+                    {
+                        succeed = gcvFALSE;
+                        break;
+                    }
+                }
+
+                if (succeed == gcvTRUE)
+                {
+                    break;
+                }
+            }
+        }
+
+        if (succeed == gcvFALSE)
+        {
+            gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+        }
+
+        gcmkONERROR(_GetStlb(Mmu, PageCount, &stlb));
+
+        stlb->mtlbIndex = i;
+        stlb->mtlbEntryNum = nMtlbEntry;
+
+        addr = stlb->physBase;
+        for (j = 0; j < nMtlbEntry; j++)
+        {
+            gcmkASSERT(!(addr & (gcdMMU_STLB_4K_SIZE - 1)));
+            *(Mmu->pageTableLogical + i + j) =  addr
+                        /* 4KB page size */
+                        | (0 << 2)
+                        /* Ignore exception */
+                        | (0 << 1)
+                        /* Present */
+                        | (1 << 0);
+#if gcdMMU_TABLE_DUMP
+            gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
+                __FUNCTION__, __LINE__,
+                i + j,
+                *(Mmu->pageTableLogical + i + j));
+#endif
+            addr += gcdMMU_STLB_4K_SIZE;
+        }
+
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+
+        *PageTable = (gctUINT8_PTR)stlb + gcvMMU_STLB_SIZE;
+
+        if (Address != gcvNULL)
+        {
+            *Address = (i << gcdMMU_MTLB_SHIFT)
+                     | (gcvMMU_STLB_SIZE << 10);
+        }
+
+        /* Flush the MMU cache. */
+        gcmkONERROR(
+            gckHARDWARE_FlushMMU(Mmu->hardware));
+
+        /* Success. */
+        gcmkFOOTER_ARG("*PageTable=0x%x *Address=%08x",
+                       *PageTable, gcmOPT_VALUE(Address));
+        return gcvSTATUS_OK;
+    }
+
+OnError:
+
+    if (mutex)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckMMU_FreePages
+**
+**  Free pages inside the page table.
+**
+**  INPUT:
+**
+**      gckMMU Mmu
+**          Pointer to an gckMMU object.
+**
+**      gctPOINTER PageTable
+**          Base address of the page table to free.
+**
+**      gctSIZE_T PageCount
+**          Number of pages to free.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckMMU_FreePages(
+    IN gckMMU Mmu,
+    IN gctPOINTER PageTable,
+    IN gctSIZE_T PageCount
+    )
+{
+    gceSTATUS status;
+    gctBOOL mutex = gcvFALSE;
+
+    gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=%lu",
+                   Mmu, PageTable, PageCount);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+    gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+    gcmkVERIFY_ARGUMENT(PageCount > 0);
+
+    if (Mmu->hardware->mmuVersion == 0)
+    {
+        gctUINT32_PTR pageTable;
+
+        /* Convert the pointer. */
+        pageTable = (gctUINT32_PTR) PageTable;
+
+        if (PageCount == 1)
+        {
+            /* Single page node. */
+            pageTable[0] = (~((1U<<8)-1)) | gcvMMU_SINGLE;
+        }
+        else
+        {
+            /* Mark the node as free. */
+            pageTable[0] = (PageCount << 8) | gcvMMU_FREE;
+            pageTable[1] = ~0U;
+        }
+
+        /* We have free nodes. */
+        Mmu->freeNodes = gcvTRUE;
+
+        /* Success. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+    else
+    {
+        gcsMMU_STLB_PTR stlb = (gcsMMU_STLB_PTR)((gctUINT8_PTR) PageTable - gcvMMU_STLB_SIZE);
+        gctUINT32 i;
+
+        if (Mmu->enabled == gcvFALSE)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_MMU,
+                "gckMMU_FreePages(New MMU): failed by the MMU not enabled");
+
+            gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+        }
+
+        if ((stlb->logical != (gctPOINTER)stlb)
+            || (stlb->pageCount != PageCount)
+            || (stlb->mtlbIndex >= gcdMMU_MTLB_ENTRY_NUM)
+            || (stlb->mtlbEntryNum == 0))
+        {
+            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+        }
+
+        /* Flush the MMU cache. */
+        gcmkONERROR(
+            gckHARDWARE_FlushMMU(Mmu->hardware));
+
+        /* Grab the mutex. */
+        gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+        mutex = gcvTRUE;
+
+        for (i = 0; i < stlb->mtlbEntryNum; i++)
+        {
+            /* clean the MTLB entries. */
+            gcmkASSERT((*(Mmu->pageTableLogical + stlb->mtlbIndex + i) & 7) == 1);
+            *(Mmu->pageTableLogical + stlb->mtlbIndex + i) = 0;
+#if gcdMMU_TABLE_DUMP
+            gckOS_Print("%s(%d): clean MTLB[%d]\n",
+                __FUNCTION__, __LINE__,
+                stlb->mtlbIndex + i);
+#endif
+        }
+
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+        mutex = gcvFALSE;
+
+        gcmkONERROR(_PutStlb(Mmu, stlb));
+
+        /* Success. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+OnError:
+    if (mutex)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckMMU_Enable(
+    IN gckMMU Mmu,
+    IN gctUINT32 PhysBaseAddr,
+    IN gctUINT32 PhysSize
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+    if (Mmu->hardware->mmuVersion == 0)
+    {
+        /* Success. */
+        gcmkFOOTER_ARG("Status=%d", gcvSTATUS_SKIP);
+        return gcvSTATUS_SKIP;
+    }
+    else
+    {
+        if (PhysSize != 0)
+        {
+            gcmkONERROR(_FillFlatMapping(
+                Mmu,
+                PhysBaseAddr,
+                PhysSize
+                ));
+        }
+
+        gcmkONERROR(
+            gckHARDWARE_SetMMUv2(
+                Mmu->hardware,
+                gcvTRUE,
+                Mmu->pageTableLogical,
+                gcvMMU_MODE_4K,
+                (gctUINT8_PTR)Mmu->pageTableLogical + gcdMMU_MTLB_SIZE
+                ));
+
+        Mmu->enabled = gcvTRUE;
+
+        /* Success. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckMMU_SetPage(
+    IN gckMMU Mmu,
+    IN gctUINT32 PageAddress,
+    IN gctUINT32 *PageEntry
+    )
+{
+    gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+    gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
+    gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
+
+    if (Mmu->hardware->mmuVersion == 0)
+    {
+        *PageEntry = PageAddress;
+    }
+    else
+    {
+        *PageEntry = _SetPage(PageAddress);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+#ifdef __QNXNTO__
+gceSTATUS
+gckMMU_InsertNode(
+    IN gckMMU Mmu,
+    IN gcuVIDMEM_NODE_PTR Node)
+{
+    gceSTATUS status;
+    gctBOOL mutex = gcvFALSE;
+
+    gcmkHEADER_ARG("Mmu=0x%x Node=0x%x", Mmu, Node);
+
+    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+    gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
+    mutex = gcvTRUE;
+
+    Node->Virtual.next = Mmu->nodeList;
+    Mmu->nodeList = Node;
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (mutex)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckMMU_RemoveNode(
+    IN gckMMU Mmu,
+    IN gcuVIDMEM_NODE_PTR Node)
+{
+    gceSTATUS status;
+    gctBOOL mutex = gcvFALSE;
+    gcuVIDMEM_NODE_PTR *iter;
+
+    gcmkHEADER_ARG("Mmu=0x%x Node=0x%x", Mmu, Node);
+
+    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+    gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
+    mutex = gcvTRUE;
+
+    for (iter = &Mmu->nodeList; *iter; iter = &(*iter)->Virtual.next)
+    {
+        if (*iter == Node)
+        {
+            *iter = Node->Virtual.next;
+            break;
+        }
+    }
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (mutex)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckMMU_FreeHandleMemory(
+    IN gckKERNEL Kernel,
+    IN gckMMU Mmu,
+    IN gctUINT32 Pid
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gcuVIDMEM_NODE_PTR curr, next;
+
+    gcmkHEADER_ARG("Kernel=0x%x, Mmu=0x%x Pid=%u", Kernel, Mmu, Pid);
+
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+    gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    for (curr = Mmu->nodeList; curr != gcvNULL; curr = next)
+    {
+        next = curr->Virtual.next;
+
+        if (curr->Virtual.processID == Pid)
+        {
+            while (curr->Virtual.unlockPendings[Kernel->core] == 0 && curr->Virtual.lockeds[Kernel->core] > 0)
+            {
+                gcmkONERROR(gckVIDMEM_Unlock(Kernel, curr, gcvSURF_TYPE_UNKNOWN, gcvNULL));
+            }
+
+            gcmkVERIFY_OK(gckVIDMEM_Free(curr));
+        }
+    }
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+#endif
+
+/******************************************************************************
+****************************** T E S T   C O D E ******************************
+******************************************************************************/
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c
new file mode 100644 (file)
index 0000000..e320627
--- /dev/null
@@ -0,0 +1,503 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdENABLE_VG
+
+#define _GC_OBJ_ZONE    gcvZONE_MMU
+
+/*******************************************************************************
+**
+**  gckVGMMU_Construct
+**
+**  Construct a new gckVGMMU object.
+**
+**  INPUT:
+**
+**      gckVGKERNEL Kernel
+**          Pointer to an gckVGKERNEL object.
+**
+**      gctSIZE_T MmuSize
+**          Number of bytes for the page table.
+**
+**  OUTPUT:
+**
+**      gckVGMMU * Mmu
+**          Pointer to a variable that receives the gckVGMMU object pointer.
+*/
+gceSTATUS gckVGMMU_Construct(
+    IN gckVGKERNEL Kernel,
+    IN gctSIZE_T MmuSize,
+    OUT gckVGMMU * Mmu
+    )
+{
+    gckOS os;
+    gckVGHARDWARE hardware;
+    gceSTATUS status;
+    gckVGMMU mmu;
+    gctUINT32 * pageTable;
+    gctUINT32 i;
+
+    gcmkHEADER_ARG("Kernel=0x%x MmuSize=0x%x Mmu=0x%x", Kernel, MmuSize, Mmu);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(MmuSize > 0);
+    gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
+
+    /* Extract the gckOS object pointer. */
+    os = Kernel->os;
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+    /* Extract the gckVGHARDWARE object pointer. */
+    hardware = Kernel->hardware;
+    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+    /* Allocate memory for the gckVGMMU object. */
+    status = gckOS_Allocate(os, sizeof(struct _gckVGMMU), (gctPOINTER *) &mmu);
+
+    if (status < 0)
+    {
+        /* Error. */
+        gcmkFATAL(
+            "%s(%d): could not allocate gckVGMMU object.",
+            __FUNCTION__, __LINE__
+            );
+
+        return status;
+    }
+
+    /* Initialize the gckVGMMU object. */
+    mmu->object.type = gcvOBJ_MMU;
+    mmu->os = os;
+    mmu->hardware = hardware;
+
+    /* Create the mutex. */
+    status = gckOS_CreateMutex(os, &mmu->mutex);
+
+    if (status < 0)
+    {
+        /* Roll back. */
+        mmu->object.type = gcvOBJ_UNKNOWN;
+        gcmkVERIFY_OK(gckOS_Free(os, mmu));
+
+        /* Error. */
+        return status;
+    }
+
+    /* Allocate the page table. */
+    mmu->pageTableSize = MmuSize;
+    status = gckOS_AllocateContiguous(os,
+                                      gcvFALSE,
+                                      &mmu->pageTableSize,
+                                      &mmu->pageTablePhysical,
+                                      &mmu->pageTableLogical);
+
+    if (status < 0)
+    {
+        /* Roll back. */
+        gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex));
+
+        mmu->object.type = gcvOBJ_UNKNOWN;
+        gcmkVERIFY_OK(gckOS_Free(os, mmu));
+
+        /* Error. */
+        gcmkFATAL(
+            "%s(%d): could not allocate page table.",
+            __FUNCTION__, __LINE__
+            );
+
+        return status;
+    }
+
+    /* Compute number of entries in page table. */
+    mmu->entryCount = mmu->pageTableSize / sizeof(gctUINT32);
+    mmu->entry = 0;
+
+    /* Mark the entire page table as available. */
+    pageTable = (gctUINT32 *) mmu->pageTableLogical;
+    for (i = 0; i < mmu->entryCount; i++)
+    {
+        pageTable[i] = (gctUINT32)~0;
+    }
+
+    /* Set page table address. */
+    status = gckVGHARDWARE_SetMMU(hardware, mmu->pageTableLogical);
+
+    if (status < 0)
+    {
+        /* Free the page table. */
+        gcmkVERIFY_OK(gckOS_FreeContiguous(mmu->os,
+                                      mmu->pageTablePhysical,
+                                      mmu->pageTableLogical,
+                                      mmu->pageTableSize));
+
+        /* Roll back. */
+        gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex));
+
+        mmu->object.type = gcvOBJ_UNKNOWN;
+        gcmkVERIFY_OK(gckOS_Free(os, mmu));
+
+        /* Error. */
+        gcmkFATAL(
+            "%s(%d): could not program page table.",
+            __FUNCTION__, __LINE__
+            );
+
+        return status;
+    }
+
+    /* Return the gckVGMMU object pointer. */
+    *Mmu = mmu;
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_INFO, gcvZONE_MMU,
+        "%s(%d): %u entries at %p.(0x%08X)\n",
+        __FUNCTION__, __LINE__,
+        mmu->entryCount,
+        mmu->pageTableLogical,
+        mmu->pageTablePhysical
+        );
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGMMU_Destroy
+**
+**  Destroy a nAQMMU object.
+**
+**  INPUT:
+**
+**      gckVGMMU Mmu
+**          Pointer to an gckVGMMU object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS gckVGMMU_Destroy(
+    IN gckVGMMU Mmu
+    )
+{
+    gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+    /* Free the page table. */
+    gcmkVERIFY_OK(gckOS_FreeContiguous(Mmu->os,
+                                  Mmu->pageTablePhysical,
+                                  Mmu->pageTableLogical,
+                                  Mmu->pageTableSize));
+
+    /* Roll back. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->mutex));
+
+    /* Mark the gckVGMMU object as unknown. */
+    Mmu->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the gckVGMMU object. */
+    gcmkVERIFY_OK(gckOS_Free(Mmu->os, Mmu));
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVGMMU_AllocatePages
+**
+**  Allocate pages inside the page table.
+**
+**  INPUT:
+**
+**      gckVGMMU Mmu
+**          Pointer to an gckVGMMU object.
+**
+**      gctSIZE_T PageCount
+**          Number of pages to allocate.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * PageTable
+**          Pointer to a variable that receives the base address of the page
+**          table.
+**
+**      gctUINT32 * Address
+**          Pointer to a variable that receives the hardware specific address.
+*/
+gceSTATUS gckVGMMU_AllocatePages(
+    IN gckVGMMU Mmu,
+    IN gctSIZE_T PageCount,
+    OUT gctPOINTER * PageTable,
+    OUT gctUINT32 * Address
+    )
+{
+    gceSTATUS status;
+    gctUINT32 tail, index, i;
+    gctUINT32 * table;
+    gctBOOL allocated = gcvFALSE;
+
+    gcmkHEADER_ARG("Mmu=0x%x PageCount=0x%x PageTable=0x%x Address=0x%x",
+        Mmu, PageCount, PageTable, Address);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+    gcmkVERIFY_ARGUMENT(PageCount > 0);
+    gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_INFO, gcvZONE_MMU,
+        "%s(%d): %u pages.\n",
+        __FUNCTION__, __LINE__,
+        PageCount
+        );
+
+    if (PageCount > Mmu->entryCount)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_MMU,
+            "%s(%d): page table too small for %u pages.\n",
+            __FUNCTION__, __LINE__,
+            PageCount
+            );
+
+        /* Not enough pages avaiable. */
+        return gcvSTATUS_OUT_OF_RESOURCES;
+    }
+
+    /* Grab the mutex. */
+    status = gckOS_AcquireMutex(Mmu->os, Mmu->mutex, gcvINFINITE);
+
+    if (status < 0)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_MMU,
+            "%s(%d): could not acquire mutex.\n"
+            ,__FUNCTION__, __LINE__
+            );
+
+        /* Error. */
+        return status;
+    }
+
+    /* Compute the tail for this allocation. */
+    tail = Mmu->entryCount - PageCount;
+
+    /* Walk all entries until we find enough slots. */
+    for (index = Mmu->entry; index <= tail;)
+    {
+        /* Access page table. */
+        table = (gctUINT32 *) Mmu->pageTableLogical + index;
+
+        /* See if all slots are available. */
+        for (i = 0; i < PageCount; i++, table++)
+        {
+            if (*table != ~0)
+            {
+                /* Start from next slot. */
+                index += i + 1;
+                break;
+            }
+        }
+
+        if (i == PageCount)
+        {
+            /* Bail out if we have enough page entries. */
+            allocated = gcvTRUE;
+            break;
+        }
+    }
+
+    if (!allocated)
+    {
+        /* Flush the MMU. */
+        status = gckVGHARDWARE_FlushMMU(Mmu->hardware);
+
+        if (status >= 0)
+        {
+            /* Walk all entries until we find enough slots. */
+            for (index = 0; index <= tail;)
+            {
+                /* Access page table. */
+                table = (gctUINT32 *) Mmu->pageTableLogical + index;
+
+                /* See if all slots are available. */
+                for (i = 0; i < PageCount; i++, table++)
+                {
+                    if (*table != ~0)
+                    {
+                        /* Start from next slot. */
+                        index += i + 1;
+                        break;
+                    }
+                }
+
+                if (i == PageCount)
+                {
+                    /* Bail out if we have enough page entries. */
+                    allocated = gcvTRUE;
+                    break;
+                }
+            }
+        }
+    }
+
+    if (!allocated && (status >= 0))
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_MMU,
+            "%s(%d): not enough free pages for %u pages.\n",
+            __FUNCTION__, __LINE__,
+            PageCount
+            );
+
+        /* Not enough empty slots available. */
+        status = gcvSTATUS_OUT_OF_RESOURCES;
+    }
+
+    if (status >= 0)
+    {
+        /* Build virtual address. */
+        status = gckVGHARDWARE_BuildVirtualAddress(Mmu->hardware,
+                                                 index,
+                                                 0,
+                                                 Address);
+
+        if (status >= 0)
+        {
+            /* Update current entry into page table. */
+            Mmu->entry = index + PageCount;
+
+            /* Return pointer to page table. */
+            *PageTable = (gctUINT32 *)  Mmu->pageTableLogical + index;
+
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO, gcvZONE_MMU,
+                "%s(%d): allocated %u pages at index %u (0x%08X) @ %p.\n",
+                __FUNCTION__, __LINE__,
+                PageCount,
+                index,
+                *Address,
+                *PageTable
+                );
+            }
+    }
+
+    /* Release the mutex. */
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->mutex));
+    gcmkFOOTER();
+
+    /* Return status. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVGMMU_FreePages
+**
+**  Free pages inside the page table.
+**
+**  INPUT:
+**
+**      gckVGMMU Mmu
+**          Pointer to an gckVGMMU object.
+**
+**      gctPOINTER PageTable
+**          Base address of the page table to free.
+**
+**      gctSIZE_T PageCount
+**          Number of pages to free.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS gckVGMMU_FreePages(
+    IN gckVGMMU Mmu,
+    IN gctPOINTER PageTable,
+    IN gctSIZE_T PageCount
+    )
+{
+    gctUINT32 * table;
+
+    gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=0x%x",
+        Mmu, PageTable, PageCount);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+    gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+    gcmkVERIFY_ARGUMENT(PageCount > 0);
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_INFO, gcvZONE_MMU,
+        "%s(%d): freeing %u pages at index %u @ %p.\n",
+        __FUNCTION__, __LINE__,
+        PageCount,
+        ((gctUINT32 *) PageTable - (gctUINT32 *) Mmu->pageTableLogical),
+        PageTable
+        );
+
+    /* Convert pointer. */
+    table = (gctUINT32 *) PageTable;
+
+    /* Mark the page table entries as available. */
+    while (PageCount-- > 0)
+    {
+        *table++ = (gctUINT32)~0;
+    }
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVGMMU_SetPage(
+    IN gckVGMMU Mmu,
+    IN gctUINT32 PageAddress,
+    IN gctUINT32 *PageEntry
+    )
+{
+    gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+    gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
+    gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
+
+    *PageEntry = PageAddress;
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+#endif /* gcdENABLE_VG */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h
new file mode 100644 (file)
index 0000000..7366491
--- /dev/null
@@ -0,0 +1,31 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_precomp_h_
+#define __gc_hal_kernel_precomp_h_
+
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel.h"
+
+#endif /* __gc_hal_kernel_precomp_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
new file mode 100644 (file)
index 0000000..828295a
--- /dev/null
@@ -0,0 +1,786 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#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(32), &kernel->mmu
+            ));
+
+        /* Return pointer to the gckKERNEL object. */
+        *Kernel = 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));
+    }
+
+    /* 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
+gckKERNEL_AllocateLinearMemory(
+    IN gckKERNEL Kernel,
+    IN OUT gcePOOL * Pool,
+    IN gctSIZE_T Bytes,
+    IN gctSIZE_T 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(videoMemory,
+                                                  Bytes,
+                                                  Alignment,
+                                                  Type,
+                                                  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;
+    gcuVIDMEM_NODE_PTR node;
+    gctUINT32 processID;
+
+    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:
+        /* Allocate non-paged memory. */
+        gcmkERR_BREAK(gckOS_AllocateContiguous(
+            Kernel->os,
+            gcvTRUE,
+            &kernelInterface->u.AllocateNonPagedMemory.bytes,
+            &kernelInterface->u.AllocateNonPagedMemory.physical,
+            &kernelInterface->u.AllocateNonPagedMemory.logical
+            ));
+        break;
+
+    case gcvHAL_FREE_NON_PAGED_MEMORY:
+        /* Free non-paged memory. */
+        gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
+            Kernel->os,
+            kernelInterface->u.AllocateNonPagedMemory.bytes,
+            kernelInterface->u.AllocateNonPagedMemory.physical,
+            kernelInterface->u.AllocateNonPagedMemory.logical
+            ));
+        break;
+
+    case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
+        /* Allocate contiguous memory. */
+        gcmkERR_BREAK(gckOS_AllocateContiguous(
+            Kernel->os,
+            gcvTRUE,
+            &kernelInterface->u.AllocateNonPagedMemory.bytes,
+            &kernelInterface->u.AllocateNonPagedMemory.physical,
+            &kernelInterface->u.AllocateNonPagedMemory.logical
+            ));
+        break;
+
+    case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+        /* Free contiguous memory. */
+        gcmkERR_BREAK(gckOS_FreeContiguous(
+            Kernel->os,
+            kernelInterface->u.AllocateNonPagedMemory.physical,
+            kernelInterface->u.AllocateNonPagedMemory.logical,
+            kernelInterface->u.AllocateNonPagedMemory.bytes
+            ));
+        break;
+
+    case gcvHAL_ALLOCATE_VIDEO_MEMORY:
+        {
+            gctSIZE_T bytes;
+            gctUINT32 bitsPerPixel;
+            gctUINT32 bits;
+
+            /* Align width and height to tiles. */
+            gcmkERR_BREAK(gckVGHARDWARE_AlignToTile(
+                Kernel->vg->hardware,
+                kernelInterface->u.AllocateVideoMemory.type,
+                &kernelInterface->u.AllocateVideoMemory.width,
+                &kernelInterface->u.AllocateVideoMemory.height
+                ));
+
+            /* Convert format into bytes per pixel and bytes per tile. */
+            gcmkERR_BREAK(gckVGHARDWARE_ConvertFormat(
+                Kernel->vg->hardware,
+                kernelInterface->u.AllocateVideoMemory.format,
+                &bitsPerPixel,
+                gcvNULL
+                ));
+
+            /* Compute number of bits for the allocation. */
+            bits
+                = kernelInterface->u.AllocateVideoMemory.width
+                * kernelInterface->u.AllocateVideoMemory.height
+                * kernelInterface->u.AllocateVideoMemory.depth
+                * bitsPerPixel;
+
+            /* Compute number of bytes for the allocation. */
+            bytes = gcmALIGN(bits, 8) / 8;
+
+            /* Allocate memory. */
+            gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
+                Kernel,
+                &kernelInterface->u.AllocateVideoMemory.pool,
+                bytes,
+                64,
+                kernelInterface->u.AllocateVideoMemory.type,
+                &kernelInterface->u.AllocateVideoMemory.node
+                ));
+        }
+        break;
+
+    case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
+        /* Allocate memory. */
+        gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
+            Kernel,
+            &kernelInterface->u.AllocateLinearVideoMemory.pool,
+            kernelInterface->u.AllocateLinearVideoMemory.bytes,
+            kernelInterface->u.AllocateLinearVideoMemory.alignment,
+            kernelInterface->u.AllocateLinearVideoMemory.type,
+            &kernelInterface->u.AllocateLinearVideoMemory.node
+            ));
+        break;
+
+    case gcvHAL_FREE_VIDEO_MEMORY:
+        /* Free video memory. */
+        gcmkERR_BREAK(gckVIDMEM_Free(
+            Interface->u.FreeVideoMemory.node
+            ));
+        break;
+
+    case gcvHAL_MAP_MEMORY:
+        /* Map memory. */
+        gcmkERR_BREAK(gckKERNEL_MapMemory(
+            Kernel,
+            kernelInterface->u.MapMemory.physical,
+            kernelInterface->u.MapMemory.bytes,
+            &kernelInterface->u.MapMemory.logical
+            ));
+        break;
+
+    case gcvHAL_UNMAP_MEMORY:
+        /* Unmap memory. */
+        gcmkERR_BREAK(gckKERNEL_UnmapMemory(
+            Kernel,
+            kernelInterface->u.MapMemory.physical,
+            kernelInterface->u.MapMemory.bytes,
+            kernelInterface->u.MapMemory.logical
+            ));
+        break;
+
+    case gcvHAL_MAP_USER_MEMORY:
+        /* Map user memory to DMA. */
+        gcmkERR_BREAK(gckOS_MapUserMemory(
+            Kernel->os,
+            kernelInterface->u.MapUserMemory.memory,
+            kernelInterface->u.MapUserMemory.size,
+            &kernelInterface->u.MapUserMemory.info,
+            &kernelInterface->u.MapUserMemory.address
+            ));
+        break;
+
+    case gcvHAL_UNMAP_USER_MEMORY:
+        /* Unmap user memory. */
+        gcmkERR_BREAK(gckOS_UnmapUserMemory(
+            Kernel->os,
+            kernelInterface->u.UnmapUserMemory.memory,
+            kernelInterface->u.UnmapUserMemory.size,
+            kernelInterface->u.UnmapUserMemory.info,
+            kernelInterface->u.UnmapUserMemory.address
+            ));
+        break;
+    case gcvHAL_LOCK_VIDEO_MEMORY:
+        /* Lock video memory. */
+        gcmkERR_BREAK(
+            gckVIDMEM_Lock(Kernel,
+                           Interface->u.LockVideoMemory.node,
+                                                  gcvFALSE,
+                           &Interface->u.LockVideoMemory.address));
+
+        node = Interface->u.LockVideoMemory.node;
+        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+        {
+            /* Map video memory address into user space. */
+#ifdef __QNXNTO__
+        if (node->VidMem.logical == gcvNULL)
+        {
+            gcmkONERROR(
+                gckKERNEL_MapVideoMemory(Kernel,
+                                         FromUser,
+                                         Interface->u.LockVideoMemory.address,
+                                         processID,
+                                         node->VidMem.bytes,
+                                         &node->VidMem.logical));
+        }
+
+        Interface->u.LockVideoMemory.memory = node->VidMem.logical;
+#else
+            gcmkERR_BREAK(
+                gckKERNEL_MapVideoMemoryEx(Kernel,
+                                         gcvCORE_VG,
+                                         FromUser,
+                                         Interface->u.LockVideoMemory.address,
+                                         &Interface->u.LockVideoMemory.memory));
+#endif
+        }
+        else
+        {
+            Interface->u.LockVideoMemory.memory = node->Virtual.logical;
+
+            /* Success. */
+            status = gcvSTATUS_OK;
+        }
+
+#if gcdSECURE_USER
+        /* Return logical address as physical address. */
+        Interface->u.LockVideoMemory.address =
+            gcmPTR2INT(Interface->u.LockVideoMemory.memory);
+#endif
+        break;
+
+    case gcvHAL_UNLOCK_VIDEO_MEMORY:
+        /* Unlock video memory. */
+        node = Interface->u.UnlockVideoMemory.node;
+
+#if gcdSECURE_USER
+        /* Save node information before it disappears. */
+        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+        {
+            logical = gcvNULL;
+            bytes   = 0;
+        }
+        else
+        {
+            logical = node->Virtual.logical;
+            bytes   = node->Virtual.bytes;
+        }
+#endif
+
+        /* Unlock video memory. */
+        gcmkERR_BREAK(
+            gckVIDMEM_Unlock(Kernel,
+                             node,
+                             Interface->u.UnlockVideoMemory.type,
+                             &Interface->u.UnlockVideoMemory.asynchroneous));
+
+#if gcdSECURE_USER
+        /* Flush the translation cache for virtual surfaces. */
+        if (logical != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
+                                                          cache,
+                                                          logical,
+                                                          bytes));
+        }
+#endif
+        break;
+    case gcvHAL_USER_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:
+            /* Destroy the signal. */
+            gcmkERR_BREAK(
+                gckOS_DestroyUserSignal(Kernel->os,
+                                        Interface->u.UserSignal.id));
+
+            gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+                Kernel,
+                processID, gcvDB_SIGNAL,
+                gcmINT2PTR(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);
+        }
+        break;
+
+    case gcvHAL_COMMIT:
+        /* Commit a command and context buffer. */
+        gcmkERR_BREAK(gckVGCOMMAND_Commit(
+            Kernel->vg->command,
+            kernelInterface->u.VGCommit.context,
+            kernelInterface->u.VGCommit.queue,
+            kernelInterface->u.VGCommit.entryCount,
+            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;
+    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 */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h
new file mode 100644 (file)
index 0000000..bf0f305
--- /dev/null
@@ -0,0 +1,90 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+
+
+#ifndef __gc_hal_kernel_vg_h_
+#define __gc_hal_kernel_vg_h_
+
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel_hardware.h"
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+
+/* gckKERNEL object. */
+struct _gckVGKERNEL
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gckOS object. */
+    gckOS                       os;
+
+    /* Pointer to gckHARDWARE object. */
+    gckVGHARDWARE                   hardware;
+
+    /* Pointer to gckINTERRUPT object. */
+    gckVGINTERRUPT              interrupt;
+
+    /* Pointer to gckCOMMAND object. */
+    gckVGCOMMAND                    command;
+
+    /* Pointer to context. */
+    gctPOINTER                  context;
+
+    /* Pointer to gckMMU object. */
+    gckVGMMU                        mmu;
+
+    gckKERNEL                   kernel;
+};
+
+/* gckMMU object. */
+struct _gckVGMMU
+{
+    /* The object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gckOS object. */
+    gckOS                       os;
+
+    /* Pointer to gckHARDWARE object. */
+    gckVGHARDWARE                   hardware;
+
+    /* The page table mutex. */
+    gctPOINTER                  mutex;
+
+    /* Page table information. */
+    gctSIZE_T                   pageTableSize;
+    gctPHYS_ADDR                pageTablePhysical;
+    gctPOINTER                  pageTableLogical;
+
+    /* Allocation index. */
+    gctUINT32                   entryCount;
+    gctUINT32                   entry;
+};
+
+#endif /* __gc_hal_kernel_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
new file mode 100644 (file)
index 0000000..2c282f8
--- /dev/null
@@ -0,0 +1,1953 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE    gcvZONE_VIDMEM
+
+/******************************************************************************\
+******************************* Private Functions ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  _Split
+**
+**  Split a node on the required byte boundary.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gcuVIDMEM_NODE_PTR Node
+**          Pointer to the node to split.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to keep in the node.
+**
+**  OUTPUT:
+**
+**      Nothing.
+**
+**  RETURNS:
+**
+**      gctBOOL
+**          gcvTRUE if the node was split successfully, or gcvFALSE if there is an
+**          error.
+**
+*/
+static gctBOOL
+_Split(
+    IN gckOS Os,
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctSIZE_T Bytes
+    )
+{
+    gcuVIDMEM_NODE_PTR node;
+    gctPOINTER pointer = gcvNULL;
+
+    /* Make sure the byte boundary makes sense. */
+    if ((Bytes <= 0) || (Bytes > Node->VidMem.bytes))
+    {
+        return gcvFALSE;
+    }
+
+    /* Allocate a new gcuVIDMEM_NODE object. */
+    if (gcmIS_ERROR(gckOS_Allocate(Os,
+                                   gcmSIZEOF(gcuVIDMEM_NODE),
+                                   &pointer)))
+    {
+        /* Error. */
+        return gcvFALSE;
+    }
+
+    node = pointer;
+
+    /* Initialize gcuVIDMEM_NODE structure. */
+    node->VidMem.offset    = Node->VidMem.offset + Bytes;
+    node->VidMem.bytes     = Node->VidMem.bytes  - Bytes;
+    node->VidMem.alignment = 0;
+    node->VidMem.locked    = 0;
+    node->VidMem.memory    = Node->VidMem.memory;
+    node->VidMem.pool      = Node->VidMem.pool;
+    node->VidMem.physical  = Node->VidMem.physical;
+#ifdef __QNXNTO__
+#if gcdUSE_VIDMEM_PER_PID
+    gcmkASSERT(Node->VidMem.physical != 0);
+    gcmkASSERT(Node->VidMem.logical != gcvNULL);
+    node->VidMem.processID = Node->VidMem.processID;
+    node->VidMem.physical  = Node->VidMem.physical + Bytes;
+    node->VidMem.logical   = Node->VidMem.logical + Bytes;
+#else
+    node->VidMem.processID = 0;
+    node->VidMem.logical   = gcvNULL;
+#endif
+#endif
+
+    /* Insert node behind specified node. */
+    node->VidMem.next = Node->VidMem.next;
+    node->VidMem.prev = Node;
+    Node->VidMem.next = node->VidMem.next->VidMem.prev = node;
+
+    /* Insert free node behind specified node. */
+    node->VidMem.nextFree = Node->VidMem.nextFree;
+    node->VidMem.prevFree = Node;
+    Node->VidMem.nextFree = node->VidMem.nextFree->VidMem.prevFree = node;
+
+    /* Adjust size of specified node. */
+    Node->VidMem.bytes = Bytes;
+
+    /* Success. */
+    return gcvTRUE;
+}
+
+/*******************************************************************************
+**
+**  _Merge
+**
+**  Merge two adjacent nodes together.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gcuVIDMEM_NODE_PTR Node
+**          Pointer to the first of the two nodes to merge.
+**
+**  OUTPUT:
+**
+**      Nothing.
+**
+*/
+static gceSTATUS
+_Merge(
+    IN gckOS Os,
+    IN gcuVIDMEM_NODE_PTR Node
+    )
+{
+    gcuVIDMEM_NODE_PTR node;
+    gceSTATUS status;
+
+    /* Save pointer to next node. */
+    node = Node->VidMem.next;
+#if gcdUSE_VIDMEM_PER_PID
+    /* Check if the nodes are adjacent physically. */
+    if ( ((Node->VidMem.physical + Node->VidMem.bytes) != node->VidMem.physical) ||
+          ((Node->VidMem.logical + Node->VidMem.bytes) != node->VidMem.logical) )
+    {
+        /* Can't merge. */
+        return gcvSTATUS_OK;
+    }
+#else
+
+    /* This is a good time to make sure the heap is not corrupted. */
+    if (Node->VidMem.offset + Node->VidMem.bytes != node->VidMem.offset)
+    {
+        /* Corrupted heap. */
+        gcmkASSERT(
+            Node->VidMem.offset + Node->VidMem.bytes == node->VidMem.offset);
+        return gcvSTATUS_HEAP_CORRUPTED;
+    }
+#endif
+
+    /* Adjust byte count. */
+    Node->VidMem.bytes += node->VidMem.bytes;
+
+    /* Unlink next node from linked list. */
+    Node->VidMem.next     = node->VidMem.next;
+    Node->VidMem.nextFree = node->VidMem.nextFree;
+
+    Node->VidMem.next->VidMem.prev         =
+    Node->VidMem.nextFree->VidMem.prevFree = Node;
+
+    /* Free next node. */
+    status = gcmkOS_SAFE_FREE(Os, node);
+    return status;
+}
+
+/******************************************************************************\
+******************************* gckVIDMEM API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckVIDMEM_ConstructVirtual
+**
+**  Construct a new gcuVIDMEM_NODE union for virtual memory.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctSIZE_T Bytes
+**          Number of byte to allocate.
+**
+**  OUTPUT:
+**
+**      gcuVIDMEM_NODE_PTR * Node
+**          Pointer to a variable that receives the gcuVIDMEM_NODE union pointer.
+*/
+gceSTATUS
+gckVIDMEM_ConstructVirtual(
+    IN gckKERNEL Kernel,
+    IN gctBOOL Contiguous,
+    IN gctSIZE_T Bytes,
+    OUT gcuVIDMEM_NODE_PTR * Node
+    )
+{
+    gckOS os;
+    gceSTATUS status;
+    gcuVIDMEM_NODE_PTR node = gcvNULL;
+    gctPOINTER pointer = gcvNULL;
+    gctINT i;
+
+    gcmkHEADER_ARG("Kernel=0x%x Contiguous=%d Bytes=%lu", Kernel, Contiguous, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+    /* Extract the gckOS object pointer. */
+    os = Kernel->os;
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+    /* Allocate an gcuVIDMEM_NODE union. */
+    gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
+
+    node = pointer;
+
+    /* Initialize gcuVIDMEM_NODE union for virtual memory. */
+    node->Virtual.kernel        = Kernel;
+    node->Virtual.contiguous    = Contiguous;
+    node->Virtual.logical       = gcvNULL;
+
+    for (i = 0; i < gcdCORE_COUNT; i++)
+    {
+        node->Virtual.lockeds[i]        = 0;
+        node->Virtual.pageTables[i]     = gcvNULL;
+        node->Virtual.lockKernels[i]    = gcvNULL;
+    }
+
+    node->Virtual.mutex         = gcvNULL;
+
+    gcmkONERROR(gckOS_GetProcessID(&node->Virtual.processID));
+
+#ifdef __QNXNTO__
+    node->Virtual.next          = gcvNULL;
+    node->Virtual.freePending   = gcvFALSE;
+    for (i = 0; i < gcdCORE_COUNT; i++)
+    {
+        node->Virtual.unlockPendings[i] = gcvFALSE;
+    }
+#endif
+
+    node->Virtual.freed         = gcvFALSE;
+    /* Create the mutex. */
+    gcmkONERROR(
+        gckOS_CreateMutex(os, &node->Virtual.mutex));
+
+    /* Allocate the virtual memory. */
+    gcmkONERROR(
+        gckOS_AllocatePagedMemoryEx(os,
+                                    node->Virtual.contiguous,
+                                    node->Virtual.bytes = Bytes,
+                                    &node->Virtual.physical));
+
+#ifdef __QNXNTO__
+    /* Register. */
+    gckMMU_InsertNode(Kernel->mmu, node);
+#endif
+
+    /* Return pointer to the gcuVIDMEM_NODE union. */
+    *Node = node;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                   "Created virtual node 0x%x for %u bytes @ 0x%x",
+                   node, Bytes, node->Virtual.physical);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Node=0x%x", *Node);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (node != gcvNULL)
+    {
+        if (node->Virtual.mutex != gcvNULL)
+        {
+            /* Destroy the mutex. */
+            gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->Virtual.mutex));
+        }
+
+        /* Free the structure. */
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, node));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVIDMEM_DestroyVirtual
+**
+**  Destroy an gcuVIDMEM_NODE union for virtual memory.
+**
+**  INPUT:
+**
+**      gcuVIDMEM_NODE_PTR Node
+**          Pointer to a gcuVIDMEM_NODE union.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckVIDMEM_DestroyVirtual(
+    IN gcuVIDMEM_NODE_PTR Node
+    )
+{
+    gckOS os;
+    gctINT i;
+
+    gcmkHEADER_ARG("Node=0x%x", Node);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
+
+    /* Extact the gckOS object pointer. */
+    os = Node->Virtual.kernel->os;
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+#ifdef __QNXNTO__
+    /* Unregister. */
+    gcmkVERIFY_OK(
+            gckMMU_RemoveNode(Node->Virtual.kernel->mmu, Node));
+#endif
+
+    /* Delete the mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(os, Node->Virtual.mutex));
+
+    for (i = 0; i < gcdCORE_COUNT; i++)
+    {
+        if (Node->Virtual.pageTables[i] != gcvNULL)
+        {
+#if gcdENABLE_VG
+            if (i == gcvCORE_VG)
+            {
+                /* Free the pages. */
+                gcmkVERIFY_OK(gckVGMMU_FreePages(Node->Virtual.lockKernels[i]->vg->mmu,
+                                               Node->Virtual.pageTables[i],
+                                               Node->Virtual.pageCount));
+            }
+            else
+#endif
+            {
+                /* Free the pages. */
+                gcmkVERIFY_OK(gckMMU_FreePages(Node->Virtual.lockKernels[i]->mmu,
+                                               Node->Virtual.pageTables[i],
+                                               Node->Virtual.pageCount));
+            }
+        }
+    }
+
+    /* Delete the gcuVIDMEM_NODE union. */
+    gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, Node));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVIDMEM_Construct
+**
+**  Construct a new gckVIDMEM object.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctUINT32 BaseAddress
+**          Base address for the video memory heap.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes in the video memory heap.
+**
+**      gctSIZE_T Threshold
+**          Minimum number of bytes beyond am allocation before the node is
+**          split.  Can be used as a minimum alignment requirement.
+**
+**      gctSIZE_T BankSize
+**          Number of bytes per physical memory bank.  Used by bank
+**          optimization.
+**
+**  OUTPUT:
+**
+**      gckVIDMEM * Memory
+**          Pointer to a variable that will hold the pointer to the gckVIDMEM
+**          object.
+*/
+gceSTATUS
+gckVIDMEM_Construct(
+    IN gckOS Os,
+    IN gctUINT32 BaseAddress,
+    IN gctSIZE_T Bytes,
+    IN gctSIZE_T Threshold,
+    IN gctSIZE_T BankSize,
+    OUT gckVIDMEM * Memory
+    )
+{
+    gckVIDMEM memory = gcvNULL;
+    gceSTATUS status;
+    gcuVIDMEM_NODE_PTR node;
+    gctINT i, banks = 0;
+    gctPOINTER pointer = gcvNULL;
+
+    gcmkHEADER_ARG("Os=0x%x BaseAddress=%08x Bytes=%lu Threshold=%lu "
+                   "BankSize=%lu",
+                   Os, BaseAddress, Bytes, Threshold, BankSize);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+    /* Allocate the gckVIDMEM object. */
+    gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct _gckVIDMEM), &pointer));
+
+    memory = pointer;
+
+    /* Initialize the gckVIDMEM object. */
+    memory->object.type = gcvOBJ_VIDMEM;
+    memory->os          = Os;
+
+    /* Set video memory heap information. */
+    memory->baseAddress = BaseAddress;
+    memory->bytes       = Bytes;
+    memory->freeBytes   = Bytes;
+    memory->threshold   = Threshold;
+    memory->mutex       = gcvNULL;
+#if gcdUSE_VIDMEM_PER_PID
+    gcmkONERROR(gckOS_GetProcessID(&memory->pid));
+#endif
+
+    BaseAddress = 0;
+
+    /* Walk all possible banks. */
+    for (i = 0; i < gcmCOUNTOF(memory->sentinel); ++i)
+    {
+        gctSIZE_T bytes;
+
+        if (BankSize == 0)
+        {
+            /* Use all bytes for the first bank. */
+            bytes = Bytes;
+        }
+        else
+        {
+            /* Compute number of bytes for this bank. */
+            bytes = gcmALIGN(BaseAddress + 1, BankSize) - BaseAddress;
+
+            if (bytes > Bytes)
+            {
+                /* Make sure we don't exceed the total number of bytes. */
+                bytes = Bytes;
+            }
+        }
+
+        if (bytes == 0)
+        {
+            /* Mark heap is not used. */
+            memory->sentinel[i].VidMem.next     =
+            memory->sentinel[i].VidMem.prev     =
+            memory->sentinel[i].VidMem.nextFree =
+            memory->sentinel[i].VidMem.prevFree = gcvNULL;
+            continue;
+        }
+
+        /* Allocate one gcuVIDMEM_NODE union. */
+        gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
+
+        node = pointer;
+
+        /* Initialize gcuVIDMEM_NODE union. */
+        node->VidMem.memory    = memory;
+
+        node->VidMem.next      =
+        node->VidMem.prev      =
+        node->VidMem.nextFree  =
+        node->VidMem.prevFree  = &memory->sentinel[i];
+
+        node->VidMem.offset    = BaseAddress;
+        node->VidMem.bytes     = bytes;
+        node->VidMem.alignment = 0;
+        node->VidMem.physical  = 0;
+        node->VidMem.pool      = gcvPOOL_UNKNOWN;
+
+        node->VidMem.locked    = 0;
+
+#ifdef __QNXNTO__
+#if gcdUSE_VIDMEM_PER_PID
+        node->VidMem.processID = memory->pid;
+        node->VidMem.physical  = memory->baseAddress + BaseAddress;
+        gcmkONERROR(gckOS_GetLogicalAddressProcess(Os,
+                    node->VidMem.processID,
+                    node->VidMem.physical,
+                    &node->VidMem.logical));
+#else
+        node->VidMem.processID = 0;
+        node->VidMem.logical   = gcvNULL;
+#endif
+#endif
+
+        /* Initialize the linked list of nodes. */
+        memory->sentinel[i].VidMem.next     =
+        memory->sentinel[i].VidMem.prev     =
+        memory->sentinel[i].VidMem.nextFree =
+        memory->sentinel[i].VidMem.prevFree = node;
+
+        /* Mark sentinel. */
+        memory->sentinel[i].VidMem.bytes = 0;
+
+        /* Adjust address for next bank. */
+        BaseAddress += bytes;
+        Bytes       -= bytes;
+        banks       ++;
+    }
+
+    /* Assign all the bank mappings. */
+    memory->mapping[gcvSURF_RENDER_TARGET]      = banks - 1;
+    memory->mapping[gcvSURF_BITMAP]             = banks - 1;
+    if (banks > 1) --banks;
+    memory->mapping[gcvSURF_DEPTH]              = banks - 1;
+    memory->mapping[gcvSURF_HIERARCHICAL_DEPTH] = banks - 1;
+    if (banks > 1) --banks;
+    memory->mapping[gcvSURF_TEXTURE]            = banks - 1;
+    if (banks > 1) --banks;
+    memory->mapping[gcvSURF_VERTEX]             = banks - 1;
+    if (banks > 1) --banks;
+    memory->mapping[gcvSURF_INDEX]              = banks - 1;
+    if (banks > 1) --banks;
+    memory->mapping[gcvSURF_TILE_STATUS]        = banks - 1;
+    if (banks > 1) --banks;
+    memory->mapping[gcvSURF_TYPE_UNKNOWN]       = 0;
+
+#if gcdENABLE_VG
+    memory->mapping[gcvSURF_IMAGE]   = 0;
+    memory->mapping[gcvSURF_MASK]    = 0;
+    memory->mapping[gcvSURF_SCISSOR] = 0;
+#endif
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                  "[GALCORE] INDEX:         bank %d",
+                  memory->mapping[gcvSURF_INDEX]);
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                  "[GALCORE] VERTEX:        bank %d",
+                  memory->mapping[gcvSURF_VERTEX]);
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                  "[GALCORE] TEXTURE:       bank %d",
+                  memory->mapping[gcvSURF_TEXTURE]);
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                  "[GALCORE] RENDER_TARGET: bank %d",
+                  memory->mapping[gcvSURF_RENDER_TARGET]);
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                  "[GALCORE] DEPTH:         bank %d",
+                  memory->mapping[gcvSURF_DEPTH]);
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                  "[GALCORE] TILE_STATUS:   bank %d",
+                  memory->mapping[gcvSURF_TILE_STATUS]);
+
+    /* Allocate the mutex. */
+    gcmkONERROR(gckOS_CreateMutex(Os, &memory->mutex));
+
+    /* Return pointer to the gckVIDMEM object. */
+    *Memory = memory;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (memory != gcvNULL)
+    {
+        if (memory->mutex != gcvNULL)
+        {
+            /* Delete the mutex. */
+            gcmkVERIFY_OK(gckOS_DeleteMutex(Os, memory->mutex));
+        }
+
+        for (i = 0; i < banks; ++i)
+        {
+            /* Free the heap. */
+            gcmkASSERT(memory->sentinel[i].VidMem.next != gcvNULL);
+            gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, memory->sentinel[i].VidMem.next));
+        }
+
+        /* Free the object. */
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, memory));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVIDMEM_Destroy
+**
+**  Destroy an gckVIDMEM object.
+**
+**  INPUT:
+**
+**      gckVIDMEM Memory
+**          Pointer to an gckVIDMEM object to destroy.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckVIDMEM_Destroy(
+    IN gckVIDMEM Memory
+    )
+{
+    gcuVIDMEM_NODE_PTR node, next;
+    gctINT i;
+
+    gcmkHEADER_ARG("Memory=0x%x", Memory);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+
+    /* Walk all sentinels. */
+    for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i)
+    {
+        /* Bail out of the heap is not used. */
+        if (Memory->sentinel[i].VidMem.next == gcvNULL)
+        {
+            break;
+        }
+
+        /* Walk all the nodes until we reach the sentinel. */
+        for (node = Memory->sentinel[i].VidMem.next;
+             node->VidMem.bytes != 0;
+             node = next)
+        {
+            /* Save pointer to the next node. */
+            next = node->VidMem.next;
+
+            /* Free the node. */
+            gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Memory->os, node));
+        }
+    }
+
+    /* Free the mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Memory->os, Memory->mutex));
+
+    /* Mark the object as unknown. */
+    Memory->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the gckVIDMEM object. */
+    gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Memory->os, Memory));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVIDMEM_Allocate
+**
+**  Allocate rectangular memory from the gckVIDMEM object.
+**
+**  INPUT:
+**
+**      gckVIDMEM Memory
+**          Pointer to an gckVIDMEM object.
+**
+**      gctUINT Width
+**          Width of rectangle to allocate.  Make sure the width is properly
+**          aligned.
+**
+**      gctUINT Height
+**          Height of rectangle to allocate.  Make sure the height is properly
+**          aligned.
+**
+**      gctUINT Depth
+**          Depth of rectangle to allocate.  This equals to the number of
+**          rectangles to allocate contiguously (i.e., for cubic maps and volume
+**          textures).
+**
+**      gctUINT BytesPerPixel
+**          Number of bytes per pixel.
+**
+**      gctUINT32 Alignment
+**          Byte alignment for allocation.
+**
+**      gceSURF_TYPE Type
+**          Type of surface to allocate (use by bank optimization).
+**
+**  OUTPUT:
+**
+**      gcuVIDMEM_NODE_PTR * Node
+**          Pointer to a variable that will hold the allocated memory node.
+*/
+gceSTATUS
+gckVIDMEM_Allocate(
+    IN gckVIDMEM Memory,
+    IN gctUINT Width,
+    IN gctUINT Height,
+    IN gctUINT Depth,
+    IN gctUINT BytesPerPixel,
+    IN gctUINT32 Alignment,
+    IN gceSURF_TYPE Type,
+    OUT gcuVIDMEM_NODE_PTR * Node
+    )
+{
+    gctSIZE_T bytes;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Memory=0x%x Width=%u Height=%u Depth=%u BytesPerPixel=%u "
+                   "Alignment=%u Type=%d",
+                   Memory, Width, Height, Depth, BytesPerPixel, Alignment,
+                   Type);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+    gcmkVERIFY_ARGUMENT(Width > 0);
+    gcmkVERIFY_ARGUMENT(Height > 0);
+    gcmkVERIFY_ARGUMENT(Depth > 0);
+    gcmkVERIFY_ARGUMENT(BytesPerPixel > 0);
+    gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+    /* Compute linear size. */
+    bytes = Width * Height * Depth * BytesPerPixel;
+
+    /* Allocate through linear function. */
+    gcmkONERROR(
+        gckVIDMEM_AllocateLinear(Memory, bytes, Alignment, Type, Node));
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Node=0x%x", *Node);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+static gcuVIDMEM_NODE_PTR
+_FindNode(
+    IN gckVIDMEM Memory,
+    IN gctINT Bank,
+    IN gctSIZE_T Bytes,
+    IN gceSURF_TYPE Type,
+    IN OUT gctUINT32_PTR Alignment
+    )
+{
+    gcuVIDMEM_NODE_PTR node;
+    gctUINT32 alignment;
+
+#if gcdENABLE_BANK_ALIGNMENT
+    gctUINT32 bankAlignment;
+    gceSTATUS status;
+
+    /* Walk all free nodes until we have one that is big enough or we have
+    ** reached the sentinel. */
+    for (node = Memory->sentinel[Bank].VidMem.nextFree;
+         node->VidMem.bytes != 0;
+         node = node->VidMem.nextFree)
+    {
+        gcmkONERROR(gckOS_GetSurfaceBankAlignment(
+                       Memory->os,
+            Type,
+            node->VidMem.memory->baseAddress + node->VidMem.offset,
+            &bankAlignment));
+
+        bankAlignment = gcmALIGN(bankAlignment, *Alignment);
+
+        /* Compute number of bytes to skip for alignment. */
+        alignment = (*Alignment == 0)
+                  ? 0
+                  : (*Alignment - (node->VidMem.offset % *Alignment));
+
+        if (alignment == *Alignment)
+        {
+            /* Node is already aligned. */
+            alignment = 0;
+        }
+
+        if (node->VidMem.bytes >= Bytes + alignment + bankAlignment)
+        {
+            /* This node is big enough. */
+            *Alignment = alignment + bankAlignment;
+            return node;
+        }
+    }
+#endif
+
+    /* Walk all free nodes until we have one that is big enough or we have
+       reached the sentinel. */
+    for (node = Memory->sentinel[Bank].VidMem.nextFree;
+         node->VidMem.bytes != 0;
+         node = node->VidMem.nextFree)
+    {
+
+        gctINT modulo = gckMATH_ModuloInt(node->VidMem.offset, *Alignment);
+
+        /* Compute number of bytes to skip for alignment. */
+        alignment = (*Alignment == 0) ? 0 : (*Alignment - modulo);
+
+        if (alignment == *Alignment)
+        {
+            /* Node is already aligned. */
+            alignment = 0;
+        }
+
+        if (node->VidMem.bytes >= Bytes + alignment)
+        {
+            /* This node is big enough. */
+            *Alignment = alignment;
+            return node;
+        }
+    }
+
+#if gcdENABLE_BANK_ALIGNMENT
+OnError:
+#endif
+    /* Not enough memory. */
+    return gcvNULL;
+}
+
+/*******************************************************************************
+**
+**  gckVIDMEM_AllocateLinear
+**
+**  Allocate linear memory from the gckVIDMEM object.
+**
+**  INPUT:
+**
+**      gckVIDMEM Memory
+**          Pointer to an gckVIDMEM object.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to allocate.
+**
+**      gctUINT32 Alignment
+**          Byte alignment for allocation.
+**
+**      gceSURF_TYPE Type
+**          Type of surface to allocate (use by bank optimization).
+**
+**  OUTPUT:
+**
+**      gcuVIDMEM_NODE_PTR * Node
+**          Pointer to a variable that will hold the allocated memory node.
+*/
+gceSTATUS
+gckVIDMEM_AllocateLinear(
+    IN gckVIDMEM Memory,
+    IN gctSIZE_T Bytes,
+    IN gctUINT32 Alignment,
+    IN gceSURF_TYPE Type,
+    OUT gcuVIDMEM_NODE_PTR * Node
+    )
+{
+    gceSTATUS status;
+    gcuVIDMEM_NODE_PTR node;
+    gctUINT32 alignment;
+    gctINT bank, i;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Memory=0x%x Bytes=%lu Alignment=%u Type=%d",
+                   Memory, Bytes, Alignment, Type);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Type < gcvSURF_NUM_TYPES);
+
+    /* Acquire the mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
+
+    acquired = gcvTRUE;
+#if !gcdUSE_VIDMEM_PER_PID
+
+    if (Bytes > Memory->freeBytes)
+    {
+        /* Not enough memory. */
+        status = gcvSTATUS_OUT_OF_MEMORY;
+        goto OnError;
+    }
+#endif
+
+    /* Find the default bank for this surface type. */
+    gcmkASSERT((gctINT) Type < gcmCOUNTOF(Memory->mapping));
+    bank      = Memory->mapping[Type];
+    alignment = Alignment;
+
+#if gcdUSE_VIDMEM_PER_PID
+    if (Bytes <= Memory->freeBytes)
+    {
+#endif
+    /* Find a free node in the default bank. */
+    node = _FindNode(Memory, bank, Bytes, Type, &alignment);
+
+    /* Out of memory? */
+    if (node == gcvNULL)
+    {
+        /* Walk all lower banks. */
+        for (i = bank - 1; i >= 0; --i)
+        {
+            /* Find a free node inside the current bank. */
+            node = _FindNode(Memory, i, Bytes, Type, &alignment);
+            if (node != gcvNULL)
+            {
+                break;
+            }
+        }
+    }
+
+    if (node == gcvNULL)
+    {
+        /* Walk all upper banks. */
+        for (i = bank + 1; i < gcmCOUNTOF(Memory->sentinel); ++i)
+        {
+            if (Memory->sentinel[i].VidMem.nextFree == gcvNULL)
+            {
+                /* Abort when we reach unused banks. */
+                break;
+            }
+
+            /* Find a free node inside the current bank. */
+            node = _FindNode(Memory, i, Bytes, Type, &alignment);
+            if (node != gcvNULL)
+            {
+                break;
+            }
+        }
+    }
+#if gcdUSE_VIDMEM_PER_PID
+    }
+#endif
+
+    if (node == gcvNULL)
+    {
+        /* Out of memory. */
+#if gcdUSE_VIDMEM_PER_PID
+        /* Allocate more memory from shared pool. */
+        gctSIZE_T bytes;
+        gctPHYS_ADDR physical_temp;
+        gctUINT32 physical;
+        gctPOINTER logical;
+
+        bytes = gcmALIGN(Bytes, gcdUSE_VIDMEM_PER_PID_SIZE);
+
+        gcmkONERROR(gckOS_AllocateContiguous(Memory->os,
+                gcvTRUE,
+                &bytes,
+                &physical_temp,
+                &logical));
+
+        /* physical address is returned as 0 for user space. workaround. */
+        if (physical_temp == gcvNULL)
+        {
+        gcmkONERROR(gckOS_GetPhysicalAddress(Memory->os, logical, &physical));
+        }
+
+        /* Allocate one gcuVIDMEM_NODE union. */
+        gcmkONERROR(
+            gckOS_Allocate(Memory->os,
+                           gcmSIZEOF(gcuVIDMEM_NODE),
+                           (gctPOINTER *) &node));
+
+        /* Initialize gcuVIDMEM_NODE union. */
+        node->VidMem.memory    = Memory;
+
+        node->VidMem.offset    = 0;
+        node->VidMem.bytes     = bytes;
+        node->VidMem.alignment = 0;
+        node->VidMem.physical  = physical;
+        node->VidMem.pool      = gcvPOOL_UNKNOWN;
+
+        node->VidMem.locked    = 0;
+
+#ifdef __QNXNTO__
+        gcmkONERROR(gckOS_GetProcessID(&node->VidMem.processID));
+        node->VidMem.logical   = logical;
+        gcmkASSERT(logical != gcvNULL);
+#endif
+
+        /* Insert node behind sentinel node. */
+        node->VidMem.next = Memory->sentinel[bank].VidMem.next;
+        node->VidMem.prev = &Memory->sentinel[bank];
+        Memory->sentinel[bank].VidMem.next = node->VidMem.next->VidMem.prev = node;
+
+        /* Insert free node behind sentinel node. */
+        node->VidMem.nextFree = Memory->sentinel[bank].VidMem.nextFree;
+        node->VidMem.prevFree = &Memory->sentinel[bank];
+        Memory->sentinel[bank].VidMem.nextFree = node->VidMem.nextFree->VidMem.prevFree = node;
+
+        Memory->freeBytes += bytes;
+#else
+        status = gcvSTATUS_OUT_OF_MEMORY;
+        goto OnError;
+#endif
+    }
+
+    /* Do we have an alignment? */
+    if (alignment > 0)
+    {
+        /* Split the node so it is aligned. */
+        if (_Split(Memory->os, node, alignment))
+        {
+            /* Successful split, move to aligned node. */
+            node = node->VidMem.next;
+
+            /* Remove alignment. */
+            alignment = 0;
+        }
+    }
+
+    /* Do we have enough memory after the allocation to split it? */
+    if (node->VidMem.bytes - Bytes > Memory->threshold)
+    {
+        /* Adjust the node size. */
+        _Split(Memory->os, node, Bytes);
+    }
+
+    /* Remove the node from the free list. */
+    node->VidMem.prevFree->VidMem.nextFree = node->VidMem.nextFree;
+    node->VidMem.nextFree->VidMem.prevFree = node->VidMem.prevFree;
+    node->VidMem.nextFree                  =
+    node->VidMem.prevFree                  = gcvNULL;
+
+    /* Fill in the information. */
+    node->VidMem.alignment = alignment;
+    node->VidMem.memory    = Memory;
+#ifdef __QNXNTO__
+#if !gcdUSE_VIDMEM_PER_PID
+    node->VidMem.logical   = gcvNULL;
+    gcmkONERROR(gckOS_GetProcessID(&node->VidMem.processID));
+#else
+    gcmkASSERT(node->VidMem.logical != gcvNULL);
+#endif
+#endif
+
+    /* Adjust the number of free bytes. */
+    Memory->freeBytes -= node->VidMem.bytes;
+
+    node->VidMem.freePending = gcvFALSE;
+
+    /* Release the mutex. */
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+
+    /* Return the pointer to the node. */
+    *Node = node;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                   "Allocated %u bytes @ 0x%x [0x%08X]",
+                   node->VidMem.bytes, node, node->VidMem.offset);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Node=0x%x", *Node);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+     /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVIDMEM_Free
+**
+**  Free an allocated video memory node.
+**
+**  INPUT:
+**
+**      gcuVIDMEM_NODE_PTR Node
+**          Pointer to a gcuVIDMEM_NODE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckVIDMEM_Free(
+    IN gcuVIDMEM_NODE_PTR Node
+    )
+{
+    gceSTATUS status;
+    gckKERNEL kernel = gcvNULL;
+    gckVIDMEM memory = gcvNULL;
+    gcuVIDMEM_NODE_PTR node;
+    gctBOOL mutexAcquired = gcvFALSE;
+    gckOS os = gcvFALSE;
+    gctBOOL acquired = gcvFALSE;
+    gctINT32 i, totalLocked;
+
+    gcmkHEADER_ARG("Node=0x%x", Node);
+
+    /* Verify the arguments. */
+    if ((Node == gcvNULL)
+    ||  (Node->VidMem.memory == gcvNULL)
+    )
+    {
+        /* Invalid object. */
+        gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+    }
+
+    /**************************** Video Memory ********************************/
+
+    if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+    {
+        if (Node->VidMem.locked > 0)
+        {
+            /* Client still has a lock, defer free op 'till when lock reaches 0. */
+            Node->VidMem.freePending = gcvTRUE;
+
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                           "Node 0x%x is locked (%d)... deferring free.",
+                           Node, Node->VidMem.locked);
+
+            gcmkFOOTER_NO();
+            return gcvSTATUS_OK;
+        }
+
+        /* Extract pointer to gckVIDMEM object owning the node. */
+        memory = Node->VidMem.memory;
+
+        /* Acquire the mutex. */
+        gcmkONERROR(
+            gckOS_AcquireMutex(memory->os, memory->mutex, gcvINFINITE));
+
+        mutexAcquired = gcvTRUE;
+
+#ifdef __QNXNTO__
+#if !gcdUSE_VIDMEM_PER_PID
+        /* Reset. */
+        Node->VidMem.processID = 0;
+        Node->VidMem.logical = gcvNULL;
+#endif
+
+        /* Don't try to re-free an already freed node. */
+        if ((Node->VidMem.nextFree == gcvNULL)
+        &&  (Node->VidMem.prevFree == gcvNULL)
+        )
+#endif
+        {
+            /* Update the number of free bytes. */
+            memory->freeBytes += Node->VidMem.bytes;
+
+            /* Find the next free node. */
+            for (node = Node->VidMem.next;
+                 node != gcvNULL && node->VidMem.nextFree == gcvNULL;
+                 node = node->VidMem.next) ;
+
+            /* Insert this node in the free list. */
+            Node->VidMem.nextFree = node;
+            Node->VidMem.prevFree = node->VidMem.prevFree;
+
+            Node->VidMem.prevFree->VidMem.nextFree =
+            node->VidMem.prevFree                  = Node;
+
+            /* Is the next node a free node and not the sentinel? */
+            if ((Node->VidMem.next == Node->VidMem.nextFree)
+            &&  (Node->VidMem.next->VidMem.bytes != 0)
+            )
+            {
+                /* Merge this node with the next node. */
+                gcmkONERROR(_Merge(memory->os, node = Node));
+                gcmkASSERT(node->VidMem.nextFree != node);
+                gcmkASSERT(node->VidMem.prevFree != node);
+            }
+
+            /* Is the previous node a free node and not the sentinel? */
+            if ((Node->VidMem.prev == Node->VidMem.prevFree)
+            &&  (Node->VidMem.prev->VidMem.bytes != 0)
+            )
+            {
+                /* Merge this node with the previous node. */
+                gcmkONERROR(_Merge(memory->os, node = Node->VidMem.prev));
+                gcmkASSERT(node->VidMem.nextFree != node);
+                gcmkASSERT(node->VidMem.prevFree != node);
+            }
+        }
+
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex));
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                       "Node 0x%x is freed.",
+                       Node);
+
+        /* Success. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+    /*************************** Virtual Memory *******************************/
+
+    /* Get gckKERNEL object. */
+    kernel = Node->Virtual.kernel;
+
+    /* Verify the gckKERNEL object pointer. */
+    gcmkVERIFY_OBJECT(kernel, gcvOBJ_KERNEL);
+
+    /* Get the gckOS object pointer. */
+    os = kernel->os;
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+    /* Grab the mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
+
+    acquired = gcvTRUE;
+
+    for (i = 0, totalLocked = 0; i < gcdCORE_COUNT; i++)
+    {
+        totalLocked += Node->Virtual.lockeds[i];
+    }
+
+    if (totalLocked > 0)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_VIDMEM,
+                       "gckVIDMEM_Free: Virtual node 0x%x is locked (%d)",
+                       Node, totalLocked);
+
+        /* Set Flag */
+        Node->Virtual.freed = gcvTRUE;
+
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+    }
+    else
+    {
+        /* Free the virtual memory. */
+        gcmkVERIFY_OK(gckOS_FreePagedMemory(kernel->os,
+                                            Node->Virtual.physical,
+                                            Node->Virtual.bytes));
+
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+
+        /* Destroy the gcuVIDMEM_NODE union. */
+        gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node));
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (mutexAcquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(
+            memory->os, memory->mutex
+            ));
+    }
+
+    if (acquired)
+    {
+       gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+
+#ifdef __QNXNTO__
+/*******************************************************************************
+**
+**  gcoVIDMEM_FreeHandleMemory
+**
+**  Free all allocated video memory nodes for a handle.
+**
+**  INPUT:
+**
+**      gcoVIDMEM Memory
+**          Pointer to an gcoVIDMEM object..
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckVIDMEM_FreeHandleMemory(
+    IN gckKERNEL Kernel,
+    IN gckVIDMEM Memory,
+    IN gctUINT32 Pid
+    )
+{
+    gceSTATUS status;
+    gctBOOL mutex = gcvFALSE;
+    gcuVIDMEM_NODE_PTR node;
+    gctINT i;
+    gctUINT32 nodeCount = 0, byteCount = 0;
+    gctBOOL again;
+
+    gcmkHEADER_ARG("Kernel=0x%x, Memory=0x%x Pid=0x%u", Kernel, Memory, Pid);
+
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+
+    gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
+    mutex = gcvTRUE;
+
+    /* Walk all sentinels. */
+    for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i)
+    {
+        /* Bail out of the heap if it is not used. */
+        if (Memory->sentinel[i].VidMem.next == gcvNULL)
+        {
+            break;
+        }
+
+        do
+        {
+            again = gcvFALSE;
+
+            /* Walk all the nodes until we reach the sentinel. */
+            for (node = Memory->sentinel[i].VidMem.next;
+                 node->VidMem.bytes != 0;
+                 node = node->VidMem.next)
+            {
+                /* Free the node if it was allocated by Handle. */
+                if (node->VidMem.processID == Pid)
+                {
+                    /* Unlock video memory. */
+                    while (node->VidMem.locked > 0)
+                    {
+                        gckVIDMEM_Unlock(Kernel, node, gcvSURF_TYPE_UNKNOWN, gcvNULL);
+                    }
+
+                    nodeCount++;
+                    byteCount += node->VidMem.bytes;
+
+                    /* Free video memory. */
+                    gcmkVERIFY_OK(gckVIDMEM_Free(node));
+
+                    /*
+                     * Freeing may cause a merge which will invalidate our iteration.
+                     * Don't be clever, just restart.
+                     */
+                    again = gcvTRUE;
+
+                    break;
+                }
+#if gcdUSE_VIDMEM_PER_PID
+                else
+                {
+                    gcmkASSERT(node->VidMem.processID == Pid);
+                }
+#endif
+            }
+        }
+        while (again);
+    }
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (mutex)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+#endif
+
+/*******************************************************************************
+**
+**  gckVIDMEM_Lock
+**
+**  Lock a video memory node and return its hardware specific address.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gcuVIDMEM_NODE_PTR Node
+**          Pointer to a gcuVIDMEM_NODE union.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Address
+**          Pointer to a variable that will hold the hardware specific address.
+*/
+gceSTATUS
+gckVIDMEM_Lock(
+    IN gckKERNEL Kernel,
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctBOOL Cacheable,
+    OUT gctUINT32 * Address
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gctBOOL locked = gcvFALSE;
+    gckOS os = gcvNULL;
+
+    gcmkHEADER_ARG("Node=0x%x", Node);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    if ((Node == gcvNULL)
+    ||  (Node->VidMem.memory == gcvNULL)
+    )
+    {
+        /* Invalid object. */
+        gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+    }
+
+    /**************************** Video Memory ********************************/
+
+    if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+    {
+        if (Cacheable == gcvTRUE)
+        {
+            gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+        }
+
+        /* Increment the lock count. */
+        Node->VidMem.locked ++;
+
+        /* Return the address of the node. */
+#if !gcdUSE_VIDMEM_PER_PID
+        *Address = Node->VidMem.memory->baseAddress
+                 + Node->VidMem.offset
+                 + Node->VidMem.alignment;
+#else
+        *Address = Node->VidMem.physical;
+#endif
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                      "Locked node 0x%x (%d) @ 0x%08X",
+                      Node,
+                      Node->VidMem.locked,
+                      *Address);
+    }
+
+    /*************************** Virtual Memory *******************************/
+
+    else
+    {
+        /* Verify the gckKERNEL object pointer. */
+        gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
+
+        /* Extract the gckOS object pointer. */
+        os = Node->Virtual.kernel->os;
+        gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+        /* Grab the mutex. */
+        gcmkONERROR(gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
+        acquired = gcvTRUE;
+
+        gcmkONERROR(
+            gckOS_LockPages(os,
+                            Node->Virtual.physical,
+                            Node->Virtual.bytes,
+                            Cacheable,
+                            &Node->Virtual.logical,
+                            &Node->Virtual.pageCount));
+
+        /* Increment the lock count. */
+        if (Node->Virtual.lockeds[Kernel->core] ++ == 0)
+        {
+            /* Is this node pending for a final unlock? */
+#ifdef __QNXNTO__
+            if (!Node->Virtual.contiguous && Node->Virtual.unlockPendings[Kernel->core])
+            {
+                /* Make sure we have a page table. */
+                gcmkASSERT(Node->Virtual.pageTables[Kernel->core] != gcvNULL);
+
+                /* Remove pending unlock. */
+                Node->Virtual.unlockPendings[Kernel->core] = gcvFALSE;
+            }
+
+            /* First lock - create a page table. */
+            gcmkASSERT(Node->Virtual.pageTables[Kernel->core] == gcvNULL);
+
+            /* Make sure we mark our node as not flushed. */
+            Node->Virtual.unlockPendings[Kernel->core] = gcvFALSE;
+#endif
+
+            locked = gcvTRUE;
+
+            if (Node->Virtual.contiguous)
+            {
+                /* Get physical address directly */
+                 gcmkONERROR(gckOS_GetPhysicalAddress(os,
+                             Node->Virtual.logical,
+                             &Node->Virtual.addresses[Kernel->core]));
+            }
+            else
+            {
+#if gcdENABLE_VG
+                if (Kernel->vg != gcvNULL)
+                {
+                    /* Allocate pages inside the MMU. */
+                    gcmkONERROR(
+                        gckVGMMU_AllocatePages(Kernel->vg->mmu,
+                                             Node->Virtual.pageCount,
+                                             &Node->Virtual.pageTables[Kernel->core],
+                                             &Node->Virtual.addresses[Kernel->core]));
+                }
+                else
+#endif
+                {
+                    /* Allocate pages inside the MMU. */
+                    gcmkONERROR(
+                        gckMMU_AllocatePages(Kernel->mmu,
+                                             Node->Virtual.pageCount,
+                                             &Node->Virtual.pageTables[Kernel->core],
+                                             &Node->Virtual.addresses[Kernel->core]));
+                }
+
+                Node->Virtual.lockKernels[Kernel->core] = Kernel;
+
+                /* Map the pages. */
+#ifdef __QNXNTO__
+                gcmkONERROR(
+                    gckOS_MapPagesEx(os,
+                                     Kernel->core,
+                                     Node->Virtual.physical,
+                                     Node->Virtual.logical,
+                                     Node->Virtual.pageCount,
+                                     Node->Virtual.pageTables[Kernel->core]));
+#else
+                gcmkONERROR(
+                    gckOS_MapPagesEx(os,
+                                     Kernel->core,
+                                     Node->Virtual.physical,
+                                     Node->Virtual.pageCount,
+                                     Node->Virtual.pageTables[Kernel->core]));
+#endif
+            }
+
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                           "Mapped virtual node 0x%x to 0x%08X",
+                           Node,
+                           Node->Virtual.addresses[Kernel->core]);
+        }
+
+        /* Return hardware address. */
+        *Address = Node->Virtual.addresses[Kernel->core];
+
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Address=%08x", *Address);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (locked)
+    {
+        if (Node->Virtual.pageTables[Kernel->core] != gcvNULL)
+        {
+#if gcdENABLE_VG
+            if (Kernel->vg != gcvNULL)
+            {
+                /* Free the pages from the MMU. */
+                gcmkVERIFY_OK(
+                    gckVGMMU_FreePages(Kernel->vg->mmu,
+                                     Node->Virtual.pageTables[Kernel->core],
+                                     Node->Virtual.pageCount));
+            }
+            else
+#endif
+            {
+                /* Free the pages from the MMU. */
+                gcmkVERIFY_OK(
+                    gckMMU_FreePages(Kernel->mmu,
+                                     Node->Virtual.pageTables[Kernel->core],
+                                     Node->Virtual.pageCount));
+            }
+            Node->Virtual.pageTables[Kernel->core]  = gcvNULL;
+            Node->Virtual.lockKernels[Kernel->core] = gcvNULL;
+        }
+
+        /* Unlock the pages. */
+        gcmkVERIFY_OK(
+            gckOS_UnlockPages(os,
+                              Node->Virtual.physical,
+                              Node->Virtual.bytes,
+                              Node->Virtual.logical
+                              ));
+
+        Node->Virtual.lockeds[Kernel->core]--;
+    }
+
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVIDMEM_Unlock
+**
+**  Unlock a video memory node.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gcuVIDMEM_NODE_PTR Node
+**          Pointer to a locked gcuVIDMEM_NODE union.
+**
+**      gceSURF_TYPE Type
+**          Type of surface to unlock.
+**
+**      gctBOOL * Asynchroneous
+**          Pointer to a variable specifying whether the surface should be
+**          unlocked asynchroneously or not.
+**
+**  OUTPUT:
+**
+**      gctBOOL * Asynchroneous
+**          Pointer to a variable receiving the number of bytes used in the
+**          command buffer specified by 'Commands'.  If gcvNULL, there is no
+**          command buffer.
+*/
+gceSTATUS
+gckVIDMEM_Unlock(
+    IN gckKERNEL Kernel,
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gceSURF_TYPE Type,
+    IN OUT gctBOOL * Asynchroneous
+    )
+{
+    gceSTATUS status;
+    gckHARDWARE hardware;
+    gctPOINTER buffer;
+    gctSIZE_T requested, bufferSize;
+    gckCOMMAND command = gcvNULL;
+    gceKERNEL_FLUSH flush;
+    gckOS os = gcvNULL;
+    gctBOOL acquired = gcvFALSE;
+    gctBOOL commitEntered = gcvFALSE;
+    gctINT32 i, totalLocked;
+
+    gcmkHEADER_ARG("Node=0x%x Type=%d *Asynchroneous=%d",
+                   Node, Type, gcmOPT_VALUE(Asynchroneous));
+
+    /* Verify the arguments. */
+    if ((Node == gcvNULL)
+    ||  (Node->VidMem.memory == gcvNULL)
+    )
+    {
+        /* Invalid object. */
+        gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+    }
+
+    /**************************** Video Memory ********************************/
+
+    if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+    {
+        if (Node->VidMem.locked <= 0)
+        {
+            /* The surface was not locked. */
+            status = gcvSTATUS_MEMORY_UNLOCKED;
+            goto OnError;
+        }
+
+        /* Decrement the lock count. */
+        Node->VidMem.locked --;
+
+        if (Asynchroneous != gcvNULL)
+        {
+            /* No need for any events. */
+            *Asynchroneous = gcvFALSE;
+        }
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                      "Unlocked node 0x%x (%d)",
+                      Node,
+                      Node->VidMem.locked);
+
+        if (Node->VidMem.freePending && (Node->VidMem.locked == 0))
+        {
+            /* Client has unlocked node previously attempted to be freed by compositor. Free now. */
+            Node->VidMem.freePending = gcvFALSE;
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                           "Deferred-freeing Node 0x%x.",
+                           Node);
+            gcmkONERROR(gckVIDMEM_Free(Node));
+        }
+    }
+
+    /*************************** Virtual Memory *******************************/
+
+    else
+    {
+        /* Verify the gckHARDWARE object pointer. */
+        hardware = Kernel->hardware;
+        gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+        /* Verify the gckCOMMAND object pointer. */
+        command = Kernel->command;
+        gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
+        /* Get the gckOS object pointer. */
+        os = Kernel->os;
+        gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+        /* Grab the mutex. */
+        gcmkONERROR(
+            gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
+
+        acquired = gcvTRUE;
+
+        if (Asynchroneous == gcvNULL)
+        {
+            if (Node->Virtual.lockeds[Kernel->core] == 0)
+            {
+                status = gcvSTATUS_MEMORY_UNLOCKED;
+                goto OnError;
+            }
+
+            /* Decrement lock count. */
+            -- Node->Virtual.lockeds[Kernel->core];
+
+            /* See if we can unlock the resources. */
+            if (Node->Virtual.lockeds[Kernel->core] == 0)
+            {
+                /* Free the page table. */
+                if (Node->Virtual.pageTables[Kernel->core] != gcvNULL)
+                {
+#if gcdENABLE_VG
+                    if (Kernel->vg != gcvNULL)
+                    {
+                        gcmkONERROR(
+                            gckVGMMU_FreePages(Kernel->vg->mmu,
+                                             Node->Virtual.pageTables[Kernel->core],
+                                             Node->Virtual.pageCount));
+                    }
+                    else
+#endif
+                    {
+                        gcmkONERROR(
+                            gckMMU_FreePages(Kernel->mmu,
+                                             Node->Virtual.pageTables[Kernel->core],
+                                             Node->Virtual.pageCount));
+                    }
+                    /* Mark page table as freed. */
+                    Node->Virtual.pageTables[Kernel->core] = gcvNULL;
+                    Node->Virtual.lockKernels[Kernel->core] = gcvNULL;
+                }
+
+#ifdef __QNXNTO__
+                /* Mark node as unlocked. */
+                Node->Virtual.unlockPendings[Kernel->core] = gcvFALSE;
+#endif
+            }
+
+            for (i = 0, totalLocked = 0; i < gcdCORE_COUNT; i++)
+            {
+                totalLocked += Node->Virtual.lockeds[i];
+            }
+
+            if (totalLocked == 0)
+            {
+                /* Owner have already freed this node
+                ** and we are the last one to unlock, do
+                ** real free */
+                if (Node->Virtual.freed)
+                {
+                    /* Free the virtual memory. */
+                    gcmkVERIFY_OK(gckOS_FreePagedMemory(Kernel->os,
+                                                        Node->Virtual.physical,
+                                                        Node->Virtual.bytes));
+
+                    /* Release mutex before node is destroyed */
+                    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+
+                    acquired = gcvFALSE;
+
+                    /* Destroy the gcuVIDMEM_NODE union. */
+                    gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node));
+
+                    /* Node has been destroyed, so we should not touch it any more */
+                    gcmkFOOTER();
+                    return gcvSTATUS_OK;
+                }
+            }
+
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                           "Unmapped virtual node 0x%x from 0x%08X",
+                           Node, Node->Virtual.addresses[Kernel->core]);
+
+        }
+
+        else
+        {
+            /* If we need to unlock a node from virtual memory we have to be
+            ** very carefull.  If the node is still inside the caches we
+            ** might get a bus error later if the cache line needs to be
+            ** replaced.  So - we have to flush the caches before we do
+            ** anything. */
+
+            /* gckCommand_EnterCommit() can't be called in interrupt handler because
+            ** of a dead lock situation:
+            ** process call Command_Commit(), and acquire Command->mutexQueue in
+            ** gckCOMMAND_EnterCommit(). Then it will wait for a signal which depends
+            ** on interrupt handler to generate, if interrupt handler enter
+            ** gckCommand_EnterCommit(), process will never get the signal. */
+
+            /* So, flush cache when we still in process context, and then ask caller to
+            ** schedule a event. */
+
+            gcmkONERROR(
+                gckOS_UnlockPages(os,
+                              Node->Virtual.physical,
+                              Node->Virtual.bytes,
+                              Node->Virtual.logical));
+
+            if (!Node->Virtual.contiguous
+            &&  (Node->Virtual.lockeds[Kernel->core] == 1)
+            )
+            {
+                if (Type == gcvSURF_BITMAP)
+                {
+                    /* Flush 2D cache. */
+                    flush = gcvFLUSH_2D;
+                }
+                else if (Type == gcvSURF_RENDER_TARGET)
+                {
+                    /* Flush color cache. */
+                    flush = gcvFLUSH_COLOR;
+                }
+                else if (Type == gcvSURF_DEPTH)
+                {
+                    /* Flush depth cache. */
+                    flush = gcvFLUSH_DEPTH;
+                }
+                else
+                {
+                    /* No flush required. */
+                    flush = (gceKERNEL_FLUSH) 0;
+                }
+
+                gcmkONERROR(
+                    gckHARDWARE_Flush(hardware, flush, gcvNULL, &requested));
+
+                if (requested != 0)
+                {
+                    /* Acquire the command queue. */
+                    gcmkONERROR(gckCOMMAND_EnterCommit(command, gcvFALSE));
+                    commitEntered = gcvTRUE;
+
+                    gcmkONERROR(gckCOMMAND_Reserve(
+                        command, requested, &buffer, &bufferSize
+                        ));
+
+                    gcmkONERROR(gckHARDWARE_Flush(
+                        hardware, flush, buffer, &bufferSize
+                        ));
+
+                    /* Mark node as pending. */
+#ifdef __QNXNTO__
+                    Node->Virtual.unlockPendings[Kernel->core] = gcvTRUE;
+#endif
+
+                    gcmkONERROR(gckCOMMAND_Execute(command, requested));
+
+                    /* Release the command queue. */
+                    gcmkONERROR(gckCOMMAND_ExitCommit(command, gcvFALSE));
+                    commitEntered = gcvFALSE;
+                }
+            }
+
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                           "Scheduled unlock for virtual node 0x%x",
+                           Node);
+
+            /* Schedule the surface to be unlocked. */
+            *Asynchroneous = gcvTRUE;
+        }
+
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+
+        acquired = gcvFALSE;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Asynchroneous=%d", gcmOPT_VALUE(Asynchroneous));
+    return gcvSTATUS_OK;
+
+OnError:
+    if (commitEntered)
+    {
+        /* Release the command queue mutex. */
+        gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, gcvFALSE));
+    }
+
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
new file mode 100644 (file)
index 0000000..505b69c
--- /dev/null
@@ -0,0 +1,2334 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_h_
+#define __gc_hal_h_
+
+#include "gc_hal_rename.h"
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+#include "gc_hal_base.h"
+#include "gc_hal_profiler.h"
+#include "gc_hal_driver.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* Alignment Macros *******************************
+\******************************************************************************/
+
+#define gcmALIGN(n, align) \
+( \
+    ((n) + ((align) - 1)) & ~((align) - 1) \
+)
+
+#define gcmALIGN_BASE(n, align) \
+( \
+    (n) & ~((align) - 1) \
+)
+
+/******************************************************************************\
+***************************** Element Count Macro *****************************
+\******************************************************************************/
+
+#define gcmSIZEOF(a) \
+( \
+    (gctSIZE_T) (sizeof(a)) \
+)
+
+#define gcmCOUNTOF(a) \
+( \
+    sizeof(a) / sizeof(a[0]) \
+)
+
+/******************************************************************************\
+******************************** gcsOBJECT Object *******************************
+\******************************************************************************/
+
+/* Type of objects. */
+typedef enum _gceOBJECT_TYPE
+{
+    gcvOBJ_UNKNOWN              = 0,
+    gcvOBJ_2D                   = gcmCC('2','D',' ',' '),
+    gcvOBJ_3D                   = gcmCC('3','D',' ',' '),
+    gcvOBJ_ATTRIBUTE            = gcmCC('A','T','T','R'),
+    gcvOBJ_BRUSHCACHE           = gcmCC('B','R','U','$'),
+    gcvOBJ_BRUSHNODE            = gcmCC('B','R','U','n'),
+    gcvOBJ_BRUSH                = gcmCC('B','R','U','o'),
+    gcvOBJ_BUFFER               = gcmCC('B','U','F','R'),
+    gcvOBJ_COMMAND              = gcmCC('C','M','D',' '),
+    gcvOBJ_COMMANDBUFFER        = gcmCC('C','M','D','B'),
+    gcvOBJ_CONTEXT              = gcmCC('C','T','X','T'),
+    gcvOBJ_DEVICE               = gcmCC('D','E','V',' '),
+    gcvOBJ_DUMP                 = gcmCC('D','U','M','P'),
+    gcvOBJ_EVENT                = gcmCC('E','V','N','T'),
+    gcvOBJ_FUNCTION             = gcmCC('F','U','N','C'),
+    gcvOBJ_HAL                  = gcmCC('H','A','L',' '),
+    gcvOBJ_HARDWARE             = gcmCC('H','A','R','D'),
+    gcvOBJ_HEAP                 = gcmCC('H','E','A','P'),
+    gcvOBJ_INDEX                = gcmCC('I','N','D','X'),
+    gcvOBJ_INTERRUPT            = gcmCC('I','N','T','R'),
+    gcvOBJ_KERNEL               = gcmCC('K','E','R','N'),
+    gcvOBJ_KERNEL_FUNCTION      = gcmCC('K','F','C','N'),
+    gcvOBJ_MEMORYBUFFER         = gcmCC('M','E','M','B'),
+    gcvOBJ_MMU                  = gcmCC('M','M','U',' '),
+    gcvOBJ_OS                   = gcmCC('O','S',' ',' '),
+    gcvOBJ_OUTPUT               = gcmCC('O','U','T','P'),
+    gcvOBJ_PAINT                = gcmCC('P','N','T',' '),
+    gcvOBJ_PATH                 = gcmCC('P','A','T','H'),
+    gcvOBJ_QUEUE                = gcmCC('Q','U','E',' '),
+    gcvOBJ_SAMPLER              = gcmCC('S','A','M','P'),
+    gcvOBJ_SHADER               = gcmCC('S','H','D','R'),
+    gcvOBJ_STREAM               = gcmCC('S','T','R','M'),
+    gcvOBJ_SURF                 = gcmCC('S','U','R','F'),
+    gcvOBJ_TEXTURE              = gcmCC('T','X','T','R'),
+    gcvOBJ_UNIFORM              = gcmCC('U','N','I','F'),
+    gcvOBJ_VARIABLE             = gcmCC('V','A','R','I'),
+    gcvOBJ_VERTEX               = gcmCC('V','R','T','X'),
+    gcvOBJ_VIDMEM               = gcmCC('V','M','E','M'),
+    gcvOBJ_VG                   = gcmCC('V','G',' ',' '),
+}
+gceOBJECT_TYPE;
+
+/* gcsOBJECT object defintinon. */
+typedef struct _gcsOBJECT
+{
+    /* Type of an object. */
+    gceOBJECT_TYPE              type;
+}
+gcsOBJECT;
+
+typedef struct _gckHARDWARE *       gckHARDWARE;
+
+/* CORE flags. */
+typedef enum _gceCORE
+{
+    gcvCORE_MAJOR       = 0x0,
+    gcvCORE_2D          = 0x1,
+    gcvCORE_VG          = 0x2
+}
+gceCORE;
+
+#define gcdCORE_COUNT               3
+
+/*******************************************************************************
+**
+**  gcmVERIFY_OBJECT
+**
+**      Assert if an object is invalid or is not of the specified type.  If the
+**      object is invalid or not of the specified type, gcvSTATUS_INVALID_OBJECT
+**      will be returned from the current function.  In retail mode this macro
+**      does nothing.
+**
+**  ARGUMENTS:
+**
+**      obj     Object to test.
+**      t       Expected type of the object.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+#define _gcmVERIFY_OBJECT(prefix, obj, t) \
+    if ((obj) == gcvNULL) \
+    { \
+        prefix##TRACE(gcvLEVEL_ERROR, \
+                      #prefix "VERIFY_OBJECT failed: NULL"); \
+        prefix##TRACE(gcvLEVEL_ERROR, "  expected: %c%c%c%c", \
+                      gcmCC_PRINT(t)); \
+        prefix##ASSERT((obj) != gcvNULL); \
+        prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
+        return gcvSTATUS_INVALID_OBJECT; \
+    } \
+    else if (((gcsOBJECT*) (obj))->type != t) \
+    { \
+        prefix##TRACE(gcvLEVEL_ERROR, \
+                      #prefix "VERIFY_OBJECT failed: %c%c%c%c", \
+                      gcmCC_PRINT(((gcsOBJECT*) (obj))->type)); \
+        prefix##TRACE(gcvLEVEL_ERROR, "  expected: %c%c%c%c", \
+                      gcmCC_PRINT(t)); \
+        prefix##ASSERT(((gcsOBJECT*)(obj))->type == t); \
+        prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
+        return gcvSTATUS_INVALID_OBJECT; \
+    }
+
+#   define gcmVERIFY_OBJECT(obj, t)     _gcmVERIFY_OBJECT(gcm, obj, t)
+#   define gcmkVERIFY_OBJECT(obj, t)    _gcmVERIFY_OBJECT(gcmk, obj, t)
+#else
+#   define gcmVERIFY_OBJECT(obj, t)     do {} while (gcvFALSE)
+#   define gcmkVERIFY_OBJECT(obj, t)    do {} while (gcvFALSE)
+#endif
+
+/******************************************************************************/
+/*VERIFY_OBJECT if special return expected*/
+/******************************************************************************/
+#ifndef EGL_API_ANDROID
+#   define _gcmVERIFY_OBJECT_RETURN(prefix, obj, t, retVal) \
+        do \
+        { \
+            if ((obj) == gcvNULL) \
+            { \
+                prefix##PRINT_VERSION(); \
+                prefix##TRACE(gcvLEVEL_ERROR, \
+                              #prefix "VERIFY_OBJECT_RETURN failed: NULL"); \
+                prefix##TRACE(gcvLEVEL_ERROR, "  expected: %c%c%c%c", \
+                              gcmCC_PRINT(t)); \
+                prefix##ASSERT((obj) != gcvNULL); \
+                prefix##FOOTER_ARG("retVal=%d", retVal); \
+                return retVal; \
+            } \
+            else if (((gcsOBJECT*) (obj))->type != t) \
+            { \
+                prefix##PRINT_VERSION(); \
+                prefix##TRACE(gcvLEVEL_ERROR, \
+                              #prefix "VERIFY_OBJECT_RETURN failed: %c%c%c%c", \
+                              gcmCC_PRINT(((gcsOBJECT*) (obj))->type)); \
+                prefix##TRACE(gcvLEVEL_ERROR, "  expected: %c%c%c%c", \
+                              gcmCC_PRINT(t)); \
+                prefix##ASSERT(((gcsOBJECT*)(obj))->type == t); \
+                prefix##FOOTER_ARG("retVal=%d", retVal); \
+                return retVal; \
+            } \
+        } \
+        while (gcvFALSE)
+#   define gcmVERIFY_OBJECT_RETURN(obj, t, retVal) \
+                            _gcmVERIFY_OBJECT_RETURN(gcm, obj, t, retVal)
+#   define gcmkVERIFY_OBJECT_RETURN(obj, t, retVal) \
+                            _gcmVERIFY_OBJECT_RETURN(gcmk, obj, t, retVal)
+#else
+#   define gcmVERIFY_OBJECT_RETURN(obj, t)     do {} while (gcvFALSE)
+#   define gcmVERIFY_OBJECT_RETURN(obj, t)    do {} while (gcvFALSE)
+#endif
+
+/******************************************************************************\
+********************************** gckOS Object *********************************
+\******************************************************************************/
+
+/* Construct a new gckOS object. */
+gceSTATUS
+gckOS_Construct(
+    IN gctPOINTER Context,
+    OUT gckOS * Os
+    );
+
+/* Destroy an gckOS object. */
+gceSTATUS
+gckOS_Destroy(
+    IN gckOS Os
+    );
+
+/* Query the video memory. */
+gceSTATUS
+gckOS_QueryVideoMemory(
+    IN gckOS Os,
+    OUT gctPHYS_ADDR * InternalAddress,
+    OUT gctSIZE_T * InternalSize,
+    OUT gctPHYS_ADDR * ExternalAddress,
+    OUT gctSIZE_T * ExternalSize,
+    OUT gctPHYS_ADDR * ContiguousAddress,
+    OUT gctSIZE_T * ContiguousSize
+    );
+
+/* Allocate memory from the heap. */
+gceSTATUS
+gckOS_Allocate(
+    IN gckOS Os,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Memory
+    );
+
+/* Free allocated memory. */
+gceSTATUS
+gckOS_Free(
+    IN gckOS Os,
+    IN gctPOINTER Memory
+    );
+
+/* Wrapper for allocation memory.. */
+gceSTATUS
+gckOS_AllocateMemory(
+    IN gckOS Os,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Memory
+    );
+
+/* Wrapper for freeing memory. */
+gceSTATUS
+gckOS_FreeMemory(
+    IN gckOS Os,
+    IN gctPOINTER Memory
+    );
+
+/* Allocate paged memory. */
+gceSTATUS
+gckOS_AllocatePagedMemory(
+    IN gckOS Os,
+    IN gctSIZE_T Bytes,
+    OUT gctPHYS_ADDR * Physical
+    );
+
+/* Allocate paged memory. */
+gceSTATUS
+gckOS_AllocatePagedMemoryEx(
+    IN gckOS Os,
+    IN gctBOOL Contiguous,
+    IN gctSIZE_T Bytes,
+    OUT gctPHYS_ADDR * Physical
+    );
+
+/* Lock pages. */
+gceSTATUS
+gckOS_LockPages(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctBOOL Cacheable,
+    OUT gctPOINTER * Logical,
+    OUT gctSIZE_T * PageCount
+    );
+
+/* Map pages. */
+gceSTATUS
+gckOS_MapPages(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+#ifdef __QNXNTO__
+    IN gctPOINTER Logical,
+#endif
+    IN gctSIZE_T PageCount,
+    IN gctPOINTER PageTable
+    );
+
+/* Map pages. */
+gceSTATUS
+gckOS_MapPagesEx(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctPHYS_ADDR Physical,
+#ifdef __QNXNTO__
+    IN gctPOINTER Logical,
+#endif
+    IN gctSIZE_T PageCount,
+    IN gctPOINTER PageTable
+    );
+
+/* Unlock pages. */
+gceSTATUS
+gckOS_UnlockPages(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctPOINTER Logical
+    );
+
+/* Free paged memory. */
+gceSTATUS
+gckOS_FreePagedMemory(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes
+    );
+
+/* Allocate non-paged memory. */
+gceSTATUS
+gckOS_AllocateNonPagedMemory(
+    IN gckOS Os,
+    IN gctBOOL InUserSpace,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctPHYS_ADDR * Physical,
+    OUT gctPOINTER * Logical
+    );
+
+/* Free non-paged memory. */
+gceSTATUS
+gckOS_FreeNonPagedMemory(
+    IN gckOS Os,
+    IN gctSIZE_T Bytes,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical
+    );
+
+/* Allocate contiguous memory. */
+gceSTATUS
+gckOS_AllocateContiguous(
+    IN gckOS Os,
+    IN gctBOOL InUserSpace,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctPHYS_ADDR * Physical,
+    OUT gctPOINTER * Logical
+    );
+
+/* Free contiguous memory. */
+gceSTATUS
+gckOS_FreeContiguous(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    );
+
+/* Get the number fo bytes per page. */
+gceSTATUS
+gckOS_GetPageSize(
+    IN gckOS Os,
+    OUT gctSIZE_T * PageSize
+    );
+
+/* Get the physical address of a corresponding logical address. */
+gceSTATUS
+gckOS_GetPhysicalAddress(
+    IN gckOS Os,
+    IN gctPOINTER Logical,
+    OUT gctUINT32 * Address
+    );
+
+/* Get the physical address of a corresponding logical address. */
+gceSTATUS
+gckOS_GetPhysicalAddressProcess(
+    IN gckOS Os,
+    IN gctPOINTER Logical,
+    IN gctUINT32 ProcessID,
+    OUT gctUINT32 * Address
+    );
+
+/* Map physical memory. */
+gceSTATUS
+gckOS_MapPhysical(
+    IN gckOS Os,
+    IN gctUINT32 Physical,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Logical
+    );
+
+/* Unmap previously mapped physical memory. */
+gceSTATUS
+gckOS_UnmapPhysical(
+    IN gckOS Os,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    );
+
+/* Read data from a hardware register. */
+gceSTATUS
+gckOS_ReadRegister(
+    IN gckOS Os,
+    IN gctUINT32 Address,
+    OUT gctUINT32 * Data
+    );
+
+/* Read data from a hardware register. */
+gceSTATUS
+gckOS_ReadRegisterEx(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctUINT32 Address,
+    OUT gctUINT32 * Data
+    );
+
+/* Write data to a hardware register. */
+gceSTATUS
+gckOS_WriteRegister(
+    IN gckOS Os,
+    IN gctUINT32 Address,
+    IN gctUINT32 Data
+    );
+
+/* Write data to a hardware register. */
+gceSTATUS
+gckOS_WriteRegisterEx(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctUINT32 Address,
+    IN gctUINT32 Data
+    );
+
+/* Write data to a 32-bit memory location. */
+gceSTATUS
+gckOS_WriteMemory(
+    IN gckOS Os,
+    IN gctPOINTER Address,
+    IN gctUINT32 Data
+    );
+
+/* Map physical memory into the process space. */
+gceSTATUS
+gckOS_MapMemory(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Logical
+    );
+
+/* Unmap physical memory from the specified process space. */
+gceSTATUS
+gckOS_UnmapMemoryEx(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctPOINTER Logical,
+    IN gctUINT32 PID
+    );
+
+/* Unmap physical memory from the process space. */
+gceSTATUS
+gckOS_UnmapMemory(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctPOINTER Logical
+    );
+
+/* Create a new mutex. */
+gceSTATUS
+gckOS_CreateMutex(
+    IN gckOS Os,
+    OUT gctPOINTER * Mutex
+    );
+
+/* Delete a mutex. */
+gceSTATUS
+gckOS_DeleteMutex(
+    IN gckOS Os,
+    IN gctPOINTER Mutex
+    );
+
+/* Acquire a mutex. */
+gceSTATUS
+gckOS_AcquireMutex(
+    IN gckOS Os,
+    IN gctPOINTER Mutex,
+    IN gctUINT32 Timeout
+    );
+
+/* Release a mutex. */
+gceSTATUS
+gckOS_ReleaseMutex(
+    IN gckOS Os,
+    IN gctPOINTER Mutex
+    );
+
+/* Atomically exchange a pair of 32-bit values. */
+gceSTATUS
+gckOS_AtomicExchange(
+    IN gckOS Os,
+    IN OUT gctUINT32_PTR Target,
+    IN gctUINT32 NewValue,
+    OUT gctUINT32_PTR OldValue
+    );
+
+/* Atomically exchange a pair of pointers. */
+gceSTATUS
+gckOS_AtomicExchangePtr(
+    IN gckOS Os,
+    IN OUT gctPOINTER * Target,
+    IN gctPOINTER NewValue,
+    OUT gctPOINTER * OldValue
+    );
+
+/*******************************************************************************
+**
+**  gckOS_AtomConstruct
+**
+**  Create an atom.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Atom
+**          Pointer to a variable receiving the constructed atom.
+*/
+gceSTATUS
+gckOS_AtomConstruct(
+    IN gckOS Os,
+    OUT gctPOINTER * Atom
+    );
+
+/*******************************************************************************
+**
+**  gckOS_AtomDestroy
+**
+**  Destroy an atom.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**      gctPOINTER Atom
+**          Pointer to the atom to destroy.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_AtomDestroy(
+    IN gckOS Os,
+    OUT gctPOINTER Atom
+    );
+
+/*******************************************************************************
+**
+**  gckOS_AtomGet
+**
+**  Get the 32-bit value protected by an atom.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**      gctPOINTER Atom
+**          Pointer to the atom.
+**
+**  OUTPUT:
+**
+**      gctINT32_PTR Value
+**          Pointer to a variable the receives the value of the atom.
+*/
+gceSTATUS
+gckOS_AtomGet(
+    IN gckOS Os,
+    IN gctPOINTER Atom,
+    OUT gctINT32_PTR Value
+    );
+
+/*******************************************************************************
+**
+**  gckOS_AtomSet
+**
+**  Set the 32-bit value protected by an atom.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**      gctPOINTER Atom
+**          Pointer to the atom.
+**
+**      gctINT32 Value
+**          The value of the atom.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_AtomSet(
+    IN gckOS Os,
+    IN gctPOINTER Atom,
+    IN gctINT32 Value
+    );
+
+/*******************************************************************************
+**
+**  gckOS_AtomIncrement
+**
+**  Atomically increment the 32-bit integer value inside an atom.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**      gctPOINTER Atom
+**          Pointer to the atom.
+**
+**  OUTPUT:
+**
+**      gctINT32_PTR Value
+**          Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomIncrement(
+    IN gckOS Os,
+    IN gctPOINTER Atom,
+    OUT gctINT32_PTR Value
+    );
+
+/*******************************************************************************
+**
+**  gckOS_AtomDecrement
+**
+**  Atomically decrement the 32-bit integer value inside an atom.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**      gctPOINTER Atom
+**          Pointer to the atom.
+**
+**  OUTPUT:
+**
+**      gctINT32_PTR Value
+**          Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomDecrement(
+    IN gckOS Os,
+    IN gctPOINTER Atom,
+    OUT gctINT32_PTR Value
+    );
+
+/* Delay a number of microseconds. */
+gceSTATUS
+gckOS_Delay(
+    IN gckOS Os,
+    IN gctUINT32 Delay
+    );
+
+/* Get time in milliseconds. */
+gceSTATUS
+gckOS_GetTicks(
+    OUT gctUINT32_PTR Time
+    );
+
+/* Compare time value. */
+gceSTATUS
+gckOS_TicksAfter(
+    IN gctUINT32 Time1,
+    IN gctUINT32 Time2,
+    OUT gctBOOL_PTR IsAfter
+    );
+
+/* Get time in microseconds. */
+gceSTATUS
+gckOS_GetTime(
+    OUT gctUINT64_PTR Time
+    );
+
+/* Memory barrier. */
+gceSTATUS
+gckOS_MemoryBarrier(
+    IN gckOS Os,
+    IN gctPOINTER Address
+    );
+
+/* Map user pointer. */
+gceSTATUS
+gckOS_MapUserPointer(
+    IN gckOS Os,
+    IN gctPOINTER Pointer,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * KernelPointer
+    );
+
+/* Unmap user pointer. */
+gceSTATUS
+gckOS_UnmapUserPointer(
+    IN gckOS Os,
+    IN gctPOINTER Pointer,
+    IN gctSIZE_T Size,
+    IN gctPOINTER KernelPointer
+    );
+
+/*******************************************************************************
+**
+**  gckOS_QueryNeedCopy
+**
+**  Query whether the memory can be accessed or mapped directly or it has to be
+**  copied.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctUINT32 ProcessID
+**          Process ID of the current process.
+**
+**  OUTPUT:
+**
+**      gctBOOL_PTR NeedCopy
+**          Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
+**          gcvFALSE if the memory can be accessed or mapped dircetly.
+*/
+gceSTATUS
+gckOS_QueryNeedCopy(
+    IN gckOS Os,
+    IN gctUINT32 ProcessID,
+    OUT gctBOOL_PTR NeedCopy
+    );
+
+/*******************************************************************************
+**
+**  gckOS_CopyFromUserData
+**
+**  Copy data from user to kernel memory.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER KernelPointer
+**          Pointer to kernel memory.
+**
+**      gctPOINTER Pointer
+**          Pointer to user memory.
+**
+**      gctSIZE_T Size
+**          Number of bytes to copy.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_CopyFromUserData(
+    IN gckOS Os,
+    IN gctPOINTER KernelPointer,
+    IN gctPOINTER Pointer,
+    IN gctSIZE_T Size
+    );
+
+/*******************************************************************************
+**
+**  gckOS_CopyToUserData
+**
+**  Copy data from kernel to user memory.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER KernelPointer
+**          Pointer to kernel memory.
+**
+**      gctPOINTER Pointer
+**          Pointer to user memory.
+**
+**      gctSIZE_T Size
+**          Number of bytes to copy.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_CopyToUserData(
+    IN gckOS Os,
+    IN gctPOINTER KernelPointer,
+    IN gctPOINTER Pointer,
+    IN gctSIZE_T Size
+    );
+
+#ifdef __QNXNTO__
+/* Map user physical address. */
+gceSTATUS
+gckOS_MapUserPhysical(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Phys,
+    OUT gctPOINTER * KernelPointer
+    );
+#endif
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+    IN gckOS Os
+    );
+
+gceSTATUS
+gckOS_SuspendInterruptEx(
+    IN gckOS Os,
+    IN gceCORE Core
+    );
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+    IN gckOS Os
+    );
+
+gceSTATUS
+gckOS_ResumeInterruptEx(
+    IN gckOS Os,
+    IN gceCORE Core
+    );
+
+/* Get the base address for the physical memory. */
+gceSTATUS
+gckOS_GetBaseAddress(
+    IN gckOS Os,
+    OUT gctUINT32_PTR BaseAddress
+    );
+
+/* Perform a memory copy. */
+gceSTATUS
+gckOS_MemCopy(
+    IN gctPOINTER Destination,
+    IN gctCONST_POINTER Source,
+    IN gctSIZE_T Bytes
+    );
+
+/* Zero memory. */
+gceSTATUS
+gckOS_ZeroMemory(
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Bytes
+    );
+
+/* Device I/O control to the kernel HAL layer. */
+gceSTATUS
+gckOS_DeviceControl(
+    IN gckOS Os,
+    IN gctBOOL FromUser,
+    IN gctUINT32 IoControlCode,
+    IN gctPOINTER InputBuffer,
+    IN gctSIZE_T InputBufferSize,
+    OUT gctPOINTER OutputBuffer,
+    IN gctSIZE_T OutputBufferSize
+    );
+
+#if gcdENABLE_BANK_ALIGNMENT
+gceSTATUS
+gckOS_GetSurfaceBankAlignment(
+    IN gckOS Os,
+    IN gceSURF_TYPE Type,
+    IN gctUINT32 BaseAddress,
+    OUT gctUINT32_PTR Alignment
+    );
+#endif
+
+/*******************************************************************************
+**
+**  gckOS_GetProcessID
+**
+**  Get current process ID.
+**
+**  INPUT:
+**
+**      Nothing.
+**
+**  OUTPUT:
+**
+**      gctUINT32_PTR ProcessID
+**          Pointer to the variable that receives the process ID.
+*/
+gceSTATUS
+gckOS_GetProcessID(
+    OUT gctUINT32_PTR ProcessID
+    );
+
+gceSTATUS
+gckOS_GetCurrentProcessID(
+    OUT gctUINT32_PTR ProcessID
+    );
+
+/*******************************************************************************
+**
+**  gckOS_GetThreadID
+**
+**  Get current thread ID.
+**
+**  INPUT:
+**
+**      Nothing.
+**
+**  OUTPUT:
+**
+**      gctUINT32_PTR ThreadID
+**          Pointer to the variable that receives the thread ID.
+*/
+gceSTATUS
+gckOS_GetThreadID(
+    OUT gctUINT32_PTR ThreadID
+    );
+
+/******************************************************************************\
+********************************** Signal Object *********************************
+\******************************************************************************/
+
+/* Create a signal. */
+gceSTATUS
+gckOS_CreateSignal(
+    IN gckOS Os,
+    IN gctBOOL ManualReset,
+    OUT gctSIGNAL * Signal
+    );
+
+/* Destroy a signal. */
+gceSTATUS
+gckOS_DestroySignal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal
+    );
+
+/* Signal a signal. */
+gceSTATUS
+gckOS_Signal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal,
+    IN gctBOOL State
+    );
+
+/* Wait for a signal. */
+gceSTATUS
+gckOS_WaitSignal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal,
+    IN gctUINT32 Wait
+    );
+
+/* Map a user signal to the kernel space. */
+gceSTATUS
+gckOS_MapSignal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal,
+    IN gctHANDLE Process,
+    OUT gctSIGNAL * MappedSignal
+    );
+
+/* Unmap a user signal */
+gceSTATUS
+gckOS_UnmapSignal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal
+    );
+
+/* Map user memory. */
+gceSTATUS
+gckOS_MapUserMemory(
+    IN gckOS Os,
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * Info,
+    OUT gctUINT32_PTR Address
+    );
+
+/* Map user memory. */
+gceSTATUS
+gckOS_MapUserMemoryEx(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * Info,
+    OUT gctUINT32_PTR Address
+    );
+
+/* Unmap user memory. */
+gceSTATUS
+gckOS_UnmapUserMemory(
+    IN gckOS Os,
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Size,
+    IN gctPOINTER Info,
+    IN gctUINT32 Address
+    );
+
+/* Unmap user memory. */
+gceSTATUS
+gckOS_UnmapUserMemoryEx(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Size,
+    IN gctPOINTER Info,
+    IN gctUINT32 Address
+    );
+
+#if !USE_NEW_LINUX_SIGNAL
+/* Create signal to be used in the user space. */
+gceSTATUS
+gckOS_CreateUserSignal(
+    IN gckOS Os,
+    IN gctBOOL ManualReset,
+    OUT gctINT * SignalID
+    );
+
+/* Destroy signal used in the user space. */
+gceSTATUS
+gckOS_DestroyUserSignal(
+    IN gckOS Os,
+    IN gctINT SignalID
+    );
+
+/* Wait for signal used in the user space. */
+gceSTATUS
+gckOS_WaitUserSignal(
+    IN gckOS Os,
+    IN gctINT SignalID,
+    IN gctUINT32 Wait
+    );
+
+/* Signal a signal used in the user space. */
+gceSTATUS
+gckOS_SignalUserSignal(
+    IN gckOS Os,
+    IN gctINT SignalID,
+    IN gctBOOL State
+    );
+#endif /* USE_NEW_LINUX_SIGNAL */
+
+/* Set a signal owned by a process. */
+#if defined(__QNXNTO__)
+gceSTATUS
+gckOS_UserSignal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal,
+    IN gctINT Recvid,
+    IN gctINT Coid
+    );
+#else
+gceSTATUS
+gckOS_UserSignal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal,
+    IN gctHANDLE Process
+    );
+#endif
+
+/******************************************************************************\
+** Cache Support
+*/
+
+gceSTATUS
+gckOS_CacheClean(
+    gckOS Os,
+    gctUINT32 ProcessID,
+    gctPHYS_ADDR Handle,
+    gctPOINTER Physical,
+    gctPOINTER Logical,
+    gctSIZE_T Bytes
+    );
+
+gceSTATUS
+gckOS_CacheFlush(
+    gckOS Os,
+    gctUINT32 ProcessID,
+    gctPHYS_ADDR Handle,
+    gctPOINTER Physical,
+    gctPOINTER Logical,
+    gctSIZE_T Bytes
+    );
+
+gceSTATUS
+gckOS_CacheInvalidate(
+    gckOS Os,
+    gctUINT32 ProcessID,
+    gctPHYS_ADDR Handle,
+    gctPOINTER Physical,
+    gctPOINTER Logical,
+    gctSIZE_T Bytes
+    );
+
+/******************************************************************************\
+** Debug Support
+*/
+
+void
+gckOS_SetDebugLevel(
+    IN gctUINT32 Level
+    );
+
+void
+gckOS_SetDebugZone(
+    IN gctUINT32 Zone
+    );
+
+void
+gckOS_SetDebugLevelZone(
+    IN gctUINT32 Level,
+    IN gctUINT32 Zone
+    );
+
+void
+gckOS_SetDebugZones(
+    IN gctUINT32 Zones,
+    IN gctBOOL Enable
+    );
+
+void
+gckOS_SetDebugFile(
+    IN gctCONST_STRING FileName
+    );
+
+/*******************************************************************************
+** Broadcast interface.
+*/
+
+typedef enum _gceBROADCAST
+{
+    /* GPU might be idle. */
+    gcvBROADCAST_GPU_IDLE,
+
+    /* A commit is going to happen. */
+    gcvBROADCAST_GPU_COMMIT,
+
+    /* GPU seems to be stuck. */
+    gcvBROADCAST_GPU_STUCK,
+
+    /* First process gets attached. */
+    gcvBROADCAST_FIRST_PROCESS,
+
+    /* Last process gets detached. */
+    gcvBROADCAST_LAST_PROCESS,
+
+    /* AXI bus error. */
+    gcvBROADCAST_AXI_BUS_ERROR,
+}
+gceBROADCAST;
+
+gceSTATUS
+gckOS_Broadcast(
+    IN gckOS Os,
+    IN gckHARDWARE Hardware,
+    IN gceBROADCAST Reason
+    );
+
+gceSTATUS
+gckOS_BroadcastHurry(
+    IN gckOS Os,
+    IN gckHARDWARE Hardware,
+    IN gctUINT Urgency
+    );
+
+gceSTATUS
+gckOS_BroadcastCalibrateSpeed(
+    IN gckOS Os,
+    IN gckHARDWARE Hardware,
+    IN gctUINT Idle,
+    IN gctUINT Time
+    );
+
+/*******************************************************************************
+**
+**  gckOS_SetGPUPower
+**
+**  Set the power of the GPU on or off.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.ß
+**
+**      gctBOOL Clock
+**          gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
+**
+**      gctBOOL Power
+**          gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_SetGPUPower(
+    IN gckOS Os,
+    IN gctBOOL Clock,
+    IN gctBOOL Power
+    );
+
+/*******************************************************************************
+** Semaphores.
+*/
+
+/* Create a new semaphore. */
+gceSTATUS
+gckOS_CreateSemaphore(
+    IN gckOS Os,
+    OUT gctPOINTER * Semaphore
+    );
+
+#if gcdENABLE_VG
+gceSTATUS
+gckOS_CreateSemaphoreVG(
+    IN gckOS Os,
+    OUT gctPOINTER * Semaphore
+    );
+#endif
+
+/* Delete a semahore. */
+gceSTATUS
+gckOS_DestroySemaphore(
+    IN gckOS Os,
+    IN gctPOINTER Semaphore
+    );
+
+/* Acquire a semahore. */
+gceSTATUS
+gckOS_AcquireSemaphore(
+    IN gckOS Os,
+    IN gctPOINTER Semaphore
+    );
+
+/* Try to acquire a semahore. */
+gceSTATUS
+gckOS_TryAcquireSemaphore(
+    IN gckOS Os,
+    IN gctPOINTER Semaphore
+    );
+
+/* Release a semahore. */
+gceSTATUS
+gckOS_ReleaseSemaphore(
+    IN gckOS Os,
+    IN gctPOINTER Semaphore
+    );
+
+/******************************************************************************\
+********************************* gckHEAP Object ********************************
+\******************************************************************************/
+
+typedef struct _gckHEAP *       gckHEAP;
+
+/* Construct a new gckHEAP object. */
+gceSTATUS
+gckHEAP_Construct(
+    IN gckOS Os,
+    IN gctSIZE_T AllocationSize,
+    OUT gckHEAP * Heap
+    );
+
+/* Destroy an gckHEAP object. */
+gceSTATUS
+gckHEAP_Destroy(
+    IN gckHEAP Heap
+    );
+
+/* Allocate memory. */
+gceSTATUS
+gckHEAP_Allocate(
+    IN gckHEAP Heap,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Node
+    );
+
+/* Free memory. */
+gceSTATUS
+gckHEAP_Free(
+    IN gckHEAP Heap,
+    IN gctPOINTER Node
+    );
+
+/* Profile the heap. */
+gceSTATUS
+gckHEAP_ProfileStart(
+    IN gckHEAP Heap
+    );
+
+gceSTATUS
+gckHEAP_ProfileEnd(
+    IN gckHEAP Heap,
+    IN gctCONST_STRING Title
+    );
+
+
+/******************************************************************************\
+******************************** gckVIDMEM Object ******************************
+\******************************************************************************/
+
+typedef struct _gckVIDMEM *         gckVIDMEM;
+typedef struct _gckKERNEL *         gckKERNEL;
+typedef struct _gckDB *             gckDB;
+
+/* Construct a new gckVIDMEM object. */
+gceSTATUS
+gckVIDMEM_Construct(
+    IN gckOS Os,
+    IN gctUINT32 BaseAddress,
+    IN gctSIZE_T Bytes,
+    IN gctSIZE_T Threshold,
+    IN gctSIZE_T Banking,
+    OUT gckVIDMEM * Memory
+    );
+
+/* Destroy an gckVDIMEM object. */
+gceSTATUS
+gckVIDMEM_Destroy(
+    IN gckVIDMEM Memory
+    );
+
+/* Allocate rectangular memory. */
+gceSTATUS
+gckVIDMEM_Allocate(
+    IN gckVIDMEM Memory,
+    IN gctUINT Width,
+    IN gctUINT Height,
+    IN gctUINT Depth,
+    IN gctUINT BytesPerPixel,
+    IN gctUINT32 Alignment,
+    IN gceSURF_TYPE Type,
+    OUT gcuVIDMEM_NODE_PTR * Node
+    );
+
+/* Allocate linear memory. */
+gceSTATUS
+gckVIDMEM_AllocateLinear(
+    IN gckVIDMEM Memory,
+    IN gctSIZE_T Bytes,
+    IN gctUINT32 Alignment,
+    IN gceSURF_TYPE Type,
+    OUT gcuVIDMEM_NODE_PTR * Node
+    );
+
+/* Free memory. */
+gceSTATUS
+gckVIDMEM_Free(
+    IN gcuVIDMEM_NODE_PTR Node
+    );
+
+/* Lock memory. */
+gceSTATUS
+gckVIDMEM_Lock(
+    IN gckKERNEL Kernel,
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctBOOL Cacheable,
+    OUT gctUINT32 * Address
+    );
+
+/* Unlock memory. */
+gceSTATUS
+gckVIDMEM_Unlock(
+    IN gckKERNEL Kernel,
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gceSURF_TYPE Type,
+    IN OUT gctBOOL * Asynchroneous
+    );
+
+/* Construct a gcuVIDMEM_NODE union for virtual memory. */
+gceSTATUS
+gckVIDMEM_ConstructVirtual(
+    IN gckKERNEL Kernel,
+    IN gctBOOL Contiguous,
+    IN gctSIZE_T Bytes,
+    OUT gcuVIDMEM_NODE_PTR * Node
+    );
+
+/* Destroy a gcuVIDMEM_NODE union for virtual memory. */
+gceSTATUS
+gckVIDMEM_DestroyVirtual(
+    IN gcuVIDMEM_NODE_PTR Node
+    );
+
+/******************************************************************************\
+******************************** gckKERNEL Object ******************************
+\******************************************************************************/
+
+struct _gcsHAL_INTERFACE;
+
+/* Notifications. */
+typedef enum _gceNOTIFY
+{
+    gcvNOTIFY_INTERRUPT,
+    gcvNOTIFY_COMMAND_QUEUE,
+}
+gceNOTIFY;
+
+/* Flush flags. */
+typedef enum _gceKERNEL_FLUSH
+{
+    gcvFLUSH_COLOR              = 0x01,
+    gcvFLUSH_DEPTH              = 0x02,
+    gcvFLUSH_TEXTURE            = 0x04,
+    gcvFLUSH_2D                 = 0x08,
+    gcvFLUSH_ALL                = gcvFLUSH_COLOR
+                                | gcvFLUSH_DEPTH
+                                | gcvFLUSH_TEXTURE
+                                | gcvFLUSH_2D,
+}
+gceKERNEL_FLUSH;
+
+/* Construct a new gckKERNEL object. */
+gceSTATUS
+gckKERNEL_Construct(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctPOINTER Context,
+    IN gckDB SharedDB,
+    OUT gckKERNEL * Kernel
+    );
+
+/* Destroy an gckKERNEL object. */
+gceSTATUS
+gckKERNEL_Destroy(
+    IN gckKERNEL Kernel
+    );
+
+/* Dispatch a user-level command. */
+gceSTATUS
+gckKERNEL_Dispatch(
+    IN gckKERNEL Kernel,
+    IN gctBOOL FromUser,
+    IN OUT struct _gcsHAL_INTERFACE * Interface
+    );
+
+/* Query the video memory. */
+gceSTATUS
+gckKERNEL_QueryVideoMemory(
+    IN gckKERNEL Kernel,
+    OUT struct _gcsHAL_INTERFACE * Interface
+    );
+
+/* Lookup the gckVIDMEM object for a pool. */
+gceSTATUS
+gckKERNEL_GetVideoMemoryPool(
+    IN gckKERNEL Kernel,
+    IN gcePOOL Pool,
+    OUT gckVIDMEM * VideoMemory
+    );
+
+#if gcdUSE_VIDMEM_PER_PID
+gceSTATUS
+gckKERNEL_GetVideoMemoryPoolPid(
+    IN gckKERNEL Kernel,
+    IN gcePOOL Pool,
+    IN gctUINT32 Pid,
+    OUT gckVIDMEM * VideoMemory
+    );
+
+gceSTATUS
+gckKERNEL_CreateVideoMemoryPoolPid(
+    IN gckKERNEL Kernel,
+    IN gcePOOL Pool,
+    IN gctUINT32 Pid,
+    OUT gckVIDMEM * VideoMemory
+    );
+
+gceSTATUS
+gckKERNEL_RemoveVideoMemoryPoolPid(
+    IN gckKERNEL Kernel,
+    IN gckVIDMEM VideoMemory
+    );
+#endif
+
+/* Map video memory. */
+gceSTATUS
+gckKERNEL_MapVideoMemory(
+    IN gckKERNEL Kernel,
+    IN gctBOOL InUserSpace,
+    IN gctUINT32 Address,
+#ifdef __QNXNTO__
+    IN gctUINT32 Pid,
+    IN gctUINT32 Bytes,
+#endif
+    OUT gctPOINTER * Logical
+    );
+
+/* Map video memory. */
+gceSTATUS
+gckKERNEL_MapVideoMemoryEx(
+    IN gckKERNEL Kernel,
+    IN gceCORE Core,
+    IN gctBOOL InUserSpace,
+    IN gctUINT32 Address,
+#ifdef __QNXNTO__
+    IN gctUINT32 Pid,
+    IN gctUINT32 Bytes,
+#endif
+    OUT gctPOINTER * Logical
+    );
+
+#ifdef __QNXNTO__
+/* Unmap video memory. */
+gceSTATUS
+gckKERNEL_UnmapVideoMemory(
+    IN gckKERNEL Kernel,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Pid,
+    IN gctUINT32 Bytes
+    );
+#endif
+
+/* Map memory. */
+gceSTATUS
+gckKERNEL_MapMemory(
+    IN gckKERNEL Kernel,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Logical
+    );
+
+/* Unmap memory. */
+gceSTATUS
+gckKERNEL_UnmapMemory(
+    IN gckKERNEL Kernel,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctPOINTER Logical
+    );
+
+/* Notification of events. */
+gceSTATUS
+gckKERNEL_Notify(
+    IN gckKERNEL Kernel,
+    IN gceNOTIFY Notifcation,
+    IN gctBOOL Data
+    );
+
+gceSTATUS
+gckKERNEL_QuerySettings(
+    IN gckKERNEL Kernel,
+    OUT gcsKERNEL_SETTINGS * Settings
+    );
+
+/*******************************************************************************
+**
+**  gckKERNEL_Recovery
+**
+**  Try to recover the GPU from a fatal error.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckKERNEL_Recovery(
+    IN gckKERNEL Kernel
+    );
+
+/* Set the value of timeout on HW operation. */
+void
+gckKERNEL_SetTimeOut(
+    IN gckKERNEL Kernel,
+       IN gctUINT32 timeOut
+    );
+
+/* Get access to the user data. */
+gceSTATUS
+gckKERNEL_OpenUserData(
+    IN gckKERNEL Kernel,
+    IN gctBOOL NeedCopy,
+    IN gctPOINTER StaticStorage,
+    IN gctPOINTER UserPointer,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * KernelPointer
+    );
+
+/* Release resources associated with the user data connection. */
+gceSTATUS
+gckKERNEL_CloseUserData(
+    IN gckKERNEL Kernel,
+    IN gctBOOL NeedCopy,
+    IN gctBOOL FlushData,
+    IN gctPOINTER UserPointer,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * KernelPointer
+    );
+
+/******************************************************************************\
+******************************* gckHARDWARE Object *****************************
+\******************************************************************************/
+
+/* Construct a new gckHARDWARE object. */
+gceSTATUS
+gckHARDWARE_Construct(
+    IN gckOS Os,
+    IN gceCORE Core,
+    OUT gckHARDWARE * Hardware
+    );
+
+/* Destroy an gckHARDWARE object. */
+gceSTATUS
+gckHARDWARE_Destroy(
+    IN gckHARDWARE Hardware
+    );
+
+/* Get hardware type. */
+gceSTATUS
+gckHARDWARE_GetType(
+    IN gckHARDWARE Hardware,
+    OUT gceHARDWARE_TYPE * Type
+    );
+
+/* Query system memory requirements. */
+gceSTATUS
+gckHARDWARE_QuerySystemMemory(
+    IN gckHARDWARE Hardware,
+    OUT gctSIZE_T * SystemSize,
+    OUT gctUINT32 * SystemBaseAddress
+    );
+
+/* Build virtual address. */
+gceSTATUS
+gckHARDWARE_BuildVirtualAddress(
+    IN gckHARDWARE Hardware,
+    IN gctUINT32 Index,
+    IN gctUINT32 Offset,
+    OUT gctUINT32 * Address
+    );
+
+/* Query command buffer requirements. */
+gceSTATUS
+gckHARDWARE_QueryCommandBuffer(
+    IN gckHARDWARE Hardware,
+    OUT gctSIZE_T * Alignment,
+    OUT gctSIZE_T * ReservedHead,
+    OUT gctSIZE_T * ReservedTail
+    );
+
+/* Add a WAIT/LINK pair in the command queue. */
+gceSTATUS
+gckHARDWARE_WaitLink(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Offset,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctUINT32 * WaitOffset,
+    OUT gctSIZE_T * WaitBytes
+    );
+
+/* Kickstart the command processor. */
+gceSTATUS
+gckHARDWARE_Execute(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+#ifdef __QNXNTO__
+    IN gctPOINTER Physical,
+    IN gctBOOL PhysicalAddresses,
+#endif
+    IN gctSIZE_T Bytes
+    );
+
+/* Add an END command in the command queue. */
+gceSTATUS
+gckHARDWARE_End(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Add a NOP command in the command queue. */
+gceSTATUS
+gckHARDWARE_Nop(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Add a WAIT command in the command queue. */
+gceSTATUS
+gckHARDWARE_Wait(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Count,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Add a PIPESELECT command in the command queue. */
+gceSTATUS
+gckHARDWARE_PipeSelect(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gcePIPE_SELECT Pipe,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Add a LINK command in the command queue. */
+gceSTATUS
+gckHARDWARE_Link(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gctPOINTER FetchAddress,
+    IN gctSIZE_T FetchSize,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Add an EVENT command in the command queue. */
+gceSTATUS
+gckHARDWARE_Event(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gctUINT8 Event,
+    IN gceKERNEL_WHERE FromWhere,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Query the available memory. */
+gceSTATUS
+gckHARDWARE_QueryMemory(
+    IN gckHARDWARE Hardware,
+    OUT gctSIZE_T * InternalSize,
+    OUT gctUINT32 * InternalBaseAddress,
+    OUT gctUINT32 * InternalAlignment,
+    OUT gctSIZE_T * ExternalSize,
+    OUT gctUINT32 * ExternalBaseAddress,
+    OUT gctUINT32 * ExternalAlignment,
+    OUT gctUINT32 * HorizontalTileSize,
+    OUT gctUINT32 * VerticalTileSize
+    );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gckHARDWARE_QueryChipIdentity(
+    IN gckHARDWARE Hardware,
+    OUT gceCHIPMODEL* ChipModel,
+    OUT gctUINT32* ChipRevision,
+    OUT gctUINT32* ChipFeatures,
+    OUT gctUINT32* ChipMinorFeatures,
+    OUT gctUINT32* ChipMinorFeatures1,
+    OUT gctUINT32* ChipMinorFeatures2,
+    OUT gctUINT32* ChipMinorFeatures3
+    );
+
+/* Query the specifications sof the hardware. */
+gceSTATUS
+gckHARDWARE_QueryChipSpecs(
+    IN gckHARDWARE Hardware,
+    OUT gctUINT32_PTR StreamCount,
+    OUT gctUINT32_PTR RegisterMax,
+    OUT gctUINT32_PTR ThreadCount,
+    OUT gctUINT32_PTR ShaderCoreCount,
+    OUT gctUINT32_PTR VertexCacheSize,
+    OUT gctUINT32_PTR VertexOutputBufferSize,
+    OUT gctUINT32_PTR PixelPipes,
+    OUT gctUINT32_PTR InstructionCount,
+    OUT gctUINT32_PTR NumConstants,
+    OUT gctUINT32_PTR BufferSize
+    );
+
+/* Query the shader support. */
+gceSTATUS
+gckHARDWARE_QueryShaderCaps(
+    IN gckHARDWARE Hardware,
+    OUT gctUINT * VertexUniforms,
+    OUT gctUINT * FragmentUniforms,
+    OUT gctUINT * Varyings
+    );
+
+/* Convert an API format. */
+gceSTATUS
+gckHARDWARE_ConvertFormat(
+    IN gckHARDWARE Hardware,
+    IN gceSURF_FORMAT Format,
+    OUT gctUINT32 * BitsPerPixel,
+    OUT gctUINT32 * BytesPerTile
+    );
+
+/* Split a harwdare specific address into API stuff. */
+gceSTATUS
+gckHARDWARE_SplitMemory(
+    IN gckHARDWARE Hardware,
+    IN gctUINT32 Address,
+    OUT gcePOOL * Pool,
+    OUT gctUINT32 * Offset
+    );
+
+/* Align size to tile boundary. */
+gceSTATUS
+gckHARDWARE_AlignToTile(
+    IN gckHARDWARE Hardware,
+    IN gceSURF_TYPE Type,
+    IN OUT gctUINT32_PTR Width,
+    IN OUT gctUINT32_PTR Height,
+    OUT gctBOOL_PTR SuperTiled
+    );
+
+/* Update command queue tail pointer. */
+gceSTATUS
+gckHARDWARE_UpdateQueueTail(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Offset
+    );
+
+/* Convert logical address to hardware specific address. */
+gceSTATUS
+gckHARDWARE_ConvertLogical(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    OUT gctUINT32 * Address
+    );
+
+#ifdef __QNXNTO__
+/* Convert physical address to hardware specific address. */
+gceSTATUS
+gckHARDWARE_ConvertPhysical(
+    IN gckHARDWARE Hardware,
+    IN gctPHYS_ADDR Physical,
+    OUT gctUINT32 * Address
+    );
+#endif
+
+/* Interrupt manager. */
+gceSTATUS
+gckHARDWARE_Interrupt(
+    IN gckHARDWARE Hardware,
+    IN gctBOOL InterruptValid
+    );
+
+/* Program MMU. */
+gceSTATUS
+gckHARDWARE_SetMMU(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical
+    );
+
+/* Flush the MMU. */
+gceSTATUS
+gckHARDWARE_FlushMMU(
+    IN gckHARDWARE Hardware
+    );
+
+/* Set the page table base address. */
+gceSTATUS
+gckHARDWARE_SetMMUv2(
+    IN gckHARDWARE Hardware,
+    IN gctBOOL Enable,
+    IN gctPOINTER MtlbAddress,
+    IN gceMMU_MODE Mode,
+    IN gctPOINTER SafeAddress
+    );
+
+/* Get idle register. */
+gceSTATUS
+gckHARDWARE_GetIdle(
+    IN gckHARDWARE Hardware,
+    IN gctBOOL Wait,
+    OUT gctUINT32 * Data
+    );
+
+/* Flush the caches. */
+gceSTATUS
+gckHARDWARE_Flush(
+    IN gckHARDWARE Hardware,
+    IN gceKERNEL_FLUSH Flush,
+    IN gctPOINTER Logical,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Enable/disable fast clear. */
+gceSTATUS
+gckHARDWARE_SetFastClear(
+    IN gckHARDWARE Hardware,
+    IN gctINT Enable,
+    IN gctINT Compression
+    );
+
+gceSTATUS
+gckHARDWARE_ReadInterrupt(
+    IN gckHARDWARE Hardware,
+    OUT gctUINT32_PTR IDs
+    );
+
+/* Power management. */
+gceSTATUS
+gckHARDWARE_SetPowerManagementState(
+    IN gckHARDWARE Hardware,
+    IN gceCHIPPOWERSTATE State
+    );
+
+gceSTATUS
+gckHARDWARE_QueryPowerManagementState(
+    IN gckHARDWARE Hardware,
+    OUT gceCHIPPOWERSTATE* State
+    );
+
+/* Profile 2D Engine. */
+gceSTATUS
+gckHARDWARE_ProfileEngine2D(
+    IN gckHARDWARE Hardware,
+    OUT gcs2D_PROFILE_PTR Profile
+    );
+
+gceSTATUS
+gckHARDWARE_InitializeHardware(
+    IN gckHARDWARE Hardware
+    );
+
+gceSTATUS
+gckHARDWARE_Reset(
+    IN gckHARDWARE Hardware
+    );
+
+typedef gceSTATUS (*gctISRMANAGERFUNC)(gctPOINTER Context);
+
+gceSTATUS
+gckHARDWARE_SetIsrManager(
+    IN gckHARDWARE Hardware,
+    IN gctISRMANAGERFUNC StartIsr,
+    IN gctISRMANAGERFUNC StopIsr,
+    IN gctPOINTER Context
+    );
+
+/* Start a composition. */
+gceSTATUS
+gckHARDWARE_Compose(
+    IN gckHARDWARE Hardware,
+    IN gctUINT32 ProcessID,
+    IN gctSIZE_T Size,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical,
+    IN gctUINT8 EventID
+    );
+
+/* Check for Hardware features. */
+gceSTATUS
+gckHARDWARE_IsFeatureAvailable(
+    IN gckHARDWARE Hardware,
+    IN gceFEATURE Feature
+    );
+
+#if !gcdENABLE_VG
+/******************************************************************************\
+***************************** gckINTERRUPT Object ******************************
+\******************************************************************************/
+
+typedef struct _gckINTERRUPT *  gckINTERRUPT;
+
+typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
+    IN gckKERNEL Kernel
+    );
+
+gceSTATUS
+gckINTERRUPT_Construct(
+    IN gckKERNEL Kernel,
+    OUT gckINTERRUPT * Interrupt
+    );
+
+gceSTATUS
+gckINTERRUPT_Destroy(
+    IN gckINTERRUPT Interrupt
+    );
+
+gceSTATUS
+gckINTERRUPT_SetHandler(
+    IN gckINTERRUPT Interrupt,
+    IN OUT gctINT32_PTR Id,
+    IN gctINTERRUPT_HANDLER Handler
+    );
+
+gceSTATUS
+gckINTERRUPT_Notify(
+    IN gckINTERRUPT Interrupt,
+    IN gctBOOL Valid
+    );
+#endif
+/******************************************************************************\
+******************************** gckEVENT Object *******************************
+\******************************************************************************/
+
+typedef struct _gckEVENT *      gckEVENT;
+
+/* Construct a new gckEVENT object. */
+gceSTATUS
+gckEVENT_Construct(
+    IN gckKERNEL Kernel,
+    OUT gckEVENT * Event
+    );
+
+/* Destroy an gckEVENT object. */
+gceSTATUS
+gckEVENT_Destroy(
+    IN gckEVENT Event
+    );
+
+/* Reserve the next available hardware event. */
+gceSTATUS
+gckEVENT_GetEvent(
+    IN gckEVENT Event,
+    IN gctBOOL Wait,
+    OUT gctUINT8 * EventID,
+    IN gceKERNEL_WHERE Source
+   );
+
+/* Add a new event to the list of events. */
+gceSTATUS
+gckEVENT_AddList(
+    IN gckEVENT Event,
+    IN gcsHAL_INTERFACE_PTR Interface,
+    IN gceKERNEL_WHERE FromWhere,
+    IN gctBOOL AllocateAllowed
+    );
+
+/* Schedule a FreeNonPagedMemory event. */
+gceSTATUS
+gckEVENT_FreeNonPagedMemory(
+    IN gckEVENT Event,
+    IN gctSIZE_T Bytes,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical,
+    IN gceKERNEL_WHERE FromWhere
+    );
+
+/* Schedule a FreeContiguousMemory event. */
+gceSTATUS
+gckEVENT_FreeContiguousMemory(
+    IN gckEVENT Event,
+    IN gctSIZE_T Bytes,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical,
+    IN gceKERNEL_WHERE FromWhere
+    );
+
+/* Schedule a FreeVideoMemory event. */
+gceSTATUS
+gckEVENT_FreeVideoMemory(
+    IN gckEVENT Event,
+    IN gcuVIDMEM_NODE_PTR VideoMemory,
+    IN gceKERNEL_WHERE FromWhere
+    );
+
+/* Schedule a signal event. */
+gceSTATUS
+gckEVENT_Signal(
+    IN gckEVENT Event,
+    IN gctSIGNAL Signal,
+    IN gceKERNEL_WHERE FromWhere
+    );
+
+/* Schedule an Unlock event. */
+gceSTATUS
+gckEVENT_Unlock(
+    IN gckEVENT Event,
+    IN gceKERNEL_WHERE FromWhere,
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gceSURF_TYPE Type
+    );
+
+gceSTATUS
+gckEVENT_Submit(
+    IN gckEVENT Event,
+    IN gctBOOL Wait,
+    IN gctBOOL FromPower
+    );
+
+/* Commit an event queue. */
+gceSTATUS
+gckEVENT_Commit(
+    IN gckEVENT Event,
+    IN gcsQUEUE_PTR Queue
+    );
+
+/* Schedule a composition event. */
+gceSTATUS
+gckEVENT_Compose(
+    IN gckEVENT Event,
+    IN gcsHAL_COMPOSE_PTR Info
+    );
+
+/* Event callback routine. */
+gceSTATUS
+gckEVENT_Notify(
+    IN gckEVENT Event,
+    IN gctUINT32 IDs
+    );
+
+/* Event callback routine. */
+gceSTATUS
+gckEVENT_Interrupt(
+    IN gckEVENT Event,
+    IN gctUINT32 IDs
+    );
+
+/******************************************************************************\
+******************************* gckCOMMAND Object ******************************
+\******************************************************************************/
+
+typedef struct _gckCOMMAND *        gckCOMMAND;
+
+/* Construct a new gckCOMMAND object. */
+gceSTATUS
+gckCOMMAND_Construct(
+    IN gckKERNEL Kernel,
+    OUT gckCOMMAND * Command
+    );
+
+/* Destroy an gckCOMMAND object. */
+gceSTATUS
+gckCOMMAND_Destroy(
+    IN gckCOMMAND Command
+    );
+
+/* Acquire command queue synchronization objects. */
+gceSTATUS
+gckCOMMAND_EnterCommit(
+    IN gckCOMMAND Command,
+    IN gctBOOL FromPower
+    );
+
+/* Release command queue synchronization objects. */
+gceSTATUS
+gckCOMMAND_ExitCommit(
+    IN gckCOMMAND Command,
+    IN gctBOOL FromPower
+    );
+
+/* Start the command queue. */
+gceSTATUS
+gckCOMMAND_Start(
+    IN gckCOMMAND Command
+    );
+
+/* Stop the command queue. */
+gceSTATUS
+gckCOMMAND_Stop(
+    IN gckCOMMAND Command
+    );
+
+/* Commit a buffer to the command queue. */
+gceSTATUS
+gckCOMMAND_Commit(
+    IN gckCOMMAND Command,
+    IN gckCONTEXT Context,
+    IN gcoCMDBUF CommandBuffer,
+    IN gcsSTATE_DELTA_PTR StateDelta,
+    IN gcsQUEUE_PTR EventQueue,
+    IN gctUINT32 ProcessID
+    );
+
+/* Reserve space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Reserve(
+    IN gckCOMMAND Command,
+    IN gctSIZE_T RequestedBytes,
+    OUT gctPOINTER * Buffer,
+    OUT gctSIZE_T * BufferSize
+    );
+
+/* Execute reserved space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Execute(
+    IN gckCOMMAND Command,
+    IN gctSIZE_T RequstedBytes
+    );
+
+/* Stall the command queue. */
+gceSTATUS
+gckCOMMAND_Stall(
+    IN gckCOMMAND Command,
+    IN gctBOOL FromPower
+    );
+
+/* Attach user process. */
+gceSTATUS
+gckCOMMAND_Attach(
+    IN gckCOMMAND Command,
+    OUT gckCONTEXT * Context,
+    OUT gctSIZE_T * StateCount,
+    IN gctUINT32 ProcessID
+    );
+
+/* Detach user process. */
+gceSTATUS
+gckCOMMAND_Detach(
+    IN gckCOMMAND Command,
+    IN gckCONTEXT Context
+    );
+
+/******************************************************************************\
+********************************* gckMMU Object ********************************
+\******************************************************************************/
+
+typedef struct _gckMMU *            gckMMU;
+
+/* Construct a new gckMMU object. */
+gceSTATUS
+gckMMU_Construct(
+    IN gckKERNEL Kernel,
+    IN gctSIZE_T MmuSize,
+    OUT gckMMU * Mmu
+    );
+
+/* Destroy an gckMMU object. */
+gceSTATUS
+gckMMU_Destroy(
+    IN gckMMU Mmu
+    );
+
+/* Enable the MMU. */
+gceSTATUS
+gckMMU_Enable(
+    IN gckMMU Mmu,
+    IN gctUINT32 PhysBaseAddr,
+    IN gctUINT32 PhysSize
+    );
+
+/* Allocate pages inside the MMU. */
+gceSTATUS
+gckMMU_AllocatePages(
+    IN gckMMU Mmu,
+    IN gctSIZE_T PageCount,
+    OUT gctPOINTER * PageTable,
+    OUT gctUINT32 * Address
+    );
+
+/* Remove a page table from the MMU. */
+gceSTATUS
+gckMMU_FreePages(
+    IN gckMMU Mmu,
+    IN gctPOINTER PageTable,
+    IN gctSIZE_T PageCount
+    );
+
+/* Set the MMU page with info. */
+gceSTATUS
+gckMMU_SetPage(
+   IN gckMMU Mmu,
+   IN gctUINT32 PageAddress,
+   IN gctUINT32 *PageEntry
+   );
+
+#ifdef __QNXNTO__
+gceSTATUS
+gckMMU_InsertNode(
+    IN gckMMU Mmu,
+    IN gcuVIDMEM_NODE_PTR Node);
+
+gceSTATUS
+gckMMU_RemoveNode(
+    IN gckMMU Mmu,
+    IN gcuVIDMEM_NODE_PTR Node);
+#endif
+
+#ifdef __QNXNTO__
+gceSTATUS
+gckMMU_FreeHandleMemory(
+    IN gckKERNEL Kernel,
+    IN gckMMU Mmu,
+    IN gctUINT32 Pid
+    );
+#endif
+
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gckHARDWARE_QueryProfileRegisters(
+    IN gckHARDWARE Hardware,
+    OUT gcsPROFILER_COUNTERS * Counters
+    );
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#if gcdENABLE_VG
+#include "gc_hal_vg.h"
+#endif
+
+#endif /* __gc_hal_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
new file mode 100644 (file)
index 0000000..1c1c1ad
--- /dev/null
@@ -0,0 +1,3372 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_base_h_
+#define __gc_hal_base_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+
+#include "gc_hal_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gckOS *                 gckOS;
+typedef struct _gcoHAL *                gcoHAL;
+typedef struct _gcoOS *                 gcoOS;
+typedef struct _gco2D *                 gco2D;
+
+#ifndef VIVANTE_NO_3D
+typedef struct _gco3D *                 gco3D;
+#endif
+
+typedef struct _gcoSURF *               gcoSURF;
+typedef struct _gcsSURF_INFO *          gcsSURF_INFO_PTR;
+typedef struct _gcsSURF_NODE *          gcsSURF_NODE_PTR;
+typedef struct _gcsSURF_FORMAT_INFO *   gcsSURF_FORMAT_INFO_PTR;
+typedef struct _gcsPOINT *              gcsPOINT_PTR;
+typedef struct _gcsSIZE *               gcsSIZE_PTR;
+typedef struct _gcsRECT *               gcsRECT_PTR;
+typedef struct _gcsBOUNDARY *           gcsBOUNDARY_PTR;
+typedef struct _gcoDUMP *               gcoDUMP;
+typedef struct _gcoHARDWARE *           gcoHARDWARE;
+typedef union  _gcuVIDMEM_NODE *        gcuVIDMEM_NODE_PTR;
+
+#if gcdENABLE_VG
+typedef struct _gcoVG *                 gcoVG;
+typedef struct _gcsCOMPLETION_SIGNAL * gcsCOMPLETION_SIGNAL_PTR;
+typedef struct _gcsCONTEXT_MAP *               gcsCONTEXT_MAP_PTR;
+#else
+typedef void *                          gcoVG;
+#endif
+
+/******************************************************************************\
+******************************* Process local storage *************************
+\******************************************************************************/
+
+typedef struct _gcsPLS * gcsPLS_PTR;
+typedef struct _gcsPLS
+{
+    /* Global objects. */
+    gcoOS                       os;
+    gcoHAL                      hal;
+
+    /* Internal memory pool. */
+    gctSIZE_T                   internalSize;
+    gctPHYS_ADDR                internalPhysical;
+    gctPOINTER                  internalLogical;
+
+    /* External memory pool. */
+    gctSIZE_T                   externalSize;
+    gctPHYS_ADDR                externalPhysical;
+    gctPOINTER                  externalLogical;
+
+    /* Contiguous memory pool. */
+    gctSIZE_T                   contiguousSize;
+    gctPHYS_ADDR                contiguousPhysical;
+    gctPOINTER                  contiguousLogical;
+
+    /* EGL-specific process-wide objects. */
+    gctPOINTER                  eglDisplayInfo;
+    gctPOINTER                  eglSurfaceInfo;
+}
+gcsPLS;
+
+extern gcsPLS gcPLS;
+
+/******************************************************************************\
+******************************* Thread local storage *************************
+\******************************************************************************/
+
+typedef struct _gcsTLS * gcsTLS_PTR;
+
+typedef void (* gctTLS_DESTRUCTOR) (
+    gcsTLS_PTR TLS
+    );
+
+typedef struct _gcsTLS
+{
+    gceHARDWARE_TYPE            currentType;
+    gcoHARDWARE                 hardware;
+    /* Only for separated 3D and 2D */
+    gcoHARDWARE                 hardware2D;
+#if gcdENABLE_VG
+    gcoVGHARDWARE               vg;
+#endif /* gcdENABLE_VG */
+    gctPOINTER                  context;
+    gctTLS_DESTRUCTOR           destructor;
+    gctBOOL                     ProcessExiting;
+}
+gcsTLS;
+
+/******************************************************************************\
+********************************* Enumerations *********************************
+\******************************************************************************/
+
+typedef enum _gcePLS_VALUE
+{
+  gcePLS_VALUE_EGL_DISPLAY_INFO,
+  gcePLS_VALUE_EGL_SURFACE_INFO
+}
+gcePLS_VALUE;
+
+/* Video memory pool type. */
+typedef enum _gcePOOL
+{
+    gcvPOOL_UNKNOWN = 0,
+    gcvPOOL_DEFAULT,
+    gcvPOOL_LOCAL,
+    gcvPOOL_LOCAL_INTERNAL,
+    gcvPOOL_LOCAL_EXTERNAL,
+    gcvPOOL_UNIFIED,
+    gcvPOOL_SYSTEM,
+    gcvPOOL_VIRTUAL,
+    gcvPOOL_USER,
+    gcvPOOL_CONTIGUOUS,
+
+    gcvPOOL_NUMBER_OF_POOLS
+}
+gcePOOL;
+
+#ifndef VIVANTE_NO_3D
+/* Blending functions. */
+typedef enum _gceBLEND_FUNCTION
+{
+    gcvBLEND_ZERO,
+    gcvBLEND_ONE,
+    gcvBLEND_SOURCE_COLOR,
+    gcvBLEND_INV_SOURCE_COLOR,
+    gcvBLEND_SOURCE_ALPHA,
+    gcvBLEND_INV_SOURCE_ALPHA,
+    gcvBLEND_TARGET_COLOR,
+    gcvBLEND_INV_TARGET_COLOR,
+    gcvBLEND_TARGET_ALPHA,
+    gcvBLEND_INV_TARGET_ALPHA,
+    gcvBLEND_SOURCE_ALPHA_SATURATE,
+    gcvBLEND_CONST_COLOR,
+    gcvBLEND_INV_CONST_COLOR,
+    gcvBLEND_CONST_ALPHA,
+    gcvBLEND_INV_CONST_ALPHA,
+}
+gceBLEND_FUNCTION;
+
+/* Blending modes. */
+typedef enum _gceBLEND_MODE
+{
+    gcvBLEND_ADD,
+    gcvBLEND_SUBTRACT,
+    gcvBLEND_REVERSE_SUBTRACT,
+    gcvBLEND_MIN,
+    gcvBLEND_MAX,
+}
+gceBLEND_MODE;
+
+/* API flags. */
+typedef enum _gceAPI
+{
+    gcvAPI_D3D                  = 0x1,
+    gcvAPI_OPENGL               = 0x2,
+    gcvAPI_OPENVG               = 0x3,
+    gcvAPI_OPENCL               = 0x4,
+}
+gceAPI;
+
+/* Depth modes. */
+typedef enum _gceDEPTH_MODE
+{
+    gcvDEPTH_NONE,
+    gcvDEPTH_Z,
+    gcvDEPTH_W,
+}
+gceDEPTH_MODE;
+#endif /* VIVANTE_NO_3D */
+
+typedef enum _gceWHERE
+{
+    gcvWHERE_COMMAND,
+    gcvWHERE_RASTER,
+    gcvWHERE_PIXEL,
+}
+gceWHERE;
+
+typedef enum _gceHOW
+{
+    gcvHOW_SEMAPHORE            = 0x1,
+    gcvHOW_STALL                = 0x2,
+    gcvHOW_SEMAPHORE_STALL      = 0x3,
+}
+gceHOW;
+
+#if gcdENABLE_VG
+/* gcsHAL_Limits*/
+typedef struct _gcsHAL_LIMITS
+{
+    /* chip info */
+    gceCHIPMODEL    chipModel;
+    gctUINT32       chipRevision;
+    gctUINT32       featureCount;
+    gctUINT32       *chipFeatures;
+
+    /* target caps */
+       gctUINT32         maxWidth;
+       gctUINT32         maxHeight;
+       gctUINT32         multiTargetCount;
+       gctUINT32         maxSamples;
+
+}gcsHAL_LIMITS;
+#endif
+
+/******************************************************************************\
+********************************* gcoHAL Object *********************************
+\******************************************************************************/
+
+/* Construct a new gcoHAL object. */
+gceSTATUS
+gcoHAL_Construct(
+    IN gctPOINTER Context,
+    IN gcoOS Os,
+    OUT gcoHAL * Hal
+    );
+
+/* Destroy an gcoHAL object. */
+gceSTATUS
+gcoHAL_Destroy(
+    IN gcoHAL Hal
+    );
+
+/* Get pointer to gco2D object. */
+gceSTATUS
+gcoHAL_Get2DEngine(
+    IN gcoHAL Hal,
+    OUT gco2D * Engine
+    );
+
+#ifndef VIVANTE_NO_3D
+/* Get pointer to gco3D object. */
+gceSTATUS
+gcoHAL_Get3DEngine(
+    IN gcoHAL Hal,
+    OUT gco3D * Engine
+    );
+#endif /* VIVANTE_NO_3D */
+
+/* Verify whether the specified feature is available in hardware. */
+gceSTATUS
+gcoHAL_IsFeatureAvailable(
+    IN gcoHAL Hal,
+    IN gceFEATURE Feature
+    );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gcoHAL_QueryChipIdentity(
+    IN gcoHAL Hal,
+    OUT gceCHIPMODEL* ChipModel,
+    OUT gctUINT32* ChipRevision,
+    OUT gctUINT32* ChipFeatures,
+    OUT gctUINT32* ChipMinorFeatures
+    );
+
+/* Query the minor features of the hardware. */
+gceSTATUS gcoHAL_QueryChipMinorFeatures(
+    IN gcoHAL Hal,
+    OUT gctUINT32* NumFeatures,
+    OUT gctUINT32* ChipMinorFeatures
+    );
+
+/* Query the amount of video memory. */
+gceSTATUS
+gcoHAL_QueryVideoMemory(
+    IN gcoHAL Hal,
+    OUT gctPHYS_ADDR * InternalAddress,
+    OUT gctSIZE_T * InternalSize,
+    OUT gctPHYS_ADDR * ExternalAddress,
+    OUT gctSIZE_T * ExternalSize,
+    OUT gctPHYS_ADDR * ContiguousAddress,
+    OUT gctSIZE_T * ContiguousSize
+    );
+
+/* Map video memory. */
+gceSTATUS
+gcoHAL_MapMemory(
+    IN gcoHAL Hal,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T NumberOfBytes,
+    OUT gctPOINTER * Logical
+    );
+
+/* Unmap video memory. */
+gceSTATUS
+gcoHAL_UnmapMemory(
+    IN gcoHAL Hal,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T NumberOfBytes,
+    IN gctPOINTER Logical
+    );
+
+/* Schedule an unmap of a buffer mapped through its physical address. */
+gceSTATUS
+gcoHAL_ScheduleUnmapMemory(
+    IN gcoHAL Hal,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T NumberOfBytes,
+    IN gctPOINTER Logical
+    );
+
+/* Schedule an unmap of a user buffer using event mechanism. */
+gceSTATUS
+gcoHAL_ScheduleUnmapUserMemory(
+    IN gcoHAL Hal,
+    IN gctPOINTER Info,
+    IN gctSIZE_T Size,
+    IN gctUINT32 Address,
+    IN gctPOINTER Memory
+    );
+
+/* Commit the current command buffer. */
+gceSTATUS
+gcoHAL_Commit(
+    IN gcoHAL Hal,
+    IN gctBOOL Stall
+    );
+
+/* Query the tile capabilities. */
+gceSTATUS
+gcoHAL_QueryTiled(
+    IN gcoHAL Hal,
+    OUT gctINT32 * TileWidth2D,
+    OUT gctINT32 * TileHeight2D,
+    OUT gctINT32 * TileWidth3D,
+    OUT gctINT32 * TileHeight3D
+    );
+
+gceSTATUS
+gcoHAL_Compact(
+    IN gcoHAL Hal
+    );
+
+#if VIVANTE_PROFILER /*gcdENABLE_PROFILING*/
+gceSTATUS
+gcoHAL_ProfileStart(
+    IN gcoHAL Hal
+    );
+
+gceSTATUS
+gcoHAL_ProfileEnd(
+    IN gcoHAL Hal,
+    IN gctCONST_STRING Title
+    );
+#endif
+
+/* Power Management */
+gceSTATUS
+gcoHAL_SetPowerManagementState(
+    IN gcoHAL Hal,
+    IN gceCHIPPOWERSTATE State
+    );
+
+gceSTATUS
+gcoHAL_QueryPowerManagementState(
+    IN gcoHAL Hal,
+    OUT gceCHIPPOWERSTATE *State
+    );
+
+/* Set the filter type for filter blit. */
+gceSTATUS
+gcoHAL_SetFilterType(
+    IN gcoHAL Hal,
+    IN gceFILTER_TYPE FilterType
+    );
+
+gceSTATUS
+gcoHAL_GetDump(
+    IN gcoHAL Hal,
+    OUT gcoDUMP * Dump
+    );
+
+/* Call the kernel HAL layer. */
+gceSTATUS
+gcoHAL_Call(
+    IN gcoHAL Hal,
+    IN OUT gcsHAL_INTERFACE_PTR Interface
+    );
+
+/* Schedule an event. */
+gceSTATUS
+gcoHAL_ScheduleEvent(
+    IN gcoHAL Hal,
+    IN OUT gcsHAL_INTERFACE_PTR Interface
+    );
+
+/* Destroy a surface. */
+gceSTATUS
+gcoHAL_DestroySurface(
+    IN gcoHAL Hal,
+    IN gcoSURF Surface
+    );
+
+/* Request a start/stop timestamp. */
+gceSTATUS
+gcoHAL_SetTimer(
+    IN gcoHAL Hal,
+    IN gctUINT32 Index,
+    IN gctBOOL Start
+    );
+
+/* Get Time delta from a Timer in microseconds. */
+gceSTATUS
+gcoHAL_GetTimerTime(
+    IN gcoHAL Hal,
+    IN gctUINT32 Timer,
+    OUT gctINT32_PTR TimeDelta
+    );
+
+/* set timeout value. */
+gceSTATUS
+gcoHAL_SetTimeOut(
+    IN gcoHAL Hal,
+    IN gctUINT32 timeOut
+    );
+
+gceSTATUS
+gcoHAL_SetHardwareType(
+    IN gcoHAL Hal,
+    IN gceHARDWARE_TYPE HardwardType
+    );
+
+gceSTATUS
+gcoHAL_GetHardwareType(
+    IN gcoHAL Hal,
+    OUT gceHARDWARE_TYPE * HardwardType
+    );
+
+gceSTATUS
+gcoHAL_QueryChipCount(
+    IN gcoHAL Hal,
+    OUT gctINT32 * Count
+    );
+
+gceSTATUS
+gcoHAL_QuerySeparated3D2D(
+    IN gcoHAL Hal
+    );
+
+/* Get pointer to gcoVG object. */
+gceSTATUS
+gcoHAL_GetVGEngine(
+    IN gcoHAL Hal,
+    OUT gcoVG * Engine
+    );
+
+#if gcdENABLE_VG
+gceSTATUS
+gcoHAL_QueryChipLimits(
+    IN gcoHAL           Hal,
+    IN gctINT32         Chip,
+    OUT gcsHAL_LIMITS   *Limits);
+
+gceSTATUS
+gcoHAL_QueryChipFeature(
+    IN gcoHAL       Hal,
+    IN gctINT32     Chip,
+    IN gceFEATURE   Feature);
+
+#endif
+/******************************************************************************\
+********************************** gcoOS Object *********************************
+\******************************************************************************/
+
+/* Get PLS value for given key */
+gctPOINTER
+gcoOS_GetPLSValue(
+    IN gcePLS_VALUE key
+    );
+
+/* Set PLS value of a given key */
+void
+gcoOS_SetPLSValue(
+    IN gcePLS_VALUE key,
+    OUT gctPOINTER value
+    );
+
+/* Get access to the thread local storage. */
+gceSTATUS
+gcoOS_GetTLS(
+    OUT gcsTLS_PTR * TLS
+    );
+
+/* Destroy the objects associated with the current thread. */
+void
+gcoOS_FreeThreadData(
+    IN gctBOOL ProcessExiting
+    );
+
+/* Construct a new gcoOS object. */
+gceSTATUS
+gcoOS_Construct(
+    IN gctPOINTER Context,
+    OUT gcoOS * Os
+    );
+
+/* Destroy an gcoOS object. */
+gceSTATUS
+gcoOS_Destroy(
+    IN gcoOS Os
+    );
+
+/* Get the base address for the physical memory. */
+gceSTATUS
+gcoOS_GetBaseAddress(
+    IN gcoOS Os,
+    OUT gctUINT32_PTR BaseAddress
+    );
+
+/* Allocate memory from the heap. */
+gceSTATUS
+gcoOS_Allocate(
+    IN gcoOS Os,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Memory
+    );
+
+/* Free allocated memory. */
+gceSTATUS
+gcoOS_Free(
+    IN gcoOS Os,
+    IN gctPOINTER Memory
+    );
+
+/* Allocate memory. */
+gceSTATUS
+gcoOS_AllocateMemory(
+    IN gcoOS Os,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Memory
+    );
+
+/* Free memory. */
+gceSTATUS
+gcoOS_FreeMemory(
+    IN gcoOS Os,
+    IN gctPOINTER Memory
+    );
+
+/* Allocate contiguous memory. */
+gceSTATUS
+gcoOS_AllocateContiguous(
+    IN gcoOS Os,
+    IN gctBOOL InUserSpace,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctPHYS_ADDR * Physical,
+    OUT gctPOINTER * Logical
+    );
+
+/* Free contiguous memory. */
+gceSTATUS
+gcoOS_FreeContiguous(
+    IN gcoOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    );
+
+#if gcdENABLE_BANK_ALIGNMENT
+gceSTATUS
+gcoOS_GetBankOffsetBytes(
+    IN gcoOS Os,
+    IN gceSURF_TYPE Type,
+    IN gctUINT32 Stride,
+    IN gctUINT32_PTR Bytes
+    );
+#endif
+
+/* Map user memory. */
+gceSTATUS
+gcoOS_MapUserMemory(
+    IN gcoOS Os,
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * Info,
+    OUT gctUINT32_PTR Address
+    );
+
+/* Unmap user memory. */
+gceSTATUS
+gcoOS_UnmapUserMemory(
+    IN gcoOS Os,
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Size,
+    IN gctPOINTER Info,
+    IN gctUINT32 Address
+    );
+
+/* Device I/O Control call to the kernel HAL layer. */
+gceSTATUS
+gcoOS_DeviceControl(
+    IN gcoOS Os,
+    IN gctUINT32 IoControlCode,
+    IN gctPOINTER InputBuffer,
+    IN gctSIZE_T InputBufferSize,
+    IN gctPOINTER OutputBuffer,
+    IN gctSIZE_T OutputBufferSize
+    );
+
+/* Allocate non paged memory. */
+gceSTATUS
+gcoOS_AllocateNonPagedMemory(
+    IN gcoOS Os,
+    IN gctBOOL InUserSpace,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctPHYS_ADDR * Physical,
+    OUT gctPOINTER * Logical
+    );
+
+/* Free non paged memory. */
+gceSTATUS
+gcoOS_FreeNonPagedMemory(
+    IN gcoOS Os,
+    IN gctSIZE_T Bytes,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical
+    );
+
+#define gcmOS_SAFE_FREE(os, mem) \
+       gcoOS_Free(os, mem); \
+       mem = gcvNULL
+
+#define gcmkOS_SAFE_FREE(os, mem) \
+    gckOS_Free(os, mem); \
+       mem = gcvNULL
+
+typedef enum _gceFILE_MODE
+{
+    gcvFILE_CREATE          = 0,
+    gcvFILE_APPEND,
+    gcvFILE_READ,
+    gcvFILE_CREATETEXT,
+    gcvFILE_APPENDTEXT,
+    gcvFILE_READTEXT,
+}
+gceFILE_MODE;
+
+/* Open a file. */
+gceSTATUS
+gcoOS_Open(
+    IN gcoOS Os,
+    IN gctCONST_STRING FileName,
+    IN gceFILE_MODE Mode,
+    OUT gctFILE * File
+    );
+
+/* Close a file. */
+gceSTATUS
+gcoOS_Close(
+    IN gcoOS Os,
+    IN gctFILE File
+    );
+
+/* Read data from a file. */
+gceSTATUS
+gcoOS_Read(
+    IN gcoOS Os,
+    IN gctFILE File,
+    IN gctSIZE_T ByteCount,
+    IN gctPOINTER Data,
+    OUT gctSIZE_T * ByteRead
+    );
+
+/* Write data to a file. */
+gceSTATUS
+gcoOS_Write(
+    IN gcoOS Os,
+    IN gctFILE File,
+    IN gctSIZE_T ByteCount,
+    IN gctCONST_POINTER Data
+    );
+
+/* Flush data to a file. */
+gceSTATUS
+gcoOS_Flush(
+    IN gcoOS Os,
+    IN gctFILE File
+    );
+
+/* Create an endpoint for communication. */
+gceSTATUS
+gcoOS_Socket(
+    IN gcoOS Os,
+    IN gctINT Domain,
+    IN gctINT Type,
+    IN gctINT Protocol,
+    OUT gctINT *SockFd
+    );
+
+/* Close a socket. */
+gceSTATUS
+gcoOS_CloseSocket(
+    IN gcoOS Os,
+    IN gctINT SockFd
+    );
+
+/* Initiate a connection on a socket. */
+gceSTATUS
+gcoOS_Connect(
+    IN gcoOS Os,
+    IN gctINT SockFd,
+    IN gctCONST_POINTER HostName,
+    IN gctUINT Port);
+
+/* Shut down part of connection on a socket. */
+gceSTATUS
+gcoOS_Shutdown(
+    IN gcoOS Os,
+    IN gctINT SockFd,
+    IN gctINT How
+    );
+
+/* Send a message on a socket. */
+gceSTATUS
+gcoOS_Send(
+    IN gcoOS Os,
+    IN gctINT SockFd,
+    IN gctSIZE_T ByteCount,
+    IN gctCONST_POINTER Data,
+    IN gctINT Flags
+    );
+
+/* Initiate a connection on a socket. */
+gceSTATUS
+gcoOS_WaitForSend(
+    IN gcoOS Os,
+    IN gctINT SockFd,
+    IN gctINT Seconds,
+    IN gctINT MicroSeconds);
+
+/* Get environment variable value. */
+gceSTATUS
+gcoOS_GetEnv(
+    IN gcoOS Os,
+    IN gctCONST_STRING VarName,
+    OUT gctSTRING * Value
+    );
+
+/* Get current working directory. */
+gceSTATUS
+gcoOS_GetCwd(
+    IN gcoOS Os,
+       IN gctINT SizeInBytes,
+    OUT gctSTRING Buffer
+    );
+
+/* Get file status info. */
+gceSTATUS
+gcoOS_Stat(
+    IN gcoOS Os,
+    IN gctCONST_STRING FileName,
+    OUT gctPOINTER Buffer
+    );
+
+typedef enum _gceFILE_WHENCE
+{
+    gcvFILE_SEEK_SET,
+    gcvFILE_SEEK_CUR,
+    gcvFILE_SEEK_END
+}
+gceFILE_WHENCE;
+
+/* Set the current position of a file. */
+gceSTATUS
+gcoOS_Seek(
+    IN gcoOS Os,
+    IN gctFILE File,
+    IN gctUINT32 Offset,
+    IN gceFILE_WHENCE Whence
+    );
+
+/* Set the current position of a file. */
+gceSTATUS
+gcoOS_SetPos(
+    IN gcoOS Os,
+    IN gctFILE File,
+    IN gctUINT32 Position
+    );
+
+/* Get the current position of a file. */
+gceSTATUS
+gcoOS_GetPos(
+    IN gcoOS Os,
+    IN gctFILE File,
+    OUT gctUINT32 * Position
+    );
+
+/* Perform a memory copy. */
+gceSTATUS
+gcoOS_MemCopy(
+    IN gctPOINTER Destination,
+    IN gctCONST_POINTER Source,
+    IN gctSIZE_T Bytes
+    );
+
+/* Perform a memory fill. */
+gceSTATUS
+gcoOS_MemFill(
+    IN gctPOINTER Destination,
+    IN gctUINT8 Filler,
+    IN gctSIZE_T Bytes
+    );
+
+/* Zero memory. */
+gceSTATUS
+gcoOS_ZeroMemory(
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Bytes
+    );
+
+/* Find the last occurance of a character inside a string. */
+gceSTATUS
+gcoOS_StrFindReverse(
+    IN gctCONST_STRING String,
+    IN gctINT8 Character,
+    OUT gctSTRING * Output
+    );
+
+gceSTATUS
+gcoOS_StrLen(
+    IN gctCONST_STRING String,
+    OUT gctSIZE_T * Length
+    );
+
+gceSTATUS
+gcoOS_StrDup(
+    IN gcoOS Os,
+    IN gctCONST_STRING String,
+    OUT gctSTRING * Target
+    );
+
+/* Copy a string. */
+gceSTATUS
+gcoOS_StrCopySafe(
+    IN gctSTRING Destination,
+    IN gctSIZE_T DestinationSize,
+    IN gctCONST_STRING Source
+    );
+
+/* Append a string. */
+gceSTATUS
+gcoOS_StrCatSafe(
+    IN gctSTRING Destination,
+    IN gctSIZE_T DestinationSize,
+    IN gctCONST_STRING Source
+    );
+
+/* Compare two strings. */
+gceSTATUS
+gcoOS_StrCmp(
+    IN gctCONST_STRING String1,
+    IN gctCONST_STRING String2
+    );
+
+/* Compare characters of two strings. */
+gceSTATUS
+gcoOS_StrNCmp(
+    IN gctCONST_STRING String1,
+    IN gctCONST_STRING String2,
+    IN gctSIZE_T Count
+    );
+
+/* Convert string to float. */
+gceSTATUS
+gcoOS_StrToFloat(
+    IN gctCONST_STRING String,
+    OUT gctFLOAT * Float
+    );
+
+/* Convert hex string to integer. */
+gceSTATUS gcoOS_HexStrToInt(
+       IN gctCONST_STRING String,
+       OUT gctINT * Int
+       );
+
+/* Convert hex string to float. */
+gceSTATUS gcoOS_HexStrToFloat(
+       IN gctCONST_STRING String,
+       OUT gctFLOAT * Float
+       );
+
+/* Convert string to integer. */
+gceSTATUS
+gcoOS_StrToInt(
+    IN gctCONST_STRING String,
+    OUT gctINT * Int
+    );
+
+gceSTATUS
+gcoOS_MemCmp(
+    IN gctCONST_POINTER Memory1,
+    IN gctCONST_POINTER Memory2,
+    IN gctSIZE_T Bytes
+    );
+
+gceSTATUS
+gcoOS_PrintStrSafe(
+    OUT gctSTRING String,
+    IN gctSIZE_T StringSize,
+    IN OUT gctUINT * Offset,
+    IN gctCONST_STRING Format,
+    ...
+    );
+
+gceSTATUS
+gcoOS_LoadLibrary(
+    IN gcoOS Os,
+    IN gctCONST_STRING Library,
+    OUT gctHANDLE * Handle
+    );
+
+gceSTATUS
+gcoOS_FreeLibrary(
+    IN gcoOS Os,
+    IN gctHANDLE Handle
+    );
+
+gceSTATUS
+gcoOS_GetProcAddress(
+    IN gcoOS Os,
+    IN gctHANDLE Handle,
+    IN gctCONST_STRING Name,
+    OUT gctPOINTER * Function
+    );
+
+gceSTATUS
+gcoOS_Compact(
+    IN gcoOS Os
+    );
+
+#if VIVANTE_PROFILER /*gcdENABLE_PROFILING*/
+gceSTATUS
+gcoOS_ProfileStart(
+    IN gcoOS Os
+    );
+
+gceSTATUS
+gcoOS_ProfileEnd(
+    IN gcoOS Os,
+    IN gctCONST_STRING Title
+    );
+
+gceSTATUS
+gcoOS_SetProfileSetting(
+        IN gcoOS Os,
+        IN gctBOOL Enable,
+        IN gctCONST_STRING FileName
+        );
+#endif
+
+/* Query the video memory. */
+gceSTATUS
+gcoOS_QueryVideoMemory(
+    IN gcoOS Os,
+    OUT gctPHYS_ADDR * InternalAddress,
+    OUT gctSIZE_T * InternalSize,
+    OUT gctPHYS_ADDR * ExternalAddress,
+    OUT gctSIZE_T * ExternalSize,
+    OUT gctPHYS_ADDR * ContiguousAddress,
+    OUT gctSIZE_T * ContiguousSize
+    );
+
+/*----------------------------------------------------------------------------*/
+/*----- Atoms ----------------------------------------------------------------*/
+
+typedef struct gcsATOM * gcsATOM_PTR;
+
+/* Construct an atom. */
+gceSTATUS
+gcoOS_AtomConstruct(
+    IN gcoOS Os,
+    OUT gcsATOM_PTR * Atom
+    );
+
+/* Destroy an atom. */
+gceSTATUS
+gcoOS_AtomDestroy(
+    IN gcoOS Os,
+    IN gcsATOM_PTR Atom
+    );
+
+/* Increment an atom. */
+gceSTATUS
+gcoOS_AtomIncrement(
+    IN gcoOS Os,
+    IN gcsATOM_PTR Atom,
+    OUT gctINT32_PTR OldValue
+    );
+
+/* Decrement an atom. */
+gceSTATUS
+gcoOS_AtomDecrement(
+    IN gcoOS Os,
+    IN gcsATOM_PTR Atom,
+    OUT gctINT32_PTR OldValue
+    );
+
+gctHANDLE
+gcoOS_GetCurrentProcessID(
+    void
+    );
+
+gctHANDLE
+gcoOS_GetCurrentThreadID(
+    void
+    );
+
+/*----------------------------------------------------------------------------*/
+/*----- Time -----------------------------------------------------------------*/
+
+/* Get the number of milliseconds since the system started. */
+gctUINT32
+gcoOS_GetTicks(
+    void
+    );
+
+/* Get time in microseconds. */
+gceSTATUS
+gcoOS_GetTime(
+    gctUINT64_PTR Time
+    );
+
+/* Get CPU usage in microseconds. */
+gceSTATUS
+gcoOS_GetCPUTime(
+    gctUINT64_PTR CPUTime
+    );
+
+/* Get memory usage. */
+gceSTATUS
+gcoOS_GetMemoryUsage(
+    gctUINT32_PTR MaxRSS,
+    gctUINT32_PTR IxRSS,
+    gctUINT32_PTR IdRSS,
+    gctUINT32_PTR IsRSS
+    );
+
+/* Delay a number of microseconds. */
+gceSTATUS
+gcoOS_Delay(
+    IN gcoOS Os,
+    IN gctUINT32 Delay
+    );
+
+/*----------------------------------------------------------------------------*/
+/*----- Threads --------------------------------------------------------------*/
+
+#ifdef _WIN32
+/* Cannot include windows.h here becuase "near" and "far"
+ * which are used in gcsDEPTH_INFO, are defined to nothing in WinDef.h.
+ * So, use the real value of DWORD and WINAPI, instead.
+ * DWORD is unsigned long, and WINAPI is __stdcall.
+ * If these two are change in WinDef.h, the following two typdefs
+ * need to be changed, too.
+ */
+typedef unsigned long gctTHREAD_RETURN;
+typedef unsigned long (__stdcall * gcTHREAD_ROUTINE)(void * Argument);
+#else
+typedef void * gctTHREAD_RETURN;
+typedef void * (* gcTHREAD_ROUTINE)(void *);
+#endif
+
+/* Create a new thread. */
+gceSTATUS
+gcoOS_CreateThread(
+    IN gcoOS Os,
+    IN gcTHREAD_ROUTINE Worker,
+    IN gctPOINTER Argument,
+    OUT gctPOINTER * Thread
+    );
+
+/* Close a thread. */
+gceSTATUS
+gcoOS_CloseThread(
+    IN gcoOS Os,
+    IN gctPOINTER Thread
+    );
+
+/*----------------------------------------------------------------------------*/
+/*----- Mutexes --------------------------------------------------------------*/
+
+/* Create a new mutex. */
+gceSTATUS
+gcoOS_CreateMutex(
+    IN gcoOS Os,
+    OUT gctPOINTER * Mutex
+    );
+
+/* Delete a mutex. */
+gceSTATUS
+gcoOS_DeleteMutex(
+    IN gcoOS Os,
+    IN gctPOINTER Mutex
+    );
+
+/* Acquire a mutex. */
+gceSTATUS
+gcoOS_AcquireMutex(
+    IN gcoOS Os,
+    IN gctPOINTER Mutex,
+    IN gctUINT32 Timeout
+    );
+
+/* Release a mutex. */
+gceSTATUS
+gcoOS_ReleaseMutex(
+    IN gcoOS Os,
+    IN gctPOINTER Mutex
+    );
+
+/*----------------------------------------------------------------------------*/
+/*----- Signals --------------------------------------------------------------*/
+
+/* Create a signal. */
+gceSTATUS
+gcoOS_CreateSignal(
+    IN gcoOS Os,
+    IN gctBOOL ManualReset,
+    OUT gctSIGNAL * Signal
+    );
+
+/* Destroy a signal. */
+gceSTATUS
+gcoOS_DestroySignal(
+    IN gcoOS Os,
+    IN gctSIGNAL Signal
+    );
+
+/* Signal a signal. */
+gceSTATUS
+gcoOS_Signal(
+    IN gcoOS Os,
+    IN gctSIGNAL Signal,
+    IN gctBOOL State
+    );
+
+/* Wait for a signal. */
+gceSTATUS
+gcoOS_WaitSignal(
+    IN gcoOS Os,
+    IN gctSIGNAL Signal,
+    IN gctUINT32 Wait
+    );
+
+/* Map a signal from another process */
+gceSTATUS
+gcoOS_MapSignal(
+    IN gctSIGNAL  RemoteSignal,
+    OUT gctSIGNAL * LocalSignal
+    );
+
+/* Unmap a signal mapped from another process */
+gceSTATUS
+gcoOS_UnmapSignal(
+    IN gctSIGNAL Signal
+    );
+
+/* Write a register. */
+gceSTATUS
+gcoOS_WriteRegister(
+    IN gcoOS Os,
+    IN gctUINT32 Address,
+    IN gctUINT32 Data
+    );
+
+/* Read a register. */
+gceSTATUS
+gcoOS_ReadRegister(
+    IN gcoOS Os,
+    IN gctUINT32 Address,
+    OUT gctUINT32 * Data
+    );
+
+gceSTATUS
+gcoOS_CacheClean(
+    IN gcoOS Os,
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    );
+
+gceSTATUS
+gcoOS_CacheFlush(
+    IN gcoOS Os,
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    );
+
+gceSTATUS
+gcoOS_CacheInvalidate(
+    IN gcoOS Os,
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    );
+
+/*----------------------------------------------------------------------------*/
+/*----- Profile --------------------------------------------------------------*/
+
+gceSTATUS
+gckOS_GetProfileTick(
+    OUT gctUINT64_PTR Tick
+    );
+
+gceSTATUS
+gckOS_QueryProfileTickRate(
+    OUT gctUINT64_PTR TickRate
+    );
+
+gctUINT32
+gckOS_ProfileToMS(
+    IN gctUINT64 Ticks
+    );
+
+gceSTATUS
+gcoOS_GetProfileTick(
+    OUT gctUINT64_PTR Tick
+    );
+
+gceSTATUS
+gcoOS_QueryProfileTickRate(
+    OUT gctUINT64_PTR TickRate
+    );
+
+#define _gcmPROFILE_INIT(prefix, freq, start) \
+    do { \
+        prefix ## OS_QueryProfileTickRate(&(freq)); \
+        prefix ## OS_GetProfileTick(&(start)); \
+    } while (gcvFALSE)
+
+#define _gcmPROFILE_QUERY(prefix, start, ticks) \
+    do { \
+        prefix ## OS_GetProfileTick(&(ticks)); \
+        (ticks) = ((ticks) > (start)) ? ((ticks) - (start)) \
+                                      : (~0ull - (start) + (ticks) + 1); \
+    } while (gcvFALSE)
+
+#if gcdENABLE_PROFILING
+#   define gcmkPROFILE_INIT(freq, start)    _gcmPROFILE_INIT(gck, freq, start)
+#   define gcmkPROFILE_QUERY(start, ticks)  _gcmPROFILE_QUERY(gck, start, ticks)
+#   define gcmPROFILE_INIT(freq, start)     _gcmPROFILE_INIT(gco, freq, start)
+#   define gcmPROFILE_QUERY(start, ticks)   _gcmPROFILE_QUERY(gco, start, ticks)
+#   define gcmPROFILE_ONLY(x)               x
+#   define gcmPROFILE_ELSE(x)               do { } while (gcvFALSE)
+#   define gcmPROFILE_DECLARE_ONLY(x)       x
+#   define gcmPROFILE_DECLARE_ELSE(x)       typedef x
+#else
+#   define gcmkPROFILE_INIT(start, freq)    do { } while (gcvFALSE)
+#   define gcmkPROFILE_QUERY(start, ticks)  do { } while (gcvFALSE)
+#   define gcmPROFILE_INIT(start, freq)     do { } while (gcvFALSE)
+#   define gcmPROFILE_QUERY(start, ticks)   do { } while (gcvFALSE)
+#   define gcmPROFILE_ONLY(x)               do { } while (gcvFALSE)
+#   define gcmPROFILE_ELSE(x)               x
+#   define gcmPROFILE_DECLARE_ONLY(x)       typedef x
+#   define gcmPROFILE_DECLARE_ELSE(x)       x
+#endif
+
+/*******************************************************************************
+**  gcoMATH object
+*/
+
+#define gcdPI                   3.14159265358979323846f
+
+/* Kernel. */
+gctINT
+gckMATH_ModuloInt(
+    IN gctINT X,
+    IN gctINT Y
+    );
+
+/* User. */
+gctUINT32
+gcoMATH_Log2in5dot5(
+    IN gctINT X
+    );
+
+
+gctFLOAT
+gcoMATH_UIntAsFloat(
+    IN gctUINT32 X
+    );
+
+gctUINT32
+gcoMATH_FloatAsUInt(
+    IN gctFLOAT X
+    );
+
+gctBOOL
+gcoMATH_CompareEqualF(
+    IN gctFLOAT X,
+    IN gctFLOAT Y
+    );
+
+gctUINT16
+gcoMATH_UInt8AsFloat16(
+    IN gctUINT8 X
+    );
+
+/******************************************************************************\
+**************************** Coordinate Structures *****************************
+\******************************************************************************/
+
+typedef struct _gcsPOINT
+{
+    gctINT32                    x;
+    gctINT32                    y;
+}
+gcsPOINT;
+
+typedef struct _gcsSIZE
+{
+    gctINT32                    width;
+    gctINT32                    height;
+}
+gcsSIZE;
+
+typedef struct _gcsRECT
+{
+    gctINT32                    left;
+    gctINT32                    top;
+    gctINT32                    right;
+    gctINT32                    bottom;
+}
+gcsRECT;
+
+
+/******************************************************************************\
+********************************* gcoSURF Object ********************************
+\******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/*------------------------------- gcoSURF Common ------------------------------*/
+
+/* Color format classes. */
+typedef enum _gceFORMAT_CLASS
+{
+    gcvFORMAT_CLASS_RGBA        = 4500,
+    gcvFORMAT_CLASS_YUV,
+    gcvFORMAT_CLASS_INDEX,
+    gcvFORMAT_CLASS_LUMINANCE,
+    gcvFORMAT_CLASS_BUMP,
+    gcvFORMAT_CLASS_DEPTH,
+}
+gceFORMAT_CLASS;
+
+/* Special enums for width field in gcsFORMAT_COMPONENT. */
+typedef enum _gceCOMPONENT_CONTROL
+{
+    gcvCOMPONENT_NOTPRESENT     = 0x00,
+    gcvCOMPONENT_DONTCARE       = 0x80,
+    gcvCOMPONENT_WIDTHMASK      = 0x7F,
+    gcvCOMPONENT_ODD            = 0x80
+}
+gceCOMPONENT_CONTROL;
+
+/* Color format component parameters. */
+typedef struct _gcsFORMAT_COMPONENT
+{
+    gctUINT8                    start;
+    gctUINT8                    width;
+}
+gcsFORMAT_COMPONENT;
+
+/* RGBA color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_RGBA
+{
+    gcsFORMAT_COMPONENT         alpha;
+    gcsFORMAT_COMPONENT         red;
+    gcsFORMAT_COMPONENT         green;
+    gcsFORMAT_COMPONENT         blue;
+}
+gcsFORMAT_CLASS_TYPE_RGBA;
+
+/* YUV color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_YUV
+{
+    gcsFORMAT_COMPONENT         y;
+    gcsFORMAT_COMPONENT         u;
+    gcsFORMAT_COMPONENT         v;
+}
+gcsFORMAT_CLASS_TYPE_YUV;
+
+/* Index color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_INDEX
+{
+    gcsFORMAT_COMPONENT         value;
+}
+gcsFORMAT_CLASS_TYPE_INDEX;
+
+/* Luminance color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_LUMINANCE
+{
+    gcsFORMAT_COMPONENT         alpha;
+    gcsFORMAT_COMPONENT         value;
+}
+gcsFORMAT_CLASS_TYPE_LUMINANCE;
+
+/* Bump map color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_BUMP
+{
+    gcsFORMAT_COMPONENT         alpha;
+    gcsFORMAT_COMPONENT         l;
+    gcsFORMAT_COMPONENT         v;
+    gcsFORMAT_COMPONENT         u;
+    gcsFORMAT_COMPONENT         q;
+    gcsFORMAT_COMPONENT         w;
+}
+gcsFORMAT_CLASS_TYPE_BUMP;
+
+/* Depth and stencil format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_DEPTH
+{
+    gcsFORMAT_COMPONENT         depth;
+    gcsFORMAT_COMPONENT         stencil;
+}
+gcsFORMAT_CLASS_TYPE_DEPTH;
+
+/* Format parameters. */
+typedef struct _gcsSURF_FORMAT_INFO
+{
+    /* Format code and class. */
+    gceSURF_FORMAT              format;
+    gceFORMAT_CLASS             fmtClass;
+
+    /* The size of one pixel in bits. */
+    gctUINT8                    bitsPerPixel;
+
+    /* Component swizzle. */
+    gceSURF_SWIZZLE             swizzle;
+
+    /* Some formats have two neighbour pixels interleaved together. */
+    /* To describe such format, set the flag to 1 and add another   */
+    /* like this one describing the odd pixel format.               */
+    gctUINT8                    interleaved;
+
+    /* Format components. */
+    union
+    {
+        gcsFORMAT_CLASS_TYPE_BUMP       bump;
+        gcsFORMAT_CLASS_TYPE_RGBA       rgba;
+        gcsFORMAT_CLASS_TYPE_YUV        yuv;
+        gcsFORMAT_CLASS_TYPE_LUMINANCE  lum;
+        gcsFORMAT_CLASS_TYPE_INDEX      index;
+        gcsFORMAT_CLASS_TYPE_DEPTH      depth;
+    } u;
+}
+gcsSURF_FORMAT_INFO;
+
+/* Frame buffer information. */
+typedef struct _gcsSURF_FRAMEBUFFER
+{
+    gctPOINTER                  logical;
+    gctUINT                     width, height;
+    gctINT                      stride;
+    gceSURF_FORMAT              format;
+}
+gcsSURF_FRAMEBUFFER;
+
+typedef struct _gcsVIDMEM_NODE_SHARED_INFO
+{
+    gctBOOL                     tileStatusDisabled;
+    gcsPOINT                    SrcOrigin;
+    gcsPOINT                    DestOrigin;
+    gcsSIZE                     RectSize;
+    gctUINT32                   clearValue;
+}
+gcsVIDMEM_NODE_SHARED_INFO;
+
+/* Generic pixel component descriptors. */
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XXX8;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XX8X;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_X8XX;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_8XXX;
+
+typedef enum _gceORIENTATION
+{
+    gcvORIENTATION_TOP_BOTTOM,
+    gcvORIENTATION_BOTTOM_TOP,
+}
+gceORIENTATION;
+
+
+/* Construct a new gcoSURF object. */
+gceSTATUS
+gcoSURF_Construct(
+    IN gcoHAL Hal,
+    IN gctUINT Width,
+    IN gctUINT Height,
+    IN gctUINT Depth,
+    IN gceSURF_TYPE Type,
+    IN gceSURF_FORMAT Format,
+    IN gcePOOL Pool,
+    OUT gcoSURF * Surface
+    );
+
+/* Destroy an gcoSURF object. */
+gceSTATUS
+gcoSURF_Destroy(
+    IN gcoSURF Surface
+    );
+
+/* Map user-allocated surface. */
+gceSTATUS
+gcoSURF_MapUserSurface(
+    IN gcoSURF Surface,
+    IN gctUINT Alignment,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Physical
+    );
+
+/* Query vid mem node info. */
+gceSTATUS
+gcoSURF_QueryVidMemNode(
+    IN gcoSURF Surface,
+    OUT gcuVIDMEM_NODE_PTR * Node,
+    OUT gcePOOL * Pool,
+    OUT gctUINT_PTR Bytes
+    );
+
+/* Set the color type of the surface. */
+gceSTATUS
+gcoSURF_SetColorType(
+    IN gcoSURF Surface,
+    IN gceSURF_COLOR_TYPE ColorType
+    );
+
+/* Get the color type of the surface. */
+gceSTATUS
+gcoSURF_GetColorType(
+    IN gcoSURF Surface,
+    OUT gceSURF_COLOR_TYPE *ColorType
+    );
+
+/* Set the surface ration angle. */
+gceSTATUS
+gcoSURF_SetRotation(
+    IN gcoSURF Surface,
+    IN gceSURF_ROTATION Rotation
+    );
+
+gceSTATUS
+gcoSURF_IsValid(
+    IN gcoSURF Surface
+    );
+
+#ifndef VIVANTE_NO_3D
+/* Verify and return the state of the tile status mechanism. */
+gceSTATUS
+gcoSURF_IsTileStatusSupported(
+    IN gcoSURF Surface
+    );
+
+/* Process tile status for the specified surface. */
+gceSTATUS
+gcoSURF_SetTileStatus(
+    IN gcoSURF Surface
+    );
+
+/* Enable tile status for the specified surface. */
+gceSTATUS
+gcoSURF_EnableTileStatus(
+    IN gcoSURF Surface
+    );
+
+/* Disable tile status for the specified surface. */
+gceSTATUS
+gcoSURF_DisableTileStatus(
+    IN gcoSURF Surface,
+    IN gctBOOL Decompress
+    );
+#endif /* VIVANTE_NO_3D */
+
+/* Get surface size. */
+gceSTATUS
+gcoSURF_GetSize(
+    IN gcoSURF Surface,
+    OUT gctUINT * Width,
+    OUT gctUINT * Height,
+    OUT gctUINT * Depth
+    );
+
+/* Get surface aligned sizes. */
+gceSTATUS
+gcoSURF_GetAlignedSize(
+    IN gcoSURF Surface,
+    OUT gctUINT * Width,
+    OUT gctUINT * Height,
+    OUT gctINT * Stride
+    );
+
+/* Get alignments. */
+gceSTATUS
+gcoSURF_GetAlignment(
+    IN gceSURF_TYPE Type,
+    IN gceSURF_FORMAT Format,
+    OUT gctUINT * AddressAlignment,
+    OUT gctUINT * XAlignment,
+    OUT gctUINT * YAlignment
+    );
+
+/* Get surface type and format. */
+gceSTATUS
+gcoSURF_GetFormat(
+    IN gcoSURF Surface,
+    OUT gceSURF_TYPE * Type,
+    OUT gceSURF_FORMAT * Format
+    );
+
+/* Lock the surface. */
+gceSTATUS
+gcoSURF_Lock(
+    IN gcoSURF Surface,
+    IN OUT gctUINT32 * Address,
+    IN OUT gctPOINTER * Memory
+    );
+
+/* Unlock the surface. */
+gceSTATUS
+gcoSURF_Unlock(
+    IN gcoSURF Surface,
+    IN gctPOINTER Memory
+    );
+
+/* Return pixel format parameters. */
+gceSTATUS
+gcoSURF_QueryFormat(
+    IN gceSURF_FORMAT Format,
+    OUT gcsSURF_FORMAT_INFO_PTR * Info
+    );
+
+/* Compute the color pixel mask. */
+gceSTATUS
+gcoSURF_ComputeColorMask(
+    IN gcsSURF_FORMAT_INFO_PTR Format,
+    OUT gctUINT32_PTR ColorMask
+    );
+
+/* Flush the surface. */
+gceSTATUS
+gcoSURF_Flush(
+    IN gcoSURF Surface
+    );
+
+/* Fill surface from it's tile status buffer. */
+gceSTATUS
+gcoSURF_FillFromTile(
+    IN gcoSURF Surface
+    );
+
+/* Fill surface with a value. */
+gceSTATUS
+gcoSURF_Fill(
+    IN gcoSURF Surface,
+    IN gcsPOINT_PTR Origin,
+    IN gcsSIZE_PTR Size,
+    IN gctUINT32 Value,
+    IN gctUINT32 Mask
+    );
+
+/* Alpha blend two surfaces together. */
+gceSTATUS
+gcoSURF_Blend(
+    IN gcoSURF SrcSurface,
+    IN gcoSURF DestSurface,
+    IN gcsPOINT_PTR SrcOrig,
+    IN gcsPOINT_PTR DestOrigin,
+    IN gcsSIZE_PTR Size,
+    IN gceSURF_BLEND_MODE Mode
+    );
+
+/* Create a new gcoSURF wrapper object. */
+gceSTATUS
+gcoSURF_ConstructWrapper(
+    IN gcoHAL Hal,
+    OUT gcoSURF * Surface
+    );
+
+/* Set the underlying buffer for the surface wrapper. */
+gceSTATUS
+gcoSURF_SetBuffer(
+    IN gcoSURF Surface,
+    IN gceSURF_TYPE Type,
+    IN gceSURF_FORMAT Format,
+    IN gctUINT Stride,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Physical
+    );
+
+/* Set the size of the surface in pixels and map the underlying buffer. */
+gceSTATUS
+gcoSURF_SetWindow(
+    IN gcoSURF Surface,
+    IN gctUINT X,
+    IN gctUINT Y,
+    IN gctUINT Width,
+    IN gctUINT Height
+    );
+
+/* Increase reference count of the surface. */
+gceSTATUS
+gcoSURF_ReferenceSurface(
+    IN gcoSURF Surface
+    );
+
+/* Get surface reference count. */
+gceSTATUS
+gcoSURF_QueryReferenceCount(
+    IN gcoSURF Surface,
+    OUT gctINT32 * ReferenceCount
+    );
+
+/* Set surface orientation. */
+gceSTATUS
+gcoSURF_SetOrientation(
+    IN gcoSURF Surface,
+    IN gceORIENTATION Orientation
+    );
+
+/* Query surface orientation. */
+gceSTATUS
+gcoSURF_QueryOrientation(
+    IN gcoSURF Surface,
+    OUT gceORIENTATION * Orientation
+    );
+
+/******************************************************************************\
+********************************* gcoDUMP Object ********************************
+\******************************************************************************/
+
+/* Construct a new gcoDUMP object. */
+gceSTATUS
+gcoDUMP_Construct(
+    IN gcoOS Os,
+    IN gcoHAL Hal,
+    OUT gcoDUMP * Dump
+    );
+
+/* Destroy a gcoDUMP object. */
+gceSTATUS
+gcoDUMP_Destroy(
+    IN gcoDUMP Dump
+    );
+
+/* Enable/disable dumping. */
+gceSTATUS
+gcoDUMP_Control(
+    IN gcoDUMP Dump,
+    IN gctSTRING FileName
+    );
+
+gceSTATUS
+gcoDUMP_IsEnabled(
+    IN gcoDUMP Dump,
+    OUT gctBOOL * Enabled
+    );
+
+/* Add surface. */
+gceSTATUS
+gcoDUMP_AddSurface(
+    IN gcoDUMP Dump,
+    IN gctINT32 Width,
+    IN gctINT32 Height,
+    IN gceSURF_FORMAT PixelFormat,
+    IN gctUINT32 Address,
+    IN gctSIZE_T ByteCount
+    );
+
+/* Mark the beginning of a frame. */
+gceSTATUS
+gcoDUMP_FrameBegin(
+    IN gcoDUMP Dump
+    );
+
+/* Mark the end of a frame. */
+gceSTATUS
+gcoDUMP_FrameEnd(
+    IN gcoDUMP Dump
+    );
+
+/* Dump data. */
+gceSTATUS
+gcoDUMP_DumpData(
+    IN gcoDUMP Dump,
+    IN gceDUMP_TAG Type,
+    IN gctUINT32 Address,
+    IN gctSIZE_T ByteCount,
+    IN gctCONST_POINTER Data
+    );
+
+/* Delete an address. */
+gceSTATUS
+gcoDUMP_Delete(
+    IN gcoDUMP Dump,
+    IN gctUINT32 Address
+    );
+
+
+/******************************************************************************\
+******************************* gcsRECT Structure ******************************
+\******************************************************************************/
+
+/* Initialize rectangle structure. */
+gceSTATUS
+gcsRECT_Set(
+    OUT gcsRECT_PTR Rect,
+    IN gctINT32 Left,
+    IN gctINT32 Top,
+    IN gctINT32 Right,
+    IN gctINT32 Bottom
+    );
+
+/* Return the width of the rectangle. */
+gceSTATUS
+gcsRECT_Width(
+    IN gcsRECT_PTR Rect,
+    OUT gctINT32 * Width
+    );
+
+/* Return the height of the rectangle. */
+gceSTATUS
+gcsRECT_Height(
+    IN gcsRECT_PTR Rect,
+    OUT gctINT32 * Height
+    );
+
+/* Ensure that top left corner is to the left and above the right bottom. */
+gceSTATUS
+gcsRECT_Normalize(
+    IN OUT gcsRECT_PTR Rect
+    );
+
+/* Compare two rectangles. */
+gceSTATUS
+gcsRECT_IsEqual(
+    IN gcsRECT_PTR Rect1,
+    IN gcsRECT_PTR Rect2,
+    OUT gctBOOL * Equal
+    );
+
+/* Compare the sizes of two rectangles. */
+gceSTATUS
+gcsRECT_IsOfEqualSize(
+    IN gcsRECT_PTR Rect1,
+    IN gcsRECT_PTR Rect2,
+    OUT gctBOOL * EqualSize
+    );
+
+gceSTATUS
+gcsRECT_RelativeRotation(
+    IN gceSURF_ROTATION Orientation,
+    IN OUT gceSURF_ROTATION *Relation);
+
+gceSTATUS
+
+gcsRECT_Rotate(
+
+    IN OUT gcsRECT_PTR Rect,
+
+    IN gceSURF_ROTATION Rotation,
+
+    IN gceSURF_ROTATION toRotation,
+
+    IN gctINT32 SurfaceWidth,
+
+    IN gctINT32 SurfaceHeight
+
+    );
+
+/******************************************************************************\
+**************************** gcsBOUNDARY Structure *****************************
+\******************************************************************************/
+
+typedef struct _gcsBOUNDARY
+{
+    gctINT                      x;
+    gctINT                      y;
+    gctINT                      width;
+    gctINT                      height;
+}
+gcsBOUNDARY;
+
+/******************************************************************************\
+********************************* gcoHEAP Object ********************************
+\******************************************************************************/
+
+typedef struct _gcoHEAP *       gcoHEAP;
+
+/* Construct a new gcoHEAP object. */
+gceSTATUS
+gcoHEAP_Construct(
+    IN gcoOS Os,
+    IN gctSIZE_T AllocationSize,
+    OUT gcoHEAP * Heap
+    );
+
+/* Destroy an gcoHEAP object. */
+gceSTATUS
+gcoHEAP_Destroy(
+    IN gcoHEAP Heap
+    );
+
+/* Allocate memory. */
+gceSTATUS
+gcoHEAP_Allocate(
+    IN gcoHEAP Heap,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Node
+    );
+
+/* Free memory. */
+gceSTATUS
+gcoHEAP_Free(
+    IN gcoHEAP Heap,
+    IN gctPOINTER Node
+    );
+
+#if (VIVANTE_PROFILER /*gcdENABLE_PROFILING*/ || gcdDEBUG)
+/* Profile the heap. */
+gceSTATUS
+gcoHEAP_ProfileStart(
+    IN gcoHEAP Heap
+    );
+
+gceSTATUS
+gcoHEAP_ProfileEnd(
+    IN gcoHEAP Heap,
+    IN gctCONST_STRING Title
+    );
+#endif
+
+
+/******************************************************************************\
+******************************* Debugging Macros *******************************
+\******************************************************************************/
+
+void
+gcoOS_SetDebugLevel(
+    IN gctUINT32 Level
+    );
+
+void
+gcoOS_SetDebugZone(
+    IN gctUINT32 Zone
+    );
+
+void
+gcoOS_SetDebugLevelZone(
+    IN gctUINT32 Level,
+    IN gctUINT32 Zone
+    );
+
+void
+gcoOS_SetDebugZones(
+    IN gctUINT32 Zones,
+    IN gctBOOL Enable
+    );
+
+void
+gcoOS_SetDebugFile(
+    IN gctCONST_STRING FileName
+    );
+
+/*******************************************************************************
+**
+**  gcmFATAL
+**
+**      Print a message to the debugger and execute a break point.
+**
+**  ARGUMENTS:
+**
+**      message Message.
+**      ...     Optional arguments.
+*/
+
+void
+gckOS_DebugFatal(
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+void
+gcoOS_DebugFatal(
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+#if gcmIS_DEBUG(gcdDEBUG_FATAL)
+#   define gcmFATAL             gcoOS_DebugFatal
+#   define gcmkFATAL            gckOS_DebugFatal
+#elif gcdHAS_ELLIPSES
+#   define gcmFATAL(...)
+#   define gcmkFATAL(...)
+#else
+    gcmINLINE static void
+    __dummy_fatal(
+        IN gctCONST_STRING Message,
+        ...
+        )
+    {
+    }
+#   define gcmFATAL             __dummy_fatal
+#   define gcmkFATAL            __dummy_fatal
+#endif
+
+#define gcmENUM2TEXT(e)         case e: return #e
+
+/*******************************************************************************
+**
+**  gcmTRACE
+**
+**      Print a message to the debugfer if the correct level has been set.  In
+**      retail mode this macro does nothing.
+**
+**  ARGUMENTS:
+**
+**      level   Level of message.
+**      message Message.
+**      ...     Optional arguments.
+*/
+#define gcvLEVEL_NONE           -1
+#define gcvLEVEL_ERROR          0
+#define gcvLEVEL_WARNING        1
+#define gcvLEVEL_INFO           2
+#define gcvLEVEL_VERBOSE        3
+
+void
+gckOS_DebugTrace(
+    IN gctUINT32 Level,
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+void
+gckOS_DebugTraceN(
+    IN gctUINT32 Level,
+    IN gctUINT ArgumentSize,
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+void
+gcoOS_DebugTrace(
+    IN gctUINT32 Level,
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+#   define gcmTRACE             gcoOS_DebugTrace
+#   define gcmkTRACE            gckOS_DebugTrace
+#   define gcmkTRACE_N          gckOS_DebugTraceN
+#elif gcdHAS_ELLIPSES
+#   define gcmTRACE(...)
+#   define gcmkTRACE(...)
+#   define gcmkTRACE_N(...)
+#else
+    gcmINLINE static void
+    __dummy_trace(
+        IN gctUINT32 Level,
+        IN gctCONST_STRING Message,
+        ...
+        )
+    {
+    }
+
+    gcmINLINE static void
+    __dummy_trace_n(
+        IN gctUINT32 Level,
+        IN gctUINT ArgumentSize,
+        IN gctCONST_STRING Message,
+        ...
+        )
+    {
+    }
+
+#   define gcmTRACE             __dummy_trace
+#   define gcmkTRACE            __dummy_trace
+#   define gcmkTRACE_N          __dummy_trace_n
+#endif
+
+/* Zones common for kernel and user. */
+#define gcvZONE_OS              (1 << 0)
+#define gcvZONE_HARDWARE        (1 << 1)
+#define gcvZONE_HEAP            (1 << 2)
+#define gcvZONE_SIGNAL          (1 << 27)
+
+/* Kernel zones. */
+#define gcvZONE_KERNEL          (1 << 3)
+#define gcvZONE_VIDMEM          (1 << 4)
+#define gcvZONE_COMMAND         (1 << 5)
+#define gcvZONE_DRIVER          (1 << 6)
+#define gcvZONE_CMODEL          (1 << 7)
+#define gcvZONE_MMU             (1 << 8)
+#define gcvZONE_EVENT           (1 << 9)
+#define gcvZONE_DEVICE          (1 << 10)
+#define gcvZONE_DATABASE        (1 << 11)
+#define gcvZONE_INTERRUPT       (1 << 12)
+
+/* User zones. */
+#define gcvZONE_HAL             (1 << 3)
+#define gcvZONE_BUFFER          (1 << 4)
+#define gcvZONE_CONTEXT         (1 << 5)
+#define gcvZONE_SURFACE         (1 << 6)
+#define gcvZONE_INDEX           (1 << 7)
+#define gcvZONE_STREAM          (1 << 8)
+#define gcvZONE_TEXTURE         (1 << 9)
+#define gcvZONE_2D              (1 << 10)
+#define gcvZONE_3D              (1 << 11)
+#define gcvZONE_COMPILER        (1 << 12)
+#define gcvZONE_MEMORY          (1 << 13)
+#define gcvZONE_STATE           (1 << 14)
+#define gcvZONE_AUX             (1 << 15)
+#define gcvZONE_VERTEX          (1 << 16)
+#define gcvZONE_CL              (1 << 17)
+#define gcvZONE_COMPOSITION     (1 << 17)
+#define gcvZONE_VG              (1 << 18)
+#define gcvZONE_IMAGE           (1 << 19)
+#define gcvZONE_UTILITY         (1 << 20)
+#define gcvZONE_PARAMETERS      (1 << 21)
+
+/* API definitions. */
+#define gcvZONE_API_HAL         (0 << 28)
+#define gcvZONE_API_EGL         (1 << 28)
+#define gcvZONE_API_ES11        (2 << 28)
+#define gcvZONE_API_ES20        (3 << 28)
+#define gcvZONE_API_VG11        (4 << 28)
+#define gcvZONE_API_GL          (5 << 28)
+#define gcvZONE_API_DFB         (6 << 28)
+#define gcvZONE_API_GDI         (7 << 28)
+#define gcvZONE_API_D3D         (8 << 28)
+
+#define gcmZONE_GET_API(zone)   ((zone) >> 28)
+#define gcdZONE_MASK            0x0FFFFFFF
+
+/* Handy zones. */
+#define gcvZONE_NONE            0
+#define gcvZONE_ALL             gcdZONE_MASK
+
+/*******************************************************************************
+**
+**  gcmTRACE_ZONE
+**
+**      Print a message to the debugger if the correct level and zone has been
+**      set.  In retail mode this macro does nothing.
+**
+**  ARGUMENTS:
+**
+**      Level   Level of message.
+**      Zone    Zone of message.
+**      Message Message.
+**      ...     Optional arguments.
+*/
+
+void
+gckOS_DebugTraceZone(
+    IN gctUINT32 Level,
+    IN gctUINT32 Zone,
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+void
+gckOS_DebugTraceZoneN(
+    IN gctUINT32 Level,
+    IN gctUINT32 Zone,
+    IN gctUINT ArgumentSize,
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+void
+gcoOS_DebugTraceZone(
+    IN gctUINT32 Level,
+    IN gctUINT32 Zone,
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+#   define gcmTRACE_ZONE            gcoOS_DebugTraceZone
+#   define gcmkTRACE_ZONE           gckOS_DebugTraceZone
+#   define gcmkTRACE_ZONE_N         gckOS_DebugTraceZoneN
+#elif gcdHAS_ELLIPSES
+#   define gcmTRACE_ZONE(...)
+#   define gcmkTRACE_ZONE(...)
+#   define gcmkTRACE_ZONE_N(...)
+#else
+    gcmINLINE static void
+    __dummy_trace_zone(
+        IN gctUINT32 Level,
+        IN gctUINT32 Zone,
+        IN gctCONST_STRING Message,
+        ...
+        )
+    {
+    }
+
+    gcmINLINE static void
+    __dummy_trace_zone_n(
+        IN gctUINT32 Level,
+        IN gctUINT32 Zone,
+        IN gctUINT ArgumentSize,
+        IN gctCONST_STRING Message,
+        ...
+        )
+    {
+    }
+
+#   define gcmTRACE_ZONE            __dummy_trace_zone
+#   define gcmkTRACE_ZONE           __dummy_trace_zone
+#   define gcmkTRACE_ZONE_N         __dummy_trace_zone_n
+#endif
+
+/*******************************************************************************
+**
+**  gcmDEBUG_ONLY
+**
+**      Execute a statement or function only in DEBUG mode.
+**
+**  ARGUMENTS:
+**
+**      f       Statement or function to execute.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+#   define gcmDEBUG_ONLY(f)         f
+#else
+#   define gcmDEBUG_ONLY(f)
+#endif
+
+/*******************************************************************************
+**
+**  gcmSTACK_PUSH
+**  gcmSTACK_POP
+**  gcmSTACK_DUMP
+**
+**      Push or pop a function with entry arguments on the trace stack.
+**
+**  ARGUMENTS:
+**
+**      Function    Name of function.
+**      Line        Line number.
+**      Text        Optional text.
+**      ...         Optional arguments for text.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_STACK)
+    void
+    gcoOS_StackPush(
+        IN gctCONST_STRING Function,
+        IN gctINT Line,
+        IN gctCONST_STRING Text,
+        ...
+        );
+    void
+    gcoOS_StackPop(
+        IN gctCONST_STRING Function
+        );
+    void
+    gcoOS_StackDump(
+        void
+        );
+#   define gcmSTACK_PUSH            gcoOS_StackPush
+#   define gcmSTACK_POP             gcoOS_StackPop
+#   define gcmSTACK_DUMP            gcoOS_StackDump
+#elif gcdHAS_ELLIPSES
+#   define gcmSTACK_PUSH(...)       do { } while (0)
+#   define gcmSTACK_POP(Function)   do { } while (0)
+#   define gcmSTACK_DUMP()          do { } while (0)
+#else
+    gcmINLINE static void
+    __dummy_stack_push(
+        IN gctCONST_STRING Function,
+        IN gctINT Line,
+        IN gctCONST_STRING Text, ...
+        )
+    {
+    }
+#   define gcmSTACK_PUSH            __dummy_stack_push
+#   define gcmSTACK_POP(Function)   do { } while (0)
+#   define gcmSTACK_DUMP()          do { } while (0)
+#endif
+
+/******************************************************************************\
+******************************** Logging Macros ********************************
+\******************************************************************************/
+
+#define gcdHEADER_LEVEL             gcvLEVEL_VERBOSE
+
+#if gcdENABLE_PROFILING
+void
+gcoOS_ProfileDB(
+    IN gctCONST_STRING Function,
+    IN OUT gctBOOL_PTR Initialized
+    );
+
+#define gcmHEADER() \
+    static gctBOOL __profile__initialized__ = gcvFALSE; \
+    gcmSTACK_PUSH(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+    gcoOS_ProfileDB(__FUNCTION__, &__profile__initialized__)
+#define gcmHEADER_ARG(...) \
+    static gctBOOL __profile__initialized__ = gcvFALSE; \
+    gcmSTACK_PUSH(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
+    gcoOS_ProfileDB(__FUNCTION__, &__profile__initialized__)
+#define gcmFOOTER() \
+    gcmSTACK_POP(__FUNCTION__); \
+    gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
+#define gcmFOOTER_NO() \
+    gcmSTACK_POP(__FUNCTION__); \
+    gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
+#define gcmFOOTER_ARG(...) \
+    gcmSTACK_POP(__FUNCTION__); \
+    gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
+#define gcmFOOTER_KILL() \
+    gcmSTACK_POP(__FUNCTION__); \
+    gcoOS_ProfileDB(gcvNULL, gcvNULL)
+
+#else /* gcdENABLE_PROFILING */
+
+#if gcdHAS_ELLIPSES
+#define gcmHEADER() \
+    gctINT8 __user__ = 1; \
+    gctINT8_PTR __user_ptr__ = &__user__; \
+    gcmSTACK_PUSH(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+    gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                  "++%s(%d)", __FUNCTION__, __LINE__)
+#else
+    gcmINLINE static void
+    __dummy_header(void)
+    {
+    }
+#   define gcmHEADER                   __dummy_header
+#endif
+
+#if gcdHAS_ELLIPSES
+#   define gcmHEADER_ARG(Text, ...) \
+        gctINT8 __user__ = 1; \
+        gctINT8_PTR __user_ptr__ = &__user__; \
+        gcmSTACK_PUSH(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
+        gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                      "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+    gcmINLINE static void
+    __dummy_header_arg(
+        IN gctCONST_STRING Text,
+        ...
+        )
+    {
+    }
+#   define gcmHEADER_ARG                __dummy_header_arg
+#endif
+
+#if gcdHAS_ELLIPSES
+#   define gcmFOOTER() \
+    gcmSTACK_POP(__FUNCTION__); \
+    gcmPROFILE_ONLY(gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                                  "--%s(%d) [%llu,%llu]: status=%d(%s)", \
+                                  __FUNCTION__, __LINE__, \
+                                  __ticks__, __total__, \
+                                  status, gcoOS_DebugStatus2Name(status))); \
+    gcmPROFILE_ELSE(gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                                  "--%s(%d): status=%d(%s)", \
+                                  __FUNCTION__, __LINE__, \
+                                  status, gcoOS_DebugStatus2Name(status))); \
+    *__user_ptr__ -= 1
+#else
+    gcmINLINE static void
+    __dummy_footer(void)
+    {
+    }
+#   define gcmFOOTER                    __dummy_footer
+#endif
+
+#if gcdHAS_ELLIPSES
+#define gcmFOOTER_NO() \
+    gcmSTACK_POP(__FUNCTION__); \
+    gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                  "--%s(%d)", __FUNCTION__, __LINE__); \
+    *__user_ptr__ -= 1
+#else
+    gcmINLINE static void
+    __dummy_footer_no(void)
+    {
+    }
+#   define gcmFOOTER_NO                 __dummy_footer_no
+#endif
+
+#if gcdHAS_ELLIPSES
+#define gcmFOOTER_KILL() \
+    gcmSTACK_POP(__FUNCTION__); \
+    gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                  "--%s(%d)", __FUNCTION__, __LINE__); \
+    *__user_ptr__ -= 1
+#else
+    gcmINLINE static void
+    __dummy_footer_kill(void)
+    {
+    }
+#   define gcmFOOTER_KILL               __dummy_footer_kill
+#endif
+
+#if gcdHAS_ELLIPSES
+#   define gcmFOOTER_ARG(Text, ...) \
+        gcmSTACK_POP(__FUNCTION__); \
+        gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                      "--%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__); \
+        *__user_ptr__ -= 1
+#else
+    gcmINLINE static void
+    __dummy_footer_arg(
+        IN gctCONST_STRING Text,
+        ...
+        )
+    {
+    }
+#   define gcmFOOTER_ARG                __dummy_footer_arg
+#endif
+
+#endif /* gcdENABLE_PROFILING */
+
+#if gcdHAS_ELLIPSES
+#define gcmkHEADER() \
+    gctINT8 __kernel__ = 1; \
+    gctINT8_PTR __kernel_ptr__ = &__kernel__; \
+    gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                   "++%s(%d)", __FUNCTION__, __LINE__)
+#else
+    gcmINLINE static void
+    __dummy_kheader(void)
+    {
+    }
+#   define gcmkHEADER                  __dummy_kheader
+#endif
+
+#if gcdHAS_ELLIPSES
+#   define gcmkHEADER_ARG(Text, ...) \
+        gctINT8 __kernel__ = 1; \
+        gctINT8_PTR __kernel_ptr__ = &__kernel__; \
+        gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                       "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+    gcmINLINE static void
+    __dummy_kheader_arg(
+        IN gctCONST_STRING Text,
+        ...
+        )
+    {
+    }
+#   define gcmkHEADER_ARG               __dummy_kheader_arg
+#endif
+
+#if gcdHAS_ELLIPSES
+#define gcmkFOOTER() \
+    gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                   "--%s(%d): status=%d(%s)", \
+                   __FUNCTION__, __LINE__, status, gckOS_DebugStatus2Name(status)); \
+    *__kernel_ptr__ -= 1
+#else
+    gcmINLINE static void
+    __dummy_kfooter(void)
+    {
+    }
+#   define gcmkFOOTER                   __dummy_kfooter
+#endif
+
+#if gcdHAS_ELLIPSES
+#define gcmkFOOTER_NO() \
+    gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                   "--%s(%d)", __FUNCTION__, __LINE__); \
+    *__kernel_ptr__ -= 1
+#else
+    gcmINLINE static void
+    __dummy_kfooter_no(void)
+    {
+    }
+#   define gcmkFOOTER_NO                __dummy_kfooter_no
+#endif
+
+#if gcdHAS_ELLIPSES
+#   define gcmkFOOTER_ARG(Text, ...) \
+        gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                       "--%s(%d): " Text, \
+                       __FUNCTION__, __LINE__, __VA_ARGS__); \
+        *__kernel_ptr__ -= 1
+#else
+    gcmINLINE static void
+    __dummy_kfooter_arg(
+        IN gctCONST_STRING Text,
+        ...
+        )
+    {
+    }
+#   define gcmkFOOTER_ARG               __dummy_kfooter_arg
+#endif
+
+#define gcmOPT_VALUE(ptr)           (((ptr) == gcvNULL) ? 0 : *(ptr))
+#define gcmOPT_POINTER(ptr)         (((ptr) == gcvNULL) ? gcvNULL : *(ptr))
+#define gcmOPT_STRING(ptr)          (((ptr) == gcvNULL) ? "(nil)" : (ptr))
+
+void
+gckOS_Print(
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+void
+gckOS_PrintN(
+    IN gctUINT ArgumentSize,
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+void
+gckOS_CopyPrint(
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+void
+gcoOS_Print(
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+#define gcmPRINT                gcoOS_Print
+#define gcmkPRINT               gckOS_Print
+#define gcmkPRINT_N             gckOS_PrintN
+
+#if gcdPRINT_VERSION
+#   define gcmPRINT_VERSION()       do { \
+                                        _gcmPRINT_VERSION(gcm); \
+                                        gcmSTACK_DUMP(); \
+                                    } while (0)
+#   define gcmkPRINT_VERSION()      _gcmPRINT_VERSION(gcmk)
+#   define _gcmPRINT_VERSION(prefix) \
+        prefix##TRACE(gcvLEVEL_ERROR, \
+                      "Vivante HAL version %d.%d.%d build %d  %s  %s", \
+                      gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, \
+                      gcvVERSION_BUILD, gcvVERSION_DATE, gcvVERSION_TIME )
+#else
+#   define gcmPRINT_VERSION()       do { gcmSTACK_DUMP(); } while (gcvFALSE)
+#   define gcmkPRINT_VERSION()      do { } while (gcvFALSE)
+#endif
+
+typedef enum _gceDUMP_BUFFER
+{
+    gceDUMP_BUFFER_CONTEXT,
+    gceDUMP_BUFFER_USER,
+    gceDUMP_BUFFER_KERNEL,
+    gceDUMP_BUFFER_LINK,
+    gceDUMP_BUFFER_WAITLINK,
+    gceDUMP_BUFFER_FROM_USER,
+}
+gceDUMP_BUFFER;
+
+void
+gckOS_DumpBuffer(
+    IN gckOS Os,
+    IN gctPOINTER Buffer,
+    IN gctUINT Size,
+    IN gceDUMP_BUFFER Type,
+    IN gctBOOL CopyMessage
+    );
+
+#define gcmkDUMPBUFFER          gckOS_DumpBuffer
+
+#if gcdDUMP_COMMAND
+#   define gcmkDUMPCOMMAND(Os, Buffer, Size, Type, CopyMessage) \
+        gcmkDUMPBUFFER(Os, Buffer, Size, Type, CopyMessage)
+#else
+#   define gcmkDUMPCOMMAND(Os, Buffer, Size, Type, CopyMessage)
+#endif
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+
+void
+gckOS_DebugFlush(
+    gctCONST_STRING CallerName,
+    gctUINT LineNumber,
+    gctUINT32 DmaAddress
+    );
+
+#   define gcmkDEBUGFLUSH(DmaAddress) \
+        gckOS_DebugFlush(__FUNCTION__, __LINE__, DmaAddress)
+#else
+#   define gcmkDEBUGFLUSH(DmaAddress)
+#endif
+
+
+/*******************************************************************************
+**
+**  gcmDUMP
+**
+**      Print a dump message.
+**
+**  ARGUMENTS:
+**
+**      gctSTRING   Message.
+**
+**      ...         Optional arguments.
+*/
+#if gcdDUMP
+    gceSTATUS
+    gcfDump(
+        IN gcoOS Os,
+        IN gctCONST_STRING String,
+        ...
+        );
+#  define gcmDUMP               gcfDump
+#elif gcdHAS_ELLIPSES
+#  define gcmDUMP(...)
+#else
+    gcmINLINE static void
+    __dummy_dump(
+        IN gcoOS Os,
+        IN gctCONST_STRING Message,
+        ...
+        )
+    {
+    }
+#  define gcmDUMP               __dummy_dump
+#endif
+
+/*******************************************************************************
+**
+**  gcmDUMP_DATA
+**
+**      Add data to the dump.
+**
+**  ARGUMENTS:
+**
+**      gctSTRING Tag
+**          Tag for dump.
+**
+**      gctPOINTER Logical
+**          Logical address of buffer.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes.
+*/
+
+#if gcdDUMP || gcdDUMP_COMMAND
+    gceSTATUS
+    gcfDumpData(
+        IN gcoOS Os,
+        IN gctSTRING Tag,
+        IN gctPOINTER Logical,
+        IN gctSIZE_T Bytes
+        );
+#  define gcmDUMP_DATA          gcfDumpData
+#elif gcdHAS_ELLIPSES
+#  define gcmDUMP_DATA(...)
+#else
+    gcmINLINE static void
+    __dummy_dump_data(
+        IN gcoOS Os,
+        IN gctSTRING Tag,
+        IN gctPOINTER Logical,
+        IN gctSIZE_T Bytes
+        )
+    {
+    }
+#  define gcmDUMP_DATA          __dummy_dump_data
+#endif
+
+/*******************************************************************************
+**
+**  gcmDUMP_BUFFER
+**
+**      Print a buffer to the dump.
+**
+**  ARGUMENTS:
+**
+**      gctSTRING Tag
+**          Tag for dump.
+**
+**      gctUINT32 Physical
+**          Physical address of buffer.
+**
+**      gctPOINTER Logical
+**          Logical address of buffer.
+**
+**      gctUINT32 Offset
+**          Offset into buffer.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes.
+*/
+
+#if gcdDUMP || gcdDUMP_COMMAND
+gceSTATUS
+gcfDumpBuffer(
+    IN gcoOS Os,
+    IN gctSTRING Tag,
+    IN gctUINT32 Physical,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Offset,
+    IN gctSIZE_T Bytes
+    );
+#   define gcmDUMP_BUFFER       gcfDumpBuffer
+#elif gcdHAS_ELLIPSES
+#   define gcmDUMP_BUFFER(...)
+#else
+    gcmINLINE static void
+    __dummy_dump_buffer(
+        IN gcoOS Os,
+        IN gctSTRING Tag,
+        IN gctUINT32 Physical,
+        IN gctPOINTER Logical,
+        IN gctUINT32 Offset,
+        IN gctSIZE_T Bytes
+        )
+    {
+    }
+#   define gcmDUMP_BUFFER       __dummy_dump_buffer
+#endif
+
+/*******************************************************************************
+**
+**  gcmDUMP_API
+**
+**      Print a dump message for a high level API prefixed by the function name.
+**
+**  ARGUMENTS:
+**
+**      gctSTRING   Message.
+**
+**      ...         Optional arguments.
+*/
+#if gcdDUMP_API
+    gceSTATUS
+    gcfDumpApi(
+        IN gctCONST_STRING String,
+        ...
+        );
+#   define gcmDUMP_API           gcfDumpApi
+#elif gcdHAS_ELLIPSES
+#   define gcmDUMP_API(...)
+#else
+    gcmINLINE static void
+    __dummy_dump_api(
+        IN gctCONST_STRING Message,
+        ...
+        )
+    {
+    }
+#  define gcmDUMP_API           __dummy_dump_api
+#endif
+
+/*******************************************************************************
+**
+**  gcmDUMP_API_ARRAY
+**
+**      Print an array of data.
+**
+**  ARGUMENTS:
+**
+**      gctUINT32_PTR   Pointer to array.
+**      gctUINT32       Size.
+*/
+#if gcdDUMP_API
+    gceSTATUS
+    gcfDumpArray(
+        IN gctCONST_POINTER Data,
+        IN gctUINT32 Size
+    );
+#   define gcmDUMP_API_ARRAY        gcfDumpArray
+#elif gcdHAS_ELLIPSES
+#   define gcmDUMP_API_ARRAY(...)
+#else
+    gcmINLINE static void
+    __dummy_dump_api_array(
+        IN gctCONST_POINTER Data,
+        IN gctUINT32 Size
+        )
+    {
+    }
+#   define gcmDUMP_API_ARRAY        __dummy_dump_api_array
+#endif
+
+/*******************************************************************************
+**
+**  gcmDUMP_API_ARRAY_TOKEN
+**
+**      Print an array of data terminated by a token.
+**
+**  ARGUMENTS:
+**
+**      gctUINT32_PTR   Pointer to array.
+**      gctUINT32       Termination.
+*/
+#if gcdDUMP_API
+    gceSTATUS
+    gcfDumpArrayToken(
+        IN gctCONST_POINTER Data,
+        IN gctUINT32 Termination
+    );
+#   define gcmDUMP_API_ARRAY_TOKEN  gcfDumpArrayToken
+#elif gcdHAS_ELLIPSES
+#   define gcmDUMP_API_ARRAY_TOKEN(...)
+#else
+    gcmINLINE static void
+    __dummy_dump_api_array_token(
+        IN gctCONST_POINTER Data,
+        IN gctUINT32 Termination
+        )
+    {
+    }
+#   define gcmDUMP_API_ARRAY_TOKEN  __dummy_dump_api_array_token
+#endif
+
+/*******************************************************************************
+**
+**  gcmDUMP_API_DATA
+**
+**      Print an array of bytes.
+**
+**  ARGUMENTS:
+**
+**      gctCONST_POINTER    Pointer to array.
+**      gctSIZE_T           Size.
+*/
+#if gcdDUMP_API
+    gceSTATUS
+    gcfDumpApiData(
+        IN gctCONST_POINTER Data,
+        IN gctSIZE_T Size
+    );
+#   define gcmDUMP_API_DATA         gcfDumpApiData
+#elif gcdHAS_ELLIPSES
+#   define gcmDUMP_API_DATA(...)
+#else
+    gcmINLINE static void
+    __dummy_dump_api_data(
+        IN gctCONST_POINTER Data,
+        IN gctSIZE_T Size
+        )
+    {
+    }
+#   define gcmDUMP_API_DATA         __dummy_dump_api_data
+#endif
+
+/*******************************************************************************
+**
+**  gcmTRACE_RELEASE
+**
+**      Print a message to the shader debugger.
+**
+**  ARGUMENTS:
+**
+**      message Message.
+**      ...     Optional arguments.
+*/
+
+#define gcmTRACE_RELEASE                gcoOS_DebugShaderTrace
+
+void
+gcoOS_DebugShaderTrace(
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+void
+gcoOS_SetDebugShaderFiles(
+    IN gctCONST_STRING VSFileName,
+    IN gctCONST_STRING FSFileName
+    );
+
+void
+gcoOS_SetDebugShaderFileType(
+    IN gctUINT32 ShaderType
+    );
+
+void
+gcoOS_EnableDebugBuffer(
+    IN gctBOOL Enable
+    );
+
+/*******************************************************************************
+**
+**  gcmBREAK
+**
+**      Break into the debugger.  In retail mode this macro does nothing.
+**
+**  ARGUMENTS:
+**
+**      None.
+*/
+
+void
+gcoOS_DebugBreak(
+    void
+    );
+
+void
+gckOS_DebugBreak(
+    void
+    );
+
+#if gcmIS_DEBUG(gcdDEBUG_BREAK)
+#   define gcmBREAK             gcoOS_DebugBreak
+#   define gcmkBREAK            gckOS_DebugBreak
+#else
+#   define gcmBREAK()
+#   define gcmkBREAK()
+#endif
+
+/*******************************************************************************
+**
+**  gcmASSERT
+**
+**      Evaluate an expression and break into the debugger if the expression
+**      evaluates to false.  In retail mode this macro does nothing.
+**
+**  ARGUMENTS:
+**
+**      exp     Expression to evaluate.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
+#   define _gcmASSERT(prefix, exp) \
+        do \
+        { \
+            if (!(exp)) \
+            { \
+                prefix##TRACE(gcvLEVEL_ERROR, \
+                              #prefix "ASSERT at %s(%d)", \
+                              __FUNCTION__, __LINE__); \
+                prefix##TRACE(gcvLEVEL_ERROR, \
+                              "(%s)", #exp); \
+                prefix##BREAK(); \
+            } \
+        } \
+        while (gcvFALSE)
+#   define gcmASSERT(exp)           _gcmASSERT(gcm, exp)
+#   define gcmkASSERT(exp)          _gcmASSERT(gcmk, exp)
+#else
+#   define gcmASSERT(exp)
+#   define gcmkASSERT(exp)
+#endif
+
+/*******************************************************************************
+**
+**  gcmVERIFY
+**
+**      Verify if an expression returns true.  If the expression does not
+**      evaluates to true, an assertion will happen in debug mode.
+**
+**  ARGUMENTS:
+**
+**      exp     Expression to evaluate.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
+#   define gcmVERIFY(exp)           gcmASSERT(exp)
+#   define gcmkVERIFY(exp)          gcmkASSERT(exp)
+#else
+#   define gcmVERIFY(exp)           exp
+#   define gcmkVERIFY(exp)          exp
+#endif
+
+/*******************************************************************************
+**
+**  gcmVERIFY_OK
+**
+**      Verify a fucntion returns gcvSTATUS_OK.  If the function does not return
+**      gcvSTATUS_OK, an assertion will happen in debug mode.
+**
+**  ARGUMENTS:
+**
+**      func    Function to evaluate.
+*/
+
+void
+gcoOS_Verify(
+    IN gceSTATUS Status
+    );
+
+void
+gckOS_Verify(
+    IN gceSTATUS Status
+    );
+
+#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
+#   define gcmVERIFY_OK(func) \
+        do \
+        { \
+            gceSTATUS verifyStatus = func; \
+            gcoOS_Verify(verifyStatus); \
+            if (verifyStatus != gcvSTATUS_OK) \
+            { \
+                gcmTRACE( \
+                    gcvLEVEL_ERROR, \
+                    "gcmVERIFY_OK(%d): function returned %d", \
+                    __LINE__, verifyStatus \
+                    ); \
+            } \
+            gcmASSERT(verifyStatus == gcvSTATUS_OK); \
+        } \
+        while (gcvFALSE)
+#   define gcmkVERIFY_OK(func) \
+        do \
+        { \
+            gceSTATUS verifyStatus = func; \
+            if (verifyStatus != gcvSTATUS_OK) \
+            { \
+                gcmkTRACE( \
+                    gcvLEVEL_ERROR, \
+                    "gcmkVERIFY_OK(%d): function returned %d", \
+                    __LINE__, verifyStatus \
+                    ); \
+            } \
+            gckOS_Verify(verifyStatus); \
+            gcmkASSERT(verifyStatus == gcvSTATUS_OK); \
+        } \
+        while (gcvFALSE)
+#else
+#   define gcmVERIFY_OK(func)       func
+#   define gcmkVERIFY_OK(func)      func
+#endif
+
+gctCONST_STRING
+gcoOS_DebugStatus2Name(
+    gceSTATUS status
+    );
+
+gctCONST_STRING
+gckOS_DebugStatus2Name(
+    gceSTATUS status
+    );
+
+/*******************************************************************************
+**
+**  gcmERR_BREAK
+**
+**      Executes a break statement on error.
+**
+**  ASSUMPTIONS:
+**
+**      'status' variable of gceSTATUS type must be defined.
+**
+**  ARGUMENTS:
+**
+**      func    Function to evaluate.
+*/
+#define _gcmERR_BREAK(prefix, func) \
+    status = func; \
+    if (gcmIS_ERROR(status)) \
+    { \
+        prefix##PRINT_VERSION(); \
+        prefix##TRACE(gcvLEVEL_ERROR, \
+            #prefix "ERR_BREAK: status=%d(%s) @ %s(%d)", \
+            status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+        break; \
+    } \
+    do { } while (gcvFALSE)
+#define _gcmkERR_BREAK(prefix, func) \
+    status = func; \
+    if (gcmIS_ERROR(status)) \
+    { \
+        prefix##PRINT_VERSION(); \
+        prefix##TRACE(gcvLEVEL_ERROR, \
+            #prefix "ERR_BREAK: status=%d(%s) @ %s(%d)", \
+            status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+        break; \
+    } \
+    do { } while (gcvFALSE)
+#define gcmERR_BREAK(func)          _gcmERR_BREAK(gcm, func)
+#define gcmkERR_BREAK(func)         _gcmkERR_BREAK(gcmk, func)
+
+/*******************************************************************************
+**
+**  gcmERR_RETURN
+**
+**      Executes a return on error.
+**
+**  ASSUMPTIONS:
+**
+**      'status' variable of gceSTATUS type must be defined.
+**
+**  ARGUMENTS:
+**
+**      func    Function to evaluate.
+*/
+#define _gcmERR_RETURN(prefix, func) \
+    status = func; \
+    if (gcmIS_ERROR(status)) \
+    { \
+        prefix##PRINT_VERSION(); \
+        prefix##TRACE(gcvLEVEL_ERROR, \
+            #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
+            status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+        prefix##FOOTER(); \
+        return status; \
+    } \
+    do { } while (gcvFALSE)
+#define _gcmkERR_RETURN(prefix, func) \
+    status = func; \
+    if (gcmIS_ERROR(status)) \
+    { \
+        prefix##PRINT_VERSION(); \
+        prefix##TRACE(gcvLEVEL_ERROR, \
+            #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
+            status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+        prefix##FOOTER(); \
+        return status; \
+    } \
+    do { } while (gcvFALSE)
+#define gcmERR_RETURN(func)         _gcmERR_RETURN(gcm, func)
+#define gcmkERR_RETURN(func)        _gcmkERR_RETURN(gcmk, func)
+
+
+/*******************************************************************************
+**
+**  gcmONERROR
+**
+**      Jump to the error handler in case there is an error.
+**
+**  ASSUMPTIONS:
+**
+**      'status' variable of gceSTATUS type must be defined.
+**
+**  ARGUMENTS:
+**
+**      func    Function to evaluate.
+*/
+#define _gcmONERROR(prefix, func) \
+    do \
+    { \
+        status = func; \
+        if (gcmIS_ERROR(status)) \
+        { \
+            prefix##PRINT_VERSION(); \
+            prefix##TRACE(gcvLEVEL_ERROR, \
+                #prefix "ONERROR: status=%d(%s) @ %s(%d)", \
+                status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+            goto OnError; \
+        } \
+    } \
+    while (gcvFALSE)
+#define _gcmkONERROR(prefix, func) \
+    do \
+    { \
+        status = func; \
+        if (gcmIS_ERROR(status)) \
+        { \
+            prefix##PRINT_VERSION(); \
+            prefix##TRACE(gcvLEVEL_ERROR, \
+                #prefix "ONERROR: status=%d(%s) @ %s(%d)", \
+                status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+            goto OnError; \
+        } \
+    } \
+    while (gcvFALSE)
+#define gcmONERROR(func)            _gcmONERROR(gcm, func)
+#define gcmkONERROR(func)           _gcmkONERROR(gcmk, func)
+
+/*******************************************************************************
+**
+**  gcmVERIFY_LOCK
+**
+**      Verifies whether the surface is locked.
+**
+**  ARGUMENTS:
+**
+**      surfaceInfo Pointer to the surface iniformational structure.
+*/
+#define gcmVERIFY_LOCK(surfaceInfo) \
+    if (!surfaceInfo->node.valid) \
+    { \
+        gcmONERROR(gcvSTATUS_MEMORY_UNLOCKED); \
+    } \
+
+/*******************************************************************************
+**
+**  gcmVERIFY_NODE_LOCK
+**
+**      Verifies whether the surface node is locked.
+**
+**  ARGUMENTS:
+**
+**      surfaceInfo Pointer to the surface iniformational structure.
+*/
+#define gcmVERIFY_NODE_LOCK(surfaceNode) \
+    if (!surfaceNode->valid) \
+    { \
+        status = gcvSTATUS_MEMORY_UNLOCKED; \
+        break; \
+    } \
+    do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+**  gcmBADOBJECT_BREAK
+**
+**      Executes a break statement on bad object.
+**
+**  ARGUMENTS:
+**
+**      obj     Object to test.
+**      t       Expected type of the object.
+*/
+#define gcmBADOBJECT_BREAK(obj, t) \
+    if ((obj == gcvNULL) \
+    ||  (((gcsOBJECT *)(obj))->type != t) \
+    ) \
+    { \
+        status = gcvSTATUS_INVALID_OBJECT; \
+        break; \
+    } \
+    do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+**  gcmCHECK_STATUS
+**
+**      Executes a break statement on error.
+**
+**  ASSUMPTIONS:
+**
+**      'status' variable of gceSTATUS type must be defined.
+**
+**  ARGUMENTS:
+**
+**      func    Function to evaluate.
+*/
+#define _gcmCHECK_STATUS(prefix, func) \
+    do \
+    { \
+        last = func; \
+        if (gcmIS_ERROR(last)) \
+        { \
+            prefix##TRACE(gcvLEVEL_ERROR, \
+                #prefix "CHECK_STATUS: status=%d(%s) @ %s(%d)", \
+                last, gcoOS_DebugStatus2Name(last), __FUNCTION__, __LINE__); \
+            status = last; \
+        } \
+    } \
+    while (gcvFALSE)
+#define _gcmkCHECK_STATUS(prefix, func) \
+    do \
+    { \
+        last = func; \
+        if (gcmIS_ERROR(last)) \
+        { \
+            prefix##TRACE(gcvLEVEL_ERROR, \
+                #prefix "CHECK_STATUS: status=%d(%s) @ %s(%d)", \
+                last, gckOS_DebugStatus2Name(last), __FUNCTION__, __LINE__); \
+            status = last; \
+        } \
+    } \
+    while (gcvFALSE)
+#define gcmCHECK_STATUS(func)       _gcmCHECK_STATUS(gcm, func)
+#define gcmkCHECK_STATUS(func)      _gcmkCHECK_STATUS(gcmk, func)
+
+/*******************************************************************************
+**
+**  gcmVERIFY_ARGUMENT
+**
+**      Assert if an argument does not apply to the specified expression.  If
+**      the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
+**      returned from the current function.  In retail mode this macro does
+**      nothing.
+**
+**  ARGUMENTS:
+**
+**      arg     Argument to evaluate.
+*/
+#   define _gcmVERIFY_ARGUMENT(prefix, arg) \
+       do \
+       { \
+           if (!(arg)) \
+           { \
+               prefix##TRACE(gcvLEVEL_ERROR, #prefix "VERIFY_ARGUMENT failed:"); \
+               prefix##ASSERT(arg); \
+               prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT); \
+               return gcvSTATUS_INVALID_ARGUMENT; \
+           } \
+       } \
+       while (gcvFALSE)
+#   define gcmVERIFY_ARGUMENT(arg)     _gcmVERIFY_ARGUMENT(gcm, arg)
+#   define gcmkVERIFY_ARGUMENT(arg)    _gcmVERIFY_ARGUMENT(gcmk, arg)
+
+/*******************************************************************************
+**
+**  gcmDEBUG_VERIFY_ARGUMENT
+**
+**      Works just like gcmVERIFY_ARGUMENT, but is only valid in debug mode.
+**      Use this to verify arguments inside non-public API functions.
+*/
+#if gcdDEBUG
+#   define gcmDEBUG_VERIFY_ARGUMENT(arg)    _gcmVERIFY_ARGUMENT(gcm, arg)
+#   define gcmkDEBUG_VERIFY_ARGUMENT(arg)   _gcmkVERIFY_ARGUMENT(gcm, arg)
+#else
+#   define gcmDEBUG_VERIFY_ARGUMENT(arg)
+#   define gcmkDEBUG_VERIFY_ARGUMENT(arg)
+#endif
+/*******************************************************************************
+**
+**  gcmVERIFY_ARGUMENT_RETURN
+**
+**      Assert if an argument does not apply to the specified expression.  If
+**      the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
+**      returned from the current function.  In retail mode this macro does
+**      nothing.
+**
+**  ARGUMENTS:
+**
+**      arg     Argument to evaluate.
+*/
+#   define _gcmVERIFY_ARGUMENT_RETURN(prefix, arg, value) \
+       do \
+       { \
+           if (!(arg)) \
+           { \
+               prefix##TRACE(gcvLEVEL_ERROR, \
+                             #prefix "gcmVERIFY_ARGUMENT_RETURN failed:"); \
+               prefix##ASSERT(arg); \
+               prefix##FOOTER_ARG("value=%d", value); \
+               return value; \
+           } \
+       } \
+       while (gcvFALSE)
+#   define gcmVERIFY_ARGUMENT_RETURN(arg, value) \
+                _gcmVERIFY_ARGUMENT_RETURN(gcm, arg, value)
+#   define gcmkVERIFY_ARGUMENT_RETURN(arg, value) \
+                _gcmVERIFY_ARGUMENT_RETURN(gcmk, arg, value)
+
+#define MAX_LOOP_COUNT 0x7FFFFFFF
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_base_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_cl.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_cl.h
new file mode 100644 (file)
index 0000000..5acc46d
--- /dev/null
@@ -0,0 +1,281 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_user_cl_h_
+#define __gc_hal_user_cl_h_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define     USE_NEW_MEMORY_ALLOCATION   0
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+/* gcoCL_DEVICE_INFO object. */
+typedef struct _gcoCL_DEVICE_INFO
+{
+       gctUINT             maxComputeUnits;
+    gctUINT             maxWorkItemDimensions;
+    gctUINT             maxWorkItemSizes[3];
+    gctUINT             maxWorkGroupSize;
+    gctUINT             maxGlobalWorkSize ;
+       gctUINT                         clockFrequency;
+
+       gctUINT                         addrBits;
+       gctUINT64                       maxMemAllocSize;
+       gctUINT64                       globalMemSize;
+       gctUINT64                       localMemSize;
+       gctUINT             localMemType;                               /* cl_device_local_mem_type */
+       gctUINT             globalMemCacheType;                 /* cl_device_mem_cache_type */
+       gctUINT                         globalMemCachelineSize;
+       gctUINT64                       globalMemCacheSize;
+       gctUINT                         maxConstantArgs;
+       gctUINT64                       maxConstantBufferSize;
+       gctUINT                         maxParameterSize;
+       gctUINT                         memBaseAddrAlign;
+       gctUINT                         minDataTypeAlignSize;
+
+       gctBOOL                         imageSupport;
+       gctUINT                         maxReadImageArgs;
+       gctUINT                         maxWriteImageArgs;
+       gctUINT                         vectorWidthChar;
+       gctUINT                         vectorWidthShort;
+       gctUINT                         vectorWidthInt;
+       gctUINT                         vectorWidthLong;
+       gctUINT                         vectorWidthFloat;
+       gctUINT                         vectorWidthDouble;
+       gctUINT                         vectorWidthHalf;
+       gctUINT                         image2DMaxWidth;
+       gctUINT                         image2DMaxHeight;
+       gctUINT                         image3DMaxWidth;
+       gctUINT                         image3DMaxHeight;
+       gctUINT                         image3DMaxDepth;
+       gctUINT                         maxSamplers;
+
+       gctUINT64           queueProperties;            /* cl_command_queue_properties */
+       gctBOOL                 hostUnifiedMemory;
+       gctBOOL                         errorCorrectionSupport;
+       gctUINT64           singleFpConfig;                     /* cl_device_fp_config */
+       gctUINT64           doubleFpConfig;                     /* cl_device_fp_config */
+       gctUINT                         profilingTimingRes;
+       gctBOOL                         endianLittle;
+       gctBOOL                         deviceAvail;
+       gctBOOL                         compilerAvail;
+       gctUINT64                       execCapability;                 /* cl_device_exec_capabilities */
+} gcoCL_DEVICE_INFO;
+
+typedef gcoCL_DEVICE_INFO *  gcoCL_DEVICE_INFO_PTR;
+
+
+/*******************************************************************************
+**
+**  gcoCL_InitializeHardware
+**
+**  Initialize hardware.  This is required for each thread.
+**
+**  INPUT:
+**
+**      Nothing
+**
+**  OUTPUT:
+**
+**      Nothing
+*/
+gceSTATUS
+gcoCL_InitializeHardware(
+    );
+
+/*******************************************************************************
+**
+**  gcoCL_AllocateMemory
+**
+**  Allocate contiguous memory from the kernel.
+**
+**  INPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes to allocate.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that will receive the aligned number of bytes
+**          allocated.
+**
+**      gctPHYS_ADDR * Physical
+**          Pointer to a variable that will receive the physical addresses of
+**          the allocated memory.
+**
+**      gctPOINTER * Logical
+**          Pointer to a variable that will receive the logical address of the
+**          allocation.
+**
+**      gcsSURF_NODE_PTR  * Node
+**          Pointer to a variable that will receive the gcsSURF_NODE structure
+**          pointer that describes the video memory to lock.
+*/
+gceSTATUS
+gcoCL_AllocateMemory(
+    IN OUT gctSIZE_T *      Bytes,
+    OUT gctPHYS_ADDR *      Physical,
+    OUT gctPOINTER *        Logical,
+    OUT gcsSURF_NODE_PTR *  Node
+    );
+
+/*******************************************************************************
+**
+**  gcoCL_FreeMemory
+**
+**  Free contiguous memeory to the kernel.
+**
+**  INPUT:
+**
+**      gctPHYS_ADDR Physical
+**          The physical addresses of the allocated pages.
+**
+**      gctPOINTER Logical
+**          The logical address of the allocation.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes allocated.
+**
+**      gcsSURF_NODE_PTR  Node
+**          Pointer to a gcsSURF_NODE structure
+**          that describes the video memory to unlock.
+**
+**  OUTPUT:
+**
+**      Nothing
+*/
+gceSTATUS
+gcoCL_FreeMemory(
+    IN gctPHYS_ADDR         Physical,
+    IN gctPOINTER           Logical,
+    IN gctSIZE_T            Bytes,
+    IN gcsSURF_NODE_PTR     Node
+    );
+
+/*******************************************************************************
+**
+**  gcoCL_CreateTexture
+**
+**  Create texture for image.
+**
+**  INPUT:
+**
+**      gctUINT Width
+**          Width of the image.
+**
+**      gctUINT Heighth
+**          Heighth of the image.
+**
+**      gctUINT Depth
+**          Depth of the image.
+**
+**      gctCONST_POINTER Memory
+**          Pointer to the data of the input image.
+**
+**      gctUINT Stride
+**          Size of one row.
+**
+**      gctUINT Slice
+**          Size of one plane.
+**
+**      gceSURF_FORMAT FORMAT
+**          Format of the image.
+**
+**      gceENDIAN_HINT EndianHint
+**          Endian needed to handle the image data.
+**
+**  OUTPUT:
+**
+**      gcoTEXTURE * Texture
+**          Pointer to a variable that will receive the gcoTEXTURE structure.
+**
+**      gcoSURF * Surface
+**          Pointer to a variable that will receive the gcoSURF structure.
+**
+**      gctPHYS_ADDR * Physical
+**          Pointer to a variable that will receive the physical addresses of
+**          the allocated memory.
+**
+**      gctPOINTER * Logical
+**          Pointer to a variable that will receive the logical address of the
+**          allocation.
+*/
+gceSTATUS
+gcoCL_CreateTexture(
+    IN gctUINT              Width,
+    IN gctUINT              Height,
+    IN gctUINT              Depth,
+    IN gctCONST_POINTER     Memory,
+    IN gctUINT              Stride,
+    IN gctUINT              Slice,
+    IN gceSURF_FORMAT       Format,
+    IN gceENDIAN_HINT       EndianHint,
+    OUT gcoTEXTURE *        Texture,
+    OUT gcoSURF *           Surface,
+    OUT gctPHYS_ADDR *      Physical,
+    OUT gctPOINTER *        Logical
+    );
+
+/*******************************************************************************
+**
+**  gcoCL_QueryDeviceInfo
+**
+**  Query the OpenCL capabilities of the device.
+**
+**  INPUT:
+**
+**      Nothing
+**
+**  OUTPUT:
+**
+**      gcoCL_DEVICE_INFO_PTR DeviceInfo
+**          Pointer to the device information
+*/
+gceSTATUS
+gcoCL_QueryDeviceInfo(
+    OUT gcoCL_DEVICE_INFO_PTR  DeviceInfo
+    );
+
+gceSTATUS
+gcoCL_SubmitSignal(
+    IN gctSIGNAL    Signal,
+    IN gctHANDLE    Process
+    );
+
+gceSTATUS
+gcoCL_Flush(
+    IN gctBOOL      Stall
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_user_cl_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h
new file mode 100644 (file)
index 0000000..9db51b5
--- /dev/null
@@ -0,0 +1,3039 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+/*
+**     Include file the defines the front- and back-end compilers, as well as the
+**     objects they use.
+*/
+
+#ifndef __gc_hal_compiler_h_
+#define __gc_hal_compiler_h_
+
+#ifndef VIVANTE_NO_3D
+#include "gc_hal_types.h"
+#include "gc_hal_engine.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************* IR VERSION ******************/
+#define gcdSL_IR_VERSION gcmCC('\0','\0','\0','\1')
+
+/******************************************************************************\
+|******************************* SHADER LANGUAGE ******************************|
+\******************************************************************************/
+
+/* Possible shader language opcodes. */
+typedef enum _gcSL_OPCODE
+{
+       gcSL_NOP,                                                       /* 0x00 */
+       gcSL_MOV,                                                       /* 0x01 */
+       gcSL_SAT,                                                       /* 0x02 */
+       gcSL_DP3,                                                       /* 0x03 */
+       gcSL_DP4,                                                       /* 0x04 */
+       gcSL_ABS,                                                       /* 0x05 */
+       gcSL_JMP,                                                       /* 0x06 */
+       gcSL_ADD,                                                       /* 0x07 */
+       gcSL_MUL,                                                       /* 0x08 */
+       gcSL_RCP,                                                       /* 0x09 */
+       gcSL_SUB,                                                       /* 0x0A */
+       gcSL_KILL,                                                      /* 0x0B */
+       gcSL_TEXLD,                                                     /* 0x0C */
+       gcSL_CALL,                                                      /* 0x0D */
+       gcSL_RET,                                                       /* 0x0E */
+       gcSL_NORM,                                                      /* 0x0F */
+       gcSL_MAX,                                                       /* 0x10 */
+       gcSL_MIN,                                                       /* 0x11 */
+       gcSL_POW,                                                       /* 0x12 */
+       gcSL_RSQ,                                                       /* 0x13 */
+       gcSL_LOG,                                                       /* 0x14 */
+       gcSL_FRAC,                                                      /* 0x15 */
+       gcSL_FLOOR,                                                     /* 0x16 */
+       gcSL_CEIL,                                                      /* 0x17 */
+       gcSL_CROSS,                                                     /* 0x18 */
+       gcSL_TEXLDP,                                            /* 0x19 */
+       gcSL_TEXBIAS,                                           /* 0x1A */
+       gcSL_TEXGRAD,                                           /* 0x1B */
+       gcSL_TEXLOD,                                            /* 0x1C */
+       gcSL_SIN,                                                       /* 0x1D */
+       gcSL_COS,                                                       /* 0x1E */
+       gcSL_TAN,                                                       /* 0x1F */
+       gcSL_EXP,                                                       /* 0x20 */
+       gcSL_SIGN,                                                      /* 0x21 */
+       gcSL_STEP,                                                      /* 0x22 */
+       gcSL_SQRT,                                                      /* 0x23 */
+       gcSL_ACOS,                                                      /* 0x24 */
+       gcSL_ASIN,                                                      /* 0x25 */
+       gcSL_ATAN,                                                      /* 0x26 */
+       gcSL_SET,                                                       /* 0x27 */
+       gcSL_DSX,                                                       /* 0x28 */
+       gcSL_DSY,                                                       /* 0x29 */
+       gcSL_FWIDTH,                                            /* 0x2A */
+       gcSL_DIV,                                               /* 0x2B */
+       gcSL_MOD,                                               /* 0x2C */
+       gcSL_AND_BITWISE,                                       /* 0x2D */
+       gcSL_OR_BITWISE,                                        /* 0x2E */
+       gcSL_XOR_BITWISE,                                       /* 0x2F */
+       gcSL_NOT_BITWISE,                                       /* 0x30 */
+       gcSL_LSHIFT,                                            /* 0x31 */
+       gcSL_RSHIFT,                                            /* 0x32 */
+       gcSL_ROTATE,                                            /* 0x33 */
+       gcSL_BITSEL,                                            /* 0x34 */
+       gcSL_LEADZERO,                                          /* 0x35 */
+       gcSL_LOAD,                                                      /* 0x36 */
+       gcSL_STORE,                                                     /* 0x37 */
+       gcSL_BARRIER,                                           /* 0x38 */
+       gcSL_SIN_CL,                                            /* 0x39 */
+       gcSL_COS_CL,                                            /* 0x3A */
+       gcSL_TAN_CL,                                            /* 0x3B */
+       gcSL_ACOS_CL,                                           /* 0x3C */
+       gcSL_ASIN_CL,                                           /* 0x3D */
+       gcSL_ATAN_CL,                                           /* 0x3E */
+       gcSL_SINH_CL,                                           /* 0x3F */
+       gcSL_COSH_CL,                                           /* 0x40 */
+       gcSL_TANH_CL,                                           /* 0x41 */
+       gcSL_ASINH_CL,                                          /* 0x42 */
+       gcSL_ACOSH_CL,                                          /* 0x43 */
+       gcSL_ATANH_CL,                                          /* 0x44 */
+       gcSL_SINPI_CL,                                          /* 0x45 */
+       gcSL_COSPI_CL,                                          /* 0x46 */
+       gcSL_TANPI_CL,                                          /* 0x47 */
+       gcSL_ASINPI_CL,                                         /* 0x48 */
+       gcSL_ACOSPI_CL,                                         /* 0x49 */
+       gcSL_ATANPI_CL,                                         /* 0x4A */
+       gcSL_ATAN2_CL,                                          /* 0x4B */
+       gcSL_ATAN2PI_CL,                                        /* 0x4C */
+       gcSL_POW_CL,                                            /* 0x4D */
+       gcSL_RSQ_CL,                                            /* 0x4E */
+       gcSL_LOG_CL,                                            /* 0x4F */
+       gcSL_EXP_CL,                                            /* 0x50 */
+       gcSL_SQRT_CL,                                           /* 0x51 */
+       gcSL_CBRT_CL,                                           /* 0x52 */
+       gcSL_ADDLO,                                                     /* 0x53 */  /* Float only. */
+       gcSL_MULLO,                                                     /* 0x54 */  /* Float only. */
+       gcSL_CONV,                                                      /* 0x55 */
+       gcSL_GETEXP,                                            /* 0x56 */
+       gcSL_GETMANT,                                           /* 0x57 */
+       gcSL_MULHI,                                                     /* 0x58 */  /* Integer only. */
+       gcSL_CMP,                                                       /* 0x59 */
+       gcSL_I2F,                                                       /* 0x5A */
+       gcSL_F2I,                                                       /* 0x5B */
+       gcSL_ADDSAT,                                            /* 0x5C */  /* Integer only. */
+       gcSL_SUBSAT,                                            /* 0x5D */  /* Integer only. */
+       gcSL_MULSAT,                                            /* 0x5E */  /* Integer only. */
+}
+gcSL_OPCODE;
+
+typedef enum _gcSL_FORMAT
+{
+       gcSL_FLOAT = 0,                                         /* 0 */
+       gcSL_INTEGER = 1,                                   /* 1 */
+       gcSL_INT32 = 1,                                     /* 1 */
+       gcSL_BOOLEAN = 2,                                       /* 2 */
+       gcSL_UINT32 = 3,                                        /* 3 */
+       gcSL_INT8,                                                  /* 4 */
+       gcSL_UINT8,                                                 /* 5 */
+       gcSL_INT16,                                                 /* 6 */
+       gcSL_UINT16,                                            /* 7 */
+       gcSL_INT64,                                                 /* 8 */     /* Reserved for future enhancement. */
+       gcSL_UINT64,                                            /* 9 */     /* Reserved for future enhancement. */
+       gcSL_INT128,                                        /* 10 */    /* Reserved for future enhancement. */
+       gcSL_UINT128,                                           /* 11 */    /* Reserved for future enhancement. */
+       gcSL_FLOAT16,                                       /* 12 */
+       gcSL_FLOAT64,                                           /* 13 */    /* Reserved for future enhancement. */
+       gcSL_FLOAT128,                                          /* 14 */    /* Reserved for future enhancement. */
+}
+gcSL_FORMAT;
+
+/* Destination write enable bits. */
+typedef enum _gcSL_ENABLE
+{
+       gcSL_ENABLE_X                                           = 0x1,
+       gcSL_ENABLE_Y                                           = 0x2,
+       gcSL_ENABLE_Z                                           = 0x4,
+       gcSL_ENABLE_W                                           = 0x8,
+       /* Combinations. */
+       gcSL_ENABLE_XY                                          = gcSL_ENABLE_X | gcSL_ENABLE_Y,
+       gcSL_ENABLE_XYZ                                         = gcSL_ENABLE_X | gcSL_ENABLE_Y | gcSL_ENABLE_Z,
+       gcSL_ENABLE_XYZW                                        = gcSL_ENABLE_X | gcSL_ENABLE_Y | gcSL_ENABLE_Z | gcSL_ENABLE_W,
+       gcSL_ENABLE_XYW                                         = gcSL_ENABLE_X | gcSL_ENABLE_Y | gcSL_ENABLE_W,
+       gcSL_ENABLE_XZ                                          = gcSL_ENABLE_X | gcSL_ENABLE_Z,
+       gcSL_ENABLE_XZW                                         = gcSL_ENABLE_X | gcSL_ENABLE_Z | gcSL_ENABLE_W,
+       gcSL_ENABLE_XW                                          = gcSL_ENABLE_X | gcSL_ENABLE_W,
+       gcSL_ENABLE_YZ                                          = gcSL_ENABLE_Y | gcSL_ENABLE_Z,
+       gcSL_ENABLE_YZW                                         = gcSL_ENABLE_Y | gcSL_ENABLE_Z | gcSL_ENABLE_W,
+       gcSL_ENABLE_YW                                          = gcSL_ENABLE_Y | gcSL_ENABLE_W,
+       gcSL_ENABLE_ZW                                          = gcSL_ENABLE_Z | gcSL_ENABLE_W,
+}
+gcSL_ENABLE;
+
+/* Possible indices. */
+typedef enum _gcSL_INDEXED
+{
+       gcSL_NOT_INDEXED,                                       /* 0 */
+       gcSL_INDEXED_X,                                         /* 1 */
+       gcSL_INDEXED_Y,                                         /* 2 */
+       gcSL_INDEXED_Z,                                         /* 3 */
+       gcSL_INDEXED_W,                                         /* 4 */
+}
+gcSL_INDEXED;
+
+/* Opcode conditions. */
+typedef enum _gcSL_CONDITION
+{
+       gcSL_ALWAYS,                                            /* 0x0 */
+       gcSL_NOT_EQUAL,                                         /* 0x1 */
+       gcSL_LESS_OR_EQUAL,                                     /* 0x2 */
+       gcSL_LESS,                                                      /* 0x3 */
+       gcSL_EQUAL,                                                     /* 0x4 */
+       gcSL_GREATER,                                           /* 0x5 */
+       gcSL_GREATER_OR_EQUAL,                          /* 0x6 */
+       gcSL_AND,                                                       /* 0x7 */
+       gcSL_OR,                                                        /* 0x8 */
+       gcSL_XOR,                                                       /* 0x9 */
+    gcSL_NOT_ZERO,                      /* 0xA */
+}
+gcSL_CONDITION;
+
+/* Possible source operand types. */
+typedef enum _gcSL_TYPE
+{
+       gcSL_NONE,                                                      /* 0x0 */
+       gcSL_TEMP,                                                      /* 0x1 */
+       gcSL_ATTRIBUTE,                                         /* 0x2 */
+       gcSL_UNIFORM,                                           /* 0x3 */
+       gcSL_SAMPLER,                                           /* 0x4 */
+       gcSL_CONSTANT,                                          /* 0x5 */
+       gcSL_OUTPUT,                                            /* 0x6 */
+       gcSL_PHYSICAL,                                          /* 0x7 */
+}
+gcSL_TYPE;
+
+/* Swizzle generator macro. */
+#define gcmSWIZZLE(Component1, Component2, Component3, Component4) \
+( \
+       (gcSL_SWIZZLE_ ## Component1 << 0) | \
+       (gcSL_SWIZZLE_ ## Component2 << 2) | \
+       (gcSL_SWIZZLE_ ## Component3 << 4) | \
+       (gcSL_SWIZZLE_ ## Component4 << 6)   \
+)
+
+/* Possible swizzle values. */
+typedef enum _gcSL_SWIZZLE
+{
+       gcSL_SWIZZLE_X,                                         /* 0x0 */
+       gcSL_SWIZZLE_Y,                                         /* 0x1 */
+       gcSL_SWIZZLE_Z,                                         /* 0x2 */
+       gcSL_SWIZZLE_W,                                         /* 0x3 */
+       /* Combinations. */
+       gcSL_SWIZZLE_XXXX = gcmSWIZZLE(X, X, X, X),
+       gcSL_SWIZZLE_YYYY = gcmSWIZZLE(Y, Y, Y, Y),
+       gcSL_SWIZZLE_ZZZZ = gcmSWIZZLE(Z, Z, Z, Z),
+       gcSL_SWIZZLE_WWWW = gcmSWIZZLE(W, W, W, W),
+       gcSL_SWIZZLE_XYYY = gcmSWIZZLE(X, Y, Y, Y),
+       gcSL_SWIZZLE_XZZZ = gcmSWIZZLE(X, Z, Z, Z),
+       gcSL_SWIZZLE_XWWW = gcmSWIZZLE(X, W, W, W),
+       gcSL_SWIZZLE_YZZZ = gcmSWIZZLE(Y, Z, Z, Z),
+       gcSL_SWIZZLE_YWWW = gcmSWIZZLE(Y, W, W, W),
+       gcSL_SWIZZLE_ZWWW = gcmSWIZZLE(Z, W, W, W),
+       gcSL_SWIZZLE_XYZZ = gcmSWIZZLE(X, Y, Z, Z),
+       gcSL_SWIZZLE_XYWW = gcmSWIZZLE(X, Y, W, W),
+       gcSL_SWIZZLE_XZWW = gcmSWIZZLE(X, Z, W, W),
+       gcSL_SWIZZLE_YZWW = gcmSWIZZLE(Y, Z, W, W),
+       gcSL_SWIZZLE_XXYZ = gcmSWIZZLE(X, X, Y, Z),
+       gcSL_SWIZZLE_XYZW = gcmSWIZZLE(X, Y, Z, W),
+       gcSL_SWIZZLE_XYXY = gcmSWIZZLE(X, Y, X, Y),
+
+    gcSL_SWIZZLE_INVALID = 0x7FFFFFFF
+}
+gcSL_SWIZZLE;
+
+
+/******************************************************************************\
+|*********************************** SHADERS **********************************|
+\******************************************************************************/
+
+/* Shader types. */
+#define gcSHADER_TYPE_UNKNOWN                  0
+#define gcSHADER_TYPE_VERTEX                   1
+#define gcSHADER_TYPE_FRAGMENT                 2
+#define gcSHADER_TYPE_CL                       3
+#define gcSHADER_TYPE_PRECOMPILED              4
+
+#define gcm
+/* gcSHADER objects. */
+typedef struct _gcSHADER *                     gcSHADER;
+typedef struct _gcATTRIBUTE *                  gcATTRIBUTE;
+typedef struct _gcUNIFORM *                    gcUNIFORM;
+typedef struct _gcOUTPUT *                     gcOUTPUT;
+typedef struct _gcsFUNCTION *                  gcFUNCTION;
+typedef struct _gcsKERNEL_FUNCTION *           gcKERNEL_FUNCTION;
+typedef struct _gcsHINT *                      gcsHINT_PTR;
+typedef struct _gcSHADER_PROFILER *            gcSHADER_PROFILER;
+typedef struct _gcVARIABLE *                   gcVARIABLE;
+
+struct _gcsHINT
+{
+    /* Numbr of data transfers for Vertex Shader output. */
+    gctUINT32   vsOutputCount;
+
+    /* Flag whether the VS has point size or not. */
+    gctBOOL     vsHasPointSize;
+
+    /* Element count. */
+    gctUINT32   elementCount;
+
+    /* Component count. */
+    gctUINT32   componentCount;
+
+    /* Number of data transfers for Fragment Shader input. */
+    gctUINT32   fsInputCount;
+
+    /* Maximum number of temporary registers used in FS. */
+    gctUINT32   fsMaxTemp;
+
+       /* Maximum number of temporary registers used in VS. */
+       gctUINT32   vsMaxTemp;
+
+    /* Balance minimum. */
+    gctUINT32   balanceMin;
+
+    /* Balance maximum. */
+    gctUINT32   balanceMax;
+
+    /* Flag whether the PS outputs the depth value or not. */
+    gctBOOL     psHasFragDepthOut;
+
+       /* Flag whether the ThreadWalker is in PS. */
+       gctBOOL         threadWalkerInPS;
+
+};
+
+/* gcSHADER_TYPE enumeration. */
+typedef enum _gcSHADER_TYPE
+{
+       gcSHADER_FLOAT_X1,                              /* 0x00 */
+       gcSHADER_FLOAT_X2,                              /* 0x01 */
+       gcSHADER_FLOAT_X3,                              /* 0x02 */
+       gcSHADER_FLOAT_X4,                              /* 0x03 */
+       gcSHADER_FLOAT_2X2,                             /* 0x04 */
+       gcSHADER_FLOAT_3X3,                             /* 0x05 */
+       gcSHADER_FLOAT_4X4,                             /* 0x06 */
+       gcSHADER_BOOLEAN_X1,                    /* 0x07 */
+       gcSHADER_BOOLEAN_X2,                    /* 0x08 */
+       gcSHADER_BOOLEAN_X3,                    /* 0x09 */
+       gcSHADER_BOOLEAN_X4,                    /* 0x0A */
+       gcSHADER_INTEGER_X1,                    /* 0x0B */
+       gcSHADER_INTEGER_X2,                    /* 0x0C */
+       gcSHADER_INTEGER_X3,                    /* 0x0D */
+       gcSHADER_INTEGER_X4,                    /* 0x0E */
+       gcSHADER_SAMPLER_1D,                    /* 0x0F */
+       gcSHADER_SAMPLER_2D,                    /* 0x10 */
+       gcSHADER_SAMPLER_3D,                    /* 0x11 */
+       gcSHADER_SAMPLER_CUBIC,                 /* 0x12 */
+       gcSHADER_FIXED_X1,                              /* 0x13 */
+       gcSHADER_FIXED_X2,                              /* 0x14 */
+       gcSHADER_FIXED_X3,                              /* 0x15 */
+       gcSHADER_FIXED_X4,                              /* 0x16 */
+       gcSHADER_IMAGE_2D,                              /* 0x17 */  /* For OCL. */
+       gcSHADER_IMAGE_3D,                              /* 0x18 */  /* For OCL. */
+       gcSHADER_SAMPLER,                               /* 0x19 */  /* For OCL. */
+       gcSHADER_FLOAT_2X3,                             /* 0x1A */
+       gcSHADER_FLOAT_2X4,                             /* 0x1B */
+       gcSHADER_FLOAT_3X2,                             /* 0x1C */
+       gcSHADER_FLOAT_3X4,                             /* 0x1D */
+       gcSHADER_FLOAT_4X2,                             /* 0x1E */
+       gcSHADER_FLOAT_4X3,                             /* 0x1F */
+       gcSHADER_ISAMPLER_2D,                   /* 0x20 */
+       gcSHADER_ISAMPLER_3D,                   /* 0x21 */
+       gcSHADER_ISAMPLER_CUBIC,                /* 0x22 */
+       gcSHADER_USAMPLER_2D,                   /* 0x23 */
+       gcSHADER_USAMPLER_3D,                   /* 0x24 */
+       gcSHADER_USAMPLER_CUBIC,                /* 0x25 */
+       gcSHADER_SAMPLER_EXTERNAL_OES,          /* 0x26 */
+
+}
+gcSHADER_TYPE;
+
+/* Shader flags. */
+typedef enum _gceSHADER_FLAGS
+{
+       gcvSHADER_DEAD_CODE                                     = 0x01,
+       gcvSHADER_RESOURCE_USAGE                        = 0x02,
+       gcvSHADER_OPTIMIZER                                     = 0x04,
+       gcvSHADER_USE_GL_Z                                      = 0x08,
+       gcvSHADER_USE_GL_POSITION                       = 0x10,
+       gcvSHADER_USE_GL_FACE                           = 0x20,
+       gcvSHADER_USE_GL_POINT_COORD            = 0x40,
+}
+gceSHADER_FLAGS;
+
+/* Function argument qualifier */
+typedef enum _gceINPUT_OUTPUT
+{
+       gcvFUNCTION_INPUT,
+       gcvFUNCTION_OUTPUT,
+       gcvFUNCTION_INOUT
+}
+gceINPUT_OUTPUT;
+
+/* Kernel function property flags. */
+typedef enum _gcePROPERTY_FLAGS
+{
+       gcvPROPERTY_REQD_WORK_GRP_SIZE  = 0x01
+}
+gceKERNEL_FUNCTION_PROPERTY_FLAGS;
+
+/* Uniform flags. */
+typedef enum _gceUNIFORM_FLAGS
+{
+       gcvUNIFORM_KERNEL_ARG                   = 0x01,
+       gcvUNIFORM_KERNEL_ARG_LOCAL             = 0x02,
+       gcvUNIFORM_KERNEL_ARG_SAMPLER           = 0x04,
+       gcvUNIFORM_LOCAL_ADDRESS_SPACE          = 0x08,
+       gcvUNIFORM_PRIVATE_ADDRESS_SPACE        = 0x10,
+       gcvUNIFORM_CONSTANT_ADDRESS_SPACE       = 0x20,
+       gcvUNIFORM_GLOBAL_SIZE                  = 0x40,
+       gcvUNIFORM_LOCAL_SIZE                   = 0x80,
+       gcvUNIFORM_NUM_GROUPS                   = 0x100,
+       gcvUNIFORM_GLOBAL_OFFSET                = 0x200,
+       gcvUNIFORM_WORK_DIM                     = 0x400,
+       gcvUNIFORM_KERNEL_ARG_CONSTANT          = 0x800,
+}
+gceUNIFORM_FLAGS;
+
+#define gcdUNIFORM_KERNEL_ARG_MASK  (gcvUNIFORM_KERNEL_ARG         | \
+                                     gcvUNIFORM_KERNEL_ARG_LOCAL   | \
+                                                                        gcvUNIFORM_KERNEL_ARG_SAMPLER | \
+                                                                        gcvUNIFORM_KERNEL_ARG_CONSTANT)
+
+/*******************************************************************************
+**  gcSHADER_SetCompilerVersion
+**
+**  Set the compiler version of a gcSHADER object.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to gcSHADER object
+**
+**      gctINT *Version
+**          Pointer to a two word version
+*/
+gceSTATUS
+gcSHADER_SetCompilerVersion(
+    IN gcSHADER Shader,
+    IN gctUINT32 *Version
+    );
+
+/*******************************************************************************
+**  gcSHADER_GetCompilerVersion
+**
+**  Get the compiler version of a gcSHADER object.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**  OUTPUT:
+**
+**      gctUINT32_PTR *CompilerVersion.
+**          Pointer to holder of returned compilerVersion pointer
+*/
+gceSTATUS
+gcSHADER_GetCompilerVersion(
+    IN gcSHADER Shader,
+    OUT gctUINT32_PTR *CompilerVersion
+    );
+
+/*******************************************************************************
+**  gcSHADER_GetType
+**
+**  Get the gcSHADER object's type.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**  OUTPUT:
+**
+**      gctINT *Type.
+**          Pointer to return shader type.
+*/
+gceSTATUS
+gcSHADER_GetType(
+    IN gcSHADER Shader,
+    OUT gctINT *Type
+    );
+/*******************************************************************************
+**                             gcSHADER_Construct
+********************************************************************************
+**
+**     Construct a new gcSHADER object.
+**
+**     INPUT:
+**
+**             gcoOS Hal
+**                     Pointer to an gcoHAL object.
+**
+**             gctINT ShaderType
+**                     Type of gcSHADER object to cerate.  'ShaderType' can be one of the
+**                     following:
+**
+**                             gcSHADER_TYPE_VERTEX    Vertex shader.
+**                             gcSHADER_TYPE_FRAGMENT  Fragment shader.
+**
+**     OUTPUT:
+**
+**             gcSHADER * Shader
+**                     Pointer to a variable receiving the gcSHADER object pointer.
+*/
+gceSTATUS
+gcSHADER_Construct(
+       IN gcoHAL Hal,
+       IN gctINT ShaderType,
+       OUT gcSHADER * Shader
+       );
+
+/*******************************************************************************
+**                              gcSHADER_Destroy
+********************************************************************************
+**
+**     Destroy a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_Destroy(
+       IN gcSHADER Shader
+       );
+
+/*******************************************************************************
+**                              gcSHADER_Copy
+********************************************************************************
+**
+**     Copy a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**      gcSHADER Source
+**          Pointer to a gcSHADER object that will be copied.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_Copy(
+       IN gcSHADER Shader,
+       IN gcSHADER Source
+       );
+
+/*******************************************************************************
+**  gcSHADER_LoadHeader
+**
+**  Load a gcSHADER object from a binary buffer.  The binary buffer is layed out
+**  as follows:
+**      // Six word header
+**      // Signature, must be 'S','H','D','R'.
+**      gctINT8             signature[4];
+**      gctUINT32           binFileVersion;
+**      gctUINT32           compilerVersion[2];
+**      gctUINT32           gcSLVersion;
+**      gctUINT32           binarySize;
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**          Shader type will be returned if type in shader object is not gcSHADER_TYPE_PRECOMPILED
+**
+**      gctPOINTER Buffer
+**          Pointer to a binary buffer containing the shader data to load.
+**
+**      gctSIZE_T BufferSize
+**          Number of bytes inside the binary buffer pointed to by 'Buffer'.
+**
+**  OUTPUT:
+**      nothing
+**
+*/
+gceSTATUS
+gcSHADER_LoadHeader(
+    IN gcSHADER Shader,
+    IN gctPOINTER Buffer,
+    IN gctSIZE_T BufferSize
+    );
+
+/*******************************************************************************
+**  gcSHADER_LoadKernel
+**
+**  Load a kernel function given by name into gcSHADER object
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**      gctSTRING KernelName
+**          Pointer to a kernel function name
+**
+**  OUTPUT:
+**      nothing
+**
+*/
+gceSTATUS
+gcSHADER_LoadKernel(
+    IN gcSHADER Shader,
+    IN gctSTRING KernelName
+    );
+
+/*******************************************************************************
+**                                gcSHADER_Load
+********************************************************************************
+**
+**     Load a gcSHADER object from a binary buffer.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctPOINTER Buffer
+**                     Pointer to a binary buffer containg the shader data to load.
+**
+**             gctSIZE_T BufferSize
+**                     Number of bytes inside the binary buffer pointed to by 'Buffer'.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_Load(
+       IN gcSHADER Shader,
+       IN gctPOINTER Buffer,
+       IN gctSIZE_T BufferSize
+       );
+
+/*******************************************************************************
+**                                gcSHADER_Save
+********************************************************************************
+**
+**     Save a gcSHADER object to a binary buffer.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctPOINTER Buffer
+**                     Pointer to a binary buffer to be used as storage for the gcSHADER
+**                     object.  If 'Buffer' is gcvNULL, the gcSHADER object will not be saved,
+**                     but the number of bytes required to hold the binary output for the
+**                     gcSHADER object will be returned.
+**
+**             gctSIZE_T * BufferSize
+**                     Pointer to a variable holding the number of bytes allocated in
+**                     'Buffer'.  Only valid if 'Buffer' is not gcvNULL.
+**
+**     OUTPUT:
+**
+**             gctSIZE_T * BufferSize
+**                     Pointer to a variable receiving the number of bytes required to hold
+**                     the binary form of the gcSHADER object.
+*/
+gceSTATUS
+gcSHADER_Save(
+       IN gcSHADER Shader,
+       IN gctPOINTER Buffer,
+       IN OUT gctSIZE_T * BufferSize
+       );
+
+/*******************************************************************************
+**                                gcSHADER_LoadEx
+********************************************************************************
+**
+**     Load a gcSHADER object from a binary buffer.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctPOINTER Buffer
+**                     Pointer to a binary buffer containg the shader data to load.
+**
+**             gctSIZE_T BufferSize
+**                     Number of bytes inside the binary buffer pointed to by 'Buffer'.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_LoadEx(
+       IN gcSHADER Shader,
+       IN gctPOINTER Buffer,
+       IN gctSIZE_T BufferSize
+       );
+
+/*******************************************************************************
+**                                gcSHADER_SaveEx
+********************************************************************************
+**
+**     Save a gcSHADER object to a binary buffer.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctPOINTER Buffer
+**                     Pointer to a binary buffer to be used as storage for the gcSHADER
+**                     object.  If 'Buffer' is gcvNULL, the gcSHADER object will not be saved,
+**                     but the number of bytes required to hold the binary output for the
+**                     gcSHADER object will be returned.
+**
+**             gctSIZE_T * BufferSize
+**                     Pointer to a variable holding the number of bytes allocated in
+**                     'Buffer'.  Only valid if 'Buffer' is not gcvNULL.
+**
+**     OUTPUT:
+**
+**             gctSIZE_T * BufferSize
+**                     Pointer to a variable receiving the number of bytes required to hold
+**                     the binary form of the gcSHADER object.
+*/
+gceSTATUS
+gcSHADER_SaveEx(
+       IN gcSHADER Shader,
+       IN gctPOINTER Buffer,
+       IN OUT gctSIZE_T * BufferSize
+       );
+
+/*******************************************************************************
+**  gcSHADER_ReallocateAttributes
+**
+**  Reallocate an array of pointers to gcATTRIBUTE objects.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**      gctSIZE_T Count
+**          Array count to reallocate.  'Count' must be at least 1.
+*/
+gceSTATUS
+gcSHADER_ReallocateAttributes(
+    IN gcSHADER Shader,
+    IN gctSIZE_T Count
+    );
+
+/*******************************************************************************
+**                                                       gcSHADER_AddAttribute
+********************************************************************************
+**
+**     Add an attribute to a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctCONST_STRING Name
+**                     Name of the attribute to add.
+**
+**             gcSHADER_TYPE Type
+**                     Type of the attribute to add.
+**
+**             gctSIZE_T Length
+**                     Array length of the attribute to add.  'Length' must be at least 1.
+**
+**             gctBOOL IsTexture
+**                     gcvTRUE if the attribute is used as a texture coordinate, gcvFALSE if not.
+**
+**     OUTPUT:
+**
+**             gcATTRIBUTE * Attribute
+**                     Pointer to a variable receiving the gcATTRIBUTE object pointer.
+*/
+gceSTATUS
+gcSHADER_AddAttribute(
+       IN gcSHADER Shader,
+       IN gctCONST_STRING Name,
+       IN gcSHADER_TYPE Type,
+       IN gctSIZE_T Length,
+       IN gctBOOL IsTexture,
+       OUT gcATTRIBUTE * Attribute
+       );
+
+/*******************************************************************************
+**                         gcSHADER_GetAttributeCount
+********************************************************************************
+**
+**     Get the number of attributes for this shader.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**     OUTPUT:
+**
+**             gctSIZE_T * Count
+**                     Pointer to a variable receiving the number of attributes.
+*/
+gceSTATUS
+gcSHADER_GetAttributeCount(
+       IN gcSHADER Shader,
+       OUT gctSIZE_T * Count
+       );
+
+/*******************************************************************************
+**                            gcSHADER_GetAttribute
+********************************************************************************
+**
+**     Get the gcATTRIBUTE object poniter for an indexed attribute for this shader.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctUINT Index
+**                     Index of the attribute to retrieve.
+**
+**     OUTPUT:
+**
+**             gcATTRIBUTE * Attribute
+**                     Pointer to a variable receiving the gcATTRIBUTE object pointer.
+*/
+gceSTATUS
+gcSHADER_GetAttribute(
+       IN gcSHADER Shader,
+       IN gctUINT Index,
+       OUT gcATTRIBUTE * Attribute
+       );
+
+/*******************************************************************************
+**  gcSHADER_ReallocateUniforms
+**
+**  Reallocate an array of pointers to gcUNIFORM objects.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**      gctSIZE_T Count
+**          Array count to reallocate.  'Count' must be at least 1.
+*/
+gceSTATUS
+gcSHADER_ReallocateUniforms(
+    IN gcSHADER Shader,
+    IN gctSIZE_T Count
+    );
+
+/*******************************************************************************
+**                                                        gcSHADER_AddUniform
+********************************************************************************
+**
+**     Add an uniform to a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctCONST_STRING Name
+**                     Name of the uniform to add.
+**
+**             gcSHADER_TYPE Type
+**                     Type of the uniform to add.
+**
+**             gctSIZE_T Length
+**                     Array length of the uniform to add.  'Length' must be at least 1.
+**
+**     OUTPUT:
+**
+**             gcUNIFORM * Uniform
+**                     Pointer to a variable receiving the gcUNIFORM object pointer.
+*/
+gceSTATUS
+gcSHADER_AddUniform(
+       IN gcSHADER Shader,
+       IN gctCONST_STRING Name,
+       IN gcSHADER_TYPE Type,
+       IN gctSIZE_T Length,
+       OUT gcUNIFORM * Uniform
+       );
+
+/*******************************************************************************
+**                          gcSHADER_GetUniformCount
+********************************************************************************
+**
+**     Get the number of uniforms for this shader.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**     OUTPUT:
+**
+**             gctSIZE_T * Count
+**                     Pointer to a variable receiving the number of uniforms.
+*/
+gceSTATUS
+gcSHADER_GetUniformCount(
+       IN gcSHADER Shader,
+       OUT gctSIZE_T * Count
+       );
+
+/*******************************************************************************
+**                             gcSHADER_GetUniform
+********************************************************************************
+**
+**     Get the gcUNIFORM object pointer for an indexed uniform for this shader.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctUINT Index
+**                     Index of the uniform to retrieve.
+**
+**     OUTPUT:
+**
+**             gcUNIFORM * Uniform
+**                     Pointer to a variable receiving the gcUNIFORM object pointer.
+*/
+gceSTATUS
+gcSHADER_GetUniform(
+       IN gcSHADER Shader,
+       IN gctUINT Index,
+       OUT gcUNIFORM * Uniform
+       );
+
+/*******************************************************************************
+**  gcSHADER_GetKernelFucntion
+**
+**  Get the gcKERNEL_FUNCTION object pointer for an indexed kernel function for this shader.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**      gctUINT Index
+**          Index of kernel function to retreive the name for.
+**
+**  OUTPUT:
+**
+**      gcKERNEL_FUNCTION * KernelFunction
+**          Pointer to a variable receiving the gcKERNEL_FUNCTION object pointer.
+*/
+gceSTATUS
+gcSHADER_GetKernelFunction(
+    IN gcSHADER Shader,
+    IN gctUINT Index,
+    OUT gcKERNEL_FUNCTION * KernelFunction
+    );
+
+gceSTATUS
+gcSHADER_GetKernelFunctionByName(
+       IN gcSHADER Shader,
+    IN gctSTRING KernelName,
+    OUT gcKERNEL_FUNCTION * KernelFunction
+    );
+/*******************************************************************************
+**  gcSHADER_GetKernelFunctionCount
+**
+**  Get the number of kernel functions for this shader.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Count
+**          Pointer to a variable receiving the number of kernel functions.
+*/
+gceSTATUS
+gcSHADER_GetKernelFunctionCount(
+    IN gcSHADER Shader,
+    OUT gctSIZE_T * Count
+    );
+
+/*******************************************************************************
+**  gcSHADER_ReallocateOutputs
+**
+**  Reallocate an array of pointers to gcOUTPUT objects.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**      gctSIZE_T Count
+**          Array count to reallocate.  'Count' must be at least 1.
+*/
+gceSTATUS
+gcSHADER_ReallocateOutputs(
+    IN gcSHADER Shader,
+    IN gctSIZE_T Count
+    );
+
+/*******************************************************************************
+**                                                        gcSHADER_AddOutput
+********************************************************************************
+**
+**     Add an output to a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctCONST_STRING Name
+**                     Name of the output to add.
+**
+**             gcSHADER_TYPE Type
+**                     Type of the output to add.
+**
+**             gctSIZE_T Length
+**                     Array length of the output to add.  'Length' must be at least 1.
+**
+**             gctUINT16 TempRegister
+**                     Temporary register index that holds the output value.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddOutput(
+       IN gcSHADER Shader,
+       IN gctCONST_STRING Name,
+       IN gcSHADER_TYPE Type,
+       IN gctSIZE_T Length,
+       IN gctUINT16 TempRegister
+       );
+
+gceSTATUS
+gcSHADER_AddOutputIndexed(
+       IN gcSHADER Shader,
+       IN gctCONST_STRING Name,
+       IN gctSIZE_T Index,
+       IN gctUINT16 TempIndex
+       );
+
+/*******************************************************************************
+**                                                      gcSHADER_GetOutputCount
+********************************************************************************
+**
+**     Get the number of outputs for this shader.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**     OUTPUT:
+**
+**             gctSIZE_T * Count
+**                     Pointer to a variable receiving the number of outputs.
+*/
+gceSTATUS
+gcSHADER_GetOutputCount(
+       IN gcSHADER Shader,
+       OUT gctSIZE_T * Count
+       );
+
+/*******************************************************************************
+**                                                        gcSHADER_GetOutput
+********************************************************************************
+**
+**     Get the gcOUTPUT object pointer for an indexed output for this shader.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctUINT Index
+**                     Index of output to retrieve.
+**
+**     OUTPUT:
+**
+**             gcOUTPUT * Output
+**                     Pointer to a variable receiving the gcOUTPUT object pointer.
+*/
+gceSTATUS
+gcSHADER_GetOutput(
+       IN gcSHADER Shader,
+       IN gctUINT Index,
+       OUT gcOUTPUT * Output
+       );
+
+/*******************************************************************************
+**  gcSHADER_ReallocateVariables
+**
+**  Reallocate an array of pointers to gcVARIABLE objects.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**      gctSIZE_T Count
+**          Array count to reallocate.  'Count' must be at least 1.
+*/
+gceSTATUS
+gcSHADER_ReallocateVariables(
+    IN gcSHADER Shader,
+    IN gctSIZE_T Count
+    );
+
+/*******************************************************************************
+**                                                        gcSHADER_AddVariable
+********************************************************************************
+**
+**     Add a variable to a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctCONST_STRING Name
+**                     Name of the variable to add.
+**
+**             gcSHADER_TYPE Type
+**                     Type of the variable to add.
+**
+**             gctSIZE_T Length
+**                     Array length of the variable to add.  'Length' must be at least 1.
+**
+**             gctUINT16 TempRegister
+**                     Temporary register index that holds the variable value.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddVariable(
+       IN gcSHADER Shader,
+       IN gctCONST_STRING Name,
+       IN gcSHADER_TYPE Type,
+       IN gctSIZE_T Length,
+       IN gctUINT16 TempRegister
+       );
+
+/*******************************************************************************
+**                                                      gcSHADER_GetVariableCount
+********************************************************************************
+**
+**     Get the number of variables for this shader.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**     OUTPUT:
+**
+**             gctSIZE_T * Count
+**                     Pointer to a variable receiving the number of variables.
+*/
+gceSTATUS
+gcSHADER_GetVariableCount(
+       IN gcSHADER Shader,
+       OUT gctSIZE_T * Count
+       );
+
+/*******************************************************************************
+**                                                        gcSHADER_GetVariable
+********************************************************************************
+**
+**     Get the gcVARIABLE object pointer for an indexed variable for this shader.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctUINT Index
+**                     Index of variable to retrieve.
+**
+**     OUTPUT:
+**
+**             gcVARIABLE * Variable
+**                     Pointer to a variable receiving the gcVARIABLE object pointer.
+*/
+gceSTATUS
+gcSHADER_GetVariable(
+       IN gcSHADER Shader,
+       IN gctUINT Index,
+       OUT gcVARIABLE * Variable
+       );
+
+/*******************************************************************************
+**                                                        gcSHADER_AddOpcode
+********************************************************************************
+**
+**     Add an opcode to a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gcSL_OPCODE Opcode
+**                     Opcode to add.
+**
+**             gctUINT16 TempRegister
+**                     Temporary register index that acts as the target of the opcode.
+**
+**             gctUINT8 Enable
+**                     Write enable bits for the temporary register that acts as the target
+**                     of the opcode.
+**
+**             gcSL_FORMAT Format
+**                     Format of the temporary register.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddOpcode(
+       IN gcSHADER Shader,
+       IN gcSL_OPCODE Opcode,
+       IN gctUINT16 TempRegister,
+       IN gctUINT8 Enable,
+       IN gcSL_FORMAT Format
+       );
+
+gceSTATUS
+gcSHADER_AddOpcode2(
+       IN gcSHADER Shader,
+       IN gcSL_OPCODE Opcode,
+       IN gcSL_CONDITION Condition,
+       IN gctUINT16 TempRegister,
+       IN gctUINT8 Enable,
+       IN gcSL_FORMAT Format
+       );
+
+/*******************************************************************************
+**                                                     gcSHADER_AddOpcodeIndexed
+********************************************************************************
+**
+**     Add an opcode to a gcSHADER object that writes to an dynamically indexed
+**     target.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gcSL_OPCODE Opcode
+**                     Opcode to add.
+**
+**             gctUINT16 TempRegister
+**                     Temporary register index that acts as the target of the opcode.
+**
+**             gctUINT8 Enable
+**                     Write enable bits  for the temporary register that acts as the
+**                     target of the opcode.
+**
+**             gcSL_INDEXED Mode
+**                     Location of the dynamic index inside the temporary register.  Valid
+**                     values can be:
+**
+**                             gcSL_INDEXED_X - Use x component of the temporary register.
+**                             gcSL_INDEXED_Y - Use y component of the temporary register.
+**                             gcSL_INDEXED_Z - Use z component of the temporary register.
+**                             gcSL_INDEXED_W - Use w component of the temporary register.
+**
+**             gctUINT16 IndexRegister
+**                     Temporary register index that holds the dynamic index.
+**
+**             gcSL_FORMAT Format
+**                     Format of the temporary register.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddOpcodeIndexed(
+       IN gcSHADER Shader,
+       IN gcSL_OPCODE Opcode,
+       IN gctUINT16 TempRegister,
+       IN gctUINT8 Enable,
+       IN gcSL_INDEXED Mode,
+       IN gctUINT16 IndexRegister,
+       IN gcSL_FORMAT Format
+       );
+
+/*******************************************************************************
+**  gcSHADER_AddOpcodeConditionIndexed
+**
+**  Add an opcode to a gcSHADER object that writes to an dynamically indexed
+**  target.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**      gcSL_OPCODE Opcode
+**          Opcode to add.
+**
+**      gcSL_CONDITION Condition
+**          Condition to check.
+**
+**      gctUINT16 TempRegister
+**          Temporary register index that acts as the target of the opcode.
+**
+**      gctUINT8 Enable
+**          Write enable bits  for the temporary register that acts as the
+**          target of the opcode.
+**
+**      gcSL_INDEXED Indexed
+**          Location of the dynamic index inside the temporary register.  Valid
+**          values can be:
+**
+**              gcSL_INDEXED_X - Use x component of the temporary register.
+**              gcSL_INDEXED_Y - Use y component of the temporary register.
+**              gcSL_INDEXED_Z - Use z component of the temporary register.
+**              gcSL_INDEXED_W - Use w component of the temporary register.
+**
+**      gctUINT16 IndexRegister
+**          Temporary register index that holds the dynamic index.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gcSHADER_AddOpcodeConditionIndexed(
+    IN gcSHADER Shader,
+    IN gcSL_OPCODE Opcode,
+    IN gcSL_CONDITION Condition,
+    IN gctUINT16 TempRegister,
+    IN gctUINT8 Enable,
+    IN gcSL_INDEXED Indexed,
+    IN gctUINT16 IndexRegister,
+    IN gcSL_FORMAT Format
+    );
+
+/*******************************************************************************
+**                                               gcSHADER_AddOpcodeConditional
+********************************************************************************
+**
+**     Add an conditional opcode to a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gcSL_OPCODE Opcode
+**                     Opcode to add.
+**
+**             gcSL_CONDITION Condition
+**                     Condition that needs to evaluate to gcvTRUE in order for the opcode to
+**                     execute.
+**
+**             gctUINT Label
+**                     Target label if 'Condition' evaluates to gcvTRUE.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddOpcodeConditional(
+       IN gcSHADER Shader,
+       IN gcSL_OPCODE Opcode,
+       IN gcSL_CONDITION Condition,
+       IN gctUINT Label
+       );
+
+/*******************************************************************************
+**  gcSHADER_AddOpcodeConditionalFormatted
+**
+**  Add an conditional jump or call opcode to a gcSHADER object.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**      gcSL_OPCODE Opcode
+**          Opcode to add.
+**
+**      gcSL_CONDITION Condition
+**          Condition that needs to evaluate to gcvTRUE in order for the opcode to
+**          execute.
+**
+**      gcSL_FORMAT Format
+**          Format of conditional operands
+**
+**      gctUINT Label
+**          Target label if 'Condition' evaluates to gcvTRUE.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gcSHADER_AddOpcodeConditionalFormatted(
+    IN gcSHADER Shader,
+    IN gcSL_OPCODE Opcode,
+    IN gcSL_CONDITION Condition,
+    IN gcSL_FORMAT Format,
+    IN gctUINT Label
+    );
+
+/*******************************************************************************
+**                                                             gcSHADER_AddLabel
+********************************************************************************
+**
+**     Define a label at the current instruction of a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctUINT Label
+**                     Label to define.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddLabel(
+       IN gcSHADER Shader,
+       IN gctUINT Label
+       );
+
+/*******************************************************************************
+**                                                        gcSHADER_AddSource
+********************************************************************************
+**
+**     Add a source operand to a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gcSL_TYPE Type
+**                     Type of the source operand.
+**
+**             gctUINT16 SourceIndex
+**                     Index of the source operand.
+**
+**             gctUINT8 Swizzle
+**                     x, y, z, and w swizzle values packed into one 8-bit value.
+**
+**             gcSL_FORMAT Format
+**                     Format of the source operand.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSource(
+       IN gcSHADER Shader,
+       IN gcSL_TYPE Type,
+       IN gctUINT16 SourceIndex,
+       IN gctUINT8 Swizzle,
+       IN gcSL_FORMAT Format
+       );
+
+/*******************************************************************************
+**                                                     gcSHADER_AddSourceIndexed
+********************************************************************************
+**
+**     Add a dynamically indexed source operand to a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gcSL_TYPE Type
+**                     Type of the source operand.
+**
+**             gctUINT16 SourceIndex
+**                     Index of the source operand.
+**
+**             gctUINT8 Swizzle
+**                     x, y, z, and w swizzle values packed into one 8-bit value.
+**
+**             gcSL_INDEXED Mode
+**                     Addressing mode for the index.
+**
+**             gctUINT16 IndexRegister
+**                     Temporary register index that holds the dynamic index.
+**
+**             gcSL_FORMAT Format
+**                     Format of the source operand.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceIndexed(
+       IN gcSHADER Shader,
+       IN gcSL_TYPE Type,
+       IN gctUINT16 SourceIndex,
+       IN gctUINT8 Swizzle,
+       IN gcSL_INDEXED Mode,
+       IN gctUINT16 IndexRegister,
+       IN gcSL_FORMAT Format
+       );
+
+/*******************************************************************************
+**                                                gcSHADER_AddSourceAttribute
+********************************************************************************
+**
+**     Add an attribute as a source operand to a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gcATTRIBUTE Attribute
+**                     Pointer to a gcATTRIBUTE object.
+**
+**             gctUINT8 Swizzle
+**                     x, y, z, and w swizzle values packed into one 8-bit value.
+**
+**             gctINT Index
+**                     Static index into the attribute in case the attribute is a matrix
+**                     or array.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceAttribute(
+       IN gcSHADER Shader,
+       IN gcATTRIBUTE Attribute,
+       IN gctUINT8 Swizzle,
+       IN gctINT Index
+       );
+
+/*******************************************************************************
+**                                                gcSHADER_AddSourceAttributeIndexed
+********************************************************************************
+**
+**     Add an indexed attribute as a source operand to a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gcATTRIBUTE Attribute
+**                     Pointer to a gcATTRIBUTE object.
+**
+**             gctUINT8 Swizzle
+**                     x, y, z, and w swizzle values packed into one 8-bit value.
+**
+**             gctINT Index
+**                     Static index into the attribute in case the attribute is a matrix
+**                     or array.
+**
+**             gcSL_INDEXED Mode
+**                     Addressing mode of the dynamic index.
+**
+**             gctUINT16 IndexRegister
+**                     Temporary register index that holds the dynamic index.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceAttributeIndexed(
+       IN gcSHADER Shader,
+       IN gcATTRIBUTE Attribute,
+       IN gctUINT8 Swizzle,
+       IN gctINT Index,
+       IN gcSL_INDEXED Mode,
+       IN gctUINT16 IndexRegister
+       );
+
+/*******************************************************************************
+**                                                     gcSHADER_AddSourceUniform
+********************************************************************************
+**
+**     Add a uniform as a source operand to a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gcUNIFORM Uniform
+**                     Pointer to a gcUNIFORM object.
+**
+**             gctUINT8 Swizzle
+**                     x, y, z, and w swizzle values packed into one 8-bit value.
+**
+**             gctINT Index
+**                     Static index into the uniform in case the uniform is a matrix or
+**                     array.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceUniform(
+       IN gcSHADER Shader,
+       IN gcUNIFORM Uniform,
+       IN gctUINT8 Swizzle,
+       IN gctINT Index
+       );
+
+/*******************************************************************************
+**                                             gcSHADER_AddSourceUniformIndexed
+********************************************************************************
+**
+**     Add an indexed uniform as a source operand to a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gcUNIFORM Uniform
+**                     Pointer to a gcUNIFORM object.
+**
+**             gctUINT8 Swizzle
+**                     x, y, z, and w swizzle values packed into one 8-bit value.
+**
+**             gctINT Index
+**                     Static index into the uniform in case the uniform is a matrix or
+**                     array.
+**
+**             gcSL_INDEXED Mode
+**                     Addressing mode of the dynamic index.
+**
+**             gctUINT16 IndexRegister
+**                     Temporary register index that holds the dynamic index.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceUniformIndexed(
+       IN gcSHADER Shader,
+       IN gcUNIFORM Uniform,
+       IN gctUINT8 Swizzle,
+       IN gctINT Index,
+       IN gcSL_INDEXED Mode,
+       IN gctUINT16 IndexRegister
+       );
+
+gceSTATUS
+gcSHADER_AddSourceSamplerIndexed(
+       IN gcSHADER Shader,
+       IN gctUINT8 Swizzle,
+       IN gcSL_INDEXED Mode,
+       IN gctUINT16 IndexRegister
+       );
+
+gceSTATUS
+gcSHADER_AddSourceAttributeFormatted(
+    IN gcSHADER Shader,
+    IN gcATTRIBUTE Attribute,
+    IN gctUINT8 Swizzle,
+    IN gctINT Index,
+    IN gcSL_FORMAT Format
+    );
+
+gceSTATUS
+gcSHADER_AddSourceAttributeIndexedFormatted(
+    IN gcSHADER Shader,
+    IN gcATTRIBUTE Attribute,
+    IN gctUINT8 Swizzle,
+    IN gctINT Index,
+    IN gcSL_INDEXED Mode,
+    IN gctUINT16 IndexRegister,
+    IN gcSL_FORMAT Format
+    );
+
+gceSTATUS
+gcSHADER_AddSourceUniformFormatted(
+    IN gcSHADER Shader,
+    IN gcUNIFORM Uniform,
+    IN gctUINT8 Swizzle,
+    IN gctINT Index,
+    IN gcSL_FORMAT Format
+    );
+
+gceSTATUS
+gcSHADER_AddSourceUniformIndexedFormatted(
+    IN gcSHADER Shader,
+    IN gcUNIFORM Uniform,
+    IN gctUINT8 Swizzle,
+    IN gctINT Index,
+    IN gcSL_INDEXED Mode,
+    IN gctUINT16 IndexRegister,
+    IN gcSL_FORMAT Format
+    );
+
+gceSTATUS
+gcSHADER_AddSourceSamplerIndexedFormatted(
+    IN gcSHADER Shader,
+    IN gctUINT8 Swizzle,
+    IN gcSL_INDEXED Mode,
+    IN gctUINT16 IndexRegister,
+    IN gcSL_FORMAT Format
+    );
+
+/*******************************************************************************
+**                                                gcSHADER_AddSourceConstant
+********************************************************************************
+**
+**     Add a constant floating point value as a source operand to a gcSHADER
+**     object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctFLOAT Constant
+**                     Floating point constant.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceConstant(
+       IN gcSHADER Shader,
+       IN gctFLOAT Constant
+       );
+
+/*******************************************************************************
+**                                        gcSHADER_AddSourceConstantFormatted
+********************************************************************************
+**
+**     Add a constant value as a source operand to a gcSHADER
+**     object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             void * Constant
+**                     Pointer to constant.
+**
+**             gcSL_FORMAT Format
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceConstantFormatted(
+       IN gcSHADER Shader,
+       IN void *Constant,
+       IN gcSL_FORMAT Format
+       );
+
+/*******************************************************************************
+**                                                               gcSHADER_Pack
+********************************************************************************
+**
+**     Pack a dynamically created gcSHADER object by trimming the allocated arrays
+**     and resolving all the labeling.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_Pack(
+       IN gcSHADER Shader
+       );
+
+/*******************************************************************************
+**                                                             gcSHADER_SetOptimizationOption
+********************************************************************************
+**
+**     Set optimization option of a gcSHADER object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctUINT OptimizationOption
+**                     Optimization option.  Can be one of the following:
+**
+**                             0                                               - No optimization.
+**                             1                                               - Full optimization.
+**                             Other value                             - For optimizer testing.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_SetOptimizationOption(
+       IN gcSHADER Shader,
+       IN gctUINT OptimizationOption
+       );
+
+/*******************************************************************************
+**  gcSHADER_ReallocateFunctions
+**
+**  Reallocate an array of pointers to gcFUNCTION objects.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**      gctSIZE_T Count
+**          Array count to reallocate.  'Count' must be at least 1.
+*/
+gceSTATUS
+gcSHADER_ReallocateFunctions(
+    IN gcSHADER Shader,
+    IN gctSIZE_T Count
+    );
+
+gceSTATUS
+gcSHADER_AddFunction(
+       IN gcSHADER Shader,
+       IN gctCONST_STRING Name,
+       OUT gcFUNCTION * Function
+       );
+
+gceSTATUS
+gcSHADER_ReallocateKernelFunctions(
+    IN gcSHADER Shader,
+    IN gctSIZE_T Count
+    );
+
+gceSTATUS
+gcSHADER_AddKernelFunction(
+       IN gcSHADER Shader,
+       IN gctCONST_STRING Name,
+       OUT gcKERNEL_FUNCTION * KernelFunction
+       );
+
+gceSTATUS
+gcSHADER_BeginFunction(
+       IN gcSHADER Shader,
+       IN gcFUNCTION Function
+       );
+
+gceSTATUS
+gcSHADER_EndFunction(
+       IN gcSHADER Shader,
+       IN gcFUNCTION Function
+       );
+
+gceSTATUS
+gcSHADER_BeginKernelFunction(
+       IN gcSHADER Shader,
+       IN gcKERNEL_FUNCTION KernelFunction
+       );
+
+gceSTATUS
+gcSHADER_EndKernelFunction(
+       IN gcSHADER Shader,
+       IN gcKERNEL_FUNCTION KernelFunction,
+       IN gctSIZE_T LocalMemorySize
+       );
+
+gceSTATUS
+gcSHADER_SetMaxKernelFunctionArgs(
+    IN gcSHADER Shader,
+    IN gctUINT32 MaxKernelFunctionArgs
+    );
+
+/*******************************************************************************
+**  gcSHADER_SetConstantMemorySize
+**
+**  Set the constant memory address space size of a gcSHADER object.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**      gctSIZE_T ConstantMemorySize
+**          Constant memory size in bytes
+**
+**      gctCHAR *ConstantMemoryBuffer
+**          Constant memory buffer
+*/
+gceSTATUS
+gcSHADER_SetConstantMemorySize(
+    IN gcSHADER Shader,
+    IN gctSIZE_T ConstantMemorySize,
+    IN gctCHAR * ConstantMemoryBuffer
+    );
+
+/*******************************************************************************
+**  gcSHADER_GetConstantMemorySize
+**
+**  Set the constant memory address space size of a gcSHADER object.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * ConstantMemorySize
+**          Pointer to a variable receiving constant memory size in bytes
+**
+**      gctCHAR **ConstantMemoryBuffer.
+**          Pointer to a variable for returned shader constant memory buffer.
+*/
+gceSTATUS
+gcSHADER_GetConstantMemorySize(
+    IN gcSHADER Shader,
+    OUT gctSIZE_T * ConstantMemorySize,
+    OUT gctCHAR ** ConstantMemoryBuffer
+    );
+
+/*******************************************************************************
+**  gcSHADER_SetPrivateMemorySize
+**
+**  Set the private memory address space size of a gcSHADER object.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**      gctSIZE_T PrivateMemorySize
+**          Private memory size in bytes
+*/
+gceSTATUS
+gcSHADER_SetPrivateMemorySize(
+    IN gcSHADER Shader,
+    IN gctSIZE_T PrivateMemorySize
+    );
+
+/*******************************************************************************
+**  gcSHADER_GetPrivateMemorySize
+**
+**  Set the private memory address space size of a gcSHADER object.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * PrivateMemorySize
+**          Pointer to a variable receiving private memory size in bytes
+*/
+gceSTATUS
+gcSHADER_GetPrivateMemorySize(
+    IN gcSHADER Shader,
+    OUT gctSIZE_T * PrivateMemorySize
+    );
+
+/*******************************************************************************
+**  gcSHADER_SetLocalMemorySize
+**
+**  Set the local memory address space size of a gcSHADER object.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**      gctSIZE_T LocalMemorySize
+**          Local memory size in bytes
+*/
+gceSTATUS
+gcSHADER_SetLocalMemorySize(
+    IN gcSHADER Shader,
+    IN gctSIZE_T LocalMemorySize
+    );
+
+/*******************************************************************************
+**  gcSHADER_GetLocalMemorySize
+**
+**  Set the local memory address space size of a gcSHADER object.
+**
+**  INPUT:
+**
+**      gcSHADER Shader
+**          Pointer to a gcSHADER object.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * LocalMemorySize
+**          Pointer to a variable receiving lcoal memory size in bytes
+*/
+gceSTATUS
+gcSHADER_GetLocalMemorySize(
+    IN gcSHADER Shader,
+    OUT gctSIZE_T * LocalMemorySize
+    );
+
+/*******************************************************************************
+**                             gcATTRIBUTE_GetType
+********************************************************************************
+**
+**     Get the type and array length of a gcATTRIBUTE object.
+**
+**     INPUT:
+**
+**             gcATTRIBUTE Attribute
+**                     Pointer to a gcATTRIBUTE object.
+**
+**     OUTPUT:
+**
+**             gcSHADER_TYPE * Type
+**                     Pointer to a variable receiving the type of the attribute.  'Type'
+**                     can be gcvNULL, in which case no type will be returned.
+**
+**             gctSIZE_T * ArrayLength
+**                     Pointer to a variable receiving the length of the array if the
+**                     attribute was declared as an array.  If the attribute was not
+**                     declared as an array, the array length will be 1.  'ArrayLength' can
+**                     be gcvNULL, in which case no array length will be returned.
+*/
+gceSTATUS
+gcATTRIBUTE_GetType(
+       IN gcATTRIBUTE Attribute,
+       OUT gcSHADER_TYPE * Type,
+       OUT gctSIZE_T * ArrayLength
+       );
+
+/*******************************************************************************
+**                            gcATTRIBUTE_GetName
+********************************************************************************
+**
+**     Get the name of a gcATTRIBUTE object.
+**
+**     INPUT:
+**
+**             gcATTRIBUTE Attribute
+**                     Pointer to a gcATTRIBUTE object.
+**
+**     OUTPUT:
+**
+**             gctSIZE_T * Length
+**                     Pointer to a variable receiving the length of the attribute name.
+**                     'Length' can be gcvNULL, in which case no length will be returned.
+**
+**             gctCONST_STRING * Name
+**                     Pointer to a variable receiving the pointer to the attribute name.
+**                     'Name' can be gcvNULL, in which case no name will be returned.
+*/
+gceSTATUS
+gcATTRIBUTE_GetName(
+       IN gcATTRIBUTE Attribute,
+       OUT gctSIZE_T * Length,
+       OUT gctCONST_STRING * Name
+       );
+
+/*******************************************************************************
+**                            gcATTRIBUTE_IsEnabled
+********************************************************************************
+**
+**     Query the enabled state of a gcATTRIBUTE object.
+**
+**     INPUT:
+**
+**             gcATTRIBUTE Attribute
+**                     Pointer to a gcATTRIBUTE object.
+**
+**     OUTPUT:
+**
+**             gctBOOL * Enabled
+**                     Pointer to a variable receiving the enabled state of the attribute.
+*/
+gceSTATUS
+gcATTRIBUTE_IsEnabled(
+       IN gcATTRIBUTE Attribute,
+       OUT gctBOOL * Enabled
+       );
+
+/*******************************************************************************
+**                              gcUNIFORM_GetType
+********************************************************************************
+**
+**     Get the type and array length of a gcUNIFORM object.
+**
+**     INPUT:
+**
+**             gcUNIFORM Uniform
+**                     Pointer to a gcUNIFORM object.
+**
+**     OUTPUT:
+**
+**             gcSHADER_TYPE * Type
+**                     Pointer to a variable receiving the type of the uniform.  'Type' can
+**                     be gcvNULL, in which case no type will be returned.
+**
+**             gctSIZE_T * ArrayLength
+**                     Pointer to a variable receiving the length of the array if the
+**                     uniform was declared as an array.  If the uniform was not declared
+**                     as an array, the array length will be 1.  'ArrayLength' can be gcvNULL,
+**                     in which case no array length will be returned.
+*/
+gceSTATUS
+gcUNIFORM_GetType(
+       IN gcUNIFORM Uniform,
+       OUT gcSHADER_TYPE * Type,
+       OUT gctSIZE_T * ArrayLength
+       );
+
+/*******************************************************************************
+**                              gcUNIFORM_GetFlags
+********************************************************************************
+**
+**     Get the flags of a gcUNIFORM object.
+**
+**     INPUT:
+**
+**             gcUNIFORM Uniform
+**                     Pointer to a gcUNIFORM object.
+**
+**     OUTPUT:
+**
+**             gceUNIFORM_FLAGS * Flags
+**                     Pointer to a variable receiving the flags of the uniform.
+**
+*/
+gceSTATUS
+gcUNIFORM_GetFlags(
+       IN gcUNIFORM Uniform,
+       OUT gceUNIFORM_FLAGS * Flags
+       );
+
+/*******************************************************************************
+**                              gcUNIFORM_SetFlags
+********************************************************************************
+**
+**     Set the flags of a gcUNIFORM object.
+**
+**     INPUT:
+**
+**             gcUNIFORM Uniform
+**                     Pointer to a gcUNIFORM object.
+**
+**             gceUNIFORM_FLAGS Flags
+**                     Flags of the uniform to be set.
+**
+**     OUTPUT:
+**                     Nothing.
+**
+*/
+gceSTATUS
+gcUNIFORM_SetFlags(
+       IN gcUNIFORM Uniform,
+       IN gceUNIFORM_FLAGS Flags
+       );
+
+/*******************************************************************************
+**                              gcUNIFORM_GetName
+********************************************************************************
+**
+**     Get the name of a gcUNIFORM object.
+**
+**     INPUT:
+**
+**             gcUNIFORM Uniform
+**                     Pointer to a gcUNIFORM object.
+**
+**     OUTPUT:
+**
+**             gctSIZE_T * Length
+**                     Pointer to a variable receiving the length of the uniform name.
+**                     'Length' can be gcvNULL, in which case no length will be returned.
+**
+**             gctCONST_STRING * Name
+**                     Pointer to a variable receiving the pointer to the uniform name.
+**                     'Name' can be gcvNULL, in which case no name will be returned.
+*/
+gceSTATUS
+gcUNIFORM_GetName(
+       IN gcUNIFORM Uniform,
+       OUT gctSIZE_T * Length,
+       OUT gctCONST_STRING * Name
+       );
+
+/*******************************************************************************
+**                              gcUNIFORM_GetSampler
+********************************************************************************
+**
+**     Get the physical sampler number for a sampler gcUNIFORM object.
+**
+**     INPUT:
+**
+**             gcUNIFORM Uniform
+**                     Pointer to a gcUNIFORM object.
+**
+**     OUTPUT:
+**
+**             gctUINT32 * Sampler
+**                     Pointer to a variable receiving the physical sampler.
+*/
+gceSTATUS
+gcUNIFORM_GetSampler(
+       IN gcUNIFORM Uniform,
+       OUT gctUINT32 * Sampler
+       );
+
+/*******************************************************************************
+**  gcUNIFORM_GetFormat
+**
+**  Get the type and array length of a gcUNIFORM object.
+**
+**  INPUT:
+**
+**      gcUNIFORM Uniform
+**          Pointer to a gcUNIFORM object.
+**
+**  OUTPUT:
+**
+**      gcSL_FORMAT * Format
+**          Pointer to a variable receiving the format of element of the uniform.
+**          'Type' can be gcvNULL, in which case no type will be returned.
+**
+**      gctBOOL * IsPointer
+**          Pointer to a variable receiving the state wheter the uniform is a pointer.
+**          'IsPointer' can be gcvNULL, in which case no array length will be returned.
+*/
+gceSTATUS
+gcUNIFORM_GetFormat(
+    IN gcUNIFORM Uniform,
+    OUT gcSL_FORMAT * Format,
+    OUT gctBOOL * IsPointer
+    );
+
+/*******************************************************************************
+**  gcUNIFORM_SetFormat
+**
+**  Set the format and isPointer of a uniform.
+**
+**  INPUT:
+**
+**      gcUNIFORM Uniform
+**          Pointer to a gcUNIFORM object.
+**
+**      gcSL_FORMAT Format
+**          Format of element of the uniform shaderType.
+**
+**      gctBOOL IsPointer
+**          Wheter the uniform is a pointer.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gcUNIFORM_SetFormat(
+    IN gcUNIFORM Uniform,
+    IN gcSL_FORMAT Format,
+    IN gctBOOL IsPointer
+    );
+
+/*******************************************************************************
+**                                                        gcUNIFORM_SetValue
+********************************************************************************
+**
+**     Set the value of a uniform in integer.
+**
+**     INPUT:
+**
+**             gcUNIFORM Uniform
+**                     Pointer to a gcUNIFORM object.
+**
+**             gctSIZE_T Count
+**                     Number of entries to program if the uniform has been declared as an
+**                     array.
+**
+**             const gctINT * Value
+**                     Pointer to a buffer holding the integer values for the uniform.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcUNIFORM_SetValue(
+       IN gcUNIFORM Uniform,
+       IN gctSIZE_T Count,
+       IN const gctINT * Value
+       );
+
+/*******************************************************************************
+**                                                        gcUNIFORM_SetValueX
+********************************************************************************
+**
+**     Set the value of a uniform in fixed point.
+**
+**     INPUT:
+**
+**             gcUNIFORM Uniform
+**                     Pointer to a gcUNIFORM object.
+**
+**             gctSIZE_T Count
+**                     Number of entries to program if the uniform has been declared as an
+**                     array.
+**
+**             const gctFIXED_POINT * Value
+**                     Pointer to a buffer holding the fixed point values for the uniform.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcUNIFORM_SetValueX(
+       IN gcUNIFORM Uniform,
+       IN gctSIZE_T Count,
+       IN gctFIXED_POINT * Value
+       );
+
+/*******************************************************************************
+**                                                        gcUNIFORM_SetValueF
+********************************************************************************
+**
+**     Set the value of a uniform in floating point.
+**
+**     INPUT:
+**
+**             gcUNIFORM Uniform
+**                     Pointer to a gcUNIFORM object.
+**
+**             gctSIZE_T Count
+**                     Number of entries to program if the uniform has been declared as an
+**                     array.
+**
+**             const gctFLOAT * Value
+**                     Pointer to a buffer holding the floating point values for the
+**                     uniform.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcUNIFORM_SetValueF(
+       IN gcUNIFORM Uniform,
+       IN gctSIZE_T Count,
+       IN const gctFLOAT * Value
+       );
+
+/*******************************************************************************
+**                                                             gcOUTPUT_GetType
+********************************************************************************
+**
+**     Get the type and array length of a gcOUTPUT object.
+**
+**     INPUT:
+**
+**             gcOUTPUT Output
+**                     Pointer to a gcOUTPUT object.
+**
+**     OUTPUT:
+**
+**             gcSHADER_TYPE * Type
+**                     Pointer to a variable receiving the type of the output.  'Type' can
+**                     be gcvNULL, in which case no type will be returned.
+**
+**             gctSIZE_T * ArrayLength
+**                     Pointer to a variable receiving the length of the array if the
+**                     output was declared as an array.  If the output was not declared
+**                     as an array, the array length will be 1.  'ArrayLength' can be gcvNULL,
+**                     in which case no array length will be returned.
+*/
+gceSTATUS
+gcOUTPUT_GetType(
+       IN gcOUTPUT Output,
+       OUT gcSHADER_TYPE * Type,
+       OUT gctSIZE_T * ArrayLength
+       );
+
+/*******************************************************************************
+**                                                        gcOUTPUT_GetIndex
+********************************************************************************
+**
+**     Get the index of a gcOUTPUT object.
+**
+**     INPUT:
+**
+**             gcOUTPUT Output
+**                     Pointer to a gcOUTPUT object.
+**
+**     OUTPUT:
+**
+**             gctUINT * Index
+**                     Pointer to a variable receiving the temporary register index of the
+**                     output.  'Index' can be gcvNULL,. in which case no index will be
+**                     returned.
+*/
+gceSTATUS
+gcOUTPUT_GetIndex(
+       IN gcOUTPUT Output,
+       OUT gctUINT * Index
+       );
+
+/*******************************************************************************
+**                                                             gcOUTPUT_GetName
+********************************************************************************
+**
+**     Get the name of a gcOUTPUT object.
+**
+**     INPUT:
+**
+**             gcOUTPUT Output
+**                     Pointer to a gcOUTPUT object.
+**
+**     OUTPUT:
+**
+**             gctSIZE_T * Length
+**                     Pointer to a variable receiving the length of the output name.
+**                     'Length' can be gcvNULL, in which case no length will be returned.
+**
+**             gctCONST_STRING * Name
+**                     Pointer to a variable receiving the pointer to the output name.
+**                     'Name' can be gcvNULL, in which case no name will be returned.
+*/
+gceSTATUS
+gcOUTPUT_GetName(
+       IN gcOUTPUT Output,
+       OUT gctSIZE_T * Length,
+       OUT gctCONST_STRING * Name
+       );
+
+/*******************************************************************************
+*********************************************************** F U N C T I O N S **
+*******************************************************************************/
+
+/*******************************************************************************
+**  gcFUNCTION_ReallocateArguments
+**
+**  Reallocate an array of gcsFUNCTION_ARGUMENT objects.
+**
+**  INPUT:
+**
+**      gcFUNCTION Function
+**          Pointer to a gcFUNCTION object.
+**
+**      gctSIZE_T Count
+**          Array count to reallocate.  'Count' must be at least 1.
+*/
+gceSTATUS
+gcFUNCTION_ReallocateArguments(
+    IN gcFUNCTION Function,
+    IN gctSIZE_T Count
+    );
+
+gceSTATUS
+gcFUNCTION_AddArgument(
+       IN gcFUNCTION Function,
+       IN gctUINT16 TempIndex,
+       IN gctUINT8 Enable,
+       IN gctUINT8 Qualifier
+       );
+
+gceSTATUS
+gcFUNCTION_GetArgument(
+       IN gcFUNCTION Function,
+       IN gctUINT16 Index,
+       OUT gctUINT16_PTR Temp,
+       OUT gctUINT8_PTR Enable,
+       OUT gctUINT8_PTR Swizzle
+       );
+
+gceSTATUS
+gcFUNCTION_GetLabel(
+       IN gcFUNCTION Function,
+       OUT gctUINT_PTR Label
+       );
+
+/*******************************************************************************
+************************* K E R N E L    P R O P E R T Y    F U N C T I O N S **
+*******************************************************************************/
+/*******************************************************************************/
+gceSTATUS
+gcKERNEL_FUNCTION_AddKernelFunctionProperties(
+           IN gcKERNEL_FUNCTION KernelFunction,
+               IN gctINT propertyType,
+               IN gctSIZE_T propertySize,
+               IN gctINT * values
+               );
+
+gceSTATUS
+gcKERNEL_FUNCTION_GetPropertyCount(
+    IN gcKERNEL_FUNCTION KernelFunction,
+    OUT gctSIZE_T * Count
+    );
+
+gceSTATUS
+gcKERNEL_FUNCTION_GetProperty(
+    IN gcKERNEL_FUNCTION KernelFunction,
+    IN gctUINT Index,
+       OUT gctSIZE_T * propertySize,
+       OUT gctINT * propertyType,
+       OUT gctINT * propertyValues
+    );
+
+
+/*******************************************************************************
+*******************************I M A G E   S A M P L E R    F U N C T I O N S **
+*******************************************************************************/
+/*******************************************************************************
+**  gcKERNEL_FUNCTION_ReallocateImageSamplers
+**
+**  Reallocate an array of pointers to image sampler pair.
+**
+**  INPUT:
+**
+**      gcKERNEL_FUNCTION KernelFunction
+**          Pointer to a gcKERNEL_FUNCTION object.
+**
+**      gctSIZE_T Count
+**          Array count to reallocate.  'Count' must be at least 1.
+*/
+gceSTATUS
+gcKERNEL_FUNCTION_ReallocateImageSamplers(
+    IN gcKERNEL_FUNCTION KernelFunction,
+    IN gctSIZE_T Count
+    );
+
+gceSTATUS
+gcKERNEL_FUNCTION_AddImageSampler(
+    IN gcKERNEL_FUNCTION KernelFunction,
+    IN gctUINT8 ImageNum,
+    IN gctBOOL IsConstantSamplerType,
+    IN gctUINT32 SamplerType
+    );
+
+gceSTATUS
+gcKERNEL_FUNCTION_GetImageSamplerCount(
+    IN gcKERNEL_FUNCTION KernelFunction,
+    OUT gctSIZE_T * Count
+    );
+
+gceSTATUS
+gcKERNEL_FUNCTION_GetImageSampler(
+    IN gcKERNEL_FUNCTION KernelFunction,
+    IN gctUINT Index,
+    OUT gctUINT8 *ImageNum,
+    OUT gctBOOL *IsConstantSamplerType,
+    OUT gctUINT32 *SamplerType
+    );
+
+/*******************************************************************************
+*********************************************K E R N E L    F U N C T I O N S **
+*******************************************************************************/
+
+/*******************************************************************************
+**  gcKERNEL_FUNCTION_ReallocateArguments
+**
+**  Reallocate an array of gcsFUNCTION_ARGUMENT objects.
+**
+**  INPUT:
+**
+**      gcKERNEL_FUNCTION Function
+**          Pointer to a gcKERNEL_FUNCTION object.
+**
+**      gctSIZE_T Count
+**          Array count to reallocate.  'Count' must be at least 1.
+*/
+gceSTATUS
+gcKERNEL_FUNCTION_ReallocateArguments(
+    IN gcKERNEL_FUNCTION Function,
+    IN gctSIZE_T Count
+    );
+
+gceSTATUS
+gcKERNEL_FUNCTION_AddArgument(
+       IN gcKERNEL_FUNCTION Function,
+       IN gctUINT16 TempIndex,
+       IN gctUINT8 Enable,
+       IN gctUINT8 Qualifier
+       );
+
+gceSTATUS
+gcKERNEL_FUNCTION_GetArgument(
+       IN gcKERNEL_FUNCTION Function,
+       IN gctUINT16 Index,
+       OUT gctUINT16_PTR Temp,
+       OUT gctUINT8_PTR Enable,
+       OUT gctUINT8_PTR Swizzle
+       );
+
+gceSTATUS
+gcKERNEL_FUNCTION_GetLabel(
+       IN gcKERNEL_FUNCTION Function,
+       OUT gctUINT_PTR Label
+       );
+
+gceSTATUS
+gcKERNEL_FUNCTION_GetName(
+    IN gcKERNEL_FUNCTION KernelFunction,
+    OUT gctSIZE_T * Length,
+    OUT gctCONST_STRING * Name
+    );
+
+gceSTATUS
+gcKERNEL_FUNCTION_ReallocateUniformArguments(
+    IN gcKERNEL_FUNCTION KernelFunction,
+    IN gctSIZE_T Count
+    );
+
+gceSTATUS
+gcKERNEL_FUNCTION_AddUniformArgument(
+    IN gcKERNEL_FUNCTION KernelFunction,
+    IN gctCONST_STRING Name,
+    IN gcSHADER_TYPE Type,
+    IN gctSIZE_T Length,
+    OUT gcUNIFORM * UniformArgument
+    );
+
+gceSTATUS
+gcKERNEL_FUNCTION_GetUniformArgumentCount(
+    IN gcKERNEL_FUNCTION KernelFunction,
+    OUT gctSIZE_T * Count
+    );
+
+gceSTATUS
+gcKERNEL_FUNCTION_GetUniformArgument(
+    IN gcKERNEL_FUNCTION KernelFunction,
+    IN gctUINT Index,
+    OUT gcUNIFORM * UniformArgument
+    );
+
+gceSTATUS
+gcKERNEL_FUNCTION_SetCodeEnd(
+    IN gcKERNEL_FUNCTION KernelFunction
+    );
+
+/*******************************************************************************
+**                              gcCompileShader
+********************************************************************************
+**
+**     Compile a shader.
+**
+**     INPUT:
+**
+**             gcoOS Hal
+**                     Pointer to an gcoHAL object.
+**
+**             gctINT ShaderType
+**                     Shader type to compile.  Can be one of the following values:
+**
+**                             gcSHADER_TYPE_VERTEX
+**                                     Compile a vertex shader.
+**
+**                             gcSHADER_TYPE_FRAGMENT
+**                                     Compile a fragment shader.
+**
+**             gctSIZE_T SourceSize
+**                     Size of the source buffer in bytes.
+**
+**             gctCONST_STRING Source
+**                     Pointer to the buffer containing the shader source code.
+**
+**     OUTPUT:
+**
+**             gcSHADER * Binary
+**                     Pointer to a variable receiving the pointer to a gcSHADER object
+**                     containg the compiled shader code.
+**
+**             gctSTRING * Log
+**                     Pointer to a variable receiving a string pointer containging the
+**                     compile log.
+*/
+gceSTATUS
+gcCompileShader(
+       IN gcoHAL Hal,
+       IN gctINT ShaderType,
+       IN gctSIZE_T SourceSize,
+       IN gctCONST_STRING Source,
+       OUT gcSHADER * Binary,
+       OUT gctSTRING * Log
+       );
+
+/*******************************************************************************
+**                              gcOptimizeShader
+********************************************************************************
+**
+**     Optimize a shader.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object holding information about the compiled
+**                     shader.
+**
+**             gctFILE LogFile
+**                     Pointer to an open FILE object.
+*/
+gceSTATUS
+gcOptimizeShader(
+       IN gcSHADER Shader,
+       IN gctFILE LogFile
+       );
+
+/*******************************************************************************
+**                                gcLinkShaders
+********************************************************************************
+**
+**     Link two shaders and generate a harwdare specific state buffer by compiling
+**     the compiler generated code through the resource allocator and code
+**     generator.
+**
+**     INPUT:
+**
+**             gcSHADER VertexShader
+**                     Pointer to a gcSHADER object holding information about the compiled
+**                     vertex shader.
+**
+**             gcSHADER FragmentShader
+**                     Pointer to a gcSHADER object holding information about the compiled
+**                     fragment shader.
+**
+**             gceSHADER_FLAGS Flags
+**                     Compiler flags.  Can be any of the following:
+**
+**                             gcvSHADER_DEAD_CODE       - Dead code elimination.
+**                             gcvSHADER_RESOURCE_USAGE  - Resource usage optimizaion.
+**                             gcvSHADER_OPTIMIZER       - Full optimization.
+**                             gcvSHADER_USE_GL_Z        - Use OpenGL ES Z coordinate.
+**                             gcvSHADER_USE_GL_POSITION - Use OpenGL ES gl_Position.
+**                             gcvSHADER_USE_GL_FACE     - Use OpenGL ES gl_FaceForward.
+**
+**     OUTPUT:
+**
+**             gctSIZE_T * StateBufferSize
+**                     Pointer to a variable receicing the number of bytes in the buffer
+**                     returned in 'StateBuffer'.
+**
+**             gctPOINTER * StateBuffer
+**                     Pointer to a variable receiving a buffer pointer that contains the
+**                     states required to download the shaders into the hardware.
+**
+**             gcsHINT_PTR * Hints
+**                     Pointer to a variable receiving a gcsHINT structure pointer that
+**                     contains information required when loading the shader states.
+*/
+gceSTATUS
+gcLinkShaders(
+       IN gcSHADER VertexShader,
+       IN gcSHADER FragmentShader,
+       IN gceSHADER_FLAGS Flags,
+       OUT gctSIZE_T * StateBufferSize,
+       OUT gctPOINTER * StateBuffer,
+       OUT gcsHINT_PTR * Hints
+       );
+
+/*******************************************************************************
+**                                gcLoadShaders
+********************************************************************************
+**
+**     Load a pre-compiled and pre-linked shader program into the hardware.
+**
+**     INPUT:
+**
+**             gcoHAL Hal
+**                     Pointer to a gcoHAL object.
+**
+**             gctSIZE_T StateBufferSize
+**                     The number of bytes in the 'StateBuffer'.
+**
+**             gctPOINTER StateBuffer
+**                     Pointer to the states that make up the shader program.
+**
+**             gcsHINT_PTR Hints
+**                     Pointer to a gcsHINT structure that contains information required
+**                     when loading the shader states.
+*/
+gceSTATUS
+gcLoadShaders(
+       IN gcoHAL Hal,
+       IN gctSIZE_T StateBufferSize,
+       IN gctPOINTER StateBuffer,
+       IN gcsHINT_PTR Hints
+       );
+
+/*******************************************************************************
+**                                gcSaveProgram
+********************************************************************************
+**
+**     Save pre-compiled shaders and pre-linked programs to a binary file.
+**
+**     INPUT:
+**
+**             gcSHADER VertexShader
+**                     Pointer to vertex shader object.
+**
+**             gcSHADER FragmentShader
+**                     Pointer to fragment shader object.
+**
+**             gctSIZE_T ProgramBufferSize
+**                     Number of bytes in 'ProgramBuffer'.
+**
+**             gctPOINTER ProgramBuffer
+**                     Pointer to buffer containing the program states.
+**
+**             gcsHINT_PTR Hints
+**                     Pointer to HINTS structure for program states.
+**
+**     OUTPUT:
+**
+**             gctPOINTER * Binary
+**                     Pointer to a variable receiving the binary data to be saved.
+**
+**             gctSIZE_T * BinarySize
+**                     Pointer to a variable receiving the number of bytes inside 'Binary'.
+*/
+gceSTATUS
+gcSaveProgram(
+       IN gcSHADER VertexShader,
+       IN gcSHADER FragmentShader,
+       IN gctSIZE_T ProgramBufferSize,
+       IN gctPOINTER ProgramBuffer,
+       IN gcsHINT_PTR Hints,
+       OUT gctPOINTER * Binary,
+       OUT gctSIZE_T * BinarySize
+       );
+
+/*******************************************************************************
+**                                gcLoadProgram
+********************************************************************************
+**
+**     Load pre-compiled shaders and pre-linked programs from a binary file.
+**
+**     INPUT:
+**
+**             gctPOINTER Binary
+**                     Pointer to the binary data loaded.
+**
+**             gctSIZE_T BinarySize
+**                     Number of bytes in 'Binary'.
+**
+**     OUTPUT:
+**
+**             gcSHADER VertexShader
+**                     Pointer to a vertex shader object.
+**
+**             gcSHADER FragmentShader
+**                     Pointer to a fragment shader object.
+**
+**             gctSIZE_T * ProgramBufferSize
+**                     Pointer to a variable receicing the number of bytes in the buffer
+**                     returned in 'ProgramBuffer'.
+**
+**             gctPOINTER * ProgramBuffer
+**                     Pointer to a variable receiving a buffer pointer that contains the
+**                     states required to download the shaders into the hardware.
+**
+**             gcsHINT_PTR * Hints
+**                     Pointer to a variable receiving a gcsHINT structure pointer that
+**                     contains information required when loading the shader states.
+*/
+gceSTATUS
+gcLoadProgram(
+       IN gctPOINTER Binary,
+       IN gctSIZE_T BinarySize,
+       OUT gcSHADER VertexShader,
+       OUT gcSHADER FragmentShader,
+       OUT gctSIZE_T * ProgramBufferSize,
+       OUT gctPOINTER * ProgramBuffer,
+       OUT gcsHINT_PTR * Hints
+       );
+
+/*******************************************************************************
+**                              gcCompileKernel
+********************************************************************************
+**
+**     Compile a OpenCL kernel shader.
+**
+**     INPUT:
+**
+**             gcoOS Hal
+**                     Pointer to an gcoHAL object.
+**
+**             gctSIZE_T SourceSize
+**                     Size of the source buffer in bytes.
+**
+**             gctCONST_STRING Source
+**                     Pointer to the buffer containing the shader source code.
+**
+**     OUTPUT:
+**
+**             gcSHADER * Binary
+**                     Pointer to a variable receiving the pointer to a gcSHADER object
+**                     containg the compiled shader code.
+**
+**             gctSTRING * Log
+**                     Pointer to a variable receiving a string pointer containging the
+**                     compile log.
+*/
+gceSTATUS
+gcCompileKernel(
+       IN gcoHAL Hal,
+       IN gctSIZE_T SourceSize,
+       IN gctCONST_STRING Source,
+       IN gctCONST_STRING Options,
+       OUT gcSHADER * Binary,
+       OUT gctSTRING * Log
+       );
+
+/*******************************************************************************
+**                                gcLinkKernel
+********************************************************************************
+**
+**     Link OpenCL kernel and generate a harwdare specific state buffer by compiling
+**     the compiler generated code through the resource allocator and code
+**     generator.
+**
+**     INPUT:
+**
+**             gcSHADER Kernel
+**                     Pointer to a gcSHADER object holding information about the compiled
+**                     OpenCL kernel.
+**
+**             gceSHADER_FLAGS Flags
+**                     Compiler flags.  Can be any of the following:
+**
+**                             gcvSHADER_DEAD_CODE       - Dead code elimination.
+**                             gcvSHADER_RESOURCE_USAGE  - Resource usage optimizaion.
+**                             gcvSHADER_OPTIMIZER       - Full optimization.
+**                             gcvSHADER_USE_GL_Z        - Use OpenGL ES Z coordinate.
+**                             gcvSHADER_USE_GL_POSITION - Use OpenGL ES gl_Position.
+**                             gcvSHADER_USE_GL_FACE     - Use OpenGL ES gl_FaceForward.
+**
+**     OUTPUT:
+**
+**             gctSIZE_T * StateBufferSize
+**                     Pointer to a variable receiving the number of bytes in the buffer
+**                     returned in 'StateBuffer'.
+**
+**             gctPOINTER * StateBuffer
+**                     Pointer to a variable receiving a buffer pointer that contains the
+**                     states required to download the shaders into the hardware.
+**
+**             gcsHINT_PTR * Hints
+**                     Pointer to a variable receiving a gcsHINT structure pointer that
+**                     contains information required when loading the shader states.
+*/
+gceSTATUS
+gcLinkKernel(
+       IN gcSHADER Kernel,
+       IN gceSHADER_FLAGS Flags,
+       OUT gctSIZE_T * StateBufferSize,
+       OUT gctPOINTER * StateBuffer,
+       OUT gcsHINT_PTR * Hints
+       );
+
+/*******************************************************************************
+**                                gcLoadKernel
+********************************************************************************
+**
+**  Load a pre-compiled and pre-linked kernel program into the hardware.
+**
+**  INPUT:
+**
+**      gctSIZE_T StateBufferSize
+**          The number of bytes in the 'StateBuffer'.
+**
+**      gctPOINTER StateBuffer
+**          Pointer to the states that make up the shader program.
+**
+**      gcsHINT_PTR Hints
+**          Pointer to a gcsHINT structure that contains information required
+**          when loading the shader states.
+*/
+gceSTATUS
+gcLoadKernel(
+    IN gctSIZE_T StateBufferSize,
+    IN gctPOINTER StateBuffer,
+    IN gcsHINT_PTR Hints
+    );
+
+gceSTATUS
+gcInvokeThreadWalker(
+    IN gcsTHREAD_WALKER_INFO_PTR Info
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VIVANTE_NO_3D */
+#endif /* __gc_hal_compiler_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h
new file mode 100644 (file)
index 0000000..9574eb0
--- /dev/null
@@ -0,0 +1,891 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_driver_h_
+#define __gc_hal_driver_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+
+#if gcdENABLE_VG
+#include "gc_hal_driver_vg.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* I/O Control Codes ******************************
+\******************************************************************************/
+
+#define gcvHAL_CLASS                    "galcore"
+#define IOCTL_GCHAL_INTERFACE           30000
+#define IOCTL_GCHAL_KERNEL_INTERFACE    30001
+#define IOCTL_GCHAL_TERMINATE           30002
+
+/******************************************************************************\
+********************************* Command Codes ********************************
+\******************************************************************************/
+
+typedef enum _gceHAL_COMMAND_CODES
+{
+    /* Generic query. */
+    gcvHAL_QUERY_VIDEO_MEMORY,
+    gcvHAL_QUERY_CHIP_IDENTITY,
+
+    /* Contiguous memory. */
+    gcvHAL_ALLOCATE_NON_PAGED_MEMORY,
+    gcvHAL_FREE_NON_PAGED_MEMORY,
+    gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY,
+    gcvHAL_FREE_CONTIGUOUS_MEMORY,
+
+    /* Video memory allocation. */
+    gcvHAL_ALLOCATE_VIDEO_MEMORY,           /* Enforced alignment. */
+    gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY,    /* No alignment. */
+    gcvHAL_FREE_VIDEO_MEMORY,
+
+    /* Physical-to-logical mapping. */
+    gcvHAL_MAP_MEMORY,
+    gcvHAL_UNMAP_MEMORY,
+
+    /* Logical-to-physical mapping. */
+    gcvHAL_MAP_USER_MEMORY,
+    gcvHAL_UNMAP_USER_MEMORY,
+
+    /* Surface lock/unlock. */
+    gcvHAL_LOCK_VIDEO_MEMORY,
+    gcvHAL_UNLOCK_VIDEO_MEMORY,
+
+    /* Event queue. */
+    gcvHAL_EVENT_COMMIT,
+
+    gcvHAL_USER_SIGNAL,
+    gcvHAL_SIGNAL,
+    gcvHAL_WRITE_DATA,
+
+    gcvHAL_COMMIT,
+    gcvHAL_STALL,
+
+    gcvHAL_READ_REGISTER,
+    gcvHAL_WRITE_REGISTER,
+
+    gcvHAL_GET_PROFILE_SETTING,
+    gcvHAL_SET_PROFILE_SETTING,
+
+    gcvHAL_READ_ALL_PROFILE_REGISTERS,
+    gcvHAL_PROFILE_REGISTERS_2D,
+
+    /* Power management. */
+    gcvHAL_SET_POWER_MANAGEMENT_STATE,
+    gcvHAL_QUERY_POWER_MANAGEMENT_STATE,
+
+    gcvHAL_GET_BASE_ADDRESS,
+
+    gcvHAL_SET_IDLE, /* reserved */
+
+    /* Queries. */
+    gcvHAL_QUERY_KERNEL_SETTINGS,
+
+    /* Reset. */
+    gcvHAL_RESET,
+
+    /* Map physical address into handle. */
+    gcvHAL_MAP_PHYSICAL,
+
+    /* Debugger stuff. */
+    gcvHAL_DEBUG,
+
+    /* Cache stuff. */
+    gcvHAL_CACHE,
+
+    /* TimeStamp */
+    gcvHAL_TIMESTAMP,
+
+    /* Database. */
+    gcvHAL_DATABASE,
+
+    /* Version. */
+    gcvHAL_VERSION,
+
+    /* Chip info */
+    gcvHAL_CHIP_INFO,
+
+    /* Process attaching/detaching. */
+    gcvHAL_ATTACH,
+    gcvHAL_DETACH,
+
+    /* Composition. */
+    gcvHAL_COMPOSE,
+
+    /* Set timeOut value */
+    gcvHAL_SET_TIMEOUT,
+
+    /* Frame database. */
+    gcvHAL_GET_FRAME_INFO,
+
+#if gcdENABLE_SHARED_INFO
+    /* Shared info for each process */
+    gcvHAL_GET_SHARED_INFO,
+    gcvHAL_SET_SHARED_INFO,
+#endif
+    gcvHAL_QUERY_COMMAND_BUFFER
+}
+gceHAL_COMMAND_CODES;
+
+/******************************************************************************\
+****************************** Interface Structure *****************************
+\******************************************************************************/
+
+#define gcdMAX_PROFILE_FILE_NAME    128
+
+/* Kernel settings. */
+typedef struct _gcsKERNEL_SETTINGS
+{
+    /* Used RealTime signal between kernel and user. */
+    gctINT signal;
+}
+gcsKERNEL_SETTINGS;
+
+/* gcvHAL_COMPOSE. */
+typedef struct _gcsHAL_COMPOSE * gcsHAL_COMPOSE_PTR;
+typedef struct _gcsHAL_COMPOSE
+{
+    /* Composition state buffer. */
+    IN gctSIZE_T                size;
+    IN gctPHYS_ADDR             physical;
+    IN gctPOINTER               logical;
+
+    /* Composition end signal. */
+    IN gctHANDLE                process;
+    IN gctSIGNAL                signal;
+
+    /* User signals. */
+    IN gctHANDLE                userProcess;
+    IN gctSIGNAL                userSignal1;
+    IN gctSIGNAL                userSignal2;
+
+#if defined(__QNXNTO__)
+    /* Client pulse side-channel connection ID. */
+    IN gctINT32                 coid;
+
+    /* Set by server. */
+    IN gctINT32                 rcvid;
+#endif
+}
+gcsHAL_COMPOSE;
+
+typedef struct _gcsHAL_INTERFACE
+{
+    /* Command code. */
+    gceHAL_COMMAND_CODES        command;
+
+    /* Hardware type. */
+    gceHARDWARE_TYPE            hardwareType;
+
+    /* Status value. */
+    gceSTATUS                   status;
+
+    /* Handle to this interface channel. */
+    gctHANDLE                   handle;
+
+    /* Pid of the client. */
+    gctUINT32                   pid;
+
+    /* Union of command structures. */
+    union _u
+    {
+        /* gcvHAL_GET_BASE_ADDRESS */
+        struct _gcsHAL_GET_BASE_ADDRESS
+        {
+            /* Physical memory address of internal memory. */
+            OUT gctUINT32               baseAddress;
+        }
+        GetBaseAddress;
+
+        /* gcvHAL_QUERY_VIDEO_MEMORY */
+        struct _gcsHAL_QUERY_VIDEO_MEMORY
+        {
+            /* Physical memory address of internal memory. */
+            OUT gctPHYS_ADDR            internalPhysical;
+
+            /* Size in bytes of internal memory.*/
+            OUT gctSIZE_T               internalSize;
+
+            /* Physical memory address of external memory. */
+            OUT gctPHYS_ADDR            externalPhysical;
+
+            /* Size in bytes of external memory.*/
+            OUT gctSIZE_T               externalSize;
+
+            /* Physical memory address of contiguous memory. */
+            OUT gctPHYS_ADDR            contiguousPhysical;
+
+            /* Size in bytes of contiguous memory.*/
+            OUT gctSIZE_T               contiguousSize;
+        }
+        QueryVideoMemory;
+
+        /* gcvHAL_QUERY_CHIP_IDENTITY */
+        struct _gcsHAL_QUERY_CHIP_IDENTITY
+        {
+
+            /* Chip model. */
+            OUT gceCHIPMODEL            chipModel;
+
+            /* Revision value.*/
+            OUT gctUINT32               chipRevision;
+
+            /* Supported feature fields. */
+            OUT gctUINT32               chipFeatures;
+
+            /* Supported minor feature fields. */
+            OUT gctUINT32               chipMinorFeatures;
+
+            /* Supported minor feature 1 fields. */
+            OUT gctUINT32               chipMinorFeatures1;
+
+            /* Supported minor feature 2 fields. */
+            OUT gctUINT32               chipMinorFeatures2;
+
+            /* Supported minor feature 3 fields. */
+            OUT gctUINT32               chipMinorFeatures3;
+
+            /* Number of streams supported. */
+            OUT gctUINT32               streamCount;
+
+            /* Total number of temporary registers per thread. */
+            OUT gctUINT32               registerMax;
+
+            /* Maximum number of threads. */
+            OUT gctUINT32               threadCount;
+
+            /* Number of shader cores. */
+            OUT gctUINT32               shaderCoreCount;
+
+            /* Size of the vertex cache. */
+            OUT gctUINT32               vertexCacheSize;
+
+            /* Number of entries in the vertex output buffer. */
+            OUT gctUINT32               vertexOutputBufferSize;
+
+            /* Number of pixel pipes. */
+            OUT gctUINT32               pixelPipes;
+
+            /* Number of instructions. */
+                       OUT gctUINT32               instructionCount;
+
+            /* Number of constants. */
+                       OUT gctUINT32               numConstants;
+
+                       /* Buffer size */
+                       OUT gctUINT32               bufferSize;
+
+        }
+        QueryChipIdentity;
+
+        /* gcvHAL_MAP_MEMORY */
+        struct _gcsHAL_MAP_MEMORY
+        {
+            /* Physical memory address to map. */
+            IN gctPHYS_ADDR             physical;
+
+            /* Number of bytes in physical memory to map. */
+            IN gctSIZE_T                bytes;
+
+            /* Address of mapped memory. */
+            OUT gctPOINTER              logical;
+        }
+        MapMemory;
+
+        /* gcvHAL_UNMAP_MEMORY */
+        struct _gcsHAL_UNMAP_MEMORY
+        {
+            /* Physical memory address to unmap. */
+            IN gctPHYS_ADDR             physical;
+
+            /* Number of bytes in physical memory to unmap. */
+            IN gctSIZE_T                bytes;
+
+            /* Address of mapped memory to unmap. */
+            IN gctPOINTER               logical;
+        }
+        UnmapMemory;
+
+        /* gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY */
+        struct _gcsHAL_ALLOCATE_LINEAR_VIDEO_MEMORY
+        {
+            /* Number of bytes to allocate. */
+            IN OUT gctUINT              bytes;
+
+            /* Buffer alignment. */
+            IN gctUINT                  alignment;
+
+            /* Type of allocation. */
+            IN gceSURF_TYPE             type;
+
+            /* Memory pool to allocate from. */
+            IN OUT gcePOOL              pool;
+
+            /* Allocated video memory. */
+            OUT gcuVIDMEM_NODE_PTR      node;
+        }
+        AllocateLinearVideoMemory;
+
+        /* gcvHAL_ALLOCATE_VIDEO_MEMORY */
+        struct _gcsHAL_ALLOCATE_VIDEO_MEMORY
+        {
+            /* Width of rectangle to allocate. */
+            IN OUT gctUINT              width;
+
+            /* Height of rectangle to allocate. */
+            IN OUT gctUINT              height;
+
+            /* Depth of rectangle to allocate. */
+            IN gctUINT                  depth;
+
+            /* Format rectangle to allocate in gceSURF_FORMAT. */
+            IN gceSURF_FORMAT           format;
+
+            /* Type of allocation. */
+            IN gceSURF_TYPE             type;
+
+            /* Memory pool to allocate from. */
+            IN OUT gcePOOL              pool;
+
+            /* Allocated video memory. */
+            OUT gcuVIDMEM_NODE_PTR      node;
+        }
+        AllocateVideoMemory;
+
+        /* gcvHAL_FREE_VIDEO_MEMORY */
+        struct _gcsHAL_FREE_VIDEO_MEMORY
+        {
+            /* Allocated video memory. */
+            IN gcuVIDMEM_NODE_PTR       node;
+
+#ifdef __QNXNTO__
+/* TODO: This is part of the unlock - why is it here? */
+            /* Mapped logical address to unmap in user space. */
+            OUT gctPOINTER              memory;
+
+            /* Number of bytes to allocated. */
+            OUT gctSIZE_T               bytes;
+#endif
+        }
+        FreeVideoMemory;
+
+        /* gcvHAL_LOCK_VIDEO_MEMORY */
+        struct _gcsHAL_LOCK_VIDEO_MEMORY
+        {
+            /* Allocated video memory. */
+            IN gcuVIDMEM_NODE_PTR       node;
+
+            /* Cache configuration. */
+            /* Only gcvPOOL_CONTIGUOUS and gcvPOOL_VIRUTAL
+            ** can be configured */
+            IN gctBOOL                  cacheable;
+
+            /* Hardware specific address. */
+            OUT gctUINT32               address;
+
+            /* Mapped logical address. */
+            OUT gctPOINTER              memory;
+        }
+        LockVideoMemory;
+
+        /* gcvHAL_UNLOCK_VIDEO_MEMORY */
+        struct _gcsHAL_UNLOCK_VIDEO_MEMORY
+        {
+            /* Allocated video memory. */
+            IN gcuVIDMEM_NODE_PTR       node;
+
+            /* Type of surface. */
+            IN gceSURF_TYPE             type;
+
+            /* Flag to unlock surface asynchroneously. */
+            IN OUT gctBOOL              asynchroneous;
+        }
+        UnlockVideoMemory;
+
+        /* gcvHAL_ALLOCATE_NON_PAGED_MEMORY */
+        struct _gcsHAL_ALLOCATE_NON_PAGED_MEMORY
+        {
+            /* Number of bytes to allocate. */
+            IN OUT gctSIZE_T            bytes;
+
+            /* Physical address of allocation. */
+            OUT gctPHYS_ADDR            physical;
+
+            /* Logical address of allocation. */
+            OUT gctPOINTER              logical;
+        }
+        AllocateNonPagedMemory;
+
+        /* gcvHAL_FREE_NON_PAGED_MEMORY */
+        struct _gcsHAL_FREE_NON_PAGED_MEMORY
+        {
+            /* Number of bytes allocated. */
+            IN gctSIZE_T                bytes;
+
+            /* Physical address of allocation. */
+            IN gctPHYS_ADDR             physical;
+
+            /* Logical address of allocation. */
+            IN gctPOINTER               logical;
+        }
+        FreeNonPagedMemory;
+
+        /* gcvHAL_EVENT_COMMIT. */
+        struct _gcsHAL_EVENT_COMMIT
+        {
+            /* Event queue. */
+            IN gcsQUEUE_PTR             queue;
+        }
+        Event;
+
+        /* gcvHAL_COMMIT */
+        struct _gcsHAL_COMMIT
+        {
+            /* Context buffer object. */
+            IN gckCONTEXT               context;
+
+            /* Command buffer. */
+            IN gcoCMDBUF                commandBuffer;
+
+            /* State delta buffer. */
+            gcsSTATE_DELTA_PTR          delta;
+
+            /* Event queue. */
+            IN gcsQUEUE_PTR             queue;
+        }
+        Commit;
+
+        /* gcvHAL_MAP_USER_MEMORY */
+        struct _gcsHAL_MAP_USER_MEMORY
+        {
+            /* Base address of user memory to map. */
+            IN gctPOINTER               memory;
+
+            /* Size of user memory in bytes to map. */
+            IN gctSIZE_T                size;
+
+            /* Info record required by gcvHAL_UNMAP_USER_MEMORY. */
+            OUT gctPOINTER              info;
+
+            /* Physical address of mapped memory. */
+            OUT gctUINT32               address;
+        }
+        MapUserMemory;
+
+        /* gcvHAL_UNMAP_USER_MEMORY */
+        struct _gcsHAL_UNMAP_USER_MEMORY
+        {
+            /* Base address of user memory to unmap. */
+            IN gctPOINTER               memory;
+
+            /* Size of user memory in bytes to unmap. */
+            IN gctSIZE_T                size;
+
+            /* Info record returned by gcvHAL_MAP_USER_MEMORY. */
+            IN gctPOINTER               info;
+
+            /* Physical address of mapped memory as returned by
+               gcvHAL_MAP_USER_MEMORY. */
+            IN gctUINT32                address;
+        }
+        UnmapUserMemory;
+#if !USE_NEW_LINUX_SIGNAL
+        /* gcsHAL_USER_SIGNAL  */
+        struct _gcsHAL_USER_SIGNAL
+        {
+            /* Command. */
+            gceUSER_SIGNAL_COMMAND_CODES command;
+
+            /* Signal ID. */
+            IN OUT gctINT               id;
+
+            /* Reset mode. */
+            IN gctBOOL                  manualReset;
+
+            /* Wait timedout. */
+            IN gctUINT32                wait;
+
+            /* State. */
+            IN gctBOOL                  state;
+        }
+        UserSignal;
+#endif
+
+        /* gcvHAL_SIGNAL. */
+        struct _gcsHAL_SIGNAL
+        {
+            /* Signal handle to signal. */
+            IN gctSIGNAL                signal;
+
+            /* Reserved. */
+            IN gctSIGNAL                auxSignal;
+
+            /* Process owning the signal. */
+            IN gctHANDLE                process;
+
+#if defined(__QNXNTO__)
+            /* Client pulse side-channel connection ID. Set by client in gcoOS_CreateSignal. */
+            IN gctINT32                 coid;
+
+            /* Set by server. */
+            IN gctINT32                 rcvid;
+#endif
+            /* Event generated from where of pipeline */
+            IN gceKERNEL_WHERE          fromWhere;
+        }
+        Signal;
+
+        /* gcvHAL_WRITE_DATA. */
+        struct _gcsHAL_WRITE_DATA
+        {
+            /* Address to write data to. */
+            IN gctUINT32                address;
+
+            /* Data to write. */
+            IN gctUINT32                data;
+        }
+        WriteData;
+
+        /* gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY */
+        struct _gcsHAL_ALLOCATE_CONTIGUOUS_MEMORY
+        {
+            /* Number of bytes to allocate. */
+            IN OUT gctSIZE_T            bytes;
+
+            /* Hardware address of allocation. */
+            OUT gctUINT32               address;
+
+            /* Physical address of allocation. */
+            OUT gctPHYS_ADDR            physical;
+
+            /* Logical address of allocation. */
+            OUT gctPOINTER              logical;
+        }
+        AllocateContiguousMemory;
+
+        /* gcvHAL_FREE_CONTIGUOUS_MEMORY */
+        struct _gcsHAL_FREE_CONTIGUOUS_MEMORY
+        {
+            /* Number of bytes allocated. */
+            IN gctSIZE_T                bytes;
+
+            /* Physical address of allocation. */
+            IN gctPHYS_ADDR             physical;
+
+            /* Logical address of allocation. */
+            IN gctPOINTER               logical;
+        }
+        FreeContiguousMemory;
+
+        /* gcvHAL_READ_REGISTER */
+        struct _gcsHAL_READ_REGISTER
+        {
+            /* Logical address of memory to write data to. */
+            IN gctUINT32            address;
+
+            /* Data read. */
+            OUT gctUINT32           data;
+        }
+        ReadRegisterData;
+
+        /* gcvHAL_WRITE_REGISTER */
+        struct _gcsHAL_WRITE_REGISTER
+        {
+            /* Logical address of memory to write data to. */
+            IN gctUINT32            address;
+
+            /* Data read. */
+            IN gctUINT32            data;
+        }
+        WriteRegisterData;
+
+#if VIVANTE_PROFILER
+        /* gcvHAL_GET_PROFILE_SETTING */
+        struct _gcsHAL_GET_PROFILE_SETTING
+        {
+            /* Enable profiling */
+            OUT gctBOOL             enable;
+
+            /* The profile file name */
+            OUT gctCHAR             fileName[gcdMAX_PROFILE_FILE_NAME];
+        }
+        GetProfileSetting;
+
+        /* gcvHAL_SET_PROFILE_SETTING */
+        struct _gcsHAL_SET_PROFILE_SETTING
+        {
+            /* Enable profiling */
+            IN gctBOOL              enable;
+
+            /* The profile file name */
+            IN gctCHAR              fileName[gcdMAX_PROFILE_FILE_NAME];
+        }
+        SetProfileSetting;
+
+        /* gcvHAL_READ_ALL_PROFILE_REGISTERS */
+        struct _gcsHAL_READ_ALL_PROFILE_REGISTERS
+        {
+            /* Data read. */
+            OUT gcsPROFILER_COUNTERS    counters;
+        }
+        RegisterProfileData;
+
+        /* gcvHAL_PROFILE_REGISTERS_2D */
+        struct _gcsHAL_PROFILE_REGISTERS_2D
+        {
+            /* Data read. */
+            OUT gcs2D_PROFILE_PTR       hwProfile2D;
+        }
+        RegisterProfileData2D;
+#endif
+        /* Power management. */
+        /* gcvHAL_SET_POWER_MANAGEMENT_STATE */
+        struct _gcsHAL_SET_POWER_MANAGEMENT
+        {
+            /* Data read. */
+            IN gceCHIPPOWERSTATE        state;
+        }
+        SetPowerManagement;
+
+        /* gcvHAL_QUERY_POWER_MANAGEMENT_STATE */
+        struct _gcsHAL_QUERY_POWER_MANAGEMENT
+        {
+            /* Data read. */
+            OUT gceCHIPPOWERSTATE       state;
+
+            /* Idle query. */
+            OUT gctBOOL                 isIdle;
+        }
+        QueryPowerManagement;
+
+        /* gcvHAL_QUERY_KERNEL_SETTINGS */
+        struct _gcsHAL_QUERY_KERNEL_SETTINGS
+        {
+            /* Settings.*/
+            OUT gcsKERNEL_SETTINGS      settings;
+        }
+        QueryKernelSettings;
+
+        /* gcvHAL_MAP_PHYSICAL */
+        struct _gcsHAL_MAP_PHYSICAL
+        {
+            /* gcvTRUE to map, gcvFALSE to unmap. */
+            IN gctBOOL                  map;
+
+            /* Physical address. */
+            IN OUT gctPHYS_ADDR         physical;
+        }
+        MapPhysical;
+
+        /* gcvHAL_DEBUG */
+        struct _gcsHAL_DEBUG
+        {
+            /* If gcvTRUE, set the debug information. */
+            IN gctBOOL                  set;
+            IN gctUINT32                level;
+            IN gctUINT32                zones;
+            IN gctBOOL                  enable;
+
+            IN gceDEBUG_MESSAGE_TYPE    type;
+            IN gctUINT32                messageSize;
+
+            /* Message to print if not empty. */
+            IN gctCHAR                  message[80];
+        }
+        Debug;
+
+        /* gcvHAL_CACHE */
+        struct _gcsHAL_CACHE
+        {
+            IN gceCACHEOPERATION        operation;
+            IN gctHANDLE                process;
+            IN gctPOINTER               logical;
+            IN gctSIZE_T                bytes;
+            IN gcuVIDMEM_NODE_PTR       node;
+        }
+        Cache;
+
+        /* gcvHAL_TIMESTAMP */
+        struct _gcsHAL_TIMESTAMP
+        {
+            /* Timer select. */
+            IN gctUINT32                timer;
+
+            /* Timer request type (0-stop, 1-start, 2-send delta). */
+            IN gctUINT32                request;
+
+            /* Result of delta time in microseconds. */
+            OUT gctINT32                timeDelta;
+        }
+        TimeStamp;
+
+        /* gcvHAL_DATABASE */
+        struct _gcsHAL_DATABASE
+        {
+            /* Set to gcvTRUE if you want to query a particular process ID.
+            ** Set to gcvFALSE to query the last detached process. */
+            IN gctBOOL                  validProcessID;
+
+            /* Process ID to query. */
+            IN gctUINT32                processID;
+
+            /* Information. */
+            OUT gcuDATABASE_INFO        vidMem;
+            OUT gcuDATABASE_INFO        nonPaged;
+            OUT gcuDATABASE_INFO        contiguous;
+            OUT gcuDATABASE_INFO        gpuIdle;
+        }
+        Database;
+
+        /* gcvHAL_VERSION */
+        struct _gcsHAL_VERSION
+        {
+            /* Major version: N.n.n. */
+            OUT gctINT32                major;
+
+            /* Minor version: n.N.n. */
+            OUT gctINT32                minor;
+
+            /* Patch version: n.n.N. */
+            OUT gctINT32                patch;
+
+            /* Build version. */
+            OUT gctUINT32               build;
+        }
+        Version;
+
+        /* gcvHAL_CHIP_INFO */
+        struct _gcsHAL_CHIP_INFO
+        {
+            /* Chip count. */
+            OUT gctINT32                count;
+
+            /* Chip types. */
+            OUT gceHARDWARE_TYPE        types[gcdCHIP_COUNT];
+        }
+        ChipInfo;
+
+        /* gcvHAL_ATTACH */
+        struct _gcsHAL_ATTACH
+        {
+            /* Context buffer object. */
+            OUT gckCONTEXT              context;
+
+            /* Number of states in the buffer. */
+            OUT gctSIZE_T               stateCount;
+        }
+        Attach;
+
+        /* gcvHAL_DETACH */
+        struct _gcsHAL_DETACH
+        {
+            /* Context buffer object. */
+            IN gckCONTEXT               context;
+        }
+        Detach;
+
+        /* gcvHAL_COMPOSE. */
+        gcsHAL_COMPOSE                  Compose;
+
+        /* gcvHAL_GET_FRAME_INFO. */
+        struct _gcsHAL_GET_FRAME_INFO
+        {
+            OUT gcsHAL_FRAME_INFO *     frameInfo;
+        }
+        GetFrameInfo;
+
+        /* gcvHAL_SET_TIME_OUT. */
+        struct _gcsHAL_SET_TIMEOUT
+        {
+            gctUINT32                   timeOut;
+        }
+        SetTimeOut;
+
+#if gcdENABLE_VG
+               /* gcvHAL_COMMIT */
+               struct _gcsHAL_VGCOMMIT
+               {
+                       /* Context buffer. */
+                       IN gcsVGCONTEXT_PTR                     context;
+
+                       /* Command queue. */
+                       IN gcsVGCMDQUEUE_PTR                    queue;
+
+                       /* Number of entries in the queue. */
+                       IN gctUINT                                      entryCount;
+
+                       /* Task table. */
+                       IN gcsTASK_MASTER_TABLE_PTR     taskTable;
+               }
+               VGCommit;
+
+               /* gcvHAL_QUERY_COMMAND_BUFFER */
+               struct _gcsHAL_QUERY_COMMAND_BUFFER
+               {
+                       /* Command buffer attributes. */
+                       OUT gcsCOMMAND_BUFFER_INFO      information;
+               }
+               QueryCommandBuffer;
+
+#endif
+
+#if gcdENABLE_SHARED_INFO
+        struct _gcsHAL_GET_SHARED_INFO
+        {
+            IN gctUINT32            pid;
+            IN gctUINT32            dataId;
+            IN gcuVIDMEM_NODE_PTR   node;
+            OUT gctUINT8_PTR        data;
+            /* fix size */
+            OUT gctUINT8_PTR        nodeData;
+            gctSIZE_T               size;
+        }
+        GetSharedInfo;
+
+        struct _gcsHAL_SET_SHARED_INFO
+        {
+            IN gctUINT32            dataId;
+            IN gcuVIDMEM_NODE_PTR   node;
+            IN gctUINT8_PTR         data;
+            IN gctUINT8_PTR         nodeData;
+            IN gctSIZE_T            size;
+        }
+        SetSharedInfo;
+#endif
+    }
+    u;
+}
+gcsHAL_INTERFACE;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_driver_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h
new file mode 100644 (file)
index 0000000..aa7fac5
--- /dev/null
@@ -0,0 +1,287 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+
+
+#ifndef __gc_hal_driver_vg_h_
+#define __gc_hal_driver_vg_h_
+
+
+
+#include "gc_hal_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* I/O Control Codes ******************************
+\******************************************************************************/
+
+#define gcvHAL_CLASS            "galcore"
+#define IOCTL_GCHAL_INTERFACE   30000
+
+/******************************************************************************\
+********************************* Command Codes ********************************
+\******************************************************************************/
+
+/******************************************************************************\
+********************* Command buffer information structure. ********************
+\******************************************************************************/
+
+typedef struct _gcsCOMMAND_BUFFER_INFO * gcsCOMMAND_BUFFER_INFO_PTR;
+typedef struct _gcsCOMMAND_BUFFER_INFO
+{
+    /* FE command buffer interrupt ID. */
+    gctINT32                    feBufferInt;
+
+    /* TS overflow interrupt ID. */
+    gctINT32                    tsOverflowInt;
+
+    /* Alignment and mask for the buffer address. */
+    gctUINT                     addressMask;
+    gctSIZE_T                   addressAlignment;
+
+    /* Alignment for each command. */
+    gctSIZE_T                   commandAlignment;
+
+    /* Number of bytes required by the STATE command. */
+    gctSIZE_T                   stateCommandSize;
+
+    /* Number of bytes required by the RESTART command. */
+    gctSIZE_T                   restartCommandSize;
+
+    /* Number of bytes required by the FETCH command. */
+    gctSIZE_T                   fetchCommandSize;
+
+    /* Number of bytes required by the CALL command. */
+    gctSIZE_T                   callCommandSize;
+
+    /* Number of bytes required by the RETURN command. */
+    gctSIZE_T                   returnCommandSize;
+
+    /* Number of bytes required by the EVENT command. */
+    gctSIZE_T                   eventCommandSize;
+
+    /* Number of bytes required by the END command. */
+    gctSIZE_T                   endCommandSize;
+
+    /* Number of bytes reserved at the tail of a static command buffer. */
+    gctSIZE_T                   staticTailSize;
+
+    /* Number of bytes reserved at the tail of a dynamic command buffer. */
+    gctSIZE_T                   dynamicTailSize;
+}
+gcsCOMMAND_BUFFER_INFO;
+
+/******************************************************************************\
+******************************** Task Structures *******************************
+\******************************************************************************/
+
+typedef enum _gceTASK
+{
+    gcvTASK_LINK,
+    gcvTASK_CLUSTER,
+    gcvTASK_INCREMENT,
+    gcvTASK_DECREMENT,
+    gcvTASK_SIGNAL,
+    gcvTASK_LOCKDOWN,
+    gcvTASK_UNLOCK_VIDEO_MEMORY,
+    gcvTASK_FREE_VIDEO_MEMORY,
+    gcvTASK_FREE_CONTIGUOUS_MEMORY,
+    gcvTASK_UNMAP_USER_MEMORY,
+    gcvTASK_UNMAP_MEMORY
+}
+gceTASK;
+
+typedef struct _gcsTASK_HEADER * gcsTASK_HEADER_PTR;
+typedef struct _gcsTASK_HEADER
+{
+    /* Task ID. */
+    IN gceTASK                  id;
+}
+gcsTASK_HEADER;
+
+typedef struct _gcsTASK_LINK * gcsTASK_LINK_PTR;
+typedef struct _gcsTASK_LINK
+{
+    /* Task ID (gcvTASK_LINK). */
+    IN gceTASK                  id;
+
+    /* Pointer to the next task container. */
+    IN gctPOINTER               cotainer;
+
+    /* Pointer to the next task from the next task container. */
+    IN gcsTASK_HEADER_PTR       task;
+}
+gcsTASK_LINK;
+
+typedef struct _gcsTASK_CLUSTER * gcsTASK_CLUSTER_PTR;
+typedef struct _gcsTASK_CLUSTER
+{
+    /* Task ID (gcvTASK_CLUSTER). */
+    IN gceTASK                  id;
+
+    /* Number of tasks in the cluster. */
+    IN gctUINT                  taskCount;
+}
+gcsTASK_CLUSTER;
+
+typedef struct _gcsTASK_INCREMENT * gcsTASK_INCREMENT_PTR;
+typedef struct _gcsTASK_INCREMENT
+{
+    /* Task ID (gcvTASK_INCREMENT). */
+    IN gceTASK                  id;
+
+    /* Address of the variable to increment. */
+    IN gctUINT32                address;
+}
+gcsTASK_INCREMENT;
+
+typedef struct _gcsTASK_DECREMENT * gcsTASK_DECREMENT_PTR;
+typedef struct _gcsTASK_DECREMENT
+{
+    /* Task ID (gcvTASK_DECREMENT). */
+    IN gceTASK                  id;
+
+    /* Address of the variable to decrement. */
+    IN gctUINT32                address;
+}
+gcsTASK_DECREMENT;
+
+typedef struct _gcsTASK_SIGNAL * gcsTASK_SIGNAL_PTR;
+typedef struct _gcsTASK_SIGNAL
+{
+    /* Task ID (gcvTASK_SIGNAL). */
+    IN gceTASK                  id;
+
+    /* Process owning the signal. */
+    IN gctHANDLE                process;
+
+    /* Signal handle to signal. */
+    IN gctSIGNAL                signal;
+}
+gcsTASK_SIGNAL;
+
+typedef struct _gcsTASK_LOCKDOWN * gcsTASK_LOCKDOWN_PTR;
+typedef struct _gcsTASK_LOCKDOWN
+{
+    /* Task ID (gcvTASK_LOCKDOWN). */
+    IN gceTASK                  id;
+
+    /* Address of the user space counter. */
+    IN gctUINT32                userCounter;
+
+    /* Address of the kernel space counter. */
+    IN gctUINT32                kernelCounter;
+
+    /* Process owning the signal. */
+    IN gctHANDLE                process;
+
+    /* Signal handle to signal. */
+    IN gctSIGNAL                signal;
+}
+gcsTASK_LOCKDOWN;
+
+typedef struct _gcsTASK_UNLOCK_VIDEO_MEMORY * gcsTASK_UNLOCK_VIDEO_MEMORY_PTR;
+typedef struct _gcsTASK_UNLOCK_VIDEO_MEMORY
+{
+    /* Task ID (gcvTASK_UNLOCK_VIDEO_MEMORY). */
+    IN gceTASK                  id;
+
+    /* Allocated video memory. */
+    IN gcuVIDMEM_NODE_PTR       node;
+}
+gcsTASK_UNLOCK_VIDEO_MEMORY;
+
+typedef struct _gcsTASK_FREE_VIDEO_MEMORY * gcsTASK_FREE_VIDEO_MEMORY_PTR;
+typedef struct _gcsTASK_FREE_VIDEO_MEMORY
+{
+    /* Task ID (gcvTASK_FREE_VIDEO_MEMORY). */
+    IN gceTASK                  id;
+
+    /* Allocated video memory. */
+    IN gcuVIDMEM_NODE_PTR       node;
+}
+gcsTASK_FREE_VIDEO_MEMORY;
+
+typedef struct _gcsTASK_FREE_CONTIGUOUS_MEMORY * gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR;
+typedef struct _gcsTASK_FREE_CONTIGUOUS_MEMORY
+{
+    /* Task ID (gcvTASK_FREE_CONTIGUOUS_MEMORY). */
+    IN gceTASK                  id;
+
+    /* Number of bytes allocated. */
+    IN gctSIZE_T                bytes;
+
+    /* Physical address of allocation. */
+    IN gctPHYS_ADDR             physical;
+
+    /* Logical address of allocation. */
+    IN gctPOINTER               logical;
+}
+gcsTASK_FREE_CONTIGUOUS_MEMORY;
+
+typedef struct _gcsTASK_UNMAP_USER_MEMORY * gcsTASK_UNMAP_USER_MEMORY_PTR;
+typedef struct _gcsTASK_UNMAP_USER_MEMORY
+{
+    /* Task ID (gcvTASK_UNMAP_USER_MEMORY). */
+    IN gceTASK                  id;
+
+    /* Base address of user memory to unmap. */
+    IN gctPOINTER               memory;
+
+    /* Size of user memory in bytes to unmap. */
+    IN gctSIZE_T                size;
+
+    /* Info record returned by gcvHAL_MAP_USER_MEMORY. */
+    IN gctPOINTER               info;
+
+    /* Physical address of mapped memory as returned by
+       gcvHAL_MAP_USER_MEMORY. */
+    IN gctUINT32                address;
+}
+gcsTASK_UNMAP_USER_MEMORY;
+
+typedef struct _gcsTASK_UNMAP_MEMORY * gcsTASK_UNMAP_MEMORY_PTR;
+typedef struct _gcsTASK_UNMAP_MEMORY
+{
+    /* Task ID (gcvTASK_UNMAP_MEMORY). */
+    IN gceTASK                  id;
+
+    /* Physical memory address to unmap. */
+    IN gctPHYS_ADDR             physical;
+
+    /* Number of bytes in physical memory to unmap. */
+    IN gctSIZE_T                bytes;
+
+    /* Address of mapped memory to unmap. */
+    IN gctPOINTER               logical;
+}
+gcsTASK_UNMAP_MEMORY;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_driver_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h
new file mode 100644 (file)
index 0000000..340bc9b
--- /dev/null
@@ -0,0 +1,89 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+#ifndef __gc_hal_dump_h_
+#define __gc_hal_dump_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+**     FILE LAYOUT:
+**
+**             gcsDUMP_FILE structure
+**
+**             gcsDUMP_DATA frame
+**                     gcsDUMP_DATA or gcDUMP_DATA_SIZE records rendingring the frame
+**                     gctUINT8 data[length]
+*/
+
+#define gcvDUMP_FILE_SIGNATURE         gcmCC('g','c','D','B')
+
+typedef struct _gcsDUMP_FILE
+{
+       gctUINT32               signature;      /* File signature */
+       gctSIZE_T                       length;         /* Length of file */
+       gctUINT32                       frames;         /* Number of frames in file */
+}
+gcsDUMP_FILE;
+
+typedef enum _gceDUMP_TAG
+{
+       gcvTAG_SURFACE                                  = gcmCC('s','u','r','f'),
+       gcvTAG_FRAME                                    = gcmCC('f','r','m',' '),
+       gcvTAG_COMMAND                                  = gcmCC('c','m','d',' '),
+       gcvTAG_INDEX                                    = gcmCC('i','n','d','x'),
+       gcvTAG_STREAM                                   = gcmCC('s','t','r','m'),
+       gcvTAG_TEXTURE                                  = gcmCC('t','e','x','t'),
+       gcvTAG_RENDER_TARGET                    = gcmCC('r','n','d','r'),
+       gcvTAG_DEPTH                                    = gcmCC('z','b','u','f'),
+       gcvTAG_RESOLVE                                  = gcmCC('r','s','l','v'),
+       gcvTAG_DELETE                                   = gcmCC('d','e','l',' '),
+}
+gceDUMP_TAG;
+
+typedef struct _gcsDUMP_SURFACE
+{
+       gceDUMP_TAG                     type;           /* Type of record. */
+       gctUINT32               address;        /* Address of the surface. */
+       gctINT16                width;          /* Width of surface. */
+       gctINT16                        height;         /* Height of surface. */
+       gceSURF_FORMAT          format;         /* Surface pixel format. */
+       gctSIZE_T                       length;         /* Number of bytes inside the surface. */
+}
+gcsDUMP_SURFACE;
+
+typedef struct _gcsDUMP_DATA
+{
+       gceDUMP_TAG                     type;           /* Type of record. */
+       gctSIZE_T               length;         /* Number of bytes of data. */
+       gctUINT32               address;        /* Address for the data. */
+}
+gcsDUMP_DATA;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_dump_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
new file mode 100644 (file)
index 0000000..8389723
--- /dev/null
@@ -0,0 +1,1845 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_engine_h_
+#define __gc_hal_engine_h_
+
+#ifndef VIVANTE_NO_3D
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+
+#if gcdENABLE_VG
+#include "gc_hal_engine_vg.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoSTREAM *             gcoSTREAM;
+typedef struct _gcoVERTEX *             gcoVERTEX;
+typedef struct _gcoTEXTURE *            gcoTEXTURE;
+typedef struct _gcoINDEX *              gcoINDEX;
+typedef struct _gcsVERTEX_ATTRIBUTES *  gcsVERTEX_ATTRIBUTES_PTR;
+typedef struct _gcoVERTEXARRAY *        gcoVERTEXARRAY;
+
+#define gcdATTRIBUTE_COUNT              16
+
+/******************************************************************************\
+********************************* Enumerations *********************************
+\******************************************************************************/
+
+/* Shading format. */
+typedef enum _gceSHADING
+{
+    gcvSHADING_SMOOTH,
+    gcvSHADING_FLAT_D3D,
+    gcvSHADING_FLAT_OPENGL,
+}
+gceSHADING;
+
+/* Culling modes. */
+typedef enum _gceCULL
+{
+    gcvCULL_NONE,
+    gcvCULL_CCW,
+    gcvCULL_CW,
+}
+gceCULL;
+
+/* Fill modes. */
+typedef enum _gceFILL
+{
+    gcvFILL_POINT,
+    gcvFILL_WIRE_FRAME,
+    gcvFILL_SOLID,
+}
+gceFILL;
+
+/* Compare modes. */
+typedef enum _gceCOMPARE
+{
+    gcvCOMPARE_NEVER,
+    gcvCOMPARE_NOT_EQUAL,
+    gcvCOMPARE_LESS,
+    gcvCOMPARE_LESS_OR_EQUAL,
+    gcvCOMPARE_EQUAL,
+    gcvCOMPARE_GREATER,
+    gcvCOMPARE_GREATER_OR_EQUAL,
+    gcvCOMPARE_ALWAYS,
+    gcvCOMPARE_INVALID = -1
+}
+gceCOMPARE;
+
+/* Stencil modes. */
+typedef enum _gceSTENCIL_MODE
+{
+    gcvSTENCIL_NONE,
+    gcvSTENCIL_SINGLE_SIDED,
+    gcvSTENCIL_DOUBLE_SIDED,
+}
+gceSTENCIL_MODE;
+
+/* Stencil operations. */
+typedef enum _gceSTENCIL_OPERATION
+{
+    gcvSTENCIL_KEEP,
+    gcvSTENCIL_REPLACE,
+    gcvSTENCIL_ZERO,
+    gcvSTENCIL_INVERT,
+    gcvSTENCIL_INCREMENT,
+    gcvSTENCIL_DECREMENT,
+    gcvSTENCIL_INCREMENT_SATURATE,
+    gcvSTENCIL_DECREMENT_SATURATE,
+    gcvSTENCIL_OPERATION_INVALID = -1
+}
+gceSTENCIL_OPERATION;
+
+/* Stencil selection. */
+typedef enum _gceSTENCIL_WHERE
+{
+    gcvSTENCIL_FRONT,
+    gcvSTENCIL_BACK,
+}
+gceSTENCIL_WHERE;
+
+/* Texture addressing selection. */
+typedef enum _gceTEXTURE_WHICH
+{
+    gcvTEXTURE_S,
+    gcvTEXTURE_T,
+    gcvTEXTURE_R,
+}
+gceTEXTURE_WHICH;
+
+/* Texture addressing modes. */
+typedef enum _gceTEXTURE_ADDRESSING
+{
+    gcvTEXTURE_WRAP,
+    gcvTEXTURE_CLAMP,
+    gcvTEXTURE_BORDER,
+    gcvTEXTURE_MIRROR,
+    gcvTEXTURE_MIRROR_ONCE,
+}
+gceTEXTURE_ADDRESSING;
+
+/* Texture filters. */
+typedef enum _gceTEXTURE_FILTER
+{
+    gcvTEXTURE_NONE,
+    gcvTEXTURE_POINT,
+    gcvTEXTURE_LINEAR,
+    gcvTEXTURE_ANISOTROPIC,
+}
+gceTEXTURE_FILTER;
+
+/* Primitive types. */
+typedef enum _gcePRIMITIVE
+{
+    gcvPRIMITIVE_POINT_LIST,
+    gcvPRIMITIVE_LINE_LIST,
+    gcvPRIMITIVE_LINE_STRIP,
+    gcvPRIMITIVE_LINE_LOOP,
+    gcvPRIMITIVE_TRIANGLE_LIST,
+    gcvPRIMITIVE_TRIANGLE_STRIP,
+    gcvPRIMITIVE_TRIANGLE_FAN,
+}
+gcePRIMITIVE;
+
+/* Index types. */
+typedef enum _gceINDEX_TYPE
+{
+    gcvINDEX_8,
+    gcvINDEX_16,
+    gcvINDEX_32,
+}
+gceINDEX_TYPE;
+
+/******************************************************************************\
+********************************* gcoHAL Object *********************************
+\******************************************************************************/
+
+/* Query the target capabilities. */
+gceSTATUS
+gcoHAL_QueryTargetCaps(
+    IN gcoHAL Hal,
+    OUT gctUINT * MaxWidth,
+    OUT gctUINT * MaxHeight,
+    OUT gctUINT * MultiTargetCount,
+    OUT gctUINT * MaxSamples
+    );
+
+gceSTATUS
+gcoHAL_SetDepthOnly(
+    IN gcoHAL Hal,
+    IN gctBOOL Enable
+    );
+
+gceSTATUS
+gcoHAL_QueryShaderCaps(
+    IN gcoHAL Hal,
+    OUT gctUINT * VertexUniforms,
+    OUT gctUINT * FragmentUniforms,
+    OUT gctUINT * Varyings
+    );
+
+gceSTATUS
+gcoHAL_QueryTextureCaps(
+    IN gcoHAL Hal,
+    OUT gctUINT * MaxWidth,
+    OUT gctUINT * MaxHeight,
+    OUT gctUINT * MaxDepth,
+    OUT gctBOOL * Cubic,
+    OUT gctBOOL * NonPowerOfTwo,
+    OUT gctUINT * VertexSamplers,
+    OUT gctUINT * PixelSamplers
+    );
+
+gceSTATUS
+gcoHAL_QueryTextureMaxAniso(
+    IN gcoHAL Hal,
+    OUT gctUINT * MaxAnisoValue
+    );
+
+gceSTATUS
+gcoHAL_QueryStreamCaps(
+    IN gcoHAL Hal,
+    OUT gctUINT32 * MaxAttributes,
+    OUT gctUINT32 * MaxStreamSize,
+    OUT gctUINT32 * NumberOfStreams,
+    OUT gctUINT32 * Alignment
+    );
+
+/******************************************************************************\
+********************************* gcoSURF Object ********************************
+\******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/*--------------------------------- gcoSURF 3D --------------------------------*/
+
+/* Copy surface. */
+gceSTATUS
+gcoSURF_Copy(
+    IN gcoSURF Surface,
+    IN gcoSURF Source
+    );
+
+/* Clear surface. */
+gceSTATUS
+gcoSURF_Clear(
+    IN gcoSURF Surface,
+    IN gctUINT Flags
+    );
+
+/* Set number of samples for a gcoSURF object. */
+gceSTATUS
+gcoSURF_SetSamples(
+    IN gcoSURF Surface,
+    IN gctUINT Samples
+    );
+
+/* Get the number of samples per pixel. */
+gceSTATUS
+gcoSURF_GetSamples(
+    IN gcoSURF Surface,
+    OUT gctUINT_PTR Samples
+    );
+
+/* Clear rectangular surface. */
+gceSTATUS
+gcoSURF_ClearRect(
+    IN gcoSURF Surface,
+    IN gctINT Left,
+    IN gctINT Top,
+    IN gctINT Right,
+    IN gctINT Bottom,
+    IN gctUINT Flags
+    );
+
+/* TO BE REMOVED */
+    gceSTATUS
+    depr_gcoSURF_Resolve(
+        IN gcoSURF SrcSurface,
+        IN gcoSURF DestSurface,
+        IN gctUINT32 DestAddress,
+        IN gctPOINTER DestBits,
+        IN gctINT DestStride,
+        IN gceSURF_TYPE DestType,
+        IN gceSURF_FORMAT DestFormat,
+        IN gctUINT DestWidth,
+        IN gctUINT DestHeight
+        );
+
+    gceSTATUS
+    depr_gcoSURF_ResolveRect(
+        IN gcoSURF SrcSurface,
+        IN gcoSURF DestSurface,
+        IN gctUINT32 DestAddress,
+        IN gctPOINTER DestBits,
+        IN gctINT DestStride,
+        IN gceSURF_TYPE DestType,
+        IN gceSURF_FORMAT DestFormat,
+        IN gctUINT DestWidth,
+        IN gctUINT DestHeight,
+        IN gcsPOINT_PTR SrcOrigin,
+        IN gcsPOINT_PTR DestOrigin,
+        IN gcsPOINT_PTR RectSize
+        );
+
+/* Resample surface. */
+gceSTATUS
+gcoSURF_Resample(
+    IN gcoSURF SrcSurface,
+    IN gcoSURF DestSurface
+    );
+
+/* Resolve surface. */
+gceSTATUS
+gcoSURF_Resolve(
+    IN gcoSURF SrcSurface,
+    IN gcoSURF DestSurface
+    );
+
+/* Export the render target */
+gceSTATUS
+gcoSURF_ExportRenderTarget(
+    IN gcoSURF SrcSurface
+);
+
+/* Import the render target */
+gceSTATUS
+gcoSURF_ImportRenderTarget(
+    IN gctUINT32 Pid,
+    IN gcoSURF SrcSurface
+);
+
+/* Save the Resolve info to kernel. */
+gceSTATUS
+gcoSURF_PrepareRemoteResolveRect(
+    IN gcoSURF SrcSurface,
+    IN gcsPOINT_PTR SrcOrigin,
+    IN gcsPOINT_PTR DestOrigin,
+    IN gcsPOINT_PTR RectSize
+    );
+
+/* Using the info that Process Pid saved to do resolve. */
+gceSTATUS
+gcoSURF_RemoteResolveRect(
+    IN gcoSURF SrcSurface,
+    IN gcoSURF DestSurface
+    );
+
+/*
+  Return the "resolve submitted indicator" signal. */
+gceSTATUS
+gcoSURF_GetRTSignal(
+    IN gcoSURF RTSurface,
+    OUT gctSIGNAL * resolveSubmittedSignal
+    );
+
+/* Resolve rectangular area of a surface. */
+gceSTATUS
+gcoSURF_ResolveRect(
+    IN gcoSURF SrcSurface,
+    IN gcoSURF DestSurface,
+    IN gcsPOINT_PTR SrcOrigin,
+    IN gcsPOINT_PTR DestOrigin,
+    IN gcsPOINT_PTR RectSize
+    );
+
+/* Set surface resolvability. */
+gceSTATUS
+gcoSURF_SetResolvability(
+    IN gcoSURF Surface,
+    IN gctBOOL Resolvable
+    );
+
+/* Perform CPU cache operation on surface */
+gceSTATUS
+gcoSURF_CPUCacheOperation(
+    IN gcoSURF Surface,
+    IN gceCACHEOPERATION Operation
+    );
+
+gceSTATUS
+gcoSURF_NODE_Cache(
+    IN gcsSURF_NODE_PTR Node,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes,
+    IN gceCACHEOPERATION Operation
+    );
+
+/******************************************************************************\
+******************************** gcoINDEX Object *******************************
+\******************************************************************************/
+
+/* Construct a new gcoINDEX object. */
+gceSTATUS
+gcoINDEX_Construct(
+    IN gcoHAL Hal,
+    OUT gcoINDEX * Index
+    );
+
+/* Destroy a gcoINDEX object. */
+gceSTATUS
+gcoINDEX_Destroy(
+    IN gcoINDEX Index
+    );
+
+/* Lock index in memory. */
+gceSTATUS
+gcoINDEX_Lock(
+    IN gcoINDEX Index,
+    OUT gctUINT32 * Address,
+    OUT gctPOINTER * Memory
+    );
+
+/* Unlock index that was previously locked with gcoINDEX_Lock. */
+gceSTATUS
+gcoINDEX_Unlock(
+    IN gcoINDEX Index
+    );
+
+/* Upload index data into the memory. */
+gceSTATUS
+gcoINDEX_Load(
+    IN gcoINDEX Index,
+    IN gceINDEX_TYPE IndexType,
+    IN gctUINT32 IndexCount,
+    IN gctPOINTER IndexBuffer
+    );
+
+/* Bind an index object to the hardware. */
+gceSTATUS
+gcoINDEX_Bind(
+    IN gcoINDEX Index,
+    IN gceINDEX_TYPE Type
+    );
+
+/* Bind an index object to the hardware. */
+gceSTATUS
+gcoINDEX_BindOffset(
+    IN gcoINDEX Index,
+    IN gceINDEX_TYPE Type,
+    IN gctUINT32 Offset
+    );
+
+/* Free existing index buffer. */
+gceSTATUS
+gcoINDEX_Free(
+    IN gcoINDEX Index
+    );
+
+/* Upload data into an index buffer. */
+gceSTATUS
+gcoINDEX_Upload(
+    IN gcoINDEX Index,
+    IN gctCONST_POINTER Buffer,
+    IN gctSIZE_T Bytes
+    );
+
+/* Upload data into an index buffer starting at an offset. */
+gceSTATUS
+gcoINDEX_UploadOffset(
+    IN gcoINDEX Index,
+    IN gctUINT32 Offset,
+    IN gctCONST_POINTER Buffer,
+    IN gctSIZE_T Bytes
+    );
+
+/* Query the index capabilities. */
+gceSTATUS
+gcoINDEX_QueryCaps(
+    OUT gctBOOL * Index8,
+    OUT gctBOOL * Index16,
+    OUT gctBOOL * Index32,
+    OUT gctUINT * MaxIndex
+    );
+
+/* Determine the index range in the current index buffer. */
+gceSTATUS
+gcoINDEX_GetIndexRange(
+    IN gcoINDEX Index,
+    IN gceINDEX_TYPE Type,
+    IN gctUINT32 Offset,
+    IN gctUINT32 Count,
+    OUT gctUINT32 * MinimumIndex,
+    OUT gctUINT32 * MaximumIndex
+    );
+
+/* Dynamic buffer management. */
+gceSTATUS
+gcoINDEX_SetDynamic(
+    IN gcoINDEX Index,
+    IN gctSIZE_T Bytes,
+    IN gctUINT Buffers
+    );
+
+gceSTATUS
+gcoINDEX_UploadDynamic(
+    IN gcoINDEX Index,
+    IN gctCONST_POINTER Data,
+    IN gctSIZE_T Bytes
+    );
+
+/******************************************************************************\
+********************************** gco3D Object *********************************
+\******************************************************************************/
+
+/* Clear flags. */
+typedef enum _gceCLEAR
+{
+    gcvCLEAR_COLOR              = 0x1,
+    gcvCLEAR_DEPTH              = 0x2,
+    gcvCLEAR_STENCIL            = 0x4,
+    gcvCLEAR_HZ                 = 0x8,
+    gcvCLEAR_HAS_VAA            = 0x10,
+}
+gceCLEAR;
+
+/* Blending targets. */
+typedef enum _gceBLEND_UNIT
+{
+    gcvBLEND_SOURCE,
+    gcvBLEND_TARGET,
+}
+gceBLEND_UNIT;
+
+/* Construct a new gco3D object. */
+gceSTATUS
+gco3D_Construct(
+    IN gcoHAL Hal,
+    OUT gco3D * Engine
+    );
+
+/* Destroy an gco3D object. */
+gceSTATUS
+gco3D_Destroy(
+    IN gco3D Engine
+    );
+
+/* Set 3D API type. */
+gceSTATUS
+gco3D_SetAPI(
+    IN gco3D Engine,
+    IN gceAPI ApiType
+    );
+
+/* Set render target. */
+gceSTATUS
+gco3D_SetTarget(
+    IN gco3D Engine,
+    IN gcoSURF Surface
+    );
+
+/* Unset render target. */
+gceSTATUS
+gco3D_UnsetTarget(
+    IN gco3D Engine,
+    IN gcoSURF Surface
+    );
+
+/* Set depth buffer. */
+gceSTATUS
+gco3D_SetDepth(
+    IN gco3D Engine,
+    IN gcoSURF Surface
+    );
+
+/* Unset depth buffer. */
+gceSTATUS
+gco3D_UnsetDepth(
+    IN gco3D Engine,
+    IN gcoSURF Surface
+    );
+
+/* Set viewport. */
+gceSTATUS
+gco3D_SetViewport(
+    IN gco3D Engine,
+    IN gctINT32 Left,
+    IN gctINT32 Top,
+    IN gctINT32 Right,
+    IN gctINT32 Bottom
+    );
+
+/* Set scissors. */
+gceSTATUS
+gco3D_SetScissors(
+    IN gco3D Engine,
+    IN gctINT32 Left,
+    IN gctINT32 Top,
+    IN gctINT32 Right,
+    IN gctINT32 Bottom
+    );
+
+/* Set clear color. */
+gceSTATUS
+gco3D_SetClearColor(
+    IN gco3D Engine,
+    IN gctUINT8 Red,
+    IN gctUINT8 Green,
+    IN gctUINT8 Blue,
+    IN gctUINT8 Alpha
+    );
+
+/* Set fixed point clear color. */
+gceSTATUS
+gco3D_SetClearColorX(
+    IN gco3D Engine,
+    IN gctFIXED_POINT Red,
+    IN gctFIXED_POINT Green,
+    IN gctFIXED_POINT Blue,
+    IN gctFIXED_POINT Alpha
+    );
+
+/* Set floating point clear color. */
+gceSTATUS
+gco3D_SetClearColorF(
+    IN gco3D Engine,
+    IN gctFLOAT Red,
+    IN gctFLOAT Green,
+    IN gctFLOAT Blue,
+    IN gctFLOAT Alpha
+    );
+
+/* Set fixed point clear depth. */
+gceSTATUS
+gco3D_SetClearDepthX(
+    IN gco3D Engine,
+    IN gctFIXED_POINT Depth
+    );
+
+/* Set floating point clear depth. */
+gceSTATUS
+gco3D_SetClearDepthF(
+    IN gco3D Engine,
+    IN gctFLOAT Depth
+    );
+
+/* Set clear stencil. */
+gceSTATUS
+gco3D_SetClearStencil(
+    IN gco3D Engine,
+    IN gctUINT32 Stencil
+    );
+
+/* Clear a Rect sub-surface. */
+gceSTATUS
+gco3D_ClearRect(
+    IN gco3D Engine,
+    IN gctUINT32 Address,
+    IN gctPOINTER Memory,
+    IN gctUINT32 Stride,
+    IN gceSURF_FORMAT Format,
+    IN gctINT32 Left,
+    IN gctINT32 Top,
+    IN gctINT32 Right,
+    IN gctINT32 Bottom,
+    IN gctUINT32 Width,
+    IN gctUINT32 Height,
+    IN gctUINT32 Flags
+    );
+
+/* Clear surface. */
+gceSTATUS
+gco3D_Clear(
+    IN gco3D Engine,
+    IN gctUINT32 Address,
+    IN gctUINT32 Stride,
+    IN gceSURF_FORMAT Format,
+    IN gctUINT32 Width,
+    IN gctUINT32 Height,
+    IN gctUINT32 Flags
+    );
+
+
+/* Clear tile status. */
+gceSTATUS
+gco3D_ClearTileStatus(
+    IN gco3D Engine,
+    IN gcsSURF_INFO_PTR Surface,
+    IN gctUINT32 TileStatusAddress,
+    IN gctUINT32 Flags
+    );
+
+/* Set shading mode. */
+gceSTATUS
+gco3D_SetShading(
+    IN gco3D Engine,
+    IN gceSHADING Shading
+    );
+
+/* Set blending mode. */
+gceSTATUS
+gco3D_EnableBlending(
+    IN gco3D Engine,
+    IN gctBOOL Enable
+    );
+
+/* Set blending function. */
+gceSTATUS
+gco3D_SetBlendFunction(
+    IN gco3D Engine,
+    IN gceBLEND_UNIT Unit,
+    IN gceBLEND_FUNCTION FunctionRGB,
+    IN gceBLEND_FUNCTION FunctionAlpha
+    );
+
+/* Set blending mode. */
+gceSTATUS
+gco3D_SetBlendMode(
+    IN gco3D Engine,
+    IN gceBLEND_MODE ModeRGB,
+    IN gceBLEND_MODE ModeAlpha
+    );
+
+/* Set blending color. */
+gceSTATUS
+gco3D_SetBlendColor(
+    IN gco3D Engine,
+    IN gctUINT Red,
+    IN gctUINT Green,
+    IN gctUINT Blue,
+    IN gctUINT Alpha
+    );
+
+/* Set fixed point blending color. */
+gceSTATUS
+gco3D_SetBlendColorX(
+    IN gco3D Engine,
+    IN gctFIXED_POINT Red,
+    IN gctFIXED_POINT Green,
+    IN gctFIXED_POINT Blue,
+    IN gctFIXED_POINT Alpha
+    );
+
+/* Set floating point blending color. */
+gceSTATUS
+gco3D_SetBlendColorF(
+    IN gco3D Engine,
+    IN gctFLOAT Red,
+    IN gctFLOAT Green,
+    IN gctFLOAT Blue,
+    IN gctFLOAT Alpha
+    );
+
+/* Set culling mode. */
+gceSTATUS
+gco3D_SetCulling(
+    IN gco3D Engine,
+    IN gceCULL Mode
+    );
+
+/* Enable point size */
+gceSTATUS
+gco3D_SetPointSizeEnable(
+    IN gco3D Engine,
+    IN gctBOOL Enable
+    );
+
+/* Set point sprite */
+gceSTATUS
+gco3D_SetPointSprite(
+    IN gco3D Engine,
+    IN gctBOOL Enable
+    );
+
+/* Set fill mode. */
+gceSTATUS
+gco3D_SetFill(
+    IN gco3D Engine,
+    IN gceFILL Mode
+    );
+
+/* Set depth compare mode. */
+gceSTATUS
+gco3D_SetDepthCompare(
+    IN gco3D Engine,
+    IN gceCOMPARE Compare
+    );
+
+/* Enable depth writing. */
+gceSTATUS
+gco3D_EnableDepthWrite(
+    IN gco3D Engine,
+    IN gctBOOL Enable
+    );
+
+/* Set depth mode. */
+gceSTATUS
+gco3D_SetDepthMode(
+    IN gco3D Engine,
+    IN gceDEPTH_MODE Mode
+    );
+
+/* Set depth range. */
+gceSTATUS
+gco3D_SetDepthRangeX(
+    IN gco3D Engine,
+    IN gceDEPTH_MODE Mode,
+    IN gctFIXED_POINT Near,
+    IN gctFIXED_POINT Far
+    );
+
+/* Set depth range. */
+gceSTATUS
+gco3D_SetDepthRangeF(
+    IN gco3D Engine,
+    IN gceDEPTH_MODE Mode,
+    IN gctFLOAT Near,
+    IN gctFLOAT Far
+    );
+
+/* Set last pixel enable */
+gceSTATUS
+gco3D_SetLastPixelEnable(
+    IN gco3D Engine,
+    IN gctBOOL Enable
+    );
+
+/* Set depth Bias and Scale */
+gceSTATUS
+gco3D_SetDepthScaleBiasX(
+    IN gco3D Engine,
+    IN gctFIXED_POINT DepthScale,
+    IN gctFIXED_POINT DepthBias
+    );
+
+gceSTATUS
+gco3D_SetDepthScaleBiasF(
+    IN gco3D Engine,
+    IN gctFLOAT DepthScale,
+    IN gctFLOAT DepthBias
+    );
+
+/* Enable or disable dithering. */
+gceSTATUS
+gco3D_EnableDither(
+    IN gco3D Engine,
+    IN gctBOOL Enable
+    );
+
+/* Set color write enable bits. */
+gceSTATUS
+gco3D_SetColorWrite(
+    IN gco3D Engine,
+    IN gctUINT8 Enable
+    );
+
+/* Enable or disable early depth. */
+gceSTATUS
+gco3D_SetEarlyDepth(
+    IN gco3D Engine,
+    IN gctBOOL Enable
+    );
+
+/* Enable or disable all early depth operations. */
+gceSTATUS
+gco3D_SetAllEarlyDepthModes(
+    IN gco3D Engine,
+    IN gctBOOL Disable
+    );
+
+/* Enable or disable depth-only mode. */
+gceSTATUS
+gco3D_SetDepthOnly(
+    IN gco3D Engine,
+    IN gctBOOL Enable
+    );
+
+typedef struct _gcsSTENCIL_INFO * gcsSTENCIL_INFO_PTR;
+typedef struct _gcsSTENCIL_INFO
+{
+    gceSTENCIL_MODE         mode;
+
+    gctUINT8                mask;
+    gctUINT8                writeMask;
+
+    gctUINT8                referenceFront;
+
+    gceCOMPARE              compareFront;
+    gceSTENCIL_OPERATION    passFront;
+    gceSTENCIL_OPERATION    failFront;
+    gceSTENCIL_OPERATION    depthFailFront;
+
+    gctUINT8                referenceBack;
+    gceCOMPARE              compareBack;
+    gceSTENCIL_OPERATION    passBack;
+    gceSTENCIL_OPERATION    failBack;
+    gceSTENCIL_OPERATION    depthFailBack;
+}
+gcsSTENCIL_INFO;
+
+/* Set stencil mode. */
+gceSTATUS
+gco3D_SetStencilMode(
+    IN gco3D Engine,
+    IN gceSTENCIL_MODE Mode
+    );
+
+/* Set stencil mask. */
+gceSTATUS
+gco3D_SetStencilMask(
+    IN gco3D Engine,
+    IN gctUINT8 Mask
+    );
+
+/* Set stencil write mask. */
+gceSTATUS
+gco3D_SetStencilWriteMask(
+    IN gco3D Engine,
+    IN gctUINT8 Mask
+    );
+
+/* Set stencil reference. */
+gceSTATUS
+gco3D_SetStencilReference(
+    IN gco3D Engine,
+    IN gctUINT8 Reference,
+    IN gctBOOL Front
+    );
+
+/* Set stencil compare. */
+gceSTATUS
+gco3D_SetStencilCompare(
+    IN gco3D Engine,
+    IN gceSTENCIL_WHERE Where,
+    IN gceCOMPARE Compare
+    );
+
+/* Set stencil operation on pass. */
+gceSTATUS
+gco3D_SetStencilPass(
+    IN gco3D Engine,
+    IN gceSTENCIL_WHERE Where,
+    IN gceSTENCIL_OPERATION Operation
+    );
+
+/* Set stencil operation on fail. */
+gceSTATUS
+gco3D_SetStencilFail(
+    IN gco3D Engine,
+    IN gceSTENCIL_WHERE Where,
+    IN gceSTENCIL_OPERATION Operation
+    );
+
+/* Set stencil operation on depth fail. */
+gceSTATUS
+gco3D_SetStencilDepthFail(
+    IN gco3D Engine,
+    IN gceSTENCIL_WHERE Where,
+    IN gceSTENCIL_OPERATION Operation
+    );
+
+/* Set all stencil states in one blow. */
+gceSTATUS
+gco3D_SetStencilAll(
+    IN gco3D Engine,
+    IN gcsSTENCIL_INFO_PTR Info
+    );
+
+typedef struct _gcsALPHA_INFO * gcsALPHA_INFO_PTR;
+typedef struct _gcsALPHA_INFO
+{
+    /* Alpha test states. */
+    gctBOOL                 test;
+    gceCOMPARE              compare;
+    gctUINT8                reference;
+
+    /* Alpha blending states. */
+    gctBOOL                 blend;
+
+    gceBLEND_FUNCTION       srcFuncColor;
+    gceBLEND_FUNCTION       srcFuncAlpha;
+    gceBLEND_FUNCTION       trgFuncColor;
+    gceBLEND_FUNCTION       trgFuncAlpha;
+
+    gceBLEND_MODE           modeColor;
+    gceBLEND_MODE           modeAlpha;
+
+    gctUINT32               color;
+}
+gcsALPHA_INFO;
+
+/* Enable or disable alpha test. */
+gceSTATUS
+gco3D_SetAlphaTest(
+    IN gco3D Engine,
+    IN gctBOOL Enable
+    );
+
+/* Set alpha test compare. */
+gceSTATUS
+gco3D_SetAlphaCompare(
+    IN gco3D Engine,
+    IN gceCOMPARE Compare
+    );
+
+/* Set alpha test reference in unsigned integer. */
+gceSTATUS
+gco3D_SetAlphaReference(
+    IN gco3D Engine,
+    IN gctUINT8 Reference
+    );
+
+/* Set alpha test reference in fixed point. */
+gceSTATUS
+gco3D_SetAlphaReferenceX(
+    IN gco3D Engine,
+    IN gctFIXED_POINT Reference
+    );
+
+/* Set alpha test reference in floating point. */
+gceSTATUS
+gco3D_SetAlphaReferenceF(
+    IN gco3D Engine,
+    IN gctFLOAT Reference
+    );
+
+/* Enable/Disable anti-alias line. */
+gceSTATUS
+gco3D_SetAntiAliasLine(
+    IN gco3D Engine,
+    IN gctBOOL Enable
+    );
+
+/* Set texture slot for anti-alias line. */
+gceSTATUS
+gco3D_SetAALineTexSlot(
+    IN gco3D Engine,
+    IN gctUINT TexSlot
+    );
+
+/* Set anti-alias line width scale. */
+gceSTATUS
+gco3D_SetAALineWidth(
+    IN gco3D Engine,
+    IN gctFLOAT Width
+    );
+
+/* Draw a number of primitives. */
+gceSTATUS
+gco3D_DrawPrimitives(
+    IN gco3D Engine,
+    IN gcePRIMITIVE Type,
+    IN gctINT StartVertex,
+    IN gctSIZE_T PrimitiveCount
+    );
+
+gceSTATUS
+gco3D_DrawPrimitivesCount(
+    IN gco3D Engine,
+    IN gcePRIMITIVE Type,
+    IN gctINT* StartVertex,
+    IN gctSIZE_T* VertexCount,
+    IN gctSIZE_T PrimitiveCount
+    );
+
+
+/* Draw a number of primitives using offsets. */
+gceSTATUS
+gco3D_DrawPrimitivesOffset(
+    IN gco3D Engine,
+    IN gcePRIMITIVE Type,
+    IN gctINT32 StartOffset,
+    IN gctSIZE_T PrimitiveCount
+    );
+
+/* Draw a number of indexed primitives. */
+gceSTATUS
+gco3D_DrawIndexedPrimitives(
+    IN gco3D Engine,
+    IN gcePRIMITIVE Type,
+    IN gctINT BaseVertex,
+    IN gctINT StartIndex,
+    IN gctSIZE_T PrimitiveCount
+    );
+
+/* Draw a number of indexed primitives using offsets. */
+gceSTATUS
+gco3D_DrawIndexedPrimitivesOffset(
+    IN gco3D Engine,
+    IN gcePRIMITIVE Type,
+    IN gctINT32 BaseOffset,
+    IN gctINT32 StartOffset,
+    IN gctSIZE_T PrimitiveCount
+    );
+
+/* Enable or disable anti-aliasing. */
+gceSTATUS
+gco3D_SetAntiAlias(
+    IN gco3D Engine,
+    IN gctBOOL Enable
+    );
+
+/* Write data into the command buffer. */
+gceSTATUS
+gco3D_WriteBuffer(
+    IN gco3D Engine,
+    IN gctCONST_POINTER Data,
+    IN gctSIZE_T Bytes,
+    IN gctBOOL Aligned
+    );
+
+/* Send sempahore and stall until sempahore is signalled. */
+gceSTATUS
+gco3D_Semaphore(
+    IN gco3D Engine,
+    IN gceWHERE From,
+    IN gceWHERE To,
+    IN gceHOW How);
+
+/* Set the subpixels center. */
+gceSTATUS
+gco3D_SetCentroids(
+    IN gco3D Engine,
+    IN gctUINT32 Index,
+    IN gctPOINTER Centroids
+    );
+
+gceSTATUS
+gco3D_SetLogicOp(
+    IN gco3D Engine,
+    IN gctUINT8 Rop
+    );
+
+/* OCL thread walker information. */
+typedef struct _gcsTHREAD_WALKER_INFO * gcsTHREAD_WALKER_INFO_PTR;
+typedef struct _gcsTHREAD_WALKER_INFO
+{
+    gctUINT32   dimensions;
+    gctUINT32   traverseOrder;
+    gctUINT32   enableSwathX;
+    gctUINT32   enableSwathY;
+    gctUINT32   enableSwathZ;
+    gctUINT32   swathSizeX;
+    gctUINT32   swathSizeY;
+    gctUINT32   swathSizeZ;
+    gctUINT32   valueOrder;
+
+    gctUINT32   globalSizeX;
+    gctUINT32   globalOffsetX;
+    gctUINT32   globalSizeY;
+    gctUINT32   globalOffsetY;
+    gctUINT32   globalSizeZ;
+    gctUINT32   globalOffsetZ;
+
+    gctUINT32   workGroupSizeX;
+    gctUINT32   workGroupCountX;
+    gctUINT32   workGroupSizeY;
+    gctUINT32   workGroupCountY;
+    gctUINT32   workGroupSizeZ;
+    gctUINT32   workGroupCountZ;
+
+    gctUINT32   threadAllocation;
+}
+gcsTHREAD_WALKER_INFO;
+
+/* Start OCL thread walker. */
+gceSTATUS
+gco3D_InvokeThreadWalker(
+    IN gco3D Engine,
+    IN gcsTHREAD_WALKER_INFO_PTR Info
+    );
+
+/*----------------------------------------------------------------------------*/
+/*-------------------------- gco3D Fragment Processor ------------------------*/
+
+/* Set the fragment processor configuration. */
+gceSTATUS
+gco3D_SetFragmentConfiguration(
+    IN gco3D Engine,
+    IN gctBOOL ColorFromStream,
+    IN gctBOOL EnableFog,
+    IN gctBOOL EnableSmoothPoint,
+    IN gctUINT32 ClipPlanes
+    );
+
+/* Enable/disable texture stage operation. */
+gceSTATUS
+gco3D_EnableTextureStage(
+    IN gco3D Engine,
+    IN gctINT Stage,
+    IN gctBOOL Enable
+    );
+
+/* Program the channel enable masks for the color texture function. */
+gceSTATUS
+gco3D_SetTextureColorMask(
+    IN gco3D Engine,
+    IN gctINT Stage,
+    IN gctBOOL ColorEnabled,
+    IN gctBOOL AlphaEnabled
+    );
+
+/* Program the channel enable masks for the alpha texture function. */
+gceSTATUS
+gco3D_SetTextureAlphaMask(
+    IN gco3D Engine,
+    IN gctINT Stage,
+    IN gctBOOL ColorEnabled,
+    IN gctBOOL AlphaEnabled
+    );
+
+/* Program the constant fragment color. */
+gceSTATUS
+gco3D_SetFragmentColorX(
+    IN gco3D Engine,
+    IN gctFIXED_POINT Red,
+    IN gctFIXED_POINT Green,
+    IN gctFIXED_POINT Blue,
+    IN gctFIXED_POINT Alpha
+    );
+
+gceSTATUS
+gco3D_SetFragmentColorF(
+    IN gco3D Engine,
+    IN gctFLOAT Red,
+    IN gctFLOAT Green,
+    IN gctFLOAT Blue,
+    IN gctFLOAT Alpha
+    );
+
+/* Program the constant fog color. */
+gceSTATUS
+gco3D_SetFogColorX(
+    IN gco3D Engine,
+    IN gctFIXED_POINT Red,
+    IN gctFIXED_POINT Green,
+    IN gctFIXED_POINT Blue,
+    IN gctFIXED_POINT Alpha
+    );
+
+gceSTATUS
+gco3D_SetFogColorF(
+    IN gco3D Engine,
+    IN gctFLOAT Red,
+    IN gctFLOAT Green,
+    IN gctFLOAT Blue,
+    IN gctFLOAT Alpha
+    );
+
+/* Program the constant texture color. */
+gceSTATUS
+gco3D_SetTetxureColorX(
+    IN gco3D Engine,
+    IN gctINT Stage,
+    IN gctFIXED_POINT Red,
+    IN gctFIXED_POINT Green,
+    IN gctFIXED_POINT Blue,
+    IN gctFIXED_POINT Alpha
+    );
+
+gceSTATUS
+gco3D_SetTetxureColorF(
+    IN gco3D Engine,
+    IN gctINT Stage,
+    IN gctFLOAT Red,
+    IN gctFLOAT Green,
+    IN gctFLOAT Blue,
+    IN gctFLOAT Alpha
+    );
+
+/* Configure color texture function. */
+gceSTATUS
+gco3D_SetColorTextureFunction(
+    IN gco3D Engine,
+    IN gctINT Stage,
+    IN gceTEXTURE_FUNCTION Function,
+    IN gceTEXTURE_SOURCE Source0,
+    IN gceTEXTURE_CHANNEL Channel0,
+    IN gceTEXTURE_SOURCE Source1,
+    IN gceTEXTURE_CHANNEL Channel1,
+    IN gceTEXTURE_SOURCE Source2,
+    IN gceTEXTURE_CHANNEL Channel2,
+    IN gctINT Scale
+    );
+
+/* Configure alpha texture function. */
+gceSTATUS
+gco3D_SetAlphaTextureFunction(
+    IN gco3D Engine,
+    IN gctINT Stage,
+    IN gceTEXTURE_FUNCTION Function,
+    IN gceTEXTURE_SOURCE Source0,
+    IN gceTEXTURE_CHANNEL Channel0,
+    IN gceTEXTURE_SOURCE Source1,
+    IN gceTEXTURE_CHANNEL Channel1,
+    IN gceTEXTURE_SOURCE Source2,
+    IN gceTEXTURE_CHANNEL Channel2,
+    IN gctINT Scale
+    );
+
+/* Invoke OCL thread walker. */
+gceSTATUS
+gcoHARDWARE_InvokeThreadWalker(
+    IN gcsTHREAD_WALKER_INFO_PTR Info
+    );
+
+/******************************************************************************\
+******************************* gcoTEXTURE Object *******************************
+\******************************************************************************/
+
+/* Cube faces. */
+typedef enum _gceTEXTURE_FACE
+{
+    gcvFACE_NONE,
+    gcvFACE_POSITIVE_X,
+    gcvFACE_NEGATIVE_X,
+    gcvFACE_POSITIVE_Y,
+    gcvFACE_NEGATIVE_Y,
+    gcvFACE_POSITIVE_Z,
+    gcvFACE_NEGATIVE_Z,
+}
+gceTEXTURE_FACE;
+
+typedef struct _gcsTEXTURE
+{
+    /* Addressing modes. */
+    gceTEXTURE_ADDRESSING       s;
+    gceTEXTURE_ADDRESSING       t;
+    gceTEXTURE_ADDRESSING       r;
+
+    /* Border color. */
+    gctUINT8                    border[4];
+
+    /* Filters. */
+    gceTEXTURE_FILTER           minFilter;
+    gceTEXTURE_FILTER           magFilter;
+    gceTEXTURE_FILTER           mipFilter;
+    gctUINT                     anisoFilter;
+
+    /* Level of detail. */
+    gctFIXED_POINT              lodBias;
+    gctFIXED_POINT              lodMin;
+    gctFIXED_POINT              lodMax;
+}
+gcsTEXTURE, * gcsTEXTURE_PTR;
+
+/* Construct a new gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Construct(
+    IN gcoHAL Hal,
+    OUT gcoTEXTURE * Texture
+    );
+
+/* Construct a new sized gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_ConstructSized(
+    IN gcoHAL Hal,
+    IN gceSURF_FORMAT Format,
+    IN gctUINT Width,
+    IN gctUINT Height,
+    IN gctUINT Depth,
+    IN gctUINT Faces,
+    IN gctUINT MipMapCount,
+    IN gcePOOL Pool,
+    OUT gcoTEXTURE * Texture
+    );
+
+/* Destroy an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Destroy(
+    IN gcoTEXTURE Texture
+    );
+
+/* Upload data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Upload(
+    IN gcoTEXTURE Texture,
+    IN gceTEXTURE_FACE Face,
+    IN gctUINT Width,
+    IN gctUINT Height,
+    IN gctUINT Slice,
+    IN gctCONST_POINTER Memory,
+    IN gctINT Stride,
+    IN gceSURF_FORMAT Format
+    );
+
+/* Upload data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_UploadSub(
+    IN gcoTEXTURE Texture,
+    IN gctUINT MipMap,
+    IN gceTEXTURE_FACE Face,
+    IN gctUINT X,
+    IN gctUINT Y,
+    IN gctUINT Width,
+    IN gctUINT Height,
+    IN gctUINT Slice,
+    IN gctCONST_POINTER Memory,
+    IN gctINT Stride,
+    IN gceSURF_FORMAT Format
+    );
+
+/* Upload compressed data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_UploadCompressed(
+    IN gcoTEXTURE Texture,
+    IN gceTEXTURE_FACE Face,
+    IN gctUINT Width,
+    IN gctUINT Height,
+    IN gctUINT Slice,
+    IN gctCONST_POINTER Memory,
+    IN gctSIZE_T Bytes
+    );
+
+/* Get gcoSURF object for a mipmap level. */
+gceSTATUS
+gcoTEXTURE_GetMipMap(
+    IN gcoTEXTURE Texture,
+    IN gctUINT MipMap,
+    OUT gcoSURF * Surface
+    );
+
+/* Get gcoSURF object for a mipmap level and face offset. */
+gceSTATUS
+gcoTEXTURE_GetMipMapFace(
+    IN gcoTEXTURE Texture,
+    IN gctUINT MipMap,
+    IN gceTEXTURE_FACE Face,
+    OUT gcoSURF * Surface,
+    OUT gctUINT32_PTR Offset
+    );
+
+gceSTATUS
+gcoTEXTURE_AddMipMap(
+    IN gcoTEXTURE Texture,
+    IN gctINT Level,
+    IN gceSURF_FORMAT Format,
+    IN gctUINT Width,
+    IN gctUINT Height,
+    IN gctUINT Depth,
+    IN gctUINT Faces,
+    IN gcePOOL Pool,
+    OUT gcoSURF * Surface
+    );
+
+gceSTATUS
+gcoTEXTURE_AddMipMapFromClient(
+    IN gcoTEXTURE Texture,
+    IN gctINT     Level,
+    IN gcoSURF    Surface
+    );
+
+gceSTATUS
+gcoTEXTURE_AddMipMapFromSurface(
+    IN gcoTEXTURE Texture,
+    IN gctINT     Level,
+    IN gcoSURF    Surface
+    );
+
+gceSTATUS
+gcoTEXTURE_SetEndianHint(
+    IN gcoTEXTURE Texture,
+    IN gceENDIAN_HINT EndianHint
+    );
+
+gceSTATUS
+gcoTEXTURE_Disable(
+    IN gcoHAL Hal,
+    IN gctINT Sampler
+    );
+
+gceSTATUS
+gcoTEXTURE_Flush(
+    IN gcoTEXTURE Texture
+    );
+
+gceSTATUS
+gcoTEXTURE_QueryCaps(
+    IN  gcoHAL    Hal,
+    OUT gctUINT * MaxWidth,
+    OUT gctUINT * MaxHeight,
+    OUT gctUINT * MaxDepth,
+    OUT gctBOOL * Cubic,
+    OUT gctBOOL * NonPowerOfTwo,
+    OUT gctUINT * VertexSamplers,
+    OUT gctUINT * PixelSamplers
+    );
+
+gceSTATUS
+gcoTEXTURE_GetClosestFormat(
+    IN gcoHAL Hal,
+    IN gceSURF_FORMAT InFormat,
+    OUT gceSURF_FORMAT* OutFormat
+    );
+
+gceSTATUS
+gcoTEXTURE_RenderIntoMipMap(
+    IN gcoTEXTURE Texture,
+    IN gctINT Level
+    );
+
+gceSTATUS
+gcoTEXTURE_IsRenderable(
+    IN gcoTEXTURE Texture,
+    IN gctUINT Level
+    );
+
+gceSTATUS
+gcoTEXTURE_IsComplete(
+    IN gcoTEXTURE Texture,
+    IN gctINT MaxLevel
+    );
+
+gceSTATUS
+gcoTEXTURE_BindTexture(
+    IN gcoTEXTURE Texture,
+    IN gctINT Target,
+    IN gctINT Sampler,
+    IN gcsTEXTURE_PTR Info
+    );
+
+/******************************************************************************\
+******************************* gcoSTREAM Object ******************************
+\******************************************************************************/
+
+typedef enum _gceVERTEX_FORMAT
+{
+    gcvVERTEX_BYTE,
+    gcvVERTEX_UNSIGNED_BYTE,
+    gcvVERTEX_SHORT,
+    gcvVERTEX_UNSIGNED_SHORT,
+    gcvVERTEX_INT,
+    gcvVERTEX_UNSIGNED_INT,
+    gcvVERTEX_FIXED,
+    gcvVERTEX_HALF,
+    gcvVERTEX_FLOAT,
+    gcvVERTEX_UNSIGNED_INT_10_10_10_2,
+    gcvVERTEX_INT_10_10_10_2,
+}
+gceVERTEX_FORMAT;
+
+gceSTATUS
+gcoSTREAM_Construct(
+    IN gcoHAL Hal,
+    OUT gcoSTREAM * Stream
+    );
+
+gceSTATUS
+gcoSTREAM_Destroy(
+    IN gcoSTREAM Stream
+    );
+
+gceSTATUS
+gcoSTREAM_Upload(
+    IN gcoSTREAM Stream,
+    IN gctCONST_POINTER Buffer,
+    IN gctUINT32 Offset,
+    IN gctSIZE_T Bytes,
+    IN gctBOOL Dynamic
+    );
+
+gceSTATUS
+gcoSTREAM_SetStride(
+    IN gcoSTREAM Stream,
+    IN gctUINT32 Stride
+    );
+
+gceSTATUS
+gcoSTREAM_Lock(
+    IN gcoSTREAM Stream,
+    OUT gctPOINTER * Logical,
+    OUT gctUINT32 * Physical
+    );
+
+gceSTATUS
+gcoSTREAM_Unlock(
+    IN gcoSTREAM Stream
+    );
+
+gceSTATUS
+gcoSTREAM_Reserve(
+    IN gcoSTREAM Stream,
+    IN gctSIZE_T Bytes
+    );
+
+gceSTATUS
+gcoSTREAM_Flush(
+    IN gcoSTREAM Stream
+    );
+
+/* Dynamic buffer API. */
+gceSTATUS
+gcoSTREAM_SetDynamic(
+    IN gcoSTREAM Stream,
+    IN gctSIZE_T Bytes,
+    IN gctUINT Buffers
+    );
+
+typedef struct _gcsSTREAM_INFO
+{
+    gctUINT             index;
+    gceVERTEX_FORMAT    format;
+    gctBOOL             normalized;
+    gctUINT             components;
+    gctSIZE_T           size;
+    gctCONST_POINTER    data;
+    gctUINT             stride;
+}
+gcsSTREAM_INFO, * gcsSTREAM_INFO_PTR;
+
+gceSTATUS
+gcoSTREAM_UploadDynamic(
+    IN gcoSTREAM Stream,
+    IN gctUINT VertexCount,
+    IN gctUINT InfoCount,
+    IN gcsSTREAM_INFO_PTR Info,
+    IN gcoVERTEX Vertex
+    );
+
+gceSTATUS
+gcoSTREAM_CPUCacheOperation(
+    IN gcoSTREAM Stream,
+    IN gceCACHEOPERATION Operation
+    );
+
+/******************************************************************************\
+******************************** gcoVERTEX Object ******************************
+\******************************************************************************/
+
+typedef struct _gcsVERTEX_ATTRIBUTES
+{
+    gceVERTEX_FORMAT            format;
+    gctBOOL                     normalized;
+    gctUINT32                   components;
+    gctSIZE_T                   size;
+    gctUINT32                   stream;
+    gctUINT32                   offset;
+    gctUINT32                   stride;
+}
+gcsVERTEX_ATTRIBUTES;
+
+gceSTATUS
+gcoVERTEX_Construct(
+    IN gcoHAL Hal,
+    OUT gcoVERTEX * Vertex
+    );
+
+gceSTATUS
+gcoVERTEX_Destroy(
+    IN gcoVERTEX Vertex
+    );
+
+gceSTATUS
+gcoVERTEX_Reset(
+    IN gcoVERTEX Vertex
+    );
+
+gceSTATUS
+gcoVERTEX_EnableAttribute(
+    IN gcoVERTEX Vertex,
+    IN gctUINT32 Index,
+    IN gceVERTEX_FORMAT Format,
+    IN gctBOOL Normalized,
+    IN gctUINT32 Components,
+    IN gcoSTREAM Stream,
+    IN gctUINT32 Offset,
+    IN gctUINT32 Stride
+    );
+
+gceSTATUS
+gcoVERTEX_DisableAttribute(
+    IN gcoVERTEX Vertex,
+    IN gctUINT32 Index
+    );
+
+gceSTATUS
+gcoVERTEX_Bind(
+    IN gcoVERTEX Vertex
+    );
+
+/*******************************************************************************
+***** gcoVERTEXARRAY Object ***************************************************/
+
+typedef struct _gcsVERTEXARRAY
+{
+    /* Enabled. */
+    gctBOOL             enable;
+
+    /* Number of components. */
+    gctINT              size;
+
+    /* Attribute format. */
+    gceVERTEX_FORMAT    format;
+
+    /* Flag whether the attribute is normalized or not. */
+    gctBOOL             normalized;
+
+    /* Stride of the component. */
+    gctUINT             stride;
+
+    /* Pointer to the attribute data. */
+    gctCONST_POINTER    pointer;
+
+    /* Stream object owning the attribute data. */
+    gcoSTREAM           stream;
+
+    /* Generic values for attribute. */
+    gctFLOAT            genericValue[4];
+
+    /* Vertex shader linkage. */
+    gctUINT             linkage;
+}
+gcsVERTEXARRAY,
+* gcsVERTEXARRAY_PTR;
+
+gceSTATUS
+gcoVERTEXARRAY_Construct(
+    IN gcoHAL Hal,
+    OUT gcoVERTEXARRAY * Vertex
+    );
+
+gceSTATUS
+gcoVERTEXARRAY_Destroy(
+    IN gcoVERTEXARRAY Vertex
+    );
+
+gceSTATUS
+gcoVERTEXARRAY_Bind(
+    IN gcoVERTEXARRAY Vertex,
+    IN gctUINT32 EnableBits,
+    IN gcsVERTEXARRAY_PTR VertexArray,
+    IN gctUINT First,
+    IN gctSIZE_T Count,
+    IN gceINDEX_TYPE IndexType,
+    IN gcoINDEX IndexObject,
+    IN gctPOINTER IndexMemory,
+    IN OUT gcePRIMITIVE * PrimitiveType,
+    IN OUT gctUINT * PrimitiveCount
+    );
+
+/*******************************************************************************
+***** Composition *************************************************************/
+
+typedef enum _gceCOMPOSITION
+{
+    gcvCOMPOSE_CLEAR = 1,
+    gcvCOMPOSE_BLUR,
+    gcvCOMPOSE_DIM,
+    gcvCOMPOSE_LAYER
+}
+gceCOMPOSITION;
+
+typedef struct _gcsCOMPOSITION * gcsCOMPOSITION_PTR;
+typedef struct _gcsCOMPOSITION
+{
+    /* Structure size. */
+    gctUINT                         structSize;
+
+    /* Composition operation. */
+    gceCOMPOSITION                  operation;
+
+    /* Layer to be composed. */
+    gcoSURF                         layer;
+
+    /* Rotation angle. */
+    gceSURF_ROTATION                rotation;
+
+    /* Source and target coordinates. */
+    gcsRECT                         srcRect;
+    gcsRECT                         trgRect;
+
+    /* Blending parameters. */
+    gctBOOL                         enableBlending;
+    gctBOOL                         premultiplied;
+    gctUINT8                        alphaValue;
+
+    /* Clear color. */
+    gctFLOAT                        r;
+    gctFLOAT                        g;
+    gctFLOAT                        b;
+    gctFLOAT                        a;
+}
+gcsCOMPOSITION;
+
+gceSTATUS
+gco3D_ProbeComposition(
+    gctBOOL ResetIfEmpty
+    );
+
+gceSTATUS
+gco3D_CompositionBegin(
+    void
+    );
+
+gceSTATUS
+gco3D_ComposeLayer(
+    IN gcsCOMPOSITION_PTR Layer
+    );
+
+gceSTATUS
+gco3D_CompositionSignals(
+    IN gctHANDLE Process,
+    IN gctSIGNAL Signal1,
+    IN gctSIGNAL Signal2
+    );
+
+gceSTATUS
+gco3D_CompositionEnd(
+    IN gcoSURF Target,
+    IN gctBOOL Synchronous
+    );
+
+/* Frame Database */
+gceSTATUS
+gcoHAL_AddFrameDB(
+    void
+    );
+
+gceSTATUS
+gcoHAL_DumpFrameDB(
+    gctCONST_STRING Filename OPTIONAL
+    );
+
+gceSTATUS
+gcoHAL_GetSharedInfo(
+    IN gctUINT32 Pid,
+    IN gctUINT32 DataId,
+    OUT gctUINT8_PTR Data,
+    IN gctSIZE_T Bytes,
+    IN gcuVIDMEM_NODE_PTR Node,
+    OUT gctUINT8_PTR NodeData
+    );
+
+gceSTATUS
+gcoHAL_SetSharedInfo(
+    IN gctUINT32 DataId,
+    IN gctUINT8_PTR Data,
+    IN gctSIZE_T Bytes,
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctUINT8_PTR NodeData
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VIVANTE_NO_3D */
+#endif /* __gc_hal_engine_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h
new file mode 100644 (file)
index 0000000..2724193
--- /dev/null
@@ -0,0 +1,908 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+
+
+#ifndef __gc_hal_engine_vg_h_
+#define __gc_hal_engine_vg_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "gc_hal_types.h"
+
+/******************************************************************************\
+******************************** VG Enumerations *******************************
+\******************************************************************************/
+
+/**
+**  @ingroup gcoVG
+**
+**  @brief  Tiling mode for painting and imagig.
+**
+**  This enumeration defines the tiling modes supported by the HAL.  This is
+**  in fact a one-to-one mapping of the OpenVG 1.1 tile modes.
+*/
+typedef enum _gceTILE_MODE
+{
+    gcvTILE_FILL,
+    gcvTILE_PAD,
+    gcvTILE_REPEAT,
+    gcvTILE_REFLECT
+}
+gceTILE_MODE;
+
+/******************************************************************************/
+/** @ingroup gcoVG
+**
+**  @brief  The different paint modes.
+**
+**  This enumeration lists the available paint modes.
+*/
+typedef enum _gcePAINT_TYPE
+{
+    /** Solid color. */
+    gcvPAINT_MODE_SOLID,
+
+    /** Linear gradient. */
+    gcvPAINT_MODE_LINEAR,
+
+    /** Radial gradient. */
+    gcvPAINT_MODE_RADIAL,
+
+    /** Pattern. */
+    gcvPAINT_MODE_PATTERN,
+
+    /** Mode count. */
+    gcvPAINT_MODE_COUNT
+}
+gcePAINT_TYPE;
+
+/**
+** @ingroup gcoVG
+**
+**  @brief Types of path data supported by HAL.
+**
+**  This enumeration defines the types of path data supported by the HAL.
+**  This is in fact a one-to-one mapping of the OpenVG 1.1 path types.
+*/
+typedef enum _gcePATHTYPE
+{
+    gcePATHTYPE_UNKNOWN = -1,
+    gcePATHTYPE_INT8,
+    gcePATHTYPE_INT16,
+    gcePATHTYPE_INT32,
+    gcePATHTYPE_FLOAT
+}
+gcePATHTYPE;
+
+/**
+** @ingroup gcoVG
+**
+**  @brief Supported path segment commands.
+**
+**  This enumeration defines the path segment commands supported by the HAL.
+*/
+typedef enum _gceVGCMD
+{
+    gcvVGCMD_END,                        /*  0: GCCMD_TS_OPCODE_END           */
+    gcvVGCMD_CLOSE,                      /*  1: GCCMD_TS_OPCODE_CLOSE         */
+    gcvVGCMD_MOVE,                       /*  2: GCCMD_TS_OPCODE_MOVE          */
+    gcvVGCMD_MOVE_REL,                   /*  3: GCCMD_TS_OPCODE_MOVE_REL      */
+    gcvVGCMD_LINE,                       /*  4: GCCMD_TS_OPCODE_LINE          */
+    gcvVGCMD_LINE_REL,                   /*  5: GCCMD_TS_OPCODE_LINE_REL      */
+    gcvVGCMD_QUAD,                       /*  6: GCCMD_TS_OPCODE_QUADRATIC     */
+    gcvVGCMD_QUAD_REL,                   /*  7: GCCMD_TS_OPCODE_QUADRATIC_REL */
+    gcvVGCMD_CUBIC,                      /*  8: GCCMD_TS_OPCODE_CUBIC         */
+    gcvVGCMD_CUBIC_REL,                  /*  9: GCCMD_TS_OPCODE_CUBIC_REL     */
+    gcvVGCMD_BREAK,                      /* 10: GCCMD_TS_OPCODE_BREAK         */
+    gcvVGCMD_HLINE,                      /* 11: ******* R E S E R V E D *******/
+    gcvVGCMD_HLINE_REL,                  /* 12: ******* R E S E R V E D *******/
+    gcvVGCMD_VLINE,                      /* 13: ******* R E S E R V E D *******/
+    gcvVGCMD_VLINE_REL,                  /* 14: ******* R E S E R V E D *******/
+    gcvVGCMD_SQUAD,                      /* 15: ******* R E S E R V E D *******/
+    gcvVGCMD_SQUAD_REL,                  /* 16: ******* R E S E R V E D *******/
+    gcvVGCMD_SCUBIC,                     /* 17: ******* R E S E R V E D *******/
+    gcvVGCMD_SCUBIC_REL,                 /* 18: ******* R E S E R V E D *******/
+    gcvVGCMD_SCCWARC,                    /* 19: ******* R E S E R V E D *******/
+    gcvVGCMD_SCCWARC_REL,                /* 20: ******* R E S E R V E D *******/
+    gcvVGCMD_SCWARC,                     /* 21: ******* R E S E R V E D *******/
+    gcvVGCMD_SCWARC_REL,                 /* 22: ******* R E S E R V E D *******/
+    gcvVGCMD_LCCWARC,                    /* 23: ******* R E S E R V E D *******/
+    gcvVGCMD_LCCWARC_REL,                /* 24: ******* R E S E R V E D *******/
+    gcvVGCMD_LCWARC,                     /* 25: ******* R E S E R V E D *******/
+    gcvVGCMD_LCWARC_REL,                 /* 26: ******* R E S E R V E D *******/
+
+    /* The width of the command recognized by the hardware on bits. */
+    gcvVGCMD_WIDTH = 5,
+
+    /* Hardware command mask. */
+    gcvVGCMD_MASK = (1 << gcvVGCMD_WIDTH) - 1,
+
+    /* Command modifiers. */
+    gcvVGCMD_H_MOD   = 1 << gcvVGCMD_WIDTH,  /* =  32 */
+    gcvVGCMD_V_MOD   = 2 << gcvVGCMD_WIDTH,  /* =  64 */
+    gcvVGCMD_S_MOD   = 3 << gcvVGCMD_WIDTH,  /* =  96 */
+    gcvVGCMD_ARC_MOD = 4 << gcvVGCMD_WIDTH,  /* = 128 */
+
+    /* Emulated LINE commands. */
+    gcvVGCMD_HLINE_EMUL     = gcvVGCMD_H_MOD | gcvVGCMD_LINE,        /* =  36 */
+    gcvVGCMD_HLINE_EMUL_REL = gcvVGCMD_H_MOD | gcvVGCMD_LINE_REL,    /* =  37 */
+    gcvVGCMD_VLINE_EMUL     = gcvVGCMD_V_MOD | gcvVGCMD_LINE,        /* =  68 */
+    gcvVGCMD_VLINE_EMUL_REL = gcvVGCMD_V_MOD | gcvVGCMD_LINE_REL,    /* =  69 */
+
+    /* Emulated SMOOTH commands. */
+    gcvVGCMD_SQUAD_EMUL      = gcvVGCMD_S_MOD | gcvVGCMD_QUAD,       /* = 102 */
+    gcvVGCMD_SQUAD_EMUL_REL  = gcvVGCMD_S_MOD | gcvVGCMD_QUAD_REL,   /* = 103 */
+    gcvVGCMD_SCUBIC_EMUL     = gcvVGCMD_S_MOD | gcvVGCMD_CUBIC,      /* = 104 */
+    gcvVGCMD_SCUBIC_EMUL_REL = gcvVGCMD_S_MOD | gcvVGCMD_CUBIC_REL,  /* = 105 */
+
+    /* Emulation ARC commands. */
+    gcvVGCMD_ARC_LINE     = gcvVGCMD_ARC_MOD | gcvVGCMD_LINE,        /* = 132 */
+    gcvVGCMD_ARC_LINE_REL = gcvVGCMD_ARC_MOD | gcvVGCMD_LINE_REL,    /* = 133 */
+    gcvVGCMD_ARC_QUAD     = gcvVGCMD_ARC_MOD | gcvVGCMD_QUAD,        /* = 134 */
+    gcvVGCMD_ARC_QUAD_REL = gcvVGCMD_ARC_MOD | gcvVGCMD_QUAD_REL     /* = 135 */
+}
+gceVGCMD;
+typedef enum _gceVGCMD * gceVGCMD_PTR;
+
+/**
+**  @ingroup gcoVG
+**
+**  @brief  Blending modes supported by the HAL.
+**
+**  This enumeration defines the blending modes supported by the HAL.  This is
+**  in fact a one-to-one mapping of the OpenVG 1.1 blending modes.
+*/
+typedef enum _gceVG_BLEND
+{
+    gcvVG_BLEND_SRC,
+    gcvVG_BLEND_SRC_OVER,
+    gcvVG_BLEND_DST_OVER,
+    gcvVG_BLEND_SRC_IN,
+    gcvVG_BLEND_DST_IN,
+    gcvVG_BLEND_MULTIPLY,
+    gcvVG_BLEND_SCREEN,
+    gcvVG_BLEND_DARKEN,
+    gcvVG_BLEND_LIGHTEN,
+    gcvVG_BLEND_ADDITIVE,
+    gcvVG_BLEND_SUBTRACT,
+    gcvVG_BLEND_FILTER
+}
+gceVG_BLEND;
+
+/**
+**  @ingroup gcoVG
+**
+**  @brief  Image modes supported by the HAL.
+**
+**  This enumeration defines the image modes supported by the HAL.  This is
+**  in fact a one-to-one mapping of the OpenVG 1.1 image modes with the addition
+**  of NO IMAGE.
+*/
+typedef enum _gceVG_IMAGE
+{
+    gcvVG_IMAGE_NONE,
+    gcvVG_IMAGE_NORMAL,
+    gcvVG_IMAGE_MULTIPLY,
+    gcvVG_IMAGE_STENCIL,
+    gcvVG_IMAGE_FILTER
+}
+gceVG_IMAGE;
+
+/**
+**  @ingroup gcoVG
+**
+**  @brief  Filter mode patterns and imaging.
+**
+**  This enumeration defines the filter modes supported by the HAL.
+*/
+typedef enum _gceIMAGE_FILTER
+{
+    gcvFILTER_POINT,
+    gcvFILTER_LINEAR,
+    gcvFILTER_BI_LINEAR
+}
+gceIMAGE_FILTER;
+
+/**
+**  @ingroup gcoVG
+**
+**  @brief  Primitive modes supported by the HAL.
+**
+**  This enumeration defines the primitive modes supported by the HAL.
+*/
+typedef enum _gceVG_PRIMITIVE
+{
+    gcvVG_SCANLINE,
+    gcvVG_RECTANGLE,
+    gcvVG_TESSELLATED,
+    gcvVG_TESSELLATED_TILED
+}
+gceVG_PRIMITIVE;
+
+/**
+**  @ingroup gcoVG
+**
+**  @brief  Rendering quality modes supported by the HAL.
+**
+**  This enumeration defines the rendering quality modes supported by the HAL.
+*/
+typedef enum _gceRENDER_QUALITY
+{
+    gcvVG_NONANTIALIASED,
+    gcvVG_2X2_MSAA,
+    gcvVG_2X4_MSAA,
+    gcvVG_4X4_MSAA
+}
+gceRENDER_QUALITY;
+
+/**
+**  @ingroup gcoVG
+**
+**  @brief  Fill rules supported by the HAL.
+**
+**  This enumeration defines the fill rules supported by the HAL.
+*/
+typedef enum _gceFILL_RULE
+{
+    gcvVG_EVEN_ODD,
+    gcvVG_NON_ZERO
+}
+gceFILL_RULE;
+
+/**
+**  @ingroup gcoVG
+**
+**  @brief  Cap styles supported by the HAL.
+**
+**  This enumeration defines the cap styles supported by the HAL.
+*/
+typedef enum _gceCAP_STYLE
+{
+    gcvCAP_BUTT,
+    gcvCAP_ROUND,
+    gcvCAP_SQUARE
+}
+gceCAP_STYLE;
+
+/**
+**  @ingroup gcoVG
+**
+**  @brief  Join styles supported by the HAL.
+**
+**  This enumeration defines the join styles supported by the HAL.
+*/
+typedef enum _gceJOIN_STYLE
+{
+    gcvJOIN_MITER,
+    gcvJOIN_ROUND,
+    gcvJOIN_BEVEL
+}
+gceJOIN_STYLE;
+
+/**
+**  @ingroup gcoVG
+**
+**  @brief  Channel mask values.
+**
+**  This enumeration defines the values for channel mask used in image
+**  filtering.
+*/
+
+/* Base values for channel mask definitions. */
+#define gcvCHANNEL_X    (0)
+#define gcvCHANNEL_R    (1 << 0)
+#define gcvCHANNEL_G    (1 << 1)
+#define gcvCHANNEL_B    (1 << 2)
+#define gcvCHANNEL_A    (1 << 3)
+
+typedef enum _gceCHANNEL
+{
+    gcvCHANNEL_XXXX = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X),
+    gcvCHANNEL_XXXA = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_A),
+    gcvCHANNEL_XXBX = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_X),
+    gcvCHANNEL_XXBA = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_A),
+
+    gcvCHANNEL_XGXX = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_X),
+    gcvCHANNEL_XGXA = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_A),
+    gcvCHANNEL_XGBX = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_X),
+    gcvCHANNEL_XGBA = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_A),
+
+    gcvCHANNEL_RXXX = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X),
+    gcvCHANNEL_RXXA = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_A),
+    gcvCHANNEL_RXBX = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_X),
+    gcvCHANNEL_RXBA = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_A),
+
+    gcvCHANNEL_RGXX = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_X),
+    gcvCHANNEL_RGXA = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_A),
+    gcvCHANNEL_RGBX = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_X),
+    gcvCHANNEL_RGBA = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_A),
+}
+gceCHANNEL;
+
+/******************************************************************************\
+******************************** VG Structures *******************************
+\******************************************************************************/
+
+/**
+**  @ingroup    gcoVG
+**
+**  @brief      Definition of the color ramp used by the gradient paints.
+**
+**  The gcsCOLOR_RAMP structure defines the layout of one single color inside
+**  a color ramp which is used by gradient paints.
+*/
+typedef struct _gcsCOLOR_RAMP
+{
+    /** Value for the color stop. */
+    gctFLOAT        stop;
+
+    /** Red color channel value for the color stop. */
+    gctFLOAT        red;
+
+    /** Green color channel value for the color stop. */
+    gctFLOAT        green;
+
+    /** Blue color channel value for the color stop. */
+    gctFLOAT        blue;
+
+    /** Alpha color channel value for the color stop. */
+    gctFLOAT        alpha;
+}
+gcsCOLOR_RAMP, * gcsCOLOR_RAMP_PTR;
+
+/**
+**  @ingroup    gcoVG
+**
+**  @brief      Definition of the color ramp used by the gradient paints in fixed form.
+**
+**  The gcsCOLOR_RAMP structure defines the layout of one single color inside
+**  a color ramp which is used by gradient paints.
+*/
+typedef struct _gcsFIXED_COLOR_RAMP
+{
+    /** Value for the color stop. */
+    gctFIXED_POINT      stop;
+
+    /** Red color channel value for the color stop. */
+    gctFIXED_POINT      red;
+
+    /** Green color channel value for the color stop. */
+    gctFIXED_POINT      green;
+
+    /** Blue color channel value for the color stop. */
+    gctFIXED_POINT      blue;
+
+    /** Alpha color channel value for the color stop. */
+    gctFIXED_POINT      alpha;
+}
+gcsFIXED_COLOR_RAMP, * gcsFIXED_COLOR_RAMP_PTR;
+
+
+/**
+**  @ingroup gcoVG
+**
+**  @brief  Rectangle structure used by the gcoVG object.
+**
+**  This structure defines the layout of a rectangle.  Make sure width and
+**  height are larger than 0.
+*/
+typedef struct _gcsVG_RECT * gcsVG_RECT_PTR;
+typedef struct _gcsVG_RECT
+{
+    /** Left location of the rectangle. */
+    gctINT      x;
+
+    /** Top location of the rectangle. */
+    gctINT      y;
+
+    /** Width of the rectangle. */
+    gctINT      width;
+
+    /** Height of the rectangle. */
+    gctINT      height;
+}
+gcsVG_RECT;
+
+/**
+**  @ingroup    gcoVG
+**
+**  @brief      Path command buffer attribute structure.
+**
+**  The gcsPATH_BUFFER_INFO structure contains the specifics about
+**  the layout of the path data command buffer.
+*/
+typedef struct _gcsPATH_BUFFER_INFO * gcsPATH_BUFFER_INFO_PTR;
+typedef struct _gcsPATH_BUFFER_INFO
+{
+    gctUINT     reservedForHead;
+    gctUINT     reservedForTail;
+}
+gcsPATH_BUFFER_INFO;
+
+/**
+**  @ingroup    gcoVG
+**
+**  @brief      Definition of the path data container structure.
+**
+**  The gcsPATH structure defines the layout of the path data container.
+*/
+typedef struct _gcsPATH_DATA * gcsPATH_DATA_PTR;
+typedef struct _gcsPATH_DATA
+{
+    /* Data container in command buffer format. */
+    gcsCMDBUFFER    data;
+
+    /* Path data type. */
+    gcePATHTYPE     dataType;
+}
+gcsPATH_DATA;
+
+
+/******************************************************************************\
+********************************* gcoHAL Object ********************************
+\******************************************************************************/
+
+/* Query path data storage attributes. */
+gceSTATUS
+gcoHAL_QueryPathStorage(
+    IN gcoHAL Hal,
+    OUT gcsPATH_BUFFER_INFO_PTR Information
+    );
+
+/* Associate a completion signal with the command buffer. */
+gceSTATUS
+gcoHAL_AssociateCompletion(
+    IN gcoHAL Hal,
+    IN gcsPATH_DATA_PTR PathData
+    );
+
+/* Release the current command buffer completion signal. */
+gceSTATUS
+gcoHAL_DeassociateCompletion(
+    IN gcoHAL Hal,
+    IN gcsPATH_DATA_PTR PathData
+    );
+
+/* Verify whether the command buffer is still in use. */
+gceSTATUS
+gcoHAL_CheckCompletion(
+    IN gcoHAL Hal,
+    IN gcsPATH_DATA_PTR PathData
+    );
+
+/* Wait until the command buffer is no longer in use. */
+gceSTATUS
+gcoHAL_WaitCompletion(
+    IN gcoHAL Hal,
+    IN gcsPATH_DATA_PTR PathData
+    );
+
+/* Flush the pixel cache. */
+gceSTATUS
+gcoHAL_Flush(
+    IN gcoHAL Hal
+    );
+
+/* Split a harwdare address into pool and offset. */
+gceSTATUS
+gcoHAL_SplitAddress(
+    IN gcoHAL Hal,
+    IN gctUINT32 Address,
+    OUT gcePOOL * Pool,
+    OUT gctUINT32 * Offset
+    );
+
+/* Combine pool and offset into a harwdare address. */
+gceSTATUS
+gcoHAL_CombineAddress(
+    IN gcoHAL Hal,
+    IN gcePOOL Pool,
+    IN gctUINT32 Offset,
+    OUT gctUINT32 * Address
+    );
+
+/* Schedule to free linear video memory allocated. */
+gceSTATUS
+gcoHAL_ScheduleVideoMemory(
+    IN gcoHAL Hal,
+    IN gcuVIDMEM_NODE_PTR Node
+    );
+
+/* Free linear video memory allocated with gcoHAL_AllocateLinearVideoMemory. */
+gceSTATUS
+gcoHAL_FreeVideoMemory(
+    IN gcoHAL Hal,
+    IN gcuVIDMEM_NODE_PTR Node
+    );
+
+/* Query command buffer attributes. */
+gceSTATUS
+gcoHAL_QueryCommandBuffer(
+    IN gcoHAL Hal,
+    OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+    );
+/* Allocate and lock linear video memory. */
+gceSTATUS
+gcoHAL_AllocateLinearVideoMemory(
+    IN gcoHAL Hal,
+    IN gctUINT Size,
+    IN gctUINT Alignment,
+    IN gcePOOL Pool,
+    OUT gcuVIDMEM_NODE_PTR * Node,
+    OUT gctUINT32 * Address,
+    OUT gctPOINTER * Memory
+    );
+
+/* Align the specified size accordingly to the hardware requirements. */
+gceSTATUS
+gcoHAL_GetAlignedSurfaceSize(
+    IN gcoHAL Hal,
+    IN gceSURF_TYPE Type,
+    IN OUT gctUINT32_PTR Width,
+    IN OUT gctUINT32_PTR Height
+    );
+
+gceSTATUS
+gcoHAL_ReserveTask(
+    IN gcoHAL Hal,
+    IN gceBLOCK Block,
+    IN gctUINT TaskCount,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Memory
+    );
+/******************************************************************************\
+********************************** gcoVG Object ********************************
+\******************************************************************************/
+
+/** @defgroup gcoVG gcoVG
+**
+**  The gcoVG object abstracts the VG hardware pipe.
+*/
+
+gctBOOL
+gcoVG_IsMaskSupported(
+    IN gceSURF_FORMAT Format
+    );
+
+gctBOOL
+gcoVG_IsTargetSupported(
+    IN gceSURF_FORMAT Format
+    );
+
+gctBOOL
+gcoVG_IsImageSupported(
+    IN gceSURF_FORMAT Format
+    );
+
+gctUINT8 gcoVG_PackColorComponent(
+    gctFLOAT Value
+    );
+
+gceSTATUS
+gcoVG_Construct(
+    IN gcoHAL Hal,
+    OUT gcoVG * Vg
+    );
+
+gceSTATUS
+gcoVG_Destroy(
+    IN gcoVG Vg
+    );
+
+gceSTATUS
+gcoVG_SetTarget(
+    IN gcoVG Vg,
+    IN gcoSURF Target
+    );
+
+gceSTATUS
+gcoVG_UnsetTarget(
+    IN gcoVG Vg,
+    IN gcoSURF Surface
+    );
+
+gceSTATUS
+gcoVG_SetUserToSurface(
+    IN gcoVG Vg,
+    IN gctFLOAT UserToSurface[9]
+    );
+
+gceSTATUS
+gcoVG_SetSurfaceToImage(
+    IN gcoVG Vg,
+    IN gctFLOAT SurfaceToImage[9]
+    );
+
+gceSTATUS
+gcoVG_EnableMask(
+    IN gcoVG Vg,
+    IN gctBOOL Enable
+    );
+
+gceSTATUS
+gcoVG_SetMask(
+    IN gcoVG Vg,
+    IN gcoSURF Mask
+    );
+
+gceSTATUS
+gcoVG_UnsetMask(
+    IN gcoVG Vg,
+    IN gcoSURF Surface
+    );
+
+gceSTATUS
+gcoVG_FlushMask(
+    IN gcoVG Vg
+    );
+
+gceSTATUS
+gcoVG_EnableScissor(
+    IN gcoVG Vg,
+    IN gctBOOL Enable
+    );
+
+gceSTATUS
+gcoVG_SetScissor(
+    IN gcoVG Vg,
+    IN gctSIZE_T RectangleCount,
+    IN gcsVG_RECT_PTR Rectangles
+    );
+
+gceSTATUS
+gcoVG_EnableColorTransform(
+    IN gcoVG Vg,
+    IN gctBOOL Enable
+    );
+
+gceSTATUS
+gcoVG_SetColorTransform(
+    IN gcoVG Vg,
+    IN gctFLOAT ColorTransform[8]
+    );
+
+gceSTATUS
+gcoVG_SetTileFillColor(
+    IN gcoVG Vg,
+    IN gctFLOAT Red,
+    IN gctFLOAT Green,
+    IN gctFLOAT Blue,
+    IN gctFLOAT Alpha
+    );
+
+gceSTATUS
+gcoVG_SetSolidPaint(
+    IN gcoVG Vg,
+    IN gctUINT8 Red,
+    IN gctUINT8 Green,
+    IN gctUINT8 Blue,
+    IN gctUINT8 Alpha
+    );
+
+gceSTATUS
+gcoVG_SetLinearPaint(
+    IN gcoVG Vg,
+    IN gctFLOAT Constant,
+    IN gctFLOAT StepX,
+    IN gctFLOAT StepY
+    );
+
+gceSTATUS
+gcoVG_SetRadialPaint(
+    IN gcoVG Vg,
+    IN gctFLOAT LinConstant,
+    IN gctFLOAT LinStepX,
+    IN gctFLOAT LinStepY,
+    IN gctFLOAT RadConstant,
+    IN gctFLOAT RadStepX,
+    IN gctFLOAT RadStepY,
+    IN gctFLOAT RadStepXX,
+    IN gctFLOAT RadStepYY,
+    IN gctFLOAT RadStepXY
+    );
+
+gceSTATUS
+gcoVG_SetPatternPaint(
+    IN gcoVG Vg,
+    IN gctFLOAT UConstant,
+    IN gctFLOAT UStepX,
+    IN gctFLOAT UStepY,
+    IN gctFLOAT VConstant,
+    IN gctFLOAT VStepX,
+    IN gctFLOAT VStepY,
+    IN gctBOOL Linear
+    );
+
+gceSTATUS
+gcoVG_SetColorRamp(
+    IN gcoVG Vg,
+    IN gcoSURF ColorRamp,
+    IN gceTILE_MODE ColorRampSpreadMode
+    );
+
+gceSTATUS
+gcoVG_SetPattern(
+    IN gcoVG Vg,
+    IN gcoSURF Pattern,
+    IN gceTILE_MODE TileMode,
+    IN gceIMAGE_FILTER Filter
+    );
+
+gceSTATUS
+gcoVG_SetImageMode(
+    IN gcoVG Vg,
+    IN gceVG_IMAGE Mode
+    );
+
+gceSTATUS
+gcoVG_SetBlendMode(
+    IN gcoVG Vg,
+    IN gceVG_BLEND Mode
+    );
+
+gceSTATUS
+gcoVG_SetRenderingQuality(
+    IN gcoVG Vg,
+    IN gceRENDER_QUALITY Quality
+    );
+
+gceSTATUS
+gcoVG_SetFillRule(
+    IN gcoVG Vg,
+    IN gceFILL_RULE FillRule
+    );
+
+gceSTATUS
+gcoVG_FinalizePath(
+    IN gcoVG Vg,
+    IN gcsPATH_DATA_PTR PathData
+    );
+
+gceSTATUS
+gcoVG_Clear(
+    IN gcoVG Vg,
+    IN gctINT X,
+    IN gctINT Y,
+    IN gctINT Width,
+    IN gctINT Height
+    );
+
+gceSTATUS
+gcoVG_DrawPath(
+    IN gcoVG Vg,
+    IN gcsPATH_DATA_PTR PathData,
+    IN gctFLOAT Scale,
+    IN gctFLOAT Bias,
+    IN gctBOOL SoftwareTesselation
+    );
+
+gceSTATUS
+gcoVG_DrawImage(
+    IN gcoVG Vg,
+    IN gcoSURF Source,
+    IN gcsPOINT_PTR SourceOrigin,
+    IN gcsPOINT_PTR TargetOrigin,
+    IN gcsSIZE_PTR SourceSize,
+    IN gctINT SourceX,
+    IN gctINT SourceY,
+    IN gctINT TargetX,
+    IN gctINT TargetY,
+    IN gctINT Width,
+    IN gctINT Height,
+    IN gctBOOL Mask
+    );
+
+gceSTATUS
+gcoVG_TesselateImage(
+    IN gcoVG Vg,
+    IN gcoSURF Image,
+    IN gcsVG_RECT_PTR Rectangle,
+    IN gceIMAGE_FILTER Filter,
+    IN gctBOOL Mask,
+    IN gctBOOL SoftwareTesselation
+    );
+
+gceSTATUS
+gcoVG_Blit(
+    IN gcoVG Vg,
+    IN gcoSURF Source,
+    IN gcoSURF Target,
+    IN gcsVG_RECT_PTR SrcRect,
+    IN gcsVG_RECT_PTR TrgRect,
+    IN gceIMAGE_FILTER Filter,
+    IN gceVG_BLEND Mode
+    );
+
+gceSTATUS
+gcoVG_ColorMatrix(
+    IN gcoVG Vg,
+    IN gcoSURF Source,
+    IN gcoSURF Target,
+    IN const gctFLOAT * Matrix,
+    IN gceCHANNEL ColorChannels,
+    IN gctBOOL FilterLinear,
+    IN gctBOOL FilterPremultiplied,
+    IN gcsPOINT_PTR SourceOrigin,
+    IN gcsPOINT_PTR TargetOrigin,
+    IN gctINT Width,
+    IN gctINT Height
+    );
+
+gceSTATUS
+gcoVG_SeparableConvolve(
+    IN gcoVG Vg,
+    IN gcoSURF Source,
+    IN gcoSURF Target,
+    IN gctINT KernelWidth,
+    IN gctINT KernelHeight,
+    IN gctINT ShiftX,
+    IN gctINT ShiftY,
+    IN const gctINT16 * KernelX,
+    IN const gctINT16 * KernelY,
+    IN gctFLOAT Scale,
+    IN gctFLOAT Bias,
+    IN gceTILE_MODE TilingMode,
+    IN gctFLOAT_PTR FillColor,
+    IN gceCHANNEL ColorChannels,
+    IN gctBOOL FilterLinear,
+    IN gctBOOL FilterPremultiplied,
+    IN gcsPOINT_PTR SourceOrigin,
+    IN gcsPOINT_PTR TargetOrigin,
+    IN gcsSIZE_PTR SourceSize,
+    IN gctINT Width,
+    IN gctINT Height
+    );
+
+gceSTATUS
+gcoVG_GaussianBlur(
+    IN gcoVG Vg,
+    IN gcoSURF Source,
+    IN gcoSURF Target,
+    IN gctFLOAT StdDeviationX,
+    IN gctFLOAT StdDeviationY,
+    IN gceTILE_MODE TilingMode,
+    IN gctFLOAT_PTR FillColor,
+    IN gceCHANNEL ColorChannels,
+    IN gctBOOL FilterLinear,
+    IN gctBOOL FilterPremultiplied,
+    IN gcsPOINT_PTR SourceOrigin,
+    IN gcsPOINT_PTR TargetOrigin,
+    IN gcsSIZE_PTR SourceSize,
+    IN gctINT Width,
+    IN gctINT Height
+    );
+
+gceSTATUS
+gcoVG_EnableDither(
+    IN gcoVG Vg,
+    IN gctBOOL Enable
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __gc_hal_vg_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
new file mode 100644 (file)
index 0000000..d867ecd
--- /dev/null
@@ -0,0 +1,783 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_enum_h_
+#define __gc_hal_enum_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Chip models. */
+typedef enum _gceCHIPMODEL
+{
+    gcv300  = 0x0300,
+    gcv320  = 0x0320,
+    gcv350  = 0x0350,
+    gcv355  = 0x0355,
+    gcv400  = 0x0400,
+    gcv410  = 0x0410,
+    gcv450  = 0x0450,
+    gcv500  = 0x0500,
+    gcv530  = 0x0530,
+    gcv600  = 0x0600,
+    gcv700  = 0x0700,
+    gcv800  = 0x0800,
+    gcv860  = 0x0860,
+    gcv880  = 0x0880,
+    gcv1000 = 0x1000,
+    gcv2000 = 0x2000,
+    gcv2100 = 0x2100,
+    gcv4000 = 0x4000,
+}
+gceCHIPMODEL;
+
+/* Chip features. */
+typedef enum _gceFEATURE
+{
+    gcvFEATURE_PIPE_2D = 0,
+    gcvFEATURE_PIPE_3D,
+    gcvFEATURE_PIPE_VG,
+    gcvFEATURE_DC,
+    gcvFEATURE_HIGH_DYNAMIC_RANGE,
+    gcvFEATURE_MODULE_CG,
+    gcvFEATURE_MIN_AREA,
+    gcvFEATURE_BUFFER_INTERLEAVING,
+    gcvFEATURE_BYTE_WRITE_2D,
+    gcvFEATURE_ENDIANNESS_CONFIG,
+    gcvFEATURE_DUAL_RETURN_BUS,
+    gcvFEATURE_DEBUG_MODE,
+    gcvFEATURE_YUY2_RENDER_TARGET,
+    gcvFEATURE_FRAGMENT_PROCESSOR,
+    gcvFEATURE_2DPE20,
+    gcvFEATURE_FAST_CLEAR,
+    gcvFEATURE_YUV420_TILER,
+    gcvFEATURE_YUY2_AVERAGING,
+    gcvFEATURE_FLIP_Y,
+    gcvFEATURE_EARLY_Z,
+    gcvFEATURE_Z_COMPRESSION,
+    gcvFEATURE_MSAA,
+    gcvFEATURE_SPECIAL_ANTI_ALIASING,
+    gcvFEATURE_SPECIAL_MSAA_LOD,
+    gcvFEATURE_422_TEXTURE_COMPRESSION,
+    gcvFEATURE_DXT_TEXTURE_COMPRESSION,
+    gcvFEATURE_ETC1_TEXTURE_COMPRESSION,
+    gcvFEATURE_CORRECT_TEXTURE_CONVERTER,
+    gcvFEATURE_TEXTURE_8K,
+    gcvFEATURE_SCALER,
+    gcvFEATURE_YUV420_SCALER,
+    gcvFEATURE_SHADER_HAS_W,
+    gcvFEATURE_SHADER_HAS_SIGN,
+    gcvFEATURE_SHADER_HAS_FLOOR,
+    gcvFEATURE_SHADER_HAS_CEIL,
+    gcvFEATURE_SHADER_HAS_SQRT,
+    gcvFEATURE_SHADER_HAS_TRIG,
+    gcvFEATURE_VAA,
+    gcvFEATURE_HZ,
+    gcvFEATURE_CORRECT_STENCIL,
+    gcvFEATURE_VG20,
+    gcvFEATURE_VG_FILTER,
+    gcvFEATURE_VG21,
+    gcvFEATURE_VG_DOUBLE_BUFFER,
+    gcvFEATURE_MC20,
+    gcvFEATURE_SUPER_TILED,
+    gcvFEATURE_2D_FILTERBLIT_PLUS_ALPHABLEND,
+    gcvFEATURE_2D_DITHER,
+    gcvFEATURE_2D_A8_TARGET,
+    gcvFEATURE_2D_FILTERBLIT_FULLROTATION,
+    gcvFEATURE_2D_BITBLIT_FULLROTATION,
+    gcvFEATURE_WIDE_LINE,
+    gcvFEATURE_FC_FLUSH_STALL,
+    gcvFEATURE_FULL_DIRECTFB,
+    gcvFEATURE_HALF_FLOAT_PIPE,
+    gcvFEATURE_LINE_LOOP,
+    gcvFEATURE_2D_YUV_BLIT,
+    gcvFEATURE_2D_TILING,
+    gcvFEATURE_NON_POWER_OF_TWO,
+    gcvFEATURE_3D_TEXTURE,
+    gcvFEATURE_TEXTURE_ARRAY,
+    gcvFEATURE_TILE_FILLER,
+    gcvFEATURE_LOGIC_OP,
+    gcvFEATURE_COMPOSITION,
+    gcvFEATURE_MIXED_STREAMS,
+    gcvFEATURE_2D_MULTI_SOURCE_BLT,
+    gcvFEATURE_END_EVENT,
+    gcvFEATURE_VERTEX_10_10_10_2,
+    gcvFEATURE_TEXTURE_10_10_10_2,
+    gcvFEATURE_TEXTURE_ANISOTROPIC_FILTERING,
+    gcvFEATURE_TEXTURE_FLOAT_HALF_FLOAT,
+       gcvFEATURE_2D_ROTATION_STALL_FIX,
+}
+gceFEATURE;
+
+/* Chip Power Status. */
+typedef enum _gceCHIPPOWERSTATE
+{
+    gcvPOWER_ON = 0,
+    gcvPOWER_OFF,
+    gcvPOWER_IDLE,
+    gcvPOWER_SUSPEND,
+    gcvPOWER_SUSPEND_ATPOWERON,
+    gcvPOWER_OFF_ATPOWERON,
+    gcvPOWER_IDLE_BROADCAST,
+    gcvPOWER_SUSPEND_BROADCAST,
+    gcvPOWER_OFF_BROADCAST,
+    gcvPOWER_OFF_RECOVERY,
+#if gcdPOWEROFF_TIMEOUT
+    gcvPOWER_OFF_TIMEOUT,
+#endif
+    gcvPOWER_ON_AUTO
+}
+gceCHIPPOWERSTATE;
+
+/* CPU cache operations */
+typedef enum _gceCACHEOPERATION
+{
+    gcvCACHE_CLEAN      = 0x01,
+    gcvCACHE_INVALIDATE = 0x02,
+    gcvCACHE_FLUSH      = gcvCACHE_CLEAN  | gcvCACHE_INVALIDATE
+}
+gceCACHEOPERATION;
+
+/* Surface types. */
+typedef enum _gceSURF_TYPE
+{
+    gcvSURF_TYPE_UNKNOWN = 0,
+    gcvSURF_INDEX,
+    gcvSURF_VERTEX,
+    gcvSURF_TEXTURE,
+    gcvSURF_RENDER_TARGET,
+    gcvSURF_DEPTH,
+    gcvSURF_BITMAP,
+    gcvSURF_TILE_STATUS,
+       gcvSURF_IMAGE,
+    gcvSURF_MASK,
+    gcvSURF_SCISSOR,
+    gcvSURF_HIERARCHICAL_DEPTH,
+    gcvSURF_NUM_TYPES, /* Make sure this is the last one! */
+
+    /* Combinations. */
+    gcvSURF_NO_TILE_STATUS = 0x100,
+    gcvSURF_NO_VIDMEM      = 0x200, /* Used to allocate surfaces with no underlying vidmem node.
+                                       In Android, vidmem node is allocated by another process. */
+    gcvSURF_CACHEABLE      = 0x400, /* Used to allocate a cacheable surface */
+
+    gcvSURF_RENDER_TARGET_NO_TILE_STATUS = gcvSURF_RENDER_TARGET
+                                         | gcvSURF_NO_TILE_STATUS,
+
+    gcvSURF_DEPTH_NO_TILE_STATUS         = gcvSURF_DEPTH
+                                         | gcvSURF_NO_TILE_STATUS,
+
+    /* Supported surface types with no vidmem node. */
+    gcvSURF_BITMAP_NO_VIDMEM             = gcvSURF_BITMAP
+                                         | gcvSURF_NO_VIDMEM,
+
+    gcvSURF_TEXTURE_NO_VIDMEM            = gcvSURF_TEXTURE
+                                         | gcvSURF_NO_VIDMEM,
+
+    /* Cacheable surface types with no vidmem node. */
+    gcvSURF_CACHEABLE_BITMAP_NO_VIDMEM   = gcvSURF_BITMAP_NO_VIDMEM
+                                         | gcvSURF_CACHEABLE,
+
+    gcvSURF_CACHEABLE_BITMAP             = gcvSURF_BITMAP
+                                         | gcvSURF_CACHEABLE
+}
+gceSURF_TYPE;
+
+typedef enum _gceSURF_COLOR_TYPE
+{
+    gcvSURF_COLOR_UNKNOWN = 0,
+    gcvSURF_COLOR_LINEAR        = 0x01,
+    gcvSURF_COLOR_ALPHA_PRE     = 0x02,
+}
+gceSURF_COLOR_TYPE;
+
+/* Rotation. */
+typedef enum _gceSURF_ROTATION
+{
+    gcvSURF_0_DEGREE = 0,
+    gcvSURF_90_DEGREE,
+    gcvSURF_180_DEGREE,
+    gcvSURF_270_DEGREE,
+    gcvSURF_FLIP_X,
+    gcvSURF_FLIP_Y,
+}
+gceSURF_ROTATION;
+
+/* Surface formats. */
+typedef enum _gceSURF_FORMAT
+{
+    /* Unknown format. */
+    gcvSURF_UNKNOWN             = 0,
+
+    /* Palettized formats. */
+    gcvSURF_INDEX1              = 100,
+    gcvSURF_INDEX4,
+    gcvSURF_INDEX8,
+
+    /* RGB formats. */
+    gcvSURF_A2R2G2B2            = 200,
+    gcvSURF_R3G3B2,
+    gcvSURF_A8R3G3B2,
+    gcvSURF_X4R4G4B4,
+    gcvSURF_A4R4G4B4,
+    gcvSURF_R4G4B4A4,
+    gcvSURF_X1R5G5B5,
+    gcvSURF_A1R5G5B5,
+    gcvSURF_R5G5B5A1,
+    gcvSURF_R5G6B5,
+    gcvSURF_R8G8B8,
+    gcvSURF_X8R8G8B8,
+    gcvSURF_A8R8G8B8,
+    gcvSURF_R8G8B8A8,
+    gcvSURF_G8R8G8B8,
+    gcvSURF_R8G8B8G8,
+    gcvSURF_X2R10G10B10,
+    gcvSURF_A2R10G10B10,
+    gcvSURF_X12R12G12B12,
+    gcvSURF_A12R12G12B12,
+    gcvSURF_X16R16G16B16,
+    gcvSURF_A16R16G16B16,
+    gcvSURF_A32R32G32B32,
+    gcvSURF_R8G8B8X8,
+    gcvSURF_R5G5B5X1,
+    gcvSURF_R4G4B4X4,
+
+    /* BGR formats. */
+    gcvSURF_A4B4G4R4            = 300,
+    gcvSURF_A1B5G5R5,
+    gcvSURF_B5G6R5,
+    gcvSURF_B8G8R8,
+    gcvSURF_B16G16R16,
+    gcvSURF_X8B8G8R8,
+    gcvSURF_A8B8G8R8,
+    gcvSURF_A2B10G10R10,
+    gcvSURF_X16B16G16R16,
+    gcvSURF_A16B16G16R16,
+    gcvSURF_B32G32R32,
+    gcvSURF_X32B32G32R32,
+    gcvSURF_A32B32G32R32,
+    gcvSURF_B4G4R4A4,
+    gcvSURF_B5G5R5A1,
+    gcvSURF_B8G8R8X8,
+    gcvSURF_B8G8R8A8,
+    gcvSURF_X4B4G4R4,
+    gcvSURF_X1B5G5R5,
+    gcvSURF_B4G4R4X4,
+    gcvSURF_B5G5R5X1,
+    gcvSURF_X2B10G10R10,
+
+    /* Compressed formats. */
+    gcvSURF_DXT1                = 400,
+    gcvSURF_DXT2,
+    gcvSURF_DXT3,
+    gcvSURF_DXT4,
+    gcvSURF_DXT5,
+    gcvSURF_CXV8U8,
+    gcvSURF_ETC1,
+
+    /* YUV formats. */
+    gcvSURF_YUY2                = 500,
+    gcvSURF_UYVY,
+    gcvSURF_YV12,
+    gcvSURF_I420,
+    gcvSURF_NV12,
+    gcvSURF_NV21,
+    gcvSURF_NV16,
+    gcvSURF_NV61,
+    gcvSURF_YVYU,
+    gcvSURF_VYUY,
+
+    /* Depth formats. */
+    gcvSURF_D16                 = 600,
+    gcvSURF_D24S8,
+    gcvSURF_D32,
+    gcvSURF_D24X8,
+
+    /* Alpha formats. */
+    gcvSURF_A4                  = 700,
+    gcvSURF_A8,
+    gcvSURF_A12,
+    gcvSURF_A16,
+    gcvSURF_A32,
+    gcvSURF_A1,
+
+    /* Luminance formats. */
+    gcvSURF_L4                  = 800,
+    gcvSURF_L8,
+    gcvSURF_L12,
+    gcvSURF_L16,
+    gcvSURF_L32,
+    gcvSURF_L1,
+
+    /* Alpha/Luminance formats. */
+    gcvSURF_A4L4                = 900,
+    gcvSURF_A2L6,
+    gcvSURF_A8L8,
+    gcvSURF_A4L12,
+    gcvSURF_A12L12,
+    gcvSURF_A16L16,
+
+    /* Bump formats. */
+    gcvSURF_L6V5U5              = 1000,
+    gcvSURF_V8U8,
+    gcvSURF_X8L8V8U8,
+    gcvSURF_Q8W8V8U8,
+    gcvSURF_A2W10V10U10,
+    gcvSURF_V16U16,
+    gcvSURF_Q16W16V16U16,
+
+    /* R/RG/RA formats. */
+    gcvSURF_R8                  = 1100,
+    gcvSURF_X8R8,
+    gcvSURF_G8R8,
+    gcvSURF_X8G8R8,
+    gcvSURF_A8R8,
+    gcvSURF_R16,
+    gcvSURF_X16R16,
+    gcvSURF_G16R16,
+    gcvSURF_X16G16R16,
+    gcvSURF_A16R16,
+    gcvSURF_R32,
+    gcvSURF_X32R32,
+    gcvSURF_G32R32,
+    gcvSURF_X32G32R32,
+    gcvSURF_A32R32,
+
+    /* Floating point formats. */
+    gcvSURF_R16F                = 1200,
+    gcvSURF_X16R16F,
+    gcvSURF_G16R16F,
+    gcvSURF_X16G16R16F,
+    gcvSURF_B16G16R16F,
+    gcvSURF_X16B16G16R16F,
+    gcvSURF_A16B16G16R16F,
+    gcvSURF_R32F,
+    gcvSURF_X32R32F,
+    gcvSURF_G32R32F,
+    gcvSURF_X32G32R32F,
+    gcvSURF_B32G32R32F,
+    gcvSURF_X32B32G32R32F,
+    gcvSURF_A32B32G32R32F,
+    gcvSURF_A16F,
+    gcvSURF_L16F,
+    gcvSURF_A16L16F,
+    gcvSURF_A16R16F,
+    gcvSURF_A32F,
+    gcvSURF_L32F,
+    gcvSURF_A32L32F,
+    gcvSURF_A32R32F,
+
+}
+gceSURF_FORMAT;
+
+/* Pixel swizzle modes. */
+typedef enum _gceSURF_SWIZZLE
+{
+    gcvSURF_NOSWIZZLE = 0,
+    gcvSURF_ARGB,
+    gcvSURF_ABGR,
+    gcvSURF_RGBA,
+    gcvSURF_BGRA
+}
+gceSURF_SWIZZLE;
+
+/* Transparency modes. */
+typedef enum _gceSURF_TRANSPARENCY
+{
+    /* Valid only for PE 1.0 */
+    gcvSURF_OPAQUE = 0,
+    gcvSURF_SOURCE_MATCH,
+    gcvSURF_SOURCE_MASK,
+    gcvSURF_PATTERN_MASK,
+}
+gceSURF_TRANSPARENCY;
+
+/* Surface Alignment. */
+typedef enum _gceSURF_ALIGNMENT
+{
+    gcvSURF_FOUR = 0,
+    gcvSURF_SIXTEEN,
+    gcvSURF_SUPER_TILED,
+    gcvSURF_SPLIT_TILED,
+    gcvSURF_SPLIT_SUPER_TILED,
+}
+gceSURF_ALIGNMENT;
+
+/* Transparency modes. */
+typedef enum _gce2D_TRANSPARENCY
+{
+    /* Valid only for PE 2.0 */
+    gcv2D_OPAQUE = 0,
+    gcv2D_KEYED,
+    gcv2D_MASKED
+}
+gce2D_TRANSPARENCY;
+
+/* Mono packing modes. */
+typedef enum _gceSURF_MONOPACK
+{
+    gcvSURF_PACKED8 = 0,
+    gcvSURF_PACKED16,
+    gcvSURF_PACKED32,
+    gcvSURF_UNPACKED,
+}
+gceSURF_MONOPACK;
+
+/* Blending modes. */
+typedef enum _gceSURF_BLEND_MODE
+{
+    /* Porter-Duff blending modes.                   */
+    /*                         Fsrc      Fdst        */
+    gcvBLEND_CLEAR = 0,     /* 0         0           */
+    gcvBLEND_SRC,           /* 1         0           */
+    gcvBLEND_DST,           /* 0         1           */
+    gcvBLEND_SRC_OVER_DST,  /* 1         1 - Asrc    */
+    gcvBLEND_DST_OVER_SRC,  /* 1 - Adst  1           */
+    gcvBLEND_SRC_IN_DST,    /* Adst      0           */
+    gcvBLEND_DST_IN_SRC,    /* 0         Asrc        */
+    gcvBLEND_SRC_OUT_DST,   /* 1 - Adst  0           */
+    gcvBLEND_DST_OUT_SRC,   /* 0         1 - Asrc    */
+    gcvBLEND_SRC_ATOP_DST,  /* Adst      1 - Asrc    */
+    gcvBLEND_DST_ATOP_SRC,  /* 1 - Adst  Asrc        */
+    gcvBLEND_SRC_XOR_DST,   /* 1 - Adst  1 - Asrc    */
+
+    /* Special blending modes.                       */
+    gcvBLEND_SET,           /* DST = 1               */
+    gcvBLEND_SUB            /* DST = DST * (1 - SRC) */
+}
+gceSURF_BLEND_MODE;
+
+/* Per-pixel alpha modes. */
+typedef enum _gceSURF_PIXEL_ALPHA_MODE
+{
+    gcvSURF_PIXEL_ALPHA_STRAIGHT = 0,
+    gcvSURF_PIXEL_ALPHA_INVERSED
+}
+gceSURF_PIXEL_ALPHA_MODE;
+
+/* Global alpha modes. */
+typedef enum _gceSURF_GLOBAL_ALPHA_MODE
+{
+    gcvSURF_GLOBAL_ALPHA_OFF = 0,
+    gcvSURF_GLOBAL_ALPHA_ON,
+    gcvSURF_GLOBAL_ALPHA_SCALE
+}
+gceSURF_GLOBAL_ALPHA_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gceSURF_PIXEL_COLOR_MODE
+{
+    gcvSURF_COLOR_STRAIGHT = 0,
+    gcvSURF_COLOR_MULTIPLY
+}
+gceSURF_PIXEL_COLOR_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gce2D_PIXEL_COLOR_MULTIPLY_MODE
+{
+    gcv2D_COLOR_MULTIPLY_DISABLE = 0,
+    gcv2D_COLOR_MULTIPLY_ENABLE
+}
+gce2D_PIXEL_COLOR_MULTIPLY_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gce2D_GLOBAL_COLOR_MULTIPLY_MODE
+{
+    gcv2D_GLOBAL_COLOR_MULTIPLY_DISABLE = 0,
+    gcv2D_GLOBAL_COLOR_MULTIPLY_ALPHA,
+    gcv2D_GLOBAL_COLOR_MULTIPLY_COLOR
+}
+gce2D_GLOBAL_COLOR_MULTIPLY_MODE;
+
+/* Alpha blending factor modes. */
+typedef enum _gceSURF_BLEND_FACTOR_MODE
+{
+    gcvSURF_BLEND_ZERO = 0,
+    gcvSURF_BLEND_ONE,
+    gcvSURF_BLEND_STRAIGHT,
+    gcvSURF_BLEND_INVERSED,
+    gcvSURF_BLEND_COLOR,
+    gcvSURF_BLEND_COLOR_INVERSED,
+    gcvSURF_BLEND_SRC_ALPHA_SATURATED,
+    gcvSURF_BLEND_STRAIGHT_NO_CROSS,
+    gcvSURF_BLEND_INVERSED_NO_CROSS,
+    gcvSURF_BLEND_COLOR_NO_CROSS,
+    gcvSURF_BLEND_COLOR_INVERSED_NO_CROSS,
+    gcvSURF_BLEND_SRC_ALPHA_SATURATED_CROSS
+}
+gceSURF_BLEND_FACTOR_MODE;
+
+/* Alpha blending porter duff rules. */
+typedef enum _gce2D_PORTER_DUFF_RULE
+{
+    gcvPD_CLEAR = 0,
+    gcvPD_SRC,
+    gcvPD_SRC_OVER,
+    gcvPD_DST_OVER,
+    gcvPD_SRC_IN,
+    gcvPD_DST_IN,
+    gcvPD_SRC_OUT,
+    gcvPD_DST_OUT,
+    gcvPD_SRC_ATOP,
+    gcvPD_DST_ATOP,
+    gcvPD_ADD,
+    gcvPD_XOR,
+    gcvPD_DST
+}
+gce2D_PORTER_DUFF_RULE;
+
+/* Alpha blending factor modes. */
+typedef enum _gce2D_YUV_COLOR_MODE
+{
+    gcv2D_YUV_601= 0,
+    gcv2D_YUV_709
+}
+gce2D_YUV_COLOR_MODE;
+
+/* 2D Rotation and flipping. */
+typedef enum _gce2D_ORIENTATION
+{
+    gcv2D_0_DEGREE = 0,
+    gcv2D_90_DEGREE,
+    gcv2D_180_DEGREE,
+    gcv2D_270_DEGREE,
+    gcv2D_X_FLIP,
+    gcv2D_Y_FLIP
+}
+gce2D_ORIENTATION;
+
+typedef enum _gce2D_COMMAND
+{
+    gcv2D_CLEAR = 0,
+    gcv2D_LINE,
+    gcv2D_BLT,
+    gcv2D_STRETCH,
+    gcv2D_HOR_FILTER,
+    gcv2D_VER_FILTER,
+    gcv2D_MULTI_SOURCE_BLT,
+}
+gce2D_COMMAND;
+
+#ifndef VIVANTE_NO_3D
+/* Texture functions. */
+typedef enum _gceTEXTURE_FUNCTION
+{
+    gcvTEXTURE_DUMMY = 0,
+    gcvTEXTURE_REPLACE = 0,
+    gcvTEXTURE_MODULATE,
+    gcvTEXTURE_ADD,
+    gcvTEXTURE_ADD_SIGNED,
+    gcvTEXTURE_INTERPOLATE,
+    gcvTEXTURE_SUBTRACT,
+    gcvTEXTURE_DOT3
+}
+gceTEXTURE_FUNCTION;
+
+/* Texture sources. */
+typedef enum _gceTEXTURE_SOURCE
+{
+    gcvCOLOR_FROM_TEXTURE = 0,
+    gcvCOLOR_FROM_CONSTANT_COLOR,
+    gcvCOLOR_FROM_PRIMARY_COLOR,
+    gcvCOLOR_FROM_PREVIOUS_COLOR
+}
+gceTEXTURE_SOURCE;
+
+/* Texture source channels. */
+typedef enum _gceTEXTURE_CHANNEL
+{
+    gcvFROM_COLOR = 0,
+    gcvFROM_ONE_MINUS_COLOR,
+    gcvFROM_ALPHA,
+    gcvFROM_ONE_MINUS_ALPHA
+}
+gceTEXTURE_CHANNEL;
+#endif /* VIVANTE_NO_3D */
+
+/* Filter types. */
+typedef enum _gceFILTER_TYPE
+{
+    gcvFILTER_SYNC = 0,
+    gcvFILTER_BLUR,
+    gcvFILTER_USER
+}
+gceFILTER_TYPE;
+
+/* Filter pass types. */
+typedef enum _gceFILTER_PASS_TYPE
+{
+    gcvFILTER_HOR_PASS = 0,
+    gcvFILTER_VER_PASS
+}
+gceFILTER_PASS_TYPE;
+
+/* Endian hints. */
+typedef enum _gceENDIAN_HINT
+{
+    gcvENDIAN_NO_SWAP = 0,
+    gcvENDIAN_SWAP_WORD,
+    gcvENDIAN_SWAP_DWORD
+}
+gceENDIAN_HINT;
+
+/* Tiling modes. */
+typedef enum _gceTILING
+{
+    gcvLINEAR = 0,
+    gcvTILED,
+    gcvSUPERTILED,
+    gcvMULTI_TILED,
+    gcvMULTI_SUPERTILED,
+}
+gceTILING;
+
+/* 2D pattern type. */
+typedef enum _gce2D_PATTERN
+{
+    gcv2D_PATTERN_SOLID = 0,
+    gcv2D_PATTERN_MONO,
+    gcv2D_PATTERN_COLOR,
+    gcv2D_PATTERN_INVALID
+}
+gce2D_PATTERN;
+
+/* 2D source type. */
+typedef enum _gce2D_SOURCE
+{
+    gcv2D_SOURCE_MASKED = 0,
+    gcv2D_SOURCE_MONO,
+    gcv2D_SOURCE_COLOR,
+    gcv2D_SOURCE_INVALID
+}
+gce2D_SOURCE;
+
+/* Pipes. */
+typedef enum _gcePIPE_SELECT
+{
+    gcvPIPE_INVALID = ~0,
+    gcvPIPE_3D      =  0,
+    gcvPIPE_2D
+}
+gcePIPE_SELECT;
+
+/* Hardware type. */
+typedef enum _gceHARDWARE_TYPE
+{
+    gcvHARDWARE_INVALID = 0x00,
+    gcvHARDWARE_3D      = 0x01,
+    gcvHARDWARE_2D      = 0x02,
+    gcvHARDWARE_VG      = 0x04,
+
+    gcvHARDWARE_3D2D    = gcvHARDWARE_3D | gcvHARDWARE_2D
+}
+gceHARDWARE_TYPE;
+
+#define gcdCHIP_COUNT               3
+
+typedef enum _gceMMU_MODE
+{
+    gcvMMU_MODE_1K,
+    gcvMMU_MODE_4K,
+} gceMMU_MODE;
+
+/* User signal command codes. */
+typedef enum _gceUSER_SIGNAL_COMMAND_CODES
+{
+    gcvUSER_SIGNAL_CREATE,
+    gcvUSER_SIGNAL_DESTROY,
+    gcvUSER_SIGNAL_SIGNAL,
+    gcvUSER_SIGNAL_WAIT,
+    gcvUSER_SIGNAL_MAP,
+    gcvUSER_SIGNAL_UNMAP,
+}
+gceUSER_SIGNAL_COMMAND_CODES;
+
+/* Event locations. */
+typedef enum _gceKERNEL_WHERE
+{
+    gcvKERNEL_COMMAND,
+    gcvKERNEL_VERTEX,
+    gcvKERNEL_TRIANGLE,
+    gcvKERNEL_TEXTURE,
+    gcvKERNEL_PIXEL,
+}
+gceKERNEL_WHERE;
+
+#if gcdENABLE_VG
+/* Hardware blocks. */
+typedef enum _gceBLOCK
+{
+       gcvBLOCK_COMMAND,
+       gcvBLOCK_TESSELLATOR,
+       gcvBLOCK_TESSELLATOR2,
+       gcvBLOCK_TESSELLATOR3,
+       gcvBLOCK_RASTER,
+       gcvBLOCK_VG,
+       gcvBLOCK_VG2,
+       gcvBLOCK_VG3,
+       gcvBLOCK_PIXEL,
+
+       /* Number of defined blocks. */
+       gcvBLOCK_COUNT
+}
+gceBLOCK;
+#endif
+
+/* gcdDUMP message type. */
+typedef enum _gceDEBUG_MESSAGE_TYPE
+{
+    gcvMESSAGE_TEXT,
+    gcvMESSAGE_DUMP
+}
+gceDEBUG_MESSAGE_TYPE;
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gckCONTEXT          * gckCONTEXT;
+typedef struct _gcoCMDBUF           * gcoCMDBUF;
+typedef struct _gcsSTATE_DELTA      * gcsSTATE_DELTA_PTR;
+typedef struct _gcsQUEUE            * gcsQUEUE_PTR;
+typedef struct _gcoQUEUE            * gcoQUEUE;
+typedef struct _gcsHAL_INTERFACE    * gcsHAL_INTERFACE_PTR;
+typedef struct _gcs2D_PROFILE       * gcs2D_PROFILE_PTR;
+
+#if gcdENABLE_VG
+typedef struct _gcoVGHARDWARE *                        gcoVGHARDWARE;
+typedef struct _gcoVGBUFFER *           gcoVGBUFFER;
+typedef struct _gckVGHARDWARE *         gckVGHARDWARE;
+typedef struct _gcsVGCONTEXT *                 gcsVGCONTEXT_PTR;
+typedef struct _gcsVGCONTEXT_MAP *             gcsVGCONTEXT_MAP_PTR;
+typedef struct _gcsVGCMDQUEUE *                        gcsVGCMDQUEUE_PTR;
+typedef struct _gcsTASK_MASTER_TABLE * gcsTASK_MASTER_TABLE_PTR;
+typedef struct _gckVGKERNEL *                  gckVGKERNEL;
+typedef void *                                         gctTHREAD;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_enum_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h
new file mode 100644 (file)
index 0000000..c8c14f3
--- /dev/null
@@ -0,0 +1,192 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_buffer_h_
+#define __gc_hal_kernel_buffer_h_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+************************ Command Buffer and Event Objects **********************
+\******************************************************************************/
+
+/* The number of context buffers per user. */
+#define gcdCONTEXT_BUFFER_COUNT 2
+
+/* State delta record. */
+typedef struct _gcsSTATE_DELTA_RECORD * gcsSTATE_DELTA_RECORD_PTR;
+typedef struct _gcsSTATE_DELTA_RECORD
+{
+    /* State address. */
+    gctUINT                     address;
+
+    /* State mask. */
+    gctUINT32                   mask;
+
+    /* State data. */
+    gctUINT32                   data;
+}
+gcsSTATE_DELTA_RECORD;
+
+/* State delta. */
+typedef struct _gcsSTATE_DELTA
+{
+    /* For debugging: the number of delta in the order of creation. */
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+    gctUINT                     num;
+#endif
+
+    /* For dumping. */
+#if gcdDUMP
+    gcoOS                       os;
+#endif
+
+    /* Main state delta ID. Every time state delta structure gets reinitialized,
+       main ID is incremented. If main state ID overflows, all map entry IDs get
+       reinitialized to make sure there is no potential erroneous match after
+       the overflow.*/
+    gctUINT                     id;
+
+    /* The number of contexts pending modification by the delta. */
+    gctINT                      refCount;
+
+    /* Vertex element count for the delta buffer. */
+    gctUINT                     elementCount;
+
+    /* Number of states currently stored in the record array. */
+    gctUINT                     recordCount;
+
+    /* Record array; holds all modified states. */
+    gcsSTATE_DELTA_RECORD_PTR   recordArray;
+
+    /* Map entry ID is used for map entry validation. If map entry ID does not
+       match the main state delta ID, the entry and the corresponding state are
+       considered not in use. */
+    gctUINT_PTR                 mapEntryID;
+    gctUINT                     mapEntryIDSize;
+
+    /* If the map entry ID matches the main state delta ID, index points to
+       the state record in the record array. */
+    gctUINT_PTR                 mapEntryIndex;
+
+    /* Previous and next state deltas. */
+    gcsSTATE_DELTA_PTR          prev;
+    gcsSTATE_DELTA_PTR          next;
+}
+gcsSTATE_DELTA;
+
+/* Command buffer object. */
+struct _gcoCMDBUF
+{
+    /* The object. */
+    gcsOBJECT                   object;
+
+    /* Command buffer entry and exit pipes. */
+    gcePIPE_SELECT              entryPipe;
+    gcePIPE_SELECT              exitPipe;
+
+    /* Feature usage flags. */
+    gctBOOL                     using2D;
+    gctBOOL                     using3D;
+    gctBOOL                     usingFilterBlit;
+    gctBOOL                     usingPalette;
+
+    /* Physical address of command buffer. */
+    gctPHYS_ADDR                physical;
+
+    /* Logical address of command buffer. */
+    gctPOINTER                  logical;
+
+    /* Number of bytes in command buffer. */
+    gctSIZE_T                   bytes;
+
+    /* Start offset into the command buffer. */
+    gctUINT32                   startOffset;
+
+    /* Current offset into the command buffer. */
+    gctUINT32                   offset;
+
+    /* Number of free bytes in command buffer. */
+    gctSIZE_T                   free;
+
+    /* Location of the last reserved area. */
+    gctPOINTER                  lastReserve;
+    gctUINT                     lastOffset;
+
+#if gcdSECURE_USER
+    /* Hint array for the current command buffer. */
+    gctUINT                     hintArraySize;
+    gctUINT32_PTR               hintArray;
+    gctUINT32_PTR               hintArrayTail;
+#endif
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+    /* Last load state command location and hardware address. */
+    gctUINT32_PTR               lastLoadStatePtr;
+    gctUINT32                   lastLoadStateAddress;
+    gctUINT32                   lastLoadStateCount;
+#endif
+};
+
+typedef struct _gcsQUEUE
+{
+    /* Pointer to next gcsQUEUE structure. */
+    gcsQUEUE_PTR                next;
+
+    /* Event information. */
+    gcsHAL_INTERFACE            iface;
+}
+gcsQUEUE;
+
+/* Event queue. */
+struct _gcoQUEUE
+{
+    /* The object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to current event queue. */
+    gcsQUEUE_PTR                head;
+    gcsQUEUE_PTR                tail;
+
+#ifdef __QNXNTO__
+    /* Buffer for records. */
+    gcsQUEUE_PTR                records;
+    gctUINT32                   freeBytes;
+    gctUINT32                   offset;
+#else
+    /* List of free records. */
+    gcsQUEUE_PTR                freeList;
+#endif
+    #define gcdIN_QUEUE_RECORD_LIMIT 16
+    /* Number of records currently in queue */
+    gctUINT32                   recordCount;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_buffer_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h
new file mode 100644 (file)
index 0000000..9599388
--- /dev/null
@@ -0,0 +1,532 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+/*
+**     Include file for the local memory management.
+*/
+
+#ifndef __gc_hal_mem_h_
+#define __gc_hal_mem_h_
+#ifndef VIVANTE_NO_3D
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+**  Usage:
+
+       The macros to declare MemPool type and functions are
+       gcmMEM_DeclareFSMemPool (Type, TypeName, Prefix)
+       gcmMEM_DeclareVSMemPool (Type, TypeName, Prefix)
+       gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix)
+
+       The data structures for MemPool are
+       typedef struct _gcsMEM_FS_MEM_POOL *    gcsMEM_FS_MEM_POOL;
+       typedef struct _gcsMEM_VS_MEM_POOL *    gcsMEM_VS_MEM_POOL;
+       typedef struct _gcsMEM_AFS_MEM_POOL *   gcsMEM_AFS_MEM_POOL;
+
+       The MemPool constructor and destructor functions are
+       gcfMEM_InitFSMemPool(gcsMEM_FS_MEM_POOL *, gcoOS, gctUINT, gctUINT);
+       gcfMEM_FreeFSMemPool(gcsMEM_FS_MEM_POOL *);
+       gcfMEM_InitVSMemPool(gcsMEM_VS_MEM_POOL *, gcoOS, gctUINT, gctBOOL);
+       gcfMEM_FreeVSMemPool(gcsMEM_VS_MEM_POOL *);
+       gcfMEM_InitAFSMemPool(gcsMEM_AFS_MEM_POOL *, gcoOS, gctUINT);
+       gcfMEM_FreeAFSMemPool(gcsMEM_AFS_MEM_POOL *);
+
+       FS:  for Fixed-Size data structures
+       VS:  for Variable-size data structures
+       AFS: for Array of Fixed-Size data structures
+
+
+       // Example 1: For a fixed-size data structure, struct gcsNode.
+       // It is used locally in a file, so the functions are static without prefix.
+       // At top level, declear allocate and free functions.
+       // The first argument is the data type.
+       // The second armument is the short name used in the fuctions.
+       gcmMEM_DeclareFSMemPool(struct gcsNode, Node, );
+
+       // The previous macro creates two inline functions,
+       // _AllocateNode and _FreeNode.
+
+       // In function or struct
+       gcsMEM_FS_MEM_POOL nodeMemPool;
+
+       // In function,
+       struct gcsNode * node;
+       gceSTATUS status;
+
+       // Before using the memory pool, initialize it.
+       // The second argument is the gcoOS object.
+       // The third argument is the number of data structures to allocate for each chunk.
+       status = gcfMEM_InitFSMemPool(&nodeMemPool, os, 100, sizeof(struct gcsNode));
+       ...
+
+       // Allocate a node.
+       status = _AllocateNode(nodeMemPool, &node);
+       ...
+       // Free a node.
+       _FreeNode(nodeMemPool, node);
+
+       // After using the memory pool, free it.
+       gcfMEM_FreeFSMemPool(&nodeMemPool);
+
+
+       // Example 2: For array of fixed-size data structures, struct gcsNode.
+       // It is used in several files, so the functions are extern with prefix.
+       // At top level, declear allocate and free functions.
+       // The first argument is the data type, and the second one is the short name
+       // used in the fuctions.
+       gcmMEM_DeclareAFSMemPool(struct gcsNode, NodeArray, gcfOpt);
+
+       // The previous macro creates two inline functions,
+       // gcfOpt_AllocateNodeArray and gcfOpt_FreeNodeArray.
+
+       // In function or struct
+       gcsMEM_AFS_MEM_POOL nodeArrayMemPool;
+
+       // In function,
+       struct gcsNode * nodeArray;
+       gceSTATUS status;
+
+       // Before using the array memory pool, initialize it.
+       // The second argument is the gcoOS object, the third is the number of data
+       // structures to allocate for each chunk.
+       status = gcfMEM_InitAFSMemPool(&nodeArrayMemPool, os, sizeof(struct gcsNode));
+       ...
+
+       // Allocate a node array of size 100.
+       status = gcfOpt_AllocateNodeArray(nodeArrayMemPool, &nodeArray, 100);
+       ...
+       // Free a node array.
+       gcfOpt_FreeNodeArray(&nodeArrayMemPool, nodeArray);
+
+       // After using the array memory pool, free it.
+       gcfMEM_FreeAFSMemPool(&nodeArrayMemPool);
+
+*******************************************************************************/
+
+/*******************************************************************************
+**     To switch back to use gcoOS_Allocate and gcoOS_Free, add
+**     #define USE_LOCAL_MEMORY_POOL 0
+**     before including this file.
+*******************************************************************************/
+#ifndef USE_LOCAL_MEMORY_POOL
+/*
+    USE_LOCAL_MEMORY_POOL
+
+    This define enables the local memory management to improve performance.
+*/
+#define USE_LOCAL_MEMORY_POOL          1
+#endif
+
+/*******************************************************************************
+**                                                     Memory Pool Data Structures
+*******************************************************************************/
+#if USE_LOCAL_MEMORY_POOL
+       typedef struct _gcsMEM_FS_MEM_POOL *    gcsMEM_FS_MEM_POOL;
+       typedef struct _gcsMEM_VS_MEM_POOL *    gcsMEM_VS_MEM_POOL;
+       typedef struct _gcsMEM_AFS_MEM_POOL *   gcsMEM_AFS_MEM_POOL;
+#else
+       typedef gcoOS   gcsMEM_FS_MEM_POOL;
+       typedef gcoOS   gcsMEM_VS_MEM_POOL;
+       typedef gcoOS   gcsMEM_AFS_MEM_POOL;
+#endif
+
+/*******************************************************************************
+**                                                     Memory Pool Macros
+*******************************************************************************/
+#if USE_LOCAL_MEMORY_POOL
+#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type **                                 Pointer \
+       ) \
+{ \
+       return(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type **                                 Pointer \
+       ) \
+{ \
+       gceSTATUS                               status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+       gcmERR_RETURN(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+       gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type))); \
+    gcmFOOTER(); \
+       return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type *                                  Pointer \
+       ) \
+{ \
+    gceSTATUS                          status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+    status = gcfMEM_FSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
+    gcmFOOTER(); \
+       return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName##List( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type *                                  FirstPointer, \
+       Type *                                  LastPointer \
+       ) \
+{ \
+    gceSTATUS               status; \
+    gcmHEADER_ARG("MemPool=0x%x FirstPointer=0x%x LastPointer=0x%x", MemPool, FirstPointer, LastPointer); \
+    status = gcfMEM_FSMemPoolFreeAList(MemPool, (gctPOINTER) FirstPointer, (gctPOINTER) LastPointer); \
+    gcmFOOTER(); \
+       return status; \
+}
+
+#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Size \
+       ) \
+{ \
+    gceSTATUS               status;\
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
+    status = gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer); \
+    gcmFOOTER(); \
+       return status; \
+} \
+ \
+gceSTATUS \
+ Prefix##_CAllocate##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Size \
+       ) \
+{ \
+       gceSTATUS                               status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
+       gcmERR_RETURN(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
+       gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, size)); \
+    gcmFOOTER(); \
+       return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type *                                  Pointer \
+       ) \
+{ \
+    gceSTATUS               status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pinter); \
+    status = gcfMEM_VSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
+    gcmFOOTER(); \
+       return status; \
+}
+
+#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+       gcsMEM_AFS_MEM_POOL             MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Count \
+       ) \
+{ \
+    gceSTATUS               status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
+    status = gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer); \
+    gcmFOOTER(); \
+       return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+       gcsMEM_AFS_MEM_POOL             MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Count \
+       ) \
+{ \
+       gceSTATUS                               status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
+       gcmERR_RETURN(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
+       gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type))); \
+    gcmFOOTER(); \
+       return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+       gcsMEM_AFS_MEM_POOL             MemPool, \
+       Type *                                  Pointer \
+       ) \
+{ \
+    gceSTATUS               status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+    status = gcfMEM_AFSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
+    gcmFOOTER(); \
+       return status; \
+}
+
+#else
+
+#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type **                                 Pointer \
+       ) \
+{ \
+    gceSTATUS               status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+    status = gcoOS_Allocate(MemPool, \
+                                                       gcmSIZEOF(Type), \
+                                                       (gctPOINTER *) Pointer); \
+    gcmFOOTER(); \
+       return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type **                                 Pointer \
+       ) \
+{ \
+       gceSTATUS                               status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+       gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+                                                       gcmSIZEOF(Type), \
+                                                       (gctPOINTER *) Pointer)); \
+       gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type))); \
+    gcmFOOTER(); \
+       return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type *                                  Pointer \
+       ) \
+{ \
+    gceSTATUS                          status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+    status = gcmOS_SAFE_FREE(MemPool, Pointer); \
+    gcmFOOTER(); \
+       return status; \
+}
+
+#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+       gcsMEM_VS_MEM_POOL              MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Size \
+       ) \
+{ \
+    gceSTATUS                          status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
+    status = gcoOS_Allocate(MemPool, \
+                                                       Size, \
+                                                       (gctPOINTER *) Pointer); \
+    gcmFOOTER(); \
+       return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+       gcsMEM_VS_MEM_POOL              MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Size \
+       ) \
+{ \
+       gceSTATUS                               status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
+       gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+                                                       Size, \
+                                                       (gctPOINTER *) Pointer)); \
+       gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Size)); \
+    gcmFOOTER(); \
+       return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+       gcsMEM_VS_MEM_POOL              MemPool, \
+       Type *                                  Pointer \
+       ) \
+{ \
+    gceSTATUS                          status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+    status = gcmOS_SAFE_FREE(MemPool, Pointer); \
+    gcmFOOTER(); \
+       return status; \
+}
+
+#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+       gcsMEM_AFS_MEM_POOL             MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Count \
+       ) \
+{ \
+    gceSTATUS                          status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
+    status = gcoOS_Allocate(MemPool, \
+                                                       Count * gcmSIZEOF(Type), \
+                                                       (gctPOINTER *) Pointer); \
+    gcmFOOTER(); \
+       return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+       gcsMEM_AFS_MEM_POOL             MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Count \
+       ) \
+{ \
+       gceSTATUS                               status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
+       gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+                                                       Count * gcmSIZEOF(Type), \
+                                                       (gctPOINTER *) Pointer)); \
+       gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type))); \
+    gcmFOOTER(); \
+       return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+       gcsMEM_AFS_MEM_POOL             MemPool, \
+       Type *                                  Pointer \
+       ) \
+{ \
+    gceSTATUS                          status; \
+    gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+    status = gcmOS_SAFE_FREE(MemPool, Pointer); \
+    gcmFOOTER(); \
+       return status; \
+}
+#endif
+
+/*******************************************************************************
+**                                                     Memory Pool Data Functions
+*******************************************************************************/
+gceSTATUS
+gcfMEM_InitFSMemPool(
+       IN gcsMEM_FS_MEM_POOL * MemPool,
+       IN gcoOS                                OS,
+       IN gctUINT                              NodeCount,
+       IN gctUINT                              NodeSize
+       );
+
+gceSTATUS
+gcfMEM_FreeFSMemPool(
+       IN gcsMEM_FS_MEM_POOL * MemPool
+       );
+
+gceSTATUS
+gcfMEM_FSMemPoolGetANode(
+       IN gcsMEM_FS_MEM_POOL   MemPool,
+       OUT gctPOINTER *                Node
+       );
+
+gceSTATUS
+gcfMEM_FSMemPoolFreeANode(
+       IN gcsMEM_FS_MEM_POOL   MemPool,
+       IN gctPOINTER                   Node
+       );
+
+gceSTATUS
+gcfMEM_FSMemPoolFreeAList(
+       IN gcsMEM_FS_MEM_POOL   MemPool,
+       IN gctPOINTER                   FirstNode,
+       IN gctPOINTER                   LastNode
+       );
+
+gceSTATUS
+gcfMEM_InitVSMemPool(
+       IN gcsMEM_VS_MEM_POOL * MemPool,
+       IN gcoOS                                OS,
+       IN gctUINT                              BlockSize,
+       IN gctBOOL                              RecycleFreeNode
+       );
+
+gceSTATUS
+gcfMEM_FreeVSMemPool(
+       IN gcsMEM_VS_MEM_POOL * MemPool
+       );
+
+gceSTATUS
+gcfMEM_VSMemPoolGetANode(
+       IN gcsMEM_VS_MEM_POOL   MemPool,
+       IN gctUINT                              Size,
+       IN gctUINT                              Alignment,
+       OUT gctPOINTER *                Node
+       );
+
+gceSTATUS
+gcfMEM_VSMemPoolFreeANode(
+       IN gcsMEM_VS_MEM_POOL   MemPool,
+       IN gctPOINTER                   Node
+       );
+
+gceSTATUS
+gcfMEM_InitAFSMemPool(
+       IN gcsMEM_AFS_MEM_POOL *MemPool,
+       IN gcoOS                                OS,
+       IN gctUINT                              NodeCount,
+       IN gctUINT                              NodeSize
+       );
+
+gceSTATUS
+gcfMEM_FreeAFSMemPool(
+       IN gcsMEM_AFS_MEM_POOL *MemPool
+       );
+
+gceSTATUS
+gcfMEM_AFSMemPoolGetANode(
+       IN gcsMEM_AFS_MEM_POOL  MemPool,
+       IN gctUINT                              Count,
+       OUT gctPOINTER *                Node
+       );
+
+gceSTATUS
+gcfMEM_AFSMemPoolFreeANode(
+       IN gcsMEM_AFS_MEM_POOL  MemPool,
+       IN gctPOINTER                   Node
+       );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VIVANTE_NO_3D */
+#endif /* __gc_hal_mem_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
new file mode 100644 (file)
index 0000000..c33f8bd
--- /dev/null
@@ -0,0 +1,574 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_options_h_
+#define __gc_hal_options_h_
+
+/*
+    gcdPRINT_VERSION
+
+        Print HAL version.
+*/
+#ifndef gcdPRINT_VERSION
+#   define gcdPRINT_VERSION                     0
+#endif
+
+/*
+    USE_NEW_LINUX_SIGNAL
+
+        This define enables the Linux kernel signaling between kernel and user.
+*/
+#ifndef USE_NEW_LINUX_SIGNAL
+#   define USE_NEW_LINUX_SIGNAL                 0
+#endif
+
+/*
+    NO_USER_DIRECT_ACCESS_FROM_KERNEL
+
+        This define enables the Linux kernel behavior accessing user memory.
+*/
+#ifndef NO_USER_DIRECT_ACCESS_FROM_KERNEL
+#   define NO_USER_DIRECT_ACCESS_FROM_KERNEL    0
+#endif
+
+/*
+    VIVANTE_PROFILER
+
+        This define enables the profiler.
+*/
+#ifndef VIVANTE_PROFILER
+#   define VIVANTE_PROFILER                     0
+#endif
+
+/*
+    gcdUSE_VG
+
+        Enable VG HAL layer (only for GC350).
+*/
+#ifndef gcdUSE_VG
+#   define gcdUSE_VG                            0
+#endif
+
+/*
+    USE_SW_FB
+
+        Set to 1 if the frame buffer memory cannot be accessed by the GPU.
+*/
+#ifndef USE_SW_FB
+#   define USE_SW_FB                            0
+#endif
+
+/*
+    USE_SUPER_SAMPLING
+
+        This define enables super-sampling support.
+*/
+#define USE_SUPER_SAMPLING                      0
+
+/*
+    PROFILE_HAL_COUNTERS
+
+        This define enables HAL counter profiling support.  HW and SHADER
+        counter profiling depends on this.
+*/
+#ifndef PROFILE_HAL_COUNTERS
+#   define PROFILE_HAL_COUNTERS                 1
+#endif
+
+/*
+    PROFILE_HW_COUNTERS
+
+        This define enables HW counter profiling support.
+*/
+#ifndef PROFILE_HW_COUNTERS
+#   define PROFILE_HW_COUNTERS                  1
+#endif
+
+/*
+    PROFILE_SHADER_COUNTERS
+
+        This define enables SHADER counter profiling support.
+*/
+#ifndef PROFILE_SHADER_COUNTERS
+#   define PROFILE_SHADER_COUNTERS              1
+#endif
+
+/*
+    COMMAND_PROCESSOR_VERSION
+
+        The version of the command buffer and task manager.
+*/
+#define COMMAND_PROCESSOR_VERSION               1
+
+/*
+    gcdDUMP
+
+        When set to 1, a dump of all states and memory uploads, as well as other
+        hardware related execution will be printed to the debug console.  This
+        data can be used for playing back applications.
+*/
+#ifndef gcdDUMP
+#   define gcdDUMP                              0
+#endif
+
+/*
+    gcdDUMP_API
+
+        When set to 1, a high level dump of the EGL and GL/VG APs's are
+        captured.
+*/
+#ifndef gcdDUMP_API
+#   define gcdDUMP_API                          0
+#endif
+
+/*
+    gcdDUMP_IN_KERNEL
+
+        When set to 1, all dumps will happen in the kernel.  This is handy if
+        you want the kernel to dump its command buffers as well and the data
+        needs to be in sync.
+*/
+#ifndef gcdDUMP_IN_KERNEL
+#   define gcdDUMP_IN_KERNEL                    0
+#endif
+
+/*
+    gcdDUMP_COMMAND
+
+        When set to non-zero, the command queue will dump all incoming command
+        and context buffers as well as all other modifications to the command
+        queue.
+*/
+#ifndef gcdDUMP_COMMAND
+#   define gcdDUMP_COMMAND                      0
+#endif
+
+/*
+    gcdDUMP_FRAME_TGA
+
+    When set to a value other than 0, a dump of the frame specified by the value,
+    will be done into frame.tga. Frame count starts from 1.
+ */
+#ifndef gcdDUMP_FRAME_TGA
+#define gcdDUMP_FRAME_TGA                       0
+#endif
+/*
+    gcdNULL_DRIVER
+
+    Set to 1 for infinite speed hardware.
+    Set to 2 for bypassing the HAL.
+    Set to 3 for bypassing the drivers.
+*/
+#ifndef gcdNULL_DRIVER
+#   define gcdNULL_DRIVER  0
+#endif
+
+/*
+    gcdENABLE_TIMEOUT_DETECTION
+
+        Enable timeout detection.
+*/
+#ifndef gcdENABLE_TIMEOUT_DETECTION
+#   define gcdENABLE_TIMEOUT_DETECTION          0
+#endif
+
+/*
+    gcdCMD_BUFFER_SIZE
+
+        Number of bytes in a command buffer.
+*/
+#ifndef gcdCMD_BUFFER_SIZE
+#   define gcdCMD_BUFFER_SIZE                   (128 << 10)
+#endif
+
+/*
+    gcdCMD_BUFFERS
+
+        Number of command buffers to use per client.
+*/
+#ifndef gcdCMD_BUFFERS
+#   define gcdCMD_BUFFERS                       2
+#endif
+
+/*
+    gcdMAX_CMD_BUFFERS
+
+        Maximum number of command buffers to use per client.
+*/
+#ifndef gcdMAX_CMD_BUFFERS
+#   define gcdMAX_CMD_BUFFERS                   8
+#endif
+
+/*
+    gcdCOMMAND_QUEUES
+
+        Number of command queues in the kernel.
+*/
+#ifndef gcdCOMMAND_QUEUES
+#   define gcdCOMMAND_QUEUES                    2
+#endif
+
+/*
+    gcdPOWER_CONTROL_DELAY
+
+        The delay in milliseconds required to wait until the GPU has woke up
+        from a suspend or power-down state.  This is system dependent because
+        the bus clock also needs to stabalize.
+*/
+#ifndef gcdPOWER_CONTROL_DELAY
+#   define gcdPOWER_CONTROL_DELAY               0
+#endif
+
+/*
+    gcdMMU_SIZE
+
+        Size of the MMU page table in bytes.  Each 4 bytes can hold 4kB worth of
+        virtual data.
+*/
+#ifndef gcdMMU_SIZE
+#   define gcdMMU_SIZE                          (128 << 10)
+#endif
+
+/*
+    gcdSECURE_USER
+
+        Use logical addresses instead of physical addresses in user land.  In
+        this case a hint table is created for both command buffers and context
+        buffers, and that hint table will be used to patch up those buffers in
+        the kernel when they are ready to submit.
+*/
+#ifndef gcdSECURE_USER
+#   define gcdSECURE_USER                       0
+#endif
+
+/*
+    gcdSECURE_CACHE_SLOTS
+
+        Number of slots in the logical to DMA address cache table.  Each time a
+        logical address needs to be translated into a DMA address for the GPU,
+        this cache will be walked.  The replacement scheme is LRU.
+*/
+#ifndef gcdSECURE_CACHE_SLOTS
+#   define gcdSECURE_CACHE_SLOTS                1024
+#endif
+
+/*
+    gcdSECURE_CACHE_METHOD
+
+        Replacement scheme used for Secure Cache.  The following options are
+        available:
+
+            gcdSECURE_CACHE_LRU
+                A standard LRU cache.
+
+            gcdSECURE_CACHE_LINEAR
+                A linear walker with the idea that an application will always
+                render the scene in a similar way, so the next entry in the
+                cache should be a hit most of the time.
+
+            gcdSECURE_CACHE_HASH
+                A 256-entry hash table.
+
+            gcdSECURE_CACHE_TABLE
+                A simple cache but with potential of a lot of cache replacement.
+*/
+#ifndef gcdSECURE_CACHE_METHOD
+#   define gcdSECURE_CACHE_METHOD               gcdSECURE_CACHE_HASH
+#endif
+
+/*
+    gcdREGISTER_ACCESS_FROM_USER
+
+        Set to 1 to allow IOCTL calls to get through from user land.  This
+        should only be in debug or development drops.
+*/
+#ifndef gcdREGISTER_ACCESS_FROM_USER
+#   define gcdREGISTER_ACCESS_FROM_USER         1
+#endif
+
+/*
+    gcdHEAP_SIZE
+
+        Set the allocation size for the internal heaps.  Each time a heap is
+        full, a new heap will be allocated with this minmimum amount of bytes.
+        The bigger this size, the fewer heaps there are to allocate, the better
+        the performance.  However, heaps won't be freed until they are
+        completely free, so there might be some more memory waste if the size is
+        too big.
+*/
+#ifndef gcdHEAP_SIZE
+#   define gcdHEAP_SIZE                         (64 << 10)
+#endif
+
+/*
+    gcdPOWER_MANAGEMENT
+
+        This define enables the power management code.
+*/
+#ifndef gcdPOWER_MANAGEMENT
+#   define gcdPOWER_MANAGEMENT                  1
+#endif
+
+/*
+    gcdFPGA_BUILD
+
+        This define enables work arounds for FPGA images.
+*/
+#ifndef gcdFPGA_BUILD
+#   define gcdFPGA_BUILD                        0
+#endif
+
+/*
+    gcdGPU_TIMEOUT
+
+        This define specified the number of milliseconds the system will wait
+        before it broadcasts the GPU is stuck.  In other words, it will define
+        the timeout of any operation that needs to wait for the GPU.
+
+        If the value is 0, no timeout will be checked for.
+*/
+#ifndef gcdGPU_TIMEOUT
+#   if gcdFPGA_BUILD
+#       define gcdGPU_TIMEOUT                   0
+#   else
+#       define gcdGPU_TIMEOUT                   2000
+#   endif
+#endif
+
+/*
+    gcdGPU_ADVANCETIMER
+
+        it is advance timer.
+*/
+#ifndef gcdGPU_ADVANCETIMER
+#   define gcdGPU_ADVANCETIMER                  250
+#endif
+
+/*
+    gcdSTATIC_LINK
+
+        This define disalbes static linking;
+*/
+#ifndef gcdSTATIC_LINK
+#   define gcdSTATIC_LINK                       0
+#endif
+
+/*
+    gcdUSE_NEW_HEAP
+
+        Setting this define to 1 enables new heap.
+*/
+#ifndef gcdUSE_NEW_HEAP
+#   define gcdUSE_NEW_HEAP                      0
+#endif
+
+/*
+    gcdCMD_NO_2D_CONTEXT
+
+        This define enables no-context 2D command buffer.
+*/
+#ifndef gcdCMD_NO_2D_CONTEXT
+#   define gcdCMD_NO_2D_CONTEXT                 1
+#endif
+
+/*
+    gcdENABLE_BANK_ALIGNMENT
+
+    When enabled, video memory is allocated bank aligned. The vendor can modify
+    gckOS_GetSurfaceBankAlignment() and gcoOS_GetBankOffsetBytes() to define how
+    different types of allocations are bank and channel aligned.
+    When disabled (default), no bank alignment is done.
+*/
+#ifndef gcdENABLE_BANK_ALIGNMENT
+#   define gcdENABLE_BANK_ALIGNMENT             0
+#endif
+
+/*
+    gcdDYNAMIC_SPEED
+
+        When non-zero, it informs the kernel driver to use the speed throttling
+        broadcasting functions to inform the system the GPU should be spet up or
+        slowed down. It will send a broadcast for slowdown each "interval"
+        specified by this define in milliseconds
+        (gckOS_BroadcastCalibrateSpeed).
+*/
+#ifndef gcdDYNAMIC_SPEED
+#    define gcdDYNAMIC_SPEED                    2000
+#endif
+
+/*
+    gcdDYNAMIC_EVENT_THRESHOLD
+
+        When non-zero, it specifies the maximum number of available events at
+        which the kernel driver will issue a broadcast to speed up the GPU
+        (gckOS_BroadcastHurry).
+*/
+#ifndef gcdDYNAMIC_EVENT_THRESHOLD
+#    define gcdDYNAMIC_EVENT_THRESHOLD          5
+#endif
+
+/*
+    gcdENABLE_PROFILING
+
+        Enable profiling macros.
+*/
+#ifndef gcdENABLE_PROFILING
+#   define gcdENABLE_PROFILING                  0
+#endif
+
+/*
+    gcdENABLE_128B_MERGE
+
+        Enable 128B merge for the BUS control.
+*/
+#ifndef gcdENABLE_128B_MERGE
+#   define gcdENABLE_128B_MERGE                 0
+#endif
+
+/*
+    gcdFRAME_DB
+
+        When non-zero, it specified the number of frames inside the frame
+        database. The frame DB will collect per-frame timestamps and hardware
+        counters.
+*/
+#ifndef gcdFRAME_DB
+#   define gcdFRAME_DB                          0
+#   define gcdFRAME_DB_RESET                    0
+#   define gcdFRAME_DB_NAME                     "/var/log/frameDB.log"
+#endif
+
+/*
+    gcdENABLE_VG
+            enable the 2D openVG
+*/
+
+#ifndef gcdENABLE_VG
+#   define gcdENABLE_VG                         0
+#endif
+
+/*
+   gcdPAGED_MEMORY_CACHEABLE
+
+        When non-zero, paged memory will be cacheable.
+ */
+
+#ifndef gcdPAGED_MEMORY_CACHEABLE
+#   define gcdPAGED_MEMORY_CACHEABLE            0
+#endif
+
+/*
+   gcdNONPAGED_MEMORY_CACHEABLE
+
+        When non-zero, non paged memory will be cacheable.
+ */
+
+#ifndef gcdNONPAGED_MEMORY_CACHEABLE
+#   define gcdNONPAGED_MEMORY_CACHEABLE         0
+#endif
+
+/*
+   gcdNONPAGED_MEMORY_BUFFERABLE
+
+        When non-zero, non paged memory will be bufferable.
+        gcdNONPAGED_MEMORY_BUFFERABLE and gcdNONPAGED_MEMORY_CACHEABLE
+        can't be set 1 at same time
+ */
+
+#ifndef gcdNONPAGED_MEMORY_BUFFERABLE
+#   define gcdNONPAGED_MEMORY_BUFFERABLE        1
+#endif
+
+/*
+    gcdENABLE_INFINITE_SPEED_HW
+            enable the Infinte HW , this is for 2D openVG
+*/
+
+#ifndef gcdENABLE_INFINITE_SPEED_HW
+#   define gcdENABLE_INFINITE_SPEED_HW          0
+#endif
+
+/*
+    gcdENABLE_TS_DOUBLE_BUFFER
+            enable the TS double buffer, this is for 2D openVG
+*/
+
+#ifndef gcdENABLE_TS_DOUBLE_BUFFER
+#   define gcdENABLE_TS_DOUBLE_BUFFER           1
+#endif
+
+
+/*
+    gcdENABLE_SHARED_INFO
+
+        When non-zero, enable process store some shared data in kernel
+        which can be got by other processes
+ */
+#ifndef gcdENABLE_SHARED_INFO
+#   define gcdENABLE_SHARED_INFO                1
+#endif
+
+/*
+    gcd6000_SUPPORT
+
+    Temporary define to enable/disable 6000 support.
+ */
+#ifndef gcd6000_SUPPORT
+#   define gcd6000_SUPPORT                      0
+#endif
+
+/*
+    gcdPOWEROFF_TIMEOUT
+
+        When non-zero, GPU will power off automatically after idle
+        state lasting for gcdPOWEROFF_TIMEOUT milliseconds.
+ */
+
+#ifndef gcdPOWEROFF_TIMEOUT
+#   define gcdPOWEROFF_TIMEOUT                  5000
+#endif
+
+/*
+    gcdUSE_VIDMEM_PER_PID
+*/
+#ifndef gcdUSE_VIDMEM_PER_PID
+#   define gcdUSE_VIDMEM_PER_PID                0
+#endif
+
+/*
+    QNX_SINGLE_THREADED_DEBUGGING
+*/
+#ifndef QNX_SINGLE_THREADED_DEBUGGING
+#   define QNX_SINGLE_THREADED_DEBUGGING        0
+#endif
+
+/*
+    gcdENABLE_RECOVERY
+
+        This define enables the recovery code.
+*/
+#ifndef gcdENABLE_RECOVERY
+#   define gcdENABLE_RECOVERY                   0
+#endif
+
+#endif /* __gc_hal_options_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h
new file mode 100644 (file)
index 0000000..bcfb2d4
--- /dev/null
@@ -0,0 +1,1275 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_profiler_h_
+#define __gc_hal_profiler_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GLVERTEX_OBJECT 10
+#define GLVERTEX_OBJECT_BYTES 11
+
+#define GLINDEX_OBJECT 20
+#define GLINDEX_OBJECT_BYTES 21
+
+#define GLTEXTURE_OBJECT 30
+#define GLTEXTURE_OBJECT_BYTES 31
+
+#if VIVANTE_PROFILER
+#define gcmPROFILE_GC(Enum, Value)  gcoPROFILER_Count(gcvNULL, Enum, Value)
+#else
+#define gcmPROFILE_GC(Enum, Value)  do { } while (gcvFALSE)
+#endif
+
+#ifndef gcdNEW_PROFILER_FILE
+#define gcdNEW_PROFILER_FILE    1
+#endif
+
+/* OpenGL ES11 API IDs. */
+#define        ES11_ACTIVETEXTURE                              1
+#define        ES11_ALPHAFUNC                                  (ES11_ACTIVETEXTURE                             + 1)
+#define        ES11_ALPHAFUNCX                                 (ES11_ALPHAFUNC                                 + 1)
+#define        ES11_BINDBUFFER                                 (ES11_ALPHAFUNCX                                + 1)
+#define        ES11_BINDTEXTURE                                (ES11_BINDBUFFER                                + 1)
+#define        ES11_BLENDFUNC                                  (ES11_BINDTEXTURE                               + 1)
+#define        ES11_BUFFERDATA                                 (ES11_BLENDFUNC                                 + 1)
+#define        ES11_BUFFERSUBDATA                              (ES11_BUFFERDATA                                + 1)
+#define        ES11_CLEAR                                              (ES11_BUFFERSUBDATA                             + 1)
+#define        ES11_CLEARCOLOR                                 (ES11_CLEAR                                             + 1)
+#define        ES11_CLEARCOLORX                                (ES11_CLEARCOLOR                                + 1)
+#define        ES11_CLEARDEPTHF                                (ES11_CLEARCOLORX                               + 1)
+#define        ES11_CLEARDEPTHX                                (ES11_CLEARDEPTHF                               + 1)
+#define        ES11_CLEARSTENCIL                               (ES11_CLEARDEPTHX                               + 1)
+#define        ES11_CLIENTACTIVETEXTURE        (ES11_CLEARSTENCIL                              + 1)
+#define        ES11_CLIPPLANEF                         (ES11_CLIENTACTIVETEXTURE               + 1)
+#define        ES11_CLIPPLANEX                         (ES11_CLIPPLANEF                        + 1)
+#define        ES11_COLOR4F                                    (ES11_CLIPPLANEX                        + 1)
+#define        ES11_COLOR4UB                           (ES11_COLOR4F                                   + 1)
+#define        ES11_COLOR4X                                    (ES11_COLOR4UB                                  + 1)
+#define        ES11_COLORMASK                          (ES11_COLOR4X                                   + 1)
+#define        ES11_COLORPOINTER                       (ES11_COLORMASK                         + 1)
+#define        ES11_COMPRESSEDTEXIMAGE2D       (ES11_COLORPOINTER                      + 1)
+#define        ES11_COMPRESSEDTEXSUBIMAGE2D    (ES11_COMPRESSEDTEXIMAGE2D      + 1)
+#define        ES11_COPYTEXIMAGE2D                     (ES11_COMPRESSEDTEXSUBIMAGE2D   + 1)
+#define        ES11_COPYTEXSUBIMAGE2D          (ES11_COPYTEXIMAGE2D                    + 1)
+#define        ES11_CULLFACE                           (ES11_COPYTEXSUBIMAGE2D                 + 1)
+#define        ES11_DELETEBUFFERS                      (ES11_CULLFACE                          + 1)
+#define        ES11_DELETETEXTURES                     (ES11_DELETEBUFFERS                     + 1)
+#define        ES11_DEPTHFUNC                          (ES11_DELETETEXTURES                    + 1)
+#define        ES11_DEPTHMASK                          (ES11_DEPTHFUNC                         + 1)
+#define        ES11_DEPTHRANGEF                        (ES11_DEPTHMASK                         + 1)
+#define        ES11_DEPTHRANGEX                        (ES11_DEPTHRANGEF                       + 1)
+#define        ES11_DISABLE                                    (ES11_DEPTHRANGEX                       + 1)
+#define        ES11_DISABLECLIENTSTATE         (ES11_DISABLE                                   + 1)
+#define        ES11_DRAWARRAYS                         (ES11_DISABLECLIENTSTATE                + 1)
+#define        ES11_DRAWELEMENTS                       (ES11_DRAWARRAYS                        + 1)
+#define        ES11_ENABLE                                     (ES11_DRAWELEMENTS                      + 1)
+#define        ES11_ENABLECLIENTSTATE          (ES11_ENABLE                                    + 1)
+#define        ES11_FINISH                                     (ES11_ENABLECLIENTSTATE                 + 1)
+#define        ES11_FLUSH                                      (ES11_FINISH                                    + 1)
+#define        ES11_FOGF                                       (ES11_FLUSH                                     + 1)
+#define        ES11_FOGFV                                      (ES11_FOGF                                      + 1)
+#define        ES11_FOGX                                       (ES11_FOGFV                                     + 1)
+#define        ES11_FOGXV                                      (ES11_FOGX                                      + 1)
+#define        ES11_FRONTFACE                          (ES11_FOGXV                                     + 1)
+#define        ES11_FRUSTUMF                           (ES11_FRONTFACE                         + 1)
+#define        ES11_FRUSTUMX                           (ES11_FRUSTUMF                          + 1)
+#define        ES11_GENBUFFERS                         (ES11_FRUSTUMX                          + 1)
+#define        ES11_GENTEXTURES                        (ES11_GENBUFFERS                        + 1)
+#define        ES11_GETBOOLEANV                        (ES11_GENTEXTURES                       + 1)
+#define        ES11_GETBUFFERPARAMETERIV       (ES11_GETBOOLEANV                       + 1)
+#define        ES11_GETCLIPPLANEF                      (ES11_GETBUFFERPARAMETERIV              + 1)
+#define        ES11_GETCLIPPLANEX                      (ES11_GETCLIPPLANEF                     + 1)
+#define        ES11_GETERROR                           (ES11_GETCLIPPLANEX                     + 1)
+#define        ES11_GETFIXEDV                          (ES11_GETERROR                          + 1)
+#define        ES11_GETFLOATV                          (ES11_GETFIXEDV                         + 1)
+#define        ES11_GETINTEGERV                        (ES11_GETFLOATV                         + 1)
+#define        ES11_GETLIGHTFV                         (ES11_GETINTEGERV                       + 1)
+#define        ES11_GETLIGHTXV                         (ES11_GETLIGHTFV                        + 1)
+#define        ES11_GETMATERIALFV                      (ES11_GETLIGHTXV                        + 1)
+#define        ES11_GETMATERIALXV                      (ES11_GETMATERIALFV                     + 1)
+#define        ES11_GETPOINTERV                        (ES11_GETMATERIALXV                     + 1)
+#define        ES11_GETSTRING                          (ES11_GETPOINTERV                       + 1)
+#define        ES11_GETTEXENVFV                        (ES11_GETSTRING                         + 1)
+#define        ES11_GETTEXENVIV                        (ES11_GETTEXENVFV                       + 1)
+#define        ES11_GETTEXENVXV                        (ES11_GETTEXENVIV                       + 1)
+#define        ES11_GETTEXPARAMETERFV          (ES11_GETTEXENVXV                       + 1)
+#define        ES11_GETTEXPARAMETERIV          (ES11_GETTEXPARAMETERFV         + 1)
+#define        ES11_GETTEXPARAMETERXV          (ES11_GETTEXPARAMETERIV         + 1)
+#define        ES11_HINT                                       (ES11_GETTEXPARAMETERXV         + 1)
+#define        ES11_ISBUFFER                           (ES11_HINT                                      + 1)
+#define        ES11_ISENABLED                          (ES11_ISBUFFER                          + 1)
+#define        ES11_ISTEXTURE                          (ES11_ISENABLED                         + 1)
+#define        ES11_LIGHTF                                     (ES11_ISTEXTURE                         + 1)
+#define        ES11_LIGHTFV                                    (ES11_LIGHTF                                    + 1)
+#define        ES11_LIGHTMODELF                        (ES11_LIGHTFV                                   + 1)
+#define        ES11_LIGHTMODELFV                       (ES11_LIGHTMODELF                       + 1)
+#define        ES11_LIGHTMODELX                        (ES11_LIGHTMODELFV                      + 1)
+#define        ES11_LIGHTMODELXV                       (ES11_LIGHTMODELX                       + 1)
+#define        ES11_LIGHTX                                     (ES11_LIGHTMODELXV                      + 1)
+#define        ES11_LIGHTXV                                    (ES11_LIGHTX                                    + 1)
+#define        ES11_LINEWIDTH                          (ES11_LIGHTXV                                   + 1)
+#define        ES11_LINEWIDTHX                         (ES11_LINEWIDTH                         + 1)
+#define        ES11_LOADIDENTITY                       (ES11_LINEWIDTHX                        + 1)
+#define        ES11_LOADMATRIXF                        (ES11_LOADIDENTITY                      + 1)
+#define        ES11_LOADMATRIXX                        (ES11_LOADMATRIXF                       + 1)
+#define        ES11_LOGICOP                                    (ES11_LOADMATRIXX                       + 1)
+#define        ES11_MATERIALF                          (ES11_LOGICOP                                   + 1)
+#define        ES11_MATERIALFV                         (ES11_MATERIALF                         + 1)
+#define        ES11_MATERIALX                          (ES11_MATERIALFV                        + 1)
+#define        ES11_MATERIALXV                         (ES11_MATERIALX                         + 1)
+#define        ES11_MATRIXMODE                         (ES11_MATERIALXV                        + 1)
+#define        ES11_MULTITEXCOORD4F                    (ES11_MATRIXMODE                        + 1)
+#define        ES11_MULTITEXCOORD4X                    (ES11_MULTITEXCOORD4F                   + 1)
+#define        ES11_MULTMATRIXF                        (ES11_MULTITEXCOORD4X                   + 1)
+#define        ES11_MULTMATRIXX                        (ES11_MULTMATRIXF                       + 1)
+#define        ES11_NORMAL3F                           (ES11_MULTMATRIXX                       + 1)
+#define        ES11_NORMAL3X                           (ES11_NORMAL3F                          + 1)
+#define        ES11_NORMALPOINTER                      (ES11_NORMAL3X                          + 1)
+#define        ES11_ORTHOF                                     (ES11_NORMALPOINTER                     + 1)
+#define        ES11_ORTHOX                                     (ES11_ORTHOF                                    + 1)
+#define        ES11_PIXELSTOREI                        (ES11_ORTHOX                                    + 1)
+#define        ES11_POINTPARAMETERF                    (ES11_PIXELSTOREI                       + 1)
+#define        ES11_POINTPARAMETERFV                   (ES11_POINTPARAMETERF                   + 1)
+#define        ES11_POINTPARAMETERX                    (ES11_POINTPARAMETERFV                  + 1)
+#define        ES11_POINTPARAMETERXV                   (ES11_POINTPARAMETERX                   + 1)
+#define        ES11_POINTSIZE                          (ES11_POINTPARAMETERXV                  + 1)
+#define        ES11_POINTSIZEX                         (ES11_POINTSIZE                         + 1)
+#define        ES11_POLYGONOFFSET                      (ES11_POINTSIZEX                        + 1)
+#define        ES11_POLYGONOFFSETX                     (ES11_POLYGONOFFSET                     + 1)
+#define        ES11_POPMATRIX                          (ES11_POLYGONOFFSETX                    + 1)
+#define        ES11_PUSHMATRIX                         (ES11_POPMATRIX                         + 1)
+#define        ES11_READPIXELS                         (ES11_PUSHMATRIX                        + 1)
+#define        ES11_ROTATEF                                    (ES11_READPIXELS                        + 1)
+#define        ES11_ROTATEX                                    (ES11_ROTATEF                                   + 1)
+#define        ES11_SAMPLECOVERAGE                     (ES11_ROTATEX                                   + 1)
+#define        ES11_SAMPLECOVERAGEX                    (ES11_SAMPLECOVERAGE                    + 1)
+#define        ES11_SCALEF                                     (ES11_SAMPLECOVERAGEX                   + 1)
+#define        ES11_SCALEX                                     (ES11_SCALEF                                    + 1)
+#define        ES11_SCISSOR                                    (ES11_SCALEX                                    + 1)
+#define        ES11_SHADEMODEL                         (ES11_SCISSOR                                   + 1)
+#define        ES11_STENCILFUNC                        (ES11_SHADEMODEL                        + 1)
+#define        ES11_STENCILMASK                        (ES11_STENCILFUNC                       + 1)
+#define        ES11_STENCILOP                          (ES11_STENCILMASK                       + 1)
+#define        ES11_TEXCOORDPOINTER                    (ES11_STENCILOP                         + 1)
+#define        ES11_TEXENVF                                    (ES11_TEXCOORDPOINTER                   + 1)
+#define        ES11_TEXENVFV                                   (ES11_TEXENVF                                   + 1)
+#define        ES11_TEXENVI                                    (ES11_TEXENVFV                                  + 1)
+#define        ES11_TEXENVIV                                   (ES11_TEXENVI                                   + 1)
+#define        ES11_TEXENVX                                    (ES11_TEXENVIV                                  + 1)
+#define        ES11_TEXENVXV                           (ES11_TEXENVX                                   + 1)
+#define        ES11_TEXIMAGE2D                         (ES11_TEXENVXV                          + 1)
+#define        ES11_TEXPARAMETERF                      (ES11_TEXIMAGE2D                        + 1)
+#define        ES11_TEXPARAMETERFV                     (ES11_TEXPARAMETERF                     + 1)
+#define        ES11_TEXPARAMETERI                      (ES11_TEXPARAMETERFV                    + 1)
+#define        ES11_TEXPARAMETERIV                     (ES11_TEXPARAMETERI                     + 1)
+#define        ES11_TEXPARAMETERX                      (ES11_TEXPARAMETERIV                    + 1)
+#define        ES11_TEXPARAMETERXV                     (ES11_TEXPARAMETERX                     + 1)
+#define        ES11_TEXSUBIMAGE2D                      (ES11_TEXPARAMETERXV                    + 1)
+#define        ES11_TRANSLATEF                         (ES11_TEXSUBIMAGE2D                     + 1)
+#define        ES11_TRANSLATEX                         (ES11_TRANSLATEF                        + 1)
+#define        ES11_VERTEXPOINTER                      (ES11_TRANSLATEX                        + 1)
+#define        ES11_VIEWPORT                           (ES11_VERTEXPOINTER                     + 1)
+#define        ES11_CALLS                                      (ES11_VIEWPORT                          + 1)
+#define        ES11_DRAWCALLS                          (ES11_CALLS                                             + 1)
+#define        ES11_STATECHANGECALLS                   (ES11_DRAWCALLS                                 + 1)
+#define        ES11_POINTCOUNT                         (ES11_STATECHANGECALLS                  + 1)
+#define        ES11_LINECOUNT                          (ES11_POINTCOUNT                        + 1)
+#define        ES11_TRIANGLECOUNT                      (ES11_LINECOUNT                         + 1)
+
+/* OpenGL ES2X API IDs. */
+#define        ES20_ACTIVETEXTURE                              1
+#define        ES20_ATTACHSHADER                                                       (ES20_ACTIVETEXTURE                                                     +       1)
+#define        ES20_BINDATTRIBLOCATION                                         (ES20_ATTACHSHADER                                                      +       1)
+#define        ES20_BINDBUFFER                                                         (ES20_BINDATTRIBLOCATION                                        +       1)
+#define        ES20_BINDFRAMEBUFFER                                            (ES20_BINDBUFFER                                                        +       1)
+#define        ES20_BINDRENDERBUFFER                                           (ES20_BINDFRAMEBUFFER                                           +       1)
+#define        ES20_BINDTEXTURE                                                        (ES20_BINDRENDERBUFFER                                          +       1)
+#define        ES20_BLENDCOLOR                                                         (ES20_BINDTEXTURE                                                       +       1)
+#define        ES20_BLENDEQUATION                                                      (ES20_BLENDCOLOR                                                        +       1)
+#define        ES20_BLENDEQUATIONSEPARATE                                      (ES20_BLENDEQUATION                                                     +       1)
+#define        ES20_BLENDFUNC                                                          (ES20_BLENDEQUATIONSEPARATE                                     +       1)
+#define        ES20_BLENDFUNCSEPARATE                                          (ES20_BLENDFUNC                                                         +       1)
+#define        ES20_BUFFERDATA                                                         (ES20_BLENDFUNCSEPARATE                                         +       1)
+#define        ES20_BUFFERSUBDATA                                                      (ES20_BUFFERDATA                                                        +       1)
+#define        ES20_CHECKFRAMEBUFFERSTATUS                                     (ES20_BUFFERSUBDATA                                                     +       1)
+#define        ES20_CLEAR                                                                      (ES20_CHECKFRAMEBUFFERSTATUS                            +       1)
+#define        ES20_CLEARCOLOR                                                         (ES20_CLEAR                                                                     +       1)
+#define        ES20_CLEARDEPTHF                                                        (ES20_CLEARCOLOR                                                        +       1)
+#define        ES20_CLEARSTENCIL                                                       (ES20_CLEARDEPTHF                                                       +       1)
+#define        ES20_COLORMASK                                                          (ES20_CLEARSTENCIL                                                      +       1)
+#define        ES20_COMPILESHADER                                                      (ES20_COLORMASK                                                         +       1)
+#define        ES20_COMPRESSEDTEXIMAGE2D                                       (ES20_COMPILESHADER                                                     +       1)
+#define        ES20_COMPRESSEDTEXSUBIMAGE2D                            (ES20_COMPRESSEDTEXIMAGE2D                                      +       1)
+#define        ES20_COPYTEXIMAGE2D                                                     (ES20_COMPRESSEDTEXSUBIMAGE2D                           +       1)
+#define        ES20_COPYTEXSUBIMAGE2D                                          (ES20_COPYTEXIMAGE2D                                            +       1)
+#define        ES20_CREATEPROGRAM                                                      (ES20_COPYTEXSUBIMAGE2D                                         +       1)
+#define        ES20_CREATESHADER                                                       (ES20_CREATEPROGRAM                                                     +       1)
+#define        ES20_CULLFACE                                                           (ES20_CREATESHADER                                                      +       1)
+#define        ES20_DELETEBUFFERS                                                      (ES20_CULLFACE                                                          +       1)
+#define        ES20_DELETEFRAMEBUFFERS                                         (ES20_DELETEBUFFERS                                                     +       1)
+#define        ES20_DELETEPROGRAM                                                      (ES20_DELETEFRAMEBUFFERS                                        +       1)
+#define        ES20_DELETERENDERBUFFERS                                        (ES20_DELETEPROGRAM                                                     +       1)
+#define        ES20_DELETESHADER                                                       (ES20_DELETERENDERBUFFERS                                       +       1)
+#define        ES20_DELETETEXTURES                                                     (ES20_DELETESHADER                                                      +       1)
+#define        ES20_DEPTHFUNC                                                          (ES20_DELETETEXTURES                                            +       1)
+#define        ES20_DEPTHMASK                                                          (ES20_DEPTHFUNC                                                         +       1)
+#define        ES20_DEPTHRANGEF                                                        (ES20_DEPTHMASK                                                         +       1)
+#define        ES20_DETACHSHADER                                                       (ES20_DEPTHRANGEF                                                       +       1)
+#define        ES20_DISABLE                                                            (ES20_DETACHSHADER                                                      +       1)
+#define        ES20_DISABLEVERTEXATTRIBARRAY                           (ES20_DISABLE                                                           +       1)
+#define        ES20_DRAWARRAYS                                                         (ES20_DISABLEVERTEXATTRIBARRAY                          +       1)
+#define        ES20_DRAWELEMENTS                                                       (ES20_DRAWARRAYS                                                        +       1)
+#define        ES20_ENABLE                                                                     (ES20_DRAWELEMENTS                                                      +       1)
+#define        ES20_ENABLEVERTEXATTRIBARRAY                            (ES20_ENABLE                                                            +       1)
+#define        ES20_FINISH                                                                     (ES20_ENABLEVERTEXATTRIBARRAY                           +       1)
+#define        ES20_FLUSH                                                                      (ES20_FINISH                                                            +       1)
+#define        ES20_FRAMEBUFFERRENDERBUFFER                            (ES20_FLUSH                                                                     +       1)
+#define        ES20_FRAMEBUFFERTEXTURE2D                                       (ES20_FRAMEBUFFERRENDERBUFFER                           +       1)
+#define        ES20_FRONTFACE                                                          (ES20_FRAMEBUFFERTEXTURE2D                                      +       1)
+#define        ES20_GENBUFFERS                                                         (ES20_FRONTFACE                                                         +       1)
+#define        ES20_GENERATEMIPMAP                                                     (ES20_GENBUFFERS                                                        +       1)
+#define        ES20_GENFRAMEBUFFERS                                            (ES20_GENERATEMIPMAP                                            +       1)
+#define        ES20_GENRENDERBUFFERS                                           (ES20_GENFRAMEBUFFERS                                           +       1)
+#define        ES20_GENTEXTURES                                                        (ES20_GENRENDERBUFFERS                                          +       1)
+#define        ES20_GETACTIVEATTRIB                                            (ES20_GENTEXTURES                                                       +       1)
+#define        ES20_GETACTIVEUNIFORM                                           (ES20_GETACTIVEATTRIB                                           +       1)
+#define        ES20_GETATTACHEDSHADERS                                         (ES20_GETACTIVEUNIFORM                                          +       1)
+#define        ES20_GETATTRIBLOCATION                                          (ES20_GETATTACHEDSHADERS                                        +       1)
+#define        ES20_GETBOOLEANV                                                        (ES20_GETATTRIBLOCATION                                         +       1)
+#define        ES20_GETBUFFERPARAMETERIV                                       (ES20_GETBOOLEANV                                                       +       1)
+#define        ES20_GETERROR                                                           (ES20_GETBUFFERPARAMETERIV                                      +       1)
+#define        ES20_GETFLOATV                                                          (ES20_GETERROR                                                          +       1)
+#define        ES20_GETFRAMEBUFFERATTACHMENTPARAMETERIV        (ES20_GETFLOATV                                                         +       1)
+#define        ES20_GETINTEGERV                                                        (ES20_GETFRAMEBUFFERATTACHMENTPARAMETERIV       +       1)
+#define        ES20_GETPROGRAMIV                                                       (ES20_GETINTEGERV                                                       +       1)
+#define        ES20_GETPROGRAMINFOLOG                                          (ES20_GETPROGRAMIV                                                      +       1)
+#define        ES20_GETRENDERBUFFERPARAMETERIV                         (ES20_GETPROGRAMINFOLOG                                         +       1)
+#define        ES20_GETSHADERIV                                                        (ES20_GETRENDERBUFFERPARAMETERIV                        +       1)
+#define        ES20_GETSHADERINFOLOG                                           (ES20_GETSHADERIV                                                       +       1)
+#define        ES20_GETSHADERPRECISIONFORMAT                           (ES20_GETSHADERINFOLOG                                          +       1)
+#define        ES20_GETSHADERSOURCE                                            (ES20_GETSHADERPRECISIONFORMAT                          +       1)
+#define        ES20_GETSTRING                                                          (ES20_GETSHADERSOURCE                                           +       1)
+#define        ES20_GETTEXPARAMETERFV                                          (ES20_GETSTRING                                                         +       1)
+#define        ES20_GETTEXPARAMETERIV                                          (ES20_GETTEXPARAMETERFV                                         +       1)
+#define        ES20_GETUNIFORMFV                                                       (ES20_GETTEXPARAMETERIV                                         +       1)
+#define        ES20_GETUNIFORMIV                                                       (ES20_GETUNIFORMFV                                                      +       1)
+#define        ES20_GETUNIFORMLOCATION                                         (ES20_GETUNIFORMIV                                                      +       1)
+#define        ES20_GETVERTEXATTRIBFV                                          (ES20_GETUNIFORMLOCATION                                        +       1)
+#define        ES20_GETVERTEXATTRIBIV                                          (ES20_GETVERTEXATTRIBFV                                         +       1)
+#define        ES20_GETVERTEXATTRIBPOINTERV                            (ES20_GETVERTEXATTRIBIV                                         +       1)
+#define        ES20_HINT                                                                       (ES20_GETVERTEXATTRIBPOINTERV                           +       1)
+#define        ES20_ISBUFFER                                                           (ES20_HINT                                                                      +       1)
+#define        ES20_ISENABLED                                                          (ES20_ISBUFFER                                                          +       1)
+#define        ES20_ISFRAMEBUFFER                                                      (ES20_ISENABLED                                                         +       1)
+#define        ES20_ISPROGRAM                                                          (ES20_ISFRAMEBUFFER                                                     +       1)
+#define        ES20_ISRENDERBUFFER                                                     (ES20_ISPROGRAM                                                         +       1)
+#define        ES20_ISSHADER                                                           (ES20_ISRENDERBUFFER                                            +       1)
+#define        ES20_ISTEXTURE                                                          (ES20_ISSHADER                                                          +       1)
+#define        ES20_LINEWIDTH                                                          (ES20_ISTEXTURE                                                         +       1)
+#define        ES20_LINKPROGRAM                                                        (ES20_LINEWIDTH                                                         +       1)
+#define        ES20_PIXELSTOREI                                                        (ES20_LINKPROGRAM                                                       +       1)
+#define        ES20_POLYGONOFFSET                                                      (ES20_PIXELSTOREI                                                       +       1)
+#define        ES20_READPIXELS                                                         (ES20_POLYGONOFFSET                                                     +       1)
+#define        ES20_RELEASESHADERCOMPILER                                      (ES20_READPIXELS                                                        +       1)
+#define        ES20_RENDERBUFFERSTORAGE                                        (ES20_RELEASESHADERCOMPILER                                     +       1)
+#define        ES20_SAMPLECOVERAGE                                                     (ES20_RENDERBUFFERSTORAGE                                       +       1)
+#define        ES20_SCISSOR                                                            (ES20_SAMPLECOVERAGE                                            +       1)
+#define        ES20_SHADERBINARY                                                       (ES20_SCISSOR                                                           +       1)
+#define        ES20_SHADERSOURCE                                                       (ES20_SHADERBINARY                                                      +       1)
+#define        ES20_STENCILFUNC                                                        (ES20_SHADERSOURCE                                                      +       1)
+#define        ES20_STENCILFUNCSEPARATE                                        (ES20_STENCILFUNC                                                       +       1)
+#define        ES20_STENCILMASK                                                        (ES20_STENCILFUNCSEPARATE                                       +       1)
+#define        ES20_STENCILMASKSEPARATE                                        (ES20_STENCILMASK                                                       +       1)
+#define        ES20_STENCILOP                                                          (ES20_STENCILMASKSEPARATE                                       +       1)
+#define        ES20_STENCILOPSEPARATE                                          (ES20_STENCILOP                                                         +       1)
+#define        ES20_TEXIMAGE2D                                                         (ES20_STENCILOPSEPARATE                                         +       1)
+#define        ES20_TEXPARAMETERF                                                      (ES20_TEXIMAGE2D                                                        +       1)
+#define        ES20_TEXPARAMETERFV                                                     (ES20_TEXPARAMETERF                                                     +       1)
+#define        ES20_TEXPARAMETERI                                                      (ES20_TEXPARAMETERFV                                            +       1)
+#define        ES20_TEXPARAMETERIV                                                     (ES20_TEXPARAMETERI                                                     +       1)
+#define        ES20_TEXSUBIMAGE2D                                                      (ES20_TEXPARAMETERIV                                            +       1)
+#define        ES20_UNIFORM1F                                                          (ES20_TEXSUBIMAGE2D                                                     +       1)
+#define        ES20_UNIFORM1FV                                                         (ES20_UNIFORM1F                                                         +       1)
+#define        ES20_UNIFORM1I                                                          (ES20_UNIFORM1FV                                                        +       1)
+#define        ES20_UNIFORM1IV                                                         (ES20_UNIFORM1I                                                         +       1)
+#define        ES20_UNIFORM2F                                                          (ES20_UNIFORM1IV                                                        +       1)
+#define        ES20_UNIFORM2FV                                                         (ES20_UNIFORM2F                                                         +       1)
+#define        ES20_UNIFORM2I                                                          (ES20_UNIFORM2FV                                                        +       1)
+#define        ES20_UNIFORM2IV                                                         (ES20_UNIFORM2I                                                         +       1)
+#define        ES20_UNIFORM3F                                                          (ES20_UNIFORM2IV                                                        +       1)
+#define        ES20_UNIFORM3FV                                                         (ES20_UNIFORM3F                                                         +       1)
+#define        ES20_UNIFORM3I                                                          (ES20_UNIFORM3FV                                                        +       1)
+#define        ES20_UNIFORM3IV                                                         (ES20_UNIFORM3I                                                         +       1)
+#define        ES20_UNIFORM4F                                                          (ES20_UNIFORM3IV                                                        +       1)
+#define        ES20_UNIFORM4FV                                                         (ES20_UNIFORM4F                                                         +       1)
+#define        ES20_UNIFORM4I                                                          (ES20_UNIFORM4FV                                                        +       1)
+#define        ES20_UNIFORM4IV                                                         (ES20_UNIFORM4I                                                         +       1)
+#define        ES20_UNIFORMMATRIX2FV                                           (ES20_UNIFORM4IV                                                        +       1)
+#define        ES20_UNIFORMMATRIX3FV                                           (ES20_UNIFORMMATRIX2FV                                          +       1)
+#define        ES20_UNIFORMMATRIX4FV                                           (ES20_UNIFORMMATRIX3FV                                          +       1)
+#define        ES20_USEPROGRAM                                                         (ES20_UNIFORMMATRIX4FV                                          +       1)
+#define        ES20_VALIDATEPROGRAM                                            (ES20_USEPROGRAM                                                        +       1)
+#define        ES20_VERTEXATTRIB1F                                                     (ES20_VALIDATEPROGRAM                                           +       1)
+#define        ES20_VERTEXATTRIB1FV                                            (ES20_VERTEXATTRIB1F                                            +       1)
+#define        ES20_VERTEXATTRIB2F                                                     (ES20_VERTEXATTRIB1FV                                           +       1)
+#define        ES20_VERTEXATTRIB2FV                                            (ES20_VERTEXATTRIB2F                                            +       1)
+#define        ES20_VERTEXATTRIB3F                                                     (ES20_VERTEXATTRIB2FV                                           +       1)
+#define        ES20_VERTEXATTRIB3FV                                            (ES20_VERTEXATTRIB3F                                            +       1)
+#define        ES20_VERTEXATTRIB4F                                                     (ES20_VERTEXATTRIB3FV                                           +       1)
+#define        ES20_VERTEXATTRIB4FV                                            (ES20_VERTEXATTRIB4F                                            +       1)
+#define        ES20_VERTEXATTRIBPOINTER                                        (ES20_VERTEXATTRIB4FV                                           +       1)
+#define        ES20_VIEWPORT                                                           (ES20_VERTEXATTRIBPOINTER                                       +       1)
+#define        ES20_CALLS                                                                      (ES20_VIEWPORT                                                          +       1)
+#define        ES20_DRAWCALLS                                                          (ES20_CALLS                                                                     +       1)
+#define        ES20_STATECHANGECALLS                                           (ES20_DRAWCALLS                                                         +       1)
+#define        ES20_POINTCOUNT                                                         (ES20_STATECHANGECALLS                                          +       1)
+#define        ES20_LINECOUNT                                                          (ES20_POINTCOUNT                                                        +       1)
+#define        ES20_TRIANGLECOUNT                                                      (ES20_LINECOUNT                                                         +       1)
+
+/* OpenVG API IDs. */
+#define        VG11_APPENDPATH                      1
+#define        VG11_APPENDPATHDATA                     (VG11_APPENDPATH                                + 1)
+#define        VG11_CHILDIMAGE                         (VG11_APPENDPATHDATA                    + 1)
+#define        VG11_CLEAR                                      (VG11_CHILDIMAGE                                + 1)
+#define        VG11_CLEARGLYPH                         (VG11_CLEAR                                             + 1)
+#define        VG11_CLEARIMAGE                         (VG11_CLEARGLYPH                                + 1)
+#define        VG11_CLEARPATH                          (VG11_CLEARIMAGE                                + 1)
+#define        VG11_COLORMATRIX                        (VG11_CLEARPATH                                 + 1)
+#define        VG11_CONVOLVE                           (VG11_COLORMATRIX                               + 1)
+#define        VG11_COPYIMAGE                          (VG11_CONVOLVE                                  + 1)
+#define        VG11_COPYMASK                           (VG11_COPYIMAGE                                 + 1)
+#define        VG11_COPYPIXELS                         (VG11_COPYMASK                                  + 1)
+#define        VG11_CREATEFONT                         (VG11_COPYPIXELS                                + 1)
+#define        VG11_CREATEIMAGE                        (VG11_CREATEFONT                                + 1)
+#define        VG11_CREATEMASKLAYER            (VG11_CREATEIMAGE                               + 1)
+#define        VG11_CREATEPAINT                        (VG11_CREATEMASKLAYER                   + 1)
+#define        VG11_CREATEPATH                         (VG11_CREATEPAINT                               + 1)
+#define        VG11_DESTROYFONT                        (VG11_CREATEPATH                                + 1)
+#define        VG11_DESTROYIMAGE                       (VG11_DESTROYFONT                               + 1)
+#define        VG11_DESTROYMASKLAYER           (VG11_DESTROYIMAGE                              + 1)
+#define        VG11_DESTROYPAINT                       (VG11_DESTROYMASKLAYER                  + 1)
+#define        VG11_DESTROYPATH                        (VG11_DESTROYPAINT                              + 1)
+#define        VG11_DRAWGLYPH                          (VG11_DESTROYPATH                               + 1)
+#define        VG11_DRAWGLYPHS                         (VG11_DRAWGLYPH                                 + 1)
+#define        VG11_DRAWIMAGE                          (VG11_DRAWGLYPHS                                + 1)
+#define        VG11_DRAWPATH                           (VG11_DRAWIMAGE                                 + 1)
+#define        VG11_FILLMASKLAYER                      (VG11_DRAWPATH                                  + 1)
+#define        VG11_FINISH                                     (VG11_FILLMASKLAYER                             + 1)
+#define        VG11_FLUSH                                      (VG11_FINISH                                    + 1)
+#define        VG11_GAUSSIANBLUR                       (VG11_FLUSH                                             + 1)
+#define        VG11_GETCOLOR                           (VG11_GAUSSIANBLUR                              + 1)
+#define        VG11_GETERROR                           (VG11_GETCOLOR                                  + 1)
+#define        VG11_GETF                                       (VG11_GETERROR                                  + 1)
+#define        VG11_GETFV                                      (VG11_GETF                                              + 1)
+#define        VG11_GETI                                       (VG11_GETFV                                             + 1)
+#define        VG11_GETIMAGESUBDATA            (VG11_GETI                                              + 1)
+#define        VG11_GETIV                                      (VG11_GETIMAGESUBDATA                   + 1)
+#define        VG11_GETMATRIX                          (VG11_GETIV                                             + 1)
+#define        VG11_GETPAINT                           (VG11_GETMATRIX                                 + 1)
+#define        VG11_GETPARAMETERF                      (VG11_GETPAINT                                  + 1)
+#define        VG11_GETPARAMETERFV                     (VG11_GETPARAMETERF                             + 1)
+#define        VG11_GETPARAMETERI                      (VG11_GETPARAMETERFV                    + 1)
+#define        VG11_GETPARAMETERIV                     (VG11_GETPARAMETERI                             + 1)
+#define        VG11_GETPARAMETERVECTORSIZE     (VG11_GETPARAMETERIV                    + 1)
+#define        VG11_GETPARENT                          (VG11_GETPARAMETERVECTORSIZE    + 1)
+#define        VG11_GETPATHCAPABILITIES        (VG11_GETPARENT                                 + 1)
+#define        VG11_GETPIXELS                          (VG11_GETPATHCAPABILITIES               + 1)
+#define        VG11_GETSTRING                          (VG11_GETPIXELS                                 + 1)
+#define        VG11_GETVECTORSIZE                      (VG11_GETSTRING                                 + 1)
+#define        VG11_HARDWAREQUERY                      (VG11_GETVECTORSIZE                             + 1)
+#define        VG11_IMAGESUBDATA                       (VG11_HARDWAREQUERY                             + 1)
+#define        VG11_INTERPOLATEPATH            (VG11_IMAGESUBDATA                              + 1)
+#define        VG11_LOADIDENTITY                       (VG11_INTERPOLATEPATH                   + 1)
+#define        VG11_LOADMATRIX                         (VG11_LOADIDENTITY                              + 1)
+#define        VG11_LOOKUP                                     (VG11_LOADMATRIX                                + 1)
+#define        VG11_LOOKUPSINGLE                       (VG11_LOOKUP                                    + 1)
+#define        VG11_MASK                                       (VG11_LOOKUPSINGLE                              + 1)
+#define        VG11_MODIFYPATHCOORDS           (VG11_MASK                                              + 1)
+#define        VG11_MULTMATRIX                         (VG11_MODIFYPATHCOORDS                  + 1)
+#define        VG11_PAINTPATTERN                       (VG11_MULTMATRIX                                + 1)
+#define        VG11_PATHBOUNDS                         (VG11_PAINTPATTERN                              + 1)
+#define        VG11_PATHLENGTH                         (VG11_PATHBOUNDS                                + 1)
+#define        VG11_PATHTRANSFORMEDBOUNDS      (VG11_PATHLENGTH                                + 1)
+#define        VG11_POINTALONGPATH                     (VG11_PATHTRANSFORMEDBOUNDS             + 1)
+#define        VG11_READPIXELS                         (VG11_POINTALONGPATH                    + 1)
+#define        VG11_REMOVEPATHCAPABILITIES     (VG11_READPIXELS                                + 1)
+#define        VG11_RENDERTOMASK                       (VG11_REMOVEPATHCAPABILITIES    + 1)
+#define        VG11_ROTATE                                     (VG11_RENDERTOMASK                              + 1)
+#define        VG11_SCALE                                      (VG11_ROTATE                                    + 1)
+#define        VG11_SEPARABLECONVOLVE          (VG11_SCALE                                             + 1)
+#define        VG11_SETCOLOR                           (VG11_SEPARABLECONVOLVE                 + 1)
+#define        VG11_SETF                                       (VG11_SETCOLOR                                  + 1)
+#define        VG11_SETFV                                      (VG11_SETF                                              + 1)
+#define        VG11_SETGLYPHTOIMAGE            (VG11_SETFV                                             + 1)
+#define        VG11_SETGLYPHTOPATH                     (VG11_SETGLYPHTOIMAGE                   + 1)
+#define        VG11_SETI                                       (VG11_SETGLYPHTOPATH                    + 1)
+#define        VG11_SETIV                                      (VG11_SETI                                              + 1)
+#define        VG11_SETPAINT                           (VG11_SETIV                                             + 1)
+#define        VG11_SETPARAMETERF                      (VG11_SETPAINT                                  + 1)
+#define        VG11_SETPARAMETERFV                     (VG11_SETPARAMETERF                             + 1)
+#define        VG11_SETPARAMETERI                      (VG11_SETPARAMETERFV                    + 1)
+#define        VG11_SETPARAMETERIV                     (VG11_SETPARAMETERI                             + 1)
+#define        VG11_SETPIXELS                          (VG11_SETPARAMETERIV                    + 1)
+#define        VG11_SHEAR                                      (VG11_SETPIXELS                                 + 1)
+#define        VG11_TRANSFORMPATH                      (VG11_SHEAR                                             + 1)
+#define        VG11_TRANSLATE                          (VG11_TRANSFORMPATH                             + 1)
+#define        VG11_WRITEPIXELS                        (VG11_TRANSLATE                                 + 1)
+/* End of Driver API ID Definitions. */
+
+/* HAL & MISC IDs. */
+#define HAL_VERTBUFNEWBYTEALLOC                1
+#define HAL_VERTBUFTOTALBYTEALLOC      (HAL_VERTBUFNEWBYTEALLOC        + 1)
+#define HAL_VERTBUFNEWOBJALLOC         (HAL_VERTBUFTOTALBYTEALLOC      + 1)
+#define HAL_VERTBUFTOTALOBJALLOC       (HAL_VERTBUFNEWOBJALLOC         + 1)
+#define HAL_INDBUFNEWBYTEALLOC         (HAL_VERTBUFTOTALOBJALLOC       + 1)
+#define HAL_INDBUFTOTALBYTEALLOC       (HAL_INDBUFNEWBYTEALLOC         + 1)
+#define HAL_INDBUFNEWOBJALLOC          (HAL_INDBUFTOTALBYTEALLOC       + 1)
+#define HAL_INDBUFTOTALOBJALLOC                (HAL_INDBUFNEWOBJALLOC          + 1)
+#define HAL_TEXBUFNEWBYTEALLOC         (HAL_INDBUFTOTALOBJALLOC        + 1)
+#define HAL_TEXBUFTOTALBYTEALLOC       (HAL_TEXBUFNEWBYTEALLOC         + 1)
+#define HAL_TEXBUFNEWOBJALLOC          (HAL_TEXBUFTOTALBYTEALLOC       + 1)
+#define HAL_TEXBUFTOTALOBJALLOC                (HAL_TEXBUFNEWOBJALLOC          + 1)
+
+#define GPU_CYCLES             1
+#define GPU_READ64BYTE (GPU_CYCLES             + 1)
+#define GPU_WRITE64BYTE        (GPU_READ64BYTE + 1)
+
+#define VS_INSTCOUNT                   1
+#define VS_BRANCHINSTCOUNT             (VS_INSTCOUNT           + 1)
+#define VS_TEXLDINSTCOUNT              (VS_BRANCHINSTCOUNT     + 1)
+#define VS_RENDEREDVERTCOUNT   (VS_TEXLDINSTCOUNT      + 1)
+
+#define PS_INSTCOUNT                   1
+#define PS_BRANCHINSTCOUNT             (PS_INSTCOUNT           + 1)
+#define PS_TEXLDINSTCOUNT              (PS_BRANCHINSTCOUNT     + 1)
+#define PS_RENDEREDPIXCOUNT            (PS_TEXLDINSTCOUNT      + 1)
+
+#define PA_INVERTCOUNT         1
+#define        PA_INPRIMCOUNT          (PA_INVERTCOUNT         + 1)
+#define PA_OUTPRIMCOUNT                (PA_INPRIMCOUNT         + 1)
+#define PA_DEPTHCLIPCOUNT      (PA_OUTPRIMCOUNT        + 1)
+#define PA_TRIVIALREJCOUNT     (PA_DEPTHCLIPCOUNT      + 1)
+#define PA_CULLCOUNT           (PA_TRIVIALREJCOUNT     + 1)
+
+#define SE_TRIANGLECOUNT       1
+#define SE_LINECOUNT           (SE_TRIANGLECOUNT       + 1)
+
+#define RA_VALIDPIXCOUNT               1
+#define RA_TOTALQUADCOUNT              (RA_VALIDPIXCOUNT               + 1)
+#define RA_VALIDQUADCOUNTEZ            (RA_TOTALQUADCOUNT              + 1)
+#define RA_TOTALPRIMCOUNT              (RA_VALIDQUADCOUNTEZ    + 1)
+#define RA_PIPECACHEMISSCOUNT  (RA_TOTALPRIMCOUNT              + 1)
+#define RA_PREFCACHEMISSCOUNT  (RA_PIPECACHEMISSCOUNT  + 1)
+#define RA_EEZCULLCOUNT                        (RA_PREFCACHEMISSCOUNT  + 1)
+
+#define TX_TOTBILINEARREQ              1
+#define TX_TOTTRILINEARREQ             (TX_TOTBILINEARREQ              + 1)
+#define TX_TOTDISCARDTEXREQ            (TX_TOTTRILINEARREQ             + 1)
+#define TX_TOTTEXREQ                   (TX_TOTDISCARDTEXREQ    + 1)
+#define TX_MEMREADCOUNT                        (TX_TOTTEXREQ                   + 1)
+#define TX_MEMREADIN8BCOUNT            (TX_MEMREADCOUNT                + 1)
+#define TX_CACHEMISSCOUNT              (TX_MEMREADIN8BCOUNT    + 1)
+#define TX_CACHEHITTEXELCOUNT  (TX_CACHEMISSCOUNT              + 1)
+#define TX_CACHEMISSTEXELCOUNT (TX_CACHEHITTEXELCOUNT  + 1)
+
+#define PE_KILLEDBYCOLOR       1
+#define PE_KILLEDBYDEPTH       (PE_KILLEDBYCOLOR       + 1)
+#define PE_DRAWNBYCOLOR                (PE_KILLEDBYDEPTH       + 1)
+#define PE_DRAWNBYDEPTH                (PE_DRAWNBYCOLOR        + 1)
+
+#define MC_READREQ8BPIPE       1
+#define MC_READREQ8BIP         (MC_READREQ8BPIPE       + 1)
+#define MC_WRITEREQ8BPIPE      (MC_READREQ8BIP         + 1)
+
+#define AXI_READREQSTALLED             1
+#define AXI_WRITEREQSTALLED            (AXI_READREQSTALLED             + 1)
+#define AXI_WRITEDATASTALLED   (AXI_WRITEREQSTALLED    + 1)
+
+#define PVS_INSTRCOUNT         1
+#define PVS_ALUINSTRCOUNT      (PVS_INSTRCOUNT         + 1)
+#define PVS_TEXINSTRCOUNT      (PVS_ALUINSTRCOUNT      + 1)
+#define PVS_ATTRIBCOUNT                (PVS_TEXINSTRCOUNT      + 1)
+#define PVS_UNIFORMCOUNT       (PVS_ATTRIBCOUNT        + 1)
+#define PVS_FUNCTIONCOUNT      (PVS_UNIFORMCOUNT       + 1)
+
+#define PPS_INSTRCOUNT         1
+#define PPS_ALUINSTRCOUNT      (PPS_INSTRCOUNT         + 1)
+#define PPS_TEXINSTRCOUNT      (PPS_ALUINSTRCOUNT      + 1)
+#define PPS_ATTRIBCOUNT                (PPS_TEXINSTRCOUNT      + 1)
+#define PPS_UNIFORMCOUNT       (PPS_ATTRIBCOUNT        + 1)
+#define PPS_FUNCTIONCOUNT      (PPS_UNIFORMCOUNT       + 1)
+/* End of MISC Counter IDs. */
+
+#ifdef gcdNEW_PROFILER_FILE
+
+/* Category Constants. */
+#define VPHEADER        0x010000
+#define VPG_INFO        0x020000
+#define VPG_TIME        0x030000
+#define VPG_MEM         0x040000
+#define VPG_ES11        0x050000
+#define VPG_ES20        0x060000
+#define VPG_VG11        0x070000
+#define VPG_HAL         0x080000
+#define VPG_HW          0x090000
+#define VPG_GPU         0x0a0000
+#define VPG_VS          0x0b0000
+#define VPG_PS          0x0c0000
+#define VPG_PA          0x0d0000
+#define VPG_SETUP       0x0e0000
+#define VPG_RA          0x0f0000
+#define VPG_TX          0x100000
+#define VPG_PE          0x110000
+#define VPG_MC          0x120000
+#define VPG_AXI         0x130000
+#define VPG_PROG        0x140000
+#define VPG_PVS         0x150000
+#define VPG_PPS         0x160000
+#define VPG_FRAME       0x170000
+#define VPG_END         0xff0000
+
+/* Info. */
+#define VPC_INFOCOMPANY         (VPG_INFO + 1)
+#define VPC_INFOVERSION         (VPC_INFOCOMPANY + 1)
+#define VPC_INFORENDERER        (VPC_INFOVERSION + 1)
+#define VPC_INFOREVISION        (VPC_INFORENDERER + 1)
+#define VPC_INFODRIVER          (VPC_INFOREVISION + 1)
+#define VPC_INFODRIVERMODE      (VPC_INFODRIVER + 1)
+#define VPC_INFOSCREENSIZE      (VPC_INFODRIVERMODE + 1)
+
+/* Counter Constants. */
+#define VPC_ELAPSETIME                 (VPG_TIME + 1)
+#define VPC_CPUTIME             (VPC_ELAPSETIME + 1)
+
+#define VPC_MEMMAXRES           (VPG_MEM + 1)
+#define VPC_MEMSHARED           (VPC_MEMMAXRES + 1)
+#define VPC_MEMUNSHAREDDATA     (VPC_MEMSHARED + 1)
+#define VPC_MEMUNSHAREDSTACK    (VPC_MEMUNSHAREDDATA + 1)
+
+/* OpenGL ES11 Counters. */
+#define        VPC_ES11ACTIVETEXTURE                   (VPG_ES11 +     ES11_ACTIVETEXTURE)
+#define        VPC_ES11ALPHAFUNC                               (VPG_ES11 +     ES11_ALPHAFUNC)
+#define        VPC_ES11ALPHAFUNCX                              (VPG_ES11 +     ES11_ALPHAFUNCX)
+#define        VPC_ES11BINDBUFFER                              (VPG_ES11 +     ES11_BINDBUFFER)
+#define        VPC_ES11BINDTEXTURE                             (VPG_ES11 +     ES11_BINDTEXTURE)
+#define        VPC_ES11BLENDFUNC                               (VPG_ES11 +     ES11_BLENDFUNC)
+#define        VPC_ES11BUFFERDATA                              (VPG_ES11 +     ES11_BUFFERDATA)
+#define        VPC_ES11BUFFERSUBDATA                   (VPG_ES11 +     ES11_BUFFERSUBDATA)
+#define        VPC_ES11CLEAR                                   (VPG_ES11 +     ES11_CLEAR)
+#define        VPC_ES11CLEARCOLOR                              (VPG_ES11 +     ES11_CLEARCOLOR)
+#define        VPC_ES11CLEARCOLORX                             (VPG_ES11 +     ES11_CLEARCOLORX)
+#define        VPC_ES11CLEARDEPTHF                             (VPG_ES11 +     ES11_CLEARDEPTHF)
+#define        VPC_ES11CLEARDEPTHX                             (VPG_ES11 +     ES11_CLEARDEPTHX)
+#define        VPC_ES11CLEARSTENCIL                    (VPG_ES11 +     ES11_CLEARSTENCIL)
+#define        VPC_ES11CLIENTACTIVETEXTURE             (VPG_ES11 +     ES11_CLIENTACTIVETEXTURE)
+#define        VPC_ES11CLIPPLANEF                              (VPG_ES11 +     ES11_CLIPPLANEF)
+#define        VPC_ES11CLIPPLANEX                              (VPG_ES11 +     ES11_CLIPPLANEX)
+#define        VPC_ES11COLOR4F                                 (VPG_ES11 +     ES11_COLOR4F)
+#define        VPC_ES11COLOR4UB                                (VPG_ES11 +     ES11_COLOR4UB)
+#define        VPC_ES11COLOR4X                                 (VPG_ES11 +     ES11_COLOR4X)
+#define        VPC_ES11COLORMASK                               (VPG_ES11 +     ES11_COLORMASK)
+#define        VPC_ES11COLORPOINTER                    (VPG_ES11 +     ES11_COLORPOINTER)
+#define        VPC_ES11COMPRESSEDTEXIMAGE2D    (VPG_ES11 +     ES11_COMPRESSEDTEXIMAGE2D)
+#define        VPC_ES11COMPRESSEDTEXSUBIMAGE2D (VPG_ES11 +     ES11_COMPRESSEDTEXSUBIMAGE2D)
+#define        VPC_ES11COPYTEXIMAGE2D                  (VPG_ES11 +     ES11_COPYTEXIMAGE2D)
+#define        VPC_ES11COPYTEXSUBIMAGE2D               (VPG_ES11 +     ES11_COPYTEXSUBIMAGE2D)
+#define        VPC_ES11CULLFACE                                (VPG_ES11 +     ES11_CULLFACE)
+#define        VPC_ES11DELETEBUFFERS                   (VPG_ES11 +     ES11_DELETEBUFFERS)
+#define        VPC_ES11DELETETEXTURES                  (VPG_ES11 +     ES11_DELETETEXTURES)
+#define        VPC_ES11DEPTHFUNC                               (VPG_ES11 +     ES11_DEPTHFUNC)
+#define        VPC_ES11DEPTHMASK                               (VPG_ES11 +     ES11_DEPTHMASK)
+#define        VPC_ES11DEPTHRANGEF                             (VPG_ES11 +     ES11_DEPTHRANGEF)
+#define        VPC_ES11DEPTHRANGEX                             (VPG_ES11 +     ES11_DEPTHRANGEX)
+#define        VPC_ES11DISABLE                                 (VPG_ES11 +     ES11_DISABLE)
+#define        VPC_ES11DISABLECLIENTSTATE              (VPG_ES11 +     ES11_DISABLECLIENTSTATE)
+#define        VPC_ES11DRAWARRAYS                              (VPG_ES11 +     ES11_DRAWARRAYS)
+#define        VPC_ES11DRAWELEMENTS                    (VPG_ES11 +     ES11_DRAWELEMENTS)
+#define        VPC_ES11ENABLE                                  (VPG_ES11 +     ES11_ENABLE)
+#define        VPC_ES11ENABLECLIENTSTATE               (VPG_ES11 +     ES11_ENABLECLIENTSTATE)
+#define        VPC_ES11FINISH                                  (VPG_ES11 +     ES11_FINISH)
+#define        VPC_ES11FLUSH                                   (VPG_ES11 +     ES11_FLUSH)
+#define        VPC_ES11FOGF                                    (VPG_ES11 +     ES11_FOGF)
+#define        VPC_ES11FOGFV                                   (VPG_ES11 +     ES11_FOGFV)
+#define        VPC_ES11FOGX                                    (VPG_ES11 +     ES11_FOGX)
+#define        VPC_ES11FOGXV                                   (VPG_ES11 +     ES11_FOGXV)
+#define        VPC_ES11FRONTFACE                               (VPG_ES11 +     ES11_FRONTFACE)
+#define        VPC_ES11FRUSTUMF                                (VPG_ES11 +     ES11_FRUSTUMF)
+#define        VPC_ES11FRUSTUMX                                (VPG_ES11 +     ES11_FRUSTUMX)
+#define        VPC_ES11GENBUFFERS                              (VPG_ES11 +     ES11_GENBUFFERS)
+#define        VPC_ES11GENTEXTURES                             (VPG_ES11 +     ES11_GENTEXTURES)
+#define        VPC_ES11GETBOOLEANV                             (VPG_ES11 +     ES11_GETBOOLEANV)
+#define        VPC_ES11GETBUFFERPARAMETERIV    (VPG_ES11 +     ES11_GETBUFFERPARAMETERIV)
+#define        VPC_ES11GETCLIPPLANEF                   (VPG_ES11 +     ES11_GETCLIPPLANEF)
+#define        VPC_ES11GETCLIPPLANEX                   (VPG_ES11 +     ES11_GETCLIPPLANEX)
+#define        VPC_ES11GETERROR                                (VPG_ES11 +     ES11_GETERROR)
+#define        VPC_ES11GETFIXEDV                               (VPG_ES11 +     ES11_GETFIXEDV)
+#define        VPC_ES11GETFLOATV                               (VPG_ES11 +     ES11_GETFLOATV)
+#define        VPC_ES11GETINTEGERV                             (VPG_ES11 +     ES11_GETINTEGERV)
+#define        VPC_ES11GETLIGHTFV                              (VPG_ES11 +     ES11_GETLIGHTFV)
+#define        VPC_ES11GETLIGHTXV                              (VPG_ES11 +     ES11_GETLIGHTXV)
+#define        VPC_ES11GETMATERIALFV                   (VPG_ES11 +     ES11_GETMATERIALFV)
+#define        VPC_ES11GETMATERIALXV                   (VPG_ES11 +     ES11_GETMATERIALXV)
+#define        VPC_ES11GETPOINTERV                             (VPG_ES11 +     ES11_GETPOINTERV)
+#define        VPC_ES11GETSTRING                               (VPG_ES11 +     ES11_GETSTRING)
+#define        VPC_ES11GETTEXENVFV                             (VPG_ES11 +     ES11_GETTEXENVFV)
+#define        VPC_ES11GETTEXENVIV                             (VPG_ES11 +     ES11_GETTEXENVIV)
+#define        VPC_ES11GETTEXENVXV                             (VPG_ES11 +     ES11_GETTEXENVXV)
+#define        VPC_ES11GETTEXPARAMETERFV               (VPG_ES11 +     ES11_GETTEXPARAMETERFV)
+#define        VPC_ES11GETTEXPARAMETERIV               (VPG_ES11 +     ES11_GETTEXPARAMETERIV)
+#define        VPC_ES11GETTEXPARAMETERXV               (VPG_ES11 +     ES11_GETTEXPARAMETERXV)
+#define        VPC_ES11HINT                                    (VPG_ES11 +     ES11_HINT)
+#define        VPC_ES11ISBUFFER                                (VPG_ES11 +     ES11_ISBUFFER)
+#define        VPC_ES11ISENABLED                               (VPG_ES11 +     ES11_ISENABLED)
+#define        VPC_ES11ISTEXTURE                               (VPG_ES11 +     ES11_ISTEXTURE)
+#define        VPC_ES11LIGHTF                                  (VPG_ES11 +     ES11_LIGHTF)
+#define        VPC_ES11LIGHTFV                                 (VPG_ES11 +     ES11_LIGHTFV)
+#define        VPC_ES11LIGHTMODELF                             (VPG_ES11 +     ES11_LIGHTMODELF)
+#define        VPC_ES11LIGHTMODELFV                    (VPG_ES11 +     ES11_LIGHTMODELFV)
+#define        VPC_ES11LIGHTMODELX                             (VPG_ES11 +     ES11_LIGHTMODELX)
+#define        VPC_ES11LIGHTMODELXV                    (VPG_ES11 +     ES11_LIGHTMODELXV)
+#define        VPC_ES11LIGHTX                                  (VPG_ES11 +     ES11_LIGHTX)
+#define        VPC_ES11LIGHTXV                                 (VPG_ES11 +     ES11_LIGHTXV)
+#define        VPC_ES11LINEWIDTH                               (VPG_ES11 +     ES11_LINEWIDTH)
+#define        VPC_ES11LINEWIDTHX                              (VPG_ES11 +     ES11_LINEWIDTHX)
+#define        VPC_ES11LOADIDENTITY                    (VPG_ES11 +     ES11_LOADIDENTITY)
+#define        VPC_ES11LOADMATRIXF                             (VPG_ES11 +     ES11_LOADMATRIXF)
+#define        VPC_ES11LOADMATRIXX                             (VPG_ES11 +     ES11_LOADMATRIXX)
+#define        VPC_ES11LOGICOP                                 (VPG_ES11 +     ES11_LOGICOP)
+#define        VPC_ES11MATERIALF                               (VPG_ES11 +     ES11_MATERIALF)
+#define        VPC_ES11MATERIALFV                              (VPG_ES11 +     ES11_MATERIALFV)
+#define        VPC_ES11MATERIALX                               (VPG_ES11 +     ES11_MATERIALX)
+#define        VPC_ES11MATERIALXV                              (VPG_ES11 +     ES11_MATERIALXV)
+#define        VPC_ES11MATRIXMODE                              (VPG_ES11 +     ES11_MATRIXMODE)
+#define        VPC_ES11MULTITEXCOORD4F                 (VPG_ES11 +     ES11_MULTITEXCOORD4F)
+#define        VPC_ES11MULTITEXCOORD4X                 (VPG_ES11 +     ES11_MULTITEXCOORD4X)
+#define        VPC_ES11MULTMATRIXF                             (VPG_ES11 +     ES11_MULTMATRIXF)
+#define        VPC_ES11MULTMATRIXX                             (VPG_ES11 +     ES11_MULTMATRIXX)
+#define        VPC_ES11NORMAL3F                                (VPG_ES11 +     ES11_NORMAL3F)
+#define        VPC_ES11NORMAL3X                                (VPG_ES11 +     ES11_NORMAL3X)
+#define        VPC_ES11NORMALPOINTER                   (VPG_ES11 +     ES11_NORMALPOINTER)
+#define        VPC_ES11ORTHOF                                  (VPG_ES11 +     ES11_ORTHOF)
+#define        VPC_ES11ORTHOX                                  (VPG_ES11 +     ES11_ORTHOX)
+#define        VPC_ES11PIXELSTOREI                             (VPG_ES11 +     ES11_PIXELSTOREI)
+#define        VPC_ES11POINTPARAMETERF                 (VPG_ES11 +     ES11_POINTPARAMETERF)
+#define        VPC_ES11POINTPARAMETERFV                (VPG_ES11 +     ES11_POINTPARAMETERFV)
+#define        VPC_ES11POINTPARAMETERX                 (VPG_ES11 +     ES11_POINTPARAMETERX)
+#define        VPC_ES11POINTPARAMETERXV                (VPG_ES11 +     ES11_POINTPARAMETERXV)
+#define        VPC_ES11POINTSIZE                               (VPG_ES11 +     ES11_POINTSIZE)
+#define        VPC_ES11POINTSIZEX                              (VPG_ES11 +     ES11_POINTSIZEX)
+#define        VPC_ES11POLYGONOFFSET                   (VPG_ES11 +     ES11_POLYGONOFFSET)
+#define        VPC_ES11POLYGONOFFSETX                  (VPG_ES11 +     ES11_POLYGONOFFSETX)
+#define        VPC_ES11POPMATRIX                               (VPG_ES11 +     ES11_POPMATRIX)
+#define        VPC_ES11PUSHMATRIX                              (VPG_ES11 +     ES11_PUSHMATRIX)
+#define        VPC_ES11READPIXELS                              (VPG_ES11 +     ES11_READPIXELS)
+#define        VPC_ES11ROTATEF                                 (VPG_ES11 +     ES11_ROTATEF)
+#define        VPC_ES11ROTATEX                                 (VPG_ES11 +     ES11_ROTATEX)
+#define        VPC_ES11SAMPLECOVERAGE                  (VPG_ES11 +     ES11_SAMPLECOVERAGE)
+#define        VPC_ES11SAMPLECOVERAGEX                 (VPG_ES11 +     ES11_SAMPLECOVERAGEX)
+#define        VPC_ES11SCALEF                                  (VPG_ES11 +     ES11_SCALEF)
+#define        VPC_ES11SCALEX                                  (VPG_ES11 +     ES11_SCALEX)
+#define        VPC_ES11SCISSOR                                 (VPG_ES11 +     ES11_SCISSOR)
+#define        VPC_ES11SHADEMODEL                              (VPG_ES11 +     ES11_SHADEMODEL)
+#define        VPC_ES11STENCILFUNC                             (VPG_ES11 +     ES11_STENCILFUNC)
+#define        VPC_ES11STENCILMASK                             (VPG_ES11 +     ES11_STENCILMASK)
+#define        VPC_ES11STENCILOP                               (VPG_ES11 +     ES11_STENCILOP)
+#define        VPC_ES11TEXCOORDPOINTER                 (VPG_ES11 +     ES11_TEXCOORDPOINTER)
+#define        VPC_ES11TEXENVF                                 (VPG_ES11 +     ES11_TEXENVF)
+#define        VPC_ES11TEXENVFV                                (VPG_ES11 +     ES11_TEXENVFV)
+#define        VPC_ES11TEXENVI                                 (VPG_ES11 +     ES11_TEXENVI)
+#define        VPC_ES11TEXENVIV                                (VPG_ES11 +     ES11_TEXENVIV)
+#define        VPC_ES11TEXENVX                                 (VPG_ES11 +     ES11_TEXENVX)
+#define        VPC_ES11TEXENVXV                                (VPG_ES11 +     ES11_TEXENVXV)
+#define        VPC_ES11TEXIMAGE2D                              (VPG_ES11 +     ES11_TEXIMAGE2D)
+#define        VPC_ES11TEXPARAMETERF                   (VPG_ES11 +     ES11_TEXPARAMETERF)
+#define        VPC_ES11TEXPARAMETERFV                  (VPG_ES11 +     ES11_TEXPARAMETERFV)
+#define        VPC_ES11TEXPARAMETERI                   (VPG_ES11 +     ES11_TEXPARAMETERI)
+#define        VPC_ES11TEXPARAMETERIV                  (VPG_ES11 +     ES11_TEXPARAMETERIV)
+#define        VPC_ES11TEXPARAMETERX                   (VPG_ES11 +     ES11_TEXPARAMETERX)
+#define        VPC_ES11TEXPARAMETERXV                  (VPG_ES11 +     ES11_TEXPARAMETERXV)
+#define        VPC_ES11TEXSUBIMAGE2D                   (VPG_ES11 +     ES11_TEXSUBIMAGE2D)
+#define        VPC_ES11TRANSLATEF                              (VPG_ES11 +     ES11_TRANSLATEF)
+#define        VPC_ES11TRANSLATEX                              (VPG_ES11 +     ES11_TRANSLATEX)
+#define        VPC_ES11VERTEXPOINTER                   (VPG_ES11 +     ES11_VERTEXPOINTER)
+#define        VPC_ES11VIEWPORT                                (VPG_ES11 +     ES11_VIEWPORT)
+/* OpenGL ES11 Statics Counter IDs. */
+#define        VPC_ES11CALLS                                   (VPG_ES11 +     ES11_CALLS)
+#define        VPC_ES11DRAWCALLS                               (VPG_ES11 +     ES11_DRAWCALLS)
+#define        VPC_ES11STATECHANGECALLS                (VPG_ES11 +     ES11_STATECHANGECALLS)
+#define        VPC_ES11POINTCOUNT                              (VPG_ES11 +     ES11_POINTCOUNT)
+#define        VPC_ES11LINECOUNT                               (VPG_ES11 +     ES11_LINECOUNT)
+#define        VPC_ES11TRIANGLECOUNT                   (VPG_ES11 +     ES11_TRIANGLECOUNT)
+
+/* OpenGLES 2.x */
+#define        VPC_ES20ACTIVETEXTURE                                           (VPG_ES20 +     ES20_ACTIVETEXTURE)
+#define        VPC_ES20ATTACHSHADER                                            (VPG_ES20 +     ES20_ATTACHSHADER)
+#define        VPC_ES20BINDATTRIBLOCATION                                      (VPG_ES20 +     ES20_BINDATTRIBLOCATION)
+#define        VPC_ES20BINDBUFFER                                                      (VPG_ES20 +     ES20_BINDBUFFER)
+#define        VPC_ES20BINDFRAMEBUFFER                                         (VPG_ES20 +     ES20_BINDFRAMEBUFFER)
+#define        VPC_ES20BINDRENDERBUFFER                                        (VPG_ES20 +     ES20_BINDRENDERBUFFER)
+#define        VPC_ES20BINDTEXTURE                                                     (VPG_ES20 +     ES20_BINDTEXTURE)
+#define        VPC_ES20BLENDCOLOR                                                      (VPG_ES20 +     ES20_BLENDCOLOR)
+#define        VPC_ES20BLENDEQUATION                                           (VPG_ES20 +     ES20_BLENDEQUATION)
+#define        VPC_ES20BLENDEQUATIONSEPARATE                           (VPG_ES20 +     ES20_BLENDEQUATIONSEPARATE)
+#define        VPC_ES20BLENDFUNC                                                       (VPG_ES20 +     ES20_BLENDFUNC)
+#define        VPC_ES20BLENDFUNCSEPARATE                                       (VPG_ES20 +     ES20_BLENDFUNCSEPARATE)
+#define        VPC_ES20BUFFERDATA                                                      (VPG_ES20 +     ES20_BUFFERDATA)
+#define        VPC_ES20BUFFERSUBDATA                                           (VPG_ES20 +     ES20_BUFFERSUBDATA)
+#define        VPC_ES20CHECKFRAMEBUFFERSTATUS                          (VPG_ES20 +     ES20_CHECKFRAMEBUFFERSTATUS)
+#define        VPC_ES20CLEAR                                                           (VPG_ES20 +     ES20_CLEAR)
+#define        VPC_ES20CLEARCOLOR                                                      (VPG_ES20 +     ES20_CLEARCOLOR)
+#define        VPC_ES20CLEARDEPTHF                                                     (VPG_ES20 +     ES20_CLEARDEPTHF)
+#define        VPC_ES20CLEARSTENCIL                                            (VPG_ES20 +     ES20_CLEARSTENCIL)
+#define        VPC_ES20COLORMASK                                                       (VPG_ES20 +     ES20_COLORMASK)
+#define        VPC_ES20COMPILESHADER                                           (VPG_ES20 +     ES20_COMPILESHADER)
+#define        VPC_ES20COMPRESSEDTEXIMAGE2D                            (VPG_ES20 +     ES20_COMPRESSEDTEXIMAGE2D)
+#define        VPC_ES20COMPRESSEDTEXSUBIMAGE2D                         (VPG_ES20 +     ES20_COMPRESSEDTEXSUBIMAGE2D)
+#define        VPC_ES20COPYTEXIMAGE2D                                          (VPG_ES20 +     ES20_COPYTEXIMAGE2D)
+#define        VPC_ES20COPYTEXSUBIMAGE2D                                       (VPG_ES20 +     ES20_COPYTEXSUBIMAGE2D)
+#define        VPC_ES20CREATEPROGRAM                                           (VPG_ES20 +     ES20_CREATEPROGRAM)
+#define        VPC_ES20CREATESHADER                                            (VPG_ES20 +     ES20_CREATESHADER)
+#define        VPC_ES20CULLFACE                                                        (VPG_ES20 +     ES20_CULLFACE)
+#define        VPC_ES20DELETEBUFFERS                                           (VPG_ES20 +     ES20_DELETEBUFFERS)
+#define        VPC_ES20DELETEFRAMEBUFFERS                                      (VPG_ES20 +     ES20_DELETEFRAMEBUFFERS)
+#define        VPC_ES20DELETEPROGRAM                                           (VPG_ES20 +     ES20_DELETEPROGRAM)
+#define        VPC_ES20DELETERENDERBUFFERS                                     (VPG_ES20 +     ES20_DELETERENDERBUFFERS)
+#define        VPC_ES20DELETESHADER                                            (VPG_ES20 +     ES20_DELETESHADER)
+#define        VPC_ES20DELETETEXTURES                                          (VPG_ES20 +     ES20_DELETETEXTURES)
+#define        VPC_ES20DEPTHFUNC                                                       (VPG_ES20 +     ES20_DEPTHFUNC)
+#define        VPC_ES20DEPTHMASK                                                       (VPG_ES20 +     ES20_DEPTHMASK)
+#define        VPC_ES20DEPTHRANGEF                                                     (VPG_ES20 +     ES20_DEPTHRANGEF)
+#define        VPC_ES20DETACHSHADER                                            (VPG_ES20 +     ES20_DETACHSHADER)
+#define        VPC_ES20DISABLE                                                         (VPG_ES20 +     ES20_DISABLE)
+#define        VPC_ES20DISABLEVERTEXATTRIBARRAY                        (VPG_ES20 +     ES20_DISABLEVERTEXATTRIBARRAY)
+#define        VPC_ES20DRAWARRAYS                                                      (VPG_ES20 +     ES20_DRAWARRAYS)
+#define        VPC_ES20DRAWELEMENTS                                            (VPG_ES20 +     ES20_DRAWELEMENTS)
+#define        VPC_ES20ENABLE                                                          (VPG_ES20 +     ES20_ENABLE)
+#define        VPC_ES20ENABLEVERTEXATTRIBARRAY                         (VPG_ES20 +     ES20_ENABLEVERTEXATTRIBARRAY)
+#define        VPC_ES20FINISH                                                          (VPG_ES20 +     ES20_FINISH)
+#define        VPC_ES20FLUSH                                                           (VPG_ES20 +     ES20_FLUSH)
+#define        VPC_ES20FRAMEBUFFERRENDERBUFFER                         (VPG_ES20 +     ES20_FRAMEBUFFERRENDERBUFFER)
+#define        VPC_ES20FRAMEBUFFERTEXTURE2D                            (VPG_ES20 +     ES20_FRAMEBUFFERTEXTURE2D)
+#define        VPC_ES20FRONTFACE                                                       (VPG_ES20 +     ES20_FRONTFACE)
+#define        VPC_ES20GENBUFFERS                                                      (VPG_ES20 +     ES20_GENBUFFERS)
+#define        VPC_ES20GENERATEMIPMAP                                          (VPG_ES20 +     ES20_GENERATEMIPMAP)
+#define        VPC_ES20GENFRAMEBUFFERS                                         (VPG_ES20 +     ES20_GENFRAMEBUFFERS)
+#define        VPC_ES20GENRENDERBUFFERS                                        (VPG_ES20 +     ES20_GENRENDERBUFFERS)
+#define        VPC_ES20GENTEXTURES                                                     (VPG_ES20 +     ES20_GENTEXTURES)
+#define        VPC_ES20GETACTIVEATTRIB                                         (VPG_ES20 +     ES20_GETACTIVEATTRIB)
+#define        VPC_ES20GETACTIVEUNIFORM                                        (VPG_ES20 +     ES20_GETACTIVEUNIFORM)
+#define        VPC_ES20GETATTACHEDSHADERS                                      (VPG_ES20 +     ES20_GETATTACHEDSHADERS)
+#define        VPC_ES20GETATTRIBLOCATION                                       (VPG_ES20 +     ES20_GETATTRIBLOCATION)
+#define        VPC_ES20GETBOOLEANV                                                     (VPG_ES20 +     ES20_GETBOOLEANV)
+#define        VPC_ES20GETBUFFERPARAMETERIV                            (VPG_ES20 +     ES20_GETBUFFERPARAMETERIV)
+#define        VPC_ES20GETERROR                                                        (VPG_ES20 +     ES20_GETERROR)
+#define        VPC_ES20GETFLOATV                                                       (VPG_ES20 +     ES20_GETFLOATV)
+#define        VPC_ES20GETFRAMEBUFFERATTACHMENTPARAMETERIV     (VPG_ES20 +     ES20_GETFRAMEBUFFERATTACHMENTPARAMETERIV)
+#define        VPC_ES20GETINTEGERV                                                     (VPG_ES20 +     ES20_GETINTEGERV)
+#define        VPC_ES20GETPROGRAMIV                                            (VPG_ES20 +     ES20_GETPROGRAMIV)
+#define        VPC_ES20GETPROGRAMINFOLOG                                       (VPG_ES20 +     ES20_GETPROGRAMINFOLOG)
+#define        VPC_ES20GETRENDERBUFFERPARAMETERIV                      (VPG_ES20 +     ES20_GETRENDERBUFFERPARAMETERIV)
+#define        VPC_ES20GETSHADERIV                                                     (VPG_ES20 +     ES20_GETSHADERIV)
+#define        VPC_ES20GETSHADERINFOLOG                                        (VPG_ES20 +     ES20_GETSHADERINFOLOG)
+#define        VPC_ES20GETSHADERPRECISIONFORMAT                        (VPG_ES20 +     ES20_GETSHADERPRECISIONFORMAT)
+#define        VPC_ES20GETSHADERSOURCE                                         (VPG_ES20 +     ES20_GETSHADERSOURCE)
+#define        VPC_ES20GETSTRING                                                       (VPG_ES20 +     ES20_GETSTRING)
+#define        VPC_ES20GETTEXPARAMETERFV                                       (VPG_ES20 +     ES20_GETTEXPARAMETERFV)
+#define        VPC_ES20GETTEXPARAMETERIV                                       (VPG_ES20 +     ES20_GETTEXPARAMETERIV)
+#define        VPC_ES20GETUNIFORMFV                                            (VPG_ES20 +     ES20_GETUNIFORMFV)
+#define        VPC_ES20GETUNIFORMIV                                            (VPG_ES20 +     ES20_GETUNIFORMIV)
+#define        VPC_ES20GETUNIFORMLOCATION                                      (VPG_ES20 +     ES20_GETUNIFORMLOCATION)
+#define        VPC_ES20GETVERTEXATTRIBFV                                       (VPG_ES20 +     ES20_GETVERTEXATTRIBFV)
+#define        VPC_ES20GETVERTEXATTRIBIV                                       (VPG_ES20 +     ES20_GETVERTEXATTRIBIV)
+#define        VPC_ES20GETVERTEXATTRIBPOINTERV                         (VPG_ES20 +     ES20_GETVERTEXATTRIBPOINTERV)
+#define        VPC_ES20HINT                                                            (VPG_ES20 +     ES20_HINT)
+#define        VPC_ES20ISBUFFER                                                        (VPG_ES20 +     ES20_ISBUFFER)
+#define        VPC_ES20ISENABLED                                                       (VPG_ES20 +     ES20_ISENABLED)
+#define        VPC_ES20ISFRAMEBUFFER                                           (VPG_ES20 +     ES20_ISFRAMEBUFFER)
+#define        VPC_ES20ISPROGRAM                                                       (VPG_ES20 +     ES20_ISPROGRAM)
+#define        VPC_ES20ISRENDERBUFFER                                          (VPG_ES20 +     ES20_ISRENDERBUFFER)
+#define        VPC_ES20ISSHADER                                                        (VPG_ES20 +     ES20_ISSHADER)
+#define        VPC_ES20ISTEXTURE                                                       (VPG_ES20 +     ES20_ISTEXTURE)
+#define        VPC_ES20LINEWIDTH                                                       (VPG_ES20 +     ES20_LINEWIDTH)
+#define        VPC_ES20LINKPROGRAM                                                     (VPG_ES20 +     ES20_LINKPROGRAM)
+#define        VPC_ES20PIXELSTOREI                                                     (VPG_ES20 +     ES20_PIXELSTOREI)
+#define        VPC_ES20POLYGONOFFSET                                           (VPG_ES20 +     ES20_POLYGONOFFSET)
+#define        VPC_ES20READPIXELS                                                      (VPG_ES20 +     ES20_READPIXELS)
+#define        VPC_ES20RELEASESHADERCOMPILER                           (VPG_ES20 +     ES20_RELEASESHADERCOMPILER)
+#define        VPC_ES20RENDERBUFFERSTORAGE                                     (VPG_ES20 +     ES20_RENDERBUFFERSTORAGE)
+#define        VPC_ES20SAMPLECOVERAGE                                          (VPG_ES20 +     ES20_SAMPLECOVERAGE)
+#define        VPC_ES20SCISSOR                                                         (VPG_ES20 +     ES20_SCISSOR)
+#define        VPC_ES20SHADERBINARY                                            (VPG_ES20 +     ES20_SHADERBINARY)
+#define        VPC_ES20SHADERSOURCE                                            (VPG_ES20 +     ES20_SHADERSOURCE)
+#define        VPC_ES20STENCILFUNC                                                     (VPG_ES20 +     ES20_STENCILFUNC)
+#define        VPC_ES20STENCILFUNCSEPARATE                                     (VPG_ES20 +     ES20_STENCILFUNCSEPARATE)
+#define        VPC_ES20STENCILMASK                                                     (VPG_ES20 +     ES20_STENCILMASK)
+#define        VPC_ES20STENCILMASKSEPARATE                                     (VPG_ES20 +     ES20_STENCILMASKSEPARATE)
+#define        VPC_ES20STENCILOP                                                       (VPG_ES20 +     ES20_STENCILOP)
+#define        VPC_ES20STENCILOPSEPARATE                                       (VPG_ES20 +     ES20_STENCILOPSEPARATE)
+#define        VPC_ES20TEXIMAGE2D                                                      (VPG_ES20 +     ES20_TEXIMAGE2D)
+#define        VPC_ES20TEXPARAMETERF                                           (VPG_ES20 +     ES20_TEXPARAMETERF)
+#define        VPC_ES20TEXPARAMETERFV                                          (VPG_ES20 +     ES20_TEXPARAMETERFV)
+#define        VPC_ES20TEXPARAMETERI                                           (VPG_ES20 +     ES20_TEXPARAMETERI)
+#define        VPC_ES20TEXPARAMETERIV                                          (VPG_ES20 +     ES20_TEXPARAMETERIV)
+#define        VPC_ES20TEXSUBIMAGE2D                                           (VPG_ES20 +     ES20_TEXSUBIMAGE2D)
+#define        VPC_ES20UNIFORM1F                                                       (VPG_ES20 +     ES20_UNIFORM1F)
+#define        VPC_ES20UNIFORM1FV                                                      (VPG_ES20 +     ES20_UNIFORM1FV)
+#define        VPC_ES20UNIFORM1I                                                       (VPG_ES20 +     ES20_UNIFORM1I)
+#define        VPC_ES20UNIFORM1IV                                                      (VPG_ES20 +     ES20_UNIFORM1IV)
+#define        VPC_ES20UNIFORM2F                                                       (VPG_ES20 +     ES20_UNIFORM2F)
+#define        VPC_ES20UNIFORM2FV                                                      (VPG_ES20 +     ES20_UNIFORM2FV)
+#define        VPC_ES20UNIFORM2I                                                       (VPG_ES20 +     ES20_UNIFORM2I)
+#define        VPC_ES20UNIFORM2IV                                                      (VPG_ES20 +     ES20_UNIFORM2IV)
+#define        VPC_ES20UNIFORM3F                                                       (VPG_ES20 +     ES20_UNIFORM3F)
+#define        VPC_ES20UNIFORM3FV                                                      (VPG_ES20 +     ES20_UNIFORM3FV)
+#define        VPC_ES20UNIFORM3I                                                       (VPG_ES20 +     ES20_UNIFORM3I)
+#define        VPC_ES20UNIFORM3IV                                                      (VPG_ES20 +     ES20_UNIFORM3IV)
+#define        VPC_ES20UNIFORM4F                                                       (VPG_ES20 +     ES20_UNIFORM4F)
+#define        VPC_ES20UNIFORM4FV                                                      (VPG_ES20 +     ES20_UNIFORM4FV)
+#define        VPC_ES20UNIFORM4I                                                       (VPG_ES20 +     ES20_UNIFORM4I)
+#define        VPC_ES20UNIFORM4IV                                                      (VPG_ES20 +     ES20_UNIFORM4IV)
+#define        VPC_ES20UNIFORMMATRIX2FV                                        (VPG_ES20 +     ES20_UNIFORMMATRIX2FV)
+#define        VPC_ES20UNIFORMMATRIX3FV                                        (VPG_ES20 +     ES20_UNIFORMMATRIX3FV)
+#define        VPC_ES20UNIFORMMATRIX4FV                                        (VPG_ES20 +     ES20_UNIFORMMATRIX4FV)
+#define        VPC_ES20USEPROGRAM                                                      (VPG_ES20 +     ES20_USEPROGRAM)
+#define        VPC_ES20VALIDATEPROGRAM                                         (VPG_ES20 +     ES20_VALIDATEPROGRAM)
+#define        VPC_ES20VERTEXATTRIB1F                                          (VPG_ES20 +     ES20_VERTEXATTRIB1F)
+#define        VPC_ES20VERTEXATTRIB1FV                                         (VPG_ES20 +     ES20_VERTEXATTRIB1FV)
+#define        VPC_ES20VERTEXATTRIB2F                                          (VPG_ES20 +     ES20_VERTEXATTRIB2F)
+#define        VPC_ES20VERTEXATTRIB2FV                                         (VPG_ES20 +     ES20_VERTEXATTRIB2FV)
+#define        VPC_ES20VERTEXATTRIB3F                                          (VPG_ES20 +     ES20_VERTEXATTRIB3F)
+#define        VPC_ES20VERTEXATTRIB3FV                                         (VPG_ES20 +     ES20_VERTEXATTRIB3FV)
+#define        VPC_ES20VERTEXATTRIB4F                                          (VPG_ES20 +     ES20_VERTEXATTRIB4F)
+#define        VPC_ES20VERTEXATTRIB4FV                                         (VPG_ES20 +     ES20_VERTEXATTRIB4FV)
+#define        VPC_ES20VERTEXATTRIBPOINTER                                     (VPG_ES20 +     ES20_VERTEXATTRIBPOINTER)
+#define        VPC_ES20VIEWPORT                                                        (VPG_ES20 +     ES20_VIEWPORT)
+/* OpenGL ES20 Statistics Counter IDs. */
+#define        VPC_ES20CALLS                                                           (VPG_ES20 +     ES20_CALLS)
+#define        VPC_ES20DRAWCALLS                                                       (VPG_ES20 +     ES20_DRAWCALLS)
+#define        VPC_ES20STATECHANGECALLS                                        (VPG_ES20 +     ES20_STATECHANGECALLS)
+#define        VPC_ES20POINTCOUNT                                                      (VPG_ES20 +     ES20_POINTCOUNT)
+#define        VPC_ES20LINECOUNT                                                       (VPG_ES20 +     ES20_LINECOUNT)
+#define        VPC_ES20TRIANGLECOUNT                                           (VPG_ES20 +     ES20_TRIANGLECOUNT)
+
+/* VG11 Counters. */
+#define        VPC_VG11APPENDPATH                              (VPG_VG11 +     VG11_APPENDPATH)
+#define        VPC_VG11APPENDPATHDATA                  (VPG_VG11 +     VG11_APPENDPATHDATA)
+#define        VPC_VG11CHILDIMAGE                              (VPG_VG11 +     VG11_CHILDIMAGE)
+#define        VPC_VG11CLEAR                                   (VPG_VG11 +     VG11_CLEAR)
+#define        VPC_VG11CLEARGLYPH                              (VPG_VG11 +     VG11_CLEARGLYPH)
+#define        VPC_VG11CLEARIMAGE                              (VPG_VG11 +     VG11_CLEARIMAGE)
+#define        VPC_VG11CLEARPATH                               (VPG_VG11 +     VG11_CLEARPATH)
+#define        VPC_VG11COLORMATRIX                             (VPG_VG11 +     VG11_COLORMATRIX)
+#define        VPC_VG11CONVOLVE                                (VPG_VG11 +     VG11_CONVOLVE)
+#define        VPC_VG11COPYIMAGE                               (VPG_VG11 +     VG11_COPYIMAGE)
+#define        VPC_VG11COPYMASK                                (VPG_VG11 +     VG11_COPYMASK)
+#define        VPC_VG11COPYPIXELS                              (VPG_VG11 +     VG11_COPYPIXELS)
+#define        VPC_VG11CREATEFONT                              (VPG_VG11 +     VG11_CREATEFONT)
+#define        VPC_VG11CREATEIMAGE                             (VPG_VG11 +     VG11_CREATEIMAGE)
+#define        VPC_VG11CREATEMASKLAYER                 (VPG_VG11 +     VG11_CREATEMASKLAYER)
+#define        VPC_VG11CREATEPAINT                             (VPG_VG11 +     VG11_CREATEPAINT)
+#define        VPC_VG11CREATEPATH                              (VPG_VG11 +     VG11_CREATEPATH)
+#define        VPC_VG11DESTROYFONT                             (VPG_VG11 +     VG11_DESTROYFONT)
+#define        VPC_VG11DESTROYIMAGE                    (VPG_VG11 +     VG11_DESTROYIMAGE)
+#define        VPC_VG11DESTROYMASKLAYER                (VPG_VG11 +     VG11_DESTROYMASKLAYER)
+#define        VPC_VG11DESTROYPAINT                    (VPG_VG11 +     VG11_DESTROYPAINT)
+#define        VPC_VG11DESTROYPATH                             (VPG_VG11 +     VG11_DESTROYPATH)
+#define        VPC_VG11DRAWGLYPH                               (VPG_VG11 +     VG11_DRAWGLYPH)
+#define        VPC_VG11DRAWGLYPHS                              (VPG_VG11 +     VG11_DRAWGLYPHS)
+#define        VPC_VG11DRAWIMAGE                               (VPG_VG11 +     VG11_DRAWIMAGE)
+#define        VPC_VG11DRAWPATH                                (VPG_VG11 +     VG11_DRAWPATH)
+#define        VPC_VG11FILLMASKLAYER                   (VPG_VG11 +     VG11_FILLMASKLAYER)
+#define        VPC_VG11FINISH                                  (VPG_VG11 +     VG11_FINISH)
+#define        VPC_VG11FLUSH                                   (VPG_VG11 +     VG11_FLUSH)
+#define        VPC_VG11GAUSSIANBLUR                    (VPG_VG11 +     VG11_GAUSSIANBLUR)
+#define        VPC_VG11GETCOLOR                                (VPG_VG11 +     VG11_GETCOLOR)
+#define        VPC_VG11GETERROR                                (VPG_VG11 +     VG11_GETERROR)
+#define        VPC_VG11GETF                                    (VPG_VG11 +     VG11_GETF)
+#define        VPC_VG11GETFV                                   (VPG_VG11 +     VG11_GETFV)
+#define        VPC_VG11GETI                                    (VPG_VG11 +     VG11_GETI)
+#define        VPC_VG11GETIMAGESUBDATA                 (VPG_VG11 +     VG11_GETIMAGESUBDATA)
+#define        VPC_VG11GETIV                                   (VPG_VG11 +     VG11_GETIV)
+#define        VPC_VG11GETMATRIX                               (VPG_VG11 +     VG11_GETMATRIX)
+#define        VPC_VG11GETPAINT                                (VPG_VG11 +     VG11_GETPAINT)
+#define        VPC_VG11GETPARAMETERF                   (VPG_VG11 +     VG11_GETPARAMETERF)
+#define        VPC_VG11GETPARAMETERFV                  (VPG_VG11 +     VG11_GETPARAMETERFV)
+#define        VPC_VG11GETPARAMETERI                   (VPG_VG11 +     VG11_GETPARAMETERI)
+#define        VPC_VG11GETPARAMETERIV                  (VPG_VG11 +     VG11_GETPARAMETERIV)
+#define        VPC_VG11GETPARAMETERVECTORSIZE  (VPG_VG11 +     VG11_GETPARAMETERVECTORSIZE)
+#define        VPC_VG11GETPARENT                               (VPG_VG11 +     VG11_GETPARENT)
+#define        VPC_VG11GETPATHCAPABILITIES             (VPG_VG11 +     VG11_GETPATHCAPABILITIES)
+#define        VPC_VG11GETPIXELS                               (VPG_VG11 +     VG11_GETPIXELS)
+#define        VPC_VG11GETSTRING                               (VPG_VG11 +     VG11_GETSTRING)
+#define        VPC_VG11GETVECTORSIZE                   (VPG_VG11 +     VG11_GETVECTORSIZE)
+#define        VPC_VG11HARDWAREQUERY                   (VPG_VG11 +     VG11_HARDWAREQUERY)
+#define        VPC_VG11IMAGESUBDATA                    (VPG_VG11 +     VG11_IMAGESUBDATA)
+#define        VPC_VG11INTERPOLATEPATH                 (VPG_VG11 +     VG11_INTERPOLATEPATH)
+#define        VPC_VG11LOADIDENTITY                    (VPG_VG11 +     VG11_LOADIDENTITY)
+#define        VPC_VG11LOADMATRIX                              (VPG_VG11 +     VG11_LOADMATRIX)
+#define        VPC_VG11LOOKUP                                  (VPG_VG11 +     VG11_LOOKUP)
+#define        VPC_VG11LOOKUPSINGLE                    (VPG_VG11 +     VG11_LOOKUPSINGLE)
+#define        VPC_VG11MASK                                    (VPG_VG11 +     VG11_MASK)
+#define        VPC_VG11MODIFYPATHCOORDS                (VPG_VG11 +     VG11_MODIFYPATHCOORDS)
+#define        VPC_VG11MULTMATRIX                              (VPG_VG11 +     VG11_MULTMATRIX)
+#define        VPC_VG11PAINTPATTERN                    (VPG_VG11 +     VG11_PAINTPATTERN)
+#define        VPC_VG11PATHBOUNDS                              (VPG_VG11 +     VG11_PATHBOUNDS)
+#define        VPC_VG11PATHLENGTH                              (VPG_VG11 +     VG11_PATHLENGTH)
+#define        VPC_VG11PATHTRANSFORMEDBOUNDS   (VPG_VG11 +     VG11_PATHTRANSFORMEDBOUNDS)
+#define        VPC_VG11POINTALONGPATH                  (VPG_VG11 +     VG11_POINTALONGPATH)
+#define        VPC_VG11READPIXELS                              (VPG_VG11 +     VG11_READPIXELS)
+#define        VPC_VG11REMOVEPATHCAPABILITIES  (VPG_VG11 +     VG11_REMOVEPATHCAPABILITIES)
+#define        VPC_VG11RENDERTOMASK                    (VPG_VG11 +     VG11_RENDERTOMASK)
+#define        VPC_VG11ROTATE                                  (VPG_VG11 +     VG11_ROTATE)
+#define        VPC_VG11SCALE                                   (VPG_VG11 +     VG11_SCALE)
+#define        VPC_VG11SEPARABLECONVOLVE               (VPG_VG11 +     VG11_SEPARABLECONVOLVE)
+#define        VPC_VG11SETCOLOR                                (VPG_VG11 +     VG11_SETCOLOR)
+#define        VPC_VG11SETF                                    (VPG_VG11 +     VG11_SETF)
+#define        VPC_VG11SETFV                                   (VPG_VG11 +     VG11_SETFV)
+#define        VPC_VG11SETGLYPHTOIMAGE                 (VPG_VG11 +     VG11_SETGLYPHTOIMAGE)
+#define        VPC_VG11SETGLYPHTOPATH                  (VPG_VG11 +     VG11_SETGLYPHTOPATH)
+#define        VPC_VG11SETI                                    (VPG_VG11 +     VG11_SETI)
+#define        VPC_VG11SETIV                                   (VPG_VG11 +     VG11_SETIV)
+#define        VPC_VG11SETPAINT                                (VPG_VG11 +     VG11_SETPAINT)
+#define        VPC_VG11SETPARAMETERF                   (VPG_VG11 +     VG11_SETPARAMETERF)
+#define        VPC_VG11SETPARAMETERFV                  (VPG_VG11 +     VG11_SETPARAMETERFV)
+#define        VPC_VG11SETPARAMETERI                   (VPG_VG11 +     VG11_SETPARAMETERI)
+#define        VPC_VG11SETPARAMETERIV                  (VPG_VG11 +     VG11_SETPARAMETERIV)
+#define        VPC_VG11SETPIXELS                               (VPG_VG11 +     VG11_SETPIXELS)
+#define        VPC_VG11SHEAR                                   (VPG_VG11 +     VG11_SHEAR)
+#define        VPC_VG11TRANSFORMPATH                   (VPG_VG11 +     VG11_TRANSFORMPATH)
+#define        VPC_VG11TRANSLATE                               (VPG_VG11 +     VG11_TRANSLATE)
+#define        VPC_VG11WRITEPIXELS                             (VPG_VG11 +     VG11_WRITEPIXELS)
+/* OpenVG Statistics Counter IDs. */
+#define        VPC_VG11CALLS                                   (VPG_VG11 +     VG11_CALLS)
+#define        VPC_VG11DRAWCALLS                               (VPG_VG11 +     VG11_DRAWCALLS)
+#define        VPC_VG11STATECHANGECALLS                (VPG_VG11 +     VG11_STATECHANGECALLS)
+#define        VPC_VG11FILLCOUNT                               (VPG_VG11 +     VG11_FILLCOUNT)
+#define        VPC_VG11STROKECOUNT                             (VPG_VG11 +     VG11_STROKECOUNT)
+
+/* HAL Counters. */
+#define VPC_HALVERTBUFNEWBYTEALLOC      (VPG_HAL + HAL_VERTBUFNEWBYTEALLOC)
+#define VPC_HALVERTBUFTOTALBYTEALLOC    (VPG_HAL + HAL_VERTBUFTOTALBYTEALLOC)
+#define VPC_HALVERTBUFNEWOBJALLOC       (VPG_HAL + HAL_VERTBUFNEWOBJALLOC)
+#define VPC_HALVERTBUFTOTALOBJALLOC     (VPG_HAL + HAL_VERTBUFTOTALOBJALLOC)
+#define VPC_HALINDBUFNEWBYTEALLOC       (VPG_HAL + HAL_INDBUFNEWBYTEALLOC)
+#define VPC_HALINDBUFTOTALBYTEALLOC     (VPG_HAL + HAL_INDBUFTOTALBYTEALLOC)
+#define VPC_HALINDBUFNEWOBJALLOC        (VPG_HAL + HAL_INDBUFNEWOBJALLOC)
+#define VPC_HALINDBUFTOTALOBJALLOC      (VPG_HAL + HAL_INDBUFTOTALOBJALLOC)
+#define VPC_HALTEXBUFNEWBYTEALLOC       (VPG_HAL + HAL_TEXBUFNEWBYTEALLOC)
+#define VPC_HALTEXBUFTOTALBYTEALLOC     (VPG_HAL + HAL_TEXBUFTOTALBYTEALLOC)
+#define VPC_HALTEXBUFNEWOBJALLOC        (VPG_HAL + HAL_TEXBUFNEWOBJALLOC)
+#define VPC_HALTEXBUFTOTALOBJALLOC      (VPG_HAL + HAL_TEXBUFTOTALOBJALLOC)
+
+/* HW: GPU Counters. */
+#define VPC_GPUCYCLES                   (VPG_GPU + GPU_CYCLES)
+#define VPC_GPUREAD64BYTE               (VPG_GPU + GPU_READ64BYTE)
+#define VPC_GPUWRITE64BYTE              (VPG_GPU + GPU_WRITE64BYTE)
+
+/* HW: Shader Counters. */
+#define VPC_VSINSTCOUNT                 (VPG_VS + VS_INSTCOUNT)
+#define VPC_VSBRANCHINSTCOUNT           (VPG_VS + VS_BRANCHINSTCOUNT)
+#define VPC_VSTEXLDINSTCOUNT            (VPG_VS + VS_TEXLDINSTCOUNT)
+#define VPC_VSRENDEREDVERTCOUNT         (VPG_VS + VS_RENDEREDVERTCOUNT)
+/* HW: PS Count. */
+#define VPC_PSINSTCOUNT                (VPG_PS + PS_INSTCOUNT)
+#define VPC_PSBRANCHINSTCOUNT          (VPG_PS + PS_BRANCHINSTCOUNT)
+#define VPC_PSTEXLDINSTCOUNT           (VPG_PS + PS_TEXLDINSTCOUNT)
+#define VPC_PSRENDEREDPIXCOUNT          (VPG_PS + PS_RENDEREDPIXCOUNT)
+
+
+/* HW: PA Counters. */
+#define VPC_PAINVERTCOUNT               (VPG_PA + PA_INVERTCOUNT)
+#define VPC_PAINPRIMCOUNT               (VPG_PA + PA_INPRIMCOUNT)
+#define VPC_PAOUTPRIMCOUNT              (VPG_PA + PA_OUTPRIMCOUNT)
+#define VPC_PADEPTHCLIPCOUNT            (VPG_PA + PA_DEPTHCLIPCOUNT)
+#define VPC_PATRIVIALREJCOUNT           (VPG_PA + PA_TRIVIALREJCOUNT)
+#define VPC_PACULLCOUNT                 (VPG_PA + PA_CULLCOUNT)
+
+/* HW: Setup Counters. */
+#define VPC_SETRIANGLECOUNT             (VPG_SETUP + SE_TRIANGLECOUNT)
+#define VPC_SELINECOUNT                 (VPG_SETUP + SE_LINECOUNT)
+
+/* HW: RA Counters. */
+#define VPC_RAVALIDPIXCOUNT             (VPG_RA + RA_VALIDPIXCOUNT)
+#define VPC_RATOTALQUADCOUNT            (VPG_RA + RA_TOTALQUADCOUNT)
+#define VPC_RAVALIDQUADCOUNTEZ          (VPG_RA + RA_VALIDQUADCOUNTEZ)
+#define VPC_RATOTALPRIMCOUNT            (VPG_RA + RA_TOTALPRIMCOUNT)
+#define VPC_RAPIPECACHEMISSCOUNT        (VPG_RA + RA_PIPECACHEMISSCOUNT)
+#define VPC_RAPREFCACHEMISSCOUNT        (VPG_RA + RA_PREFCACHEMISSCOUNT)
+#define VPC_RAEEZCULLCOUNT              (VPG_RA + RA_EEZCULLCOUNT)
+
+/* HW: TEX Counters. */
+#define VPC_TXTOTBILINEARREQ            (VPG_TX + TX_TOTBILINEARREQ)
+#define VPC_TXTOTTRILINEARREQ           (VPG_TX + TX_TOTTRILINEARREQ)
+#define VPC_TXTOTDISCARDTEXREQ          (VPG_TX + TX_TOTDISCARDTEXREQ)
+#define VPC_TXTOTTEXREQ                 (VPG_TX + TX_TOTTEXREQ)
+#define VPC_TXMEMREADCOUNT              (VPG_TX + TX_MEMREADCOUNT)
+#define VPC_TXMEMREADIN8BCOUNT          (VPG_TX + TX_MEMREADIN8BCOUNT)
+#define VPC_TXCACHEMISSCOUNT            (VPG_TX + TX_CACHEMISSCOUNT)
+#define VPC_TXCACHEHITTEXELCOUNT        (VPG_TX + TX_CACHEHITTEXELCOUNT)
+#define VPC_TXCACHEMISSTEXELCOUNT       (VPG_TX + TX_CACHEMISSTEXELCOUNT)
+
+/* HW: PE Counters. */
+#define VPC_PEKILLEDBYCOLOR             (VPG_PE + PE_KILLEDBYCOLOR)
+#define VPC_PEKILLEDBYDEPTH             (VPG_PE + PE_KILLEDBYDEPTH)
+#define VPC_PEDRAWNBYCOLOR              (VPG_PE + PE_DRAWNBYCOLOR)
+#define VPC_PEDRAWNBYDEPTH              (VPG_PE + PE_DRAWNBYDEPTH)
+
+/* HW: MC Counters. */
+#define VPC_MCREADREQ8BPIPE                    (VPG_MC + MC_READREQ8BPIPE)
+#define VPC_MCREADREQ8BIP               (VPG_MC + MC_READREQ8BIP)
+#define VPC_MCWRITEREQ8BPIPE            (VPG_MC + MC_WRITEREQ8BPIPE)
+
+/* HW: AXI Counters. */
+#define VPC_AXIREADREQSTALLED           (VPG_AXI + AXI_READREQSTALLED)
+#define VPC_AXIWRITEREQSTALLED          (VPG_AXI + AXI_WRITEREQSTALLED)
+#define VPC_AXIWRITEDATASTALLED         (VPG_AXI + AXI_WRITEDATASTALLED)
+
+/* PROGRAM: Shader program counters. */
+#define VPC_PVSINSTRCOUNT           (VPG_PVS + PVS_INSTRCOUNT)
+#define VPC_PVSALUINSTRCOUNT        (VPG_PVS + PVS_ALUINSTRCOUNT)
+#define VPC_PVSTEXINSTRCOUNT        (VPG_PVS + PVS_TEXINSTRCOUNT)
+#define VPC_PVSATTRIBCOUNT          (VPG_PVS + PVS_ATTRIBCOUNT)
+#define VPC_PVSUNIFORMCOUNT         (VPG_PVS + PVS_UNIFORMCOUNT)
+#define VPC_PVSFUNCTIONCOUNT        (VPG_PVS + PVS_FUNCTIONCOUNT)
+
+#define VPC_PPSINSTRCOUNT           (VPG_PPS + PPS_INSTRCOUNT)
+#define VPC_PPSALUINSTRCOUNT        (VPG_PPS + PPS_ALUINSTRCOUNT)
+#define VPC_PPSTEXINSTRCOUNT        (VPG_PPS + PPS_TEXINSTRCOUNT)
+#define VPC_PPSATTRIBCOUNT          (VPG_PPS + PPS_ATTRIBCOUNT)
+#define VPC_PPSUNIFORMCOUNT         (VPG_PPS + PPS_UNIFORMCOUNT)
+#define VPC_PPSFUNCTIONCOUNT        (VPG_PPS + PPS_FUNCTIONCOUNT)
+
+#endif
+
+
+/* HW profile information. */
+typedef struct _gcsPROFILER_COUNTERS
+{
+    /* HW static counters. */
+    gctUINT32       gpuClock;
+    gctUINT32       axiClock;
+    gctUINT32       shaderClock;
+
+    /* HW vairable counters. */
+    gctUINT32       gpuClockStart;
+    gctUINT32       gpuClockEnd;
+
+    /* HW vairable counters. */
+    gctUINT32       gpuCyclesCounter;
+    gctUINT32       gpuTotalRead64BytesPerFrame;
+    gctUINT32       gpuTotalWrite64BytesPerFrame;
+
+    /* PE */
+    gctUINT32       pe_pixel_count_killed_by_color_pipe;
+    gctUINT32       pe_pixel_count_killed_by_depth_pipe;
+    gctUINT32       pe_pixel_count_drawn_by_color_pipe;
+    gctUINT32       pe_pixel_count_drawn_by_depth_pipe;
+
+    /* SH */
+    gctUINT32       ps_inst_counter;
+    gctUINT32       rendered_pixel_counter;
+    gctUINT32       vs_inst_counter;
+    gctUINT32       rendered_vertice_counter;
+    gctUINT32       vtx_branch_inst_counter;
+    gctUINT32       vtx_texld_inst_counter;
+    gctUINT32       pxl_branch_inst_counter;
+    gctUINT32       pxl_texld_inst_counter;
+
+    /* PA */
+    gctUINT32       pa_input_vtx_counter;
+    gctUINT32       pa_input_prim_counter;
+    gctUINT32       pa_output_prim_counter;
+    gctUINT32       pa_depth_clipped_counter;
+    gctUINT32       pa_trivial_rejected_counter;
+    gctUINT32       pa_culled_counter;
+
+    /* SE */
+    gctUINT32       se_culled_triangle_count;
+    gctUINT32       se_culled_lines_count;
+
+    /* RA */
+    gctUINT32       ra_valid_pixel_count;
+    gctUINT32       ra_total_quad_count;
+    gctUINT32       ra_valid_quad_count_after_early_z;
+    gctUINT32       ra_total_primitive_count;
+    gctUINT32       ra_pipe_cache_miss_counter;
+    gctUINT32       ra_prefetch_cache_miss_counter;
+       gctUINT32       ra_eez_culled_counter;
+
+    /* TX */
+    gctUINT32       tx_total_bilinear_requests;
+    gctUINT32       tx_total_trilinear_requests;
+    gctUINT32       tx_total_discarded_texture_requests;
+    gctUINT32       tx_total_texture_requests;
+    gctUINT32       tx_mem_read_count;
+    gctUINT32       tx_mem_read_in_8B_count;
+    gctUINT32       tx_cache_miss_count;
+    gctUINT32       tx_cache_hit_texel_count;
+    gctUINT32       tx_cache_miss_texel_count;
+
+    /* MC */
+    gctUINT32       mc_total_read_req_8B_from_pipeline;
+    gctUINT32       mc_total_read_req_8B_from_IP;
+    gctUINT32       mc_total_write_req_8B_from_pipeline;
+
+    /* HI */
+    gctUINT32       hi_axi_cycles_read_request_stalled;
+    gctUINT32       hi_axi_cycles_write_request_stalled;
+    gctUINT32       hi_axi_cycles_write_data_stalled;
+}
+gcsPROFILER_COUNTERS;
+
+/* HAL profile information. */
+typedef struct _gcsPROFILER
+{
+    gctUINT32       enable;
+    gctBOOL         enableHal;
+    gctBOOL         enableHW;
+    gctBOOL         enableSH;
+
+    gctBOOL         useSocket;
+    gctINT          sockFd;
+
+    gctFILE         file;
+
+    /* Aggregate Information */
+
+    /* Clock Info */
+    gctUINT64       frameStart;
+    gctUINT64       frameEnd;
+
+    /* Current frame information */
+    gctUINT32       frameNumber;
+    gctUINT64       frameStartTimeusec;
+    gctUINT64       frameEndTimeusec;
+    gctUINT64       frameStartCPUTimeusec;
+    gctUINT64       frameEndCPUTimeusec;
+
+#if PROFILE_HAL_COUNTERS
+    gctUINT32       vertexBufferTotalBytesAlloc;
+    gctUINT32       vertexBufferNewBytesAlloc;
+    int             vertexBufferTotalObjectsAlloc;
+    int             vertexBufferNewObjectsAlloc;
+
+    gctUINT32       indexBufferTotalBytesAlloc;
+    gctUINT32       indexBufferNewBytesAlloc;
+    int             indexBufferTotalObjectsAlloc;
+    int             indexBufferNewObjectsAlloc;
+
+    gctUINT32       textureBufferTotalBytesAlloc;
+    gctUINT32       textureBufferNewBytesAlloc;
+    int             textureBufferTotalObjectsAlloc;
+    int             textureBufferNewObjectsAlloc;
+
+    gctUINT32       numCommits;
+    gctUINT32       drawPointCount;
+    gctUINT32       drawLineCount;
+    gctUINT32       drawTriangleCount;
+    gctUINT32       drawVertexCount;
+    gctUINT32       redundantStateChangeCalls;
+#endif
+}
+gcsPROFILER;
+
+/* Memory profile information. */
+struct _gcsMemProfile
+{
+    /* Memory Usage */
+    gctUINT32       videoMemUsed;
+    gctUINT32       systemMemUsed;
+    gctUINT32       commitBufferSize;
+    gctUINT32       contextBufferCopyBytes;
+};
+
+/* Shader profile information. */
+struct _gcsSHADER_PROFILER
+{
+    gctUINT32       shaderLength;
+    gctUINT32       shaderALUCycles;
+    gctUINT32       shaderTexLoadCycles;
+    gctUINT32       shaderTempRegCount;
+    gctUINT32       shaderSamplerRegCount;
+    gctUINT32       shaderInputRegCount;
+    gctUINT32       shaderOutputRegCount;
+};
+
+/* Initialize the gcsProfiler. */
+gceSTATUS
+gcoPROFILER_Initialize(
+    IN gcoHAL Hal
+    );
+
+/* Destroy the gcProfiler. */
+gceSTATUS
+gcoPROFILER_Destroy(
+    IN gcoHAL Hal
+    );
+
+/* Write data to profiler. */
+gceSTATUS
+gcoPROFILER_Write(
+    IN gcoHAL Hal,
+    IN gctSIZE_T ByteCount,
+    IN gctCONST_POINTER Data
+    );
+
+/* Flush data out. */
+gceSTATUS
+gcoPROFILER_Flush(
+    IN gcoHAL Hal
+    );
+
+/* Call to signal end of frame. */
+gceSTATUS
+gcoPROFILER_EndFrame(
+    IN gcoHAL Hal
+    );
+
+/* Increase profile counter Enum by Value. */
+gceSTATUS
+gcoPROFILER_Count(
+       IN gcoHAL Hal,
+       IN gctUINT32 Enum,
+       IN gctINT Value
+       );
+
+/* Profile input vertex shader. */
+gceSTATUS
+gcoPROFILER_ShaderVS(
+    IN gcoHAL Hal,
+    IN gctPOINTER Vs
+    );
+
+/* Profile input fragment shader. */
+gceSTATUS
+gcoPROFILER_ShaderFS(
+    IN gcoHAL Hal,
+    IN gctPOINTER Fs
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_profiler_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h
new file mode 100644 (file)
index 0000000..4a52bd8
--- /dev/null
@@ -0,0 +1,927 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_raster_h_
+#define __gc_hal_raster_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoBRUSH *                             gcoBRUSH;
+typedef struct _gcoBRUSH_CACHE *               gcoBRUSH_CACHE;
+
+/******************************************************************************\
+******************************** gcoBRUSH Object *******************************
+\******************************************************************************/
+
+/* Create a new solid color gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructSingleColor(
+       IN gcoHAL Hal,
+       IN gctUINT32 ColorConvert,
+       IN gctUINT32 Color,
+       IN gctUINT64 Mask,
+       gcoBRUSH * Brush
+       );
+
+/* Create a new monochrome gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructMonochrome(
+       IN gcoHAL Hal,
+       IN gctUINT32 OriginX,
+       IN gctUINT32 OriginY,
+       IN gctUINT32 ColorConvert,
+       IN gctUINT32 FgColor,
+       IN gctUINT32 BgColor,
+       IN gctUINT64 Bits,
+       IN gctUINT64 Mask,
+       gcoBRUSH * Brush
+       );
+
+/* Create a color gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructColor(
+       IN gcoHAL Hal,
+       IN gctUINT32 OriginX,
+       IN gctUINT32 OriginY,
+       IN gctPOINTER Address,
+       IN gceSURF_FORMAT Format,
+       IN gctUINT64 Mask,
+       gcoBRUSH * Brush
+       );
+
+/* Destroy an gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_Destroy(
+       IN gcoBRUSH Brush
+       );
+
+/******************************************************************************\
+******************************** gcoSURF Object *******************************
+\******************************************************************************/
+
+/* Set cipping rectangle. */
+gceSTATUS
+gcoSURF_SetClipping(
+       IN gcoSURF Surface
+       );
+
+/* Clear one or more rectangular areas. */
+gceSTATUS
+gcoSURF_Clear2D(
+       IN gcoSURF DestSurface,
+       IN gctUINT32 RectCount,
+       IN gcsRECT_PTR DestRect,
+       IN gctUINT32 LoColor,
+       IN gctUINT32 HiColor
+       );
+
+/* Draw one or more Bresenham lines. */
+gceSTATUS
+gcoSURF_Line(
+       IN gcoSURF Surface,
+       IN gctUINT32 LineCount,
+       IN gcsRECT_PTR Position,
+       IN gcoBRUSH Brush,
+       IN gctUINT8 FgRop,
+       IN gctUINT8 BgRop
+       );
+
+/* Generic rectangular blit. */
+gceSTATUS
+gcoSURF_Blit(
+       IN OPTIONAL gcoSURF SrcSurface,
+       IN gcoSURF DestSurface,
+       IN gctUINT32 RectCount,
+       IN OPTIONAL gcsRECT_PTR SrcRect,
+       IN gcsRECT_PTR DestRect,
+       IN OPTIONAL gcoBRUSH Brush,
+       IN gctUINT8 FgRop,
+       IN gctUINT8 BgRop,
+       IN OPTIONAL gceSURF_TRANSPARENCY Transparency,
+       IN OPTIONAL gctUINT32 TransparencyColor,
+       IN OPTIONAL gctPOINTER Mask,
+       IN OPTIONAL gceSURF_MONOPACK MaskPack
+       );
+
+/* Monochrome blit. */
+gceSTATUS
+gcoSURF_MonoBlit(
+       IN gcoSURF DestSurface,
+       IN gctPOINTER Source,
+       IN gceSURF_MONOPACK SourcePack,
+       IN gcsPOINT_PTR SourceSize,
+       IN gcsPOINT_PTR SourceOrigin,
+       IN gcsRECT_PTR DestRect,
+       IN OPTIONAL gcoBRUSH Brush,
+       IN gctUINT8 FgRop,
+       IN gctUINT8 BgRop,
+       IN gctBOOL ColorConvert,
+       IN gctUINT8 MonoTransparency,
+       IN gceSURF_TRANSPARENCY Transparency,
+       IN gctUINT32 FgColor,
+       IN gctUINT32 BgColor
+       );
+
+/* Filter blit. */
+gceSTATUS
+gcoSURF_FilterBlit(
+       IN gcoSURF SrcSurface,
+       IN gcoSURF DestSurface,
+       IN gcsRECT_PTR SrcRect,
+       IN gcsRECT_PTR DestRect,
+       IN gcsRECT_PTR DestSubRect
+       );
+
+/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
+gceSTATUS
+gcoSURF_EnableAlphaBlend(
+       IN gcoSURF Surface,
+       IN gctUINT8 SrcGlobalAlphaValue,
+       IN gctUINT8 DstGlobalAlphaValue,
+       IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+       IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+       IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+       IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+       IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+       IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
+       IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
+       IN gceSURF_PIXEL_COLOR_MODE DstColorMode
+       );
+
+/* Disable alpha blending engine in the hardware and engage the ROP engine. */
+gceSTATUS
+gcoSURF_DisableAlphaBlend(
+       IN gcoSURF Surface
+       );
+
+/* Copy a rectangular area with format conversion. */
+gceSTATUS
+gcoSURF_CopyPixels(
+       IN gcoSURF Source,
+       IN gcoSURF Target,
+       IN gctINT SourceX,
+       IN gctINT SourceY,
+       IN gctINT TargetX,
+       IN gctINT TargetY,
+       IN gctINT Width,
+       IN gctINT Height
+       );
+
+/* Read surface pixel. */
+gceSTATUS
+gcoSURF_ReadPixel(
+       IN gcoSURF Surface,
+       IN gctPOINTER Memory,
+       IN gctINT X,
+       IN gctINT Y,
+       IN gceSURF_FORMAT Format,
+       OUT gctPOINTER PixelValue
+       );
+
+/* Write surface pixel. */
+gceSTATUS
+gcoSURF_WritePixel(
+       IN gcoSURF Surface,
+       IN gctPOINTER Memory,
+       IN gctINT X,
+       IN gctINT Y,
+       IN gceSURF_FORMAT Format,
+       IN gctPOINTER PixelValue
+       );
+
+gceSTATUS
+gcoSURF_SetDither(
+    IN gcoSURF Surface,
+    IN gctBOOL Dither
+    );
+/******************************************************************************\
+********************************** gco2D Object *********************************
+\******************************************************************************/
+
+/* Construct a new gco2D object. */
+gceSTATUS
+gco2D_Construct(
+       IN gcoHAL Hal,
+       OUT gco2D * Hardware
+       );
+
+/* Destroy an gco2D object. */
+gceSTATUS
+gco2D_Destroy(
+       IN gco2D Hardware
+       );
+
+/* Sets the maximum number of brushes in the brush cache. */
+gceSTATUS
+gco2D_SetBrushLimit(
+       IN gco2D Hardware,
+       IN gctUINT MaxCount
+       );
+
+/* Flush the brush. */
+gceSTATUS
+gco2D_FlushBrush(
+       IN gco2D Engine,
+       IN gcoBRUSH Brush,
+       IN gceSURF_FORMAT Format
+       );
+
+/* Program the specified solid color brush. */
+gceSTATUS
+gco2D_LoadSolidBrush(
+       IN gco2D Engine,
+       IN gceSURF_FORMAT Format,
+       IN gctUINT32 ColorConvert,
+       IN gctUINT32 Color,
+       IN gctUINT64 Mask
+       );
+
+gceSTATUS
+gco2D_LoadMonochromeBrush(
+    IN gco2D Engine,
+    IN gctUINT32 OriginX,
+    IN gctUINT32 OriginY,
+    IN gctUINT32 ColorConvert,
+    IN gctUINT32 FgColor,
+    IN gctUINT32 BgColor,
+    IN gctUINT64 Bits,
+    IN gctUINT64 Mask
+    );
+
+gceSTATUS
+gco2D_LoadColorBrush(
+    IN gco2D Engine,
+    IN gctUINT32 OriginX,
+    IN gctUINT32 OriginY,
+    IN gctUINT32 Address,
+    IN gceSURF_FORMAT Format,
+    IN gctUINT64 Mask
+    );
+
+/* Configure monochrome source. */
+gceSTATUS
+gco2D_SetMonochromeSource(
+       IN gco2D Engine,
+       IN gctBOOL ColorConvert,
+       IN gctUINT8 MonoTransparency,
+       IN gceSURF_MONOPACK DataPack,
+       IN gctBOOL CoordRelative,
+       IN gceSURF_TRANSPARENCY Transparency,
+       IN gctUINT32 FgColor,
+       IN gctUINT32 BgColor
+       );
+
+/* Configure color source. */
+gceSTATUS
+gco2D_SetColorSource(
+       IN gco2D Engine,
+       IN gctUINT32 Address,
+       IN gctUINT32 Stride,
+       IN gceSURF_FORMAT Format,
+       IN gceSURF_ROTATION Rotation,
+       IN gctUINT32 SurfaceWidth,
+       IN gctBOOL CoordRelative,
+       IN gceSURF_TRANSPARENCY Transparency,
+       IN gctUINT32 TransparencyColor
+       );
+
+/* Configure color source extension for full rotation. */
+gceSTATUS
+gco2D_SetColorSourceEx(
+       IN gco2D Engine,
+       IN gctUINT32 Address,
+       IN gctUINT32 Stride,
+       IN gceSURF_FORMAT Format,
+       IN gceSURF_ROTATION Rotation,
+       IN gctUINT32 SurfaceWidth,
+       IN gctUINT32 SurfaceHeight,
+       IN gctBOOL CoordRelative,
+       IN gceSURF_TRANSPARENCY Transparency,
+       IN gctUINT32 TransparencyColor
+       );
+
+/* Configure color source. */
+gceSTATUS
+gco2D_SetColorSourceAdvanced(
+       IN gco2D Engine,
+       IN gctUINT32 Address,
+       IN gctUINT32 Stride,
+       IN gceSURF_FORMAT Format,
+       IN gceSURF_ROTATION Rotation,
+       IN gctUINT32 SurfaceWidth,
+       IN gctUINT32 SurfaceHeight,
+       IN gctBOOL CoordRelative
+       );
+
+gceSTATUS
+gco2D_SetColorSourceN(
+    IN gco2D Engine,
+    IN gctUINT32 Address,
+    IN gctUINT32 Stride,
+    IN gceSURF_FORMAT Format,
+    IN gceSURF_ROTATION Rotation,
+    IN gctUINT32 SurfaceWidth,
+    IN gctUINT32 SurfaceHeight,
+    IN gctUINT32 SurfaceNumber
+    );
+
+/* Configure masked color source. */
+gceSTATUS
+gco2D_SetMaskedSource(
+       IN gco2D Engine,
+       IN gctUINT32 Address,
+       IN gctUINT32 Stride,
+       IN gceSURF_FORMAT Format,
+       IN gctBOOL CoordRelative,
+       IN gceSURF_MONOPACK MaskPack
+       );
+
+/* Configure masked color source extension for full rotation. */
+gceSTATUS
+gco2D_SetMaskedSourceEx(
+       IN gco2D Engine,
+       IN gctUINT32 Address,
+       IN gctUINT32 Stride,
+       IN gceSURF_FORMAT Format,
+       IN gctBOOL CoordRelative,
+       IN gceSURF_MONOPACK MaskPack,
+       IN gceSURF_ROTATION Rotation,
+       IN gctUINT32 SurfaceWidth,
+       IN gctUINT32 SurfaceHeight
+       );
+
+/* Setup the source rectangle. */
+gceSTATUS
+gco2D_SetSource(
+       IN gco2D Engine,
+       IN gcsRECT_PTR SrcRect
+       );
+
+/* Set clipping rectangle. */
+gceSTATUS
+gco2D_SetClipping(
+       IN gco2D Engine,
+       IN gcsRECT_PTR Rect
+       );
+
+/* Configure destination. */
+gceSTATUS
+gco2D_SetTarget(
+       IN gco2D Engine,
+       IN gctUINT32 Address,
+       IN gctUINT32 Stride,
+       IN gceSURF_ROTATION Rotation,
+       IN gctUINT32 SurfaceWidth
+       );
+
+/* Configure destination extension for full rotation. */
+gceSTATUS
+gco2D_SetTargetEx(
+       IN gco2D Engine,
+       IN gctUINT32 Address,
+       IN gctUINT32 Stride,
+       IN gceSURF_ROTATION Rotation,
+       IN gctUINT32 SurfaceWidth,
+       IN gctUINT32 SurfaceHeight
+       );
+
+/* Calculate and program the stretch factors. */
+gceSTATUS
+gco2D_SetStretchFactors(
+       IN gco2D Engine,
+       IN gctUINT32 HorFactor,
+       IN gctUINT32 VerFactor
+       );
+
+/* Calculate and program the stretch factors based on the rectangles. */
+gceSTATUS
+gco2D_SetStretchRectFactors(
+       IN gco2D Engine,
+       IN gcsRECT_PTR SrcRect,
+       IN gcsRECT_PTR DestRect
+       );
+
+/* Create a new solid color gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructSingleColorBrush(
+       IN gco2D Engine,
+       IN gctUINT32 ColorConvert,
+       IN gctUINT32 Color,
+       IN gctUINT64 Mask,
+       gcoBRUSH * Brush
+       );
+
+/* Create a new monochrome gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructMonochromeBrush(
+       IN gco2D Engine,
+       IN gctUINT32 OriginX,
+       IN gctUINT32 OriginY,
+       IN gctUINT32 ColorConvert,
+       IN gctUINT32 FgColor,
+       IN gctUINT32 BgColor,
+       IN gctUINT64 Bits,
+       IN gctUINT64 Mask,
+       gcoBRUSH * Brush
+       );
+
+/* Create a color gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructColorBrush(
+       IN gco2D Engine,
+       IN gctUINT32 OriginX,
+       IN gctUINT32 OriginY,
+       IN gctPOINTER Address,
+       IN gceSURF_FORMAT Format,
+       IN gctUINT64 Mask,
+       gcoBRUSH * Brush
+       );
+
+/* Clear one or more rectangular areas. */
+gceSTATUS
+gco2D_Clear(
+       IN gco2D Engine,
+       IN gctUINT32 RectCount,
+       IN gcsRECT_PTR Rect,
+       IN gctUINT32 Color32,
+       IN gctUINT8 FgRop,
+       IN gctUINT8 BgRop,
+       IN gceSURF_FORMAT DestFormat
+       );
+
+/* Draw one or more Bresenham lines. */
+gceSTATUS
+gco2D_Line(
+       IN gco2D Engine,
+       IN gctUINT32 LineCount,
+       IN gcsRECT_PTR Position,
+       IN gcoBRUSH Brush,
+       IN gctUINT8 FgRop,
+       IN gctUINT8 BgRop,
+       IN gceSURF_FORMAT DestFormat
+       );
+
+/* Draw one or more Bresenham lines based on the 32-bit color. */
+gceSTATUS
+gco2D_ColorLine(
+       IN gco2D Engine,
+       IN gctUINT32 LineCount,
+       IN gcsRECT_PTR Position,
+       IN gctUINT32 Color32,
+       IN gctUINT8 FgRop,
+       IN gctUINT8 BgRop,
+       IN gceSURF_FORMAT DestFormat
+       );
+
+/* Generic blit. */
+gceSTATUS
+gco2D_Blit(
+       IN gco2D Engine,
+       IN gctUINT32 RectCount,
+       IN gcsRECT_PTR Rect,
+       IN gctUINT8 FgRop,
+       IN gctUINT8 BgRop,
+       IN gceSURF_FORMAT DestFormat
+       );
+
+gceSTATUS
+gco2D_Blend(
+    IN gco2D Engine,
+    IN gctUINT32 SrcCount,
+    IN gctUINT32 RectCount,
+    IN gcsRECT_PTR Rect,
+    IN gctUINT8 FgRop,
+    IN gctUINT8 BgRop,
+    IN gceSURF_FORMAT DestFormat
+    );
+
+/* Batch blit. */
+gceSTATUS
+gco2D_BatchBlit(
+       IN gco2D Engine,
+       IN gctUINT32 RectCount,
+       IN gcsRECT_PTR SrcRect,
+       IN gcsRECT_PTR DestRect,
+       IN gctUINT8 FgRop,
+       IN gctUINT8 BgRop,
+       IN gceSURF_FORMAT DestFormat
+       );
+
+/* Stretch blit. */
+gceSTATUS
+gco2D_StretchBlit(
+       IN gco2D Engine,
+       IN gctUINT32 RectCount,
+       IN gcsRECT_PTR Rect,
+       IN gctUINT8 FgRop,
+       IN gctUINT8 BgRop,
+       IN gceSURF_FORMAT DestFormat
+       );
+
+/* Monochrome blit. */
+gceSTATUS
+gco2D_MonoBlit(
+       IN gco2D Engine,
+       IN gctPOINTER StreamBits,
+       IN gcsPOINT_PTR StreamSize,
+       IN gcsRECT_PTR StreamRect,
+       IN gceSURF_MONOPACK SrcStreamPack,
+       IN gceSURF_MONOPACK DestStreamPack,
+       IN gcsRECT_PTR DestRect,
+       IN gctUINT32 FgRop,
+       IN gctUINT32 BgRop,
+       IN gceSURF_FORMAT DestFormat
+       );
+
+/* Set kernel size. */
+gceSTATUS
+gco2D_SetKernelSize(
+       IN gco2D Engine,
+       IN gctUINT8 HorKernelSize,
+       IN gctUINT8 VerKernelSize
+       );
+
+/* Set filter type. */
+gceSTATUS
+gco2D_SetFilterType(
+       IN gco2D Engine,
+       IN gceFILTER_TYPE FilterType
+       );
+
+/* Set the filter kernel by user. */
+gceSTATUS
+gco2D_SetUserFilterKernel(
+       IN gco2D Engine,
+       IN gceFILTER_PASS_TYPE PassType,
+       IN gctUINT16_PTR KernelArray
+       );
+
+/* Select the pass(es) to be done for user defined filter. */
+gceSTATUS
+gco2D_EnableUserFilterPasses(
+       IN gco2D Engine,
+       IN gctBOOL HorPass,
+       IN gctBOOL VerPass
+       );
+
+/* Frees the temporary buffer allocated by filter blit operation. */
+gceSTATUS
+gco2D_FreeFilterBuffer(
+       IN gco2D Engine
+       );
+
+/* Filter blit. */
+gceSTATUS
+gco2D_FilterBlit(
+       IN gco2D Engine,
+       IN gctUINT32 SrcAddress,
+       IN gctUINT SrcStride,
+       IN gctUINT32 SrcUAddress,
+       IN gctUINT SrcUStride,
+       IN gctUINT32 SrcVAddress,
+       IN gctUINT SrcVStride,
+       IN gceSURF_FORMAT SrcFormat,
+       IN gceSURF_ROTATION SrcRotation,
+       IN gctUINT32 SrcSurfaceWidth,
+       IN gcsRECT_PTR SrcRect,
+       IN gctUINT32 DestAddress,
+       IN gctUINT DestStride,
+       IN gceSURF_FORMAT DestFormat,
+       IN gceSURF_ROTATION DestRotation,
+       IN gctUINT32 DestSurfaceWidth,
+       IN gcsRECT_PTR DestRect,
+       IN gcsRECT_PTR DestSubRect
+       );
+
+/* Filter blit extension for full rotation. */
+gceSTATUS
+gco2D_FilterBlitEx(
+       IN gco2D Engine,
+       IN gctUINT32 SrcAddress,
+       IN gctUINT SrcStride,
+       IN gctUINT32 SrcUAddress,
+       IN gctUINT SrcUStride,
+       IN gctUINT32 SrcVAddress,
+       IN gctUINT SrcVStride,
+       IN gceSURF_FORMAT SrcFormat,
+       IN gceSURF_ROTATION SrcRotation,
+       IN gctUINT32 SrcSurfaceWidth,
+       IN gctUINT32 SrcSurfaceHeight,
+       IN gcsRECT_PTR SrcRect,
+       IN gctUINT32 DestAddress,
+       IN gctUINT DestStride,
+       IN gceSURF_FORMAT DestFormat,
+       IN gceSURF_ROTATION DestRotation,
+       IN gctUINT32 DestSurfaceWidth,
+       IN gctUINT32 DestSurfaceHeight,
+       IN gcsRECT_PTR DestRect,
+       IN gcsRECT_PTR DestSubRect
+       );
+
+gceSTATUS
+gco2D_FilterBlitEx2(
+    IN gco2D                Engine,
+    IN gctUINT32_PTR        SrcAddresses,
+    IN gctUINT32            SrcAddressNum,
+    IN gctUINT32_PTR        SrcStrides,
+    IN gctUINT32            SrcStrideNum,
+    IN gceTILING            SrcTiling,
+    IN gceSURF_FORMAT       SrcFormat,
+    IN gceSURF_ROTATION     SrcRotation,
+    IN gctUINT32            SrcSurfaceWidth,
+    IN gctUINT32            SrcSurfaceHeight,
+    IN gcsRECT_PTR          SrcRect,
+    IN gctUINT32_PTR        DestAddresses,
+    IN gctUINT32            DestAddressNum,
+    IN gctUINT32_PTR        DestStrides,
+    IN gctUINT32            DestStrideNum,
+    IN gceTILING            DestTiling,
+    IN gceSURF_FORMAT       DestFormat,
+    IN gceSURF_ROTATION     DestRotation,
+    IN gctUINT32            DestSurfaceWidth,
+    IN gctUINT32            DestSurfaceHeight,
+    IN gcsRECT_PTR          DestRect,
+    IN gcsRECT_PTR          DestSubRect
+    );
+
+/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
+gceSTATUS
+gco2D_EnableAlphaBlend(
+       IN gco2D Engine,
+       IN gctUINT8 SrcGlobalAlphaValue,
+       IN gctUINT8 DstGlobalAlphaValue,
+       IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+       IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+       IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+       IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+       IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+       IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
+       IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
+       IN gceSURF_PIXEL_COLOR_MODE DstColorMode
+       );
+
+/* Enable alpha blending engine in the hardware. */
+gceSTATUS
+gco2D_EnableAlphaBlendAdvanced(
+       IN gco2D Engine,
+       IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+       IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+       IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+       IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+       IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+       IN gceSURF_BLEND_FACTOR_MODE DstFactorMode
+       );
+
+/* Enable alpha blending engine with Porter Duff rule. */
+gceSTATUS
+gco2D_SetPorterDuffBlending(
+       IN gco2D Engine,
+       IN gce2D_PORTER_DUFF_RULE Rule
+       );
+
+/* Disable alpha blending engine in the hardware and engage the ROP engine. */
+gceSTATUS
+gco2D_DisableAlphaBlend(
+       IN gco2D Engine
+       );
+
+/* Retrieve the maximum number of 32-bit data chunks for a single DE command. */
+gctUINT32
+gco2D_GetMaximumDataCount(
+       void
+       );
+
+/* Retrieve the maximum number of rectangles, that can be passed in a single DE command. */
+gctUINT32
+gco2D_GetMaximumRectCount(
+       void
+       );
+
+/* Returns the pixel alignment of the surface. */
+gceSTATUS
+gco2D_GetPixelAlignment(
+       gceSURF_FORMAT Format,
+       gcsPOINT_PTR Alignment
+       );
+
+/* Retrieve monochrome stream pack size. */
+gceSTATUS
+gco2D_GetPackSize(
+       IN gceSURF_MONOPACK StreamPack,
+       OUT gctUINT32 * PackWidth,
+       OUT gctUINT32 * PackHeight
+       );
+
+/* Flush the 2D pipeline. */
+gceSTATUS
+gco2D_Flush(
+       IN gco2D Engine
+       );
+
+/* Load 256-entry color table for INDEX8 source surfaces. */
+gceSTATUS
+gco2D_LoadPalette(
+       IN gco2D Engine,
+       IN gctUINT FirstIndex,
+       IN gctUINT IndexCount,
+       IN gctPOINTER ColorTable,
+       IN gctBOOL ColorConvert
+       );
+
+/* Enable/disable 2D BitBlt mirrorring. */
+gceSTATUS
+gco2D_SetBitBlitMirror(
+       IN gco2D Engine,
+       IN gctBOOL HorizontalMirror,
+       IN gctBOOL VerticalMirror
+       );
+
+/*
+ * Set the transparency for source, destination and pattern.
+ * It also enable or disable the DFB color key mode.
+ */
+gceSTATUS
+gco2D_SetTransparencyAdvancedEx(
+    IN gco2D Engine,
+    IN gce2D_TRANSPARENCY SrcTransparency,
+    IN gce2D_TRANSPARENCY DstTransparency,
+    IN gce2D_TRANSPARENCY PatTransparency,
+    IN gctBOOL EnableDFBColorKeyMode
+       );
+
+/* Set the transparency for source, destination and pattern. */
+gceSTATUS
+gco2D_SetTransparencyAdvanced(
+       IN gco2D Engine,
+       IN gce2D_TRANSPARENCY SrcTransparency,
+       IN gce2D_TRANSPARENCY DstTransparency,
+       IN gce2D_TRANSPARENCY PatTransparency
+       );
+
+/* Set the source color key. */
+gceSTATUS
+gco2D_SetSourceColorKeyAdvanced(
+       IN gco2D Engine,
+       IN gctUINT32 ColorKey
+       );
+
+/* Set the source color key range. */
+gceSTATUS
+gco2D_SetSourceColorKeyRangeAdvanced(
+       IN gco2D Engine,
+       IN gctUINT32 ColorKeyLow,
+       IN gctUINT32 ColorKeyHigh
+       );
+
+/* Set the target color key. */
+gceSTATUS
+gco2D_SetTargetColorKeyAdvanced(
+       IN gco2D Engine,
+       IN gctUINT32 ColorKey
+       );
+
+/* Set the target color key range. */
+gceSTATUS
+gco2D_SetTargetColorKeyRangeAdvanced(
+       IN gco2D Engine,
+       IN gctUINT32 ColorKeyLow,
+       IN gctUINT32 ColorKeyHigh
+       );
+
+/* Set the YUV color space mode. */
+gceSTATUS
+gco2D_SetYUVColorMode(
+       IN gco2D Engine,
+       IN gce2D_YUV_COLOR_MODE Mode
+       );
+
+/* Setup the source global color value in ARGB8 format. */
+gceSTATUS gco2D_SetSourceGlobalColorAdvanced(
+       IN gco2D Engine,
+       IN gctUINT32 Color32
+       );
+
+/* Setup the target global color value in ARGB8 format. */
+gceSTATUS gco2D_SetTargetGlobalColorAdvanced(
+       IN gco2D Engine,
+       IN gctUINT32 Color32
+       );
+
+/* Setup the source and target pixel multiply modes. */
+gceSTATUS
+gco2D_SetPixelMultiplyModeAdvanced(
+       IN gco2D Engine,
+       IN gce2D_PIXEL_COLOR_MULTIPLY_MODE SrcPremultiplySrcAlpha,
+       IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstPremultiplyDstAlpha,
+       IN gce2D_GLOBAL_COLOR_MULTIPLY_MODE SrcPremultiplyGlobalMode,
+       IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstDemultiplyDstAlpha
+       );
+
+/* Set the GPU clock cycles after which the idle engine will keep auto-flushing. */
+gceSTATUS
+gco2D_SetAutoFlushCycles(
+       IN gco2D Engine,
+       IN gctUINT32 Cycles
+       );
+
+#if VIVANTE_PROFILER
+/* Read the profile registers available in the 2D engine and sets them in the profile.
+   The function will also reset the pixelsRendered counter every time.
+*/
+gceSTATUS
+gco2D_ProfileEngine(
+       IN gco2D Engine,
+       OPTIONAL gcs2D_PROFILE_PTR Profile
+       );
+#endif
+
+/* Enable or disable 2D dithering. */
+gceSTATUS
+gco2D_EnableDither(
+       IN gco2D Engine,
+       IN gctBOOL Enable
+       );
+
+gceSTATUS
+gco2D_SetGenericSource(
+    IN gco2D               Engine,
+    IN gctUINT32_PTR       Addresses,
+    IN gctUINT32           AddressNum,
+    IN gctUINT32_PTR       Strides,
+    IN gctUINT32           StrideNum,
+    IN gceTILING           Tiling,
+    IN gceSURF_FORMAT      Format,
+    IN gceSURF_ROTATION    Rotation,
+    IN gctUINT32           SurfaceWidth,
+    IN gctUINT32           SurfaceHeight
+);
+
+gceSTATUS
+gco2D_SetGenericTarget(
+    IN gco2D               Engine,
+    IN gctUINT32_PTR       Addresses,
+    IN gctUINT32           AddressNum,
+    IN gctUINT32_PTR       Strides,
+    IN gctUINT32           StrideNum,
+    IN gceTILING           Tiling,
+    IN gceSURF_FORMAT      Format,
+    IN gceSURF_ROTATION    Rotation,
+    IN gctUINT32           SurfaceWidth,
+    IN gctUINT32           SurfaceHeight
+);
+
+gceSTATUS
+gco2D_SetCurrentSourceIndex(
+    IN gco2D        Engine,
+    IN gctUINT32    SrcIndex
+    );
+
+gceSTATUS
+gco2D_MultiSourceBlit(
+    IN gco2D Engine,
+    IN gctUINT32 SourceMask,
+    IN gcsRECT_PTR DestRect,
+    IN gctUINT32 RectCount
+    );
+
+gceSTATUS
+gco2D_SetROP(
+    IN gco2D Engine,
+    IN gctUINT8 FgRop,
+    IN gctUINT8 BgRop
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_raster_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h
new file mode 100644 (file)
index 0000000..52b96d8
--- /dev/null
@@ -0,0 +1,250 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_rename_h_
+#define __gc_hal_rename_h_
+
+
+#if defined(_HAL2D_APPENDIX)
+
+#define _HAL2D_RENAME_2(api, appendix)  api ## appendix
+#define _HAL2D_RENAME_1(api, appendix)  _HAL2D_RENAME_2(api, appendix)
+#define gcmHAL2D(api)                   _HAL2D_RENAME_1(api, _HAL2D_APPENDIX)
+
+
+#define gckOS_Construct                 gcmHAL2D(gckOS_Construct)
+#define gckOS_Destroy                   gcmHAL2D(gckOS_Destroy)
+#define gckOS_QueryVideoMemory          gcmHAL2D(gckOS_QueryVideoMemory)
+#define gckOS_Allocate                  gcmHAL2D(gckOS_Allocate)
+#define gckOS_Free                      gcmHAL2D(gckOS_Free)
+#define gckOS_AllocateMemory            gcmHAL2D(gckOS_AllocateMemory)
+#define gckOS_FreeMemory                gcmHAL2D(gckOS_FreeMemory)
+#define gckOS_AllocatePagedMemory       gcmHAL2D(gckOS_AllocatePagedMemory)
+#define gckOS_AllocatePagedMemoryEx     gcmHAL2D(gckOS_AllocatePagedMemoryEx)
+#define gckOS_LockPages                 gcmHAL2D(gckOS_LockPages)
+#define gckOS_MapPages                  gcmHAL2D(gckOS_MapPages)
+#define gckOS_UnlockPages               gcmHAL2D(gckOS_UnlockPages)
+#define gckOS_FreePagedMemory           gcmHAL2D(gckOS_FreePagedMemory)
+#define gckOS_AllocateNonPagedMemory    gcmHAL2D(gckOS_AllocateNonPagedMemory)
+#define gckOS_FreeNonPagedMemory        gcmHAL2D(gckOS_FreeNonPagedMemory)
+#define gckOS_AllocateContiguous        gcmHAL2D(gckOS_AllocateContiguous)
+#define gckOS_FreeContiguous            gcmHAL2D(gckOS_FreeContiguous)
+#define gckOS_GetPageSize               gcmHAL2D(gckOS_GetPageSize)
+#define gckOS_GetPhysicalAddress        gcmHAL2D(gckOS_GetPhysicalAddress)
+#define gckOS_GetPhysicalAddressProcess     gcmHAL2D(gckOS_GetPhysicalAddressProcess)
+#define gckOS_MapPhysical                   gcmHAL2D(gckOS_MapPhysical)
+#define gckOS_UnmapPhysical             gcmHAL2D(gckOS_UnmapPhysical)
+#define gckOS_ReadRegister              gcmHAL2D(gckOS_ReadRegister)
+#define gckOS_WriteRegister             gcmHAL2D(gckOS_WriteRegister)
+#define gckOS_WriteMemory               gcmHAL2D(gckOS_WriteMemory)
+#define gckOS_MapMemory                 gcmHAL2D(gckOS_MapMemory)
+#define gckOS_UnmapMemory               gcmHAL2D(gckOS_UnmapMemory)
+#define gckOS_UnmapMemoryEx             gcmHAL2D(gckOS_UnmapMemoryEx)
+#define gckOS_CreateMutex               gcmHAL2D(gckOS_CreateMutex)
+#define gckOS_DeleteMutex               gcmHAL2D(gckOS_DeleteMutex)
+#define gckOS_AcquireMutex              gcmHAL2D(gckOS_AcquireMutex)
+#define gckOS_ReleaseMutex              gcmHAL2D(gckOS_ReleaseMutex)
+#define gckOS_AtomicExchange            gcmHAL2D(gckOS_AtomicExchange)
+#define gckOS_AtomicExchangePtr         gcmHAL2D(gckOS_AtomicExchangePtr)
+#define gckOS_AtomConstruct             gcmHAL2D(gckOS_AtomConstruct)
+#define gckOS_AtomDestroy               gcmHAL2D(gckOS_AtomDestroy)
+#define gckOS_AtomGet                   gcmHAL2D(gckOS_AtomGet)
+#define gckOS_AtomIncrement             gcmHAL2D(gckOS_AtomIncrement)
+#define gckOS_AtomDecrement             gcmHAL2D(gckOS_AtomDecrement)
+#define gckOS_Delay                     gcmHAL2D(gckOS_Delay)
+#define gckOS_GetTime                   gcmHAL2D(gckOS_GetTime)
+#define gckOS_MemoryBarrier             gcmHAL2D(gckOS_MemoryBarrier)
+#define gckOS_MapUserPointer            gcmHAL2D(gckOS_MapUserPointer)
+#define gckOS_UnmapUserPointer          gcmHAL2D(gckOS_UnmapUserPointer)
+#define gckOS_QueryNeedCopy             gcmHAL2D(gckOS_QueryNeedCopy)
+#define gckOS_CopyFromUserData          gcmHAL2D(gckOS_CopyFromUserData)
+#define gckOS_CopyToUserData            gcmHAL2D(gckOS_CopyToUserData)
+#define gckOS_MapUserPhysical           gcmHAL2D(gckOS_MapUserPhysical)
+#define gckOS_SuspendInterrupt          gcmHAL2D(gckOS_SuspendInterrupt)
+#define gckOS_ResumeInterrupt           gcmHAL2D(gckOS_ResumeInterrupt)
+#define gckOS_GetBaseAddress            gcmHAL2D(gckOS_GetBaseAddress)
+#define gckOS_MemCopy                   gcmHAL2D(gckOS_MemCopy)
+#define gckOS_ZeroMemory                gcmHAL2D(gckOS_ZeroMemory)
+#define gckOS_DeviceControl             gcmHAL2D(gckOS_DeviceControl)
+#define gckOS_GetProcessID              gcmHAL2D(gckOS_GetProcessID)
+#define gckOS_GetThreadID               gcmHAL2D(gckOS_GetThreadID)
+#define gckOS_CreateSignal              gcmHAL2D(gckOS_CreateSignal)
+#define gckOS_DestroySignal             gcmHAL2D(gckOS_DestroySignal)
+#define gckOS_Signal                    gcmHAL2D(gckOS_Signal)
+#define gckOS_WaitSignal                gcmHAL2D(gckOS_WaitSignal)
+#define gckOS_MapSignal                 gcmHAL2D(gckOS_MapSignal)
+#define gckOS_MapUserMemory             gcmHAL2D(gckOS_MapUserMemory)
+#define gckOS_UnmapUserMemory           gcmHAL2D(gckOS_UnmapUserMemory)
+#define gckOS_CreateUserSignal          gcmHAL2D(gckOS_CreateUserSignal)
+#define gckOS_DestroyUserSignal         gcmHAL2D(gckOS_DestroyUserSignal)
+#define gckOS_WaitUserSignal            gcmHAL2D(gckOS_WaitUserSignal)
+#define gckOS_SignalUserSignal          gcmHAL2D(gckOS_SignalUserSignal)
+#define gckOS_UserSignal                gcmHAL2D(gckOS_UserSignal)
+#define gckOS_UserSignal                gcmHAL2D(gckOS_UserSignal)
+#define gckOS_CacheClean                gcmHAL2D(gckOS_CacheClean)
+#define gckOS_CacheFlush                gcmHAL2D(gckOS_CacheFlush)
+#define gckOS_SetDebugLevel             gcmHAL2D(gckOS_SetDebugLevel)
+#define gckOS_SetDebugZone              gcmHAL2D(gckOS_SetDebugZone)
+#define gckOS_SetDebugLevelZone         gcmHAL2D(gckOS_SetDebugLevelZone)
+#define gckOS_SetDebugZones             gcmHAL2D(gckOS_SetDebugZones)
+#define gckOS_SetDebugFile              gcmHAL2D(gckOS_SetDebugFile)
+#define gckOS_Broadcast                 gcmHAL2D(gckOS_Broadcast)
+#define gckOS_SetGPUPower               gcmHAL2D(gckOS_SetGPUPower)
+#define gckOS_CreateSemaphore           gcmHAL2D(gckOS_CreateSemaphore)
+#define gckOS_DestroySemaphore          gcmHAL2D(gckOS_DestroySemaphore)
+#define gckOS_AcquireSemaphore          gcmHAL2D(gckOS_AcquireSemaphore)
+#define gckOS_ReleaseSemaphore          gcmHAL2D(gckOS_ReleaseSemaphore)
+#define gckHEAP_Construct               gcmHAL2D(gckHEAP_Construct)
+#define gckHEAP_Destroy                 gcmHAL2D(gckHEAP_Destroy)
+#define gckHEAP_Allocate                gcmHAL2D(gckHEAP_Allocate)
+#define gckHEAP_Free                    gcmHAL2D(gckHEAP_Free)
+#define gckHEAP_ProfileStart            gcmHAL2D(gckHEAP_ProfileStart)
+#define gckHEAP_ProfileEnd              gcmHAL2D(gckHEAP_ProfileEnd)
+#define gckHEAP_Test                    gcmHAL2D(gckHEAP_Test)
+#define gckVIDMEM_Construct             gcmHAL2D(gckVIDMEM_Construct)
+#define gckVIDMEM_Destroy               gcmHAL2D(gckVIDMEM_Destroy)
+#define gckVIDMEM_Allocate              gcmHAL2D(gckVIDMEM_Allocate)
+#define gckVIDMEM_AllocateLinear        gcmHAL2D(gckVIDMEM_AllocateLinear)
+#define gckVIDMEM_Free                  gcmHAL2D(gckVIDMEM_Free)
+#define gckVIDMEM_Lock                  gcmHAL2D(gckVIDMEM_Lock)
+#define gckVIDMEM_Unlock                gcmHAL2D(gckVIDMEM_Unlock)
+#define gckVIDMEM_ConstructVirtual      gcmHAL2D(gckVIDMEM_ConstructVirtual)
+#define gckVIDMEM_DestroyVirtual        gcmHAL2D(gckVIDMEM_DestroyVirtual)
+#define gckKERNEL_Construct             gcmHAL2D(gckKERNEL_Construct)
+#define gckKERNEL_Destroy               gcmHAL2D(gckKERNEL_Destroy)
+#define gckKERNEL_Dispatch              gcmHAL2D(gckKERNEL_Dispatch)
+#define gckKERNEL_QueryVideoMemory      gcmHAL2D(gckKERNEL_QueryVideoMemory)
+#define gckKERNEL_GetVideoMemoryPool    gcmHAL2D(gckKERNEL_GetVideoMemoryPool)
+#define gckKERNEL_MapVideoMemory        gcmHAL2D(gckKERNEL_MapVideoMemory)
+#define gckKERNEL_UnmapVideoMemory      gcmHAL2D(gckKERNEL_UnmapVideoMemory)
+#define gckKERNEL_MapMemory             gcmHAL2D(gckKERNEL_MapMemory)
+#define gckKERNEL_UnmapMemory           gcmHAL2D(gckKERNEL_UnmapMemory)
+#define gckKERNEL_Notify                gcmHAL2D(gckKERNEL_Notify)
+#define gckKERNEL_QuerySettings         gcmHAL2D(gckKERNEL_QuerySettings)
+#define gckKERNEL_Recovery              gcmHAL2D(gckKERNEL_Recovery)
+#define gckKERNEL_OpenUserData          gcmHAL2D(gckKERNEL_OpenUserData)
+#define gckKERNEL_CloseUserData         gcmHAL2D(gckKERNEL_CloseUserData)
+#define gckHARDWARE_Construct           gcmHAL2D(gckHARDWARE_Construct)
+#define gckHARDWARE_Destroy             gcmHAL2D(gckHARDWARE_Destroy)
+#define gckHARDWARE_QuerySystemMemory   gcmHAL2D(gckHARDWARE_QuerySystemMemory)
+#define gckHARDWARE_BuildVirtualAddress     gcmHAL2D(gckHARDWARE_BuildVirtualAddress)
+#define gckHARDWARE_QueryCommandBuffer      gcmHAL2D(gckHARDWARE_QueryCommandBuffer)
+#define gckHARDWARE_WaitLink            gcmHAL2D(gckHARDWARE_WaitLink)
+#define gckHARDWARE_Execute             gcmHAL2D(gckHARDWARE_Execute)
+#define gckHARDWARE_End                 gcmHAL2D(gckHARDWARE_End)
+#define gckHARDWARE_Nop                 gcmHAL2D(gckHARDWARE_Nop)
+#define gckHARDWARE_Wait                gcmHAL2D(gckHARDWARE_Wait)
+#define gckHARDWARE_PipeSelect          gcmHAL2D(gckHARDWARE_PipeSelect)
+#define gckHARDWARE_Link                gcmHAL2D(gckHARDWARE_Link)
+#define gckHARDWARE_Event               gcmHAL2D(gckHARDWARE_Event)
+#define gckHARDWARE_QueryMemory         gcmHAL2D(gckHARDWARE_QueryMemory)
+#define gckHARDWARE_QueryChipIdentity   gcmHAL2D(gckHARDWARE_QueryChipIdentity)
+#define gckHARDWARE_QueryChipSpecs      gcmHAL2D(gckHARDWARE_QueryChipSpecs)
+#define gckHARDWARE_QueryShaderCaps     gcmHAL2D(gckHARDWARE_QueryShaderCaps)
+#define gckHARDWARE_ConvertFormat       gcmHAL2D(gckHARDWARE_ConvertFormat)
+#define gckHARDWARE_SplitMemory         gcmHAL2D(gckHARDWARE_SplitMemory)
+#define gckHARDWARE_AlignToTile         gcmHAL2D(gckHARDWARE_AlignToTile)
+#define gckHARDWARE_UpdateQueueTail     gcmHAL2D(gckHARDWARE_UpdateQueueTail)
+#define gckHARDWARE_ConvertLogical      gcmHAL2D(gckHARDWARE_ConvertLogical)
+#define gckHARDWARE_ConvertPhysical     gcmHAL2D(gckHARDWARE_ConvertPhysical)
+#define gckHARDWARE_Interrupt           gcmHAL2D(gckHARDWARE_Interrupt)
+#define gckHARDWARE_SetMMU              gcmHAL2D(gckHARDWARE_SetMMU)
+#define gckHARDWARE_FlushMMU            gcmHAL2D(gckHARDWARE_FlushMMU)
+#define gckHARDWARE_GetIdle             gcmHAL2D(gckHARDWARE_GetIdle)
+#define gckHARDWARE_Flush               gcmHAL2D(gckHARDWARE_Flush)
+#define gckHARDWARE_SetFastClear        gcmHAL2D(gckHARDWARE_SetFastClear)
+#define gckHARDWARE_ReadInterrupt       gcmHAL2D(gckHARDWARE_ReadInterrupt)
+#define gckHARDWARE_SetPowerManagementState         gcmHAL2D(gckHARDWARE_SetPowerManagementState)
+#define gckHARDWARE_QueryPowerManagementState       gcmHAL2D(gckHARDWARE_QueryPowerManagementState)
+#define gckHARDWARE_ProfileEngine2D     gcmHAL2D(gckHARDWARE_ProfileEngine2D)
+#define gckHARDWARE_InitializeHardware  gcmHAL2D(gckHARDWARE_InitializeHardware)
+#define gckHARDWARE_Reset               gcmHAL2D(gckHARDWARE_Reset)
+#define gckINTERRUPT_Construct          gcmHAL2D(gckINTERRUPT_Construct)
+#define gckINTERRUPT_Destroy            gcmHAL2D(gckINTERRUPT_Destroy)
+#define gckINTERRUPT_SetHandler         gcmHAL2D(gckINTERRUPT_SetHandler)
+#define gckINTERRUPT_Notify             gcmHAL2D(gckINTERRUPT_Notify)
+#define gckEVENT_Construct              gcmHAL2D(gckEVENT_Construct)
+#define gckEVENT_Destroy                gcmHAL2D(gckEVENT_Destroy)
+#define gckEVENT_AddList                gcmHAL2D(gckEVENT_AddList)
+#define gckEVENT_FreeNonPagedMemory     gcmHAL2D(gckEVENT_FreeNonPagedMemory)
+#define gckEVENT_FreeContiguousMemory   gcmHAL2D(gckEVENT_FreeContiguousMemory)
+#define gckEVENT_FreeVideoMemory        gcmHAL2D(gckEVENT_FreeVideoMemory)
+#define gckEVENT_Signal                 gcmHAL2D(gckEVENT_Signal)
+#define gckEVENT_Unlock                 gcmHAL2D(gckEVENT_Unlock)
+#define gckEVENT_Submit                 gcmHAL2D(gckEVENT_Submit)
+#define gckEVENT_Commit                 gcmHAL2D(gckEVENT_Commit)
+#define gckEVENT_Notify                 gcmHAL2D(gckEVENT_Notify)
+#define gckEVENT_Interrupt              gcmHAL2D(gckEVENT_Interrupt)
+#define gckCOMMAND_Construct            gcmHAL2D(gckCOMMAND_Construct)
+#define gckCOMMAND_Destroy              gcmHAL2D(gckCOMMAND_Destroy)
+#define gckCOMMAND_EnterCommit          gcmHAL2D(gckCOMMAND_EnterCommit)
+#define gckCOMMAND_ExitCommit           gcmHAL2D(gckCOMMAND_ExitCommit)
+#define gckCOMMAND_Start                gcmHAL2D(gckCOMMAND_Start)
+#define gckCOMMAND_Stop                 gcmHAL2D(gckCOMMAND_Stop)
+#define gckCOMMAND_Commit               gcmHAL2D(gckCOMMAND_Commit)
+#define gckCOMMAND_Reserve              gcmHAL2D(gckCOMMAND_Reserve)
+#define gckCOMMAND_Execute              gcmHAL2D(gckCOMMAND_Execute)
+#define gckCOMMAND_Stall                gcmHAL2D(gckCOMMAND_Stall)
+#define gckCOMMAND_Attach               gcmHAL2D(gckCOMMAND_Attach)
+#define gckCOMMAND_Detach               gcmHAL2D(gckCOMMAND_Detach)
+#define gckMMU_Construct                gcmHAL2D(gckMMU_Construct)
+#define gckMMU_Destroy                  gcmHAL2D(gckMMU_Destroy)
+#define gckMMU_AllocatePages            gcmHAL2D(gckMMU_AllocatePages)
+#define gckMMU_FreePages                gcmHAL2D(gckMMU_FreePages)
+#define gckMMU_InsertNode               gcmHAL2D(gckMMU_InsertNode)
+#define gckMMU_RemoveNode               gcmHAL2D(gckMMU_RemoveNode)
+#define gckMMU_FreeHandleMemory         gcmHAL2D(gckMMU_FreeHandleMemory)
+#define gckMMU_Test                     gcmHAL2D(gckMMU_Test)
+#define gckHARDWARE_QueryProfileRegisters     gcmHAL2D(gckHARDWARE_QueryProfileRegisters)
+
+
+#define FindMdlMap                      gcmHAL2D(FindMdlMap)
+#define OnProcessExit                   gcmHAL2D(OnProcessExit)
+
+#define gckGALDEVICE_Destroy            gcmHAL2D(gckGALDEVICE_Destroy)
+#define gckOS_Print                     gcmHAL2D(gckOS_Print)
+#define gckGALDEVICE_FreeMemory         gcmHAL2D(gckGALDEVICE_FreeMemory)
+#define gckGALDEVICE_AllocateMemory     gcmHAL2D(gckGALDEVICE_AllocateMemory)
+#define gckOS_DebugBreak                gcmHAL2D(gckOS_DebugBreak)
+#define gckGALDEVICE_Release_ISR        gcmHAL2D(gckGALDEVICE_Release_ISR)
+#define gckOS_Verify                    gcmHAL2D(gckOS_Verify)
+#define gckCOMMAND_Release              gcmHAL2D(gckCOMMAND_Release)
+#define gckGALDEVICE_Stop               gcmHAL2D(gckGALDEVICE_Stop)
+#define gckGALDEVICE_Construct          gcmHAL2D(gckGALDEVICE_Construct)
+#define gckOS_DebugFatal                gcmHAL2D(gckOS_DebugFatal)
+#define gckOS_DebugTrace                gcmHAL2D(gckOS_DebugTrace)
+#define gckHARDWARE_GetBaseAddress      gcmHAL2D(gckHARDWARE_GetBaseAddress)
+#define gckGALDEVICE_Setup_ISR          gcmHAL2D(gckGALDEVICE_Setup_ISR)
+#define gckKERNEL_AttachProcess         gcmHAL2D(gckKERNEL_AttachProcess)
+#define gckKERNEL_AttachProcessEx       gcmHAL2D(gckKERNEL_AttachProcessEx)
+#define gckGALDEVICE_Start_Thread       gcmHAL2D(gckGALDEVICE_Start_Thread)
+#define gckHARDWARE_QueryIdle           gcmHAL2D(gckHARDWARE_QueryIdle)
+#define gckGALDEVICE_Start              gcmHAL2D(gckGALDEVICE_Start)
+#define gckOS_GetKernelLogical          gcmHAL2D(gckOS_GetKernelLogical)
+#define gckOS_DebugTraceZone            gcmHAL2D(gckOS_DebugTraceZone)
+#define gckGALDEVICE_Stop_Thread        gcmHAL2D(gckGALDEVICE_Stop_Thread)
+#define gckHARDWARE_NeedBaseAddress     gcmHAL2D(gckHARDWARE_NeedBaseAddress)
+
+#endif
+
+#endif /* __gc_hal_rename_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h
new file mode 100644 (file)
index 0000000..8b97268
--- /dev/null
@@ -0,0 +1,969 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_types_h_
+#define __gc_hal_types_h_
+
+#include "gc_hal_version.h"
+#include "gc_hal_options.h"
+
+#ifdef _WIN32
+#pragma warning(disable:4127)   /* Conditional expression is constant (do { }
+                                ** while(0)). */
+#pragma warning(disable:4100)   /* Unreferenced formal parameter. */
+#pragma warning(disable:4204)   /* Non-constant aggregate initializer (C99). */
+#pragma warning(disable:4131)   /* Uses old-style declarator (for Bison and
+                                ** Flex generated files). */
+#pragma warning(disable:4206)   /* Translation unit is empty. */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+**  Platform macros.
+*/
+
+#if defined(__GNUC__)
+#   define gcdHAS_ELLIPSES      1       /* GCC always has it. */
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#   define gcdHAS_ELLIPSES      1       /* C99 has it. */
+#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
+#   define gcdHAS_ELLIPSES      1       /* MSVC 2007+ has it. */
+#elif defined(UNDER_CE)
+#if UNDER_CE >= 600
+#       define gcdHAS_ELLIPSES  1
+#   else
+#       define gcdHAS_ELLIPSES  0
+#   endif
+#else
+#   error "gcdHAS_ELLIPSES: Platform could not be determined"
+#endif
+
+/******************************************************************************\
+************************************ Keyword ***********************************
+\******************************************************************************/
+
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
+#   define gcmINLINE            inline      /* C99 keyword. */
+#elif defined(__GNUC__)
+#   define gcmINLINE            __inline__  /* GNU keyword. */
+#elif defined(_MSC_VER) || defined(UNDER_CE)
+#   define gcmINLINE            __inline    /* Internal keyword. */
+#else
+#   error "gcmINLINE: Platform could not be determined"
+#endif
+
+/* Possible debug flags. */
+#define gcdDEBUG_NONE           0
+#define gcdDEBUG_ALL            (1 << 0)
+#define gcdDEBUG_FATAL          (1 << 1)
+#define gcdDEBUG_TRACE          (1 << 2)
+#define gcdDEBUG_BREAK          (1 << 3)
+#define gcdDEBUG_ASSERT         (1 << 4)
+#define gcdDEBUG_CODE           (1 << 5)
+#define gcdDEBUG_STACK          (1 << 6)
+
+#define gcmIS_DEBUG(flag)       ( gcdDEBUG & (flag | gcdDEBUG_ALL) )
+
+#ifndef gcdDEBUG
+#if (defined(DBG) && DBG) || defined(DEBUG) || defined(_DEBUG)
+#       define gcdDEBUG         gcdDEBUG_ALL
+#   else
+#       define gcdDEBUG         gcdDEBUG_NONE
+#   endif
+#endif
+
+#ifdef _USRDLL
+#ifdef _MSC_VER
+#ifdef HAL_EXPORTS
+#           define HALAPI       __declspec(dllexport)
+#       else
+#           define HALAPI       __declspec(dllimport)
+#       endif
+#       define HALDECL          __cdecl
+#   else
+#ifdef HAL_EXPORTS
+#           define HALAPI
+#       else
+#           define HALAPI       extern
+#       endif
+#   endif
+#else
+#   define HALAPI
+#   define HALDECL
+#endif
+
+/******************************************************************************\
+********************************** Common Types ********************************
+\******************************************************************************/
+
+#define gcvFALSE                0
+#define gcvTRUE                 1
+
+#define gcvINFINITE             ((gctUINT32) ~0U)
+
+#define gcvINVALID_HANDLE       ((gctHANDLE) ~0U)
+
+typedef int                     gctBOOL;
+typedef gctBOOL *               gctBOOL_PTR;
+
+typedef int                     gctINT;
+typedef signed char             gctINT8;
+typedef signed short            gctINT16;
+typedef signed int              gctINT32;
+typedef signed long long        gctINT64;
+
+typedef gctINT *                gctINT_PTR;
+typedef gctINT8 *               gctINT8_PTR;
+typedef gctINT16 *              gctINT16_PTR;
+typedef gctINT32 *              gctINT32_PTR;
+typedef gctINT64 *              gctINT64_PTR;
+
+typedef unsigned int            gctUINT;
+typedef unsigned char           gctUINT8;
+typedef unsigned short          gctUINT16;
+typedef unsigned int            gctUINT32;
+typedef unsigned long long      gctUINT64;
+
+typedef gctUINT *               gctUINT_PTR;
+typedef gctUINT8 *              gctUINT8_PTR;
+typedef gctUINT16 *             gctUINT16_PTR;
+typedef gctUINT32 *             gctUINT32_PTR;
+typedef gctUINT64 *             gctUINT64_PTR;
+
+typedef unsigned long           gctSIZE_T;
+typedef gctSIZE_T *             gctSIZE_T_PTR;
+
+#ifdef __cplusplus
+#   define gcvNULL              0
+#else
+#   define gcvNULL              ((void *) 0)
+#endif
+
+typedef float                   gctFLOAT;
+typedef signed int              gctFIXED_POINT;
+typedef float *                 gctFLOAT_PTR;
+
+typedef void *                  gctPHYS_ADDR;
+typedef void *                  gctHANDLE;
+typedef void *                  gctFILE;
+typedef void *                  gctSIGNAL;
+typedef void *                  gctWINDOW;
+typedef void *                  gctIMAGE;
+
+typedef void *                                 gctSEMAPHORE;
+
+typedef void *                  gctPOINTER;
+typedef const void *            gctCONST_POINTER;
+
+typedef char                    gctCHAR;
+typedef char *                  gctSTRING;
+typedef const char *            gctCONST_STRING;
+
+typedef struct _gcsCOUNT_STRING
+{
+    gctSIZE_T                   Length;
+    gctCONST_STRING             String;
+}
+gcsCOUNT_STRING;
+
+typedef union _gcuFLOAT_UINT32
+{
+    gctFLOAT    f;
+    gctUINT32   u;
+}
+gcuFLOAT_UINT32;
+
+/* Fixed point constants. */
+#define gcvZERO_X               ((gctFIXED_POINT) 0x00000000)
+#define gcvHALF_X               ((gctFIXED_POINT) 0x00008000)
+#define gcvONE_X                ((gctFIXED_POINT) 0x00010000)
+#define gcvNEGONE_X             ((gctFIXED_POINT) 0xFFFF0000)
+#define gcvTWO_X                ((gctFIXED_POINT) 0x00020000)
+
+/* Stringizing macro. */
+#define gcmSTRING(Value)        #Value
+
+/******************************************************************************\
+******************************* Fixed Point Math *******************************
+\******************************************************************************/
+
+#define gcmXMultiply(x1, x2)            gcoMATH_MultiplyFixed(x1, x2)
+#define gcmXDivide(x1, x2)              gcoMATH_DivideFixed(x1, x2)
+#define gcmXMultiplyDivide(x1, x2, x3)  gcoMATH_MultiplyDivideFixed(x1, x2, x3)
+
+/* 2D Engine profile. */
+typedef struct _gcs2D_PROFILE
+{
+    /* Cycle count.
+       32bit counter incremented every 2D clock cycle.
+       Wraps back to 0 when the counter overflows.
+    */
+    gctUINT32 cycleCount;
+
+    /* Pixels rendered by the 2D engine.
+       Resets to 0 every time it is read. */
+    gctUINT32 pixelsRendered;
+}
+gcs2D_PROFILE;
+
+/* Macro to combine four characters into a Charcater Code. */
+#define gcmCC(c1, c2, c3, c4) \
+( \
+    (char) (c1) \
+    | \
+    ((char) (c2) <<  8) \
+    | \
+    ((char) (c3) << 16) \
+    | \
+    ((char) (c4) << 24) \
+)
+
+#define gcmPRINTABLE(c)         ((((c) >= ' ') && ((c) <= '}')) ? ((c) != '%' ?  (c) : ' ') : ' ')
+
+#define gcmCC_PRINT(cc) \
+    gcmPRINTABLE((char) ( (cc)        & 0xFF)), \
+    gcmPRINTABLE((char) (((cc) >>  8) & 0xFF)), \
+    gcmPRINTABLE((char) (((cc) >> 16) & 0xFF)), \
+    gcmPRINTABLE((char) (((cc) >> 24) & 0xFF))
+
+/******************************************************************************\
+****************************** Function Parameters *****************************
+\******************************************************************************/
+
+#define IN
+#define OUT
+#define OPTIONAL
+
+/******************************************************************************\
+********************************* Status Codes *********************************
+\******************************************************************************/
+
+typedef enum _gceSTATUS
+{
+    gcvSTATUS_OK                    =   0,
+    gcvSTATUS_FALSE                 =   0,
+    gcvSTATUS_TRUE                  =   1,
+    gcvSTATUS_NO_MORE_DATA          =   2,
+    gcvSTATUS_CACHED                =   3,
+    gcvSTATUS_MIPMAP_TOO_LARGE      =   4,
+    gcvSTATUS_NAME_NOT_FOUND        =   5,
+    gcvSTATUS_NOT_OUR_INTERRUPT     =   6,
+    gcvSTATUS_MISMATCH              =   7,
+    gcvSTATUS_MIPMAP_TOO_SMALL      =   8,
+    gcvSTATUS_LARGER                =   9,
+    gcvSTATUS_SMALLER               =   10,
+    gcvSTATUS_CHIP_NOT_READY        =   11,
+    gcvSTATUS_NEED_CONVERSION       =   12,
+    gcvSTATUS_SKIP                  =   13,
+    gcvSTATUS_DATA_TOO_LARGE        =   14,
+    gcvSTATUS_INVALID_CONFIG        =   15,
+    gcvSTATUS_CHANGED               =   16,
+    gcvSTATUS_NOT_SUPPORT_DITHER    =   17,
+       gcvSTATUS_EXECUTED                              =       18,
+    gcvSTATUS_TERMINATE             =   19,
+
+    gcvSTATUS_INVALID_ARGUMENT      =   -1,
+    gcvSTATUS_INVALID_OBJECT        =   -2,
+    gcvSTATUS_OUT_OF_MEMORY         =   -3,
+    gcvSTATUS_MEMORY_LOCKED         =   -4,
+    gcvSTATUS_MEMORY_UNLOCKED       =   -5,
+    gcvSTATUS_HEAP_CORRUPTED        =   -6,
+    gcvSTATUS_GENERIC_IO            =   -7,
+    gcvSTATUS_INVALID_ADDRESS       =   -8,
+    gcvSTATUS_CONTEXT_LOSSED        =   -9,
+    gcvSTATUS_TOO_COMPLEX           =   -10,
+    gcvSTATUS_BUFFER_TOO_SMALL      =   -11,
+    gcvSTATUS_INTERFACE_ERROR       =   -12,
+    gcvSTATUS_NOT_SUPPORTED         =   -13,
+    gcvSTATUS_MORE_DATA             =   -14,
+    gcvSTATUS_TIMEOUT               =   -15,
+    gcvSTATUS_OUT_OF_RESOURCES      =   -16,
+    gcvSTATUS_INVALID_DATA          =   -17,
+    gcvSTATUS_INVALID_MIPMAP        =   -18,
+    gcvSTATUS_NOT_FOUND             =   -19,
+    gcvSTATUS_NOT_ALIGNED           =   -20,
+    gcvSTATUS_INVALID_REQUEST       =   -21,
+    gcvSTATUS_GPU_NOT_RESPONDING    =   -22,
+    gcvSTATUS_TIMER_OVERFLOW        =   -23,
+    gcvSTATUS_VERSION_MISMATCH      =   -24,
+    gcvSTATUS_LOCKED                =   -25,
+    gcvSTATUS_INTERRUPTED           =   -26,
+    gcvSTATUS_DEVICE                =   -27,
+
+    /* Linker errors. */
+    gcvSTATUS_GLOBAL_TYPE_MISMATCH  =   -1000,
+    gcvSTATUS_TOO_MANY_ATTRIBUTES   =   -1001,
+    gcvSTATUS_TOO_MANY_UNIFORMS     =   -1002,
+    gcvSTATUS_TOO_MANY_VARYINGS     =   -1003,
+    gcvSTATUS_UNDECLARED_VARYING    =   -1004,
+    gcvSTATUS_VARYING_TYPE_MISMATCH =   -1005,
+    gcvSTATUS_MISSING_MAIN          =   -1006,
+    gcvSTATUS_NAME_MISMATCH         =   -1007,
+    gcvSTATUS_INVALID_INDEX         =   -1008,
+}
+gceSTATUS;
+
+/******************************************************************************\
+********************************* Status Macros ********************************
+\******************************************************************************/
+
+#define gcmIS_ERROR(status)         (status < 0)
+#define gcmNO_ERROR(status)         (status >= 0)
+#define gcmIS_SUCCESS(status)       (status == gcvSTATUS_OK)
+
+/******************************************************************************\
+********************************* Field Macros *********************************
+\******************************************************************************/
+
+#define __gcmSTART(reg_field) \
+    (0 ? reg_field)
+
+#define __gcmEND(reg_field) \
+    (1 ? reg_field)
+
+#define __gcmGETSIZE(reg_field) \
+    (__gcmEND(reg_field) - __gcmSTART(reg_field) + 1)
+
+#define __gcmALIGN(data, reg_field) \
+    (((gctUINT32) (data)) << __gcmSTART(reg_field))
+
+#define __gcmMASK(reg_field) \
+    ((gctUINT32) ((__gcmGETSIZE(reg_field) == 32) \
+        ?  ~0 \
+        : (~(~0 << __gcmGETSIZE(reg_field)))))
+
+/*******************************************************************************
+**
+**  gcmFIELDMASK
+**
+**      Get aligned field mask.
+**
+**  ARGUMENTS:
+**
+**      reg     Name of register.
+**      field   Name of field within register.
+*/
+#define gcmFIELDMASK(reg, field) \
+( \
+    __gcmALIGN(__gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+**  gcmGETFIELD
+**
+**      Extract the value of a field from specified data.
+**
+**  ARGUMENTS:
+**
+**      data    Data value.
+**      reg     Name of register.
+**      field   Name of field within register.
+*/
+#define gcmGETFIELD(data, reg, field) \
+( \
+    ((((gctUINT32) (data)) >> __gcmSTART(reg##_##field)) \
+        & __gcmMASK(reg##_##field)) \
+)
+
+/*******************************************************************************
+**
+**  gcmSETFIELD
+**
+**      Set the value of a field within specified data.
+**
+**  ARGUMENTS:
+**
+**      data    Data value.
+**      reg     Name of register.
+**      field   Name of field within register.
+**      value   Value for field.
+*/
+#define gcmSETFIELD(data, reg, field, value) \
+( \
+    (((gctUINT32) (data)) \
+        & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
+        |  __gcmALIGN((gctUINT32) (value) \
+            & __gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+**  gcmSETFIELDVALUE
+**
+**      Set the value of a field within specified data with a
+**      predefined value.
+**
+**  ARGUMENTS:
+**
+**      data    Data value.
+**      reg     Name of register.
+**      field   Name of field within register.
+**      value   Name of the value within the field.
+*/
+#define gcmSETFIELDVALUE(data, reg, field, value) \
+( \
+    (((gctUINT32) (data)) \
+        & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
+        |  __gcmALIGN(reg##_##field##_##value \
+            & __gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+**  gcmGETMASKEDFIELDMASK
+**
+**      Determine field mask of a masked field.
+**
+**  ARGUMENTS:
+**
+**      reg     Name of register.
+**      field   Name of field within register.
+*/
+#define gcmGETMASKEDFIELDMASK(reg, field) \
+( \
+    gcmSETFIELD(0, reg,          field, ~0) | \
+    gcmSETFIELD(0, reg, MASK_ ## field, ~0)   \
+)
+
+/*******************************************************************************
+**
+**  gcmSETMASKEDFIELD
+**
+**      Set the value of a masked field with specified data.
+**
+**  ARGUMENTS:
+**
+**      reg     Name of register.
+**      field   Name of field within register.
+**      value   Value for field.
+*/
+#define gcmSETMASKEDFIELD(reg, field, value) \
+( \
+    gcmSETFIELD     (~0, reg,          field, value) & \
+    gcmSETFIELDVALUE(~0, reg, MASK_ ## field, ENABLED) \
+)
+
+/*******************************************************************************
+**
+**  gcmSETMASKEDFIELDVALUE
+**
+**      Set the value of a masked field with specified data.
+**
+**  ARGUMENTS:
+**
+**      reg     Name of register.
+**      field   Name of field within register.
+**      value   Value for field.
+*/
+#define gcmSETMASKEDFIELDVALUE(reg, field, value) \
+( \
+    gcmSETFIELDVALUE(~0, reg,          field, value) & \
+    gcmSETFIELDVALUE(~0, reg, MASK_ ## field, ENABLED) \
+)
+
+/*******************************************************************************
+**
+**  gcmVERIFYFIELDVALUE
+**
+**      Verify if the value of a field within specified data equals a
+**      predefined value.
+**
+**  ARGUMENTS:
+**
+**      data    Data value.
+**      reg     Name of register.
+**      field   Name of field within register.
+**      value   Name of the value within the field.
+*/
+#define gcmVERIFYFIELDVALUE(data, reg, field, value) \
+( \
+    (((gctUINT32) (data)) >> __gcmSTART(reg##_##field) & \
+                             __gcmMASK(reg##_##field)) \
+        == \
+    (reg##_##field##_##value & __gcmMASK(reg##_##field)) \
+)
+
+/*******************************************************************************
+**  Bit field macros.
+*/
+
+#define __gcmSTARTBIT(Field) \
+    ( 1 ? Field )
+
+#define __gcmBITSIZE(Field) \
+    ( 0 ? Field )
+
+#define __gcmBITMASK(Field) \
+( \
+    (1 << __gcmBITSIZE(Field)) - 1 \
+)
+
+#define gcmGETBITS(Value, Type, Field) \
+( \
+    ( ((Type) (Value)) >> __gcmSTARTBIT(Field) ) \
+    & \
+    __gcmBITMASK(Field) \
+)
+
+#define gcmSETBITS(Value, Type, Field, NewValue) \
+( \
+    ( ((Type) (Value)) \
+    & ~(__gcmBITMASK(Field) << __gcmSTARTBIT(Field)) \
+    ) \
+    | \
+    ( ( ((Type) (NewValue)) \
+      & __gcmBITMASK(Field) \
+      ) << __gcmSTARTBIT(Field) \
+    ) \
+)
+
+/*******************************************************************************
+**
+**  gcmISINREGRANGE
+**
+**      Verify whether the specified address is in the register range.
+**
+**  ARGUMENTS:
+**
+**      Address Address to be verified.
+**      Name    Name of a register.
+*/
+
+#define gcmISINREGRANGE(Address, Name) \
+( \
+    ((Address & (~0U << Name ## _LSB)) == (Name ## _Address >> 2)) \
+)
+
+/*******************************************************************************
+**
+**  A set of macros to aid state loading.
+**
+**  ARGUMENTS:
+**
+**      CommandBuffer   Pointer to a gcoCMDBUF object.
+**      StateDelta      Pointer to a gcsSTATE_DELTA state delta structure.
+**      Memory          Destination memory pointer of gctUINT32_PTR type.
+**      PartOfContext   Whether or not the state is a part of the context.
+**      FixedPoint      Whether or not the state is of the fixed point format.
+**      Count           Number of consecutive states to be loaded.
+**      Address         State address.
+**      Data            Data to be set to the state.
+*/
+
+/*----------------------------------------------------------------------------*/
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+
+#   define gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count) \
+        CommandBuffer->lastLoadStatePtr     = Memory; \
+        CommandBuffer->lastLoadStateAddress = Address; \
+        CommandBuffer->lastLoadStateCount   = Count
+
+#   define gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address) \
+        gcmASSERT( \
+            (gctUINT) (Memory  - CommandBuffer->lastLoadStatePtr - 1) \
+            == \
+            (gctUINT) (Address - CommandBuffer->lastLoadStateAddress) \
+            ); \
+        \
+        gcmASSERT(CommandBuffer->lastLoadStateCount > 0); \
+        \
+        CommandBuffer->lastLoadStateCount -= 1
+
+#   define gcmVERIFYLOADSTATEDONE(CommandBuffer) \
+        gcmASSERT(CommandBuffer->lastLoadStateCount == 0)
+
+#else
+
+#   define gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count)
+#   define gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address)
+#   define gcmVERIFYLOADSTATEDONE(CommandBuffer)
+
+#endif
+
+#if gcdSECURE_USER
+
+#   define gcmDEFINESECUREUSER() \
+        gctUINT         __secure_user_offset__; \
+        gctUINT32_PTR   __secure_user_hintArray__;
+
+#   define gcmBEGINSECUREUSER() \
+        __secure_user_offset__ = reserve->lastOffset; \
+        \
+        __secure_user_hintArray__ = reserve->hintArrayTail
+
+#   define gcmENDSECUREUSER() \
+        reserve->hintArrayTail = __secure_user_hintArray__
+
+#   define gcmSKIPSECUREUSER() \
+        __secure_user_offset__ += gcmSIZEOF(gctUINT32)
+
+#   define gcmUPDATESECUREUSER() \
+        *__secure_user_hintArray__ = __secure_user_offset__; \
+        \
+        __secure_user_offset__    += gcmSIZEOF(gctUINT32); \
+        __secure_user_hintArray__ += 1
+
+#else
+
+#   define gcmDEFINESECUREUSER()
+#   define gcmBEGINSECUREUSER()
+#   define gcmENDSECUREUSER()
+#   define gcmSKIPSECUREUSER()
+#   define gcmUPDATESECUREUSER()
+
+#endif
+
+/*----------------------------------------------------------------------------*/
+
+#if gcdDUMP
+#   define gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, Data) \
+        if (FixedPoint) \
+        { \
+            gcmDUMP(StateDelta->os, "@[state.x 0x%04X 0x%08X]", \
+                Address, Data \
+                ); \
+        } \
+        else \
+        { \
+            gcmDUMP(StateDelta->os, "@[state 0x%04X 0x%08X]", \
+                Address, Data \
+                ); \
+        }
+#else
+#   define gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, Data)
+#endif
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmDEFINESTATEBUFFER(CommandBuffer, StateDelta, Memory, ReserveSize) \
+    gcmDEFINESECUREUSER() \
+    gctSIZE_T ReserveSize; \
+    gcoCMDBUF CommandBuffer; \
+    gctUINT32_PTR Memory; \
+    gcsSTATE_DELTA_PTR StateDelta
+
+#define gcmBEGINSTATEBUFFER(Hardware, CommandBuffer, StateDelta, Memory, ReserveSize) \
+{ \
+    gcmONERROR(gcoBUFFER_Reserve( \
+        Hardware->buffer, ReserveSize, gcvTRUE, &CommandBuffer \
+        )); \
+    \
+    Memory = (gctUINT32_PTR) CommandBuffer->lastReserve; \
+    \
+    StateDelta = Hardware->delta; \
+    \
+    gcmBEGINSECUREUSER(); \
+}
+
+#define gcmENDSTATEBUFFER(CommandBuffer, Memory, ReserveSize) \
+{ \
+    gcmENDSECUREUSER(); \
+    \
+    gcmASSERT( \
+        ((gctUINT8_PTR) CommandBuffer->lastReserve) + ReserveSize \
+        == \
+         (gctUINT8_PTR) Memory \
+        ); \
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, Count) \
+{ \
+    gcmASSERT(((Memory - (gctUINT32_PTR) CommandBuffer->lastReserve) & 1) == 0); \
+    \
+    gcmVERIFYLOADSTATEDONE(CommandBuffer); \
+    \
+    gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count); \
+    \
+    *Memory++ \
+        = gcmSETFIELDVALUE(0, AQ_COMMAND_LOAD_STATE_COMMAND, OPCODE,  LOAD_STATE) \
+        | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, FLOAT,   FixedPoint) \
+        | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, COUNT,   Count) \
+        | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, ADDRESS, Address); \
+    \
+    gcmSKIPSECUREUSER(); \
+}
+
+#define gcmENDSTATEBATCH(CommandBuffer, Memory) \
+{ \
+    gcmVERIFYLOADSTATEDONE(CommandBuffer); \
+    \
+    gcmASSERT(((Memory - (gctUINT32_PTR) CommandBuffer->lastReserve) & 1) == 0); \
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmSETSTATEDATA(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                        Address, Data) \
+{ \
+    gctUINT32 __temp_data32__; \
+    \
+    gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
+    \
+    __temp_data32__ = Data; \
+    \
+    *Memory++ = __temp_data32__; \
+    \
+    gcoHARDWARE_UpdateDelta( \
+        StateDelta, FixedPoint, Address, 0, __temp_data32__ \
+        ); \
+    \
+    gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+    \
+    gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETCTRLSTATE(StateDelta, CommandBuffer, Memory, Address, Data) \
+{ \
+    gctUINT32 __temp_data32__; \
+    \
+    gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
+    \
+    __temp_data32__ = Data; \
+    \
+    *Memory++ = __temp_data32__; \
+    \
+    gcmDUMPSTATEDATA(StateDelta, gcvFALSE, Address, __temp_data32__); \
+    \
+    gcmSKIPSECUREUSER(); \
+}
+
+#define gcmSETFILLER(CommandBuffer, Memory) \
+{ \
+    gcmVERIFYLOADSTATEDONE(CommandBuffer); \
+    \
+    Memory += 1; \
+    \
+    gcmSKIPSECUREUSER(); \
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmSETSINGLESTATE(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                          Address, Data) \
+{ \
+    gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
+    gcmSETSTATEDATA(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                    Address, Data); \
+    gcmENDSTATEBATCH(CommandBuffer, Memory); \
+}
+
+#define gcmSETSINGLECTRLSTATE(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                              Address, Data) \
+{ \
+    gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
+    gcmSETCTRLSTATE(StateDelta, CommandBuffer, Memory, Address, Data); \
+    gcmENDSTATEBATCH(CommandBuffer, Memory); \
+}
+
+
+/*******************************************************************************
+**
+**  gcmSETSTARTDECOMMAND
+**
+**      Form a START_DE command.
+**
+**  ARGUMENTS:
+**
+**      Memory          Destination memory pointer of gctUINT32_PTR type.
+**      Count           Number of the rectangles.
+*/
+
+#define gcmSETSTARTDECOMMAND(Memory, Count) \
+{ \
+    *Memory++ \
+        = gcmSETFIELDVALUE(0, AQ_COMMAND_START_DE_COMMAND, OPCODE,     START_DE) \
+        | gcmSETFIELD     (0, AQ_COMMAND_START_DE_COMMAND, COUNT,      Count) \
+        | gcmSETFIELD     (0, AQ_COMMAND_START_DE_COMMAND, DATA_COUNT, 0); \
+    \
+    *Memory++ = 0xDEADDEED; \
+}
+
+/******************************************************************************\
+******************************** Ceiling Macro ********************************
+\******************************************************************************/
+#define gcmCEIL(x) ((x - (gctUINT32)x) == 0 ? (gctUINT32)x : (gctUINT32)x + 1)
+
+/******************************************************************************\
+******************************** Min/Max Macros ********************************
+\******************************************************************************/
+
+#define gcmMIN(x, y)            (((x) <= (y)) ?  (x) :  (y))
+#define gcmMAX(x, y)            (((x) >= (y)) ?  (x) :  (y))
+#define gcmCLAMP(x, min, max)   (((x) < (min)) ? (min) : \
+                                 ((x) > (max)) ? (max) : (x))
+#define gcmABS(x)               (((x) < 0)    ? -(x) :  (x))
+#define gcmNEG(x)               (((x) < 0)    ?  (x) : -(x))
+
+/*******************************************************************************
+**
+**  gcmPTR2INT
+**
+**      Convert a pointer to an integer value.
+**
+**  ARGUMENTS:
+**
+**      p       Pointer value.
+*/
+#if defined(_WIN32) || (defined(__LP64__) && __LP64__)
+#   define gcmPTR2INT(p) \
+    ( \
+        (gctUINT32) (gctUINT64) (p) \
+    )
+#else
+#   define gcmPTR2INT(p) \
+    ( \
+        (gctUINT32) (p) \
+    )
+#endif
+
+/*******************************************************************************
+**
+**  gcmINT2PTR
+**
+**      Convert an integer value into a pointer.
+**
+**  ARGUMENTS:
+**
+**      v       Integer value.
+*/
+#ifdef __LP64__
+#   define gcmINT2PTR(i) \
+    ( \
+        (gctPOINTER) (gctINT64) (i) \
+    )
+#else
+#   define gcmINT2PTR(i) \
+    ( \
+        (gctPOINTER) (i) \
+    )
+#endif
+
+/*******************************************************************************
+**
+**  gcmOFFSETOF
+**
+**      Compute the byte offset of a field inside a structure.
+**
+**  ARGUMENTS:
+**
+**      s       Structure name.
+**      field   Field name.
+*/
+#define gcmOFFSETOF(s, field) \
+( \
+    gcmPTR2INT(& (((struct s *) 0)->field)) \
+)
+
+/*******************************************************************************
+***** Database ****************************************************************/
+
+typedef struct _gcsDATABASE_COUNTERS
+{
+    /* Number of currently allocated bytes. */
+    gctSIZE_T                   bytes;
+
+    /* Maximum number of bytes allocated (memory footprint). */
+    gctSIZE_T                   maxBytes;
+
+    /* Total number of bytes allocated. */
+    gctSIZE_T                   totalBytes;
+}
+gcsDATABASE_COUNTERS;
+
+typedef struct _gcuDATABASE_INFO
+{
+    /* Counters. */
+    gcsDATABASE_COUNTERS        counters;
+
+    /* Time value. */
+    gctUINT64                   time;
+}
+gcuDATABASE_INFO;
+
+/*******************************************************************************
+***** Frame database **********************************************************/
+
+/* gcsHAL_FRAME_INFO */
+typedef struct _gcsHAL_FRAME_INFO
+{
+    /* Current timer tick. */
+    OUT gctUINT64               ticks;
+
+    /* Bandwidth counters. */
+    OUT gctUINT                 readBytes8[8];
+    OUT gctUINT                 writeBytes8[8];
+
+    /* Counters. */
+    OUT gctUINT                 cycles[8];
+    OUT gctUINT                 idleCycles[8];
+    OUT gctUINT                 mcCycles[8];
+    OUT gctUINT                 readRequests[8];
+    OUT gctUINT                 writeRequests[8];
+
+    /* 3D counters. */
+    OUT gctUINT                 vertexCount;
+    OUT gctUINT                 primitiveCount;
+    OUT gctUINT                 rejectedPrimitives;
+    OUT gctUINT                 culledPrimitives;
+    OUT gctUINT                 clippedPrimitives;
+    OUT gctUINT                 outPrimitives;
+    OUT gctUINT                 inPrimitives;
+    OUT gctUINT                 culledQuadCount;
+    OUT gctUINT                 totalQuadCount;
+    OUT gctUINT                 quadCount;
+    OUT gctUINT                 totalPixelCount;
+
+    /* PE counters. */
+    OUT gctUINT                 colorKilled[8];
+    OUT gctUINT                 colorDrawn[8];
+    OUT gctUINT                 depthKilled[8];
+    OUT gctUINT                 depthDrawn[8];
+
+    /* Shader counters. */
+    OUT gctUINT                 shaderCycles;
+    OUT gctUINT                 vsInstructionCount;
+    OUT gctUINT                 vsTextureCount;
+    OUT gctUINT                 psInstructionCount;
+    OUT gctUINT                 psTextureCount;
+
+    /* Texture counters. */
+    OUT gctUINT                 bilinearRequests;
+    OUT gctUINT                 trilinearRequests;
+    OUT gctUINT                 txBytes8;
+    OUT gctUINT                 txHitCount;
+    OUT gctUINT                 txMissCount;
+}
+gcsHAL_FRAME_INFO;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_types_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
new file mode 100644 (file)
index 0000000..a9a974e
--- /dev/null
@@ -0,0 +1,39 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_version_h_
+#define __gc_hal_version_h_
+
+#define gcvVERSION_MAJOR        4
+
+#define gcvVERSION_MINOR        5
+
+#define gcvVERSION_PATCH        0
+
+#define gcvVERSION_BUILD        1190
+
+#define gcvVERSION_DATE      __DATE__
+
+#define gcvVERSION_TIME      __TIME__
+
+#endif /* __gc_hal_version_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h
new file mode 100644 (file)
index 0000000..55cc74c
--- /dev/null
@@ -0,0 +1,825 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+
+
+#ifndef __gc_hal_vg_h_
+#define __gc_hal_vg_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include "gc_hal_rename.h"
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+#include "gc_hal_base.h"
+
+#if gcdENABLE_VG
+
+/* Thread routine type. */
+#if defined(LINUX)
+    typedef gctINT              gctTHREADFUNCRESULT;
+    typedef gctPOINTER          gctTHREADFUNCPARAMETER;
+#   define  gctTHREADFUNCTYPE
+#elif defined(WIN32)
+    typedef gctUINT             gctTHREADFUNCRESULT;
+    typedef gctPOINTER          gctTHREADFUNCPARAMETER;
+#   define  gctTHREADFUNCTYPE   __stdcall
+#endif
+
+typedef gctTHREADFUNCRESULT (gctTHREADFUNCTYPE * gctTHREADFUNC) (
+    gctTHREADFUNCPARAMETER ThreadParameter
+    );
+
+
+#if defined(gcvDEBUG)
+#   undef gcvDEBUG
+#endif
+
+#define gcdFORCE_DEBUG 0
+#define gcdFORCE_MESSAGES 0
+
+
+#if DBG || defined(DEBUG) || defined(_DEBUG) || gcdFORCE_DEBUG
+#   define gcvDEBUG 1
+#else
+#   define gcvDEBUG 0
+#endif
+
+#define _gcmERROR_RETURN(prefix, func) \
+    status = func; \
+    if (gcmIS_ERROR(status)) \
+    { \
+        prefix##PRINT_VERSION(); \
+        prefix##TRACE(gcvLEVEL_ERROR, \
+            #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
+            status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+        return status; \
+    } \
+    do { } while (gcvFALSE)
+
+#define gcmERROR_RETURN(func)         _gcmERROR_RETURN(gcm, func)
+
+#define gcmLOG_LOCATION()
+
+#define gcmkIS_ERROR(status)        (status < 0)
+
+#define gcmALIGNDOWN(n, align) \
+( \
+    (n) & ~((align) - 1) \
+)
+
+#define gcmIS_VALID_INDEX(Index, Array) \
+    (((gctUINT) (Index)) < gcmCOUNTOF(Array))
+
+
+#define gcmIS_NAN(x) \
+( \
+    ((* (gctUINT32_PTR) &(x)) & 0x7FFFFFFF) == 0x7FFFFFFF \
+)
+
+#define gcmLERP(v1, v2, w) \
+    ((v1) * (w) + (v2) * (1.0f - (w)))
+
+#define gcmINTERSECT(Start1, Start2, Length) \
+    (gcmABS((Start1) - (Start2)) < (Length))
+
+/*******************************************************************************
+**
+**  gcmERR_GOTO
+**
+**      Prints a message and terminates the current loop on error.
+**
+**  ASSUMPTIONS:
+**
+**      'status' variable of gceSTATUS type must be defined.
+**
+**  ARGUMENTS:
+**
+**      Function
+**          Function to evaluate.
+*/
+
+#define gcmERR_GOTO(Function) \
+    status = Function; \
+    if (gcmIS_ERROR(status)) \
+    { \
+        gcmTRACE( \
+            gcvLEVEL_ERROR, \
+            "gcmERR_GOTO: status=%d @ line=%d in function %s.\n", \
+            status, __LINE__, __FUNCTION__ \
+            ); \
+        goto ErrorHandler; \
+    }
+
+#if gcvDEBUG || gcdFORCE_MESSAGES
+#   define gcmVERIFY_BOOLEAN(Expression) \
+        gcmASSERT( \
+            ( (Expression) == gcvFALSE ) || \
+            ( (Expression) == gcvTRUE  )    \
+            )
+#else
+#   define gcmVERIFY_BOOLEAN(Expression)
+#endif
+
+/*******************************************************************************
+**
+**  gcmVERIFYFIELDFIT
+**
+**      Verify whether the value fits in the field.
+**
+**  ARGUMENTS:
+**
+**      data    Data value.
+**      reg     Name of register.
+**      field   Name of field within register.
+**      value   Value for field.
+*/
+#define gcmVERIFYFIELDFIT(reg, field, value) \
+    gcmASSERT( \
+        (value) <= gcmFIELDMAX(reg, field) \
+        )
+/*******************************************************************************
+**
+**  gcmFIELDMAX
+**
+**      Get field maximum value.
+**
+**  ARGUMENTS:
+**
+**      reg     Name of register.
+**      field   Name of field within register.
+*/
+#define gcmFIELDMAX(reg, field) \
+( \
+    (gctUINT32) \
+        ( \
+        (__gcmGETSIZE(reg##_##field) == 32) \
+                ?  ~0 \
+                : (~(~0 << __gcmGETSIZE(reg##_##field))) \
+        ) \
+)
+
+
+/* ANSI C does not have the 'f' functions, define replacements here. */
+#define gcmSINF(x)                      ((gctFLOAT) sin(x))
+#define gcmCOSF(x)                      ((gctFLOAT) cos(x))
+#define gcmASINF(x)                     ((gctFLOAT) asin(x))
+#define gcmACOSF(x)                     ((gctFLOAT) acos(x))
+#define gcmSQRTF(x)                     ((gctFLOAT) sqrt(x))
+#define gcmFABSF(x)                     ((gctFLOAT) fabs(x))
+#define gcmFMODF(x, y)                  ((gctFLOAT) fmod((x), (y)))
+#define gcmCEILF(x)                     ((gctFLOAT) ceil(x))
+#define gcmFLOORF(x)                    ((gctFLOAT) floor(x))
+
+
+
+/* Fixed point constants. */
+#define gcvZERO_X               ((gctFIXED_POINT) 0x00000000)
+#define gcvHALF_X               ((gctFIXED_POINT) 0x00008000)
+#define gcvONE_X                ((gctFIXED_POINT) 0x00010000)
+#define gcvNEGONE_X             ((gctFIXED_POINT) 0xFFFF0000)
+#define gcvTWO_X                ((gctFIXED_POINT) 0x00020000)
+
+/* Integer constants. */
+#define gcvMAX_POS_INT          ((gctINT) 0x7FFFFFFF)
+#define gcvMAX_NEG_INT          ((gctINT) 0x80000000)
+
+/* Float constants. */
+#define gcvMAX_POS_FLOAT        ((gctFLOAT)  3.4028235e+038)
+#define gcvMAX_NEG_FLOAT        ((gctFLOAT) -3.4028235e+038)
+
+/******************************************************************************\
+***************************** Miscellaneous Macro ******************************
+\******************************************************************************/
+
+#define gcmKB2BYTES(Kilobyte) \
+( \
+    (Kilobyte) << 10 \
+)
+
+#define gcmMB2BYTES(Megabyte) \
+( \
+    (Megabyte) << 20 \
+)
+
+#define gcmMAT(Matrix, Row, Column) \
+( \
+    (Matrix) [(Row) * 3 + (Column)] \
+)
+
+#define gcmMAKE2CHAR(Char1, Char2) \
+( \
+    ((gctUINT16) (gctUINT8) (Char1) << 0) | \
+    ((gctUINT16) (gctUINT8) (Char2) << 8) \
+)
+
+#define gcmMAKE4CHAR(Char1, Char2, Char3, Char4) \
+( \
+    ((gctUINT32)(gctUINT8) (Char1) <<  0) | \
+    ((gctUINT32)(gctUINT8) (Char2) <<  8) | \
+    ((gctUINT32)(gctUINT8) (Char3) << 16) | \
+    ((gctUINT32)(gctUINT8) (Char4) << 24) \
+)
+
+/* some platforms need to fix the physical address for HW to access*/
+#define gcmFIXADDRESS(address) \
+(\
+    (address)\
+)
+/******************************************************************************\
+****************************** Kernel Debug Macro ******************************
+\******************************************************************************/
+
+/* Set signal to signaled state for specified process. */
+gceSTATUS
+gckOS_SetSignal(
+    IN gckOS Os,
+    IN gctHANDLE Process,
+    IN gctSIGNAL Signal
+    );
+
+/* Return the kernel logical pointer for the given physical one. */
+gceSTATUS
+gckOS_GetKernelLogical(
+    IN gckOS Os,
+    IN gctUINT32 Address,
+    OUT gctPOINTER * KernelPointer
+    );
+
+/* Return the kernel logical pointer for the given physical one. */
+gceSTATUS
+gckOS_GetKernelLogicalEx(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctUINT32 Address,
+    OUT gctPOINTER * KernelPointer
+    );
+
+/*----------------------------------------------------------------------------*/
+/*----------------------------- Semaphore Object -----------------------------*/
+
+/* Increment the value of a semaphore. */
+gceSTATUS
+gckOS_IncrementSemaphore(
+    IN gckOS Os,
+    IN gctSEMAPHORE Semaphore
+    );
+
+/* Decrement the value of a semaphore (waiting might occur). */
+gceSTATUS
+gckOS_DecrementSemaphore(
+    IN gckOS Os,
+    IN gctSEMAPHORE Semaphore
+    );
+
+
+/*----------------------------------------------------------------------------*/
+/*------------------------------- Thread Object ------------------------------*/
+
+/* Start a thread. */
+gceSTATUS
+gckOS_StartThread(
+    IN gckOS Os,
+    IN gctTHREADFUNC ThreadFunction,
+    IN gctPOINTER ThreadParameter,
+    OUT gctTHREAD * Thread
+    );
+
+/* Stop a thread. */
+gceSTATUS
+gckOS_StopThread(
+    IN gckOS Os,
+    IN gctTHREAD Thread
+    );
+
+/* Verify whether the thread is still running. */
+gceSTATUS
+gckOS_VerifyThread(
+    IN gckOS Os,
+    IN gctTHREAD Thread
+    );
+
+
+/* Construct a new gckVGKERNEL object. */
+gceSTATUS
+gckVGKERNEL_Construct(
+    IN gckOS Os,
+    IN gctPOINTER Context,
+    IN gckKERNEL  inKernel,
+    OUT gckVGKERNEL * Kernel
+    );
+
+/* Destroy an gckVGKERNEL object. */
+gceSTATUS
+gckVGKERNEL_Destroy(
+    IN gckVGKERNEL Kernel
+    );
+
+/* Allocate linear video memory. */
+gceSTATUS
+gckKERNEL_AllocateLinearMemory(
+    IN gckKERNEL Kernel,
+    IN OUT gcePOOL * Pool,
+    IN gctSIZE_T Bytes,
+    IN gctSIZE_T Alignment,
+    IN gceSURF_TYPE Type,
+    OUT gcuVIDMEM_NODE_PTR * Node
+    );
+
+/* Unmap memory. */
+gceSTATUS
+gckKERNEL_UnmapMemory(
+    IN gckKERNEL Kernel,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctPOINTER Logical
+    );
+
+/* Dispatch a user-level command. */
+gceSTATUS
+gckVGKERNEL_Dispatch(
+    IN gckKERNEL Kernel,
+    IN gctBOOL FromUser,
+    IN OUT struct _gcsHAL_INTERFACE * Interface
+    );
+
+/* Query command buffer requirements. */
+gceSTATUS
+gckKERNEL_QueryCommandBuffer(
+    IN gckKERNEL Kernel,
+    OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+    );
+
+/******************************************************************************\
+******************************* gckVGHARDWARE Object ******************************
+\******************************************************************************/
+
+/* Construct a new gckVGHARDWARE object. */
+gceSTATUS
+gckVGHARDWARE_Construct(
+    IN gckOS Os,
+    OUT gckVGHARDWARE * Hardware
+    );
+
+/* Destroy an gckVGHARDWARE object. */
+gceSTATUS
+gckVGHARDWARE_Destroy(
+    IN gckVGHARDWARE Hardware
+    );
+
+/* Query system memory requirements. */
+gceSTATUS
+gckVGHARDWARE_QuerySystemMemory(
+    IN gckVGHARDWARE Hardware,
+    OUT gctSIZE_T * SystemSize,
+    OUT gctUINT32 * SystemBaseAddress
+    );
+
+/* Build virtual address. */
+gceSTATUS
+gckVGHARDWARE_BuildVirtualAddress(
+    IN gckVGHARDWARE Hardware,
+    IN gctUINT32 Index,
+    IN gctUINT32 Offset,
+    OUT gctUINT32 * Address
+    );
+
+/* Kickstart the command processor. */
+gceSTATUS
+gckVGHARDWARE_Execute(
+    IN gckVGHARDWARE Hardware,
+    IN gctUINT32 Address,
+    IN gctSIZE_T Count
+    );
+
+/* Query the available memory. */
+gceSTATUS
+gckVGHARDWARE_QueryMemory(
+    IN gckVGHARDWARE Hardware,
+    OUT gctSIZE_T * InternalSize,
+    OUT gctUINT32 * InternalBaseAddress,
+    OUT gctUINT32 * InternalAlignment,
+    OUT gctSIZE_T * ExternalSize,
+    OUT gctUINT32 * ExternalBaseAddress,
+    OUT gctUINT32 * ExternalAlignment,
+    OUT gctUINT32 * HorizontalTileSize,
+    OUT gctUINT32 * VerticalTileSize
+    );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gckVGHARDWARE_QueryChipIdentity(
+    IN gckVGHARDWARE Hardware,
+    OUT gceCHIPMODEL* ChipModel,
+    OUT gctUINT32* ChipRevision,
+    OUT gctUINT32* ChipFeatures,
+    OUT gctUINT32* ChipMinorFeatures,
+    OUT gctUINT32* ChipMinorFeatures1
+    );
+
+/* Convert an API format. */
+gceSTATUS
+gckVGHARDWARE_ConvertFormat(
+    IN gckVGHARDWARE Hardware,
+    IN gceSURF_FORMAT Format,
+    OUT gctUINT32 * BitsPerPixel,
+    OUT gctUINT32 * BytesPerTile
+    );
+
+/* Split a harwdare specific address into API stuff. */
+gceSTATUS
+gckVGHARDWARE_SplitMemory(
+    IN gckVGHARDWARE Hardware,
+    IN gctUINT32 Address,
+    OUT gcePOOL * Pool,
+    OUT gctUINT32 * Offset
+    );
+
+/* Align size to tile boundary. */
+gceSTATUS
+gckVGHARDWARE_AlignToTile(
+    IN gckVGHARDWARE Hardware,
+    IN gceSURF_TYPE Type,
+    IN OUT gctUINT32_PTR Width,
+    IN OUT gctUINT32_PTR Height
+    );
+
+/* Convert logical address to hardware specific address. */
+gceSTATUS
+gckVGHARDWARE_ConvertLogical(
+    IN gckVGHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    OUT gctUINT32 * Address
+    );
+
+/* Program MMU. */
+gceSTATUS
+gckVGHARDWARE_SetMMU(
+    IN gckVGHARDWARE Hardware,
+    IN gctPOINTER Logical
+    );
+
+/* Flush the MMU. */
+gceSTATUS
+gckVGHARDWARE_FlushMMU(
+    IN gckVGHARDWARE Hardware
+    );
+
+/* Get idle register. */
+gceSTATUS
+gckVGHARDWARE_GetIdle(
+    IN gckVGHARDWARE Hardware,
+    OUT gctUINT32 * Data
+    );
+
+/* Flush the caches. */
+gceSTATUS
+gckVGHARDWARE_Flush(
+    IN gckVGHARDWARE Hardware,
+    IN gceKERNEL_FLUSH Flush,
+    IN gctPOINTER Logical,
+    IN OUT gctSIZE_T * Bytes
+    );
+
+/* Enable/disable fast clear. */
+gceSTATUS
+gckVGHARDWARE_SetFastClear(
+    IN gckVGHARDWARE Hardware,
+    IN gctINT Enable
+    );
+
+gceSTATUS
+gckVGHARDWARE_ReadInterrupt(
+    IN gckVGHARDWARE Hardware,
+    OUT gctUINT32_PTR IDs
+    );
+
+
+/******************************************************************************\
+*************************** Command Buffer Structures **************************
+\******************************************************************************/
+
+/* Vacant command buffer marker. */
+#define gcvVACANT_BUFFER        ((gcsCOMPLETION_SIGNAL_PTR) (1))
+
+/* Command buffer header. */
+typedef struct _gcsCMDBUFFER * gcsCMDBUFFER_PTR;
+typedef struct _gcsCMDBUFFER
+{
+    /* Pointer to the completion signal. */
+    gcsCOMPLETION_SIGNAL_PTR    completion;
+
+    /* The user sets this to the node of the container buffer whitin which
+       this particular command buffer resides. The kernel sets this to the
+       node of the internally allocated buffer. */
+    gcuVIDMEM_NODE_PTR          node;
+
+    /* Command buffer hardware address. */
+    gctUINT32                   address;
+
+    /* The offset of the buffer from the beginning of the header. */
+    gctUINT32                   bufferOffset;
+
+    /* Size of the area allocated for the data portion of this particular
+       command buffer (headers and tail reserves are excluded). */
+    gctSIZE_T                   size;
+
+    /* Offset into the buffer [0..size]; reflects exactly how much data has
+       been put into the command buffer. */
+    gctUINT                     offset;
+
+    /* The number of command units in the buffer for the hardware to
+       execute. */
+    gctSIZE_T                   dataCount;
+
+    /* MANAGED BY : user HAL (gcoBUFFER object).
+       USED BY    : user HAL (gcoBUFFER object).
+       Points to the immediate next allocated command buffer. */
+    gcsCMDBUFFER_PTR            nextAllocated;
+
+    /* MANAGED BY : user layers (HAL and drivers).
+       USED BY    : kernel HAL (gcoBUFFER object).
+       Points to the next subbuffer if any. A family of subbuffers are chained
+       together and are meant to be executed inseparably as a unit. Meaning
+       that context switching cannot occur while a chain of subbuffers is being
+       executed. */
+    gcsCMDBUFFER_PTR            nextSubBuffer;
+}
+gcsCMDBUFFER;
+
+/* Command queue element. */
+typedef struct _gcsVGCMDQUEUE
+{
+    /* Pointer to the command buffer header. */
+    gcsCMDBUFFER_PTR            commandBuffer;
+
+    /* Dynamic vs. static command buffer state. */
+    gctBOOL                     dynamic;
+}
+gcsVGCMDQUEUE;
+
+/* Context map entry. */
+typedef struct _gcsVGCONTEXT_MAP
+{
+    /* State index. */
+    gctUINT32                   index;
+
+    /* New state value. */
+    gctUINT32                   data;
+
+    /* Points to the next entry in the mod list. */
+    gcsVGCONTEXT_MAP_PTR            next;
+}
+gcsVGCONTEXT_MAP;
+
+/* gcsVGCONTEXT structure that holds the current context. */
+typedef struct _gcsVGCONTEXT
+{
+    /* Context ID. */
+    gctUINT64                   id;
+
+    /* State caching ebable flag. */
+    gctBOOL                     stateCachingEnabled;
+
+    /* Current pipe. */
+    gctUINT32                   currentPipe;
+
+    /* State map/mod buffer. */
+    gctSIZE_T                   mapFirst;
+    gctSIZE_T                   mapLast;
+    gcsVGCONTEXT_MAP_PTR            mapContainer;
+    gcsVGCONTEXT_MAP_PTR            mapPrev;
+    gcsVGCONTEXT_MAP_PTR            mapCurr;
+    gcsVGCONTEXT_MAP_PTR            firstPrevMap;
+    gcsVGCONTEXT_MAP_PTR            firstCurrMap;
+
+    /* Main context buffer. */
+    gcsCMDBUFFER_PTR            header;
+    gctUINT32_PTR               buffer;
+
+    /* Completion signal. */
+    gctHANDLE                   process;
+    gctSIGNAL                   signal;
+}
+gcsVGCONTEXT;
+
+/* User space task header. */
+typedef struct _gcsTASK * gcsTASK_PTR;
+typedef struct _gcsTASK
+{
+    /* Pointer to the next task for the same interrupt in user space. */
+    gcsTASK_PTR                 next;
+
+    /* Size of the task data that immediately follows the structure. */
+    gctUINT                     size;
+
+    /* Task data starts here. */
+    /* ... */
+}
+gcsTASK;
+
+/* User space task master table entry. */
+typedef struct _gcsTASK_MASTER_ENTRY * gcsTASK_MASTER_ENTRY_PTR;
+typedef struct _gcsTASK_MASTER_ENTRY
+{
+    /* Pointers to the head and to the tail of the task chain. */
+    gcsTASK_PTR                 head;
+    gcsTASK_PTR                 tail;
+}
+gcsTASK_MASTER_ENTRY;
+
+/* User space task master table entry. */
+typedef struct _gcsTASK_MASTER_TABLE
+{
+    /* Table with one entry per block. */
+    gcsTASK_MASTER_ENTRY        table[gcvBLOCK_COUNT];
+
+    /* The total number of tasks sckeduled. */
+    gctUINT                     count;
+
+    /* The total size of event data in bytes. */
+    gctUINT                     size;
+}
+gcsTASK_MASTER_TABLE;
+
+/******************************************************************************\
+***************************** gckVGINTERRUPT Object ******************************
+\******************************************************************************/
+
+typedef struct _gckVGINTERRUPT * gckVGINTERRUPT;
+
+typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
+    IN gckVGKERNEL Kernel
+    );
+
+gceSTATUS
+gckVGINTERRUPT_Construct(
+    IN gckVGKERNEL Kernel,
+    OUT gckVGINTERRUPT * Interrupt
+    );
+
+gceSTATUS
+gckVGINTERRUPT_Destroy(
+    IN gckVGINTERRUPT Interrupt
+    );
+
+gceSTATUS
+gckVGINTERRUPT_Enable(
+    IN gckVGINTERRUPT Interrupt,
+    IN OUT gctINT32_PTR Id,
+    IN gctINTERRUPT_HANDLER Handler
+    );
+
+gceSTATUS
+gckVGINTERRUPT_Disable(
+    IN gckVGINTERRUPT Interrupt,
+    IN gctINT32 Id
+    );
+
+gceSTATUS
+gckVGINTERRUPT_Enque(
+    IN gckVGINTERRUPT Interrupt
+    );
+
+gceSTATUS
+gckVGINTERRUPT_DumpState(
+    IN gckVGINTERRUPT Interrupt
+    );
+
+
+/******************************************************************************\
+******************************* gckVGCOMMAND Object *******************************
+\******************************************************************************/
+
+typedef struct _gckVGCOMMAND *      gckVGCOMMAND;
+
+/* Construct a new gckVGCOMMAND object. */
+gceSTATUS
+gckVGCOMMAND_Construct(
+    IN gckVGKERNEL Kernel,
+    IN gctUINT TaskGranularity,
+    IN gctUINT QueueSize,
+    OUT gckVGCOMMAND * Command
+    );
+
+/* Destroy an gckVGCOMMAND object. */
+gceSTATUS
+gckVGCOMMAND_Destroy(
+    IN gckVGCOMMAND Command
+    );
+
+/* Query command buffer attributes. */
+gceSTATUS
+gckVGCOMMAND_QueryCommandBuffer(
+    IN gckVGCOMMAND Command,
+    OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+    );
+
+/* Allocate a command queue. */
+gceSTATUS
+gckVGCOMMAND_Allocate(
+    IN gckVGCOMMAND Command,
+    IN gctSIZE_T Size,
+    OUT gcsCMDBUFFER_PTR * CommandBuffer,
+    OUT gctPOINTER * Data
+    );
+
+/* Release memory held by the command queue. */
+gceSTATUS
+gckVGCOMMAND_Free(
+    IN gckVGCOMMAND Command,
+    IN gcsCMDBUFFER_PTR CommandBuffer
+    );
+
+/* Schedule the command queue for execution. */
+gceSTATUS
+gckVGCOMMAND_Execute(
+    IN gckVGCOMMAND Command,
+    IN gcsCMDBUFFER_PTR CommandBuffer
+    );
+
+/* Commit a buffer to the command queue. */
+gceSTATUS
+gckVGCOMMAND_Commit(
+    IN gckVGCOMMAND Command,
+    IN gcsVGCONTEXT_PTR Context,
+    IN gcsVGCMDQUEUE_PTR Queue,
+    IN gctUINT EntryCount,
+    IN gcsTASK_MASTER_TABLE_PTR TaskTable
+    );
+
+/******************************************************************************\
+********************************* gckVGMMU Object ********************************
+\******************************************************************************/
+
+typedef struct _gckVGMMU *          gckVGMMU;
+
+/* Construct a new gckVGMMU object. */
+gceSTATUS
+gckVGMMU_Construct(
+    IN gckVGKERNEL Kernel,
+    IN gctSIZE_T MmuSize,
+    OUT gckVGMMU * Mmu
+    );
+
+/* Destroy an gckVGMMU object. */
+gceSTATUS
+gckVGMMU_Destroy(
+    IN gckVGMMU Mmu
+    );
+
+/* Allocate pages inside the MMU. */
+gceSTATUS
+gckVGMMU_AllocatePages(
+    IN gckVGMMU Mmu,
+    IN gctSIZE_T PageCount,
+    OUT gctPOINTER * PageTable,
+    OUT gctUINT32 * Address
+    );
+
+/* Remove a page table from the MMU. */
+gceSTATUS
+gckVGMMU_FreePages(
+    IN gckVGMMU Mmu,
+    IN gctPOINTER PageTable,
+    IN gctSIZE_T PageCount
+    );
+
+/* Set the MMU page with info. */
+gceSTATUS
+gckVGMMU_SetPage(
+   IN gckVGMMU Mmu,
+   IN gctUINT32 PageAddress,
+   IN gctUINT32 *PageEntry
+   );
+
+#endif /* gcdENABLE_VG */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __gc_hal_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h
new file mode 100644 (file)
index 0000000..a9b633e
--- /dev/null
@@ -0,0 +1,100 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_debug_h_
+#define __gc_hal_kernel_debug_h_
+
+#include <gc_hal_kernel_linux.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** OS-dependent Macros *****************************
+\******************************************************************************/
+
+typedef va_list gctARGUMENTS;
+
+#define gcmkARGUMENTS_START(Arguments, Pointer) \
+    va_start(Arguments, Pointer)
+
+#define gcmkARGUMENTS_END(Arguments) \
+    va_end(Arguments)
+
+#define gcmkDECLARE_LOCK(__spinLock__) \
+    static spinlock_t __spinLock__ = SPIN_LOCK_UNLOCKED;
+
+#define gcmkLOCKSECTION(__spinLock__) \
+    spin_lock(&__spinLock__)
+
+#define gcmkUNLOCKSECTION(__spinLock__) \
+    spin_unlock(&__spinLock__)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+#   define gcmkGETPROCESSID() \
+        task_tgid_vnr(current)
+#else
+#   define gcmkGETPROCESSID() \
+        current->tgid
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+#   define gcmkGETTHREADID() \
+        task_pid_vnr(current)
+#else
+#   define gcmkGETTHREADID() \
+        current->pid
+#endif
+
+#define gcmkOUTPUT_STRING(String) \
+    printk(String); \
+    touch_softlockup_watchdog()
+
+#define gcmkSPRINTF(Destination, Size, Message, Value) \
+    snprintf(Destination, Size, Message, Value)
+
+#define gcmkSPRINTF2(Destination, Size, Message, Value1, Value2) \
+    snprintf(Destination, Size, Message, Value1, Value2)
+
+#define gcmkSPRINTF3(Destination, Size, Message, Value1, Value2, Value3) \
+    snprintf(Destination, Size, Message, Value1, Value2, Value3)
+
+#define gcmkVSPRINTF(Destination, Size, Message, Arguments) \
+    vsnprintf(Destination, Size, Message, *(va_list *) &Arguments)
+
+#define gcmkSTRCAT(Destination, Size, String) \
+    strncat(Destination, String, Size)
+
+/* If not zero, forces data alignment in the variable argument list
+   by its individual size. */
+#define gcdALIGNBYSIZE      1
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_debug_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
new file mode 100644 (file)
index 0000000..fb4ccc5
--- /dev/null
@@ -0,0 +1,1577 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_linux.h"
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/slab.h>
+
+#define _GC_OBJ_ZONE    gcvZONE_DEVICE
+
+#ifdef FLAREON
+    static struct dove_gpio_irq_handler gc500_handle;
+#endif
+
+/******************************************************************************\
+*************************** Memory Allocation Wrappers *************************
+\******************************************************************************/
+
+static gceSTATUS
+_AllocateMemory(
+    IN gckGALDEVICE Device,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER *Logical,
+    OUT gctPHYS_ADDR *Physical,
+    OUT gctUINT32 *PhysAddr
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Device=0x%x Bytes=%lu", Device, Bytes);
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+    gcmkVERIFY_ARGUMENT(PhysAddr != NULL);
+
+    gcmkONERROR(gckOS_AllocateContiguous(
+        Device->os, gcvFALSE, &Bytes, Physical, Logical
+        ));
+
+    *PhysAddr = ((PLINUX_MDL)*Physical)->dmaHandle - Device->baseAddress;
+
+    /* Success. */
+    gcmkFOOTER_ARG(
+        "*Logical=0x%x *Physical=0x%x *PhysAddr=0x%08x",
+        *Logical, *Physical, *PhysAddr
+        );
+
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+static gceSTATUS
+_FreeMemory(
+    IN gckGALDEVICE Device,
+    IN gctPOINTER Logical,
+    IN gctPHYS_ADDR Physical)
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Device=0x%x Logical=0x%x Physical=0x%x",
+                   Device, Logical, Physical);
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    status = gckOS_FreeContiguous(
+        Device->os, Physical, Logical,
+        ((PLINUX_MDL) Physical)->numPages * PAGE_SIZE
+        );
+
+    gcmkFOOTER();
+    return status;
+}
+
+
+
+/******************************************************************************\
+******************************* Interrupt Handler ******************************
+\******************************************************************************/
+static irqreturn_t isrRoutine(int irq, void *ctxt)
+{
+    gceSTATUS status;
+    gckGALDEVICE device;
+
+    device = (gckGALDEVICE) ctxt;
+
+    /* Call kernel interrupt notification. */
+    status = gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvTRUE);
+
+    if (gcmIS_SUCCESS(status))
+    {
+        device->dataReadys[gcvCORE_MAJOR] = gcvTRUE;
+
+        up(&device->semas[gcvCORE_MAJOR]);
+
+        return IRQ_HANDLED;
+    }
+
+    return IRQ_NONE;
+}
+
+static int threadRoutine(void *ctxt)
+{
+    gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                   "Starting isr Thread with extension=%p",
+                   device);
+
+    for (;;)
+    {
+        static int down;
+
+        down = down_interruptible(&device->semas[gcvCORE_MAJOR]);
+        device->dataReadys[gcvCORE_MAJOR] = gcvFALSE;
+
+        if (device->killThread == gcvTRUE)
+        {
+            /* The daemon exits. */
+            while (!kthread_should_stop())
+            {
+                gckOS_Delay(device->os, 1);
+            }
+
+            return 0;
+        }
+
+        gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvFALSE);
+    }
+}
+
+static irqreturn_t isrRoutine2D(int irq, void *ctxt)
+{
+    gceSTATUS status;
+    gckGALDEVICE device;
+
+    device = (gckGALDEVICE) ctxt;
+
+    /* Call kernel interrupt notification. */
+    status = gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvTRUE);
+
+    if (gcmIS_SUCCESS(status))
+    {
+        device->dataReadys[gcvCORE_2D] = gcvTRUE;
+
+        up(&device->semas[gcvCORE_2D]);
+
+        return IRQ_HANDLED;
+    }
+
+    return IRQ_NONE;
+}
+
+static int threadRoutine2D(void *ctxt)
+{
+    gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                   "Starting isr Thread with extension=%p",
+                   device);
+
+    for (;;)
+    {
+        static int down;
+
+        down = down_interruptible(&device->semas[gcvCORE_2D]);
+        device->dataReadys[gcvCORE_2D] = gcvFALSE;
+
+        if (device->killThread == gcvTRUE)
+        {
+            /* The daemon exits. */
+            while (!kthread_should_stop())
+            {
+                gckOS_Delay(device->os, 1);
+            }
+
+            return 0;
+        }
+
+        gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvFALSE);
+    }
+}
+
+static irqreturn_t isrRoutineVG(int irq, void *ctxt)
+{
+#if gcdENABLE_VG
+    gceSTATUS status;
+    gckGALDEVICE device;
+
+    device = (gckGALDEVICE) ctxt;
+
+       /* Serve the interrupt. */
+       status = gckVGINTERRUPT_Enque(device->kernels[gcvCORE_VG]->vg->interrupt);
+
+       /* Determine the return value. */
+       return (status == gcvSTATUS_NOT_OUR_INTERRUPT)
+               ? IRQ_RETVAL(0)
+               : IRQ_RETVAL(1);
+#else
+    return IRQ_NONE;
+#endif
+}
+
+static int threadRoutineVG(void *ctxt)
+{
+    gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                   "Starting isr Thread with extension=%p",
+                   device);
+
+    for (;;)
+    {
+        static int down;
+
+        down = down_interruptible(&device->semas[gcvCORE_VG]);
+        device->dataReadys[gcvCORE_VG] = gcvFALSE;
+
+        if (device->killThread == gcvTRUE)
+        {
+            /* The daemon exits. */
+            while (!kthread_should_stop())
+            {
+                gckOS_Delay(device->os, 1);
+            }
+
+            return 0;
+        }
+
+        gckKERNEL_Notify(device->kernels[gcvCORE_VG], gcvNOTIFY_INTERRUPT, gcvFALSE);
+    }
+}
+
+#if gcdPOWEROFF_TIMEOUT
+/*
+** PM Thread Routine
+**/
+static int threadRoutinePM(void *ctxt)
+{
+    gckGALDEVICE device = (gckGALDEVICE) ctxt;
+    gckHARDWARE hardware = device->kernels[gcvCORE_MAJOR]->hardware;
+    gceCHIPPOWERSTATE state;
+
+    for(;;)
+    {
+        /* wait for idle */
+        gcmkVERIFY_OK(
+            gckOS_AcquireMutex(device->os, hardware->powerOffSema, gcvINFINITE));
+
+        /* We try to power off every 200 ms, until GPU is not idle */
+        do
+        {
+            if (device->killThread == gcvTRUE)
+            {
+                /* The daemon exits. */
+                while (!kthread_should_stop())
+                {
+                    gckOS_Delay(device->os, 1);
+                }
+                return 0;
+            }
+
+            gcmkVERIFY_OK(
+                gckHARDWARE_SetPowerManagementState(
+                    hardware,
+                    gcvPOWER_OFF_TIMEOUT));
+
+            /* relax cpu 200 ms before retry */
+            gckOS_Delay(device->os, 200);
+
+            gcmkVERIFY_OK(
+                gckHARDWARE_QueryPowerManagementState(hardware, &state));
+        }
+        while (state == gcvPOWER_IDLE);
+    }
+}
+#endif
+
+/******************************************************************************\
+******************************* gckGALDEVICE Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckGALDEVICE_Construct
+**
+**  Constructor.
+**
+**  INPUT:
+**
+**  OUTPUT:
+**
+**      gckGALDEVICE * Device
+**          Pointer to a variable receiving the gckGALDEVICE object pointer on
+**          success.
+*/
+gceSTATUS
+gckGALDEVICE_Construct(
+    IN gctINT IrqLine,
+    IN gctUINT32 RegisterMemBase,
+    IN gctSIZE_T RegisterMemSize,
+    IN gctINT IrqLine2D,
+    IN gctUINT32 RegisterMemBase2D,
+    IN gctSIZE_T RegisterMemSize2D,
+    IN gctINT IrqLineVG,
+    IN gctUINT32 RegisterMemBaseVG,
+    IN gctSIZE_T RegisterMemSizeVG,
+    IN gctUINT32 ContiguousBase,
+    IN gctSIZE_T ContiguousSize,
+    IN gctSIZE_T BankSize,
+    IN gctINT FastClear,
+    IN gctINT Compression,
+    IN gctUINT32 PhysBaseAddr,
+    IN gctUINT32 PhysSize,
+    IN gctINT Signal,
+    OUT gckGALDEVICE *Device
+    )
+{
+    gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
+    gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
+    gctUINT32 horizontalTileSize, verticalTileSize;
+    struct resource* mem_region;
+    gctUINT32 physAddr;
+    gctUINT32 physical;
+    gckGALDEVICE device;
+    gceSTATUS status;
+    gctINT32 i;
+    gceHARDWARE_TYPE type;
+    gckDB sharedDB = gcvNULL;
+
+    gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u "
+                   "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
+                   "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
+                   "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
+                   "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
+                   IrqLine, RegisterMemBase, RegisterMemSize,
+                   IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
+                   IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
+                   ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
+                   PhysBaseAddr, PhysSize, Signal);
+
+    /* Allocate device structure. */
+    device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL);
+
+    if (!device)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    memset(device, 0, sizeof(struct _gckGALDEVICE));
+
+    if (IrqLine != -1)
+    {
+        device->requestedRegisterMemBases[gcvCORE_MAJOR]    = RegisterMemBase;
+        device->requestedRegisterMemSizes[gcvCORE_MAJOR]    = RegisterMemSize;
+    }
+
+    if (IrqLine2D != -1)
+    {
+        device->requestedRegisterMemBases[gcvCORE_2D]       = RegisterMemBase2D;
+        device->requestedRegisterMemSizes[gcvCORE_2D]       = RegisterMemSize2D;
+    }
+
+    if (IrqLineVG != -1)
+    {
+        device->requestedRegisterMemBases[gcvCORE_VG]       = RegisterMemBaseVG;
+        device->requestedRegisterMemSizes[gcvCORE_VG]       = RegisterMemSizeVG;
+    }
+
+    device->requestedContiguousBase  = 0;
+    device->requestedContiguousSize  = 0;
+
+
+    for (i = 0; i < gcdCORE_COUNT; i++)
+    {
+        physical = device->requestedRegisterMemBases[i];
+
+        /* Set up register memory region. */
+        if (physical != 0)
+        {
+            mem_region = request_mem_region(
+                physical, device->requestedRegisterMemSizes[i], "galcore register region"
+                );
+
+            if (mem_region == gcvNULL)
+            {
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                    "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
+                    __FUNCTION__, __LINE__,
+                    physical, device->requestedRegisterMemSizes[i]
+                    );
+
+                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+            }
+
+            device->registerBases[i] = (gctPOINTER) ioremap_nocache(
+                physical, device->requestedRegisterMemSizes[i]);
+
+            if (device->registerBases[i] == gcvNULL)
+            {
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                    "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
+                    __FUNCTION__, __LINE__,
+                    physical, device->requestedRegisterMemSizes[i]
+                    );
+
+                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+            }
+
+            physical += device->requestedRegisterMemSizes[i];
+        }
+        else
+        {
+            device->registerBases[i] = gcvNULL;
+        }
+    }
+
+    /* Set the base address */
+    device->baseAddress = PhysBaseAddr;
+
+    /* Construct the gckOS object. */
+    gcmkONERROR(gckOS_Construct(device, &device->os));
+
+    if (IrqLine != -1)
+    {
+        /* Construct the gckKERNEL object. */
+        gcmkONERROR(gckKERNEL_Construct(
+            device->os, gcvCORE_MAJOR, device,
+            gcvNULL, &device->kernels[gcvCORE_MAJOR]));
+
+        sharedDB = device->kernels[gcvCORE_MAJOR]->db;
+
+        /* Initialize core mapping */
+        for (i = 0; i < 8; i++)
+        {
+            device->coreMapping[i] = gcvCORE_MAJOR;
+        }
+
+        /* Setup the ISR manager. */
+        gcmkONERROR(gckHARDWARE_SetIsrManager(
+            device->kernels[gcvCORE_MAJOR]->hardware,
+            (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
+            (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
+            device
+            ));
+
+        gcmkONERROR(gckHARDWARE_SetFastClear(
+            device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
+            ));
+
+
+#if COMMAND_PROCESSOR_VERSION == 1
+        /* Start the command queue. */
+        gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command));
+#endif
+    }
+    else
+    {
+        device->kernels[gcvCORE_MAJOR] = gcvNULL;
+    }
+
+    if (IrqLine2D != -1)
+    {
+        gcmkONERROR(gckKERNEL_Construct(
+            device->os, gcvCORE_2D, device,
+            sharedDB, &device->kernels[gcvCORE_2D]));
+
+        if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db;
+
+        /* Verify the hardware type */
+        gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type));
+
+        if (type != gcvHARDWARE_2D)
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): Unexpected hardware type: %d\n",
+                __FUNCTION__, __LINE__,
+                type
+                );
+
+            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+        }
+
+        /* Initialize core mapping */
+        if (device->kernels[gcvCORE_MAJOR] == gcvNULL)
+        {
+            for (i = 0; i < 8; i++)
+            {
+                device->coreMapping[i] = gcvCORE_2D;
+            }
+        }
+        else
+        {
+            device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D;
+        }
+
+        /* Setup the ISR manager. */
+        gcmkONERROR(gckHARDWARE_SetIsrManager(
+            device->kernels[gcvCORE_2D]->hardware,
+            (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR_2D,
+            (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR_2D,
+            device
+            ));
+
+#if COMMAND_PROCESSOR_VERSION == 1
+        /* Start the command queue. */
+        gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command));
+#endif
+    }
+    else
+    {
+        device->kernels[gcvCORE_2D] = gcvNULL;
+    }
+
+    if (IrqLineVG != -1)
+    {
+#if gcdENABLE_VG
+        gcmkONERROR(gckKERNEL_Construct(
+            device->os, gcvCORE_VG, device,
+            sharedDB, &device->kernels[gcvCORE_VG]));
+        /* Initialize core mapping */
+        if (device->kernels[gcvCORE_MAJOR] == gcvNULL
+            && device->kernels[gcvCORE_2D] == gcvNULL
+            )
+        {
+            for (i = 0; i < 8; i++)
+            {
+                device->coreMapping[i] = gcvCORE_VG;
+            }
+        }
+        else
+        {
+            device->coreMapping[gcvHARDWARE_VG] = gcvCORE_VG;
+        }
+
+#endif
+    }
+    else
+    {
+        device->kernels[gcvCORE_VG] = gcvNULL;
+    }
+
+    /* Initialize the ISR. */
+    device->irqLines[gcvCORE_MAJOR] = IrqLine;
+    device->irqLines[gcvCORE_2D]    = IrqLine2D;
+    device->irqLines[gcvCORE_VG]    = IrqLineVG;
+
+    /* Initialize the kernel thread semaphores. */
+    for (i = 0; i < gcdCORE_COUNT; i++)
+    {
+        if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
+    }
+
+    device->signal = Signal;
+
+    for (i = 0; i < gcdCORE_COUNT; i++)
+    {
+        if (device->kernels[i] != gcvNULL) break;
+    }
+
+    if (i == gcdCORE_COUNT) gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+
+#if gcdENABLE_VG
+    if (i == gcvCORE_VG)
+    {
+        /* Query the ceiling of the system memory. */
+        gcmkONERROR(gckVGHARDWARE_QuerySystemMemory(
+                device->kernels[i]->vg->hardware,
+                &device->systemMemorySize,
+                &device->systemMemoryBaseAddress
+                ));
+            /* query the amount of video memory */
+        gcmkONERROR(gckVGHARDWARE_QueryMemory(
+            device->kernels[i]->vg->hardware,
+            &device->internalSize, &internalBaseAddress, &internalAlignment,
+            &device->externalSize, &externalBaseAddress, &externalAlignment,
+            &horizontalTileSize, &verticalTileSize
+            ));
+    }
+    else
+#endif
+    {
+        /* Query the ceiling of the system memory. */
+        gcmkONERROR(gckHARDWARE_QuerySystemMemory(
+                device->kernels[i]->hardware,
+                &device->systemMemorySize,
+                &device->systemMemoryBaseAddress
+                ));
+
+            /* query the amount of video memory */
+        gcmkONERROR(gckHARDWARE_QueryMemory(
+            device->kernels[i]->hardware,
+            &device->internalSize, &internalBaseAddress, &internalAlignment,
+            &device->externalSize, &externalBaseAddress, &externalAlignment,
+            &horizontalTileSize, &verticalTileSize
+            ));
+    }
+
+
+    /* Set up the internal memory region. */
+    if (device->internalSize > 0)
+    {
+        status = gckVIDMEM_Construct(
+            device->os,
+            internalBaseAddress, device->internalSize, internalAlignment,
+            0, &device->internalVidMem
+            );
+
+        if (gcmIS_ERROR(status))
+        {
+            /* Error, disable internal heap. */
+            device->internalSize = 0;
+        }
+        else
+        {
+            /* Map internal memory. */
+            device->internalLogical
+                = (gctPOINTER) ioremap_nocache(physical, device->internalSize);
+
+            if (device->internalLogical == gcvNULL)
+            {
+                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+            }
+
+            device->internalPhysical = (gctPHYS_ADDR) physical;
+            physical += device->internalSize;
+        }
+    }
+
+    if (device->externalSize > 0)
+    {
+        /* create the external memory heap */
+        status = gckVIDMEM_Construct(
+            device->os,
+            externalBaseAddress, device->externalSize, externalAlignment,
+            0, &device->externalVidMem
+            );
+
+        if (gcmIS_ERROR(status))
+        {
+            /* Error, disable internal heap. */
+            device->externalSize = 0;
+        }
+        else
+        {
+            /* Map external memory. */
+            device->externalLogical
+                = (gctPOINTER) ioremap_nocache(physical, device->externalSize);
+
+            if (device->externalLogical == gcvNULL)
+            {
+                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+            }
+
+            device->externalPhysical = (gctPHYS_ADDR) physical;
+            physical += device->externalSize;
+        }
+    }
+
+    /* set up the contiguous memory */
+    device->contiguousSize = ContiguousSize;
+
+    if (ContiguousSize > 0)
+    {
+        if (ContiguousBase == 0)
+        {
+            while (device->contiguousSize > 0)
+            {
+                /* Allocate contiguous memory. */
+                status = _AllocateMemory(
+                    device,
+                    device->contiguousSize,
+                    &device->contiguousBase,
+                    &device->contiguousPhysical,
+                    &physAddr
+                    );
+
+                if (gcmIS_SUCCESS(status))
+                {
+                    status = gckVIDMEM_Construct(
+                        device->os,
+                        physAddr | device->systemMemoryBaseAddress,
+                        device->contiguousSize,
+                        64,
+                        BankSize,
+                        &device->contiguousVidMem
+                        );
+
+                    if (gcmIS_SUCCESS(status))
+                    {
+                        break;
+                    }
+
+                    gcmkONERROR(_FreeMemory(
+                        device,
+                        device->contiguousBase,
+                        device->contiguousPhysical
+                        ));
+
+                    device->contiguousBase     = gcvNULL;
+                    device->contiguousPhysical = gcvNULL;
+                }
+
+                if (device->contiguousSize <= (4 << 20))
+                {
+                    device->contiguousSize = 0;
+                }
+                else
+                {
+                    device->contiguousSize -= (4 << 20);
+                }
+            }
+        }
+        else
+        {
+            /* Create the contiguous memory heap. */
+            status = gckVIDMEM_Construct(
+                device->os,
+                (ContiguousBase - device->baseAddress) | device->systemMemoryBaseAddress,
+                 ContiguousSize,
+                64, BankSize,
+                &device->contiguousVidMem
+                );
+
+            if (gcmIS_ERROR(status))
+            {
+                /* Error, disable contiguous memory pool. */
+                device->contiguousVidMem = gcvNULL;
+                device->contiguousSize   = 0;
+            }
+            else
+            {
+                mem_region = request_mem_region(
+                    ContiguousBase, ContiguousSize, "galcore managed memory"
+                    );
+
+                if (mem_region == gcvNULL)
+                {
+                    gcmkTRACE_ZONE(
+                        gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                        "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
+                        __FUNCTION__, __LINE__,
+                        ContiguousSize, ContiguousBase
+                        );
+
+                    gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+                }
+
+                device->requestedContiguousBase  = ContiguousBase;
+                device->requestedContiguousSize  = ContiguousSize;
+
+                device->contiguousBase
+#if gcdPAGED_MEMORY_CACHEABLE
+                    = (gctPOINTER) ioremap_cached(ContiguousBase, ContiguousSize);
+#else
+                    = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize);
+#endif
+                if (device->contiguousBase == gcvNULL)
+                {
+                    device->contiguousVidMem = gcvNULL;
+                    device->contiguousSize = 0;
+
+                    gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+                }
+
+                device->contiguousPhysical = (gctPHYS_ADDR) ContiguousBase;
+                device->contiguousSize     = ContiguousSize;
+                device->contiguousMapped   = gcvTRUE;
+            }
+        }
+    }
+
+    /* Return pointer to the device. */
+    * Device = device;
+
+    gcmkFOOTER_ARG("*Device=0x%x", * Device);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
+
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckGALDEVICE_Destroy
+**
+**  Class destructor.
+**
+**  INPUT:
+**
+**      Nothing.
+**
+**  OUTPUT:
+**
+**      Nothing.
+**
+**  RETURNS:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Destroy(
+    gckGALDEVICE Device)
+{
+    gctINT i;
+    gceSTATUS status = gcvSTATUS_OK;
+
+    gcmkHEADER_ARG("Device=0x%x", Device);
+
+    if (Device != gcvNULL)
+    {
+        for (i = 0; i < gcdCORE_COUNT; i++)
+        {
+            if (Device->kernels[i] != gcvNULL)
+            {
+                /* Destroy the gckKERNEL object. */
+                gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernels[i]));
+                Device->kernels[i] = gcvNULL;
+            }
+        }
+
+        {
+            if (Device->internalLogical != gcvNULL)
+            {
+                /* Unmap the internal memory. */
+                iounmap(Device->internalLogical);
+                Device->internalLogical = gcvNULL;
+            }
+
+            if (Device->internalVidMem != gcvNULL)
+            {
+                /* Destroy the internal heap. */
+                gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
+                Device->internalVidMem = gcvNULL;
+            }
+        }
+
+        {
+            if (Device->externalLogical != gcvNULL)
+            {
+                /* Unmap the external memory. */
+                iounmap(Device->externalLogical);
+                Device->externalLogical = gcvNULL;
+            }
+
+            if (Device->externalVidMem != gcvNULL)
+            {
+                /* destroy the external heap */
+                gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
+                Device->externalVidMem = gcvNULL;
+            }
+        }
+
+        {
+            if (Device->contiguousBase != gcvNULL)
+            {
+                if (Device->contiguousMapped)
+                {
+                    /* Unmap the contiguous memory. */
+                    iounmap(Device->contiguousBase);
+                }
+                else
+                {
+                    gcmkONERROR(_FreeMemory(
+                        Device,
+                        Device->contiguousBase,
+                        Device->contiguousPhysical
+                        ));
+                }
+
+                               if (Device->requestedContiguousBase != 0)
+                               {
+                                       release_mem_region(Device->requestedContiguousBase, Device->requestedContiguousSize);
+                               }
+
+                Device->contiguousBase     = gcvNULL;
+                Device->contiguousPhysical = gcvNULL;
+                Device->requestedContiguousBase = 0;
+                Device->requestedContiguousSize = 0;
+            }
+
+            if (Device->contiguousVidMem != gcvNULL)
+            {
+                /* Destroy the contiguous heap. */
+                gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
+                Device->contiguousVidMem = gcvNULL;
+            }
+        }
+
+        for (i = 0; i < gcdCORE_COUNT; i++)
+        {
+            if (Device->registerBases[i] != gcvNULL)
+            {
+                /* Unmap register memory. */
+                iounmap(Device->registerBases[i]);
+                           if (Device->requestedRegisterMemBases[i] != 0)
+                           {
+                                   release_mem_region(Device->requestedRegisterMemBases[i], Device->requestedRegisterMemSizes[i]);
+                           }
+
+                Device->registerBases[i] = gcvNULL;
+                Device->requestedRegisterMemBases[i] = 0;
+                Device->requestedRegisterMemSizes[i] = 0;
+            }
+        }
+
+        /* Destroy the gckOS object. */
+        if (Device->os != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_Destroy(Device->os));
+            Device->os = gcvNULL;
+        }
+
+        /* Free the device. */
+        kfree(Device);
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckGALDEVICE_Setup_ISR
+**
+**  Start the ISR routine.
+**
+**  INPUT:
+**
+**      gckGALDEVICE Device
+**          Pointer to an gckGALDEVICE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+**
+**  RETURNS:
+**
+**      gcvSTATUS_OK
+**          Setup successfully.
+**      gcvSTATUS_GENERIC_IO
+**          Setup failed.
+*/
+gceSTATUS
+gckGALDEVICE_Setup_ISR(
+    IN gckGALDEVICE Device
+    )
+{
+    gceSTATUS status;
+    gctINT ret;
+
+    gcmkHEADER_ARG("Device=0x%x", Device);
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    if (Device->irqLines[gcvCORE_MAJOR] < 0)
+    {
+        gcmkONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    /* Hook up the isr based on the irq line. */
+#ifdef FLAREON
+    gc500_handle.dev_name  = "galcore interrupt service";
+    gc500_handle.dev_id    = Device;
+    gc500_handle.handler   = isrRoutine;
+    gc500_handle.intr_gen  = GPIO_INTR_LEVEL_TRIGGER;
+    gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
+
+    ret = dove_gpio_request(
+        DOVE_GPIO0_7, &gc500_handle
+        );
+#else
+    ret = request_irq(
+        Device->irqLines[gcvCORE_MAJOR], isrRoutine, IRQF_DISABLED,
+        "galcore interrupt service", Device
+        );
+#endif
+
+    if (ret != 0)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): Could not register irq line %d (error=%d)\n",
+            __FUNCTION__, __LINE__,
+            Device->irqLines[gcvCORE_MAJOR], ret
+            );
+
+        gcmkONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    /* Mark ISR as initialized. */
+    Device->isrInitializeds[gcvCORE_MAJOR] = gcvTRUE;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckGALDEVICE_Setup_ISR_2D(
+    IN gckGALDEVICE Device
+    )
+{
+    gceSTATUS status;
+    gctINT ret;
+
+    gcmkHEADER_ARG("Device=0x%x", Device);
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    if (Device->irqLines[gcvCORE_2D] < 0)
+    {
+        gcmkONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    /* Hook up the isr based on the irq line. */
+#ifdef FLAREON
+    gc500_handle.dev_name  = "galcore interrupt service";
+    gc500_handle.dev_id    = Device;
+    gc500_handle.handler   = isrRoutine2D;
+    gc500_handle.intr_gen  = GPIO_INTR_LEVEL_TRIGGER;
+    gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
+
+    ret = dove_gpio_request(
+        DOVE_GPIO0_7, &gc500_handle
+        );
+#else
+    ret = request_irq(
+        Device->irqLines[gcvCORE_2D], isrRoutine2D, IRQF_DISABLED,
+        "galcore interrupt service for 2D", Device
+        );
+#endif
+
+    if (ret != 0)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): Could not register irq line %d (error=%d)\n",
+            __FUNCTION__, __LINE__,
+            Device->irqLines[gcvCORE_2D], ret
+            );
+
+        gcmkONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    /* Mark ISR as initialized. */
+    Device->isrInitializeds[gcvCORE_2D] = gcvTRUE;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckGALDEVICE_Setup_ISR_VG(
+    IN gckGALDEVICE Device
+    )
+{
+    gceSTATUS status;
+    gctINT ret;
+
+    gcmkHEADER_ARG("Device=0x%x", Device);
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    if (Device->irqLines[gcvCORE_VG] < 0)
+    {
+        gcmkONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    /* Hook up the isr based on the irq line. */
+#ifdef FLAREON
+    gc500_handle.dev_name  = "galcore interrupt service";
+    gc500_handle.dev_id    = Device;
+    gc500_handle.handler   = isrRoutineVG;
+    gc500_handle.intr_gen  = GPIO_INTR_LEVEL_TRIGGER;
+    gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
+
+    ret = dove_gpio_request(
+        DOVE_GPIO0_7, &gc500_handle
+        );
+#else
+    ret = request_irq(
+        Device->irqLines[gcvCORE_VG], isrRoutineVG, IRQF_DISABLED,
+        "galcore interrupt service for 2D", Device
+        );
+#endif
+
+    if (ret != 0)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): Could not register irq line %d (error=%d)\n",
+            __FUNCTION__, __LINE__,
+            Device->irqLines[gcvCORE_VG], ret
+            );
+
+        gcmkONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    /* Mark ISR as initialized. */
+    Device->isrInitializeds[gcvCORE_VG] = gcvTRUE;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckGALDEVICE_Release_ISR
+**
+**  Release the irq line.
+**
+**  INPUT:
+**
+**      gckGALDEVICE Device
+**          Pointer to an gckGALDEVICE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+**
+**  RETURNS:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Release_ISR(
+    IN gckGALDEVICE Device
+    )
+{
+    gcmkHEADER_ARG("Device=0x%x", Device);
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    /* release the irq */
+    if (Device->isrInitializeds[gcvCORE_MAJOR])
+    {
+#ifdef FLAREON
+        dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
+#else
+        free_irq(Device->irqLines[gcvCORE_MAJOR], Device);
+#endif
+
+           Device->isrInitializeds[gcvCORE_MAJOR] = gcvFALSE;
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckGALDEVICE_Release_ISR_2D(
+    IN gckGALDEVICE Device
+    )
+{
+    gcmkHEADER_ARG("Device=0x%x", Device);
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    /* release the irq */
+    if (Device->isrInitializeds[gcvCORE_2D])
+    {
+#ifdef FLAREON
+        dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
+#else
+        free_irq(Device->irqLines[gcvCORE_2D], Device);
+#endif
+
+           Device->isrInitializeds[gcvCORE_2D] = gcvFALSE;
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckGALDEVICE_Release_ISR_VG(
+    IN gckGALDEVICE Device
+    )
+{
+    gcmkHEADER_ARG("Device=0x%x", Device);
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    /* release the irq */
+    if (Device->isrInitializeds[gcvCORE_VG])
+    {
+#ifdef FLAREON
+        dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
+#else
+        free_irq(Device->irqLines[gcvCORE_VG], Device);
+#endif
+
+           Device->isrInitializeds[gcvCORE_VG] = gcvFALSE;
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckGALDEVICE_Start_Threads
+**
+**  Start the daemon threads.
+**
+**  INPUT:
+**
+**      gckGALDEVICE Device
+**          Pointer to an gckGALDEVICE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+**
+**  RETURNS:
+**
+**      gcvSTATUS_OK
+**          Start successfully.
+**      gcvSTATUS_GENERIC_IO
+**          Start failed.
+*/
+gceSTATUS
+gckGALDEVICE_Start_Threads(
+    IN gckGALDEVICE Device
+    )
+{
+    gceSTATUS status;
+    struct task_struct * task;
+
+    gcmkHEADER_ARG("Device=0x%x", Device);
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
+    {
+        /* Start the kernel thread. */
+        task = kthread_run(threadRoutine, Device, "galcore daemon thread");
+
+        if (IS_ERR(task))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): Could not start the kernel thread.\n",
+                __FUNCTION__, __LINE__
+                );
+
+            gcmkONERROR(gcvSTATUS_GENERIC_IO);
+        }
+
+        Device->threadCtxts[gcvCORE_MAJOR]          = task;
+        Device->threadInitializeds[gcvCORE_MAJOR]   = gcvTRUE;
+
+#if gcdPOWEROFF_TIMEOUT
+        /* Start the kernel thread. */
+        task = kthread_run(threadRoutinePM, Device, "galcore pm thread");
+
+        if (IS_ERR(task))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): Could not start the kernel thread.\n",
+                __FUNCTION__, __LINE__
+                );
+
+            gcmkONERROR(gcvSTATUS_GENERIC_IO);
+        }
+
+        Device->pmThreadCtxts          = task;
+        Device->pmThreadInitializeds   = gcvTRUE;
+#endif
+    }
+
+    if (Device->kernels[gcvCORE_2D] != gcvNULL)
+    {
+        /* Start the kernel thread. */
+        task = kthread_run(threadRoutine2D, Device, "galcore daemon thread for 2D");
+
+        if (IS_ERR(task))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): Could not start the kernel thread.\n",
+                __FUNCTION__, __LINE__
+                );
+
+            gcmkONERROR(gcvSTATUS_GENERIC_IO);
+        }
+
+        Device->threadCtxts[gcvCORE_2D]         = task;
+        Device->threadInitializeds[gcvCORE_2D]  = gcvTRUE;
+    }
+    else
+    {
+        Device->threadInitializeds[gcvCORE_2D]  = gcvFALSE;
+    }
+
+    if (Device->kernels[gcvCORE_VG] != gcvNULL)
+    {
+        /* Start the kernel thread. */
+        task = kthread_run(threadRoutineVG, Device, "galcore daemon thread for VG");
+
+        if (IS_ERR(task))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): Could not start the kernel thread.\n",
+                __FUNCTION__, __LINE__
+                );
+
+            gcmkONERROR(gcvSTATUS_GENERIC_IO);
+        }
+
+        Device->threadCtxts[gcvCORE_VG]         = task;
+        Device->threadInitializeds[gcvCORE_VG]  = gcvTRUE;
+    }
+    else
+    {
+        Device->threadInitializeds[gcvCORE_VG]  = gcvFALSE;
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckGALDEVICE_Stop_Threads
+**
+**  Stop the gal device, including the following actions: stop the daemon
+**  thread, release the irq.
+**
+**  INPUT:
+**
+**      gckGALDEVICE Device
+**          Pointer to an gckGALDEVICE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+**
+**  RETURNS:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Stop_Threads(
+    gckGALDEVICE Device
+    )
+{
+    gctINT i;
+
+    gcmkHEADER_ARG("Device=0x%x", Device);
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    for (i = 0; i < gcdCORE_COUNT; i++)
+    {
+        /* Stop the kernel threads. */
+        if (Device->threadInitializeds[i])
+        {
+            Device->killThread = gcvTRUE;
+            up(&Device->semas[i]);
+
+            kthread_stop(Device->threadCtxts[i]);
+            Device->threadCtxts[i]        = gcvNULL;
+            Device->threadInitializeds[i] = gcvFALSE;
+        }
+    }
+
+#if gcdPOWEROFF_TIMEOUT
+    /* Stop the kernel threads. */
+    if (Device->pmThreadInitializeds)
+    {
+        gckHARDWARE hardware = Device->kernels[gcvCORE_MAJOR]->hardware;
+        Device->killThread = gcvTRUE;
+        gckOS_ReleaseSemaphore(Device->os, hardware->powerOffSema);
+
+        kthread_stop(Device->pmThreadCtxts);
+        Device->pmThreadCtxts        = gcvNULL;
+        Device->pmThreadInitializeds = gcvFALSE;
+    }
+#endif
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckGALDEVICE_Start
+**
+**  Start the gal device, including the following actions: setup the isr routine
+**  and start the daemoni thread.
+**
+**  INPUT:
+**
+**      gckGALDEVICE Device
+**          Pointer to an gckGALDEVICE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+**
+**  RETURNS:
+**
+**      gcvSTATUS_OK
+**          Start successfully.
+*/
+gceSTATUS
+gckGALDEVICE_Start(
+    IN gckGALDEVICE Device
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Device=0x%x", Device);
+
+    /* Start the kernel thread. */
+    gcmkONERROR(gckGALDEVICE_Start_Threads(Device));
+
+    if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
+    {
+        /* Setup the ISR routine. */
+        gcmkONERROR(gckGALDEVICE_Setup_ISR(Device));
+
+        /* Switch to SUSPEND power state. */
+        gcmkONERROR(gckHARDWARE_SetPowerManagementState(
+            Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_SUSPEND_ATPOWERON
+            ));
+    }
+
+    if (Device->kernels[gcvCORE_2D] != gcvNULL)
+    {
+        /* Setup the ISR routine. */
+        gcmkONERROR(gckGALDEVICE_Setup_ISR_2D(Device));
+
+        /* Switch to SUSPEND power state. */
+        gcmkONERROR(gckHARDWARE_SetPowerManagementState(
+            Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_SUSPEND_ATPOWERON
+            ));
+    }
+
+    if (Device->kernels[gcvCORE_VG] != gcvNULL)
+    {
+        /* Setup the ISR routine. */
+        gcmkONERROR(gckGALDEVICE_Setup_ISR_VG(Device));
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckGALDEVICE_Stop
+**
+**  Stop the gal device, including the following actions: stop the daemon
+**  thread, release the irq.
+**
+**  INPUT:
+**
+**      gckGALDEVICE Device
+**          Pointer to an gckGALDEVICE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+**
+**  RETURNS:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Stop(
+    gckGALDEVICE Device
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Device=0x%x", Device);
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
+    {
+        /* Switch to OFF power state. */
+        gcmkONERROR(gckHARDWARE_SetPowerManagementState(
+            Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF
+            ));
+
+        /* Remove the ISR routine. */
+        gcmkONERROR(gckGALDEVICE_Release_ISR(Device));
+    }
+
+    if (Device->kernels[gcvCORE_2D] != gcvNULL)
+    {
+        /* Setup the ISR routine. */
+        gcmkONERROR(gckGALDEVICE_Release_ISR_2D(Device));
+
+        /* Switch to OFF power state. */
+        gcmkONERROR(gckHARDWARE_SetPowerManagementState(
+            Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF
+            ));
+    }
+
+    if (Device->kernels[gcvCORE_VG] != gcvNULL)
+    {
+        /* Setup the ISR routine. */
+        gcmkONERROR(gckGALDEVICE_Release_ISR_VG(Device));
+    }
+
+    /* Stop the kernel thread. */
+    gcmkONERROR(gckGALDEVICE_Stop_Threads(Device));
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
new file mode 100644 (file)
index 0000000..08c5e82
--- /dev/null
@@ -0,0 +1,167 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_device_h_
+#define __gc_hal_kernel_device_h_
+
+#ifdef ANDROID
+#define gcdkREPORT_VIDMEM_LEAK      0
+#else
+#define gcdkREPORT_VIDMEM_LEAK      1
+#endif
+
+/******************************************************************************\
+******************************* gckGALDEVICE Structure *******************************
+\******************************************************************************/
+
+typedef struct _gckGALDEVICE
+{
+    /* Objects. */
+    gckOS               os;
+    gckKERNEL           kernels[gcdCORE_COUNT];
+
+    /* Attributes. */
+    gctSIZE_T           internalSize;
+    gctPHYS_ADDR        internalPhysical;
+    gctPOINTER          internalLogical;
+    gckVIDMEM           internalVidMem;
+    gctSIZE_T           externalSize;
+    gctPHYS_ADDR        externalPhysical;
+    gctPOINTER          externalLogical;
+    gckVIDMEM           externalVidMem;
+    gckVIDMEM           contiguousVidMem;
+    gctPOINTER          contiguousBase;
+    gctPHYS_ADDR        contiguousPhysical;
+    gctSIZE_T           contiguousSize;
+    gctBOOL             contiguousMapped;
+    gctPOINTER          contiguousMappedUser;
+    gctSIZE_T           systemMemorySize;
+    gctUINT32           systemMemoryBaseAddress;
+    gctPOINTER          registerBases[gcdCORE_COUNT];
+    gctSIZE_T           registerSizes[gcdCORE_COUNT];
+    gctUINT32           baseAddress;
+    gctUINT32           requestedRegisterMemBases[gcdCORE_COUNT];
+    gctSIZE_T           requestedRegisterMemSizes[gcdCORE_COUNT];
+    gctUINT32           requestedContiguousBase;
+    gctSIZE_T           requestedContiguousSize;
+
+    /* IRQ management. */
+    gctINT              irqLines[gcdCORE_COUNT];
+    gctBOOL             isrInitializeds[gcdCORE_COUNT];
+    gctBOOL             dataReadys[gcdCORE_COUNT];
+
+    /* Thread management. */
+    struct task_struct  *threadCtxts[gcdCORE_COUNT];
+    struct semaphore    semas[gcdCORE_COUNT];
+    gctBOOL             threadInitializeds[gcdCORE_COUNT];
+    gctBOOL             killThread;
+
+    /* Signal management. */
+    gctINT              signal;
+
+    /* Core mapping */
+    gceCORE             coreMapping[8];
+
+#if gcdPOWEROFF_TIMEOUT
+    struct task_struct  *pmThreadCtxts;
+    gctBOOL             pmThreadInitializeds;
+#endif
+}
+* gckGALDEVICE;
+
+typedef struct _gcsHAL_PRIVATE_DATA
+{
+    gckGALDEVICE        device;
+    gctPOINTER          mappedMemory;
+    gctPOINTER          contiguousLogical;
+    /* The process opening the device may not be the same as the one that closes it. */
+    gctUINT32           pidOpen;
+}
+gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
+
+gceSTATUS gckGALDEVICE_Setup_ISR(
+    IN gckGALDEVICE Device
+    );
+
+gceSTATUS gckGALDEVICE_Setup_ISR_2D(
+    IN gckGALDEVICE Device
+    );
+
+gceSTATUS gckGALDEVICE_Setup_ISR_VG(
+    IN gckGALDEVICE Device
+    );
+
+gceSTATUS gckGALDEVICE_Release_ISR(
+    IN gckGALDEVICE Device
+    );
+
+gceSTATUS gckGALDEVICE_Release_ISR_2D(
+    IN gckGALDEVICE Device
+    );
+
+gceSTATUS gckGALDEVICE_Release_ISR_VG(
+    IN gckGALDEVICE Device
+    );
+
+gceSTATUS gckGALDEVICE_Start_Threads(
+    IN gckGALDEVICE Device
+    );
+
+gceSTATUS gckGALDEVICE_Stop_Threads(
+    gckGALDEVICE Device
+    );
+
+gceSTATUS gckGALDEVICE_Start(
+    IN gckGALDEVICE Device
+    );
+
+gceSTATUS gckGALDEVICE_Stop(
+    gckGALDEVICE Device
+    );
+
+gceSTATUS gckGALDEVICE_Construct(
+    IN gctINT IrqLine,
+    IN gctUINT32 RegisterMemBase,
+    IN gctSIZE_T RegisterMemSize,
+    IN gctINT IrqLine2D,
+    IN gctUINT32 RegisterMemBase2D,
+    IN gctSIZE_T RegisterMemSize2D,
+    IN gctINT IrqLineVG,
+    IN gctUINT32 RegisterMemBaseVG,
+    IN gctSIZE_T RegisterMemSizeVG,
+    IN gctUINT32 ContiguousBase,
+    IN gctSIZE_T ContiguousSize,
+    IN gctSIZE_T BankSize,
+    IN gctINT FastClear,
+    IN gctINT Compression,
+    IN gctUINT32 PhysBaseAddr,
+    IN gctUINT32 PhysSize,
+    IN gctINT Signal,
+    OUT gckGALDEVICE *Device
+    );
+
+gceSTATUS gckGALDEVICE_Destroy(
+    IN gckGALDEVICE Device
+    );
+
+#endif /* __gc_hal_kernel_device_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
new file mode 100644 (file)
index 0000000..a826b24
--- /dev/null
@@ -0,0 +1,1167 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*    Copyright (C) 2011 Freescale Semiconductor, Inc.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <mach/viv_gpu.h>
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_driver.h"
+
+#if USE_PLATFORM_DRIVER
+#   include <linux/platform_device.h>
+#endif
+
+#ifdef CONFIG_PXA_DVFM
+#   include <mach/dvfm.h>
+#   include <mach/pxa3xx_dvfm.h>
+#endif
+
+
+/* Zone used for header/footer. */
+#define _GC_OBJ_ZONE    gcvZONE_DRIVER
+
+MODULE_DESCRIPTION("Vivante Graphics Driver");
+MODULE_LICENSE("GPL");
+
+static struct class* gpuClass;
+
+static gckGALDEVICE galDevice;
+
+static int major = 199;
+module_param(major, int, 0644);
+
+static int irqLine = -1;
+module_param(irqLine, int, 0644);
+
+static long registerMemBase = 0x80000000;
+module_param(registerMemBase, long, 0644);
+
+static ulong registerMemSize = 256 << 10;
+module_param(registerMemSize, ulong, 0644);
+
+static int irqLine2D = -1;
+module_param(irqLine2D, int, 0644);
+
+static long registerMemBase2D = 0x00000000;
+module_param(registerMemBase2D, long, 0644);
+
+static ulong registerMemSize2D = 256 << 10;
+module_param(registerMemSize2D, ulong, 0644);
+
+static int irqLineVG = -1;
+module_param(irqLineVG, int, 0644);
+
+static long registerMemBaseVG = 0x00000000;
+module_param(registerMemBaseVG, long, 0644);
+
+static ulong registerMemSizeVG = 256 << 10;
+module_param(registerMemSizeVG, ulong, 0644);
+
+static long contiguousSize = 4 << 20;
+module_param(contiguousSize, long, 0644);
+
+static ulong contiguousBase = 0;
+module_param(contiguousBase, ulong, 0644);
+
+static long bankSize = 32 << 20;
+module_param(bankSize, long, 0644);
+
+static int fastClear = -1;
+module_param(fastClear, int, 0644);
+
+static int compression = -1;
+module_param(compression, int, 0644);
+
+static int signal = 48;
+module_param(signal, int, 0644);
+
+static ulong baseAddress = 0;
+module_param(baseAddress, ulong, 0644);
+
+static ulong physSize = 0;
+module_param(physSize, ulong, 0644);
+
+static int showArgs = 0;
+module_param(showArgs, int, 0644);
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER
+    unsigned long coreClock = 156000000;
+    module_param(coreClock, ulong, 0644);
+#endif
+
+static struct clk * clk_3d_core;
+static struct clk * clk_3d_shader;
+static struct clk * clk_2d_core;
+
+static int drv_open(
+    struct inode* inode,
+    struct file* filp
+    );
+
+static int drv_release(
+    struct inode* inode,
+    struct file* filp
+    );
+
+static long drv_ioctl(
+    struct file* filp,
+    unsigned int ioctlCode,
+    unsigned long arg
+    );
+
+static int drv_mmap(
+    struct file* filp,
+    struct vm_area_struct* vma
+    );
+
+static struct file_operations driver_fops =
+{
+    .open       = drv_open,
+    .release    = drv_release,
+    .unlocked_ioctl = drv_ioctl,
+    .mmap       = drv_mmap,
+};
+
+int drv_open(
+    struct inode* inode,
+    struct file* filp
+    )
+{
+    gceSTATUS status;
+    gctBOOL attached = gcvFALSE;
+    gcsHAL_PRIVATE_DATA_PTR data = gcvNULL;
+    gctINT i;
+
+    gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
+
+    if (filp == gcvNULL)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): filp is NULL\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    data = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL);
+
+    if (data == gcvNULL)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): private_data is NULL\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    data->device             = galDevice;
+    data->mappedMemory       = gcvNULL;
+    data->contiguousLogical  = gcvNULL;
+    gcmkONERROR(gckOS_GetProcessID(&data->pidOpen));
+
+    /* Attached the process. */
+    for (i = 0; i < gcdCORE_COUNT; i++)
+    {
+        if (galDevice->kernels[i] != gcvNULL)
+        {
+            gcmkONERROR(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvTRUE));
+        }
+    }
+    attached = gcvTRUE;
+
+    if (!galDevice->contiguousMapped)
+    {
+        gcmkONERROR(gckOS_MapMemory(
+            galDevice->os,
+            galDevice->contiguousPhysical,
+            galDevice->contiguousSize,
+            &data->contiguousLogical
+            ));
+    }
+
+    filp->private_data = data;
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return 0;
+
+OnError:
+    if (data != gcvNULL)
+    {
+        if (data->contiguousLogical != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_UnmapMemory(
+                galDevice->os,
+                galDevice->contiguousPhysical,
+                galDevice->contiguousSize,
+                data->contiguousLogical
+                ));
+        }
+
+        kfree(data);
+    }
+
+    if (attached)
+    {
+        for (i = 0; i < gcdCORE_COUNT; i++)
+        {
+            if (galDevice->kernels[i] != gcvNULL)
+            {
+                gcmkVERIFY_OK(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvFALSE));
+            }
+        }
+    }
+
+    gcmkFOOTER();
+    return -ENOTTY;
+}
+
+int drv_release(
+    struct inode* inode,
+    struct file* filp
+    )
+{
+    gceSTATUS status;
+    gcsHAL_PRIVATE_DATA_PTR data;
+    gckGALDEVICE device;
+    gctINT i;
+
+    gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
+
+    if (filp == gcvNULL)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): filp is NULL\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    data = filp->private_data;
+
+    if (data == gcvNULL)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): private_data is NULL\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    device = data->device;
+
+    if (device == gcvNULL)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): device is NULL\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    if (!device->contiguousMapped)
+    {
+        if (data->contiguousLogical != gcvNULL)
+        {
+                   gctUINT32 processID;
+            gcmkVERIFY_OK(gckOS_GetProcessID(&processID));
+            gcmkONERROR(gckOS_UnmapMemoryEx(
+                galDevice->os,
+                galDevice->contiguousPhysical,
+                galDevice->contiguousSize,
+                data->contiguousLogical,
+                data->pidOpen
+                ));
+
+            for (i = 0; i < gcdCORE_COUNT; i++)
+            {
+                if (galDevice->kernels[i] != gcvNULL)
+                {
+                    gcmkVERIFY_OK(
+                         gckKERNEL_RemoveProcessDB(galDevice->kernels[i],
+                                                   processID, gcvDB_MAP_MEMORY,
+                                                   data->contiguousLogical));
+                }
+            }
+
+            data->contiguousLogical = gcvNULL;
+        }
+    }
+
+    /* A process gets detached. */
+    for (i = 0; i < gcdCORE_COUNT; i++)
+    {
+        if (galDevice->kernels[i] != gcvNULL)
+        {
+            gcmkONERROR(gckKERNEL_AttachProcessEx(galDevice->kernels[i], gcvFALSE, data->pidOpen));
+        }
+    }
+
+    kfree(data);
+    filp->private_data = NULL;
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return 0;
+
+OnError:
+    gcmkFOOTER();
+    return -ENOTTY;
+}
+
+long drv_ioctl(
+    struct file* filp,
+    unsigned int ioctlCode,
+    unsigned long arg
+    )
+{
+    gceSTATUS status;
+    gcsHAL_INTERFACE iface;
+    gctUINT32 copyLen;
+    DRIVER_ARGS drvArgs;
+    gckGALDEVICE device;
+    gcsHAL_PRIVATE_DATA_PTR data;
+    gctINT32 i, count;
+
+    gcmkHEADER_ARG(
+        "filp=0x%08X ioctlCode=0x%08X arg=0x%08X",
+        filp, ioctlCode, arg
+        );
+
+    if (filp == gcvNULL)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): filp is NULL\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    data = filp->private_data;
+
+    if (data == gcvNULL)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): private_data is NULL\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    device = data->device;
+
+    if (device == gcvNULL)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): device is NULL\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    if ((ioctlCode != IOCTL_GCHAL_INTERFACE)
+    &&  (ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE)
+    )
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): unknown command %d\n",
+            __FUNCTION__, __LINE__,
+            ioctlCode
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    /* Get the drvArgs. */
+    copyLen = copy_from_user(
+        &drvArgs, (void *) arg, sizeof(DRIVER_ARGS)
+        );
+
+    if (copyLen != 0)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): error copying of the input arguments.\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    /* Now bring in the gcsHAL_INTERFACE structure. */
+    if ((drvArgs.InputBufferSize  != sizeof(gcsHAL_INTERFACE))
+    ||  (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE))
+    )
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): input or/and output structures are invalid.\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    copyLen = copy_from_user(
+        &iface, drvArgs.InputBuffer, sizeof(gcsHAL_INTERFACE)
+        );
+
+    if (copyLen != 0)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): error copying of input HAL interface.\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    if (iface.command == gcvHAL_CHIP_INFO)
+    {
+        count = 0;
+        for (i = 0; i < gcdCORE_COUNT; i++)
+        {
+            if (device->kernels[i] != gcvNULL)
+            {
+#if gcdENABLE_VG
+                if (i == gcvCORE_VG)
+                {
+                    iface.u.ChipInfo.types[count] = gcvHARDWARE_VG;
+                }
+                else
+#endif
+                {
+                    gcmkVERIFY_OK(gckHARDWARE_GetType(device->kernels[i]->hardware,
+                                                      &iface.u.ChipInfo.types[count]));
+                }
+                count++;
+            }
+        }
+
+        iface.u.ChipInfo.count = count;
+        status = gcvSTATUS_OK;
+    }
+    else
+    {
+        if (iface.hardwareType < 0 || iface.hardwareType > 7)
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): unknown hardwareType %d\n",
+                __FUNCTION__, __LINE__,
+                iface.hardwareType
+                );
+
+            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+        }
+
+#if gcdENABLE_VG
+        if (device->coreMapping[iface.hardwareType] == gcvCORE_VG)
+        {
+            status = gckVGKERNEL_Dispatch(device->kernels[gcvCORE_VG],
+                                        (ioctlCode == IOCTL_GCHAL_INTERFACE),
+                                        &iface);
+        }
+        else
+#endif
+        {
+            status = gckKERNEL_Dispatch(device->kernels[device->coreMapping[iface.hardwareType]],
+                                        (ioctlCode == IOCTL_GCHAL_INTERFACE),
+                                        &iface);
+        }
+    }
+
+    if (gcmIS_SUCCESS(status) && (iface.command == gcvHAL_LOCK_VIDEO_MEMORY))
+    {
+        /* Special case for mapped memory. */
+        if ((data->mappedMemory != gcvNULL)
+        &&  (iface.u.LockVideoMemory.node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+        )
+        {
+            /* Compute offset into mapped memory. */
+            gctUINT32 offset
+                = (gctUINT8 *) iface.u.LockVideoMemory.memory
+                - (gctUINT8 *) device->contiguousBase;
+
+            /* Compute offset into user-mapped region. */
+            iface.u.LockVideoMemory.memory =
+                (gctUINT8 *) data->mappedMemory + offset;
+        }
+    }
+
+    /* Copy data back to the user. */
+    copyLen = copy_to_user(
+        drvArgs.OutputBuffer, &iface, sizeof(gcsHAL_INTERFACE)
+        );
+
+    if (copyLen != 0)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): error copying of output HAL interface.\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return 0;
+
+OnError:
+    gcmkFOOTER();
+    return -ENOTTY;
+}
+
+static int drv_mmap(
+    struct file* filp,
+    struct vm_area_struct* vma
+    )
+{
+    gceSTATUS status;
+    gcsHAL_PRIVATE_DATA_PTR data;
+    gckGALDEVICE device;
+
+    gcmkHEADER_ARG("filp=0x%08X vma=0x%08X", filp, vma);
+
+    if (filp == gcvNULL)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): filp is NULL\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    data = filp->private_data;
+
+    if (data == gcvNULL)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): private_data is NULL\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    device = data->device;
+
+    if (device == gcvNULL)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): device is NULL\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+#if !gcdPAGED_MEMORY_CACHEABLE
+    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+    vma->vm_flags    |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND;
+#endif
+    vma->vm_pgoff     = 0;
+
+    if (device->contiguousMapped)
+    {
+        unsigned long size = vma->vm_end - vma->vm_start;
+
+        int ret = io_remap_pfn_range(
+            vma,
+            vma->vm_start,
+            (gctUINT32) device->contiguousPhysical >> PAGE_SHIFT,
+            size,
+            vma->vm_page_prot
+            );
+
+        if (ret != 0)
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): io_remap_pfn_range failed %d\n",
+                __FUNCTION__, __LINE__,
+                ret
+                );
+
+            data->mappedMemory = gcvNULL;
+
+            gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+        }
+
+        data->mappedMemory = (gctPOINTER) vma->vm_start;
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return 0;
+
+OnError:
+    gcmkFOOTER();
+    return -ENOTTY;
+}
+
+
+#if !USE_PLATFORM_DRIVER
+static int __init drv_init(void)
+#else
+static int drv_init(void)
+#endif
+{
+    int ret;
+    int result = -EINVAL;
+    gceSTATUS status;
+    gckGALDEVICE device = gcvNULL;
+    struct class* device_class = gcvNULL;
+
+    gcmkHEADER();
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
+    {
+# if 0
+        struct clk * clk;
+
+        clk = clk_get(NULL, "GCCLK");
+
+        if (IS_ERR(clk))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): clk get error: %d\n",
+                __FUNCTION__, __LINE__,
+                PTR_ERR(clk)
+                );
+
+            result = -ENODEV;
+            gcmkONERROR(gcvSTATUS_GENERIC_IO);
+        }
+
+        /*
+         * APMU_GC_156M, APMU_GC_312M, APMU_GC_PLL2, APMU_GC_PLL2_DIV2 currently.
+         * Use the 2X clock.
+         */
+        if (clk_set_rate(clk, coreClock * 2))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): Failed to set core clock.\n",
+                __FUNCTION__, __LINE__
+                );
+
+            result = -EAGAIN;
+            gcmkONERROR(gcvSTATUS_GENERIC_IO);
+        }
+
+        clk_enable(clk);
+
+#if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
+        gc_pwr(1);
+#   endif
+# else
+    if (irqLine != -1) {
+        clk_3d_core = clk_get(NULL, "gpu3d_clk");
+        if (!IS_ERR(clk_3d_core)) {
+            clk_3d_shader = clk_get(NULL, "gpu3d_shader_clk");
+            if (!IS_ERR(clk_3d_shader)) {
+                clk_enable(clk_3d_core);
+                clk_enable(clk_3d_shader);
+            } else {
+                irqLine = -1;
+                clk_put(clk_3d_core);
+                clk_3d_core = NULL;
+                clk_3d_shader = NULL;
+                printk(KERN_ERR "galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
+            }
+        } else {
+            irqLine = -1;
+            clk_3d_core = NULL;
+            printk(KERN_ERR "galcore: clk_get gpu3d_clk failed, disable 3d!\n");
+        }
+    }
+    if ((irqLine2D != -1) || (irqLineVG != -1)) {
+        clk_2d_core = clk_get(NULL, "gpu2d_clk");
+        if (IS_ERR(clk_2d_core)) {
+            irqLine2D = -1;
+            irqLineVG = -1;
+            clk_2d_core = NULL;
+            printk(KERN_ERR "galcore: clk_get 2d clock failed, disable 2d/vg!\n");
+        } else {
+            clk_enable(clk_2d_core);
+        }
+    }
+# endif
+    }
+#endif
+
+    if (showArgs)
+    {
+        printk("galcore options:\n");
+        printk("  irqLine           = %d\n",      irqLine);
+        printk("  registerMemBase   = 0x%08lX\n", registerMemBase);
+        printk("  registerMemSize   = 0x%08lX\n", registerMemSize);
+
+        if (irqLine2D != -1)
+        {
+            printk("  irqLine2D         = %d\n",      irqLine2D);
+            printk("  registerMemBase2D = 0x%08lX\n", registerMemBase2D);
+            printk("  registerMemSize2D = 0x%08lX\n", registerMemSize2D);
+        }
+
+        if (irqLineVG != -1)
+        {
+            printk("  irqLineVG         = %d\n",      irqLineVG);
+            printk("  registerMemBaseVG = 0x%08lX\n", registerMemBaseVG);
+            printk("  registerMemSizeVG = 0x%08lX\n", registerMemSizeVG);
+        }
+
+        printk("  contiguousSize    = %ld\n",     contiguousSize);
+        printk("  contiguousBase    = 0x%08lX\n", contiguousBase);
+        printk("  bankSize          = 0x%08lX\n", bankSize);
+        printk("  fastClear         = %d\n",      fastClear);
+        printk("  compression       = %d\n",      compression);
+        printk("  signal            = %d\n",      signal);
+        printk("  baseAddress       = 0x%08lX\n", baseAddress);
+        printk("  physSize          = 0x%08lX\n", physSize);
+#if ENABLE_GPU_CLOCK_BY_DRIVER
+        printk("  coreClock       = %lu\n",     coreClock);
+#endif
+    }
+
+    /* Create the GAL device. */
+    gcmkONERROR(gckGALDEVICE_Construct(
+        irqLine,
+        registerMemBase, registerMemSize,
+        irqLine2D,
+        registerMemBase2D, registerMemSize2D,
+        irqLineVG,
+        registerMemBaseVG, registerMemSizeVG,
+        contiguousBase, contiguousSize,
+        bankSize, fastClear, compression, baseAddress, physSize, signal,
+        &device
+        ));
+
+    /* Start the GAL device. */
+    gcmkONERROR(gckGALDEVICE_Start(device));
+
+    if ((physSize != 0)
+       && (device->kernels[gcvCORE_MAJOR] != gcvNULL)
+       && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0))
+    {
+        status = gckMMU_Enable(device->kernels[gcvCORE_MAJOR]->mmu, baseAddress, physSize);
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+            "Enable new MMU: status=%d\n", status);
+
+        if ((device->kernels[gcvCORE_2D] != gcvNULL)
+            && (device->kernels[gcvCORE_2D]->hardware->mmuVersion != 0))
+        {
+            status = gckMMU_Enable(device->kernels[gcvCORE_2D]->mmu, baseAddress, physSize);
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                "Enable new MMU for 2D: status=%d\n", status);
+        }
+
+        /* Reset the base address */
+        device->baseAddress = 0;
+    }
+
+    /* Register the character device. */
+    ret = register_chrdev(major, DRV_NAME, &driver_fops);
+
+    if (ret < 0)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): Could not allocate major number for mmap.\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    if (major == 0)
+    {
+        major = ret;
+    }
+
+    /* Create the device class. */
+    device_class = class_create(THIS_MODULE, "graphics_class");
+
+    if (IS_ERR(device_class))
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): Failed to create the class.\n",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+    }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+    device_create(device_class, NULL, MKDEV(major, 0), NULL, "galcore");
+#else
+    device_create(device_class, NULL, MKDEV(major, 0), "galcore");
+#endif
+
+    galDevice = device;
+    gpuClass  = device_class;
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_INFO, gcvZONE_DRIVER,
+        "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n",
+        __FUNCTION__, __LINE__,
+        irqLine, contiguousSize, registerMemBase
+        );
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return 0;
+
+OnError:
+    /* Roll back. */
+    if (device_class != gcvNULL)
+    {
+        device_destroy(device_class, MKDEV(major, 0));
+        class_destroy(device_class);
+    }
+
+    if (device != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckGALDEVICE_Stop(device));
+        gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
+    }
+
+    gcmkFOOTER();
+    return result;
+}
+
+#if !USE_PLATFORM_DRIVER
+static void __exit drv_exit(void)
+#else
+static void drv_exit(void)
+#endif
+{
+    gcmkHEADER();
+
+    gcmkASSERT(gpuClass != gcvNULL);
+    device_destroy(gpuClass, MKDEV(major, 0));
+    class_destroy(gpuClass);
+
+    unregister_chrdev(major, DRV_NAME);
+
+    gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice));
+    gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice));
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+    {
+# if 0
+        struct clk * clk = NULL;
+
+#if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
+        gc_pwr(0);
+#endif
+        clk = clk_get(NULL, "GCCLK");
+        clk_disable(clk);
+# else
+    if (clk_3d_core) {
+       clk_disable(clk_3d_core);
+       clk_put(clk_3d_core);
+       clk_3d_core = NULL;
+    }
+    if (clk_3d_shader) {
+       clk_disable(clk_3d_shader);
+       clk_put(clk_3d_shader);
+       clk_3d_shader = NULL;
+    }
+    if (clk_2d_core) {
+        clk_disable(clk_2d_core);
+        clk_put(clk_2d_core);
+        clk_2d_core = NULL;
+    }
+# endif
+    }
+#endif
+
+    gcmkFOOTER_NO();
+}
+
+#if !USE_PLATFORM_DRIVER
+    module_init(drv_init);
+    module_exit(drv_exit);
+#else
+
+#ifdef CONFIG_DOVE_GPU
+#   define DEVICE_NAME "dove_gpu"
+#else
+#   define DEVICE_NAME "galcore"
+#endif
+
+static int __devinit gpu_probe(struct platform_device *pdev)
+{
+    int ret = -ENODEV;
+    struct resource* res;
+    struct viv_gpu_platform_data *pdata;
+
+    gcmkHEADER();
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_3d");
+    if (res)
+        irqLine = res->start;
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_3d");
+    if (res)
+    {
+        registerMemBase = res->start;
+        registerMemSize = res->end - res->start + 1;
+    }
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_2d");
+    if (res)
+        irqLine2D = res->start;
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_2d");
+    if (res)
+    {
+        registerMemBase2D = res->start;
+        registerMemSize2D = res->end - res->start + 1;
+    }
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_vg");
+    if (res)
+        irqLineVG = res->start;
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_vg");
+    if (res)
+    {
+        registerMemBaseVG = res->start;
+        registerMemSizeVG = res->end - res->start + 1;
+    }
+
+    pdata = pdev->dev.platform_data;
+    if (pdata) {
+        contiguousBase = pdata->reserved_mem_base;
+        contiguousSize = pdata->reserved_mem_size;
+     }
+
+    ret = drv_init();
+
+    if (!ret)
+    {
+        platform_set_drvdata(pdev, galDevice);
+
+        gcmkFOOTER_NO();
+        return ret;
+    }
+
+    gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret);
+    return ret;
+}
+
+static int __devinit gpu_remove(struct platform_device *pdev)
+{
+    gcmkHEADER();
+    drv_exit();
+    gcmkFOOTER_NO();
+    return 0;
+}
+
+static int __devinit gpu_suspend(struct platform_device *dev, pm_message_t state)
+{
+    gceSTATUS status;
+    gckGALDEVICE device;
+    gctINT i;
+
+    device = platform_get_drvdata(dev);
+
+    for (i = 0; i < gcdCORE_COUNT; i++)
+    {
+        if (device->kernels[i] != gcvNULL)
+        {
+#if gcdENABLE_VG
+            if (i != gcvCORE_VG)
+#endif
+            {
+                status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF);
+
+                if (gcmIS_ERROR(status))
+                {
+                    return -1;
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int __devinit gpu_resume(struct platform_device *dev)
+{
+    gceSTATUS status;
+    gckGALDEVICE device;
+    gctINT i;
+
+    device = platform_get_drvdata(dev);
+
+    for (i = 0; i < gcdCORE_COUNT; i++)
+    {
+        if (device->kernels[i] != gcvNULL)
+        {
+#if gcdENABLE_VG
+            if (i != gcvCORE_VG)
+#endif
+            {
+                status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_ON);
+
+                if (gcmIS_ERROR(status))
+                {
+                    return -1;
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+static struct platform_driver gpu_driver = {
+    .probe      = gpu_probe,
+    .remove     = gpu_remove,
+
+    .suspend    = gpu_suspend,
+    .resume     = gpu_resume,
+
+    .driver     = {
+        .name   = DEVICE_NAME,
+    }
+};
+
+#if 0 /*CONFIG_DOVE_GPU*/
+static struct resource gpu_resources[] = {
+    {
+        .name   = "gpu_irq",
+        .flags  = IORESOURCE_IRQ,
+    },
+    {
+        .name   = "gpu_base",
+        .flags  = IORESOURCE_MEM,
+    },
+    {
+        .name   = "gpu_mem",
+        .flags  = IORESOURCE_MEM,
+    },
+};
+
+static struct platform_device * gpu_device;
+#endif
+
+static int __init gpu_init(void)
+{
+    int ret = 0;
+
+#if 0 /*ndef CONFIG_DOVE_GPU*/
+    gpu_resources[0].start = gpu_resources[0].end = irqLine;
+
+    gpu_resources[1].start = registerMemBase;
+    gpu_resources[1].end   = registerMemBase + registerMemSize - 1;
+
+    gpu_resources[2].start = contiguousBase;
+    gpu_resources[2].end   = contiguousBase + contiguousSize - 1;
+
+    /* Allocate device */
+    gpu_device = platform_device_alloc(DEVICE_NAME, -1);
+    if (!gpu_device)
+    {
+        printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
+        ret = -ENOMEM;
+        goto out;
+    }
+
+    /* Insert resource */
+    ret = platform_device_add_resources(gpu_device, gpu_resources, 3);
+    if (ret)
+    {
+        printk(KERN_ERR "galcore: platform_device_add_resources failed.\n");
+        goto put_dev;
+    }
+
+    /* Add device */
+    ret = platform_device_add(gpu_device);
+    if (ret)
+    {
+        printk(KERN_ERR "galcore: platform_device_add failed.\n");
+        goto put_dev;
+    }
+#endif
+
+    ret = platform_driver_register(&gpu_driver);
+    if (!ret)
+    {
+        goto out;
+    }
+
+#if 0 /*ndef CONFIG_DOVE_GPU*/
+    platform_device_del(gpu_device);
+put_dev:
+    platform_device_put(gpu_device);
+#endif
+
+out:
+    return ret;
+}
+
+static void __exit gpu_exit(void)
+{
+    platform_driver_unregister(&gpu_driver);
+#if 0 /*ndef CONFIG_DOVE_GPU*/
+    platform_device_unregister(gpu_device);
+#endif
+}
+
+module_init(gpu_init);
+module_exit(gpu_exit);
+
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c
new file mode 100644 (file)
index 0000000..497cf55
--- /dev/null
@@ -0,0 +1,470 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_linux.h"
+
+#define _GC_OBJ_ZONE    gcvZONE_KERNEL
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckKERNEL_QueryVideoMemory
+**
+**  Query the amount of video memory.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**  OUTPUT:
+**
+**      gcsHAL_INTERFACE * Interface
+**          Pointer to an gcsHAL_INTERFACE structure that will be filled in with
+**          the memory information.
+*/
+gceSTATUS
+gckKERNEL_QueryVideoMemory(
+    IN gckKERNEL Kernel,
+    OUT gcsHAL_INTERFACE * Interface
+    )
+{
+    gckGALDEVICE device;
+
+    gcmkHEADER_ARG("Kernel=%p", Kernel);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Interface != NULL);
+
+    /* Extract the pointer to the gckGALDEVICE class. */
+    device = (gckGALDEVICE) Kernel->context;
+
+    /* Get internal memory size and physical address. */
+    Interface->u.QueryVideoMemory.internalSize = device->internalSize;
+    Interface->u.QueryVideoMemory.internalPhysical = device->internalPhysical;
+
+    /* Get external memory size and physical address. */
+    Interface->u.QueryVideoMemory.externalSize = device->externalSize;
+    Interface->u.QueryVideoMemory.externalPhysical = device->externalPhysical;
+
+    /* Get contiguous memory size and physical address. */
+    Interface->u.QueryVideoMemory.contiguousSize = device->contiguousSize;
+    Interface->u.QueryVideoMemory.contiguousPhysical = device->contiguousPhysical;
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckKERNEL_GetVideoMemoryPool
+**
+**  Get the gckVIDMEM object belonging to the specified pool.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gcePOOL Pool
+**          Pool to query gckVIDMEM object for.
+**
+**  OUTPUT:
+**
+**      gckVIDMEM * VideoMemory
+**          Pointer to a variable that will hold the pointer to the gckVIDMEM
+**          object belonging to the requested pool.
+*/
+gceSTATUS
+gckKERNEL_GetVideoMemoryPool(
+    IN gckKERNEL Kernel,
+    IN gcePOOL Pool,
+    OUT gckVIDMEM * VideoMemory
+    )
+{
+    gckGALDEVICE device;
+    gckVIDMEM videoMemory;
+
+    gcmkHEADER_ARG("Kernel=%p Pool=%d", Kernel, Pool);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(VideoMemory != NULL);
+
+    /* Extract the pointer to the gckGALDEVICE class. */
+    device = (gckGALDEVICE) Kernel->context;
+
+    /* Dispatch on pool. */
+    switch (Pool)
+    {
+    case gcvPOOL_LOCAL_INTERNAL:
+        /* Internal memory. */
+        videoMemory = device->internalVidMem;
+        break;
+
+    case gcvPOOL_LOCAL_EXTERNAL:
+        /* External memory. */
+        videoMemory = device->externalVidMem;
+        break;
+
+    case gcvPOOL_SYSTEM:
+        /* System memory. */
+        videoMemory = device->contiguousVidMem;
+        break;
+
+    default:
+        /* Unknown pool. */
+        videoMemory = NULL;
+    }
+
+    /* Return pointer to the gckVIDMEM object. */
+    *VideoMemory = videoMemory;
+
+    /* Return status. */
+    gcmkFOOTER_ARG("*VideoMemory=%p", *VideoMemory);
+    return (videoMemory == NULL) ? gcvSTATUS_OUT_OF_MEMORY : gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckKERNEL_MapMemory
+**
+**  Map video memory into the current process space.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctPHYS_ADDR Physical
+**          Physical address of video memory to map.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to map.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Logical
+**          Pointer to a variable that will hold the base address of the mapped
+**          memory region.
+*/
+gceSTATUS
+gckKERNEL_MapMemory(
+    IN gckKERNEL Kernel,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Logical
+    )
+{
+    return gckOS_MapMemory(Kernel->os, Physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+**  gckKERNEL_UnmapMemory
+**
+**  Unmap video memory from the current process space.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctPHYS_ADDR Physical
+**          Physical address of video memory to map.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to map.
+**
+**      gctPOINTER Logical
+**          Base address of the mapped memory region.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckKERNEL_UnmapMemory(
+    IN gckKERNEL Kernel,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctPOINTER Logical
+    )
+{
+    return gckOS_UnmapMemory(Kernel->os, Physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+**  gckKERNEL_MapVideoMemory
+**
+**  Get the logical address for a hardware specific memory address for the
+**  current process.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctBOOL InUserSpace
+**          gcvTRUE to map the memory into the user space.
+**
+**      gctUINT32 Address
+**          Hardware specific memory address.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Logical
+**          Pointer to a variable that will hold the logical address of the
+**          specified memory address.
+*/
+gceSTATUS
+gckKERNEL_MapVideoMemoryEx(
+    IN gckKERNEL Kernel,
+    IN gceCORE Core,
+    IN gctBOOL InUserSpace,
+    IN gctUINT32 Address,
+    OUT gctPOINTER * Logical
+    )
+{
+    gckGALDEVICE device;
+    PLINUX_MDL mdl;
+    PLINUX_MDL_MAP mdlMap;
+    gcePOOL pool;
+    gctUINT32 offset, base;
+    gceSTATUS status;
+    gctPOINTER logical;
+
+    gcmkHEADER_ARG("Kernel=%p InUserSpace=%d Address=%08x",
+                   Kernel, InUserSpace, Address);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+    /* Extract the pointer to the gckGALDEVICE class. */
+    device = (gckGALDEVICE) Kernel->context;
+
+#if gcdENABLE_VG
+    if (Core == gcvCORE_VG)
+    {
+        /* Split the memory address into a pool type and offset. */
+        gcmkONERROR(
+            gckVGHARDWARE_SplitMemory(Kernel->vg->hardware, Address, &pool, &offset));
+    }
+    else
+#endif
+    {
+        /* Split the memory address into a pool type and offset. */
+        gcmkONERROR(
+            gckHARDWARE_SplitMemory(Kernel->hardware, Address, &pool, &offset));
+    }
+
+    /* Dispatch on pool. */
+    switch (pool)
+    {
+    case gcvPOOL_LOCAL_INTERNAL:
+        /* Internal memory. */
+        logical = device->internalLogical;
+        break;
+
+    case gcvPOOL_LOCAL_EXTERNAL:
+        /* External memory. */
+        logical = device->externalLogical;
+        break;
+
+    case gcvPOOL_SYSTEM:
+        /* System memory. */
+        if (device->contiguousMapped)
+        {
+            logical = device->contiguousBase;
+        }
+        else
+        {
+            gctINT processID;
+            gckOS_GetProcessID(&processID);
+
+            mdl = (PLINUX_MDL) device->contiguousPhysical;
+
+            mdlMap = FindMdlMap(mdl, processID);
+            gcmkASSERT(mdlMap);
+
+            logical = (gctPOINTER) mdlMap->vmaAddr;
+        }
+#if gcdENABLE_VG
+        if (Core == gcvCORE_VG)
+        {
+            gcmkVERIFY_OK(
+                gckVGHARDWARE_SplitMemory(Kernel->vg->hardware,
+                                        device->contiguousVidMem->baseAddress,
+                                        &pool,
+                                        &base));
+        }
+        else
+#endif
+        {
+            gcmkVERIFY_OK(
+                gckHARDWARE_SplitMemory(Kernel->hardware,
+                                        device->contiguousVidMem->baseAddress,
+                                        &pool,
+                                        &base));
+        }
+        offset -= base;
+        break;
+
+    default:
+        /* Invalid memory pool. */
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    /* Build logical address of specified address. */
+    *Logical = (gctPOINTER) ((gctUINT8_PTR) logical + offset);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Logical=%p", *Logical);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Retunn the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckKERNEL_MapVideoMemory
+**
+**  Get the logical address for a hardware specific memory address for the
+**  current process.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctBOOL InUserSpace
+**          gcvTRUE to map the memory into the user space.
+**
+**      gctUINT32 Address
+**          Hardware specific memory address.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Logical
+**          Pointer to a variable that will hold the logical address of the
+**          specified memory address.
+*/
+gceSTATUS
+gckKERNEL_MapVideoMemory(
+    IN gckKERNEL Kernel,
+    IN gctBOOL InUserSpace,
+    IN gctUINT32 Address,
+    OUT gctPOINTER * Logical
+    )
+{
+    return gckKERNEL_MapVideoMemoryEx(Kernel, gcvCORE_MAJOR, InUserSpace, Address, Logical);
+}
+/*******************************************************************************
+**
+**  gckKERNEL_Notify
+**
+**  This function iscalled by clients to notify the gckKERNRL object of an event.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gceNOTIFY Notification
+**          Notification event.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckKERNEL_Notify(
+    IN gckKERNEL Kernel,
+    IN gceNOTIFY Notification,
+    IN gctBOOL Data
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Kernel=%p Notification=%d Data=%d",
+                   Kernel, Notification, Data);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    /* Dispatch on notifcation. */
+    switch (Notification)
+    {
+    case gcvNOTIFY_INTERRUPT:
+        /* Process the interrupt. */
+#if COMMAND_PROCESSOR_VERSION > 1
+        status = gckINTERRUPT_Notify(Kernel->interrupt, Data);
+#else
+        status = gckHARDWARE_Interrupt(Kernel->hardware, Data);
+#endif
+        break;
+
+    default:
+        status = gcvSTATUS_OK;
+        break;
+    }
+
+    /* Success. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckKERNEL_QuerySettings(
+    IN gckKERNEL Kernel,
+    OUT gcsKERNEL_SETTINGS * Settings
+    )
+{
+    gckGALDEVICE device;
+
+    gcmkHEADER_ARG("Kernel=%p", Kernel);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Settings != gcvNULL);
+
+    /* Extract the pointer to the gckGALDEVICE class. */
+    device = (gckGALDEVICE) Kernel->context;
+
+    /* Fill in signal. */
+    Settings->signal = device->signal;
+
+    /* Success. */
+    gcmkFOOTER_ARG("Settings->signal=%d", Settings->signal);
+    return gcvSTATUS_OK;
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
new file mode 100644 (file)
index 0000000..067c740
--- /dev/null
@@ -0,0 +1,88 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_linux_h_
+#define __gc_hal_kernel_linux_h_
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#ifdef FLAREON
+#   include <asm/arch-realview/dove_gpio_irq.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/kthread.h>
+
+#ifdef MODVERSIONS
+#  include <linux/modversions.h>
+#endif
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+#include <linux/clk.h>
+#endif
+
+#define NTSTRSAFE_NO_CCH_FUNCTIONS
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_device.h"
+#include "gc_hal_kernel_os.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+#define FIND_TASK_BY_PID(x) pid_task(find_vpid(x), PIDTYPE_PID)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#define FIND_TASK_BY_PID(x) find_task_by_vpid(x)
+#else
+#define FIND_TASK_BY_PID(x) find_task_by_pid(x)
+#endif
+
+#define _WIDE(string)                          L##string
+#define WIDE(string)                           _WIDE(string)
+
+#define countof(a)                                     (sizeof(a) / sizeof(a[0]))
+
+#define DRV_NAME                               "galcore"
+
+#define GetPageCount(size, offset)     ((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
+
+static inline gctINT
+GetOrder(
+       IN gctINT numPages
+       )
+{
+    gctINT order = 0;
+
+       while ((1 << order) <  numPages) order++;
+
+       return order;
+}
+
+#endif /* __gc_hal_kernel_linux_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c
new file mode 100644 (file)
index 0000000..80e4495
--- /dev/null
@@ -0,0 +1,34 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_linux.h"
+
+gctINT
+gckMATH_ModuloInt(
+    IN gctINT X,
+    IN gctINT Y
+    )
+{
+    if(Y ==0) {return 0;}
+    else {return X % Y;}
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
new file mode 100644 (file)
index 0000000..9794938
--- /dev/null
@@ -0,0 +1,7714 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_linux.h"
+
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/sched.h>
+#include <asm/atomic.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
+#include <linux/math64.h>
+#endif
+
+#define _GC_OBJ_ZONE    gcvZONE_OS
+
+/*******************************************************************************
+***** Version Signature *******************************************************/
+
+#ifdef ANDROID
+const char * _PLATFORM = "\n\0$PLATFORM$Android$\n";
+#else
+const char * _PLATFORM = "\n\0$PLATFORM$Linux$\n";
+#endif
+
+#define USER_SIGNAL_TABLE_LEN_INIT  64
+
+#define MEMORY_LOCK(os) \
+    gcmkVERIFY_OK(gckOS_AcquireMutex( \
+                                (os), \
+                                (os)->memoryLock, \
+                                gcvINFINITE))
+
+#define MEMORY_UNLOCK(os) \
+    gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
+
+#define MEMORY_MAP_LOCK(os) \
+    gcmkVERIFY_OK(gckOS_AcquireMutex( \
+                                (os), \
+                                (os)->memoryMapLock, \
+                                gcvINFINITE))
+
+#define MEMORY_MAP_UNLOCK(os) \
+    gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
+
+#define gcdINFINITE_TIMEOUT     (60 * 1000)
+#define gcdDETECT_TIMEOUT       0
+#define gcdDETECT_DMA_ADDRESS   1
+#define gcdDETECT_DMA_STATE     1
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+typedef struct _gcsUSER_MAPPING * gcsUSER_MAPPING_PTR;
+typedef struct _gcsUSER_MAPPING
+{
+    /* Pointer to next mapping structure. */
+    gcsUSER_MAPPING_PTR         next;
+
+    /* Physical address of this mapping. */
+    gctUINT32                   physical;
+
+    /* Logical address of this mapping. */
+    gctPOINTER                  logical;
+
+    /* Number of bytes of this mapping. */
+    gctSIZE_T                   bytes;
+
+    /* Starting address of this mapping. */
+    gctINT8_PTR                 start;
+
+    /* Ending address of this mapping. */
+    gctINT8_PTR                 end;
+}
+gcsUSER_MAPPING;
+
+struct _gckOS
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Heap. */
+    gckHEAP                     heap;
+
+    /* Pointer to device */
+    gckGALDEVICE                device;
+
+    /* Memory management */
+    gctPOINTER                  memoryLock;
+    gctPOINTER                  memoryMapLock;
+
+    struct _LINUX_MDL           *mdlHead;
+    struct _LINUX_MDL           *mdlTail;
+
+    /* Kernel process ID. */
+    gctUINT32                   kernelProcessID;
+
+    /* Signal management. */
+    struct _signal
+    {
+        /* Unused signal ID number. */
+        gctINT                  unused;
+
+        /* The pointer to the table. */
+        gctPOINTER *            table;
+
+        /* Signal table length. */
+        gctINT                  tableLen;
+
+        /* The current unused signal ID. */
+        gctINT                  currentID;
+
+        /* Lock. */
+        gctPOINTER              lock;
+    }
+    signal;
+
+    gcsUSER_MAPPING_PTR         userMap;
+    gctPOINTER                  debugLock;
+};
+
+typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
+typedef struct _gcsSIGNAL
+{
+    /* Kernel sync primitive. */
+    struct completion obj;
+
+    /* Manual reset flag. */
+    gctBOOL manualReset;
+
+    /* The reference counter. */
+    atomic_t ref;
+
+    /* The owner of the signal. */
+    gctHANDLE process;
+}
+gcsSIGNAL;
+
+typedef struct _gcsPageInfo * gcsPageInfo_PTR;
+typedef struct _gcsPageInfo
+{
+    struct page **pages;
+    gctUINT32_PTR pageTable;
+}
+gcsPageInfo;
+
+typedef struct _gcsiDEBUG_REGISTERS * gcsiDEBUG_REGISTERS_PTR;
+typedef struct _gcsiDEBUG_REGISTERS
+{
+    gctSTRING       module;
+    gctUINT         index;
+    gctUINT         shift;
+    gctUINT         data;
+    gctUINT         count;
+    gctUINT32       signature;
+}
+gcsiDEBUG_REGISTERS;
+
+
+/******************************************************************************\
+******************************* Private Functions ******************************
+\******************************************************************************/
+
+static gceSTATUS
+_VerifyDMA(
+    IN gckOS Os,
+    IN gceCORE Core,
+    gctUINT32_PTR Address1,
+    gctUINT32_PTR Address2,
+    gctUINT32_PTR State1,
+    gctUINT32_PTR State2
+    )
+{
+    gceSTATUS status;
+    gctUINT32 i;
+
+    gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x660, State1));
+    gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x664, Address1));
+
+    for (i = 0; i < 500; i += 1)
+    {
+        gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x660, State2));
+        gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x664, Address2));
+
+        if (*Address1 != *Address2)
+        {
+            break;
+        }
+
+#if gcdDETECT_DMA_STATE
+        if (*State1 != *State2)
+        {
+            break;
+        }
+#endif
+    }
+
+OnError:
+    return status;
+}
+
+static gceSTATUS
+_DumpDebugRegisters(
+    IN gckOS Os,
+    IN gcsiDEBUG_REGISTERS_PTR Descriptor
+    )
+{
+    gceSTATUS status;
+    gctUINT32 select;
+    gctUINT32 data;
+    gctUINT i;
+
+    gcmkHEADER_ARG("Os=0x%X Descriptor=0x%X", Os, Descriptor);
+
+    gcmkPRINT_N(4, "  %s debug registers:\n", Descriptor->module);
+
+    select = 0xF << Descriptor->shift;
+
+    for (i = 0; i < 500; i += 1)
+    {
+        gcmkONERROR(gckOS_WriteRegister(Os, Descriptor->index, select));
+        gcmkONERROR(gckOS_Delay(Os, 1000));
+        gcmkONERROR(gckOS_ReadRegister(Os, Descriptor->data, &data));
+
+        if (data == Descriptor->signature)
+        {
+            break;
+        }
+    }
+
+    if (i == 500)
+    {
+        gcmkPRINT_N(4, "    failed to obtain the signature (read 0x%08X).\n", data);
+    }
+    else
+    {
+        gcmkPRINT_N(8, "    signature = 0x%08X (%d read attempt(s))\n", data, i + 1);
+    }
+
+    for (i = 0; i < Descriptor->count; i += 1)
+    {
+        select = i << Descriptor->shift;
+
+        gcmkONERROR(gckOS_WriteRegister(Os, Descriptor->index, select));
+        gcmkONERROR(gckOS_Delay(Os, 1000));
+        gcmkONERROR(gckOS_ReadRegister(Os, Descriptor->data, &data));
+
+        gcmkPRINT_N(12, "    [0x%02X] 0x%08X\n", i, data);
+    }
+
+OnError:
+    /* Return the error. */
+    gcmkFOOTER();
+    return status;
+}
+
+static gceSTATUS
+_DumpGPUState(
+    IN gckOS Os
+    )
+{
+    static gctCONST_STRING _cmdState[] =
+    {
+        "PAR_IDLE_ST", "PAR_DEC_ST", "PAR_ADR0_ST", "PAR_LOAD0_ST",
+        "PAR_ADR1_ST", "PAR_LOAD1_ST", "PAR_3DADR_ST", "PAR_3DCMD_ST",
+        "PAR_3DCNTL_ST", "PAR_3DIDXCNTL_ST", "PAR_INITREQDMA_ST",
+        "PAR_DRAWIDX_ST", "PAR_DRAW_ST", "PAR_2DRECT0_ST", "PAR_2DRECT1_ST",
+        "PAR_2DDATA0_ST", "PAR_2DDATA1_ST", "PAR_WAITFIFO_ST", "PAR_WAIT_ST",
+        "PAR_LINK_ST", "PAR_END_ST", "PAR_STALL_ST"
+    };
+
+    static gctCONST_STRING _cmdDmaState[] =
+    {
+        "CMD_IDLE_ST", "CMD_START_ST", "CMD_REQ_ST", "CMD_END_ST"
+    };
+
+    static gctCONST_STRING _cmdFetState[] =
+    {
+        "FET_IDLE_ST", "FET_RAMVALID_ST", "FET_VALID_ST"
+    };
+
+    static gctCONST_STRING _reqDmaState[] =
+    {
+        "REQ_IDLE_ST", "REQ_WAITIDX_ST", "REQ_CAL_ST"
+    };
+
+    static gctCONST_STRING _calState[] =
+    {
+        "CAL_IDLE_ST", "CAL_LDADR_ST", "CAL_IDXCALC_ST"
+    };
+
+    static gctCONST_STRING _veReqState[] =
+    {
+        "VER_IDLE_ST", "VER_CKCACHE_ST", "VER_MISS_ST"
+    };
+
+    static gcsiDEBUG_REGISTERS _dbgRegs[] =
+    {
+        { "RA", 0x474, 16, 0x448,  4, 0x12344321 },
+        { "TX", 0x474, 24, 0x44C,  4, 0x12211221 },
+        { "FE", 0x470,  0, 0x450,  4, 0xBABEF00D },
+        { "PE", 0x470, 16, 0x454,  4, 0xBABEF00D },
+        { "DE", 0x470,  8, 0x458,  4, 0xBABEF00D },
+        { "SH", 0x470, 24, 0x45C, 15, 0xDEADBEEF },
+        { "PA", 0x474,  0, 0x460,  4, 0x0000AAAA },
+        { "SE", 0x474,  8, 0x464,  4, 0x5E5E5E5E },
+        { "MC", 0x478,  0, 0x468,  4, 0x12345678 },
+        { "HI", 0x478,  8, 0x46C,  4, 0xAAAAAAAA }
+    };
+
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gckGALDEVICE device;
+    gckKERNEL kernel;
+    gctUINT32 idle, axi;
+    gctUINT32 dmaAddress1, dmaAddress2;
+    gctUINT32 dmaState1, dmaState2;
+    gctUINT32 dmaLow, dmaHigh;
+    gctUINT32 cmdState, cmdDmaState, cmdFetState;
+    gctUINT32 dmaReqState, calState, veReqState;
+    gctUINT i;
+
+    gcmkHEADER_ARG("Os=0x%X", Os);
+
+    gcmkONERROR(gckOS_AcquireMutex(Os, Os->debugLock, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Extract the pointer to the gckGALDEVICE class. */
+    device = (gckGALDEVICE) Os->device;
+
+    /* TODO: Kernel shortcut. */
+    kernel = device->kernels[gcvCORE_MAJOR];
+
+    if (kernel == gcvNULL) return gcvSTATUS_OK;
+
+    /* Reset register values. */
+    idle        = axi         =
+    dmaState1   = dmaState2   =
+    dmaAddress1 = dmaAddress2 =
+    dmaLow      = dmaHigh     = 0;
+
+    /* Verify whether DMA is running. */
+    gcmkONERROR(_VerifyDMA(
+        Os, kernel->core, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
+        ));
+
+    cmdState    =  dmaState2        & 0x1F;
+    cmdDmaState = (dmaState2 >>  8) & 0x03;
+    cmdFetState = (dmaState2 >> 10) & 0x03;
+    dmaReqState = (dmaState2 >> 12) & 0x03;
+    calState    = (dmaState2 >> 14) & 0x03;
+    veReqState  = (dmaState2 >> 16) & 0x03;
+
+    gcmkONERROR(gckOS_ReadRegisterEx(Os, kernel->core, 0x004, &idle));
+    gcmkONERROR(gckOS_ReadRegisterEx(Os, kernel->core, 0x00C, &axi));
+    gcmkONERROR(gckOS_ReadRegisterEx(Os, kernel->core, 0x668, &dmaLow));
+    gcmkONERROR(gckOS_ReadRegisterEx(Os, kernel->core, 0x66C, &dmaHigh));
+
+    gcmkPRINT_N(0, "**************************\n");
+    gcmkPRINT_N(0, "***   GPU STATE DUMP   ***\n");
+    gcmkPRINT_N(0, "**************************\n");
+
+    gcmkPRINT_N(4, "  axi      = 0x%08X\n", axi);
+
+    gcmkPRINT_N(4, "  idle     = 0x%08X\n", idle);
+    if ((idle & 0x00000001) == 0) gcmkPRINT_N(0, "    FE not idle\n");
+    if ((idle & 0x00000002) == 0) gcmkPRINT_N(0, "    DE not idle\n");
+    if ((idle & 0x00000004) == 0) gcmkPRINT_N(0, "    PE not idle\n");
+    if ((idle & 0x00000008) == 0) gcmkPRINT_N(0, "    SH not idle\n");
+    if ((idle & 0x00000010) == 0) gcmkPRINT_N(0, "    PA not idle\n");
+    if ((idle & 0x00000020) == 0) gcmkPRINT_N(0, "    SE not idle\n");
+    if ((idle & 0x00000040) == 0) gcmkPRINT_N(0, "    RA not idle\n");
+    if ((idle & 0x00000080) == 0) gcmkPRINT_N(0, "    TX not idle\n");
+    if ((idle & 0x00000100) == 0) gcmkPRINT_N(0, "    VG not idle\n");
+    if ((idle & 0x00000200) == 0) gcmkPRINT_N(0, "    IM not idle\n");
+    if ((idle & 0x00000400) == 0) gcmkPRINT_N(0, "    FP not idle\n");
+    if ((idle & 0x00000800) == 0) gcmkPRINT_N(0, "    TS not idle\n");
+    if ((idle & 0x80000000) != 0) gcmkPRINT_N(0, "    AXI low power mode\n");
+
+    if (
+        (dmaAddress1 == dmaAddress2)
+
+#if gcdDETECT_DMA_STATE
+     && (dmaState1 == dmaState2)
+#endif
+    )
+    {
+        gcmkPRINT_N(0, "  DMA appears to be stuck at this address:\n");
+        gcmkPRINT_N(4, "    0x%08X\n", dmaAddress1);
+    }
+    else
+    {
+        if (dmaAddress1 == dmaAddress2)
+        {
+            gcmkPRINT_N(0, "  DMA address is constant, but state is changing:\n");
+            gcmkPRINT_N(4, "    0x%08X\n", dmaState1);
+            gcmkPRINT_N(4, "    0x%08X\n", dmaState2);
+        }
+        else
+        {
+            gcmkPRINT_N(0, "  DMA is running; known addresses are:\n");
+            gcmkPRINT_N(4, "    0x%08X\n", dmaAddress1);
+            gcmkPRINT_N(4, "    0x%08X\n", dmaAddress2);
+        }
+    }
+
+    gcmkPRINT_N(4, "  dmaLow   = 0x%08X\n", dmaLow);
+    gcmkPRINT_N(4, "  dmaHigh  = 0x%08X\n", dmaHigh);
+    gcmkPRINT_N(4, "  dmaState = 0x%08X\n", dmaState2);
+    gcmkPRINT_N(8, "    command state       = %d (%s)\n", cmdState,    _cmdState   [cmdState]);
+    gcmkPRINT_N(8, "    command DMA state   = %d (%s)\n", cmdDmaState, _cmdDmaState[cmdDmaState]);
+    gcmkPRINT_N(8, "    command fetch state = %d (%s)\n", cmdFetState, _cmdFetState[cmdFetState]);
+    gcmkPRINT_N(8, "    DMA request state   = %d (%s)\n", dmaReqState, _reqDmaState[dmaReqState]);
+    gcmkPRINT_N(8, "    cal state           = %d (%s)\n", calState,    _calState   [calState]);
+    gcmkPRINT_N(8, "    VE request state    = %d (%s)\n", veReqState,  _veReqState [veReqState]);
+
+    for (i = 0; i < gcmCOUNTOF(_dbgRegs); i += 1)
+    {
+        gcmkONERROR(_DumpDebugRegisters(Os, &_dbgRegs[i]));
+    }
+
+    if (kernel->hardware->chipFeatures & (1 << 4))
+    {
+        gctUINT32 read0, read1, write;
+
+        read0 = read1 = write = 0;
+
+        gcmkONERROR(gckOS_ReadRegisterEx(Os, kernel->core, 0x43C, &read0));
+        gcmkONERROR(gckOS_ReadRegisterEx(Os, kernel->core, 0x440, &read1));
+        gcmkONERROR(gckOS_ReadRegisterEx(Os, kernel->core, 0x444, &write));
+
+        gcmkPRINT_N(4, "  read0    = 0x%08X\n", read0);
+        gcmkPRINT_N(4, "  read1    = 0x%08X\n", read1);
+        gcmkPRINT_N(4, "  write    = 0x%08X\n", write);
+    }
+
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->debugLock));
+    }
+
+    /* Return the error. */
+    gcmkFOOTER();
+    return status;
+}
+
+static gctINT
+_GetProcessID(
+    void
+    )
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+    return task_tgid_vnr(current);
+#else
+    return current->tgid;
+#endif
+}
+
+static gctINT
+_GetThreadID(
+    void
+    )
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+    return task_pid_vnr(current);
+#else
+    return current->pid;
+#endif
+}
+
+static PLINUX_MDL
+_CreateMdl(
+    IN gctINT ProcessID
+    )
+{
+    PLINUX_MDL  mdl;
+
+    gcmkHEADER_ARG("ProcessID=%d", ProcessID);
+
+    mdl = (PLINUX_MDL)kmalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL);
+    if (mdl == gcvNULL)
+    {
+        gcmkFOOTER_NO();
+        return gcvNULL;
+    }
+
+    mdl->pid    = ProcessID;
+    mdl->maps   = gcvNULL;
+    mdl->prev   = gcvNULL;
+    mdl->next   = gcvNULL;
+
+    gcmkFOOTER_ARG("0x%X", mdl);
+    return mdl;
+}
+
+static gceSTATUS
+_DestroyMdlMap(
+    IN PLINUX_MDL Mdl,
+    IN PLINUX_MDL_MAP MdlMap
+    );
+
+static gceSTATUS
+_DestroyMdl(
+    IN PLINUX_MDL Mdl
+    )
+{
+    PLINUX_MDL_MAP mdlMap, next;
+
+    gcmkHEADER_ARG("Mdl=0x%X", Mdl);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
+
+    mdlMap = Mdl->maps;
+
+    while (mdlMap != gcvNULL)
+    {
+        next = mdlMap->next;
+
+        gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
+
+        mdlMap = next;
+    }
+
+    kfree(Mdl);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+static PLINUX_MDL_MAP
+_CreateMdlMap(
+    IN PLINUX_MDL Mdl,
+    IN gctINT ProcessID
+    )
+{
+    PLINUX_MDL_MAP  mdlMap;
+
+    gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
+
+    mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_KERNEL);
+    if (mdlMap == gcvNULL)
+    {
+        gcmkFOOTER_NO();
+        return gcvNULL;
+    }
+
+    mdlMap->pid     = ProcessID;
+    mdlMap->vmaAddr = gcvNULL;
+    mdlMap->vma     = gcvNULL;
+
+    mdlMap->next    = Mdl->maps;
+    Mdl->maps       = mdlMap;
+
+    gcmkFOOTER_ARG("0x%X", mdlMap);
+    return mdlMap;
+}
+
+static gceSTATUS
+_DestroyMdlMap(
+    IN PLINUX_MDL Mdl,
+    IN PLINUX_MDL_MAP MdlMap
+    )
+{
+    PLINUX_MDL_MAP  prevMdlMap;
+
+    gcmkHEADER_ARG("Mdl=0x%X MdlMap=0x%X", Mdl, MdlMap);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
+    gcmkASSERT(Mdl->maps != gcvNULL);
+
+    if (Mdl->maps == MdlMap)
+    {
+        Mdl->maps = MdlMap->next;
+    }
+    else
+    {
+        prevMdlMap = Mdl->maps;
+
+        while (prevMdlMap->next != MdlMap)
+        {
+            prevMdlMap = prevMdlMap->next;
+
+            gcmkASSERT(prevMdlMap != gcvNULL);
+        }
+
+        prevMdlMap->next = MdlMap->next;
+    }
+
+    kfree(MdlMap);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+extern PLINUX_MDL_MAP
+FindMdlMap(
+    IN PLINUX_MDL Mdl,
+    IN gctINT ProcessID
+    )
+{
+    PLINUX_MDL_MAP  mdlMap;
+
+    gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
+    if(Mdl == gcvNULL)
+    {
+        return gcvNULL;
+    }
+    mdlMap = Mdl->maps;
+
+    while (mdlMap != gcvNULL)
+    {
+        if (mdlMap->pid == ProcessID)
+        {
+            gcmkFOOTER_ARG("0x%X", mdlMap);
+            return mdlMap;
+        }
+
+        mdlMap = mdlMap->next;
+    }
+
+    gcmkFOOTER_NO();
+    return gcvNULL;
+}
+
+void
+OnProcessExit(
+    IN gckOS Os,
+    IN gckKERNEL Kernel
+    )
+{
+}
+
+/*******************************************************************************
+**
+**  gckOS_Construct
+**
+**  Construct a new gckOS object.
+**
+**  INPUT:
+**
+**      gctPOINTER Context
+**          Pointer to the gckGALDEVICE class.
+**
+**  OUTPUT:
+**
+**      gckOS * Os
+**          Pointer to a variable that will hold the pointer to the gckOS object.
+*/
+gceSTATUS
+gckOS_Construct(
+    IN gctPOINTER Context,
+    OUT gckOS * Os
+    )
+{
+    gckOS os;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Context=0x%X", Context);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Os != gcvNULL);
+
+    /* Allocate the gckOS object. */
+    os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL);
+
+    if (os == gcvNULL)
+    {
+        /* Out of memory. */
+        gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    /* Zero the memory. */
+    gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
+
+    /* Initialize the gckOS object. */
+    os->object.type = gcvOBJ_OS;
+
+    /* Set device device. */
+    os->device = Context;
+
+    /* IMPORTANT! No heap yet. */
+    os->heap = gcvNULL;
+
+    /* Initialize the memory lock. */
+    gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
+    gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
+
+    /* Create debug lock mutex. */
+    gcmkONERROR(gckOS_CreateMutex(os, &os->debugLock));
+
+    /* Create the gckHEAP object. */
+    gcmkONERROR(gckHEAP_Construct(os, gcdHEAP_SIZE, &os->heap));
+
+    os->mdlHead = os->mdlTail = gcvNULL;
+
+    /* Get the kernel process ID. */
+    gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
+
+    /*
+     * Initialize the signal manager.
+     * It creates the signals to be used in
+     * the user space.
+     */
+
+    /* Initialize mutex. */
+    gcmkONERROR(
+        gckOS_CreateMutex(os, &os->signal.lock));
+
+    /* Initialize the signal table. */
+    os->signal.table =
+        kmalloc(gcmSIZEOF(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT, GFP_KERNEL);
+
+    if (os->signal.table == gcvNULL)
+    {
+        /* Out of memory. */
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    gckOS_ZeroMemory(os->signal.table,
+                     gcmSIZEOF(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT);
+
+    /* Set the signal table length. */
+    os->signal.tableLen = USER_SIGNAL_TABLE_LEN_INIT;
+
+    /* The table is empty. */
+    os->signal.unused = os->signal.tableLen;
+
+    /* Initial signal ID. */
+    os->signal.currentID = 0;
+
+    /* Return pointer to the gckOS object. */
+    *Os = os;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Os=0x%X", *Os);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back any allocation. */
+    if (os->signal.table != gcvNULL)
+    {
+        kfree(os->signal.table);
+    }
+
+    if (os->signal.lock != gcvNULL)
+    {
+        gcmkVERIFY_OK(
+            gckOS_DeleteMutex(os, os->signal.lock));
+    }
+
+    if (os->heap != gcvNULL)
+    {
+        gcmkVERIFY_OK(
+            gckHEAP_Destroy(os->heap));
+    }
+
+    if (os->memoryMapLock != gcvNULL)
+    {
+        gcmkVERIFY_OK(
+            gckOS_DeleteMutex(os, os->memoryMapLock));
+    }
+
+    if (os->memoryLock != gcvNULL)
+    {
+        gcmkVERIFY_OK(
+            gckOS_DeleteMutex(os, os->memoryLock));
+    }
+
+    if (os->debugLock != gcvNULL)
+    {
+        gcmkVERIFY_OK(
+            gckOS_DeleteMutex(os, os->debugLock));
+    }
+
+    kfree(os);
+
+    /* Return the error. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_Destroy
+**
+**  Destroy an gckOS object.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object that needs to be destroyed.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_Destroy(
+    IN gckOS Os
+    )
+{
+    gckHEAP heap;
+
+    gcmkHEADER_ARG("Os=0x%X", Os);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    /*
+     * Destroy the signal manager.
+     */
+
+    /* Destroy the mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->signal.lock));
+
+    /* Free the signal table. */
+    kfree(Os->signal.table);
+
+    if (Os->heap != gcvNULL)
+    {
+        /* Mark gckHEAP as gone. */
+        heap     = Os->heap;
+        Os->heap = gcvNULL;
+
+        /* Destroy the gckHEAP object. */
+        gcmkVERIFY_OK(gckHEAP_Destroy(heap));
+    }
+
+    /* Destroy the memory lock. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryMapLock));
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryLock));
+
+    /* Destroy debug lock mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->debugLock));
+
+    /* Flush the debug cache. */
+    gcmkDEBUGFLUSH(~0U);
+
+    /* Mark the gckOS object as unknown. */
+    Os->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the gckOS object. */
+    kfree(Os);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_Allocate
+**
+**  Allocate memory.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to allocate.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Memory
+**          Pointer to a variable that will hold the allocated memory location.
+*/
+gceSTATUS
+gckOS_Allocate(
+    IN gckOS Os,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Memory
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+    /* Do we have a heap? */
+    if (Os->heap != gcvNULL)
+    {
+        /* Allocate from the heap. */
+        gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
+    }
+    else
+    {
+        gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_Free
+**
+**  Free allocated memory.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER Memory
+**          Pointer to memory allocation to free.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_Free(
+    IN gckOS Os,
+    IN gctPOINTER Memory
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X Memory=0x%X", Os, Memory);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+    /* Do we have a heap? */
+    if (Os->heap != gcvNULL)
+    {
+        /* Free from the heap. */
+        gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
+    }
+    else
+    {
+        gcmkONERROR(gckOS_FreeMemory(Os, Memory));
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AllocateMemory
+**
+**  Allocate memory wrapper.
+**
+**  INPUT:
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to allocate.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Memory
+**          Pointer to a variable that will hold the allocated memory location.
+*/
+gceSTATUS
+gckOS_AllocateMemory(
+    IN gckOS Os,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Memory
+    )
+{
+    gctPOINTER memory;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+    memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL);
+
+    if (memory == gcvNULL)
+    {
+        /* Out of memory. */
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    /* Return pointer to the memory allocation. */
+    *Memory = memory;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_FreeMemory
+**
+**  Free allocated memory wrapper.
+**
+**  INPUT:
+**
+**      gctPOINTER Memory
+**          Pointer to memory allocation to free.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_FreeMemory(
+    IN gckOS Os,
+    IN gctPOINTER Memory
+    )
+{
+    gcmkHEADER_ARG("Memory=0x%X", Memory);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+    /* Free the memory from the OS pool. */
+    kfree(Memory);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_MapMemory
+**
+**  Map physical memory into the current process.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPHYS_ADDR Physical
+**          Start of physical address memory.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to map.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Memory
+**          Pointer to a variable that will hold the logical address of the
+**          mapped memory.
+*/
+gceSTATUS
+gckOS_MapMemory(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Logical
+    )
+{
+    PLINUX_MDL_MAP  mdlMap;
+    PLINUX_MDL      mdl = (PLINUX_MDL)Physical;
+
+    gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != 0);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+    MEMORY_LOCK(Os);
+
+    mdlMap = FindMdlMap(mdl, _GetProcessID());
+
+    if (mdlMap == gcvNULL)
+    {
+        mdlMap = _CreateMdlMap(mdl, _GetProcessID());
+
+        if (mdlMap == gcvNULL)
+        {
+            MEMORY_UNLOCK(Os);
+
+            gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+            return gcvSTATUS_OUT_OF_MEMORY;
+        }
+    }
+
+    if (mdlMap->vmaAddr == gcvNULL)
+    {
+        down_write(&current->mm->mmap_sem);
+
+        mdlMap->vmaAddr = (char *)do_mmap_pgoff(gcvNULL,
+                    0L,
+                    mdl->numPages * PAGE_SIZE,
+                    PROT_READ | PROT_WRITE,
+                    MAP_SHARED,
+                    0);
+
+        if (IS_ERR(mdlMap->vmaAddr))
+        {
+            gcmkTRACE(
+                gcvLEVEL_ERROR,
+                "%s(%d): do_mmap_pgoff error",
+                __FUNCTION__, __LINE__
+                );
+
+            gcmkTRACE(
+                gcvLEVEL_ERROR,
+                "%s(%d): mdl->numPages: %d mdl->vmaAddr: 0x%X",
+                __FUNCTION__, __LINE__,
+                mdl->numPages,
+                mdlMap->vmaAddr
+                );
+
+            mdlMap->vmaAddr = gcvNULL;
+
+            up_write(&current->mm->mmap_sem);
+
+            MEMORY_UNLOCK(Os);
+
+            gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+            return gcvSTATUS_OUT_OF_MEMORY;
+        }
+
+        mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+        if (!mdlMap->vma)
+        {
+            gcmkTRACE(
+                gcvLEVEL_ERROR,
+                "%s(%d): find_vma error.",
+                __FUNCTION__, __LINE__
+                );
+
+            mdlMap->vmaAddr = gcvNULL;
+
+            up_write(&current->mm->mmap_sem);
+
+            MEMORY_UNLOCK(Os);
+
+            gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+
+#ifndef NO_DMA_COHERENT
+        if (dma_mmap_coherent(gcvNULL,
+                    mdlMap->vma,
+                    mdl->addr,
+                    mdl->dmaHandle,
+                    mdl->numPages * PAGE_SIZE) < 0)
+        {
+            up_write(&current->mm->mmap_sem);
+
+            gcmkTRACE(
+                gcvLEVEL_ERROR,
+                "%s(%d): dma_mmap_coherent error.",
+                __FUNCTION__, __LINE__
+                );
+
+            mdlMap->vmaAddr = gcvNULL;
+
+            MEMORY_UNLOCK(Os);
+
+            gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+#else
+#if !gcdPAGED_MEMORY_CACHEABLE
+        mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
+        mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
+#   endif
+        mdlMap->vma->vm_pgoff = 0;
+
+        if (remap_pfn_range(mdlMap->vma,
+                            mdlMap->vma->vm_start,
+                            mdl->dmaHandle >> PAGE_SHIFT,
+                            mdl->numPages*PAGE_SIZE,
+                            mdlMap->vma->vm_page_prot) < 0)
+        {
+            up_write(&current->mm->mmap_sem);
+
+            gcmkTRACE(
+                gcvLEVEL_ERROR,
+                "%s(%d): remap_pfn_range error.",
+                __FUNCTION__, __LINE__
+                );
+
+            mdlMap->vmaAddr = gcvNULL;
+
+            MEMORY_UNLOCK(Os);
+
+            gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+#endif
+
+        up_write(&current->mm->mmap_sem);
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    *Logical = mdlMap->vmaAddr;
+
+    gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_UnmapMemory
+**
+**  Unmap physical memory out of the current process.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPHYS_ADDR Physical
+**          Start of physical address memory.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to unmap.
+**
+**      gctPOINTER Memory
+**          Pointer to a previously mapped memory region.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_UnmapMemory(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctPOINTER Logical
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
+                   Os, Physical, Bytes, Logical);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != 0);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+    gckOS_UnmapMemoryEx(Os, Physical, Bytes, Logical, _GetProcessID());
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+**  gckOS_UnmapMemoryEx
+**
+**  Unmap physical memory in the specified process.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPHYS_ADDR Physical
+**          Start of physical address memory.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to unmap.
+**
+**      gctPOINTER Memory
+**          Pointer to a previously mapped memory region.
+**
+**      gctUINT32 PID
+**          Pid of the process that opened the device and mapped this memory.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_UnmapMemoryEx(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctPOINTER Logical,
+    IN gctUINT32 PID
+    )
+{
+    PLINUX_MDL_MAP          mdlMap;
+    PLINUX_MDL              mdl = (PLINUX_MDL)Physical;
+    struct task_struct *    task;
+
+    gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X PID=%d",
+                   Os, Physical, Bytes, Logical, PID);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != 0);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(PID != 0);
+
+    MEMORY_LOCK(Os);
+
+    if (Logical)
+    {
+        mdlMap = FindMdlMap(mdl, PID);
+
+        if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
+        {
+            MEMORY_UNLOCK(Os);
+
+            gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+            return gcvSTATUS_INVALID_ARGUMENT;
+        }
+
+        /* Get the current pointer for the task with stored pid. */
+        task = FIND_TASK_BY_PID(mdlMap->pid);
+
+        if (task != gcvNULL && task->mm != gcvNULL)
+        {
+            down_write(&task->mm->mmap_sem);
+            do_munmap(task->mm, (unsigned long)Logical, mdl->numPages*PAGE_SIZE);
+            up_write(&task->mm->mmap_sem);
+        }
+        else
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO, gcvZONE_OS,
+                "%s(%d): can't find the task with pid->%d. No unmapping",
+                __FUNCTION__, __LINE__,
+                mdlMap->pid
+                );
+        }
+
+        gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AllocateNonPagedMemory
+**
+**  Allocate a number of pages from non-paged memory.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctBOOL InUserSpace
+**          gcvTRUE if the pages need to be mapped into user space.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that holds the number of bytes to allocate.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that hold the number of bytes allocated.
+**
+**      gctPHYS_ADDR * Physical
+**          Pointer to a variable that will hold the physical address of the
+**          allocation.
+**
+**      gctPOINTER * Logical
+**          Pointer to a variable that will hold the logical address of the
+**          allocation.
+*/
+gceSTATUS
+gckOS_AllocateNonPagedMemory(
+    IN gckOS Os,
+    IN gctBOOL InUserSpace,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctPHYS_ADDR * Physical,
+    OUT gctPOINTER * Logical
+    )
+{
+    gctSIZE_T bytes;
+    gctINT numPages;
+    PLINUX_MDL mdl = gcvNULL;
+    PLINUX_MDL_MAP mdlMap = gcvNULL;
+    gctSTRING addr;
+#ifdef NO_DMA_COHERENT
+    struct page * page;
+    long size, order;
+    gctPOINTER vaddr;
+#endif
+    gctBOOL locked = gcvFALSE;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
+                   Os, InUserSpace, gcmOPT_VALUE(Bytes));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
+    gcmkVERIFY_ARGUMENT(*Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+    /* Align number of bytes to page size. */
+    bytes = gcmALIGN(*Bytes, PAGE_SIZE);
+
+    /* Get total number of pages.. */
+    numPages = GetPageCount(bytes, 0);
+
+    /* Allocate mdl+vector structure */
+    mdl = _CreateMdl(_GetProcessID());
+    if (mdl == gcvNULL)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    mdl->pagedMem = 0;
+    mdl->numPages = numPages;
+
+    MEMORY_LOCK(Os);
+    locked = gcvTRUE;
+
+#ifndef NO_DMA_COHERENT
+    addr = dma_alloc_coherent(gcvNULL,
+                mdl->numPages * PAGE_SIZE,
+                &mdl->dmaHandle,
+                GFP_KERNEL);
+#else
+    size    = mdl->numPages * PAGE_SIZE;
+    order   = get_order(size);
+    page    = alloc_pages(GFP_KERNEL, order);
+
+    if (page == gcvNULL)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    vaddr           = (gctPOINTER)page_address(page);
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+    addr            = vaddr;
+#   elif gcdNONPAGED_MEMORY_BUFFERABLE
+    addr            = ioremap_wc(virt_to_phys(vaddr), size);
+#   else
+    addr            = ioremap_nocache(virt_to_phys(vaddr), size);
+#   endif
+
+    mdl->dmaHandle  = virt_to_phys(vaddr);
+    mdl->kaddr      = vaddr;
+
+    /* Cache invalidate. */
+    dma_sync_single_for_device(
+                gcvNULL,
+                page_to_phys(page),
+                bytes,
+                DMA_FROM_DEVICE);
+
+    while (size > 0)
+    {
+        SetPageReserved(virt_to_page(vaddr));
+
+        vaddr   += PAGE_SIZE;
+        size    -= PAGE_SIZE;
+    }
+#endif
+
+    if (addr == gcvNULL)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    if ((Os->device->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000))
+    {
+        mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
+                       | (Os->device->baseAddress & 0x80000000);
+    }
+
+    mdl->addr = addr;
+
+    /*
+     * We will not do any mapping from here.
+     * Mapping will happen from mmap method.
+     * mdl structure will be used.
+     */
+
+    /* Return allocated memory. */
+    *Bytes = bytes;
+    *Physical = (gctPHYS_ADDR) mdl;
+
+    if (InUserSpace)
+    {
+        mdlMap = _CreateMdlMap(mdl, _GetProcessID());
+
+        if (mdlMap == gcvNULL)
+        {
+            gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+        }
+
+        /* Only after mmap this will be valid. */
+
+        /* We need to map this to user space. */
+        down_write(&current->mm->mmap_sem);
+
+        mdlMap->vmaAddr = (gctSTRING) do_mmap_pgoff(gcvNULL,
+                0L,
+                mdl->numPages * PAGE_SIZE,
+                PROT_READ | PROT_WRITE,
+                MAP_SHARED,
+                0);
+
+        if (IS_ERR(mdlMap->vmaAddr))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_WARNING, gcvZONE_OS,
+                "%s(%d): do_mmap_pgoff error",
+                __FUNCTION__, __LINE__
+                );
+
+            mdlMap->vmaAddr = gcvNULL;
+
+            up_write(&current->mm->mmap_sem);
+
+            gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+        }
+
+        mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+        if (mdlMap->vma == gcvNULL)
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_WARNING, gcvZONE_OS,
+                "%s(%d): find_vma error",
+                __FUNCTION__, __LINE__
+                );
+
+            up_write(&current->mm->mmap_sem);
+
+            gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+        }
+
+#ifndef NO_DMA_COHERENT
+        if (dma_mmap_coherent(gcvNULL,
+                mdlMap->vma,
+                mdl->addr,
+                mdl->dmaHandle,
+                mdl->numPages * PAGE_SIZE) < 0)
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_WARNING, gcvZONE_OS,
+                "%s(%d): dma_mmap_coherent error",
+                __FUNCTION__, __LINE__
+                );
+
+            up_write(&current->mm->mmap_sem);
+
+            gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+        }
+#else
+        mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
+        mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
+        mdlMap->vma->vm_pgoff = 0;
+
+        if (remap_pfn_range(mdlMap->vma,
+                            mdlMap->vma->vm_start,
+                            mdl->dmaHandle >> PAGE_SHIFT,
+                            mdl->numPages * PAGE_SIZE,
+                            mdlMap->vma->vm_page_prot))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_WARNING, gcvZONE_OS,
+                "%s(%d): remap_pfn_range error",
+                __FUNCTION__, __LINE__
+                );
+
+            up_write(&current->mm->mmap_sem);
+
+            gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+        }
+#endif /* NO_DMA_COHERENT */
+
+        up_write(&current->mm->mmap_sem);
+
+        *Logical = mdlMap->vmaAddr;
+    }
+    else
+    {
+        *Logical = (gctPOINTER)mdl->addr;
+    }
+
+    /*
+     * Add this to a global list.
+     * Will be used by get physical address
+     * and mapuser pointer functions.
+     */
+
+    if (!Os->mdlHead)
+    {
+        /* Initialize the queue. */
+        Os->mdlHead = Os->mdlTail = mdl;
+    }
+    else
+    {
+        /* Add to the tail. */
+        mdl->prev = Os->mdlTail;
+        Os->mdlTail->next = mdl;
+        Os->mdlTail = mdl;
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
+                   *Bytes, *Physical, *Logical);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (mdlMap != gcvNULL)
+    {
+        /* Free LINUX_MDL_MAP. */
+        gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+    }
+
+    if (mdl != gcvNULL)
+    {
+        /* Free LINUX_MDL. */
+        gcmkVERIFY_OK(_DestroyMdl(mdl));
+    }
+
+    if (locked)
+    {
+        /* Unlock memory. */
+        MEMORY_UNLOCK(Os);
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_FreeNonPagedMemory
+**
+**  Free previously allocated and mapped pages from non-paged memory.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes allocated.
+**
+**      gctPHYS_ADDR Physical
+**          Physical address of the allocated memory.
+**
+**      gctPOINTER Logical
+**          Logical address of the allocated memory.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS gckOS_FreeNonPagedMemory(
+    IN gckOS Os,
+    IN gctSIZE_T Bytes,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical
+    )
+{
+    PLINUX_MDL mdl;
+    PLINUX_MDL_MAP mdlMap;
+    struct task_struct * task;
+#ifdef NO_DMA_COHERENT
+    unsigned size;
+    gctPOINTER vaddr;
+#endif /* NO_DMA_COHERENT */
+
+    gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
+                   Os, Bytes, Physical, Logical);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Physical != 0);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+    /* Convert physical address into a pointer to a MDL. */
+    mdl = (PLINUX_MDL) Physical;
+
+    MEMORY_LOCK(Os);
+
+#ifndef NO_DMA_COHERENT
+    dma_free_coherent(gcvNULL,
+                    mdl->numPages * PAGE_SIZE,
+                    mdl->addr,
+                    mdl->dmaHandle);
+#else
+    size    = mdl->numPages * PAGE_SIZE;
+    vaddr   = mdl->kaddr;
+
+    while (size > 0)
+    {
+        ClearPageReserved(virt_to_page(vaddr));
+
+        vaddr   += PAGE_SIZE;
+        size    -= PAGE_SIZE;
+    }
+
+    free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
+
+#if !gcdNONPAGED_MEMORY_CACHEABLE
+    iounmap(mdl->addr);
+#endif
+
+#endif /* NO_DMA_COHERENT */
+
+    mdlMap = mdl->maps;
+
+    while (mdlMap != gcvNULL)
+    {
+        if (mdlMap->vmaAddr != gcvNULL)
+        {
+            /* Get the current pointer for the task with stored pid. */
+            task = FIND_TASK_BY_PID(mdlMap->pid);
+
+            if (task != gcvNULL && task->mm != gcvNULL)
+            {
+                down_write(&task->mm->mmap_sem);
+
+                if (do_munmap(task->mm,
+                              (unsigned long)mdlMap->vmaAddr,
+                              mdl->numPages * PAGE_SIZE) < 0)
+                {
+                    gcmkTRACE_ZONE(
+                        gcvLEVEL_WARNING, gcvZONE_OS,
+                        "%s(%d): do_munmap failed",
+                        __FUNCTION__, __LINE__
+                        );
+                }
+
+                up_write(&task->mm->mmap_sem);
+            }
+
+            mdlMap->vmaAddr = gcvNULL;
+        }
+
+        mdlMap = mdlMap->next;
+    }
+
+    /* Remove the node from global list.. */
+    if (mdl == Os->mdlHead)
+    {
+        if ((Os->mdlHead = mdl->next) == gcvNULL)
+        {
+            Os->mdlTail = gcvNULL;
+        }
+    }
+    else
+    {
+        mdl->prev->next = mdl->next;
+        if (mdl == Os->mdlTail)
+        {
+            Os->mdlTail = mdl->prev;
+        }
+        else
+        {
+            mdl->next->prev = mdl->prev;
+        }
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_ReadRegister
+**
+**  Read data from a register.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctUINT32 Address
+**          Address of register.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Data
+**          Pointer to a variable that receives the data read from the register.
+*/
+gceSTATUS
+gckOS_ReadRegister(
+    IN gckOS Os,
+    IN gctUINT32 Address,
+    OUT gctUINT32 * Data
+    )
+{
+    return gckOS_ReadRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
+}
+
+gceSTATUS
+gckOS_ReadRegisterEx(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctUINT32 Address,
+    OUT gctUINT32 * Data
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+    *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Data=0x%08x", *Data);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_WriteRegister
+**
+**  Write data to a register.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctUINT32 Address
+**          Address of register.
+**
+**      gctUINT32 Data
+**          Data for register.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_WriteRegister(
+    IN gckOS Os,
+    IN gctUINT32 Address,
+    IN gctUINT32 Data
+    )
+{
+    return gckOS_WriteRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
+}
+
+gceSTATUS
+gckOS_WriteRegisterEx(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctUINT32 Address,
+    IN gctUINT32 Data
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
+
+    writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_GetPageSize
+**
+**  Get the system's page size.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * PageSize
+**          Pointer to a variable that will receive the system's page size.
+*/
+gceSTATUS gckOS_GetPageSize(
+    IN gckOS Os,
+    OUT gctSIZE_T * PageSize
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X", Os);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
+
+    /* Return the page size. */
+    *PageSize = (gctSIZE_T) PAGE_SIZE;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*PageSize", *PageSize);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_GetPhysicalAddress
+**
+**  Get the physical system address of a corresponding virtual address.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER Logical
+**          Logical address.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Address
+**          Poinetr to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS
+gckOS_GetPhysicalAddress(
+    IN gckOS Os,
+    IN gctPOINTER Logical,
+    OUT gctUINT32 * Address
+    )
+{
+    gceSTATUS status;
+    gctUINT32 processID;
+
+    gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os, Logical);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    /* Get current process ID. */
+    processID = _GetProcessID();
+
+    /* Route through other function. */
+    gcmkONERROR(
+        gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Address=0x%08x", *Address);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+#if gcdSECURE_USER
+static gceSTATUS
+gckOS_AddMapping(
+    IN gckOS Os,
+    IN gctUINT32 Physical,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    gceSTATUS status;
+    gcsUSER_MAPPING_PTR map;
+
+    gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
+                   Os, Physical, Logical, Bytes);
+
+    gcmkONERROR(gckOS_Allocate(Os,
+                               gcmSIZEOF(gcsUSER_MAPPING),
+                               (gctPOINTER *) &map));
+
+    map->next     = Os->userMap;
+    map->physical = Physical - Os->device->baseAddress;
+    map->logical  = Logical;
+    map->bytes    = Bytes;
+    map->start    = (gctINT8_PTR) Logical;
+    map->end      = map->start + Bytes;
+
+    Os->userMap = map;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+static gceSTATUS
+gckOS_RemoveMapping(
+    IN gckOS Os,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    gceSTATUS status;
+    gcsUSER_MAPPING_PTR map, prev;
+
+    gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
+
+    for (map = Os->userMap, prev = gcvNULL; map != gcvNULL; map = map->next)
+    {
+        if ((map->logical == Logical)
+        &&  (map->bytes   == Bytes)
+        )
+        {
+            break;
+        }
+
+        prev = map;
+    }
+
+    if (map == gcvNULL)
+    {
+        gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
+    }
+
+    if (prev == gcvNULL)
+    {
+        Os->userMap = map->next;
+    }
+    else
+    {
+        prev->next = map->next;
+    }
+
+    gcmkONERROR(gcmkOS_SAFE_FREE(Os, map));
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+#endif
+
+static gceSTATUS
+_ConvertLogical2Physical(
+    IN gckOS Os,
+    IN gctPOINTER Logical,
+    IN gctUINT32 ProcessID,
+    IN PLINUX_MDL Mdl,
+    OUT gctUINT32_PTR Physical
+    )
+{
+    gctINT8_PTR base, vBase;
+    gctUINT32 offset;
+    PLINUX_MDL_MAP map;
+    gcsUSER_MAPPING_PTR userMap;
+
+    base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->addr;
+
+    /* Check for the logical address match. */
+    if ((base != gcvNULL)
+    &&  ((gctINT8_PTR) Logical >= base)
+    &&  ((gctINT8_PTR) Logical <  base + Mdl->numPages * PAGE_SIZE)
+    )
+    {
+        offset = (gctINT8_PTR) Logical - base;
+
+        if (Mdl->dmaHandle != 0)
+        {
+            /* The memory was from coherent area. */
+            *Physical = (gctUINT32) Mdl->dmaHandle + offset;
+        }
+        else if (Mdl->pagedMem && !Mdl->contiguous)
+        {
+            *Physical = page_to_phys(vmalloc_to_page(base + offset));
+        }
+        else
+        {
+            *Physical = gcmPTR2INT(virt_to_phys(base)) + offset;
+        }
+
+        return gcvSTATUS_OK;
+    }
+
+    /* Walk user maps. */
+    for (userMap = Os->userMap; userMap != gcvNULL; userMap = userMap->next)
+    {
+        if (((gctINT8_PTR) Logical >= userMap->start)
+        &&  ((gctINT8_PTR) Logical <  userMap->end)
+        )
+        {
+            *Physical = userMap->physical
+                      + (gctUINT32) ((gctINT8_PTR) Logical - userMap->start);
+
+            return gcvSTATUS_OK;
+        }
+    }
+
+    if (ProcessID != Os->kernelProcessID)
+    {
+        map   = FindMdlMap(Mdl, (gctINT) ProcessID);
+        vBase = (map == gcvNULL) ? gcvNULL : (gctINT8_PTR) map->vmaAddr;
+
+        /* Is the given address within that range. */
+        if ((vBase != gcvNULL)
+        &&  ((gctINT8_PTR) Logical >= vBase)
+        &&  ((gctINT8_PTR) Logical <  vBase + Mdl->numPages * PAGE_SIZE)
+        )
+        {
+            offset = (gctINT8_PTR) Logical - vBase;
+
+            if (Mdl->dmaHandle != 0)
+            {
+                /* The memory was from coherent area. */
+                *Physical = (gctUINT32) Mdl->dmaHandle + offset;
+            }
+            else if (Mdl->pagedMem && !Mdl->contiguous)
+            {
+                *Physical = page_to_phys(vmalloc_to_page(base + offset));
+            }
+            else
+            {
+                /* Return the kernel virtual pointer based on this. */
+                *Physical = gcmPTR2INT(virt_to_phys(base)) + offset;
+            }
+
+            return gcvSTATUS_OK;
+        }
+    }
+
+    /* Address not yet found. */
+    return gcvSTATUS_INVALID_ADDRESS;
+}
+
+/*******************************************************************************
+**
+**  gckOS_GetPhysicalAddressProcess
+**
+**  Get the physical system address of a corresponding virtual address for a
+**  given process.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to gckOS object.
+**
+**      gctPOINTER Logical
+**          Logical address.
+**
+**      gctUINT32 ProcessID
+**          Process ID.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Address
+**          Poinetr to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS
+gckOS_GetPhysicalAddressProcess(
+    IN gckOS Os,
+    IN gctPOINTER Logical,
+    IN gctUINT32 ProcessID,
+    OUT gctUINT32 * Address
+    )
+{
+    PLINUX_MDL mdl;
+    gctINT8_PTR base;
+    gceSTATUS status = gcvSTATUS_INVALID_ADDRESS;
+
+    gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os, Logical, ProcessID);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    MEMORY_LOCK(Os);
+
+    /* First try the contiguous memory pool. */
+    if (Os->device->contiguousMapped)
+    {
+        base = (gctINT8_PTR) Os->device->contiguousBase;
+
+        if (((gctINT8_PTR) Logical >= base)
+        &&  ((gctINT8_PTR) Logical <  base + Os->device->contiguousSize)
+        )
+        {
+            /* Convert logical address into physical. */
+            *Address = Os->device->contiguousVidMem->baseAddress
+                     + (gctINT8_PTR) Logical - base;
+            status   = gcvSTATUS_OK;
+        }
+    }
+    else
+    {
+        /* Try the contiguous memory pool. */
+        mdl = (PLINUX_MDL) Os->device->contiguousPhysical;
+        status = _ConvertLogical2Physical(Os,
+                                          Logical,
+                                          ProcessID,
+                                          mdl,
+                                          Address);
+    }
+
+    if (gcmIS_ERROR(status))
+    {
+        /* Walk all MDLs. */
+        for (mdl = Os->mdlHead; mdl != gcvNULL; mdl = mdl->next)
+        {
+            /* Try this MDL. */
+            status = _ConvertLogical2Physical(Os,
+                                              Logical,
+                                              ProcessID,
+                                              mdl,
+                                              Address);
+            if (gcmIS_SUCCESS(status))
+            {
+                break;
+            }
+        }
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    gcmkONERROR(status);
+
+    if (Os->device->baseAddress != 0)
+    {
+        /* Subtract base address to get a GPU physical address. */
+        gcmkASSERT(*Address >= Os->device->baseAddress);
+        *Address -= Os->device->baseAddress;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Address=0x%08x", *Address);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_MapPhysical
+**
+**  Map a physical address into kernel space.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctUINT32 Physical
+**          Physical address of the memory to map.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to map.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Logical
+**          Pointer to a variable that receives the base address of the mapped
+**          memory.
+*/
+gceSTATUS
+gckOS_MapPhysical(
+    IN gckOS Os,
+    IN gctUINT32 Physical,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Logical
+    )
+{
+    gctPOINTER logical;
+    PLINUX_MDL mdl;
+    gctUINT32 physical;
+
+    gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+    MEMORY_LOCK(Os);
+
+    /* Compute true physical address (before subtraction of the baseAddress). */
+    physical = Physical + Os->device->baseAddress;
+
+    /* Go through our mapping to see if we know this physical address already. */
+    mdl = Os->mdlHead;
+
+    while (mdl != gcvNULL)
+    {
+        if (mdl->dmaHandle != 0)
+        {
+            if ((physical >= mdl->dmaHandle)
+            &&  (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
+            )
+            {
+                *Logical = mdl->addr + (physical - mdl->dmaHandle);
+                break;
+            }
+        }
+
+        mdl = mdl->next;
+    }
+
+    if (mdl == gcvNULL)
+    {
+        /* Map memory as cached memory. */
+        request_mem_region(physical, Bytes, "MapRegion");
+        logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
+
+        if (logical == gcvNULL)
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO, gcvZONE_OS,
+                "%s(%d): Failed to ioremap",
+                __FUNCTION__, __LINE__
+                );
+
+            MEMORY_UNLOCK(Os);
+
+            /* Out of resources. */
+            gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+
+        /* Return pointer to mapped memory. */
+        *Logical = logical;
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_UnmapPhysical
+**
+**  Unmap a previously mapped memory region from kernel memory.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER Logical
+**          Pointer to the base address of the memory to unmap.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to unmap.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_UnmapPhysical(
+    IN gckOS Os,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    PLINUX_MDL  mdl;
+
+    gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+    MEMORY_LOCK(Os);
+
+    mdl = Os->mdlHead;
+
+    while (mdl != gcvNULL)
+    {
+        if (mdl->addr != gcvNULL)
+        {
+            if (Logical >= (gctPOINTER)mdl->addr
+                    && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
+            {
+                break;
+            }
+        }
+
+        mdl = mdl->next;
+    }
+
+    if (mdl == gcvNULL)
+    {
+        /* Unmap the memory. */
+        iounmap(Logical);
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_CreateMutex
+**
+**  Create a new mutex.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Mutex
+**          Pointer to a variable that will hold a pointer to the mutex.
+*/
+gceSTATUS
+gckOS_CreateMutex(
+    IN gckOS Os,
+    OUT gctPOINTER * Mutex
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X", Os);
+
+    /* Validate the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+    /* Allocate a FAST_MUTEX structure. */
+    *Mutex = (gctPOINTER)kmalloc(sizeof(struct semaphore), GFP_KERNEL);
+
+    if (*Mutex == gcvNULL)
+    {
+        gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    /* Initialize the semaphore.. Come up in unlocked state. */
+    sema_init(*Mutex, 1);
+
+    /* Return status. */
+    gcmkFOOTER_ARG("*Mutex=0x%X", *Mutex);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_DeleteMutex
+**
+**  Delete a mutex.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER Mutex
+**          Pointer to the mute to be deleted.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_DeleteMutex(
+    IN gckOS Os,
+    IN gctPOINTER Mutex
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os, Mutex);
+
+    /* Validate the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+    /* Delete the fast mutex. */
+    kfree(Mutex);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AcquireMutex
+**
+**  Acquire a mutex.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER Mutex
+**          Pointer to the mutex to be acquired.
+**
+**      gctUINT32 Timeout
+**          Timeout value specified in milliseconds.
+**          Specify the value of gcvINFINITE to keep the thread suspended
+**          until the mutex has been acquired.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_AcquireMutex(
+    IN gckOS Os,
+    IN gctPOINTER Mutex,
+    IN gctUINT32 Timeout
+    )
+{
+#if gcdDETECT_TIMEOUT
+    gctUINT32 timeout;
+#endif
+
+    gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os, Mutex, Timeout);
+
+    /* Validate the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+#if gcdDETECT_TIMEOUT
+    timeout = 0;
+
+    for (;;)
+    {
+        /* Try to acquire the mutex. */
+        if (!down_trylock((struct semaphore *) Mutex))
+        {
+            /* Success. */
+            gcmkFOOTER_NO();
+            return gcvSTATUS_OK;
+        }
+
+        /* Advance the timeout. */
+        timeout += 1;
+
+        if (Timeout == gcvINFINITE)
+        {
+            if (timeout == gcdINFINITE_TIMEOUT)
+            {
+                gctUINT32 dmaAddress1, dmaAddress2;
+                gctUINT32 dmaState1, dmaState2;
+
+                dmaState1   = dmaState2   =
+                dmaAddress1 = dmaAddress2 = 0;
+
+                /* Verify whether DMA is running. */
+                gcmkVERIFY_OK(_VerifyDMA(
+                    Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
+                    ));
+
+#if gcdDETECT_DMA_ADDRESS
+                /* Dump only if DMA appears stuck. */
+                if (
+                    (dmaAddress1 == dmaAddress2)
+#if gcdDETECT_DMA_STATE
+                 && (dmaState1   == dmaState2)
+#      endif
+                )
+#   endif
+                {
+                    gcmkVERIFY_OK(_DumpGPUState(Os));
+
+                    gcmkPRINT(
+                        "%s(%d): mutex 0x%X; forced message flush.",
+                        __FUNCTION__, __LINE__, Mutex
+                        );
+
+                    /* Flush the debug cache. */
+                    gcmkDEBUGFLUSH(dmaAddress2);
+                }
+
+                timeout = 0;
+            }
+        }
+        else
+        {
+            /* Timedout? */
+            if (timeout >= Timeout)
+            {
+                break;
+            }
+        }
+
+        /* Wait for 1 millisecond. */
+        gcmkVERIFY_OK(gckOS_Delay(Os, 1));
+    }
+#else
+    if (Timeout == gcvINFINITE)
+    {
+        down((struct semaphore *) Mutex);
+
+        /* Success. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+    for (;;)
+    {
+        /* Try to acquire the mutex. */
+        if (!down_trylock((struct semaphore *) Mutex))
+        {
+            /* Success. */
+            gcmkFOOTER_NO();
+            return gcvSTATUS_OK;
+        }
+
+        if (Timeout-- == 0)
+        {
+            break;
+        }
+
+        /* Wait for 1 millisecond. */
+        gcmkVERIFY_OK(gckOS_Delay(Os, 1));
+    }
+#endif
+
+    /* Timeout. */
+    gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
+    return gcvSTATUS_TIMEOUT;
+}
+
+/*******************************************************************************
+**
+**  gckOS_ReleaseMutex
+**
+**  Release an acquired mutex.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER Mutex
+**          Pointer to the mutex to be released.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_ReleaseMutex(
+    IN gckOS Os,
+    IN gctPOINTER Mutex
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os, Mutex);
+
+    /* Validate the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+    /* Release the fast mutex. */
+    up((struct semaphore *) Mutex);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AtomicExchange
+**
+**  Atomically exchange a pair of 32-bit values.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      IN OUT gctINT32_PTR Target
+**          Pointer to the 32-bit value to exchange.
+**
+**      IN gctINT32 NewValue
+**          Specifies a new value for the 32-bit value pointed to by Target.
+**
+**      OUT gctINT32_PTR OldValue
+**          The old value of the 32-bit value pointed to by Target.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_AtomicExchange(
+    IN gckOS Os,
+    IN OUT gctUINT32_PTR Target,
+    IN gctUINT32 NewValue,
+    OUT gctUINT32_PTR OldValue
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os, Target, NewValue);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    /* Exchange the pair of 32-bit values. */
+    *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*OldValue=%u", *OldValue);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AtomicExchangePtr
+**
+**  Atomically exchange a pair of pointers.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      IN OUT gctPOINTER * Target
+**          Pointer to the 32-bit value to exchange.
+**
+**      IN gctPOINTER NewValue
+**          Specifies a new value for the pointer pointed to by Target.
+**
+**      OUT gctPOINTER * OldValue
+**          The old value of the pointer pointed to by Target.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_AtomicExchangePtr(
+    IN gckOS Os,
+    IN OUT gctPOINTER * Target,
+    IN gctPOINTER NewValue,
+    OUT gctPOINTER * OldValue
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os, Target, NewValue);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    /* Exchange the pair of pointers. */
+    *OldValue = (gctPOINTER) atomic_xchg((atomic_t *) Target, (int) NewValue);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AtomConstruct
+**
+**  Create an atom.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Atom
+**          Pointer to a variable receiving the constructed atom.
+*/
+gceSTATUS
+gckOS_AtomConstruct(
+    IN gckOS Os,
+    OUT gctPOINTER * Atom
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X", Os);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+    /* Allocate the atom. */
+    gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
+
+    /* Initialize the atom. */
+    atomic_set((atomic_t *) *Atom, 0);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Atom=0x%X", *Atom);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AtomDestroy
+**
+**  Destroy an atom.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**      gctPOINTER Atom
+**          Pointer to the atom to destroy.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_AtomDestroy(
+    IN gckOS Os,
+    OUT gctPOINTER Atom
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+    /* Free the atom. */
+    gcmkONERROR(gcmkOS_SAFE_FREE(Os, Atom));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AtomGet
+**
+**  Get the 32-bit value protected by an atom.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**      gctPOINTER Atom
+**          Pointer to the atom.
+**
+**  OUTPUT:
+**
+**      gctINT32_PTR Value
+**          Pointer to a variable the receives the value of the atom.
+*/
+gceSTATUS
+gckOS_AtomGet(
+    IN gckOS Os,
+    IN gctPOINTER Atom,
+    OUT gctINT32_PTR Value
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+    /* Return the current value of atom. */
+    *Value = atomic_read((atomic_t *) Atom);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Value=%d", *Value);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AtomSet
+**
+**  Set the 32-bit value protected by an atom.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**      gctPOINTER Atom
+**          Pointer to the atom.
+**
+**      gctINT32 Value
+**          The value of the atom.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_AtomSet(
+    IN gckOS Os,
+    IN gctPOINTER Atom,
+    IN gctINT32 Value
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os, Atom);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+    /* Set the current value of atom. */
+    atomic_set((atomic_t *) Atom, Value);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AtomIncrement
+**
+**  Atomically increment the 32-bit integer value inside an atom.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**      gctPOINTER Atom
+**          Pointer to the atom.
+**
+**  OUTPUT:
+**
+**      gctINT32_PTR Value
+**          Pointer to a variable that receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomIncrement(
+    IN gckOS Os,
+    IN gctPOINTER Atom,
+    OUT gctINT32_PTR Value
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+    /* Increment the atom. */
+    *Value = atomic_inc_return((atomic_t *) Atom) - 1;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Value=%d", *Value);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AtomDecrement
+**
+**  Atomically decrement the 32-bit integer value inside an atom.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**      gctPOINTER Atom
+**          Pointer to the atom.
+**
+**  OUTPUT:
+**
+**      gctINT32_PTR Value
+**          Pointer to a variable that receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomDecrement(
+    IN gckOS Os,
+    IN gctPOINTER Atom,
+    OUT gctINT32_PTR Value
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+    /* Decrement the atom. */
+    *Value = atomic_dec_return((atomic_t *) Atom) + 1;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Value=%d", *Value);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_Delay
+**
+**  Delay execution of the current thread for a number of milliseconds.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctUINT32 Delay
+**          Delay to sleep, specified in milliseconds.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_Delay(
+    IN gckOS Os,
+    IN gctUINT32 Delay
+    )
+{
+    struct timeval now;
+    unsigned long jiffies;
+
+    gcmkHEADER_ARG("Os=0x%X Delay=%u", Os, Delay);
+
+    if (Delay > 0)
+    {
+        /* Convert milliseconds into seconds and microseconds. */
+        now.tv_sec  = Delay / 1000;
+        now.tv_usec = (Delay % 1000) * 1000;
+
+        /* Convert timeval to jiffies. */
+        jiffies = timeval_to_jiffies(&now);
+
+        /* Schedule timeout. */
+        schedule_timeout_interruptible(jiffies);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_GetTicks
+**
+**  Get the number of milliseconds since the system started.
+**
+**  INPUT:
+**
+**  OUTPUT:
+**
+**      gctUINT32_PTR Time
+**          Pointer to a variable to get time.
+**
+*/
+gceSTATUS
+gckOS_GetTicks(
+    OUT gctUINT32_PTR Time
+    )
+{
+     gcmkHEADER();
+
+    *Time = jiffies * 1000 / HZ;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_TicksAfter
+**
+**  Compare time values got from gckOS_GetTicks.
+**
+**  INPUT:
+**      gctUINT32 Time1
+**          First time value to be compared.
+**
+**      gctUINT32 Time2
+**          Second time value to be compared.
+**
+**  OUTPUT:
+**
+**      gctBOOL_PTR IsAfter
+**          Pointer to a variable to result.
+**
+*/
+gceSTATUS
+gckOS_TicksAfter(
+    IN gctUINT32 Time1,
+    IN gctUINT32 Time2,
+    OUT gctBOOL_PTR IsAfter
+    )
+{
+    gcmkHEADER();
+
+    *IsAfter = time_after((unsigned long)Time1, (unsigned long)Time2);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_GetTime
+**
+**  Get the number of microseconds since the system started.
+**
+**  INPUT:
+**
+**  OUTPUT:
+**
+**      gctUINT64_PTR Time
+**          Pointer to a variable to get time.
+**
+*/
+gceSTATUS
+gckOS_GetTime(
+    OUT gctUINT64_PTR Time
+    )
+{
+    gcmkHEADER();
+
+    *Time = 0;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_MemoryBarrier
+**
+**  Make sure the CPU has executed everything up to this point and the data got
+**  written to the specified pointer.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER Address
+**          Address of memory that needs to be barriered.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_MemoryBarrier(
+    IN gckOS Os,
+    IN gctPOINTER Address
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os, Address);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+#if gcdNONPAGED_MEMORY_BUFFERABLE \
+    && defined (CONFIG_ARM) \
+    && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+    /* drain write buffer */
+    dsb();
+
+    /* drain outer cache's write buffer? */
+#else
+    mb();
+#endif
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AllocatePagedMemory
+**
+**  Allocate memory from the paged pool.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to allocate.
+**
+**  OUTPUT:
+**
+**      gctPHYS_ADDR * Physical
+**          Pointer to a variable that receives the physical address of the
+**          memory allocation.
+*/
+gceSTATUS
+gckOS_AllocatePagedMemory(
+    IN gckOS Os,
+    IN gctSIZE_T Bytes,
+    OUT gctPHYS_ADDR * Physical
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+
+    /* Allocate the memory. */
+    gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical));
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AllocatePagedMemoryEx
+**
+**  Allocate memory from the paged pool.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctBOOL Contiguous
+**          Need contiguous memory or not.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes to allocate.
+**
+**  OUTPUT:
+**
+**      gctPHYS_ADDR * Physical
+**          Pointer to a variable that receives the physical address of the
+**          memory allocation.
+*/
+gceSTATUS
+gckOS_AllocatePagedMemoryEx(
+    IN gckOS Os,
+    IN gctBOOL Contiguous,
+    IN gctSIZE_T Bytes,
+    OUT gctPHYS_ADDR * Physical
+    )
+{
+    gctINT numPages;
+    gctINT i;
+    PLINUX_MDL mdl = gcvNULL;
+    gctSTRING addr;
+    gctSIZE_T bytes;
+    gctBOOL locked = gcvFALSE;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+
+    bytes = gcmALIGN(Bytes, PAGE_SIZE);
+
+    numPages = GetPageCount(bytes, 0);
+
+    MEMORY_LOCK(Os);
+    locked = gcvTRUE;
+
+    mdl = _CreateMdl(_GetProcessID());
+    if (mdl == gcvNULL)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    if (Contiguous)
+    {
+        /* Get free pages, and suppress warning (stack dump) from kernel when
+           we run out of memory. */
+        addr = (char *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN, GetOrder(numPages));
+    }
+    else
+    {
+        addr = vmalloc(bytes);
+    }
+
+    if (addr == gcvNULL)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    mdl->dmaHandle  = 0;
+    mdl->addr       = addr;
+    mdl->numPages   = numPages;
+    mdl->pagedMem   = 1;
+    mdl->contiguous = Contiguous;
+
+    for (i = 0; i < mdl->numPages; i++)
+    {
+        struct page *page;
+
+        if (mdl->contiguous)
+        {
+            page = virt_to_page(addr + i * PAGE_SIZE);
+        }
+        else
+        {
+            page = vmalloc_to_page(addr + i * PAGE_SIZE);
+        }
+
+        SetPageReserved(page);
+        flush_dcache_page(page);
+    }
+
+    /* Return physical address. */
+    *Physical = (gctPHYS_ADDR) mdl;
+
+    /*
+     * Add this to a global list.
+     * Will be used by get physical address
+     * and mapuser pointer functions.
+     */
+    if (!Os->mdlHead)
+    {
+        /* Initialize the queue. */
+        Os->mdlHead = Os->mdlTail = mdl;
+    }
+    else
+    {
+        /* Add to tail. */
+        mdl->prev           = Os->mdlTail;
+        Os->mdlTail->next   = mdl;
+        Os->mdlTail         = mdl;
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (mdl != gcvNULL)
+    {
+        /* Free the memory. */
+        _DestroyMdl(mdl);
+    }
+
+    if (locked)
+    {
+        /* Unlock the memory. */
+        MEMORY_UNLOCK(Os);
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_FreePagedMemory
+**
+**  Free memory allocated from the paged pool.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPHYS_ADDR Physical
+**          Physical address of the allocation.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes of the allocation.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_FreePagedMemory(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes
+    )
+{
+    PLINUX_MDL mdl = (PLINUX_MDL) Physical;
+    gctSTRING addr;
+    gctINT i;
+
+    gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+    addr = mdl->addr;
+
+    MEMORY_LOCK(Os);
+
+    for (i = 0; i < mdl->numPages; i++)
+    {
+        if (mdl->contiguous)
+        {
+            ClearPageReserved(virt_to_page((gctPOINTER)(((unsigned long)addr) + i * PAGE_SIZE)));
+        }
+        else
+        {
+            ClearPageReserved(vmalloc_to_page((gctPOINTER)(((unsigned long)addr) + i * PAGE_SIZE)));
+        }
+    }
+
+    if (mdl->contiguous)
+    {
+        free_pages((unsigned long)mdl->addr, GetOrder(mdl->numPages));
+    }
+    else
+    {
+        vfree(mdl->addr);
+    }
+
+    /* Remove the node from global list. */
+    if (mdl == Os->mdlHead)
+    {
+        if ((Os->mdlHead = mdl->next) == gcvNULL)
+        {
+            Os->mdlTail = gcvNULL;
+        }
+    }
+    else
+    {
+        mdl->prev->next = mdl->next;
+
+        if (mdl == Os->mdlTail)
+        {
+            Os->mdlTail = mdl->prev;
+        }
+        else
+        {
+            mdl->next->prev = mdl->prev;
+        }
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    /* Free the structure... */
+    gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_LockPages
+**
+**  Lock memory allocated from the paged pool.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPHYS_ADDR Physical
+**          Physical address of the allocation.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes of the allocation.
+**
+**      gctBOOL Cacheable
+**          Cache mode of mapping.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Logical
+**          Pointer to a variable that receives the address of the mapped
+**          memory.
+**
+**      gctSIZE_T * PageCount
+**          Pointer to a variable that receives the number of pages required for
+**          the page table according to the GPU page size.
+*/
+gceSTATUS
+gckOS_LockPages(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctBOOL Cacheable,
+    OUT gctPOINTER * Logical,
+    OUT gctSIZE_T * PageCount
+    )
+{
+    PLINUX_MDL      mdl;
+    PLINUX_MDL_MAP  mdlMap;
+    gctSTRING       addr;
+    unsigned long   start;
+    unsigned long   pfn;
+    gctINT          i;
+
+    gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
+
+    mdl = (PLINUX_MDL) Physical;
+
+    MEMORY_LOCK(Os);
+
+    mdlMap = FindMdlMap(mdl, _GetProcessID());
+
+    if (mdlMap == gcvNULL)
+    {
+        mdlMap = _CreateMdlMap(mdl, _GetProcessID());
+
+        if (mdlMap == gcvNULL)
+        {
+            MEMORY_UNLOCK(Os);
+
+            gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+            return gcvSTATUS_OUT_OF_MEMORY;
+        }
+    }
+
+    if (mdlMap->vmaAddr == gcvNULL)
+    {
+        down_write(&current->mm->mmap_sem);
+
+        mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(gcvNULL,
+                        0L,
+                        mdl->numPages * PAGE_SIZE,
+                        PROT_READ | PROT_WRITE,
+                        MAP_SHARED,
+                        0);
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS,
+            "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
+            __FUNCTION__, __LINE__,
+            (gctUINT32) mdlMap->vmaAddr,
+            (gctUINT32) mdl
+            );
+
+        if (IS_ERR(mdlMap->vmaAddr))
+        {
+            up_write(&current->mm->mmap_sem);
+
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO, gcvZONE_OS,
+                "%s(%d): do_mmap_pgoff error",
+                __FUNCTION__, __LINE__
+                );
+
+            mdlMap->vmaAddr = gcvNULL;
+
+            MEMORY_UNLOCK(Os);
+
+            gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+            return gcvSTATUS_OUT_OF_MEMORY;
+        }
+
+        mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+        if (mdlMap->vma == gcvNULL)
+        {
+            up_write(&current->mm->mmap_sem);
+
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO, gcvZONE_OS,
+                "%s(%d): find_vma error",
+                __FUNCTION__, __LINE__
+                );
+
+            mdlMap->vmaAddr = gcvNULL;
+
+            MEMORY_UNLOCK(Os);
+
+            gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+
+        mdlMap->vma->vm_flags |= VM_RESERVED;
+#if !gcdPAGED_MEMORY_CACHEABLE
+        if (Cacheable == gcvFALSE)
+        {
+            /* Make this mapping non-cached. */
+            mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
+        }
+#endif
+        addr = mdl->addr;
+
+        /* Now map all the vmalloc pages to this user address. */
+        if (mdl->contiguous)
+        {
+            /* map kernel memory to user space.. */
+            if (remap_pfn_range(mdlMap->vma,
+                                mdlMap->vma->vm_start,
+                                virt_to_phys((gctPOINTER)mdl->addr) >> PAGE_SHIFT,
+                                mdlMap->vma->vm_end - mdlMap->vma->vm_start,
+                                mdlMap->vma->vm_page_prot) < 0)
+            {
+                up_write(&current->mm->mmap_sem);
+
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_INFO, gcvZONE_OS,
+                    "%s(%d): unable to mmap ret",
+                    __FUNCTION__, __LINE__
+                    );
+
+                mdlMap->vmaAddr = gcvNULL;
+
+                MEMORY_UNLOCK(Os);
+
+                gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+                return gcvSTATUS_OUT_OF_MEMORY;
+            }
+        }
+        else
+        {
+            start = mdlMap->vma->vm_start;
+
+            for (i = 0; i < mdl->numPages; i++)
+            {
+                pfn = vmalloc_to_pfn(addr);
+
+                if (remap_pfn_range(mdlMap->vma,
+                                    start,
+                                    pfn,
+                                    PAGE_SIZE,
+                                    mdlMap->vma->vm_page_prot) < 0)
+                {
+                    up_write(&current->mm->mmap_sem);
+
+                    gcmkTRACE_ZONE(
+                        gcvLEVEL_INFO, gcvZONE_OS,
+                        "%s(%d): gctPHYS_ADDR->0x%X Logical->0x%X Unable to map addr->0x%X to start->0x%X",
+                        __FUNCTION__, __LINE__,
+                        (gctUINT32) Physical,
+                        (gctUINT32) *Logical,
+                        (gctUINT32) addr,
+                        (gctUINT32) start
+                        );
+
+                    mdlMap->vmaAddr = gcvNULL;
+
+                    MEMORY_UNLOCK(Os);
+
+                    gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+                    return gcvSTATUS_OUT_OF_MEMORY;
+                }
+
+                start += PAGE_SIZE;
+                addr += PAGE_SIZE;
+            }
+        }
+
+        up_write(&current->mm->mmap_sem);
+    }
+    else
+    {
+        /* mdlMap->vmaAddr != gcvNULL means current process has already locked this node. */
+        MEMORY_UNLOCK(Os);
+
+        gcmkFOOTER_ARG("*status=%d, mdlMap->vmaAddr=%x", gcvSTATUS_MEMORY_LOCKED, mdlMap->vmaAddr);
+        return gcvSTATUS_MEMORY_LOCKED;
+    }
+
+    /* Convert pointer to MDL. */
+    *Logical = mdlMap->vmaAddr;
+
+    /* Return the page number according to the GPU page size. */
+    gcmkASSERT((PAGE_SIZE % 4096) == 0);
+    gcmkASSERT((PAGE_SIZE / 4096) >= 1);
+
+    *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
+
+    MEMORY_UNLOCK(Os);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical, *PageCount);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_MapPages
+**
+**  Map paged memory into a page table.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPHYS_ADDR Physical
+**          Physical address of the allocation.
+**
+**      gctSIZE_T PageCount
+**          Number of pages required for the physical address.
+**
+**      gctPOINTER PageTable
+**          Pointer to the page table to fill in.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_MapPages(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T PageCount,
+    IN gctPOINTER PageTable
+    )
+{
+    return gckOS_MapPagesEx(Os,
+                            gcvCORE_MAJOR,
+                            Physical,
+                            PageCount,
+                            PageTable);
+}
+
+gceSTATUS
+gckOS_MapPagesEx(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T PageCount,
+    IN gctPOINTER PageTable
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+    PLINUX_MDL  mdl;
+    gctUINT32*  table;
+    gctSTRING   addr;
+    gctUINT32   bytes;
+    gckMMU      mmu;
+    PLINUX_MDL  mmuMdl;
+    gctPHYS_ADDR pageTablePhysical;
+
+    gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
+                   Os, Core, Physical, PageCount, PageTable);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(PageCount > 0);
+    gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+
+    /* Convert pointer to MDL. */
+    mdl = (PLINUX_MDL)Physical;
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_INFO, gcvZONE_OS,
+        "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
+        __FUNCTION__, __LINE__,
+        (gctUINT32) Physical,
+        (gctUINT32) PageCount,
+        mdl->pagedMem
+        );
+
+    MEMORY_LOCK(Os);
+
+    table = (gctUINT32 *)PageTable;
+    bytes = PageCount * sizeof(*table);
+    mmu = Os->device->kernels[Core]->mmu;
+    mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical;
+
+     /* Get all the physical addresses and store them in the page table. */
+
+    addr = mdl->addr;
+
+    if (mdl->pagedMem)
+    {
+        /* Try to get the user pages so DMA can happen. */
+        while (PageCount-- > 0)
+        {
+#if gcdENABLE_VG
+            if (Core == gcvCORE_VG)
+            {
+                if (mdl->contiguous)
+                {
+                    gcmkONERROR(
+                        gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
+                                             virt_to_phys(addr),
+                                             table));
+                }
+                else
+                {
+                    gcmkONERROR(
+                        gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
+                                             page_to_phys(vmalloc_to_page(addr)),
+                                             table));
+                }
+            }
+            else
+#endif
+            {
+                if (mdl->contiguous)
+                {
+                    gcmkONERROR(
+                        gckMMU_SetPage(Os->device->kernels[Core]->mmu,
+                                             virt_to_phys(addr),
+                                             table));
+                }
+                else
+                {
+                    gcmkONERROR(
+                        gckMMU_SetPage(Os->device->kernels[Core]->mmu,
+                                             page_to_phys(vmalloc_to_page(addr)),
+                                             table));
+                }
+            }
+
+            table++;
+            addr += 4096;
+        }
+    }
+    else
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS,
+            "%s(%d): we should not get this call for Non Paged Memory!",
+            __FUNCTION__, __LINE__
+            );
+
+        while (PageCount-- > 0)
+        {
+#if gcdENABLE_VG
+            if (Core == gcvCORE_VG)
+            {
+                gcmkONERROR(
+                        gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
+                                         (gctUINT32)virt_to_phys(addr),
+                                         table));
+            }
+            else
+#endif
+            {
+                gcmkONERROR(
+                        gckMMU_SetPage(Os->device->kernels[Core]->mmu,
+                                         (gctUINT32)virt_to_phys(addr),
+                                         table));
+            }
+            table++;
+            addr += 4096;
+        }
+    }
+
+    /* Get physical address of pageTable */
+    pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle +
+                        ((gctUINT32 *)PageTable - mmu->pageTableLogical));
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+    /* Flush the mmu page table cache. */
+    gcmkONERROR(gckOS_CacheClean(
+        Os,
+        _GetProcessID(),
+        gcvNULL,
+        pageTablePhysical,
+        PageTable,
+        bytes
+        ));
+#endif
+
+OnError:
+
+    MEMORY_UNLOCK(Os);
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_UnlockPages
+**
+**  Unlock memory allocated from the paged pool.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPHYS_ADDR Physical
+**          Physical address of the allocation.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes of the allocation.
+**
+**      gctPOINTER Logical
+**          Address of the mapped memory.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_UnlockPages(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctPOINTER Logical
+    )
+{
+    PLINUX_MDL_MAP          mdlMap;
+    PLINUX_MDL              mdl = (PLINUX_MDL)Physical;
+    struct task_struct *    task;
+
+    gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
+                   Os, Physical, Bytes, Logical);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+    /* Make sure there is already a mapping...*/
+    gcmkVERIFY_ARGUMENT(mdl->addr != gcvNULL);
+
+    MEMORY_LOCK(Os);
+
+    mdlMap = mdl->maps;
+
+    while (mdlMap != gcvNULL)
+    {
+        if ((mdlMap->vmaAddr != gcvNULL) && (_GetProcessID() == mdlMap->pid))
+        {
+            /* Get the current pointer for the task with stored pid. */
+            task = FIND_TASK_BY_PID(mdlMap->pid);
+
+            if (task != gcvNULL && task->mm != gcvNULL)
+            {
+                down_write(&task->mm->mmap_sem);
+                do_munmap(task->mm, (unsigned long)mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
+                up_write(&task->mm->mmap_sem);
+            }
+
+            mdlMap->vmaAddr = gcvNULL;
+        }
+
+        mdlMap = mdlMap->next;
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+**  gckOS_AllocateContiguous
+**
+**  Allocate memory from the contiguous pool.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctBOOL InUserSpace
+**          gcvTRUE if the pages need to be mapped into user space.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes to allocate.
+**
+**  OUTPUT:
+**
+**      gctSIZE_T * Bytes
+**          Pointer to a variable that receives the number of bytes allocated.
+**
+**      gctPHYS_ADDR * Physical
+**          Pointer to a variable that receives the physical address of the
+**          memory allocation.
+**
+**      gctPOINTER * Logical
+**          Pointer to a variable that receives the logical address of the
+**          memory allocation.
+*/
+gceSTATUS
+gckOS_AllocateContiguous(
+    IN gckOS Os,
+    IN gctBOOL InUserSpace,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctPHYS_ADDR * Physical,
+    OUT gctPOINTER * Logical
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
+                   Os, InUserSpace, gcmOPT_VALUE(Bytes));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
+    gcmkVERIFY_ARGUMENT(*Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+    /* Same as non-paged memory for now. */
+    gcmkONERROR(gckOS_AllocateNonPagedMemory(Os,
+                                             InUserSpace,
+                                             Bytes,
+                                             Physical,
+                                             Logical));
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
+                   *Bytes, *Physical, *Logical);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_FreeContiguous
+**
+**  Free memory allocated from the contiguous pool.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPHYS_ADDR Physical
+**          Physical address of the allocation.
+**
+**      gctPOINTER Logical
+**          Logicval address of the allocation.
+**
+**      gctSIZE_T Bytes
+**          Number of bytes of the allocation.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_FreeContiguous(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
+                   Os, Physical, Logical, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+    /* Same of non-paged memory for now. */
+    gcmkONERROR(gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+#if gcdENABLE_VG
+/******************************************************************************
+**
+**  gckOS_GetKernelLogical
+**
+**  Return the kernel logical pointer that corresponods to the specified
+**  hardware address.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctUINT32 Address
+**          Hardware physical address.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * KernelPointer
+**          Pointer to a variable receiving the pointer in kernel address space.
+*/
+gceSTATUS
+gckOS_GetKernelLogical(
+    IN gckOS Os,
+    IN gctUINT32 Address,
+    OUT gctPOINTER * KernelPointer
+    )
+{
+    return gckOS_GetKernelLogicalEx(Os, gcvCORE_MAJOR, Address, KernelPointer);
+}
+
+gceSTATUS
+gckOS_GetKernelLogicalEx(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctUINT32 Address,
+    OUT gctPOINTER * KernelPointer
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%08x", Os, Core, Address);
+
+    do
+    {
+        gckGALDEVICE device;
+        gckKERNEL kernel;
+        gcePOOL pool;
+        gctUINT32 offset;
+        gctPOINTER logical;
+
+        /* Extract the pointer to the gckGALDEVICE class. */
+        device = (gckGALDEVICE) Os->device;
+
+        /* Kernel shortcut. */
+        kernel = device->kernels[Core];
+#if gcdENABLE_VG
+       if (Core == gcvCORE_VG)
+       {
+           gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(
+                kernel->vg->hardware, Address, &pool, &offset
+                ));
+       }
+       else
+#endif
+       {
+        /* Split the memory address into a pool type and offset. */
+            gcmkERR_BREAK(gckHARDWARE_SplitMemory(
+                kernel->hardware, Address, &pool, &offset
+                ));
+       }
+
+        /* Dispatch on pool. */
+        switch (pool)
+        {
+        case gcvPOOL_LOCAL_INTERNAL:
+            /* Internal memory. */
+            logical = device->internalLogical;
+            break;
+
+        case gcvPOOL_LOCAL_EXTERNAL:
+            /* External memory. */
+            logical = device->externalLogical;
+            break;
+
+        case gcvPOOL_SYSTEM:
+            /* System memory. */
+            logical = device->contiguousBase;
+            break;
+
+        default:
+            /* Invalid memory pool. */
+            return gcvSTATUS_INVALID_ARGUMENT;
+        }
+
+        /* Build logical address of specified address. */
+        * KernelPointer = ((gctUINT8_PTR) logical) + offset;
+
+        /* Success. */
+        gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    gcmkFOOTER();
+    return status;
+}
+#endif
+
+/*******************************************************************************
+**
+**  gckOS_MapUserPointer
+**
+**  Map a pointer from the user process into the kernel address space.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER Pointer
+**          Pointer in user process space that needs to be mapped.
+**
+**      gctSIZE_T Size
+**          Number of bytes that need to be mapped.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * KernelPointer
+**          Pointer to a variable receiving the mapped pointer in kernel address
+**          space.
+*/
+gceSTATUS
+gckOS_MapUserPointer(
+    IN gckOS Os,
+    IN gctPOINTER Pointer,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * KernelPointer
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os, Pointer, Size);
+
+#if NO_USER_DIRECT_ACCESS_FROM_KERNEL
+{
+    gctPOINTER buf = gcvNULL;
+    gctUINT32 len;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Size > 0);
+    gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+
+    buf = kmalloc(Size, GFP_KERNEL);
+    if (buf == gcvNULL)
+    {
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): Failed to allocate memory.",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    len = copy_from_user(buf, Pointer, Size);
+    if (len != 0)
+    {
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): Failed to copy data from user.",
+            __FUNCTION__, __LINE__
+            );
+
+        if (buf != gcvNULL)
+        {
+            kfree(buf);
+        }
+
+        gcmkFOOTER_ARG("*status=%d", gcvSTATUS_GENERIC_IO);
+        return gcvSTATUS_GENERIC_IO;
+    }
+
+    *KernelPointer = buf;
+}
+#else
+    *KernelPointer = Pointer;
+#endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
+
+    gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_UnmapUserPointer
+**
+**  Unmap a user process pointer from the kernel address space.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER Pointer
+**          Pointer in user process space that needs to be unmapped.
+**
+**      gctSIZE_T Size
+**          Number of bytes that need to be unmapped.
+**
+**      gctPOINTER KernelPointer
+**          Pointer in kernel address space that needs to be unmapped.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserPointer(
+    IN gckOS Os,
+    IN gctPOINTER Pointer,
+    IN gctSIZE_T Size,
+    IN gctPOINTER KernelPointer
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
+                   Os, Pointer, Size, KernelPointer);
+
+#if NO_USER_DIRECT_ACCESS_FROM_KERNEL
+{
+    gctUINT32 len;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Size > 0);
+    gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+
+    len = copy_to_user(Pointer, KernelPointer, Size);
+
+    kfree(KernelPointer);
+
+    if (len != 0)
+    {
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): Failed to copy data to user.",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkFOOTER_ARG("status=%d", gcvSTATUS_GENERIC_IO);
+        return gcvSTATUS_GENERIC_IO;
+    }
+}
+#endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_QueryNeedCopy
+**
+**  Query whether the memory can be accessed or mapped directly or it has to be
+**  copied.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctUINT32 ProcessID
+**          Process ID of the current process.
+**
+**  OUTPUT:
+**
+**      gctBOOL_PTR NeedCopy
+**          Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
+**          gcvFALSE if the memory can be accessed or mapped dircetly.
+*/
+gceSTATUS
+gckOS_QueryNeedCopy(
+    IN gckOS Os,
+    IN gctUINT32 ProcessID,
+    OUT gctBOOL_PTR NeedCopy
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os, ProcessID);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(NeedCopy != gcvNULL);
+
+#if NO_USER_DIRECT_ACCESS_FROM_KERNEL
+    /* We need to copy data. */
+    *NeedCopy = gcvTRUE;
+#else
+    /* No need to copy data. */
+    *NeedCopy = gcvFALSE;
+#endif
+
+    /* Success. */
+    gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_CopyFromUserData
+**
+**  Copy data from user to kernel memory.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER KernelPointer
+**          Pointer to kernel memory.
+**
+**      gctPOINTER Pointer
+**          Pointer to user memory.
+**
+**      gctSIZE_T Size
+**          Number of bytes to copy.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_CopyFromUserData(
+    IN gckOS Os,
+    IN gctPOINTER KernelPointer,
+    IN gctPOINTER Pointer,
+    IN gctSIZE_T Size
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
+                   Os, KernelPointer, Pointer, Size);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Size > 0);
+
+    /* Copy data from user. */
+    if (copy_from_user(KernelPointer, Pointer, Size) != 0)
+    {
+        /* Could not copy all the bytes. */
+        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_CopyToUserData
+**
+**  Copy data from kernel to user memory.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER KernelPointer
+**          Pointer to kernel memory.
+**
+**      gctPOINTER Pointer
+**          Pointer to user memory.
+**
+**      gctSIZE_T Size
+**          Number of bytes to copy.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_CopyToUserData(
+    IN gckOS Os,
+    IN gctPOINTER KernelPointer,
+    IN gctPOINTER Pointer,
+    IN gctSIZE_T Size
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
+                   Os, KernelPointer, Pointer, Size);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Size > 0);
+
+    /* Copy data to user. */
+    if (copy_to_user(Pointer, KernelPointer, Size) != 0)
+    {
+        /* Could not copy all the bytes. */
+        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_WriteMemory
+**
+**  Write data to a memory.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER Address
+**          Address of the memory to write to.
+**
+**      gctUINT32 Data
+**          Data for register.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_WriteMemory(
+    IN gckOS Os,
+    IN gctPOINTER Address,
+    IN gctUINT32 Data
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    /* Write memory. */
+    writel(Data, (gctUINT8 *)Address);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_MapUserMemory
+**
+**  Lock down a user buffer and return an DMA'able address to be used by the
+**  hardware to access it.
+**
+**  INPUT:
+**
+**      gctPOINTER Memory
+**          Pointer to memory to lock down.
+**
+**      gctSIZE_T Size
+**          Size in bytes of the memory to lock down.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Info
+**          Pointer to variable receiving the information record required by
+**          gckOS_UnmapUserMemory.
+**
+**      gctUINT32_PTR Address
+**          Pointer to a variable that will receive the address DMA'able by the
+**          hardware.
+*/
+gceSTATUS
+gckOS_MapUserMemory(
+    IN gckOS Os,
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * Info,
+    OUT gctUINT32_PTR Address
+    )
+{
+    return gckOS_MapUserMemoryEx(Os, gcvCORE_MAJOR, Memory, Size, Info, Address);
+}
+
+gceSTATUS
+gckOS_MapUserMemoryEx(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * Info,
+    OUT gctUINT32_PTR Address
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%x Core=%d Memory=0x%x Size=%lu", Os, Core, Memory, Size);
+
+#if gcdSECURE_USER
+    gcmkONERROR(gckOS_AddMapping(Os, *Address, Memory, Size));
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+#else
+{
+    gctSIZE_T pageCount, i, j;
+    gctUINT32_PTR pageTable;
+    gctUINT32 address;
+    gctUINT32 start, end, memory;
+    gctINT result = 0;
+
+    gcsPageInfo_PTR info = gcvNULL;
+    struct page **pages = gcvNULL;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Size > 0);
+    gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    do
+    {
+        memory = (gctUINT32) Memory;
+
+        /* Get the number of required pages. */
+        end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+        start = memory >> PAGE_SHIFT;
+        pageCount = end - start;
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS,
+            "%s(%d): pageCount: %d.",
+            __FUNCTION__, __LINE__,
+            pageCount
+            );
+
+        /* Invalid argument. */
+        if (pageCount == 0)
+        {
+            gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+            return gcvSTATUS_INVALID_ARGUMENT;
+        }
+
+        /* Overflow. */
+        if ((memory + Size) < memory)
+        {
+            gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+            return gcvSTATUS_INVALID_ARGUMENT;
+        }
+
+        MEMORY_MAP_LOCK(Os);
+
+        /* Allocate the Info struct. */
+        info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL);
+
+        if (info == gcvNULL)
+        {
+            status = gcvSTATUS_OUT_OF_MEMORY;
+            break;
+        }
+
+        /* Allocate the array of page addresses. */
+        pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL);
+
+        if (pages == gcvNULL)
+        {
+            status = gcvSTATUS_OUT_OF_MEMORY;
+            break;
+        }
+
+        /* Get the user pages. */
+        down_read(&current->mm->mmap_sem);
+        result = get_user_pages(current,
+                    current->mm,
+                    memory & PAGE_MASK,
+                    pageCount,
+                    1,
+                    0,
+                    pages,
+                    gcvNULL
+                    );
+        up_read(&current->mm->mmap_sem);
+
+        if (result <=0 || result < pageCount)
+        {
+            struct vm_area_struct *vma;
+
+            vma = find_vma(current->mm, memory);
+
+            if (vma && (vma->vm_flags & VM_PFNMAP) )
+            {
+                do
+                {
+                    pte_t       * pte;
+                    spinlock_t  * ptl;
+                    unsigned long pfn;
+
+                    pgd_t * pgd = pgd_offset(current->mm, memory);
+                    pud_t * pud = pud_offset(pgd, memory);
+                    if (pud)
+                    {
+                        pmd_t * pmd = pmd_offset(pud, memory);
+                        pte = pte_offset_map_lock(current->mm, pmd, memory, &ptl);
+                        if (!pte)
+                        {
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        break;
+                    }
+
+                    pfn      = pte_pfn(*pte);
+                    *Address = ((pfn << PAGE_SHIFT) | (((unsigned long)Memory) & ~PAGE_MASK))
+                                - Os->device->baseAddress;
+                    *Info    = gcvNULL;
+
+                    pte_unmap_unlock(pte, ptl);
+
+                    /* Release page info struct. */
+                    if (info != gcvNULL)
+                    {
+                        /* Free the page info struct. */
+                        kfree(info);
+                    }
+
+                    /* Free the page table. */
+                    if (pages != gcvNULL)
+                    {
+                        /* Release the pages if any. */
+                        if (result > 0)
+                        {
+                            for (i = 0; i < result; i++)
+                            {
+                                if (pages[i] == gcvNULL)
+                                {
+                                    break;
+                                }
+
+                                page_cache_release(pages[i]);
+                            }
+                        }
+
+                        kfree(pages);
+                    }
+
+                    MEMORY_MAP_UNLOCK(Os);
+
+                    gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
+                                   *Info, *Address);
+                    return gcvSTATUS_OK;
+                }
+                while (gcvFALSE);
+
+                *Address = ~0;
+                *Info = gcvNULL;
+
+                status = gcvSTATUS_OUT_OF_RESOURCES;
+                break;
+            }
+            else
+            {
+                status = gcvSTATUS_OUT_OF_RESOURCES;
+                break;
+            }
+        }
+
+        for (i = 0; i < pageCount; i++)
+        {
+            /* Flush(clean) the data cache. */
+#if !defined(ANDROID)
+            dma_sync_single_for_device(
+                        gcvNULL,
+                        page_to_phys(pages[i]),
+                        PAGE_SIZE,
+                        DMA_TO_DEVICE);
+#else
+            flush_dcache_page(pages[i]);
+#endif
+        }
+
+#if gcdENABLE_VG
+        if (Core == gcvCORE_VG)
+        {
+            /* Allocate pages inside the page table. */
+            gcmkERR_BREAK(gckVGMMU_AllocatePages(Os->device->kernels[Core]->vg->mmu,
+                                              pageCount * (PAGE_SIZE/4096),
+                                              (gctPOINTER *) &pageTable,
+                                              &address));
+        }
+        else
+#endif
+        {
+            /* Allocate pages inside the page table. */
+            gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernels[Core]->mmu,
+                                              pageCount * (PAGE_SIZE/4096),
+                                              (gctPOINTER *) &pageTable,
+                                              &address));
+        }
+        /* Fill the page table. */
+        for (i = 0; i < pageCount; i++)
+        {
+#if gcdENABLE_VG
+            if (Core == gcvCORE_VG)
+            {
+                /* Get the physical address from page struct. */
+                gcmkONERROR(
+                    gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
+                                   page_to_phys(pages[i]),
+                                   pageTable + i * (PAGE_SIZE/4096)));
+            }
+            else
+#endif
+            {
+                /* Get the physical address from page struct. */
+                gcmkONERROR(
+                    gckMMU_SetPage(Os->device->kernels[Core]->mmu,
+                                   page_to_phys(pages[i]),
+                                   pageTable + i * (PAGE_SIZE/4096)));
+            }
+
+            for (j = 1; j < (PAGE_SIZE/4096); j++)
+            {
+                pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
+            }
+
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO, gcvZONE_OS,
+                "%s(%d): pages[%d]: 0x%X, pageTable[%d]: 0x%X.",
+                __FUNCTION__, __LINE__,
+                i, pages[i],
+                i, pageTable[i]);
+        }
+
+        /* Save pointer to page table. */
+        info->pageTable = pageTable;
+        info->pages = pages;
+
+        *Info = (gctPOINTER) info;
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS,
+            "%s(%d): info->pages: 0x%X, info->pageTable: 0x%X, info: 0x%X.",
+            __FUNCTION__, __LINE__,
+            info->pages,
+            info->pageTable,
+            info
+            );
+
+        /* Return address. */
+        *Address = address + (memory & ~PAGE_MASK);
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS,
+            "%s(%d): Address: 0x%X.",
+            __FUNCTION__, __LINE__,
+            *Address
+            );
+
+        /* Success. */
+        status = gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+OnError:
+
+    if (gcmIS_ERROR(status))
+    {
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): error occured: %d.",
+            __FUNCTION__, __LINE__,
+            status
+            );
+
+        /* Release page array. */
+        if (result > 0 && pages != gcvNULL)
+        {
+            gcmkTRACE(
+                gcvLEVEL_ERROR,
+                "%s(%d): error: page table is freed.",
+                __FUNCTION__, __LINE__
+                );
+
+            for (i = 0; i < result; i++)
+            {
+                if (pages[i] == gcvNULL)
+                {
+                    break;
+                }
+                page_cache_release(pages[i]);
+            }
+        }
+
+        if (info!= gcvNULL && pages != gcvNULL)
+        {
+            gcmkTRACE(
+                gcvLEVEL_ERROR,
+                "%s(%d): error: pages is freed.",
+                __FUNCTION__, __LINE__
+                );
+
+            /* Free the page table. */
+            kfree(pages);
+            info->pages = gcvNULL;
+        }
+
+        /* Release page info struct. */
+        if (info != gcvNULL)
+        {
+            gcmkTRACE(
+                gcvLEVEL_ERROR,
+                "%s(%d): error: info is freed.",
+                __FUNCTION__, __LINE__
+                );
+
+            /* Free the page info struct. */
+            kfree(info);
+            *Info = gcvNULL;
+        }
+    }
+
+    MEMORY_MAP_UNLOCK(Os);
+
+    /* Return the status. */
+    if (gcmIS_SUCCESS(status))
+    {
+        gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", *Info, *Address);
+    }
+    else
+    {
+        gcmkFOOTER();
+    }
+    return status;
+}
+#endif
+}
+
+/*******************************************************************************
+**
+**  gckOS_UnmapUserMemory
+**
+**  Unlock a user buffer and that was previously locked down by
+**  gckOS_MapUserMemory.
+**
+**  INPUT:
+**
+**      gctPOINTER Memory
+**          Pointer to memory to unlock.
+**
+**      gctSIZE_T Size
+**          Size in bytes of the memory to unlock.
+**
+**      gctPOINTER Info
+**          Information record returned by gckOS_MapUserMemory.
+**
+**      gctUINT32_PTR Address
+**          The address returned by gckOS_MapUserMemory.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserMemory(
+    IN gckOS Os,
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Size,
+    IN gctPOINTER Info,
+    IN gctUINT32 Address
+    )
+{
+    return gckOS_UnmapUserMemoryEx(Os, gcvCORE_MAJOR, Memory, Size, Info, Address);
+}
+
+gceSTATUS
+gckOS_UnmapUserMemoryEx(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Size,
+    IN gctPOINTER Info,
+    IN gctUINT32 Address
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X Core=%d Memory=0x%X Size=%lu Info=0x%X Address0x%08x",
+                   Os, Core, Memory, Size, Info, Address);
+
+#if gcdSECURE_USER
+    gcmkONERROR(gckOS_RemoveMapping(Os, Memory, Size));
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+#else
+{
+    gctUINT32 memory, start, end;
+    gcsPageInfo_PTR info;
+    gctSIZE_T pageCount, i;
+    struct page **pages;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Size > 0);
+    gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+
+    do
+    {
+        info = (gcsPageInfo_PTR) Info;
+
+        pages = info->pages;
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS,
+            "%s(%d): info=0x%X, pages=0x%X.",
+            __FUNCTION__, __LINE__,
+            info, pages
+            );
+
+        /* Invalid page array. */
+        if (pages == gcvNULL)
+        {
+            return gcvSTATUS_INVALID_ARGUMENT;
+        }
+
+        memory = (gctUINT32) Memory;
+        end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+        start = memory >> PAGE_SHIFT;
+        pageCount = end - start;
+
+        /* Overflow. */
+        if ((memory + Size) < memory)
+        {
+            return gcvSTATUS_INVALID_ARGUMENT;
+        }
+
+        /* Invalid argument. */
+        if (pageCount == 0)
+        {
+            return gcvSTATUS_INVALID_ARGUMENT;
+        }
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS,
+            "%s(%d): memory: 0x%X, pageCount: %d, pageTable: 0x%X.",
+            __FUNCTION__, __LINE__,
+            memory, pageCount, info->pageTable
+            );
+
+        MEMORY_MAP_LOCK(Os);
+
+#if gcdENABLE_VG
+        if (Core == gcvCORE_VG)
+        {
+            /* Free the pages from the MMU. */
+            gcmkERR_BREAK(gckVGMMU_FreePages(Os->device->kernels[Core]->vg->mmu,
+                                          info->pageTable,
+                                          pageCount * (PAGE_SIZE/4096)
+                                          ));
+        }
+        else
+#endif
+        {
+            /* Free the pages from the MMU. */
+            gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernels[Core]->mmu,
+                                          info->pageTable,
+                                          pageCount * (PAGE_SIZE/4096)
+                                          ));
+        }
+
+        /* Release the page cache. */
+        for (i = 0; i < pageCount; i++)
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO, gcvZONE_OS,
+                "%s(%d): pages[%d]: 0x%X.",
+                __FUNCTION__, __LINE__,
+                i, pages[i]
+                );
+
+            if (!PageReserved(pages[i]))
+            {
+                SetPageDirty(pages[i]);
+            }
+
+#if !defined(ANDROID)
+            /* Invalidate the data cache. */
+            dma_sync_single_for_device(
+                        gcvNULL,
+                        page_to_phys(pages[i]),
+                        PAGE_SIZE,
+                        DMA_FROM_DEVICE);
+#endif
+            page_cache_release(pages[i]);
+        }
+
+        /* Success. */
+        status = gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    if (info != gcvNULL)
+    {
+        /* Free the page array. */
+        if (info->pages != gcvNULL)
+        {
+            kfree(info->pages);
+        }
+
+        kfree(info);
+    }
+
+    MEMORY_MAP_UNLOCK(Os);
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+#endif
+}
+
+/*******************************************************************************
+**
+**  gckOS_GetBaseAddress
+**
+**  Get the base address for the physical memory.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to the gckOS object.
+**
+**  OUTPUT:
+**
+**      gctUINT32_PTR BaseAddress
+**          Pointer to a variable that will receive the base address.
+*/
+gceSTATUS
+gckOS_GetBaseAddress(
+    IN gckOS Os,
+    OUT gctUINT32_PTR BaseAddress
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X", Os);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+    /* Return base address. */
+    *BaseAddress = Os->device->baseAddress;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+    IN gckOS Os
+    )
+{
+    return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
+}
+
+gceSTATUS
+gckOS_SuspendInterruptEx(
+    IN gckOS Os,
+    IN gceCORE Core
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    disable_irq(Os->device->irqLines[Core]);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+    IN gckOS Os
+    )
+{
+    return gckOS_ResumeInterruptEx(Os, gcvCORE_MAJOR);
+}
+
+gceSTATUS
+gckOS_ResumeInterruptEx(
+    IN gckOS Os,
+    IN gceCORE Core
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    enable_irq(Os->device->irqLines[Core]);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_MemCopy(
+    IN gctPOINTER Destination,
+    IN gctCONST_POINTER Source,
+    IN gctSIZE_T Bytes
+    )
+{
+    gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
+                   Destination, Source, Bytes);
+
+    gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Source != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+    memcpy(Destination, Source, Bytes);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ZeroMemory(
+    IN gctPOINTER Memory,
+    IN gctSIZE_T Bytes
+    )
+{
+    gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory, Bytes);
+
+    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+    memset(Memory, 0, Bytes);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+********************************* Cache Control ********************************
+*******************************************************************************/
+
+/*******************************************************************************
+**  _HandleOuterCache
+**
+**  Handle the outer cache for the specified addresses.
+**
+**  ARGUMENTS:
+**
+**      gckOS Os
+**          Pointer to gckOS object.
+**
+**      gctUINT32 ProcessID
+**          Process ID Logical belongs.
+**
+**      gctPHYS_ADDR Handle
+**          Physical address handle.  If gcvNULL it is video memory.
+**
+**      gctPOINTER Physical
+**          Physical address to flush.
+**
+**      gctPOINTER Logical
+**          Logical address to flush.
+**
+**      gctSIZE_T Bytes
+**          Size of the address range in bytes to flush.
+**
+**      gceOUTERCACHE_OPERATION Type
+**          Operation need to be execute.
+*/
+#if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
+static inline gceSTATUS
+outer_func(
+    gceCACHEOPERATION Type,
+    unsigned long Start,
+    unsigned long End
+    )
+{
+    switch (Type)
+    {
+        case gcvCACHE_CLEAN:
+            outer_clean_range(Start, End);
+            break;
+        case gcvCACHE_INVALIDATE:
+            outer_inv_range(Start, End);
+            break;
+        case gcvCACHE_FLUSH:
+            outer_flush_range(Start, End);
+            break;
+        default:
+            return gcvSTATUS_INVALID_ARGUMENT;
+            break;
+    }
+    return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_HandleOuterCache(
+    IN gckOS Os,
+    IN gctUINT32 ProcessID,
+    IN gctPHYS_ADDR Handle,
+    IN gctPOINTER Physical,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes,
+    IN gceCACHEOPERATION Type
+    )
+{
+    gceSTATUS status;
+    gctUINT32 i, pageNum;
+    unsigned long paddr;
+    gctPOINTER vaddr;
+
+    gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
+                   Os, ProcessID, Handle, Logical, Bytes);
+
+    if (Physical != gcvNULL)
+    {
+        /* Non paged memory or gcvPOOL_USER surface */
+        paddr = (unsigned long) Physical;
+        gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
+    }
+    else if ((Handle == gcvNULL)
+    || (Handle != gcvNULL && ((PLINUX_MDL)Handle)->contiguous)
+    )
+    {
+        /* Video Memory or contiguous virtual memory */
+        gcmkONERROR(gckOS_GetPhysicalAddress(Os, Logical, (gctUINT32*)&paddr));
+        gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
+    }
+    else
+    {
+        /* Non contiguous virtual memory */
+        vaddr = (gctPOINTER)gcmALIGN_BASE((gctUINT32)Logical, PAGE_SIZE);
+        pageNum = GetPageCount(Bytes, 0);
+
+        for (i = 0; i < pageNum; i += 1)
+        {
+            gcmkONERROR(_ConvertLogical2Physical(
+                Os,
+                vaddr + PAGE_SIZE * i,
+                ProcessID,
+                (PLINUX_MDL)Handle,
+                (gctUINT32*)&paddr
+                ));
+
+            gcmkONERROR(outer_func(Type, paddr, paddr + PAGE_SIZE));
+        }
+    }
+
+    mb();
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+#endif
+
+/*******************************************************************************
+**  gckOS_CacheClean
+**
+**  Clean the cache for the specified addresses.  The GPU is going to need the
+**  data.  If the system is allocating memory as non-cachable, this function can
+**  be ignored.
+**
+**  ARGUMENTS:
+**
+**      gckOS Os
+**          Pointer to gckOS object.
+**
+**      gctUINT32 ProcessID
+**          Process ID Logical belongs.
+**
+**      gctPHYS_ADDR Handle
+**          Physical address handle.  If gcvNULL it is video memory.
+**
+**      gctPOINTER Physical
+**          Physical address to flush.
+**
+**      gctPOINTER Logical
+**          Logical address to flush.
+**
+**      gctSIZE_T Bytes
+**          Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheClean(
+    IN gckOS Os,
+    IN gctUINT32 ProcessID,
+    IN gctPHYS_ADDR Handle,
+    IN gctPOINTER Physical,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
+                   Os, ProcessID, Handle, Logical, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+#if !gcdCACHE_FUNCTION_UNIMPLEMENTED
+#ifdef CONFIG_ARM
+
+    /* Inner cache. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
+    dmac_map_area(Logical, Bytes, DMA_TO_DEVICE);
+#      else
+    dmac_clean_range(Logical, Logical + Bytes);
+#      endif
+
+#if defined(CONFIG_OUTER_CACHE)
+    /* Outer cache. */
+    _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_CLEAN);
+#endif
+
+#elif defined(CONFIG_MIPS)
+
+    dma_cache_wback((unsigned long) Logical, Bytes);
+
+#else
+    dma_sync_single_for_device(
+              gcvNULL,
+              Physical,
+              Bytes,
+              DMA_TO_DEVICE);
+#endif
+#endif
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**  gckOS_CacheInvalidate
+**
+**  Invalidate the cache for the specified addresses. The GPU is going to need
+**  data.  If the system is allocating memory as non-cachable, this function can
+**  be ignored.
+**
+**  ARGUMENTS:
+**
+**      gckOS Os
+**          Pointer to gckOS object.
+**
+**      gctUINT32 ProcessID
+**          Process ID Logical belongs.
+**
+**      gctPHYS_ADDR Handle
+**          Physical address handle.  If gcvNULL it is video memory.
+**
+**      gctPOINTER Logical
+**          Logical address to flush.
+**
+**      gctSIZE_T Bytes
+**          Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheInvalidate(
+    IN gckOS Os,
+    IN gctUINT32 ProcessID,
+    IN gctPHYS_ADDR Handle,
+    IN gctPOINTER Physical,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
+                   Os, ProcessID, Handle, Logical, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+#if !gcdCACHE_FUNCTION_UNIMPLEMENTED
+#ifdef CONFIG_ARM
+
+    /* Inner cache. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
+    dmac_map_area(Logical, Bytes, DMA_FROM_DEVICE);
+#      else
+    dmac_inv_range(Logical, Logical + Bytes);
+#      endif
+
+#if defined(CONFIG_OUTER_CACHE)
+    /* Outer cache. */
+    _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
+#endif
+
+#elif defined(CONFIG_MIPS)
+    dma_cache_inv((unsigned long) Logical, Bytes);
+#else
+    dma_sync_single_for_device(
+              gcvNULL,
+              Physical,
+              Bytes,
+              DMA_FROM_DEVICE);
+#endif
+#endif
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**  gckOS_CacheFlush
+**
+**  Clean the cache for the specified addresses and invalidate the lines as
+**  well.  The GPU is going to need and modify the data.  If the system is
+**  allocating memory as non-cachable, this function can be ignored.
+**
+**  ARGUMENTS:
+**
+**      gckOS Os
+**          Pointer to gckOS object.
+**
+**      gctUINT32 ProcessID
+**          Process ID Logical belongs.
+**
+**      gctPHYS_ADDR Handle
+**          Physical address handle.  If gcvNULL it is video memory.
+**
+**      gctPOINTER Logical
+**          Logical address to flush.
+**
+**      gctSIZE_T Bytes
+**          Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheFlush(
+    IN gckOS Os,
+    IN gctUINT32 ProcessID,
+    IN gctPHYS_ADDR Handle,
+    IN gctPOINTER Physical,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
+                   Os, ProcessID, Handle, Logical, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+#if !gcdCACHE_FUNCTION_UNIMPLEMENTED
+#ifdef CONFIG_ARM
+    /* Inner cache. */
+    dmac_flush_range(Logical, Logical + Bytes);
+
+#if defined(CONFIG_OUTER_CACHE)
+    /* Outer cache. */
+    _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_FLUSH);
+#endif
+
+#elif defined(CONFIG_MIPS)
+    dma_cache_wback_inv((unsigned long) Logical, Bytes);
+#else
+    dma_sync_single_for_device(
+              gcvNULL,
+              Physical,
+              Bytes,
+              DMA_BIDIRECTIONAL);
+#endif
+#endif
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+********************************* Broadcasting *********************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckOS_Broadcast
+**
+**  System hook for broadcast events from the kernel driver.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to the gckOS object.
+**
+**      gckHARDWARE Hardware
+**          Pointer to the gckHARDWARE object.
+**
+**      gceBROADCAST Reason
+**          Reason for the broadcast.  Can be one of the following values:
+**
+**              gcvBROADCAST_GPU_IDLE
+**                  Broadcasted when the kernel driver thinks the GPU might be
+**                  idle.  This can be used to handle power management.
+**
+**              gcvBROADCAST_GPU_COMMIT
+**                  Broadcasted when any client process commits a command
+**                  buffer.  This can be used to handle power management.
+**
+**              gcvBROADCAST_GPU_STUCK
+**                  Broadcasted when the kernel driver hits the timeout waiting
+**                  for the GPU.
+**
+**              gcvBROADCAST_FIRST_PROCESS
+**                  First process is trying to connect to the kernel.
+**
+**              gcvBROADCAST_LAST_PROCESS
+**                  Last process has detached from the kernel.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_Broadcast(
+    IN gckOS Os,
+    IN gckHARDWARE Hardware,
+    IN gceBROADCAST Reason
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os, Hardware, Reason);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    switch (Reason)
+    {
+    case gcvBROADCAST_FIRST_PROCESS:
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
+        break;
+
+    case gcvBROADCAST_LAST_PROCESS:
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
+
+        /* Put GPU OFF. */
+        gcmkONERROR(
+            gckHARDWARE_SetPowerManagementState(Hardware,
+                                                gcvPOWER_OFF_BROADCAST));
+        break;
+
+    case gcvBROADCAST_GPU_IDLE:
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
+
+        /* Put GPU IDLE. */
+        gcmkONERROR(
+            gckHARDWARE_SetPowerManagementState(Hardware,
+                                                gcvPOWER_IDLE_BROADCAST));
+
+        /* Add idle process DB. */
+        gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
+                                           1,
+                                           gcvDB_IDLE,
+                                           gcvNULL, gcvNULL, 0));
+        break;
+
+    case gcvBROADCAST_GPU_COMMIT:
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
+
+        /* Add busy process DB. */
+        gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
+                                           0,
+                                           gcvDB_IDLE,
+                                           gcvNULL, gcvNULL, 0));
+
+        /* Put GPU ON. */
+        gcmkONERROR(
+            gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON_AUTO));
+        break;
+
+    case gcvBROADCAST_GPU_STUCK:
+        gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
+        gcmkONERROR(_DumpGPUState(Os));
+        gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
+        break;
+
+    case gcvBROADCAST_AXI_BUS_ERROR:
+        gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
+        gcmkONERROR(_DumpGPUState(Os));
+        /*gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));*/
+        break;
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_BroadcastHurry
+**
+**  The GPU is running too slow.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to the gckOS object.
+**
+**      gckHARDWARE Hardware
+**          Pointer to the gckHARDWARE object.
+**
+**      gctUINT Urgency
+**          The higher the number, the higher the urgency to speed up the GPU.
+**          The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_BroadcastHurry(
+    IN gckOS Os,
+    IN gckHARDWARE Hardware,
+    IN gctUINT Urgency
+    )
+{
+    gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os, Hardware, Urgency);
+
+    /* Do whatever you need to do to speed up the GPU now. */
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_BroadcastCalibrateSpeed
+**
+**  Calibrate the speed of the GPU.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to the gckOS object.
+**
+**      gckHARDWARE Hardware
+**          Pointer to the gckHARDWARE object.
+**
+**      gctUINT Idle, Time
+**          Idle/Time will give the percentage the GPU is idle, so you can use
+**          this to calibrate the working point of the GPU.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_BroadcastCalibrateSpeed(
+    IN gckOS Os,
+    IN gckHARDWARE Hardware,
+    IN gctUINT Idle,
+    IN gctUINT Time
+    )
+{
+    gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
+                   Os, Hardware, Idle, Time);
+
+    /* Do whatever you need to do to callibrate the GPU speed. */
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+********************************** Semaphores **********************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckOS_CreateSemaphore
+**
+**  Create a semaphore.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to the gckOS object.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * Semaphore
+**          Pointer to the variable that will receive the created semaphore.
+*/
+gceSTATUS
+gckOS_CreateSemaphore(
+    IN gckOS Os,
+    OUT gctPOINTER * Semaphore
+    )
+{
+    gceSTATUS status;
+    struct semaphore *sem = gcvNULL;
+
+    gcmkHEADER_ARG("Os=0x%X", Os);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+    /* Allocate the semaphore structure. */
+    sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL);
+    if (sem == gcvNULL)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    /* Initialize the semaphore. */
+    sema_init(sem, 1);
+
+    /* Return to caller. */
+    *Semaphore = (gctPOINTER) sem;
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_AcquireSemaphore
+**
+**  Acquire a semaphore.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to the gckOS object.
+**
+**      gctPOINTER Semaphore
+**          Pointer to the semaphore thet needs to be acquired.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_AcquireSemaphore(
+    IN gckOS Os,
+    IN gctPOINTER Semaphore
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os, Semaphore);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+    /* Acquire the semaphore. */
+    if (down_interruptible((struct semaphore *) Semaphore))
+    {
+        gcmkONERROR(gcvSTATUS_TIMEOUT);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_TryAcquireSemaphore
+**
+**  Try to acquire a semaphore.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to the gckOS object.
+**
+**      gctPOINTER Semaphore
+**          Pointer to the semaphore thet needs to be acquired.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_TryAcquireSemaphore(
+    IN gckOS Os,
+    IN gctPOINTER Semaphore
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%x", Os);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+    /* Acquire the semaphore. */
+    if (down_trylock((struct semaphore *) Semaphore))
+    {
+        /* Timeout. */
+        status = gcvSTATUS_TIMEOUT;
+        gcmkFOOTER();
+        return status;
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_ReleaseSemaphore
+**
+**  Release a previously acquired semaphore.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to the gckOS object.
+**
+**      gctPOINTER Semaphore
+**          Pointer to the semaphore thet needs to be released.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_ReleaseSemaphore(
+    IN gckOS Os,
+    IN gctPOINTER Semaphore
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+    /* Release the semaphore. */
+    up((struct semaphore *) Semaphore);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_DestroySemaphore
+**
+**  Destroy a semaphore.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to the gckOS object.
+**
+**      gctPOINTER Semaphore
+**          Pointer to the semaphore thet needs to be destroyed.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_DestroySemaphore(
+    IN gckOS Os,
+    IN gctPOINTER Semaphore
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
+
+     /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+    /* Free the sempahore structure. */
+    kfree(Semaphore);
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_GetProcessID
+**
+**  Get current process ID.
+**
+**  INPUT:
+**
+**      Nothing.
+**
+**  OUTPUT:
+**
+**      gctUINT32_PTR ProcessID
+**          Pointer to the variable that receives the process ID.
+*/
+gceSTATUS
+gckOS_GetProcessID(
+    OUT gctUINT32_PTR ProcessID
+    )
+{
+    /* Get process ID. */
+    if (ProcessID != gcvNULL)
+    {
+        *ProcessID = _GetProcessID();
+    }
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_GetThreadID
+**
+**  Get current thread ID.
+**
+**  INPUT:
+**
+**      Nothing.
+**
+**  OUTPUT:
+**
+**      gctUINT32_PTR ThreadID
+**          Pointer to the variable that receives the thread ID.
+*/
+gceSTATUS
+gckOS_GetThreadID(
+    OUT gctUINT32_PTR ThreadID
+    )
+{
+    /* Get thread ID. */
+    if (ThreadID != gcvNULL)
+    {
+        *ThreadID = _GetThreadID();
+    }
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_SetGPUPower
+**
+**  Set the power of the GPU on or off.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to a gckOS object.
+**
+**      gctBOOL Clock
+**          gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
+**
+**      gctBOOL Power
+**          gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_SetGPUPower(
+    IN gckOS Os,
+    IN gctBOOL Clock,
+    IN gctBOOL Power
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Clock=%d Power=%d", Os, Clock, Power);
+
+    /* TODO: Put your code here. */
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*----------------------------------------------------------------------------*/
+/*----- Profile --------------------------------------------------------------*/
+
+gceSTATUS
+gckOS_GetProfileTick(
+    OUT gctUINT64_PTR Tick
+    )
+{
+    struct timespec time;
+
+    ktime_get_ts(&time);
+
+    *Tick = time.tv_nsec + time.tv_sec * 1000000000ULL;
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_QueryProfileTickRate(
+    OUT gctUINT64_PTR TickRate
+    )
+{
+    struct timespec res;
+
+    hrtimer_get_res(CLOCK_MONOTONIC, &res);
+
+    *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
+
+    return gcvSTATUS_OK;
+}
+
+gctUINT32
+gckOS_ProfileToMS(
+    IN gctUINT64 Ticks
+    )
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
+    return div_u64(Ticks, 1000000);
+#else
+    gctUINT64 rem = Ticks;
+    gctUINT64 b = 1000000;
+    gctUINT64 res, d = 1;
+    gctUINT32 high = rem >> 32;
+
+    /* Reduce the thing a bit first */
+    res = 0;
+    if (high >= 1000000)
+    {
+        high /= 1000000;
+        res   = (gctUINT64) high << 32;
+        rem  -= (gctUINT64) (high * 1000000) << 32;
+    }
+
+    while (((gctINT64) b > 0) && (b < rem))
+    {
+        b <<= 1;
+        d <<= 1;
+    }
+
+    do
+    {
+        if (rem >= b)
+        {
+            rem -= b;
+            res += d;
+        }
+
+        b >>= 1;
+        d >>= 1;
+    }
+    while (d);
+
+    return (gctUINT32) res;
+#endif
+}
+
+#if gcdENABLE_BANK_ALIGNMENT
+/*******************************************************************************
+**  gckOS_GetSurfaceBankAlignment
+**
+**  Return the required offset alignment required to the make BaseAddress
+**  aligned properly.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to gcoOS object.
+**
+**      gceSURF_TYPE Type
+**          Type of allocation.
+**
+**      gctUINT32 BaseAddress
+**          Base address of current video memory node.
+**
+**  OUTPUT:
+**
+**      gctUINT32_PTR Alignment
+**          Pointer to a variable thah twil hold the number of bytes to skip in
+**          the current video memory node in order to make the alignment bank
+**          aligned.
+*/
+gceSTATUS
+gckOS_GetSurfaceBankAlignment(
+    IN gckOS Os,
+    IN gceSURF_TYPE Type,
+    IN gctUINT32 BaseAddress,
+    OUT gctUINT32_PTR Alignment
+    )
+{
+    gctUINT32 alignedBaseAddress;
+
+    gcmkHEADER_ARG("Os=0x%x Type=%d BaseAddress=0x%x ", Os, Type, BaseAddress);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Alignment != gcvNULL);
+
+    switch (Type)
+    {
+    case gcvSURF_RENDER_TARGET:
+        /* Align to first 4kB bank. */
+        alignedBaseAddress = (((BaseAddress >> 15) << 3) + (0x8 + 0x0)) << 12;
+        break;
+
+    case gcvSURF_DEPTH:
+        /* Align to third 4kB bank. */
+        alignedBaseAddress = (((BaseAddress >> 15) << 3) + (0x8 + 0x2)) << 12;
+
+        /* Add 64-byte offset to change channel bit 6. */
+        alignedBaseAddress += 64;
+        break;
+
+    default:
+        /* no alignment needed. */
+        alignedBaseAddress = BaseAddress;
+    }
+
+    /* Return alignment. */
+    *Alignment = alignedBaseAddress - BaseAddress;
+
+    /* Return the status. */
+    gcmkFOOTER_ARG("*Alignment=%u", *Alignment);
+    return gcvSTATUS_OK;
+}
+#endif
+
+/******************************************************************************\
+******************************* Signal Management ******************************
+\******************************************************************************/
+
+#undef _GC_OBJ_ZONE
+#define _GC_OBJ_ZONE    gcvZONE_SIGNAL
+
+/*******************************************************************************
+**
+**  gckOS_CreateSignal
+**
+**  Create a new signal.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctBOOL ManualReset
+**          If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
+**          order to set the signal to nonsignaled state.
+**          If set to gcvFALSE, the signal will automatically be set to
+**          nonsignaled state by gckOS_WaitSignal function.
+**
+**  OUTPUT:
+**
+**      gctSIGNAL * Signal
+**          Pointer to a variable receiving the created gctSIGNAL.
+*/
+gceSTATUS
+gckOS_CreateSignal(
+    IN gckOS Os,
+    IN gctBOOL ManualReset,
+    OUT gctSIGNAL * Signal
+    )
+{
+    gcsSIGNAL_PTR signal;
+
+    gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os, ManualReset);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+    /* Create an event structure. */
+    signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL);
+
+    if (signal == gcvNULL)
+    {
+        gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    signal->manualReset = ManualReset;
+    init_completion(&signal->obj);
+    atomic_set(&signal->ref, 1);
+
+    *Signal = (gctSIGNAL) signal;
+
+    gcmkFOOTER_ARG("*Signal=0x%X", *Signal);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_DestroySignal
+**
+**  Destroy a signal.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctSIGNAL Signal
+**          Pointer to the gctSIGNAL.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_DestroySignal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal
+    )
+{
+    gcsSIGNAL_PTR signal;
+
+    gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+    signal = (gcsSIGNAL_PTR) Signal;
+
+    if (atomic_dec_and_test(&signal->ref))
+    {
+         /* Free the sgianl. */
+        kfree(Signal);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_Signal
+**
+**  Set a state of the specified signal.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctSIGNAL Signal
+**          Pointer to the gctSIGNAL.
+**
+**      gctBOOL State
+**          If gcvTRUE, the signal will be set to signaled state.
+**          If gcvFALSE, the signal will be set to nonsignaled state.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_Signal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal,
+    IN gctBOOL State
+    )
+{
+    gcsSIGNAL_PTR signal;
+
+    gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+    signal = (gcsSIGNAL_PTR) Signal;
+
+    if (State)
+    {
+        /* Set the event to a signaled state. */
+        complete(&signal->obj);
+    }
+    else
+    {
+        /* Set the event to an unsignaled state. */
+        INIT_COMPLETION(signal->obj);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+#if gcdENABLE_VG
+gceSTATUS
+gckOS_SetSignalVG(
+    IN gckOS Os,
+    IN gctHANDLE Process,
+    IN gctSIGNAL Signal
+    )
+{
+    gceSTATUS status;
+    gctINT result;
+    struct task_struct * userTask;
+    struct siginfo info;
+
+    userTask = FIND_TASK_BY_PID((pid_t) Process);
+
+    if (userTask != gcvNULL)
+    {
+        info.si_signo = 48;
+        info.si_code  = __SI_CODE(__SI_RT, SI_KERNEL);
+        info.si_pid   = 0;
+        info.si_uid   = 0;
+        info.si_ptr   = (gctPOINTER) Signal;
+
+        /* Signals with numbers between 32 and 63 are real-time,
+           send a real-time signal to the user process. */
+        result = send_sig_info(48, &info, userTask);
+
+        printk("gckOS_SetSignalVG:0x%x\n", result);
+        /* Error? */
+        if (result < 0)
+        {
+            status = gcvSTATUS_GENERIC_IO;
+
+            gcmkTRACE(
+                gcvLEVEL_ERROR,
+                "%s(%d): an error has occurred.\n",
+                __FUNCTION__, __LINE__
+                );
+        }
+        else
+        {
+            status = gcvSTATUS_OK;
+        }
+    }
+    else
+    {
+        status = gcvSTATUS_GENERIC_IO;
+
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): an error has occurred.\n",
+            __FUNCTION__, __LINE__
+            );
+    }
+
+    /* Return status. */
+    return status;
+}
+#endif
+
+/*******************************************************************************
+**
+**  gckOS_UserSignal
+**
+**  Set the specified signal which is owned by a process to signaled state.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctSIGNAL Signal
+**          Pointer to the gctSIGNAL.
+**
+**      gctHANDLE Process
+**          Handle of process owning the signal.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_UserSignal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal,
+    IN gctHANDLE Process
+    )
+{
+    gceSTATUS status;
+    gctSIGNAL signal;
+
+    gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
+                   Os, Signal, (gctINT32) Process);
+
+    /* Map the signal into kernel space. */
+    gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
+
+    /* Signal. */
+    status = gckOS_Signal(Os, signal, gcvTRUE);
+
+    /* Unmap the signal */
+    gcmkVERIFY_OK(gckOS_UnmapSignal(Os, Signal));
+
+    gcmkFOOTER();
+    return status;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_WaitSignal
+**
+**  Wait for a signal to become signaled.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctSIGNAL Signal
+**          Pointer to the gctSIGNAL.
+**
+**      gctUINT32 Wait
+**          Number of milliseconds to wait.
+**          Pass the value of gcvINFINITE for an infinite wait.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_WaitSignal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal,
+    IN gctUINT32 Wait
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+    gcsSIGNAL_PTR signal;
+
+    gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+    signal = (gcsSIGNAL_PTR) Signal;
+
+    might_sleep();
+
+    spin_lock_irq(&signal->obj.wait.lock);
+
+    if (signal->obj.done)
+    {
+        if (!signal->manualReset)
+        {
+            signal->obj.done = 0;
+        }
+
+        status = gcvSTATUS_OK;
+    }
+    else if (Wait == 0)
+    {
+        status = gcvSTATUS_TIMEOUT;
+    }
+    else
+    {
+        /* Convert wait to milliseconds. */
+#if gcdDETECT_TIMEOUT
+        gctINT timeout = (Wait == gcvINFINITE)
+            ? gcdINFINITE_TIMEOUT * HZ / 1000
+            : Wait * HZ / 1000;
+
+        gctUINT complained = 0;
+#else
+        gctINT timeout = (Wait == gcvINFINITE)
+            ? MAX_SCHEDULE_TIMEOUT
+            : Wait * HZ / 1000;
+#endif
+
+        DECLARE_WAITQUEUE(wait, current);
+        wait.flags |= WQ_FLAG_EXCLUSIVE;
+        __add_wait_queue_tail(&signal->obj.wait, &wait);
+
+        while (gcvTRUE)
+        {
+            if (signal_pending(current))
+            {
+                /* Interrupt received. */
+                status = gcvSTATUS_INTERRUPTED;
+                break;
+            }
+
+            __set_current_state(TASK_INTERRUPTIBLE);
+            spin_unlock_irq(&signal->obj.wait.lock);
+            timeout = schedule_timeout(timeout);
+            spin_lock_irq(&signal->obj.wait.lock);
+
+            if (signal->obj.done)
+            {
+                if (!signal->manualReset)
+                {
+                    signal->obj.done = 0;
+                }
+
+                status = gcvSTATUS_OK;
+                break;
+            }
+
+#if gcdDETECT_TIMEOUT
+            if ((Wait == gcvINFINITE) && (timeout == 0))
+            {
+                gctUINT32 dmaAddress1, dmaAddress2;
+                gctUINT32 dmaState1, dmaState2;
+
+                dmaState1   = dmaState2   =
+                dmaAddress1 = dmaAddress2 = 0;
+
+                /* Verify whether DMA is running. */
+                gcmkVERIFY_OK(_VerifyDMA(
+                    Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
+                    ));
+
+#if gcdDETECT_DMA_ADDRESS
+                /* Dump only if DMA appears stuck. */
+                if (
+                    (dmaAddress1 == dmaAddress2)
+#if gcdDETECT_DMA_STATE
+                 && (dmaState1   == dmaState2)
+#endif
+                )
+#endif
+                {
+                    /* Increment complain count. */
+                    complained += 1;
+
+                    gcmkVERIFY_OK(_DumpGPUState(Os));
+
+                    gcmkPRINT(
+                        "%s(%d): signal 0x%X; forced message flush (%d).",
+                        __FUNCTION__, __LINE__, Signal, complained
+                        );
+
+                    /* Flush the debug cache. */
+                    gcmkDEBUGFLUSH(dmaAddress2);
+                }
+
+                /* Reset timeout. */
+                timeout = gcdINFINITE_TIMEOUT * HZ / 1000;
+            }
+#endif
+
+            if (timeout == 0)
+            {
+
+                status = gcvSTATUS_TIMEOUT;
+                break;
+            }
+        }
+
+        __remove_wait_queue(&signal->obj.wait, &wait);
+
+#if gcdDETECT_TIMEOUT
+        if (complained)
+        {
+            gcmkPRINT(
+                "%s(%d): signal=0x%X; waiting done; status=%d",
+                __FUNCTION__, __LINE__, Signal, status
+                );
+        }
+#endif
+    }
+
+    spin_unlock_irq(&signal->obj.wait.lock);
+
+    /* Return status. */
+    gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_MapSignal
+**
+**  Map a signal in to the current process space.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctSIGNAL Signal
+**          Pointer to tha gctSIGNAL to map.
+**
+**      gctHANDLE Process
+**          Handle of process owning the signal.
+**
+**  OUTPUT:
+**
+**      gctSIGNAL * MappedSignal
+**          Pointer to a variable receiving the mapped gctSIGNAL.
+*/
+gceSTATUS
+gckOS_MapSignal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal,
+    IN gctHANDLE Process,
+    OUT gctSIGNAL * MappedSignal
+    )
+{
+    gctINT signalID;
+    gcsSIGNAL_PTR signal;
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process);
+
+    gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+    gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
+
+    signalID = (gctINT) Signal - 1;
+
+    gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    if (signalID >= 0 && signalID < Os->signal.tableLen)
+    {
+        /* It is a user space signal. */
+        signal = Os->signal.table[signalID];
+
+        if (signal == gcvNULL)
+        {
+            gcmkONERROR(gcvSTATUS_NOT_FOUND);
+        }
+    }
+    else
+    {
+        /* It is a kernel space signal structure. */
+        signal = (gcsSIGNAL_PTR) Signal;
+    }
+
+    if (atomic_inc_return(&signal->ref) <= 1)
+    {
+        /* The previous value is 0, it has been deleted. */
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    /* Release the mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
+
+    *MappedSignal = (gctSIGNAL) signal;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signal.lock));
+    }
+
+    /* Return the staus. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**     gckOS_UnmapSignal
+**
+**     Unmap a signal .
+**
+**     INPUT:
+**
+**             gckOS Os
+**                     Pointer to an gckOS object.
+**
+**             gctSIGNAL Signal
+**                     Pointer to that gctSIGNAL mapped.
+*/
+gceSTATUS
+gckOS_UnmapSignal(
+    IN gckOS Os,
+    IN gctSIGNAL Signal
+    )
+{
+    gctINT signalID;
+    gcsSIGNAL_PTR signal;
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Os=0x%X Signal=0x%X ", Os, Signal);
+
+    gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+    signalID = (gctINT) Signal - 1;
+
+    gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    if (signalID >= 0 && signalID < Os->signal.tableLen)
+    {
+        /* It is a user space signal. */
+        signal = Os->signal.table[signalID];
+
+        if (signal == gcvNULL)
+        {
+            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+        }
+
+        if (atomic_read(&signal->ref) == 1)
+        {
+            /* Update the table. */
+            Os->signal.table[signalID] = gcvNULL;
+
+            if (Os->signal.unused++ == 0)
+            {
+                Os->signal.currentID = signalID;
+            }
+        }
+
+        gcmkONERROR(gckOS_DestroySignal(Os, signal));
+    }
+    else
+    {
+        /* It is a kernel space signal structure. */
+        signal = (gcsSIGNAL_PTR) Signal;
+
+        gcmkONERROR(gckOS_DestroySignal(Os, signal));
+    }
+
+    /* Release the mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
+
+    /* Success. */
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signal.lock));
+    }
+
+    /* Return the staus. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_CreateUserSignal
+**
+**  Create a new signal to be used in the user space.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctBOOL ManualReset
+**          If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
+**          order to set the signal to nonsignaled state.
+**          If set to gcvFALSE, the signal will automatically be set to
+**          nonsignaled state by gckOS_WaitSignal function.
+**
+**  OUTPUT:
+**
+**      gctINT * SignalID
+**          Pointer to a variable receiving the created signal's ID.
+*/
+gceSTATUS
+gckOS_CreateUserSignal(
+    IN gckOS Os,
+    IN gctBOOL ManualReset,
+    OUT gctINT * SignalID
+    )
+{
+    gcsSIGNAL_PTR signal = gcvNULL;
+    gctINT unused, currentID, tableLen;
+    gctPOINTER * table;
+    gctINT i;
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Os=0x%0x ManualReset=%d", Os, ManualReset);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(SignalID != gcvNULL);
+
+    /* Lock the table. */
+    gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+
+    acquired = gcvTRUE;
+
+    if (Os->signal.unused < 1)
+    {
+        /* Enlarge the table. */
+        table = (gctPOINTER *) kmalloc(
+                    sizeof(gctPOINTER) * (Os->signal.tableLen + USER_SIGNAL_TABLE_LEN_INIT),
+                    GFP_KERNEL);
+
+        if (table == gcvNULL)
+        {
+            /* Out of memory. */
+            gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+        }
+
+        memset(table + Os->signal.tableLen, 0, sizeof(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT);
+        memcpy(table, Os->signal.table, sizeof(gctPOINTER) * Os->signal.tableLen);
+
+        /* Release the old table. */
+        kfree(Os->signal.table);
+
+        /* Update the table. */
+        Os->signal.table = table;
+        Os->signal.currentID = Os->signal.tableLen;
+        Os->signal.tableLen += USER_SIGNAL_TABLE_LEN_INIT;
+        Os->signal.unused += USER_SIGNAL_TABLE_LEN_INIT;
+    }
+
+    table = Os->signal.table;
+    currentID = Os->signal.currentID;
+    tableLen = Os->signal.tableLen;
+    unused = Os->signal.unused;
+
+    /* Create a new signal. */
+    gcmkONERROR(
+        gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal));
+
+    /* Save the process ID. */
+    signal->process = (gctHANDLE) _GetProcessID();
+
+    table[currentID] = signal;
+
+    /* Plus 1 to avoid gcvNULL claims. */
+    *SignalID = currentID + 1;
+
+    /* Update the currentID. */
+    if (--unused > 0)
+    {
+        for (i = 0; i < tableLen; i++)
+        {
+            if (++currentID >= tableLen)
+            {
+                /* Wrap to the begin. */
+                currentID = 0;
+            }
+
+            if (table[currentID] == gcvNULL)
+            {
+                break;
+            }
+        }
+    }
+
+    Os->signal.table = table;
+    Os->signal.currentID = currentID;
+    Os->signal.tableLen = tableLen;
+    Os->signal.unused = unused;
+
+    gcmkONERROR(
+        gckOS_ReleaseMutex(Os, Os->signal.lock));
+
+    gcmkFOOTER_ARG("*SignalID=%d", gcmOPT_VALUE(SignalID));
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkONERROR(
+            gckOS_ReleaseMutex(Os, Os->signal.lock));
+    }
+
+    /* Return the staus. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_DestroyUserSignal
+**
+**  Destroy a signal to be used in the user space.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctINT SignalID
+**          The signal's ID.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_DestroyUserSignal(
+    IN gckOS Os,
+    IN gctINT SignalID
+    )
+{
+    gceSTATUS status;
+    gcsSIGNAL_PTR signal;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Os=0x%X SignalID=%d", Os, SignalID);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    gcmkONERROR(
+        gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+
+    acquired = gcvTRUE;
+
+    if (SignalID < 1 || SignalID > Os->signal.tableLen)
+    {
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): invalid signal->%d.",
+            __FUNCTION__, __LINE__,
+            (gctINT) SignalID
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    SignalID -= 1;
+
+    signal = Os->signal.table[SignalID];
+
+    if (signal == gcvNULL)
+    {
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): signal is gcvNULL.",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+
+    if (atomic_read(&signal->ref) == 1)
+    {
+        /* Update the table. */
+        Os->signal.table[SignalID] = gcvNULL;
+
+        if (Os->signal.unused++ == 0)
+        {
+            Os->signal.currentID = SignalID;
+        }
+    }
+
+    gcmkONERROR(
+        gckOS_DestroySignal(Os, signal));
+
+    gcmkVERIFY_OK(
+        gckOS_ReleaseMutex(Os, Os->signal.lock));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseMutex(Os, Os->signal.lock));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_WaitUserSignal
+**
+**  Wait for a signal used in the user mode to become signaled.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctINT SignalID
+**          Signal ID.
+**
+**      gctUINT32 Wait
+**          Number of milliseconds to wait.
+**          Pass the value of gcvINFINITE for an infinite wait.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_WaitUserSignal(
+    IN gckOS Os,
+    IN gctINT SignalID,
+    IN gctUINT32 Wait
+    )
+{
+    gceSTATUS status;
+    gcsSIGNAL_PTR signal;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Os=0x%X SignalID=%d Wait=%u", Os, SignalID, Wait);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    if (SignalID < 1 || SignalID > Os->signal.tableLen)
+    {
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): invalid signal %d",
+            __FUNCTION__, __LINE__,
+            SignalID
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    SignalID -= 1;
+
+    signal = Os->signal.table[SignalID];
+
+    gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
+    acquired = gcvFALSE;
+
+    if (signal == gcvNULL)
+    {
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): signal is gcvNULL.",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+
+    status = gckOS_WaitSignal(Os, signal, Wait);
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signal.lock));
+    }
+
+    /* Return the staus. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_SignalUserSignal
+**
+**  Set a state of the specified signal to be used in the user space.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctINT SignalID
+**          SignalID.
+**
+**      gctBOOL State
+**          If gcvTRUE, the signal will be set to signaled state.
+**          If gcvFALSE, the signal will be set to nonsignaled state.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_SignalUserSignal(
+    IN gckOS Os,
+    IN gctINT SignalID,
+    IN gctBOOL State
+    )
+{
+    gceSTATUS status;
+    gcsSIGNAL_PTR signal;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Os=0x%X SignalID=%d State=%d", Os, SignalID, State);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    if ((SignalID < 1)
+    ||  (SignalID > Os->signal.tableLen)
+    )
+    {
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): invalid signal->%d.",
+            __FUNCTION__, __LINE__,
+            SignalID
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    SignalID -= 1;
+
+    signal = Os->signal.table[SignalID];
+
+    gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
+    acquired = gcvFALSE;
+
+    if (signal == gcvNULL)
+    {
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): signal is gcvNULL.",
+            __FUNCTION__, __LINE__
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+    }
+
+
+    status = gckOS_Signal(Os, signal, State);
+
+    /* Success. */
+    gcmkFOOTER();
+    return status;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseMutex(Os, Os->signal.lock));
+    }
+
+    /* Return the staus. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckOS_CleanProcessSignal(
+    gckOS Os,
+    gctHANDLE Process
+    )
+{
+    gctINT signal;
+
+    gcmkHEADER_ARG("Os=0x%X Process=%d", Os, Process);
+
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    gcmkVERIFY_OK(gckOS_AcquireMutex(Os,
+        Os->signal.lock,
+        gcvINFINITE
+        ));
+
+    if (Os->signal.unused == Os->signal.tableLen)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Os,
+            Os->signal.lock
+            ));
+
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+    for (signal = 0; signal < Os->signal.tableLen; signal++)
+    {
+        if (Os->signal.table[signal] != gcvNULL &&
+            ((gcsSIGNAL_PTR)Os->signal.table[signal])->process == Process)
+        {
+            gckOS_DestroySignal(Os, Os->signal.table[signal]);
+
+            /* Update the signal table. */
+            Os->signal.table[signal] = gcvNULL;
+            if (Os->signal.unused++ == 0)
+            {
+                Os->signal.currentID = signal;
+            }
+        }
+    }
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Os,
+        Os->signal.lock
+        ));
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+#if gcdENABLE_VG
+gceSTATUS
+gckOS_CreateSemaphoreVG(
+    IN gckOS Os,
+    OUT gctSEMAPHORE * Semaphore
+    )
+{
+    gceSTATUS status;
+    struct semaphore * newSemaphore;
+
+    gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+    do
+    {
+        /* Allocate the semaphore structure. */
+       newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL);
+       if (newSemaphore == gcvNULL)
+       {
+               gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
+       }
+
+        /* Initialize the semaphore. */
+        sema_init(newSemaphore, 0);
+
+        /* Set the handle. */
+        * Semaphore = (gctSEMAPHORE) newSemaphore;
+
+        /* Success. */
+        status = gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return the status. */
+    return status;
+}
+
+
+gceSTATUS
+gckOS_IncrementSemaphore(
+    IN gckOS Os,
+    IN gctSEMAPHORE Semaphore
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+    /* Increment the semaphore's count. */
+    up((struct semaphore *) Semaphore);
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_DecrementSemaphore(
+    IN gckOS Os,
+    IN gctSEMAPHORE Semaphore
+    )
+{
+    gceSTATUS status;
+    gctINT result;
+
+    gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+    do
+    {
+        /* Decrement the semaphore's count. If the count is zero, wait
+           until it gets incremented. */
+        result = down_interruptible((struct semaphore *) Semaphore);
+
+        /* Signal received? */
+        if (result != 0)
+        {
+            status = gcvSTATUS_TERMINATE;
+            break;
+        }
+
+        /* Success. */
+        status = gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return the status. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckOS_SetSignal
+**
+**  Set the specified signal to signaled state.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to the gckOS object.
+**
+**      gctHANDLE Process
+**          Handle of process owning the signal.
+**
+**      gctSIGNAL Signal
+**          Pointer to the gctSIGNAL.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckOS_SetSignal(
+    IN gckOS Os,
+    IN gctHANDLE Process,
+    IN gctSIGNAL Signal
+    )
+{
+    gceSTATUS status;
+    gctINT result;
+    struct task_struct * userTask;
+    struct siginfo info;
+
+    userTask = FIND_TASK_BY_PID((pid_t) Process);
+
+    if (userTask != gcvNULL)
+    {
+        info.si_signo = 48;
+        info.si_code  = __SI_CODE(__SI_RT, SI_KERNEL);
+        info.si_pid   = 0;
+        info.si_uid   = 0;
+        info.si_ptr   = (gctPOINTER) Signal;
+
+        /* Signals with numbers between 32 and 63 are real-time,
+           send a real-time signal to the user process. */
+        result = send_sig_info(48, &info, userTask);
+
+        /* Error? */
+        if (result < 0)
+        {
+            status = gcvSTATUS_GENERIC_IO;
+
+            gcmkTRACE(
+                gcvLEVEL_ERROR,
+                "%s(%d): an error has occurred.\n",
+                __FUNCTION__, __LINE__
+                );
+        }
+        else
+        {
+            status = gcvSTATUS_OK;
+        }
+    }
+    else
+    {
+        status = gcvSTATUS_GENERIC_IO;
+
+        gcmkTRACE(
+            gcvLEVEL_ERROR,
+            "%s(%d): an error has occurred.\n",
+            __FUNCTION__, __LINE__
+            );
+    }
+
+    /* Return status. */
+    return status;
+}
+
+/******************************************************************************\
+******************************** Thread Object *********************************
+\******************************************************************************/
+
+gceSTATUS
+gckOS_StartThread(
+    IN gckOS Os,
+    IN gctTHREADFUNC ThreadFunction,
+    IN gctPOINTER ThreadParameter,
+    OUT gctTHREAD * Thread
+    )
+{
+    gceSTATUS status;
+    struct task_struct * thread;
+
+    gcmkHEADER_ARG("Os=0x%X ", Os);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(ThreadFunction != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
+
+    do
+    {
+        /* Create the thread. */
+        thread = kthread_create(
+            ThreadFunction,
+            ThreadParameter,
+            "Vivante Kernel Thread"
+            );
+
+        /* Failed? */
+        if (IS_ERR(thread))
+        {
+            status = gcvSTATUS_GENERIC_IO;
+            break;
+        }
+
+        /* Start the thread. */
+        wake_up_process(thread);
+
+        /* Set the thread handle. */
+        * Thread = (gctTHREAD) thread;
+
+        /* Success. */
+        status = gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    gcmkFOOTER();
+    /* Return the status. */
+    return status;
+}
+
+gceSTATUS
+gckOS_StopThread(
+    IN gckOS Os,
+    IN gctTHREAD Thread
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
+
+    /* Thread should have already been enabled to terminate. */
+    kthread_stop((struct task_struct *) Thread);
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_VerifyThread(
+    IN gckOS Os,
+    IN gctTHREAD Thread
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
+
+    gcmkFOOTER_NO();
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+#endif
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h
new file mode 100644 (file)
index 0000000..f155f10
--- /dev/null
@@ -0,0 +1,79 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2011 by Vivante Corp.
+*
+*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_os_h_
+#define __gc_hal_kernel_os_h_
+
+typedef struct _LINUX_MDL_MAP
+{
+    gctINT                  pid;
+    gctPOINTER              vmaAddr;
+    struct vm_area_struct * vma;
+    struct _LINUX_MDL_MAP * next;
+}
+LINUX_MDL_MAP;
+
+typedef struct _LINUX_MDL_MAP * PLINUX_MDL_MAP;
+
+typedef struct _LINUX_MDL
+{
+    gctINT                  pid;
+    char *                  addr;
+
+#ifdef NO_DMA_COHERENT
+    gctPOINTER              kaddr;
+#endif /* NO_DMA_COHERENT */
+
+    gctINT                  numPages;
+    gctINT                  pagedMem;
+    gctBOOL                 contiguous;
+    dma_addr_t              dmaHandle;
+    PLINUX_MDL_MAP          maps;
+    struct _LINUX_MDL *     prev;
+    struct _LINUX_MDL *     next;
+}
+LINUX_MDL, *PLINUX_MDL;
+
+extern PLINUX_MDL_MAP
+FindMdlMap(
+    IN PLINUX_MDL Mdl,
+    IN gctINT PID
+    );
+
+typedef struct _DRIVER_ARGS
+{
+    gctPOINTER              InputBuffer;
+    gctUINT32               InputBufferSize;
+    gctPOINTER              OutputBuffer;
+    gctUINT32               OutputBufferSize;
+}
+DRIVER_ARGS;
+
+/* Cleanup the signal table. */
+gceSTATUS
+gckOS_CleanProcessSignal(
+    gckOS Os,
+    gctHANDLE Process
+    );
+
+#endif /* __gc_hal_kernel_os_h_ */