update vivant gpu(gc830) driver
author杜坤明 <dkm@rock-chips.com>
Fri, 5 Nov 2010 12:13:19 +0000 (20:13 +0800)
committer杜坤明 <dkm@rock-chips.com>
Fri, 5 Nov 2010 12:13:19 +0000 (20:13 +0800)
52 files changed:
drivers/staging/Kconfig [changed mode: 0644->0755]
drivers/staging/Makefile [changed mode: 0644->0755]
drivers/staging/rk29/vivante/Kbuild_ [new file with mode: 0644]
drivers/staging/rk29/vivante/Kconfig [new file with mode: 0644]
drivers/staging/rk29/vivante/Makefile [new file with mode: 0644]
drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c [new file with mode: 0644]
drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h [new file with mode: 0644]
drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/makefile.linux [new file with mode: 0644]
drivers/staging/rk29/vivante/config [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/inc/gc_hal.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/inc/gc_hal_base.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/inc/gc_hal_compiler.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/inc/gc_hal_driver.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/inc/gc_hal_dump.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/inc/gc_hal_engine.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/inc/gc_hal_enum.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/inc/gc_hal_mem.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/inc/gc_hal_options.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/inc/gc_hal_profiler.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/inc/gc_hal_raster.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/inc/gc_hal_types.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_command.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_event.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_heap.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_mmu.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_precomp.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_video_memory.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/kernel/makefile.linux [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/makefile.linux [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/libGAL.def.mak [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_debug.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_device.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_device.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_linux.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_linux.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_os.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_os.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/qnx/inc/gc_hal_common_qnx.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_debug.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_device.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_device.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_driver.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_os.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_os.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_qnx.c [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_qnx.h [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/qnx/kernel/makefile.linux [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/os/qnx/makefile.linux [new file with mode: 0644]
drivers/staging/rk29/vivante/hal/user/gc_hal_user_context.h [new file with mode: 0644]

old mode 100644 (file)
new mode 100755 (executable)
index ec496cc..34ee095
@@ -130,5 +130,7 @@ source "drivers/staging/rk2818/rk2818_dsp/Kconfig"
 source "drivers/staging/rk2818/rk1000_control/Kconfig"
 
 source "drivers/staging/rk2818/rk2818_power/Kconfig"
+
+source "drivers/staging/rk29/vivante/Kconfig"
 endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING
old mode 100644 (file)
new mode 100755 (executable)
index f34adae..5b2a508
@@ -48,3 +48,4 @@ obj-$(CONFIG_RK2818_DSP)        += rk2818/rk2818_dsp/
 obj-$(CONFIG_RK1000_CONTROL)    += rk2818/rk1000_control/
 obj-$(CONFIG_RK1000_TVOUT)    += rk2818/rk1000_tv/
 obj-$(CONFIG_RK2818_POWER)                             += rk2818/rk2818_power/
+obj-$(CONFIG_VIVANTE)           += rk29/vivante/
diff --git a/drivers/staging/rk29/vivante/Kbuild_ b/drivers/staging/rk29/vivante/Kbuild_
new file mode 100644 (file)
index 0000000..ec0cc6c
--- /dev/null
@@ -0,0 +1,171 @@
+##############################################################################
+#  
+#    Copyright (C) 2005 - 2010 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.
+#
+
+include $(AQROOT)/config
+
+DRIVER_OUT_DIR = hal/driver
+KERNEL_DIR ?= $(TOOL_DIR)/kernel
+
+OS_KERNEL_DIR   := hal/os/linux/kernel
+ARCH_KERNEL_DIR := arch/$(notdir $(AQARCH))/hal/kernel
+HAL_KERNEL_DIR  := hal/kernel
+
+EXTRA_CFLAGS += -Werror
+
+OBJS := $(OS_KERNEL_DIR)/gc_hal_kernel_debug.o \
+        $(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_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_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_hardware.o
+
+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
+
+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:
+       @mkdir -p $(DRIVER_OUT_DIR)
+       @make V=$(V) ARCH=$(ARCH_TYPE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
+
+clean:
+       @rm -rf $(OBJS)
+       @rm -rf $(DRIVER_OUT_DIR)
+       @rm -rf modules.order Module.symvers
+
+install: all
+       @mkdir -p $(SDK_DIR)/drivers
+       @cp $(DRIVER_OUT_DIR)/galcore.ko $(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 ($(ENABLE_ARM_L2_CACHE), 1)
+EXTRA_CFLAGS += -DENABLE_ARM_L2_CACHE=1
+else
+EXTRA_CFLAGS += -DENABLE_ARM_L2_CACHE=0
+endif
+
+ifeq ($(CONFIG_DOVE_GPU), 1)
+EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
+endif
+
+ifeq ($(gcdNO_POWER_MANAGEMENT), 1)
+EXTRA_CFLAGS += -DgcdNO_POWER_MANAGEMENT=1
+else
+EXTRA_CFLAGS += -DgcdNO_POWER_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
+
+EXTRA_CFLAGS += -I$(AQROOT)/hal/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/cmodel/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/user
+
+obj-m = $(DRIVER_OUT_DIR)/galcore.o
+
+$(DRIVER_OUT_DIR)/galcore-objs  = $(OBJS)
+
+endif
diff --git a/drivers/staging/rk29/vivante/Kconfig b/drivers/staging/rk29/vivante/Kconfig
new file mode 100644 (file)
index 0000000..7e0bfe8
--- /dev/null
@@ -0,0 +1,7 @@
+menu "GPU Vivante"
+config VIVANTE
+       tristate "ROCKCHIP Vivante GPU"
+       default y
+       help
+          Vivante GPU module.
+endmenu
diff --git a/drivers/staging/rk29/vivante/Makefile b/drivers/staging/rk29/vivante/Makefile
new file mode 100644 (file)
index 0000000..7889049
--- /dev/null
@@ -0,0 +1,202 @@
+##############################################################################
+#
+#    Copyright (C) 2005 - 2010 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.
+#
+
+################################################################
+# Arch.
+
+ARCH_TYPE       ?= arm
+CPU_TYPE        ?= arm920
+CPU_ARCH        ?= 0
+STATIC_LINK     ?= 0
+EGL_API_FB      ?= 0
+USE_VDK         ?= 0
+USE_PROFILER    ?= 0
+USE_SW_FB       ?= 0
+USE_3D_VG              =1
+ABI             ?= 0
+ANDROID         ?= 0
+EGL_API_ANDROID ?= 0
+ENUM_WORKAROUND ?= 0
+ENDIANNESS             ?=
+QNX             ?= 0
+LINUX_OABI             ?= 0
+USE_ARMCC              ?= 0
+
+ifeq ($(LINUX_OABI), 1)
+ABI             ?= 0
+else
+ABI             ?= aapcs-linux
+endif
+
+################################################################
+# Force to use dma_coherent_* stuff.
+
+NO_DMA_COHERENT ?= 0
+
+################################################################
+# Set this value to 1 if you are using ARM L2 cache.
+
+ENABLE_ARM_L2_CACHE    = 0
+
+################################################################
+# Set this value to 1 if you are using DOVE board.
+CONFIG_DOVE_GPU = 0
+
+
+ENABLE_GPU_CLOCK_BY_DRIVER = 0
+
+
+AQROOT          ?= drivers/staging/rk29/vivante
+AQARCH          ?= $(AQROOT)/arch/XAQ2
+
+#include $(AQROOT)/config
+ARCH_TYPE      ?= arm
+SDK_DIR                ?= $(AQROOT)/build/sdk
+USE_3D_VG      = 1
+
+DEBUG       = 1
+
+#DRIVER_OUT_DIR = hal/driver
+#KERNEL_DIR ?= $(TOOL_DIR)/kernel
+
+OS_KERNEL_DIR   := hal/os/linux/kernel
+ARCH_KERNEL_DIR := arch/XAQ2/hal/kernel
+HAL_KERNEL_DIR  := hal/kernel
+
+EXTRA_CFLAGS += -Werror
+
+OBJS := $(OS_KERNEL_DIR)/gc_hal_kernel_debug.o \
+        $(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_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_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_hardware.o
+
+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
+
+OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o \
+        $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware_command.o
+
+endif
+
+
+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 ($(ENABLE_ARM_L2_CACHE), 1)
+EXTRA_CFLAGS += -DENABLE_ARM_L2_CACHE=1
+else
+EXTRA_CFLAGS += -DENABLE_ARM_L2_CACHE=0
+endif
+
+ifeq ($(CONFIG_DOVE_GPU), 1)
+EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
+endif
+
+ifeq ($(gcdNO_POWER_MANAGEMENT), 1)
+EXTRA_CFLAGS += -DgcdNO_POWER_MANAGEMENT=1
+else
+EXTRA_CFLAGS += -DgcdNO_POWER_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
+
+EXTRA_CFLAGS += -I$(AQROOT)/hal/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/cmodel/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/user
+
+obj-$(CONFIG_VIVANTE) += galcore.o
+galcore-objs  := $(OBJS)
+
diff --git a/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c b/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
new file mode 100644 (file)
index 0000000..1e2d1cb
--- /dev/null
@@ -0,0 +1,3754 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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
+_IdentifyHardware(
+    IN gckOS Os,
+    OUT gceCHIPMODEL * ChipModel,
+    OUT gctUINT32_PTR ChipRevision,
+    OUT gctUINT32_PTR ChipFeatures,
+    OUT gctUINT32_PTR ChipMinorFeatures0,
+    OUT gctUINT32_PTR ChipMinorFeatures1
+    )
+{
+    gceSTATUS status;
+    gctUINT32 chipIdentity;
+
+    gcmkHEADER_ARG("Os=0x%x", Os);
+
+    /* Read chip identity register. */
+    gcmkONERROR(
+        gckOS_ReadRegister(Os, 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. */
+        gcmkONERROR(
+            gckOS_ReadRegister(Os,
+                               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_ReadRegister(Os, 0x00024, ChipRevision));
+
+        if ((*ChipModel    == gcv300)
+        &&  (*ChipRevision == 0x2201)
+        )
+        {
+            gctUINT32 date, time;
+
+            /* Read date and time registers. */
+            gcmkONERROR(
+                gckOS_ReadRegister(Os, 0x00028, &date));
+
+            gcmkONERROR(
+                gckOS_ReadRegister(Os, 0x0002C, &time));
+
+            if ((date == 0x20080814) && (time == 0x12051100))
+            {
+                /* This IP has an ECO; put the correct revision in it. */
+                *ChipRevision = 0x1051;
+            }
+        }
+    }
+
+    /* Read chip feature register. */
+    gcmkONERROR(
+        gckOS_ReadRegister(Os, 0x0001C, ChipFeatures));
+
+    /* 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)));
+    }
+
+    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;
+    }
+    else
+    {
+        /* Read chip minor feature register #0. */
+        gcmkONERROR(
+            gckOS_ReadRegister(Os,
+                               0x00034,
+                               ChipMinorFeatures0));
+
+        /* Disable fast clear flush on some specific cores. */
+        if (((*ChipModel == gcv600) && (*ChipRevision == 0x4302))
+        )
+        {
+            *ChipMinorFeatures0 = ((((gctUINT32) (*ChipMinorFeatures0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+        }
+
+        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_ReadRegister(Os,
+                                   0x00074,
+                                   ChipMinorFeatures1));
+        }
+        else
+        {
+            /* Chip doesn't has minor features register #1. */
+            *ChipMinorFeatures1 = 0;
+        }
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*ChipModel=%x *ChipRevision=%x *ChipFeatures=%08x "
+                   "*ChipMinorFeatures0=%08X *ChipMinorFeatures1=%08x",
+                   *ChipModel, *ChipRevision, *ChipFeatures,
+                   *ChipMinorFeatures0, *ChipMinorFeatures1);
+    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;
+    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;
+
+        /* Read gcChipSpecs register. */
+        gcmkONERROR(
+            gckOS_ReadRegister(Hardware->os, 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)))))) );
+    }
+
+    /* 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)
+                          ? 1 << registerMax
+                          : (Hardware->chipModel == gcv400) ? 32
+                          : 64;
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Specs: registerMax=%u%s",
+                   Hardware->registerMax,
+                   (registerMax == 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.
+**
+**  OUTPUT:
+**
+**      gckHARDWARE * Hardware
+**          Pointer to a variable that will hold the pointer to the gckHARDWARE
+**          object.
+*/
+gceSTATUS
+gckHARDWARE_Construct(
+    IN gckOS Os,
+    OUT gckHARDWARE * Hardware
+    )
+{
+    gckHARDWARE hardware = gcvNULL;
+    gceSTATUS status;
+    gceCHIPMODEL chipModel;
+    gctUINT32 chipRevision;
+    gctUINT32 chipFeatures;
+    gctUINT32 chipMinorFeatures0;
+    gctUINT32 chipMinorFeatures1;
+    gctUINT16 data = 0xff00;
+
+    gcmkHEADER_ARG("Os=0x%x", Os);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
+
+    /* Identify the hardware. */
+    gcmkONERROR(_IdentifyHardware(Os,
+                                  &chipModel,
+                                  &chipRevision,
+                                  &chipFeatures,
+                                  &chipMinorFeatures0,
+                                  &chipMinorFeatures1));
+
+    /* Allocate the gckHARDWARE object. */
+    gcmkONERROR(gckOS_Allocate(Os,
+                               gcmSIZEOF(struct _gckHARDWARE),
+                               (gctPOINTER *) &hardware));
+
+    /* Initialize the gckHARDWARE object. */
+    hardware->object.type = gcvOBJ_HARDWARE;
+    hardware->os          = Os;
+
+    /* Set chip identity. */
+    hardware->chipModel          = chipModel;
+    hardware->chipRevision       = chipRevision;
+    hardware->chipFeatures       = chipFeatures;
+    hardware->chipMinorFeatures0 = chipMinorFeatures0;
+    hardware->chipMinorFeatures1 = chipMinorFeatures1;
+    hardware->powerBaseAddress   = (  (chipModel == gcv300)
+                                   && (chipRevision < 0x2000)
+                                   ) ? 0x100 : 0x00;
+    hardware->powerMutex         = gcvNULL;
+
+    /* 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));
+
+    /* Set power state to ON. */
+    hardware->chipPowerState = gcvPOWER_ON;
+    hardware->lastWaitLink   = ~0U;
+
+    gcmkONERROR(gckOS_CreateMutex(Os, &hardware->powerMutex));
+
+    /* Return pointer to the gckHARDWARE object. */
+    *Hardware = hardware;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Hardware=0x%x", *Hardware);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (hardware->powerMutex != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckOS_DeleteMutex(Os, hardware->powerMutex));
+    }
+
+    if (hardware != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckOS_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);
+
+    /* Destroy the power mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Hardware->os, Hardware->powerMutex));
+
+    /* Mark the object as unknown. */
+    Hardware->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the object. */
+    gcmkONERROR(gckOS_Free(Hardware->os, Hardware));
+
+    /* Success. */
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  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_ReadRegister(Hardware->os,
+                                   0x00024,
+                                   &chipRev));
+
+    if (chipRev != Hardware->chipRevision)
+    {
+        /* Chip is not there! */
+        gcmkONERROR(gcvSTATUS_CONTEXT_LOSSED);
+    }
+
+    /* Disable isolate GPU bit. */
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+                                    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_WriteRegister(Hardware->os,
+                                    0x0003C,
+                                    ~0U));
+
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+                                    0x0003C,
+                                    0));
+
+    /* Get the system's physical base address. */
+    gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
+
+    /* Program the base addesses. */
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+                                    0x0041C,
+                                    baseAddress));
+
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+                                    0x00418,
+                                    baseAddress));
+
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+                                    0x00420,
+                                    baseAddress));
+
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+                                    0x00428,
+                                    baseAddress));
+
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+                                    0x00424,
+                                    baseAddress));
+
+#if !VIVANTE_PROFILER && 1
+    {
+        gctUINT32 data;
+
+        gcmkONERROR(gckOS_ReadRegister(Hardware->os,
+                                       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_WriteRegister(Hardware->os,
+                                        Hardware->powerBaseAddress
+                                        + 0x00100,
+                                        data));
+
+        /* 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_ReadRegister(Hardware->os,
+                                   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_WriteRegister(Hardware->os,
+                                    Hardware->powerBaseAddress
+                                    + 0x00104,
+                                    data));
+        }
+    }
+#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.
+**
+*/
+gceSTATUS
+gckHARDWARE_QueryChipIdentity(
+    IN gckHARDWARE Hardware,
+    OUT gceCHIPMODEL * ChipModel,
+    OUT gctUINT32 * ChipRevision,
+    OUT gctUINT32* ChipFeatures,
+    OUT gctUINT32* ChipMinorFeatures,
+    OUT gctUINT32* ChipMinorFeatures1
+    )
+{
+    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;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*ChipModel=0x%x *ChipRevision=0x%x *ChipFeatures=0x%08x "
+                   "*ChipMinorFeatures=0x%08x *ChipMinorFeatures1=0x%08x",
+                   gcmOPT_VALUE(ChipModel), gcmOPT_VALUE(ChipRevision),
+                   gcmOPT_VALUE(ChipFeatures), gcmOPT_VALUE(ChipMinorFeatures),
+                   gcmOPT_VALUE(ChipMinorFeatures1));
+    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
+    )
+{
+    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;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*StreamCount=%u *RegisterMax=%u *ThreadCount=%u "
+                   "*ShaderCoreCount=%u *VertexCacheSize=%u "
+                   "*VertexOutputBufferSize=%u",
+                   gcmOPT_VALUE(StreamCount), gcmOPT_VALUE(RegisterMax),
+                   gcmOPT_VALUE(ThreadCount), gcmOPT_VALUE(ShaderCoreCount),
+                   gcmOPT_VALUE(VertexCacheSize),
+                   gcmOPT_VALUE(VertexOutputBufferSize));
+    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=%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=%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_WriteRegister(Hardware->os, 0x00014, ~0U));
+
+    /* Write address register. */
+    gcmkONERROR(
+        gckOS_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 0x00658, control));
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                  "Started command buffer @ %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.
+**
+**      gctPOINTER * Wait
+**          Pointer to a variable that will receive the pointer to the WAIT
+**          command.  If 'Wait' 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 gctPOINTER * Wait,
+    OUT gctSIZE_T * WaitSize
+    )
+{
+    gceSTATUS status;
+    gctUINT32 address;
+    gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+    gctSIZE_T bytes;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=%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. */
+    bytes = gcmALIGN(Offset + 16, 8) - Offset;
+
+    if (Logical != gcvNULL)
+    {
+        /* Convert logical into hardware specific address. */
+        gcmkONERROR(
+            gckHARDWARE_ConvertLogical(Hardware,
+                                       Logical,
+                                       &address));
+
+        if (*Bytes < bytes)
+        {
+            /* Command queue too small. */
+            gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+        }
+
+        /* Append WAIT(200). */
+        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) (200) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "0x%08x: WAIT", address);
+
+        /* 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;
+
+        Hardware->lastWaitLink = address;
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "0x%08x: LINK %08x, #%lu",
+                       address + 8, address, bytes);
+
+        if (Wait != gcvNULL)
+        {
+            /* Return pointer to WAIT command. */
+            *Wait = Logical;
+        }
+
+        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 *Wait=0x%x *WaitSize=%lu",
+                   gcmOPT_VALUE(Bytes), gcmOPT_POINTER(Wait),
+                   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. */
+        gcmkVERIFY_OK(
+            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
+    )
+{
+    gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+    gceSTATUS status;
+
+    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));
+
+    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)));
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "0x%x: WAIT %u", Logical, Count);
+    }
+
+    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 gcdDEBUG
+        {
+            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.
+**
+**      gctUINT32 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 gctUINT32 Pipe,
+    IN OUT gctSIZE_T * Bytes
+    )
+{
+    gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Pipe=%u *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 == 0x1)
+              ? ((((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 %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 ? 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)))
+                   | ((((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[3] = stall;
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "0x%x: SEMAPHORE %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 %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;
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "0x%x: PIPE %u", 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)));
+
+#if gcdDEBUG
+        {
+            gctUINT32 phys;
+            gckHARDWARE_ConvertLogical(Hardware, Logical, &phys);
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                           "0x%08x: LINK %08x, #%lu", phys, address, bytes);
+        }
+#endif
+
+        /* 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;
+
+    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)))))));
+
+    /* Compute alignment factors. */
+    xAlignment = superTiled ? 64
+               : (Type == gcvSURF_TEXTURE) ? 4
+               : 16;
+    yAlignment = superTiled ? 64 : 4;
+
+    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=%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));
+
+    /* 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=%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;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    address = (gctUINT32)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=%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 event;
+    gctUINT32 data;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Hardware=0x%x InterruptValid=%d", Hardware, InterruptValid);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Extract gckEVENT object. */
+    event = Hardware->kernel->event;
+    gcmkVERIFY_OBJECT(event, gcvOBJ_EVENT);
+
+    if (InterruptValid)
+    {
+        /* Read AQIntrAcknowledge register. */
+        gcmkONERROR(
+            gckOS_ReadRegister(Hardware->os,
+                               0x00010,
+                               &data));
+
+#if gcdDEBUG
+        if (data & 0x80000000)
+        {
+            gcmkONERROR(gckOS_Broadcast(Hardware->os,
+                                        Hardware,
+                                        gcvBROADCAST_AXI_BUS_ERROR));
+        }
+#endif
+
+        if (data == 0)
+        {
+            /* Not our interrupt. */
+            status = gcvSTATUS_NOT_OUR_INTERRUPT;
+        }
+        else
+        {
+            /* Inform gckEVENT of the interrupt. */
+            status = gckEVENT_Interrupt(event, data & 0x7FFFFFFF);
+        }
+    }
+    else
+    {
+        /* Handle events. */
+        status = gckEVENT_Notify(event, 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;
+}
+
+/*******************************************************************************
+**
+**  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_WriteRegister(Hardware->os,
+                            0x00400,
+                            address + baseAddress));
+
+    /* Write the AQMemoryRaPageTable register. */
+    gcmkONERROR(
+        gckOS_WriteRegister(Hardware->os,
+                            0x00410,
+                            address + baseAddress));
+
+    /* Write the AQMemoryTxPageTable register. */
+    gcmkONERROR(
+        gckOS_WriteRegister(Hardware->os,
+                            0x00404,
+                            address + baseAddress));
+
+    /* Write the AQMemoryPePageTable register. */
+    gcmkONERROR(
+        gckOS_WriteRegister(Hardware->os,
+                            0x00408,
+                            address + baseAddress));
+
+    /* Write the AQMemoryPezPageTable register. */
+    gcmkONERROR(
+        gckOS_WriteRegister(Hardware->os,
+                            0x0040C,
+                            address + baseAddress));
+
+    /* 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;
+    gctUINT32 flush;
+    gctUINT32_PTR buffer;
+    gctSIZE_T bufferSize;
+
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Flush the memory controller. */
+    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)));
+
+    gcmkONERROR(
+        gckCOMMAND_Reserve(Hardware->kernel->command,
+                           8,
+                           (gctPOINTER *) &buffer,
+                           &bufferSize));
+
+    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] = flush;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "0x%x: FLUSH MMU", buffer);
+
+    gcmkONERROR(
+        gckCOMMAND_Execute(Hardware->kernel->command, 8));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* 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=%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_ReadRegister(Hardware->os, 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=%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=%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 %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
+    )
+{
+    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);
+        }
+
+        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_ReadRegister(Hardware->os, 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 copression 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_WriteRegister(Hardware->os,
+                                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;
+}
+
+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_OFF           = 1 << 8,
+    gcvPOWER_FLAG_CLOCK_OFF     = 1 << 9,
+}
+gcePOWER_FLAGS;
+
+/*******************************************************************************
+**
+**  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 0
+#if !gcdNO_POWER_MANAGEMENT
+    gceSTATUS status;
+    gckCOMMAND command = gcvNULL;
+    gckOS os;
+    gctUINT flag, clock;
+    gctPOINTER buffer;
+    gctSIZE_T bytes, requested;
+    gctBOOL acquired = gcvFALSE;
+    gctBOOL reserved = gcvFALSE;
+    gctBOOL mutexAcquired = gcvFALSE;
+    gctBOOL stall = gcvTRUE;
+    gctBOOL broadcast = gcvFALSE;
+    gctUINT32 process, thread;
+
+    /* 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_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_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,
+            /* OFF               */ gcvPOWER_FLAG_SAVE |
+                                    gcvPOWER_FLAG_OFF  |
+                                    gcvPOWER_FLAG_CLOCK_OFF,
+            /* IDLE              */ gcvPOWER_FLAG_START |
+                                    gcvPOWER_FLAG_DELAY,
+            /* 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);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    /* Get the gckOS object pointer. */
+    os = Hardware->os;
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+    /* 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 breoadcast. */
+        State     = gcvPOWER_IDLE;
+        broadcast = gcvTRUE;
+        break;
+
+    case gcvPOWER_SUSPEND_BROADCAST:
+        /* Convert to SUSPEND and note we are inside breoadcast. */
+        State     = gcvPOWER_SUSPEND;
+        broadcast = gcvTRUE;
+        break;
+
+    case gcvPOWER_OFF_BROADCAST:
+        /* Convert to OFF and note we are inside breoadcast. */
+        State     = gcvPOWER_OFF;
+        broadcast = gcvTRUE;
+        break;
+
+    case gcvPOWER_OFF_RECOVERY:
+        /* Convert to OFF and note we are inside breoadcast. */
+        State     = gcvPOWER_OFF;
+        stall     = gcvFALSE;
+        broadcast = gcvTRUE;
+        break;
+
+    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
+            {
+                /* Acquire the power mutex. */
+                gcmkONERROR(
+                    gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
+            }
+        }
+    }
+    else
+    {
+        /* Acquire the power mutex. */
+        gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
+    }
+
+    Hardware->powerProcess = process;
+    Hardware->powerThread  = thread;
+    mutexAcquired          = gcvTRUE;
+
+    /* Grab control flags and clock. */
+    flag  = flags[Hardware->chipPowerState][State];
+    clock = clocks[State];
+
+    if (flag == 0)
+    {
+        /* Release the power mutex. */
+        gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+        /* No need to do anything. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+    gcmkASSERT(Hardware->kernel          != gcvNULL);
+    gcmkASSERT(Hardware->kernel->command != gcvNULL);
+    command = Hardware->kernel->command;
+
+    if (flag & gcvPOWER_FLAG_INITIALIZE)
+    {
+        /* Turn on the power. */
+        gcmkONERROR(gckOS_SetGPUPower(Hardware->os, gcvTRUE, gcvTRUE));
+       }
+
+    if ((flag & gcvPOWER_FLAG_STALL) && stall)
+    {
+        gctBOOL idle;
+        gctINT32 atomValue;
+
+        /* Check commit atom. */
+        gcmkONERROR(
+            gckOS_AtomGet(Hardware->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
+        {
+            /* 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));
+
+            reserved = gcvTRUE;
+
+            /* Append a flush. */
+            gcmkONERROR(gckHARDWARE_Flush(Hardware,
+                                          gcvFLUSH_ALL,
+                                          buffer,
+                                          &bytes));
+
+            /* Execute the command queue. */
+            acquired = gcvFALSE;
+            gcmkONERROR(gckCOMMAND_Execute(command, requested));
+
+            /* Wait to finish all commands. */
+            gcmkONERROR(gckCOMMAND_Stall(command));
+        }
+    }
+
+    if (flag & gcvPOWER_FLAG_ACQUIRE)
+    {
+        /* Acquire the power management semaphore. */
+        gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+
+        acquired = gcvTRUE;
+    }
+
+    if (flag & gcvPOWER_FLAG_STOP)
+    {
+        /* Stop the command parser. */
+        gcmkONERROR(gckCOMMAND_Stop(command));
+    }
+
+    /* Write the clock control register. */
+    gcmkONERROR(gckOS_WriteRegister(os,
+                                    0x00000,
+                                    clock));
+
+    /* Done loading the frequency scaler. */
+    gcmkONERROR(gckOS_WriteRegister(os,
+                                    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));
+    }
+
+    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->currentContext = 0;
+    }
+
+    if (flag & (gcvPOWER_FLAG_OFF | gcvPOWER_FLAG_CLOCK_OFF))
+    {
+        /* Turn off the GPU power. */
+        gcmkONERROR(
+            gckOS_SetGPUPower(os,
+                              (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
+                                                               : gcvTRUE,
+                              (flag & gcvPOWER_FLAG_OFF) ? gcvFALSE : gcvTRUE));
+    }
+
+    if (flag & gcvPOWER_FLAG_START)
+    {
+        /* Start the command processor. */
+        gcmkONERROR(gckCOMMAND_Start(command));
+    }
+
+    if (flag & gcvPOWER_FLAG_RELEASE)
+    {
+        /* Release the power management semaphore. */
+        gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
+    }
+
+    /* Save the new power state. */
+    Hardware->chipPowerState = State;
+
+    /* Release the power mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (reserved)
+    {
+        /* Release command queue. */
+        gcmkVERIFY_OK(gckCOMMAND_Release(command));
+    }
+
+    if (acquired)
+    {
+        /* Release semaphore. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseSemaphore(Hardware->os, command->powerSemaphore));
+    }
+
+    if (mutexAcquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+#else
+    /* Do nothing */
+    return gcvSTATUS_OK;
+#endif
+#endif
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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_ReadRegister(Hardware->os, 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_ReadRegister(Hardware->os,
+                                           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_WriteRegister(Hardware->os, \
+                            GC_DEBUG_CONTROL##control##_Address, \
+                            gcmSETFIELD(0, \
+                                        GC_DEBUG_CONTROL##control, \
+                                        block, \
+                                        index))); \
+    gcmkONERROR( \
+        gckOS_ReadRegister(Hardware->os, \
+                           GC_DEBUG_SIGNALS_##block##_Address, \
+                           &profiler->data))
+
+#define gcmkRESET_DEBUG_REGISTER(control, block) \
+    gcmkONERROR( \
+        gckOS_WriteRegister(Hardware->os, \
+                            GC_DEBUG_CONTROL##control##_Address, \
+                            gcmSETFIELD(0, \
+                                        GC_DEBUG_CONTROL##control, \
+                                        block, \
+                                        15))); \
+    gcmkONERROR( \
+        gckOS_WriteRegister(Hardware->os, \
+                            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_ReadRegister(Hardware->os,
+                               0x00438,
+                               &Profile->cycleCount));
+
+        /* Read pixels rendered by 2D engine. */
+        gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00454, &profiler->pixelsRendered));
+
+        /* Reset counter. */
+        gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os,
+                           0x00040,
+                           &profiler->gpuTotalRead64BytesPerFrame));
+    gcmkONERROR(
+        gckOS_ReadRegister(Hardware->os,
+                           0x00044,
+                           &profiler->gpuTotalWrite64BytesPerFrame));
+    gcmkONERROR(
+        gckOS_ReadRegister(Hardware->os,
+                           0x00438,
+                           &profiler->gpuCyclesCounter));
+
+    /* Reset counters. */
+    gcmkONERROR(
+        gckOS_WriteRegister(Hardware->os, 0x0003C, 1));
+    gcmkONERROR(
+        gckOS_WriteRegister(Hardware->os, 0x0003C, 0));
+    gcmkONERROR(
+        gckOS_WriteRegister(Hardware->os, 0x00438, 0));
+
+    /* PE */
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00454, &profiler->pe_pixel_count_killed_by_color_pipe));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00454, &profiler->pe_pixel_count_killed_by_depth_pipe));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00454, &profiler->pe_pixel_count_drawn_by_color_pipe));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00454, &profiler->pe_pixel_count_drawn_by_depth_pipe));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0045C, &profiler->ps_inst_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0045C, &profiler->rendered_pixel_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0045C, &profiler->vs_inst_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0045C, &profiler->rendered_vertice_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0045C, &profiler->vtx_branch_inst_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0045C, &profiler->vtx_texld_inst_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0045C, &profiler->pxl_branch_inst_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0045C, &profiler->pxl_texld_inst_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00460, &profiler->pa_input_vtx_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00460, &profiler->pa_input_prim_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00460, &profiler->pa_output_prim_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00460, &profiler->pa_depth_clipped_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00460, &profiler->pa_trivial_rejected_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00460, &profiler->pa_culled_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00464, &profiler->se_culled_triangle_count));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00464, &profiler->se_culled_lines_count));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00448, &profiler->ra_valid_pixel_count));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00448, &profiler->ra_total_quad_count));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00448, &profiler->ra_valid_quad_count_after_early_z));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00448, &profiler->ra_total_primitive_count));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00448, &profiler->ra_pipe_cache_miss_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00448, &profiler->ra_prefetch_cache_miss_counter));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_total_bilinear_requests));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_total_trilinear_requests));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_total_discarded_texture_requests));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_total_texture_requests));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_mem_read_count));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_mem_read_in_8B_count));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_cache_miss_count));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_cache_hit_texel_count));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_cache_miss_texel_count));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00468, &profiler->mc_total_read_req_8B_from_pipeline));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00468, &profiler->mc_total_read_req_8B_from_IP));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x00468, &profiler->mc_total_write_req_8B_from_pipeline));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0046C, &profiler->hi_axi_cycles_read_request_stalled));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0046C, &profiler->hi_axi_cycles_write_request_stalled));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_ReadRegister(Hardware->os, 0x0046C, &profiler->hi_axi_cycles_write_data_stalled));
+    gcmkONERROR(gckOS_WriteRegister(Hardware->os, 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_WriteRegister(Hardware->os, 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
+
+gceSTATUS
+gckHARDWARE_Reset(
+    IN gckHARDWARE Hardware
+    )
+{
+    gceSTATUS status;
+    gctUINT32 control, idle;
+    gckCOMMAND command;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkASSERT(Hardware->kernel != gcvNULL);
+    command = Hardware->kernel->command;
+    gcmkASSERT(command != gcvNULL);
+
+    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));
+
+        /* Grab the queue mutex. */
+        gcmkONERROR(
+            gckOS_AcquireMutex(Hardware->os,
+                               command->mutexQueue,
+                               gcvINFINITE));
+    }
+
+    /* Read register. */
+    gcmkONERROR(
+        gckOS_ReadRegister(Hardware->os,
+                           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_WriteRegister(Hardware->os,
+                                0x00000,
+                                control));
+
+        /* Set soft reset. */
+        gcmkONERROR(
+            gckOS_WriteRegister(Hardware->os,
+                                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(Hardware->os, 1));
+
+        /* Reset soft reset bit. */
+        gcmkONERROR(
+            gckOS_WriteRegister(Hardware->os,
+                                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_WriteRegister(Hardware->os,
+                                0x00000,
+                                control));
+
+        /* Read idle register. */
+        gcmkONERROR(
+            gckOS_ReadRegister(Hardware->os,
+                               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_ReadRegister(Hardware->os,
+                               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;
+    }
+
+    /* 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))))))))
+    {
+        /* 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;
+        }
+    }
+
+    /* Return the flag. */
+    *NeedBase = need;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*NeedBase=%d", *NeedBase);
+    return gcvSTATUS_OK;
+}
+
diff --git a/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h b/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h
new file mode 100644 (file)
index 0000000..70e659f
--- /dev/null
@@ -0,0 +1,90 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* gckHARDWARE object. */
+struct _gckHARDWARE
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gctKERNEL object. */
+    gckKERNEL                   kernel;
+
+    /* Pointer to gctOS object. */
+    gckOS                       os;
+
+    /* Chip characteristics. */
+    gceCHIPMODEL                chipModel;
+    gctUINT32                   chipRevision;
+    gctUINT32                   chipFeatures;
+    gctUINT32                   chipMinorFeatures0;
+    gctUINT32                   chipMinorFeatures1;
+    gctBOOL                     allowFastClear;
+    gctBOOL                     allowCompression;
+    gctUINT32                   powerBaseAddress;
+    gctBOOL                     extraEventStates;
+
+    gctUINT32                   streamCount;
+    gctUINT32                   registerMax;
+    gctUINT32                   threadCount;
+    gctUINT32                   shaderCoreCount;
+    gctUINT32                   vertexCacheSize;
+    gctUINT32                   vertexOutputBufferSize;
+
+    /* Big endian */
+    gctBOOL                     bigEndian;
+
+    /* Chip status */
+    gctPOINTER                  powerMutex;
+    gctUINT32                   powerProcess;
+    gctUINT32                   powerThread;
+    gceCHIPPOWERSTATE           chipPowerState;
+    gctUINT32                   lastWaitLink;
+};
+
+gceSTATUS
+gckHARDWARE_GetBaseAddress(
+    IN gckHARDWARE Hardware,
+    OUT gctUINT32_PTR BaseAddress
+    );
+
+gceSTATUS
+gckHARDWARE_NeedBaseAddress(
+    IN gckHARDWARE Hardware,
+    IN gctUINT32 State,
+    OUT gctBOOL_PTR NeedBase
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_hardware_h_ */
+
diff --git a/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/makefile.linux b/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/makefile.linux
new file mode 100644 (file)
index 0000000..ca9f433
--- /dev/null
@@ -0,0 +1,55 @@
+##############################################################################
+#  
+#    Copyright (C) 2005 - 2010 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 architecture dependent kernel HAL layer.
+#
+#
+
+
+################################################################################
+# Include common definitions.
+
+include $(AQROOT)/makefile.linux.def
+
+################################################################################
+# Define a shortcut for the main target.
+
+STATIC = 1
+TARGET_NAME = libhalarchkernel.a
+
+################################################################################
+# Supply additional include directories.
+
+INCLUDE += -I$(AQROOT)/hal/inc
+INCLUDE += -I$(AQROOT)/hal/kernel
+INCLUDE += -I$(AQARCH)/hal/kernel
+INCLUDE += -I$(AQARCH)/cmodel/inc
+
+CFLAGS += $(INCLUDE) -Werror -ansi
+
+################################################################################
+# Describe object files.
+
+OBJECTS = $(OBJ_DIR)/gc_hal_kernel_hardware.o
+
+include $(AQROOT)/common.target
diff --git a/drivers/staging/rk29/vivante/config b/drivers/staging/rk29/vivante/config
new file mode 100644 (file)
index 0000000..779ac82
--- /dev/null
@@ -0,0 +1,24 @@
+##############################################################################
+#  
+#    Copyright (C) 2005 - 2010 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
diff --git a/drivers/staging/rk29/vivante/hal/inc/gc_hal.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal.h
new file mode 100644 (file)
index 0000000..01e7d36
--- /dev/null
@@ -0,0 +1,1859 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_types.h"
+#include "gc_hal_enum.h"
+#include "gc_hal_base.h"
+#include "gc_hal_profiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* Alignment Macros *******************************
+\******************************************************************************/
+
+#define gcmALIGN(n, align) \
+( \
+    ((n) + ((align) - 1)) & ~((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_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;
+
+/* Kernel settings. */
+typedef struct _gcsKERNEL_SETTINGS
+{
+    /* Used RealTime signal between kernel and user. */
+    gctINT signal;
+}
+gcsKERNEL_SETTINGS;
+
+typedef struct _gckHARDWARE *       gckHARDWARE;
+
+/*******************************************************************************
+**
+**  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.
+*/
+#ifndef EGL_API_ANDROID
+#   define _gcmVERIFY_OBJECT(prefix, obj, t) \
+        do \
+        { \
+            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; \
+            } \
+        } \
+        while (gcvFALSE)
+#   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
+
+/******************************************************************************\
+********************************** gckOS Object *********************************
+\******************************************************************************/
+
+typedef struct _gckOS           * gckOS;
+
+/* 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,
+#ifdef __QNXNTO__
+    IN gctUINT32 Pid,
+#endif
+    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
+    );
+
+/* Unlock pages. */
+gceSTATUS
+gckOS_UnlockPages(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+#ifdef __QNXNTO__
+    IN gctUINT32 Pid,
+#endif
+    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
+    );
+
+/* 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
+    );
+
+/* Write data to a hardware register. */
+gceSTATUS
+gckOS_WriteRegister(
+    IN gckOS Os,
+    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 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_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
+    );
+
+/* 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
+    );
+
+#ifdef __QNXNTO__
+/* Map user physical address. */
+gceSTATUS
+gckOS_MapUserPhysical(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Phys,
+    OUT gctPOINTER * KernelPointer
+    );
+
+/* Allocate from user's shared pool. */
+gceSTATUS
+gckOS_AllocateNonPagedMemoryShmPool(
+    IN gckOS Os,
+    IN gctBOOL InUserSpace,
+    IN gctUINT32 Pid,
+    IN gctHANDLE Handle,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctPHYS_ADDR * Physical,
+    OUT gctPOINTER * Logical
+    );
+#endif
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+    IN gckOS Os
+    );
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+    IN gckOS Os
+    );
+
+/* 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
+    );
+
+/*******************************************************************************
+**
+**  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
+    );
+
+/*******************************************************************************
+**
+**  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 *********************************
+\******************************************************************************/
+
+/* User signal command codes. */
+typedef enum _gceUSER_SIGNAL_COMMAND_CODES
+{
+    gcvUSER_SIGNAL_CREATE,
+    gcvUSER_SIGNAL_DESTROY,
+    gcvUSER_SIGNAL_SIGNAL,
+    gcvUSER_SIGNAL_WAIT,
+}
+gceUSER_SIGNAL_COMMAND_CODES;
+
+/* 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
+    );
+
+/* Map user memory. */
+gceSTATUS
+gckOS_MapUserMemory(
+    IN gckOS Os,
+    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
+    );
+
+#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_CacheFlush(
+    gckOS Os,
+    gctHANDLE ProcessId,
+    gctPOINTER Logical,
+    gctSIZE_T Bytes
+    );
+
+gceSTATUS
+gckOS_CacheInvalidate(
+    gckOS Os,
+    gctHANDLE ProcessId,
+    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
+    );
+
+/*******************************************************************************
+**
+**  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
+    );
+
+/* Delete a semahore. */
+gceSTATUS
+gckOS_DestroySemaphore(
+    IN gckOS Os,
+    IN gctPOINTER Semaphore
+    );
+
+/* Acquire a semahore. */
+gceSTATUS
+gckOS_AcquireSemaphore(
+    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
+    );
+
+#if defined gcdHAL_TEST
+gceSTATUS
+gckHEAP_Test(
+    IN gckHEAP Heap,
+    IN gctSIZE_T Vectors,
+    IN gctSIZE_T MaxSize
+    );
+#endif
+
+/******************************************************************************\
+******************************** gckVIDMEM Object ******************************
+\******************************************************************************/
+
+typedef struct _gckVIDMEM *         gckVIDMEM;
+typedef union  _gcuVIDMEM_NODE *    gcuVIDMEM_NODE_PTR;
+typedef struct _gckKERNEL *         gckKERNEL;
+
+/* 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,
+#ifdef __QNXNTO__
+    IN gctHANDLE Handle,
+#endif
+    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,
+#ifdef __QNXNTO__
+    IN gctHANDLE Handle,
+#endif
+    OUT gcuVIDMEM_NODE_PTR * Node
+    );
+
+/* Free memory. */
+gceSTATUS
+gckVIDMEM_Free(
+    IN gcuVIDMEM_NODE_PTR Node
+    );
+
+/* Lock memory. */
+gceSTATUS
+gckVIDMEM_Lock(
+    IN gcuVIDMEM_NODE_PTR Node,
+    OUT gctUINT32 * Address
+    );
+
+/* Unlock memory. */
+gceSTATUS
+gckVIDMEM_Unlock(
+    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,
+#ifdef __QNXNTO__
+    IN gctHANDLE Handle,
+#endif
+    OUT gcuVIDMEM_NODE_PTR * Node
+    );
+
+/* Destroy a gcuVIDMEM_NODE union for virtual memory. */
+gceSTATUS
+gckVIDMEM_DestroyVirtual(
+    IN gcuVIDMEM_NODE_PTR Node
+    );
+
+#ifdef __QNXNTO__
+/* Set the allocating process' PID for this node. */
+gceSTATUS
+gckVIDMEM_SetPID(
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctUINT32 Pid);
+#endif
+
+/******************************************************************************\
+******************************** gckKERNEL Object ******************************
+\******************************************************************************/
+
+struct _gcsHAL_INTERFACE;
+
+/* Notifications. */
+typedef enum _gceNOTIFY
+{
+    gcvNOTIFY_INTERRUPT,
+    gcvNOTIFY_COMMAND_QUEUE,
+}
+gceNOTIFY;
+
+/* Event locations. */
+typedef enum _gceKERNEL_WHERE
+{
+    gcvKERNEL_COMMAND,
+    gcvKERNEL_VERTEX,
+    gcvKERNEL_TRIANGLE,
+    gcvKERNEL_TEXTURE,
+    gcvKERNEL_PIXEL,
+}
+gceKERNEL_WHERE;
+
+/* 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 gctPOINTER Context,
+    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
+    );
+
+/* 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
+    );
+
+#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
+    );
+
+/******************************************************************************\
+******************************* gckHARDWARE Object *****************************
+\******************************************************************************/
+
+/* Construct a new gckHARDWARE object. */
+gceSTATUS
+gckHARDWARE_Construct(
+    IN gckOS Os,
+    OUT gckHARDWARE * Hardware
+    );
+
+/* Destroy an gckHARDWARE object. */
+gceSTATUS
+gckHARDWARE_Destroy(
+    IN gckHARDWARE Hardware
+    );
+
+/* 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 gctPOINTER * Wait,
+    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 gctUINT32 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
+    );
+
+/* 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
+    );
+
+/* 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
+    );
+
+/* 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
+    );
+
+/******************************************************************************\
+***************************** 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
+    );
+
+/******************************************************************************\
+******************************** 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
+    );
+
+/* 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
+    );
+
+struct _gcsQUEUE;
+
+/* Commit an event queue. */
+gceSTATUS
+gckEVENT_Commit(
+    IN gckEVENT Event,
+    IN struct _gcsQUEUE * Queue
+    );
+
+/* 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
+    );
+
+/* 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 gcoCMDBUF CommandBuffer,
+    IN gcoCONTEXT Context,
+    IN gctHANDLE Process
+    );
+
+/* Reserve space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Reserve(
+    IN gckCOMMAND Command,
+    IN gctSIZE_T RequestedBytes,
+    OUT gctPOINTER * Buffer,
+    OUT gctSIZE_T * BufferSize
+    );
+
+/* Release reserved space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Release(
+    IN gckCOMMAND Command
+    );
+
+/* 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
+    );
+
+/******************************************************************************\
+********************************* 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
+    );
+
+/* 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
+    );
+
+#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 gckMMU Mmu,
+    IN gctHANDLE Handle
+    );
+#endif
+
+#if defined gcdHAL_TEST
+gceSTATUS
+gckMMU_Test(
+    IN gckMMU Mmu,
+    IN gctSIZE_T Vectors,
+    IN gctINT MaxSize
+    );
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryProfileRegisters(
+    IN gckHARDWARE Hardware,
+    OUT gcsPROFILER_COUNTERS * Counters
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/inc/gc_hal_base.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal_base.h
new file mode 100644 (file)
index 0000000..738d189
--- /dev/null
@@ -0,0 +1,2485 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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 _gcoHAL *                gcoHAL;
+typedef struct _gcoOS *                 gcoOS;
+typedef struct _gco2D *                 gco2D;
+typedef struct _gcoVG *                 gcoVG;
+typedef struct _gco3D *                 gco3D;
+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;
+
+/******************************************************************************\
+********************************* Enumerations *********************************
+\******************************************************************************/
+
+/* Video memory pool type. */
+typedef enum _gcePOOL
+{
+    gcvPOOL_UNKNOWN,
+    gcvPOOL_DEFAULT,
+    gcvPOOL_LOCAL,
+    gcvPOOL_LOCAL_INTERNAL,
+    gcvPOOL_LOCAL_EXTERNAL,
+    gcvPOOL_UNIFIED,
+    gcvPOOL_SYSTEM,
+    gcvPOOL_VIRTUAL,
+    gcvPOOL_USER,
+    gcvPOOL_CONTIGUOUS
+}
+gcePOOL;
+
+/* 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,
+}
+gceAPI;
+
+/* Depth modes. */
+typedef enum _gceDEPTH_MODE
+{
+    gcvDEPTH_NONE,
+    gcvDEPTH_Z,
+    gcvDEPTH_W,
+}
+gceDEPTH_MODE;
+
+typedef enum _gceWHERE
+{
+    gcvWHERE_COMMAND,
+    gcvWHERE_RASTER,
+    gcvWHERE_PIXEL,
+}
+gceWHERE;
+
+typedef enum _gceHOW
+{
+    gcvHOW_SEMAPHORE            = 0x1,
+    gcvHOW_STALL                = 0x2,
+    gcvHOW_SEMAPHORE_STALL      = 0x3,
+}
+gceHOW;
+
+/******************************************************************************\
+********************************* 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
+    );
+
+/* Get pointer to gcoVG object. */
+gceSTATUS
+gcoHAL_GetVGEngine(
+    IN gcoHAL Hal,
+    OUT gcoVG * Engine
+    );
+
+/* Get pointer to gco3D object. */
+gceSTATUS
+gcoHAL_Get3DEngine(
+    IN gcoHAL Hal,
+    OUT gco3D * Engine
+    );
+
+/* 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 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
+    );
+
+gceSTATUS
+gcoHAL_ProfileStart(
+    IN gcoHAL Hal
+    );
+
+gceSTATUS
+gcoHAL_ProfileEnd(
+    IN gcoHAL Hal,
+    IN gctCONST_STRING Title
+    );
+
+/* 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
+    );
+
+/******************************************************************************\
+********************************** gcoOS Object *********************************
+\******************************************************************************/
+
+/* 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
+    );
+
+/* 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
+        );
+
+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
+    );
+
+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 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_PrintStrVSafe(
+    OUT gctSTRING String,
+    IN gctSIZE_T StringSize,
+    IN OUT gctUINT * Offset,
+    IN gctCONST_STRING Format,
+    IN gctPOINTER Arguments
+    );
+
+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
+    );
+
+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
+        );
+
+/* 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
+    );
+
+/*----------------------------------------------------------------------------*/
+/*----- 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
+    );
+
+/*----------------------------------------------------------------------------*/
+/*----- 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
+    );
+
+/* 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_CacheFlush(
+    IN gcoOS Os,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    );
+
+gceSTATUS
+gcoOS_CacheInvalidate(
+    IN gcoOS Os,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    );
+
+/*******************************************************************************
+**  gcoMATH object
+*/
+
+#define gcdPI                   3.14159265358979323846f
+
+gctUINT32
+gcoMATH_Log2in5dot5(
+    IN gctINT X
+    );
+
+gctFLOAT
+gcoMATH_Sine(
+    IN gctFLOAT X
+    );
+
+gctFLOAT
+gcoMATH_Cosine(
+    IN gctFLOAT X
+    );
+
+gctFLOAT
+gcoMATH_Floor(
+    IN gctFLOAT X
+    );
+
+gctFLOAT
+gcoMATH_Ceiling(
+    IN gctFLOAT X
+    );
+
+gctFLOAT
+gcoMATH_SquareRoot(
+    IN gctFLOAT X
+    );
+
+gctFLOAT
+gcoMATH_Log2(
+    IN gctFLOAT X
+    );
+
+gctFLOAT
+gcoMATH_Power(
+    IN gctFLOAT X,
+    IN gctFLOAT Y
+    );
+
+gctFLOAT
+gcoMATH_Modulo(
+    IN gctFLOAT X,
+    IN gctFLOAT Y
+    );
+
+gctFLOAT
+gcoMATH_Exp(
+    IN gctFLOAT X
+    );
+
+gctFLOAT
+gcoMATH_Absolute(
+    IN gctFLOAT X
+    );
+
+gctFLOAT
+gcoMATH_ArcCosine(
+    IN gctFLOAT X
+    );
+
+gctFLOAT
+gcoMATH_Tangent(
+    IN gctFLOAT X
+    );
+
+gctFLOAT
+gcoMATH_UInt2Float(
+    IN gctUINT X
+    );
+
+gctUINT
+gcoMATH_Float2UInt(
+    IN gctFLOAT X
+    );
+
+gctFLOAT
+gcoMATH_Multiply(
+    IN gctFLOAT X,
+    IN gctFLOAT Y
+    );
+
+/******************************************************************************\
+**************************** 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;
+
+/* 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
+    );
+
+/* 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
+    );
+
+/* Verify and return the state of the tile status mechanism. */
+gceSTATUS
+gcoSURF_IsTileStatusSupported(
+    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
+    );
+
+/* 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 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 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
+    );
+
+
+/******************************************************************************\
+**************************** 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
+    );
+
+/* Profile the heap. */
+gceSTATUS
+gcoHEAP_ProfileStart(
+    IN gcoHEAP Heap
+    );
+
+gceSTATUS
+gcoHEAP_ProfileEnd(
+    IN gcoHEAP Heap,
+    IN gctCONST_STRING Title
+    );
+
+#if defined gcdHAL_TEST
+gceSTATUS
+gcoHEAP_Test(
+    IN gcoHEAP Heap,
+    IN gctSIZE_T Vectors,
+    IN gctSIZE_T MaxSize
+    );
+#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 gcdDEBUG
+#   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
+
+gcoOS_DebugTrace(
+    IN gctUINT32 Level,
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+#if gcdDEBUG
+#   define gcmTRACE             gcoOS_DebugTrace
+#   define gcmkTRACE            gckOS_DebugTrace
+#elif gcdHAS_ELLIPSES
+#   define gcmTRACE(...)
+#   define gcmkTRACE(...)
+#else
+    gcmINLINE static void
+    __dummy_trace(
+        IN gctUINT32 Level,
+        IN gctCONST_STRING Message,
+        ...
+        )
+    {
+    }
+#   define gcmTRACE             __dummy_trace
+#   define gcmkTRACE            __dummy_trace
+#endif
+
+/* Debug zones. */
+#define gcvZONE_OS              (1 << 0)
+#define gcvZONE_HARDWARE        (1 << 1)
+#define gcvZONE_HEAP            (1 << 2)
+
+/* 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)
+
+/* 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)
+
+/* 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
+gcoOS_DebugTraceZone(
+    IN gctUINT32 Level,
+    IN gctUINT32 Zone,
+    IN gctCONST_STRING Message,
+    ...
+    );
+
+#if gcdDEBUG
+#   define gcmTRACE_ZONE            gcoOS_DebugTraceZone
+#   define gcmkTRACE_ZONE           gckOS_DebugTraceZone
+#elif gcdHAS_ELLIPSES
+#   define gcmTRACE_ZONE(...)
+#   define gcmkTRACE_ZONE(...)
+#else
+    gcmINLINE static void
+    __dummy_trace_zone(
+        IN gctUINT32 Level,
+        IN gctUINT32 Zone,
+        IN gctCONST_STRING Message,
+        ...
+        )
+    {
+    }
+#   define gcmTRACE_ZONE            __dummy_trace_zone
+#   define gcmkTRACE_ZONE           __dummy_trace_zone
+#endif
+
+/******************************************************************************\
+******************************** Logging Macros ********************************
+\******************************************************************************/
+
+#define gcdHEADER_LEVEL             gcvLEVEL_VERBOSE
+
+#define gcmHEADER() \
+    gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                  "++%s(%d)", __FUNCTION__, __LINE__)
+
+#if gcdHAS_ELLIPSES
+#   define gcmHEADER_ARG(Text, ...) \
+        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
+
+#define gcmFOOTER() \
+    gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                  "--%s(%d): status=%d", \
+                  __FUNCTION__, __LINE__, status)
+
+#define gcmFOOTER_NO() \
+    gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                  "--%s(%d)", __FUNCTION__, __LINE__)
+
+#if gcdHAS_ELLIPSES
+#   define gcmFOOTER_ARG(Text, ...) \
+        gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                      "--%s(%d): " Text, \
+                      __FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+    gcmINLINE static void
+    __dummy_footer_arg(
+        IN gctCONST_STRING Text,
+        ...
+        )
+    {
+    }
+#   define gcmFOOTER_ARG                __dummy_footer_arg
+#endif
+
+#define gcmkHEADER() \
+    gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                   "++%s(%d)", __FUNCTION__, __LINE__)
+
+#if gcdHAS_ELLIPSES
+#   define gcmkHEADER_ARG(Text, ...) \
+        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
+
+#define gcmkFOOTER() \
+    gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                   "--%s(%d): status=%d", \
+                   __FUNCTION__, __LINE__, status)
+
+#define gcmkFOOTER_NO() \
+    gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                   "--%s(%d)", __FUNCTION__, __LINE__)
+
+#if gcdHAS_ELLIPSES
+#   define gcmkFOOTER_ARG(Text, ...) \
+        gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                       "--%s(%d): " Text, \
+                       __FUNCTION__, __LINE__, __VA_ARGS__)
+#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))
+
+void
+gcoOS_Print(
+    IN gctCONST_STRING Message,
+    ...
+    );
+void
+gckOS_Print(
+    IN gctCONST_STRING Message,
+    ...
+    );
+#define gcmPRINT                gcoOS_Print
+#define gcmkPRINT               gckOS_Print
+
+/*******************************************************************************
+**
+**  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
+    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
+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
+
+/*******************************************************************************
+**
+**  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
+    );
+
+/*******************************************************************************
+**
+**  gcmBREAK
+**
+**      Break into the debugger.  In retail mode this macro does nothing.
+**
+**  ARGUMENTS:
+**
+**      None.
+*/
+
+void
+gcoOS_DebugBreak(
+    void
+    );
+
+void
+gckOS_DebugBreak(
+    void
+    );
+
+#if gcdDEBUG
+#   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 gcdDEBUG
+#   define _gcmASSERT(prefix, exp) \
+        do \
+        { \
+            if (!(exp)) \
+            { \
+                prefix##TRACE(gcvLEVEL_ERROR, \
+                              #prefix "ASSERT at %s(%d) in " __FILE__, \
+                              __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 gcdDEBUG
+#   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 gcdDEBUG
+#   define gcmVERIFY_OK(func) \
+        do \
+        { \
+            gceSTATUS verifyStatus = func; \
+            gcoOS_Verify(verifyStatus); \
+            gcmASSERT(verifyStatus == gcvSTATUS_OK); \
+        } \
+        while (gcvFALSE)
+#   define gcmkVERIFY_OK(func) \
+        do \
+        { \
+            gceSTATUS verifyStatus = func; \
+            gckOS_Verify(verifyStatus); \
+            gcmkASSERT(verifyStatus == gcvSTATUS_OK); \
+        } \
+        while (gcvFALSE)
+#else
+#   define gcmVERIFY_OK(func)       func
+#   define gcmkVERIFY_OK(func)      func
+#endif
+
+/*******************************************************************************
+**
+**  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##TRACE(gcvLEVEL_ERROR, \
+            #prefix "ERR_BREAK: status=%d @ %s(%d) in " __FILE__, \
+            status, __FUNCTION__, __LINE__); \
+        break; \
+    } \
+    do { } while (gcvFALSE)
+#define gcmERR_BREAK(func)          _gcmERR_BREAK(gcm, func)
+#define gcmkERR_BREAK(func)         _gcmERR_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##TRACE(gcvLEVEL_ERROR, \
+            #prefix "ERR_RETURN: status=%d @ %s(%d) in " __FILE__, \
+            status, __FUNCTION__, __LINE__); \
+        return status; \
+    } \
+    do { } while (gcvFALSE)
+#define gcmERR_RETURN(func)         _gcmERR_RETURN(gcm, func)
+#define gcmkERR_RETURN(func)        _gcmERR_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##TRACE(gcvLEVEL_ERROR, \
+                #prefix "ONERROR: status=%d @ %s(%d) in " __FILE__, \
+                status, __FUNCTION__, __LINE__); \
+            goto OnError; \
+        } \
+    } \
+    while (gcvFALSE)
+#define gcmONERROR(func)            _gcmONERROR(gcm, func)
+#define gcmkONERROR(func)           _gcmONERROR(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) \
+    { \
+        status = gcvSTATUS_MEMORY_UNLOCKED; \
+        break; \
+    } \
+    do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+**  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(%d) in " __FILE__, \
+                last, __FUNCTION__, __LINE__); \
+            status = last; \
+        } \
+    } \
+    while (gcvFALSE)
+#define gcmCHECK_STATUS(func)       _gcmCHECK_STATUS(gcm, func)
+#define gcmkCHECK_STATUS(func)      _gcmCHECK_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.
+*/
+#ifndef EGL_API_ANDROID
+#   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)
+#else
+#   define gcmVERIFY_ARGUMENT(arg)
+#   define gcmkVERIFY_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.
+*/
+#ifndef EGL_API_ANDROID
+#   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)
+#else
+#   define gcmVERIFY_ARGUMENT_RETURN(arg, value)
+#   define gcmkVERIFY_ARGUMENT_RETURN(arg, value)
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_base_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/inc/gc_hal_compiler.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal_compiler.h
new file mode 100644 (file)
index 0000000..6bc96b2
--- /dev/null
@@ -0,0 +1,1841 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_
+
+#include "gc_hal_types.h"
+#include "gc_hal_engine.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+|******************************* 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_OPCODE;
+
+typedef enum _gcSL_FORMAT
+{
+       gcSL_FLOAT,                                                     /* 0 */
+       gcSL_INTEGER,                                           /* 1 */
+       gcSL_BOOLEAN,                                           /* 2 */
+}
+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_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;
+
+
+/******************************************************************************\
+|*********************************** SHADERS **********************************|
+\******************************************************************************/
+
+/* Shader types. */
+#define gcSHADER_TYPE_UNKNOWN                  0
+#define gcSHADER_TYPE_VERTEX                   1
+#define gcSHADER_TYPE_FRAGMENT                 2
+
+/* gcSHADER objects. */
+typedef struct _gcSHADER *                             gcSHADER;
+typedef struct _gcATTRIBUTE *                  gcATTRIBUTE;
+typedef struct _gcUNIFORM *                            gcUNIFORM;
+typedef struct _gcOUTPUT *                             gcOUTPUT;
+typedef struct _gcsFUNCTION *                  gcFUNCTION;
+typedef struct _gcsHINT *                              gcsHINT_PTR;
+typedef struct _gcSHADER_PROFILER *     gcSHADER_PROFILER;
+typedef struct _gcVARIABLE *                   gcVARIABLE;
+
+/* 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_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;
+
+/*******************************************************************************
+**                             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_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_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_GetPositionAttribute
+********************************************************************************
+**
+**     Get the gcATTRIBUTE object pointer for the attribute that defines the
+**     position.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**     OUTPUT:
+**
+**             gctUINT * Index
+**                     Pointer to a variable receiving the index of te gcATTRIBUTE object
+**                     used as a position.
+**
+**             gcATTRIBUTE * Attribute
+**                     Pointer to a variable receiving the gcATTRIBUTE object pointer.
+*/
+gceSTATUS
+gcSHADER_GetPositionAttribute(
+       IN gcSHADER Shader,
+       OUT gctUINT * Index,
+       OUT gcATTRIBUTE * Attribute
+       );
+
+/*******************************************************************************
+**                                                        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_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_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_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_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
+       );
+
+/*******************************************************************************
+**                                                gcSHADER_AddSourceConstant
+********************************************************************************
+**
+**     Add a constant floating pointer value as a source operand to a gcSHADER
+**     object.
+**
+**     INPUT:
+**
+**             gcSHADER Shader
+**                     Pointer to a gcSHADER object.
+**
+**             gctFLOAT Constant
+**                     Floating pointer constant.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceConstant(
+       IN gcSHADER Shader,
+       IN gctFLOAT Constant
+       );
+
+/*******************************************************************************
+**                                                               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
+       );
+
+gceSTATUS
+gcSHADER_AddFunction(
+       IN gcSHADER Shader,
+       IN gctCONST_STRING Name,
+       OUT gcFUNCTION * Function
+       );
+
+gceSTATUS
+gcSHADER_BeginFunction(
+       IN gcSHADER Shader,
+       IN gcFUNCTION Function
+       );
+
+gceSTATUS
+gcSHADER_EndFunction(
+       IN gcSHADER Shader,
+       IN gcFUNCTION Function
+       );
+
+/*******************************************************************************
+**                             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_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_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 **
+*******************************************************************************/
+
+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
+       );
+
+/*******************************************************************************
+**                              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.
+**
+**             gcePRIMITIVE PrimitiveType
+**                     Primitive type to be rendered.
+*/
+gceSTATUS
+gcLoadShaders(
+       IN gcoHAL Hal,
+       IN gctSIZE_T StateBufferSize,
+       IN gctPOINTER StateBuffer,
+       IN gcsHINT_PTR Hints,
+       IN gcePRIMITIVE PrimitiveType
+       );
+
+/*******************************************************************************
+**                                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 variable receiving the vertex shader object.
+**
+**             gcSHADER * FragmentShader
+**                     Pointer to a variable receiving the 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
+       );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_compiler_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/inc/gc_hal_driver.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal_driver.h
new file mode 100644 (file)
index 0000000..7943e03
--- /dev/null
@@ -0,0 +1,633 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_types.h"
+
+#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,
+}
+gceHAL_COMMAND_CODES;
+
+/******************************************************************************\
+****************************** Interface Structure *****************************
+\******************************************************************************/
+
+#define gcdMAX_PROFILE_FILE_NAME    128
+
+typedef struct _gcsHAL_INTERFACE
+{
+    /* Command code. */
+    gceHAL_COMMAND_CODES        command;
+
+    /* 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;
+
+            /* 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;
+        }
+        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;
+
+            /* 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 struct _gcsQUEUE *       queue;
+        }
+        Event;
+
+        /* gcvHAL_COMMIT */
+        struct _gcsHAL_COMMIT
+        {
+            /* Command buffer. */
+            IN gcoCMDBUF                commandBuffer;
+
+            /* Context buffer. */
+            IN gcoCONTEXT               contextBuffer;
+
+            /* Process handle. */
+            IN gctHANDLE                process;
+        }
+        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;
+
+            /* 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;
+
+        /* 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;
+
+        /* 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;
+
+            /* Message to print if not empty. */
+            IN gctCHAR                  message[80];
+        }
+        Debug;
+
+        struct _gcsHAL_CACHE
+        {
+            IN gctBOOL                  invalidate;
+            IN gctHANDLE                process;
+            IN gctPOINTER               logical;
+            IN gctSIZE_T                bytes;
+        }
+        Cache;
+    }
+    u;
+}
+gcsHAL_INTERFACE;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_driver_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/inc/gc_hal_dump.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal_dump.h
new file mode 100644 (file)
index 0000000..2264b60
--- /dev/null
@@ -0,0 +1,90 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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/staging/rk29/vivante/hal/inc/gc_hal_engine.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal_engine.h
new file mode 100644 (file)
index 0000000..fc43f66
--- /dev/null
@@ -0,0 +1,1548 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_
+
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+
+#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;
+
+/******************************************************************************\
+********************************* 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,
+}
+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,
+}
+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_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 */
+#if 1
+       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
+               );
+#endif
+
+/* Resample surface. */
+gceSTATUS
+gcoSURF_Resample(
+       IN gcoSURF SrcSurface,
+       IN gcoSURF DestSurface
+       );
+
+/* Resolve surface. */
+gceSTATUS
+gcoSURF_Resolve(
+       IN gcoSURF SrcSurface,
+       IN gcoSURF DestSurface
+       );
+
+/* 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
+       );
+
+/******************************************************************************\
+******************************** 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 depth-only mode. */
+gceSTATUS
+gco3D_SetDepthOnly(
+       IN gco3D Engine,
+       IN gctBOOL Enable
+       );
+
+/* 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
+       );
+
+/* 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
+       );
+
+/* 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
+       );
+
+/* 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
+       );
+/*----------------------------------------------------------------------------*/
+/*-------------------------- 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
+       );
+
+
+/******************************************************************************\
+******************************* 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;
+
+/* 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_SetAddressingMode(
+       IN gcoTEXTURE Texture,
+       IN gceTEXTURE_WHICH Which,
+       IN gceTEXTURE_ADDRESSING Mode
+       );
+
+gceSTATUS
+gcoTEXTURE_SetBorderColor(
+       IN gcoTEXTURE Texture,
+       IN gctUINT Red,
+       IN gctUINT Green,
+       IN gctUINT Blue,
+       IN gctUINT Alpha
+       );
+
+gceSTATUS
+gcoTEXTURE_SetBorderColorX(
+       IN gcoTEXTURE Texture,
+       IN gctFIXED_POINT Red,
+       IN gctFIXED_POINT Green,
+       IN gctFIXED_POINT Blue,
+       IN gctFIXED_POINT Alpha
+       );
+
+gceSTATUS
+gcoTEXTURE_SetBorderColorF(
+       IN gcoTEXTURE Texture,
+       IN gctFLOAT Red,
+       IN gctFLOAT Green,
+       IN gctFLOAT Blue,
+       IN gctFLOAT Alpha
+       );
+
+gceSTATUS
+gcoTEXTURE_SetMinFilter(
+       IN gcoTEXTURE Texture,
+       IN gceTEXTURE_FILTER Filter
+       );
+
+gceSTATUS
+gcoTEXTURE_SetMagFilter(
+       IN gcoTEXTURE Texture,
+       IN gceTEXTURE_FILTER Filter
+       );
+
+gceSTATUS
+gcoTEXTURE_SetMipFilter(
+       IN gcoTEXTURE Texture,
+       IN gceTEXTURE_FILTER Filter
+       );
+
+gceSTATUS
+gcoTEXTURE_SetLODBiasX(
+       IN gcoTEXTURE Texture,
+       IN gctFIXED_POINT Bias
+       );
+
+gceSTATUS
+gcoTEXTURE_SetLODBiasF(
+       IN gcoTEXTURE Texture,
+       IN gctFLOAT Bias
+       );
+
+gceSTATUS
+gcoTEXTURE_SetLODMinX(
+       IN gcoTEXTURE Texture,
+       IN gctFIXED_POINT LevelOfDetail
+       );
+
+gceSTATUS
+gcoTEXTURE_SetLODMinF(
+       IN gcoTEXTURE Texture,
+       IN gctFLOAT LevelOfDetail
+       );
+
+gceSTATUS
+gcoTEXTURE_SetLODMaxX(
+       IN gcoTEXTURE Texture,
+       IN gctFIXED_POINT LevelOfDetail
+       );
+
+gceSTATUS
+gcoTEXTURE_SetLODMaxF(
+       IN gcoTEXTURE Texture,
+       IN gctFLOAT LevelOfDetail
+       );
+
+gceSTATUS
+gcoTEXTURE_Bind(
+       IN gcoTEXTURE Texture,
+       IN gctINT Sampler
+       );
+
+gceSTATUS
+gcoTEXTURE_Disable(
+       IN gcoHAL Hal,
+       IN gctINT Sampler
+       );
+
+gceSTATUS
+gcoTEXTURE_Flush(
+       IN gcoTEXTURE Texture
+       );
+
+gceSTATUS
+gcoTEXTURE_QueryCaps(
+       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
+       );
+
+/******************************************************************************\
+******************************* 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,
+}
+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
+       );
+
+/******************************************************************************\
+******************************** 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
+       );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_engine_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/inc/gc_hal_enum.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal_enum.h
new file mode 100644 (file)
index 0000000..18cfd70
--- /dev/null
@@ -0,0 +1,550 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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,
+    gcv400  = 0x0400,
+    gcv410  = 0x0410,
+    gcv450  = 0x0450,
+    gcv500  = 0x0500,
+    gcv530  = 0x0530,
+    gcv600  = 0x0600,
+    gcv700  = 0x0700,
+    gcv800  = 0x0800,
+    gcv860  = 0x0860,
+    gcv1000 = 0x1000,
+}
+gceCHIPMODEL;
+
+/* Chip features. */
+typedef enum _gceFEATURE
+{
+    gcvFEATURE_PIPE_2D,
+    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,
+}
+gceFEATURE;
+
+/* Chip Power Status. */
+typedef enum _gceCHIPPOWERSTATE
+{
+    gcvPOWER_ON,
+    gcvPOWER_OFF,
+    gcvPOWER_IDLE,
+    gcvPOWER_SUSPEND,
+    gcvPOWER_SUSPEND_ATPOWERON,
+    gcvPOWER_OFF_ATPOWERON,
+    gcvPOWER_IDLE_BROADCAST,
+    gcvPOWER_SUSPEND_BROADCAST,
+    gcvPOWER_OFF_BROADCAST,
+    gcvPOWER_OFF_RECOVERY,
+}
+gceCHIPPOWERSTATE;
+
+/* Surface types. */
+typedef enum _gceSURF_TYPE
+{
+    gcvSURF_TYPE_UNKNOWN,
+    gcvSURF_INDEX,
+    gcvSURF_VERTEX,
+    gcvSURF_TEXTURE,
+    gcvSURF_RENDER_TARGET,
+    gcvSURF_DEPTH,
+    gcvSURF_BITMAP,
+    gcvSURF_TILE_STATUS,
+    gcvSURF_MASK,
+    gcvSURF_SCISSOR,
+    gcvSURF_HIERARCHICAL_DEPTH,
+    gcvSURF_NUM_TYPES, /* Make sure this is the last one! */
+
+    /* Combinations. */
+    gcvSURF_NO_TILE_STATUS = 0x100,
+    gcvSURF_RENDER_TARGET_NO_TILE_STATUS = gcvSURF_RENDER_TARGET
+                                         | gcvSURF_NO_TILE_STATUS,
+    gcvSURF_DEPTH_NO_TILE_STATUS = gcvSURF_DEPTH
+                                 | gcvSURF_NO_TILE_STATUS,
+}
+gceSURF_TYPE;
+
+typedef enum _gceSURF_COLOR_TYPE
+{
+    gcvSURF_COLOR_UNKNOWN,
+    gcvSURF_COLOR_LINEAR        = 0x01,
+    gcvSURF_COLOR_ALPHA_PRE     = 0x02,
+}
+gceSURF_COLOR_TYPE;
+
+/* Rotation. */
+typedef enum _gceSURF_ROTATION
+{
+    gcvSURF_0_DEGREE,
+    gcvSURF_90_DEGREE,
+    gcvSURF_180_DEGREE,
+    gcvSURF_270_DEGREE
+}
+gceSURF_ROTATION;
+
+/* Surface formats. */
+typedef enum _gceSURF_FORMAT
+{
+    /* Unknown format. */
+    gcvSURF_UNKNOWN,
+
+    /* 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_R8G8B8X8,
+    gcvSURF_R5G5B5X1,
+    gcvSURF_R4G4B4X4,
+
+    /* BGR formats. */
+    gcvSURF_A4B4G4R4            = 300,
+    gcvSURF_A1B5G5R5,
+    gcvSURF_B5G6R5,
+    gcvSURF_B8G8R8,
+    gcvSURF_X8B8G8R8,
+    gcvSURF_A8B8G8R8,
+    gcvSURF_A2B10G10R10,
+    gcvSURF_A16B16G16R16,
+    gcvSURF_G16R16,
+    gcvSURF_B4G4R4A4,
+    gcvSURF_B5G5R5A1,
+    gcvSURF_B8G8R8X8,
+    gcvSURF_B8G8R8A8,
+    gcvSURF_X4B4G4R4,
+    gcvSURF_X1B5G5R5,
+    gcvSURF_B4G4R4X4,
+    gcvSURF_B5G5R5X1,
+
+    /* 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,
+
+    /* Floating point formats. */
+    gcvSURF_R16F                = 1100,
+    gcvSURF_G16R16F,
+    gcvSURF_A16B16G16R16F,
+    gcvSURF_R32F,
+    gcvSURF_G32R32F,
+    gcvSURF_A32B32G32R32F,
+
+#if 0
+    /* FIXME: remove HDR support for now. */
+    /* HDR formats. */
+    gcvSURF_HDR7E3              = 1200,
+    gcvSURF_HDR6E4,
+    gcvSURF_HDR5E5,
+    gcvSURF_HDR6E5,
+#endif
+}
+gceSURF_FORMAT;
+
+/* Pixel swizzle modes. */
+typedef enum _gceSURF_SWIZZLE
+{
+    gcvSURF_NOSWIZZLE,
+    gcvSURF_ARGB,
+    gcvSURF_ABGR,
+    gcvSURF_RGBA,
+    gcvSURF_BGRA
+}
+gceSURF_SWIZZLE;
+
+/* Transparency modes. */
+typedef enum _gceSURF_TRANSPARENCY
+{
+    /* Valid only for PE 1.0 */
+    gcvSURF_OPAQUE,
+    gcvSURF_SOURCE_MATCH,
+    gcvSURF_SOURCE_MASK,
+    gcvSURF_PATTERN_MASK,
+}
+gceSURF_TRANSPARENCY;
+
+/* Transparency modes. */
+typedef enum _gce2D_TRANSPARENCY
+{
+    /* Valid only for PE 2.0 */
+    gcv2D_OPAQUE,
+    gcv2D_KEYED,
+    gcv2D_MASKED
+}
+gce2D_TRANSPARENCY;
+
+/* Mono packing modes. */
+typedef enum _gceSURF_MONOPACK
+{
+    gcvSURF_PACKED8,
+    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           */
+    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,
+    gcvSURF_PIXEL_ALPHA_INVERSED
+}
+gceSURF_PIXEL_ALPHA_MODE;
+
+/* Global alpha modes. */
+typedef enum _gceSURF_GLOBAL_ALPHA_MODE
+{
+    gcvSURF_GLOBAL_ALPHA_OFF,
+    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,
+    gcvSURF_COLOR_MULTIPLY
+}
+gceSURF_PIXEL_COLOR_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gce2D_PIXEL_COLOR_MULTIPLY_MODE
+{
+    gcv2D_COLOR_MULTIPLY_DISABLE,
+    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,
+    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,
+    gcvSURF_BLEND_ONE,
+    gcvSURF_BLEND_STRAIGHT,
+    gcvSURF_BLEND_INVERSED,
+    gcvSURF_BLEND_COLOR,
+    gcvSURF_BLEND_COLOR_INVERSED,
+    gcvSURF_BLEND_SRC_ALPHA_SATURATED
+}
+gceSURF_BLEND_FACTOR_MODE;
+
+/* Alpha blending porter duff rules. */
+typedef enum _gce2D_PORTER_DUFF_RULE
+{
+    gcvPD_CLEAR,
+    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,
+    gcv2D_YUV_709
+}
+gce2D_YUV_COLOR_MODE;
+
+/* 2D Rotation and flipping. */
+typedef enum _gce2D_ORIENTATION
+{
+    gcv2D_0_DEGREE,
+    gcv2D_90_DEGREE,
+    gcv2D_180_DEGREE,
+    gcv2D_270_DEGREE,
+    gcv2D_X_FLIP,
+    gcv2D_Y_FLIP
+}
+gce2D_ORIENTATION;
+
+typedef enum _gce2D_COMMAND
+{
+    gcv2D_CLEAR,
+    gcv2D_LINE,
+    gcv2D_BLT,
+    gcv2D_STRETCH,
+    gcv2D_HOR_FILTER,
+    gcv2D_VER_FILTER,
+}
+gce2D_COMMAND;
+
+/* 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,
+    gcvCOLOR_FROM_CONSTANT_COLOR,
+    gcvCOLOR_FROM_PRIMARY_COLOR,
+    gcvCOLOR_FROM_PREVIOUS_COLOR
+}
+gceTEXTURE_SOURCE;
+
+/* Texture source channels. */
+typedef enum _gceTEXTURE_CHANNEL
+{
+    gcvFROM_COLOR,
+    gcvFROM_ONE_MINUS_COLOR,
+    gcvFROM_ALPHA,
+    gcvFROM_ONE_MINUS_ALPHA
+}
+gceTEXTURE_CHANNEL;
+
+/* Filter types. */
+typedef enum _gceFILTER_TYPE
+{
+    gcvFILTER_SYNC,
+    gcvFILTER_BLUR,
+    gcvFILTER_USER
+}
+gceFILTER_TYPE;
+
+/* Filter pass types. */
+typedef enum _gceFILTER_PASS_TYPE
+{
+    gcvFILTER_HOR_PASS,
+    gcvFILTER_VER_PASS
+}
+gceFILTER_PASS_TYPE;
+
+/* Endian hints. */
+typedef enum _gceENDIAN_HINT
+{
+    gcvENDIAN_NO_SWAP           = 0,
+    gcvENDIAN_SWAP_WORD,
+    gcvENDIAN_SWAP_DWORD
+}
+gceENDIAN_HINT;
+
+/* Endian hints. */
+typedef enum _gceTILING
+{
+    gcvLINEAR,
+    gcvTILED,
+    gcvSUPERTILED
+}
+gceTILING;
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoCONTEXT *        gcoCONTEXT;
+typedef struct _gcoCMDBUF *         gcoCMDBUF;
+typedef struct _gcoQUEUE *          gcoQUEUE;
+typedef struct _gcsHAL_INTERFACE *  gcsHAL_INTERFACE_PTR;
+typedef struct gcs2D_PROFILE *      gcs2D_PROFILE_PTR;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_enum_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/inc/gc_hal_mem.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal_mem.h
new file mode 100644 (file)
index 0000000..9b7d28c
--- /dev/null
@@ -0,0 +1,471 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_
+
+#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; \
+       gcmERR_RETURN(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+       gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type))); \
+       return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type *                                  Pointer \
+       ) \
+{ \
+       return(gcfMEM_FSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName##List( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type *                                  FirstPointer, \
+       Type *                                  LastPointer \
+       ) \
+{ \
+       return(gcfMEM_FSMemPoolFreeAList(MemPool, (gctPOINTER) FirstPointer, (gctPOINTER) LastPointer)); \
+}
+
+#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Size \
+       ) \
+{ \
+       return(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+ Prefix##_CAllocate##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Size \
+       ) \
+{ \
+       gceSTATUS                               status; \
+       gcmERR_RETURN(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
+       gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, size)); \
+       return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type *                                  Pointer \
+       ) \
+{ \
+       return(gcfMEM_VSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer)); \
+}
+
+#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+       gcsMEM_AFS_MEM_POOL             MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Count \
+       ) \
+{ \
+       return(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+       gcsMEM_AFS_MEM_POOL             MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Count \
+       ) \
+{ \
+       gceSTATUS                               status; \
+       gcmERR_RETURN(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
+       gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type))); \
+       return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+       gcsMEM_AFS_MEM_POOL             MemPool, \
+       Type *                                  Pointer \
+       ) \
+{ \
+       return(gcfMEM_AFSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer)); \
+}
+
+#else
+
+#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type **                                 Pointer \
+       ) \
+{ \
+       return(gcoOS_Allocate(MemPool, \
+                                                       gcmSIZEOF(Type), \
+                                                       (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type **                                 Pointer \
+       ) \
+{ \
+       gceSTATUS                               status; \
+       gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+                                                       gcmSIZEOF(Type), \
+                                                       (gctPOINTER *) Pointer)); \
+       gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type))); \
+       return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+       gcsMEM_FS_MEM_POOL              MemPool, \
+       Type *                                  Pointer \
+       ) \
+{ \
+       return(gcoOS_Free(MemPool, Pointer)); \
+}
+
+#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+       gcsMEM_VS_MEM_POOL              MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Size \
+       ) \
+{ \
+       return(gcoOS_Allocate(MemPool, \
+                                                       Size, \
+                                                       (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+       gcsMEM_VS_MEM_POOL              MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Size \
+       ) \
+{ \
+       gceSTATUS                               status; \
+       gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+                                                       Size, \
+                                                       (gctPOINTER *) Pointer)); \
+       gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Size)); \
+       return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+       gcsMEM_VS_MEM_POOL              MemPool, \
+       Type *                                  Pointer \
+       ) \
+{ \
+       return(gcoOS_Free(MemPool, Pointer)); \
+}
+
+#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+       gcsMEM_AFS_MEM_POOL             MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Count \
+       ) \
+{ \
+       return(gcoOS_Allocate(MemPool, \
+                                                       Count * gcmSIZEOF(Type), \
+                                                       (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+       gcsMEM_AFS_MEM_POOL             MemPool, \
+       Type **                                 Pointer, \
+       gctUINT                                 Count \
+       ) \
+{ \
+       gceSTATUS                               status; \
+       gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+                                                       Count * gcmSIZEOF(Type), \
+                                                       (gctPOINTER *) Pointer)); \
+       gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type))); \
+       return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+       gcsMEM_AFS_MEM_POOL             MemPool, \
+       Type *                                  Pointer \
+       ) \
+{ \
+       return(gcoOS_Free(MemPool, Pointer)); \
+}
+#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 /* __gc_hal_mem_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/inc/gc_hal_options.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal_options.h
new file mode 100644 (file)
index 0000000..b6f830f
--- /dev/null
@@ -0,0 +1,259 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_
+
+/*
+    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_SHADER_SYMBOL_TABLE
+
+    This define enables the symbol table in shader object.
+*/
+#define USE_SHADER_SYMBOL_TABLE     1
+
+/*
+    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.
+*/
+#define PROFILE_HAL_COUNTERS        1
+
+/*
+    PROFILE_HW_COUNTERS
+
+    This define enables HW counter profiling support.
+*/
+#define PROFILE_HW_COUNTERS         1
+
+/*
+    PROFILE_SHADER_COUNTERS
+
+    This define enables SHADER counter profiling support.
+*/
+#define PROFILE_SHADER_COUNTERS     1
+
+/*
+    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.
+*/
+#define gcdDUMP                     0
+
+/*
+    gcdDUMP_API
+
+        When set to 1, a high level dump of the EGL and GL/VG APs's are
+        captured.
+*/
+#define gcdDUMP_API                 0
+
+/*
+    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.
+*/
+#define gcdDUMP_IN_KERNEL           0
+
+/*
+    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.
+*/
+#define gcdDUMP_COMMAND             0
+
+/*
+    gcdNULL_DRIVER
+*/
+#define gcdNULL_DRIVER              0
+
+/*
+    gcdENABLE_TIMEOUT_DETECTION
+
+    Enable timeout detection.
+*/
+#define gcdENABLE_TIMEOUT_DETECTION 0
+
+/*
+    gcdCMD_BUFFERS
+
+    Number of command buffers to use per client.  Each command buffer is 32kB in
+    size.
+*/
+#define gcdCMD_BUFFERS              2
+
+/*
+    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 be stabalize.
+*/
+#define gcdPOWER_CONTROL_DELAY      1
+
+/*
+    gcdMMU_SIZE
+
+    Size of the MMU page table in bytes.  Each 4 bytes can hold 4kB worth of
+    virtual data.
+*/
+#define gcdMMU_SIZE                 (128 << 10)
+
+/*
+    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.
+*/
+#define gcdSECURE_USER                      0
+
+/*
+    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.
+*/
+#define gcdSECURE_CACHE_SLOTS               64
+
+/*
+    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.
+*/
+#define gcdHEAP_SIZE                (64 << 10)
+
+/*
+    gcdNO_POWER_MANAGEMENT
+
+    This define disables the power management code.
+*/
+#ifndef gcdNO_POWER_MANAGEMENT
+#   define gcdNO_POWER_MANAGEMENT           0
+#endif
+
+/*
+    gcdFPGA_BUILD
+
+    This define enables work arounds for FPGA images.
+*/
+#if !defined(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.
+*/
+#if !defined(gcdGPU_TIMEOUT)
+#   define gcdGPU_TIMEOUT                   0
+#endif
+
+#endif /* __gc_hal_options_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/inc/gc_hal_profiler.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal_profiler.h
new file mode 100644 (file)
index 0000000..8fe1f55
--- /dev/null
@@ -0,0 +1,232 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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(Hal, Enum, Value)        gcoPROFILER_Count(Hal, Enum, Value)
+#else
+#define gcmPROFILE_GC(Hal, Enum, Value) do { } while (gcvFALSE)
+#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
+{
+    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,
+    IN gctFILE File
+    );
+
+/* Destroy the gcProfiler. */
+gceSTATUS
+gcoPROFILER_Destroy(
+    IN gcoHAL Hal
+    );
+
+/* Call to signal end of frame. */
+gceSTATUS
+gcoPROFILER_EndFrame(
+    IN gcoHAL Hal
+    );
+
+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/staging/rk29/vivante/hal/inc/gc_hal_raster.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal_raster.h
new file mode 100644 (file)
index 0000000..64f897f
--- /dev/null
@@ -0,0 +1,781 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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
+       );
+
+/******************************************************************************\
+********************************** 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
+       );
+
+/* 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
+       );
+
+/* 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
+       );
+
+/* 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
+       );
+
+/* 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. */
+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
+       );
+
+/* 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
+       );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_raster_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/inc/gc_hal_types.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal_types.h
new file mode 100644 (file)
index 0000000..d572d5f
--- /dev/null
@@ -0,0 +1,544 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_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)
+#      define gcdHAS_ELLIPSES          0               /* Windows CE doesn't have it. */
+#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
+
+#ifndef gcdDEBUG
+#      if (defined(DBG) && DBG) || defined(DEBUG) || defined(_DEBUG)
+#              define gcdDEBUG                 1
+#      else
+#              define gcdDEBUG                 0
+#      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)
+
+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 *                                 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;
+
+/* 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)
+
+/******************************************************************************\
+******************************* Fixed Point Math *******************************
+\******************************************************************************/
+
+#define gcmXMultiply(x1, x2) \
+       (gctFIXED_POINT) (((gctINT64) (x1) * (x2)) >> 16)
+
+#define gcmXDivide(x1, x2) \
+       (gctFIXED_POINT) ((((gctINT64) (x1)) << 16) / (x2))
+
+#define gcmXMultiplyDivide(x1, x2, x3) \
+       (gctFIXED_POINT) ((gctINT64) (x1) * (x2) / (x3))
+
+/* 2D Engine profile. */
+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;
+};
+
+
+/* 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) : ' ')
+
+#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_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,
+
+       /* 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) \
+)
+
+/*******************************************************************************
+**
+**     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) \
+)
+
+/*******************************************************************************
+**
+**     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) \
+       ) \
+)
+
+/******************************************************************************\
+******************************** 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.
+*/
+#define gcmINT2PTR(i) \
+( \
+       (gctPOINTER) (i) \
+)
+
+/*******************************************************************************
+**
+**     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)) \
+)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_types_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel.c b/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel.c
new file mode 100644 (file)
index 0000000..0e5d0bb
--- /dev/null
@@ -0,0 +1,1237 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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
+
+/******************************************************************************\
+******************************* 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.
+*/
+
+#ifdef ANDROID
+#define DEFAULT_PROFILE_FILE_NAME   "/sdcard/vprofiler.xml"
+#else
+#define DEFAULT_PROFILE_FILE_NAME   "vprofiler.xml"
+#endif
+
+gceSTATUS
+gckKERNEL_Construct(
+    IN gckOS Os,
+    IN gctPOINTER Context,
+    OUT gckKERNEL * Kernel
+    )
+{
+    gckKERNEL kernel = gcvNULL;
+    gceSTATUS status;
+
+    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),
+                       (gctPOINTER *) &kernel));
+
+    /* Zero the object pointers. */
+    kernel->hardware = gcvNULL;
+    kernel->command  = gcvNULL;
+    kernel->event    = gcvNULL;
+    kernel->mmu      = gcvNULL;
+
+    /* Initialize the gckKERNEL object. */
+    kernel->object.type = gcvOBJ_KERNEL;
+    kernel->os          = Os;
+
+    /* Save context. */
+    kernel->context = Context;
+
+    /* Construct atom holding number of clients. */
+    kernel->atomClients = gcvNULL;
+    gcmkONERROR(gckOS_AtomConstruct(Os, &kernel->atomClients));
+
+#if gcdSECURE_USER
+    kernel->cacheSlots     = 0;
+    kernel->cacheTimeStamp = 0;
+#endif
+
+    /* Construct the gckHARDWARE object. */
+    gcmkONERROR(
+        gckHARDWARE_Construct(Os, &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->event));
+
+    /* 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 (kernel->event != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckEVENT_Destroy(kernel->event));
+        }
+
+        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));
+        }
+
+        gcmkVERIFY_OK(gckOS_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
+    )
+{
+    gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    /* Destroy the gckMMU object. */
+    gcmkVERIFY_OK(gckMMU_Destroy(Kernel->mmu));
+
+    /* Destroy the gckEVENT object. */
+    gcmkVERIFY_OK(gckEVENT_Destroy(Kernel->event));
+
+    /* Destroy the gckCOMMNAND object. */
+    gcmkVERIFY_OK(gckCOMMAND_Destroy(Kernel->command));
+
+    /* 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(gckOS_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,
+#ifdef __QNXNTO__
+    IN gctHANDLE Handle,
+#endif
+    OUT gcuVIDMEM_NODE_PTR * Node
+    )
+{
+    gcePOOL pool;
+    gceSTATUS status;
+    gckVIDMEM videoMemory;
+
+    gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+
+    /* 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)
+        {
+            gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
+        }
+
+        if (pool == gcvPOOL_VIRTUAL)
+        {
+            /* Create a gcuVIDMEM_NODE for virtual memory. */
+#ifdef __QNXNTO__
+            gcmkERR_BREAK(
+                gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Handle, Node));
+#else
+            gcmkERR_BREAK(
+                gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Node));
+#endif
+
+            /* Success. */
+            break;
+        }
+        else if (pool == gcvPOOL_CONTIGUOUS)
+        {
+            /* Create a gcuVIDMEM_NODE for contiguous memory. */
+#ifdef __QNXNTO__
+            status = gckVIDMEM_ConstructVirtual(Kernel, gcvTRUE, Bytes, Handle, Node);
+#else
+            status = gckVIDMEM_ConstructVirtual(Kernel, gcvTRUE, Bytes, Node);
+#endif
+            if (gcmIS_SUCCESS(status))
+            {
+                /* Memory allocated. */
+                break;
+            }
+        }
+        else
+        {
+            /* Get pointer to gckVIDMEM object for pool. */
+            status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
+
+            if (gcmIS_SUCCESS(status))
+            {
+                /* Allocate memory. */
+                status = gckVIDMEM_AllocateLinear(videoMemory,
+                                                  Bytes,
+                                                  Alignment,
+                                                  Type,
+#ifdef __QNXNTO__
+                                                  Handle,
+#endif
+                                                  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. */
+            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.
+**
+**      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;
+    gctUINT32 bitsPerPixel;
+    gctSIZE_T bytes;
+    gcuVIDMEM_NODE_PTR node;
+    gctBOOL locked = gcvFALSE;
+    gctPHYS_ADDR physical;
+    gctUINT32 address;
+
+    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);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+                   "Dispatching command %d", Interface->command);
+
+    /* 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));
+
+        /* 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));
+        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));
+        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));
+        break;
+
+    case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
+        /* Allocate non-paged memory. */
+#ifdef __QNXNTO__
+        if (FromUser)
+        {
+            gcmkONERROR(
+                gckOS_AllocateNonPagedMemoryShmPool(
+                Kernel->os,
+                FromUser,
+                Interface->pid,
+                Interface->handle,
+                &Interface->u.AllocateNonPagedMemory.bytes,
+                &Interface->u.AllocateNonPagedMemory.physical,
+                &Interface->u.AllocateNonPagedMemory.logical));
+            break;
+        }
+#endif
+        gcmkONERROR(
+            gckOS_AllocateNonPagedMemory(
+                Kernel->os,
+                FromUser,
+                &Interface->u.AllocateNonPagedMemory.bytes,
+                &Interface->u.AllocateNonPagedMemory.physical,
+                &Interface->u.AllocateNonPagedMemory.logical));
+        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));
+        break;
+
+    case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
+        /* Allocate contiguous memory. */
+#ifdef __QNXNTO__
+        if (FromUser)
+        {
+            gcmkONERROR(
+                gckOS_AllocateNonPagedMemoryShmPool(
+                Kernel->os,
+                FromUser,
+                Interface->pid,
+                Interface->handle,
+                &Interface->u.AllocateNonPagedMemory.bytes,
+                &Interface->u.AllocateNonPagedMemory.physical,
+                &Interface->u.AllocateNonPagedMemory.logical));
+            break;
+        }
+#endif
+        gcmkONERROR(
+            gckOS_AllocateContiguous(
+                Kernel->os,
+                FromUser,
+                &Interface->u.AllocateContiguousMemory.bytes,
+                &Interface->u.AllocateContiguousMemory.physical,
+                &Interface->u.AllocateContiguousMemory.logical));
+
+        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));
+        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. */
+#ifdef __QNXNTO__
+        gcmkONERROR(
+            _AllocateMemory(Kernel,
+                            &Interface->u.AllocateVideoMemory.pool,
+                            bytes,
+                            64,
+                            Interface->u.AllocateVideoMemory.type,
+                            Interface->handle,
+                            &Interface->u.AllocateVideoMemory.node));
+#else
+        gcmkONERROR(
+            _AllocateMemory(Kernel,
+                            &Interface->u.AllocateVideoMemory.pool,
+                            bytes,
+                            64,
+                            Interface->u.AllocateVideoMemory.type,
+                            &Interface->u.AllocateVideoMemory.node));
+#endif
+        break;
+
+    case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
+        /* Allocate memory. */
+#ifdef __QNXNTO__
+        gcmkONERROR(
+            _AllocateMemory(Kernel,
+                            &Interface->u.AllocateLinearVideoMemory.pool,
+                            Interface->u.AllocateLinearVideoMemory.bytes,
+                            Interface->u.AllocateLinearVideoMemory.alignment,
+                            Interface->u.AllocateLinearVideoMemory.type,
+                            Interface->handle,
+                            &Interface->u.AllocateLinearVideoMemory.node));
+
+        /* Set the current user pid in the node,
+         * which is used while locking memory. */
+        gcmkVERIFY_OK(gckVIDMEM_SetPID(
+                Interface->u.AllocateLinearVideoMemory.node,
+                Interface->pid));
+#else
+        gcmkONERROR(
+            _AllocateMemory(Kernel,
+                            &Interface->u.AllocateLinearVideoMemory.pool,
+                            Interface->u.AllocateLinearVideoMemory.bytes,
+                            Interface->u.AllocateLinearVideoMemory.alignment,
+                            Interface->u.AllocateLinearVideoMemory.type,
+                            &Interface->u.AllocateLinearVideoMemory.node));
+#endif
+        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,
+                                               Interface->pid,
+                                               node->VidMem.bytes));
+            node->VidMem.logical = gcvNULL;
+        }
+#endif
+        /* Free video memory. */
+        gcmkONERROR(
+            gckVIDMEM_Free(Interface->u.FreeVideoMemory.node));
+        break;
+
+    case gcvHAL_LOCK_VIDEO_MEMORY:
+        /* Lock video memory. */
+        gcmkONERROR(
+            gckVIDMEM_Lock(Interface->u.LockVideoMemory.node,
+                           &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,
+                                         Interface->pid,
+                                         node->VidMem.bytes,
+                                         &node->VidMem.logical));
+        }
+        Interface->u.LockVideoMemory.memory = node->VidMem.logical;
+#else
+            gcmkONERROR(
+                gckKERNEL_MapVideoMemory(Kernel,
+                                         FromUser,
+                                         Interface->u.LockVideoMemory.address,
+                                         &Interface->u.LockVideoMemory.memory));
+#endif
+
+#ifdef __QNXNTO__
+            /* Add more information to node, which is used while unmapping. */
+            gcmkVERIFY_OK(gckVIDMEM_SetPID(
+                    Interface->u.LockVideoMemory.node,
+                    Interface->pid));
+#endif
+        }
+
+        else
+        {
+            /* Copy logical memory for virtual memory. */
+            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;
+
+        /* Unlock video memory. */
+        gcmkONERROR(
+            gckVIDMEM_Unlock(node,
+                             Interface->u.UnlockVideoMemory.type,
+                             &Interface->u.UnlockVideoMemory.asynchroneous));
+        break;
+
+    case gcvHAL_EVENT_COMMIT:
+        /* Commit an event queue. */
+        gcmkONERROR(
+            gckEVENT_Commit(Kernel->event,
+                            Interface->u.Event.queue));
+        break;
+
+    case gcvHAL_COMMIT:
+        /* Commit a command and context buffer. */
+        gcmkONERROR(
+            gckCOMMAND_Commit(Kernel->command,
+                              Interface->u.Commit.commandBuffer,
+                              Interface->u.Commit.contextBuffer,
+                              Interface->u.Commit.process));
+        break;
+
+    case gcvHAL_STALL:
+        /* Stall the command queue. */
+        gcmkONERROR(gckCOMMAND_Stall(Kernel->command));
+        break;
+
+    case gcvHAL_MAP_USER_MEMORY:
+        /* Map user memory to DMA. */
+        gcmkONERROR(
+            gckOS_MapUserMemory(Kernel->os,
+                                Interface->u.MapUserMemory.memory,
+                                Interface->u.MapUserMemory.size,
+                                &Interface->u.MapUserMemory.info,
+                                &Interface->u.MapUserMemory.address));
+        break;
+
+    case gcvHAL_UNMAP_USER_MEMORY:
+        address = Interface->u.MapUserMemory.address;
+
+        /* Unmap user memory. */
+        gcmkONERROR(
+            gckOS_UnmapUserMemory(Kernel->os,
+                                  Interface->u.UnmapUserMemory.memory,
+                                  Interface->u.UnmapUserMemory.size,
+                                  Interface->u.UnmapUserMemory.info,
+                                  address));
+        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));
+            break;
+
+        case gcvUSER_SIGNAL_DESTROY:
+            /* Destroy the signal. */
+            gcmkONERROR(
+                gckOS_DestroyUserSignal(Kernel->os,
+                                        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;
+
+        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
+        /* Read a register. */
+        gcmkONERROR(
+            gckOS_ReadRegister(Kernel->os,
+                               Interface->u.ReadRegisterData.address,
+                               &Interface->u.ReadRegisterData.data));
+#else
+        /* No access from user land to read registers. */
+        Interface->u.ReadRegisterData.data = 0;
+        status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+        break;
+
+    case gcvHAL_WRITE_REGISTER:
+#if gcdREGISTER_ACCESS_FROM_USER
+        /* Write a register. */
+        gcmkONERROR(
+            gckOS_WriteRegister(Kernel->os,
+                                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. */
+            gcmkPRINT(Interface->u.Debug.message);
+        }
+        status = gcvSTATUS_OK;
+        break;
+
+    case gcvHAL_CACHE:
+        if (Interface->u.Cache.invalidate)
+        {
+            /* Flush and invalidate the cache. */
+            status = gckOS_CacheInvalidate(Kernel->os,
+                                           Interface->u.Cache.process,
+                                           Interface->u.Cache.logical,
+                                           Interface->u.Cache.bytes);
+        }
+        else
+        {
+            /* Flush the cache. */
+            status = gckOS_CacheFlush(Kernel->os,
+                                      Interface->u.Cache.process,
+                                      Interface->u.Cache.logical,
+                                      Interface->u.Cache.bytes);
+        }
+        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(Interface->u.LockVideoMemory.node,
+                                 gcvSURF_TYPE_UNKNOWN,
+                                 gcvNULL));
+        }
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckKERNEL_AttachProcess(
+    IN gckKERNEL Kernel,
+    IN gctBOOL Attach
+    )
+{
+    gceSTATUS status;
+    gctINT32 old;
+
+    gcmkHEADER_ARG("Kernel=0x%x Attach=%d", Kernel, Attach);
+
+    /* 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)
+        {
+            gcmkONERROR(gckOS_Broadcast(Kernel->os,
+                                        Kernel->hardware,
+                                        gcvBROADCAST_FIRST_PROCESS));
+        }
+    }
+
+    else
+    {
+        /* Decrement the number of clients attached. */
+        gcmkONERROR(
+            gckOS_AtomDecrement(Kernel->os, Kernel->atomClients, &old));
+
+        if (old == 1)
+        {
+            /* Last client detached, switch to SUSPEND power state. */
+            gcmkONERROR(gckOS_Broadcast(Kernel->os,
+                                        Kernel->hardware,
+                                        gcvBROADCAST_LAST_PROCESS));
+
+            /* Flush the debug cache. */
+            gcmkPRINT("$$FLUSH$$");
+        }
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+#if gcdSECURE_USER
+gceSTATUS
+gckKERNEL_MapLogicalToPhysical(
+    IN gckKERNEL Kernel,
+    IN gctHANDLE Process,
+    IN OUT gctPOINTER * Data
+    )
+{
+    gctUINT i, oldest;
+    gceSTATUS status;
+    gctUINT32 baseAddress;
+
+    gcmkHEADER_ARG("Kernel=0x%x Process=0x%x *Data=0x%x",
+                   Kernel, Process, gcmOPT_POINTER(Data));
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+    /* Get base address. */
+    gcmkONERROR(gckHARDWARE_GetBaseAddress(Kernel->hardware, &baseAddress));
+
+    /* Walk all used cache slots. */
+    for (i = oldest = 0; i < Kernel->cacheSlots; ++i)
+    {
+        if ((Kernel->cache[i].logical == *Data)
+        &&  (Kernel->cache[i].process == Process)
+        )
+        {
+            /* Bail out. */
+            break;
+        }
+
+        if (i == 0)
+        {
+            /* First slot. */
+            oldest = i;
+        }
+
+        /* Test if this cache slot is older. */
+        else if (Kernel->cache[i].stamp < Kernel->cache[oldest].stamp)
+        {
+            oldest = i;
+        }
+    }
+
+    /* See if we had a match. */
+    if (i == Kernel->cacheSlots)
+    {
+        /* See if there is room in the cache. */
+        if (i < gcmCOUNTOF(Kernel->cache))
+        {
+            /* Just append to the cache. */
+            i = Kernel->cacheSlots++;
+        }
+
+        else
+        {
+            /* Evict the oldest cache line. */
+            i = oldest;
+        }
+
+        /* Initialize the cache line. */
+        Kernel->cache[i].logical = *Data;
+        Kernel->cache[i].process = Process;
+
+        /* Map the logical address to a DMA address. */
+        gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os,
+                                             *Data,
+                                             &Kernel->cache[i].dma));
+
+        if (baseAddress != 0)
+        {
+            gctBOOL needBase;
+
+            /* Does this state load need a base address? */
+            gcmkONERROR(gckHARDWARE_NeedBaseAddress(Kernel->hardware,
+                                                    ((gctUINT32_PTR) Data)[-1],
+                                                    &needBase));
+
+            if (needBase)
+            {
+                /* Add the base address. */
+                Kernel->cache[i].dma += baseAddress;
+            }
+        }
+    }
+
+    /* Increment time stamp of the cache slot. */
+    Kernel->cache[i].stamp = Kernel->cacheTimeStamp++;
+
+    /* Return DMA address. */
+    *Data = gcmINT2PTR(Kernel->cache[i].dma);
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Data=0x%08x", *Data);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+#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
+    )
+{
+    gceSTATUS status;
+    gckEVENT event;
+    gckHARDWARE hardware;
+#if gcdSECURE_USER
+    gctUINT32 processID;
+#endif
+
+    gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+    /* Validate the arguemnts. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    /* Grab gckEVENT object. */
+    event = Kernel->event;
+    gcmkVERIFY_OBJECT(event, gcvOBJ_EVENT);
+
+    /* Grab gckHARDWARE object. */
+    hardware = Kernel->hardware;
+    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+    /* Handle all outstanding events now. */
+    event->pending = ~0U;
+    gcmkONERROR(gckEVENT_Notify(event, 1));
+
+    /* Again in case more events got submitted. */
+    event->pending = ~0U;
+    gcmkONERROR(gckEVENT_Notify(event, 2));
+
+#if gcdSECURE_USER
+    /* Flush the secure mapping cache. */
+    gcmkONERROR(gckOS_GetProcessID(&processID));
+    gcmkONERROR(gckKERNEL_MapLogicalToPhysical(Kernel, processID, gcvNULL));
+#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;
+}
+
diff --git a/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel.h b/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel.h
new file mode 100644 (file)
index 0000000..35adeb7
--- /dev/null
@@ -0,0 +1,406 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+#if gcdSECURE_USER
+typedef struct _gckLOGICAL_CACHE
+{
+    gctHANDLE       process;
+    gctPOINTER      logical;
+    gctUINT32       dma;
+    gctUINT64       stamp;
+}
+gckLOGICAL_CACHE;
+#endif
+
+/* gckKERNEL object. */
+struct _gckKERNEL
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gckOS object. */
+    gckOS                       os;
+
+    /* Pointer to gckHARDWARE object. */
+    gckHARDWARE                 hardware;
+
+    /* Pointer to gckCOMMAND object. */
+    gckCOMMAND                  command;
+
+    /* Pointer to gckEVENT object. */
+    gckEVENT                    event;
+
+    /* 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
+
+#if gcdSECURE_USER
+    gckLOGICAL_CACHE            cache[gcdSECURE_CACHE_SLOTS];
+    gctUINT                     cacheSlots;
+    gctUINT64                   cacheTimeStamp;
+#endif
+};
+
+#define gcdCOMMAND_QUEUES       2
+
+/* 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. */
+    gctUINT32                   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;
+    gctINT                      index;
+    gctUINT32                   offset;
+
+    /* The command queue is new. */
+    gctBOOL                     newQueue;
+    gctBOOL                     submit;
+
+    /* Context counter used for unique ID. */
+    gctUINT64                   contextCounter;
+
+    /* Current context ID. */
+    gctUINT64                   currentContext;
+
+    /* Pointer to last WAIT command. */
+    gctPOINTER                  wait;
+    gctSIZE_T                   waitSize;
+
+    /* Command buffer alignment. */
+    gctSIZE_T                   alignment;
+    gctSIZE_T                   reservedHead;
+    gctSIZE_T                   reservedTail;
+
+    /* Commit counter. */
+    gctPOINTER                  atomCommit;
+};
+
+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            event;
+
+#ifdef __QNXNTO__
+    /* Kernel. */
+    gckKERNEL                   kernel;
+#endif
+}
+gcsEVENT;
+
+/* Structure holding a list of events to be processed by an interrupt. */
+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;
+
+    /* Process ID owning the event queue. */
+    gctUINT32                   processID;
+}
+gcsEVENT_QUEUE;
+
+/* 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                  mutexQueue;
+
+    /* Array of event queues. */
+    gcsEVENT_QUEUE              queues[31];
+    gctUINT8                    lastID;
+
+    /* Pending events. */
+    volatile gctUINT            pending;
+
+    /* List of free event structures and its mutex. */
+    gcsEVENT_PTR                freeList;
+    gctSIZE_T                   freeCount;
+    gctPOINTER                  freeMutex;
+
+    /* Events queued to be added to an event queue and its mutex. */
+    gcsEVENT_QUEUE              list;
+    gctPOINTER                  listMutex;
+};
+
+/* 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;
+
+        /* Unique handle of the caller process channel. */
+        gctHANDLE               handle;
+#endif
+
+        /* Locked counter. */
+        gctINT32                locked;
+
+        /* Memory pool. */
+        gcePOOL                 pool;
+        gctUINT32               physical;
+    }
+    VidMem;
+
+    /* Allocated from gckOS. */
+    struct _gcsVIDMEM_NODE_VIRTUAL
+    {
+        /* Pointer to gckKERNEL object. */
+        gckKERNEL               kernel;
+
+        /* Information for this node. */
+        gctBOOL                 contiguous;
+        gctPHYS_ADDR            physical;
+        gctSIZE_T               bytes;
+        gctPOINTER              logical;
+
+        /* Page table information. */
+        gctSIZE_T               pageCount;
+        gctPOINTER              pageTable;
+        gctUINT32               address;
+
+        /* Mutex. */
+        gctPOINTER              mutex;
+
+        /* Locked counter. */
+        gctINT32                locked;
+
+#ifdef __QNXNTO__
+        /* Single linked list of nodes. */
+        gcuVIDMEM_NODE_PTR      next;
+
+        /* PID of the caller process channel. */
+        gctUINT32               userPID;
+
+        /* Unique handle of the caller process channel. */
+        gctHANDLE               handle;
+
+        /* Unlock pending flag. */
+        gctBOOL                 unlockPending;
+
+        /* Free pending flag. */
+        gctBOOL                 freePending;
+#else
+        /* Pending flag. */
+        gctBOOL                 pending;
+#endif
+    }
+    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;
+};
+
+/* 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;
+
+#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
+    );
+
+#if gcdSECURE_USER
+gceSTATUS
+gckKERNEL_MapLogicalToPhysical(
+    IN gckKERNEL Kernel,
+    IN gctHANDLE Process,
+    IN OUT gctPOINTER * Data
+    );
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryIdle(
+    IN gckHARDWARE Hardware,
+    OUT gctBOOL_PTR IsIdle
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_command.c b/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_command.c
new file mode 100644 (file)
index 0000000..f0a9cf8
--- /dev/null
@@ -0,0 +1,1797 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_user_context.h"
+
+#if defined(__QNXNTO__)
+#include <sys/slog.h>
+#endif
+
+#define _GC_OBJ_ZONE    gcvZONE_COMMAND
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+#if gcdDUMP_COMMAND
+static void
+_DumpCommand(
+    IN gckCOMMAND Command,
+    IN gctPOINTER Pointer,
+    IN gctSIZE_T Bytes
+    )
+{
+    gctUINT32_PTR data = (gctUINT32_PTR) Pointer;
+    gctUINT32 address;
+
+    gckOS_GetPhysicalAddress(Command->os, Pointer, &address);
+
+    gcmkPRINT("@[kernel.command %08X %08X", address, Bytes);
+    while (Bytes >= 8*4)
+    {
+        gcmkPRINT("  %08X %08X %08X %08X %08X %08X %08X %08X",
+                  data[0], data[1], data[2], data[3], data[4], data[5], data[6],
+                  data[7]);
+        data  += 8;
+        Bytes -= 32;
+    }
+
+    switch (Bytes)
+    {
+    case 7*4:
+        gcmkPRINT("  %08X %08X %08X %08X %08X %08X %08X",
+                  data[0], data[1], data[2], data[3], data[4], data[5],
+                  data[6]);
+        break;
+
+    case 6*4:
+        gcmkPRINT("  %08X %08X %08X %08X %08X %08X",
+                  data[0], data[1], data[2], data[3], data[4], data[5]);
+        break;
+
+    case 5*4:
+        gcmkPRINT("  %08X %08X %08X %08X %08X",
+                  data[0], data[1], data[2], data[3], data[4]);
+        break;
+
+    case 4*4:
+        gcmkPRINT("  %08X %08X %08X %08X", data[0], data[1], data[2], data[3]);
+        break;
+
+    case 3*4:
+        gcmkPRINT("  %08X %08X %08X", data[0], data[1], data[2]);
+        break;
+
+    case 2*4:
+        gcmkPRINT("  %08X %08X", data[0], data[1]);
+        break;
+
+    case 1*4:
+        gcmkPRINT("  %08X", data[0]);
+        break;
+    }
+
+    gcmkPRINT("] -- command");
+}
+#endif
+
+/*******************************************************************************
+**
+**  _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
+    gcmkPRINT("@[kernel.waitsignal]");
+#endif
+
+    gcmkONERROR(
+        gckOS_WaitSignal(Command->os,
+                         Command->queues[newIndex].signal,
+                         gcvINFINITE));
+
+    if (currentIndex >= 0)
+    {
+        /* Mark the command queue as available. */
+        gcmkONERROR(gckEVENT_Signal(Command->kernel->event,
+                                    Command->queues[currentIndex].signal,
+                                    gcvKERNEL_COMMAND));
+    }
+
+    /* Update gckCOMMAND object with new command queue. */
+    Command->index    = newIndex;
+    Command->newQueue = gcvTRUE;
+    Command->physical = Command->queues[newIndex].physical;
+    Command->logical  = Command->queues[newIndex].logical;
+    Command->offset   = 0;
+
+    if (currentIndex >= 0)
+    {
+        /* Submit the event queue. */
+        Command->submit = gcvTRUE;
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("Command->index=%d", Command->index);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/******************************************************************************\
+****************************** 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;
+
+    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),
+                       (gctPOINTER *) &command));
+
+    /* Initialize the gckCOMMAND object.*/
+    command->object.type    = gcvOBJ_COMMAND;
+    command->kernel         = Kernel;
+    command->os             = os;
+    command->mutexQueue     = gcvNULL;
+    command->mutexContext   = gcvNULL;
+    command->powerSemaphore = gcvNULL;
+    command->atomCommit     = gcvNULL;
+
+    /* No command queues created yet. */
+    command->index = 0;
+    for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+    {
+        command->queues[i].signal  = gcvNULL;
+        command->queues[i].logical = gcvNULL;
+    }
+
+    /* Get the command buffer requirements. */
+    gcmkONERROR(
+        gckHARDWARE_QueryCommandBuffer(Kernel->hardware,
+                                       &command->alignment,
+                                       &command->reservedHead,
+                                       &command->reservedTail));
+
+    /* No contexts available yet. */
+    command->contextCounter = command->currentContext = 0;
+
+    /* 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));
+
+    /* Set hardware to pipe 0. */
+    command->pipeSelect = 0;
+
+    /* 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->submit   = gcvFALSE;
+
+    /* Command is not yet running. */
+    command->running = gcvFALSE;
+
+    /* Command queue is idle. */
+    command->idle = gcvTRUE;
+
+    /* Commit stamp is zero. */
+    command->commitStamp = 0;
+
+    /* 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(gckOS_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));
+    }
+
+    /* 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));
+
+    /* Mark object as unknown. */
+    Command->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the gckCOMMAND object. */
+    gcmkVERIFY_OK(gckOS_Free(Command->os, Command));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    gckHARDWARE hardware;
+    gceSTATUS status;
+    gctSIZE_T bytes;
+
+    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;
+
+    /* Append WAIT/LINK. */
+    bytes = Command->pageSize;
+    gcmkONERROR(
+        gckHARDWARE_WaitLink(hardware,
+                             Command->logical,
+                             0,
+                             &bytes,
+                             &Command->wait,
+                             &Command->waitSize));
+
+    /* Flush the cache for the wait/link. */
+    gcmkONERROR(gckOS_CacheFlush(Command->os,
+                                 gcvNULL,
+                                 Command->logical,
+                                 bytes));
+
+    /* Adjust offset. */
+    Command->offset   = bytes;
+    Command->newQueue = gcvFALSE;
+
+    /* Enable command processor. */
+#ifdef __QNXNTO__
+    gcmkONERROR(
+        gckHARDWARE_Execute(hardware,
+                            Command->logical,
+                            Command->physical,
+                            gcvTRUE,
+                            bytes));
+#else
+    gcmkONERROR(
+        gckHARDWARE_Execute(hardware,
+                            Command->logical,
+                            bytes));
+#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);
+
+    /* Replace last WAIT with END. */
+    gcmkONERROR(
+        gckHARDWARE_End(hardware,
+                        Command->wait,
+                        &Command->waitSize));
+
+    /* 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;
+}
+
+typedef struct _gcsMAPPED * gcsMAPPED_PTR;
+struct _gcsMAPPED
+{
+    gcsMAPPED_PTR next;
+    gctPOINTER pointer;
+    gctPOINTER kernelPointer;
+    gctSIZE_T bytes;
+};
+
+static gceSTATUS
+_AddMap(
+    IN gckOS Os,
+    IN gctPOINTER Source,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Destination,
+    IN OUT gcsMAPPED_PTR * Stack
+    )
+{
+    gcsMAPPED_PTR map = gcvNULL;
+    gceSTATUS status;
+
+    /* Don't try to map NULL pointers. */
+    if (Source == gcvNULL)
+    {
+        *Destination = gcvNULL;
+        return gcvSTATUS_OK;
+    }
+
+    /* Allocate the gcsMAPPED structure. */
+    gcmkONERROR(
+        gckOS_Allocate(Os, gcmSIZEOF(*map), (gctPOINTER *) &map));
+
+    /* Map the user pointer into kernel addressing space. */
+    gcmkONERROR(
+        gckOS_MapUserPointer(Os, Source, Bytes, Destination));
+
+    /* Save mapping. */
+    map->pointer       = Source;
+    map->kernelPointer = *Destination;
+    map->bytes         = Bytes;
+
+    /* Push structure on top of the stack. */
+    map->next = *Stack;
+    *Stack    = map;
+
+    /* Success. */
+    return gcvSTATUS_OK;
+
+OnError:
+    if (gcmIS_ERROR(status) && (map != gcvNULL))
+    {
+        /* Roll back on error. */
+        gcmkVERIFY_OK(gckOS_Free(Os, map));
+    }
+
+    /* Return the status. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_Commit
+**
+**  Commit a command buffer to the command queue.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to an gckCOMMAND object.
+**
+**      gcoCMDBUF CommandBuffer
+**          Pointer to an gcoCMDBUF object.
+**
+**      gcoCONTEXT Context
+**          Pointer to an gcoCONTEXT object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Commit(
+    IN gckCOMMAND Command,
+    IN gcoCMDBUF CommandBuffer,
+    IN gcoCONTEXT Context,
+    IN gctHANDLE Process
+    )
+{
+    gcoCMDBUF commandBuffer;
+    gcoCONTEXT context;
+    gckHARDWARE hardware = gcvNULL;
+    gceSTATUS status;
+    gctPOINTER initialLink, link;
+    gctSIZE_T bytes, initialSize, lastRun;
+    gcoCMDBUF buffer;
+    gctPOINTER wait;
+    gctSIZE_T waitSize;
+    gctUINT32 offset;
+    gctPOINTER fetchAddress;
+    gctSIZE_T fetchSize;
+    gctUINT8_PTR logical;
+    gcsMAPPED_PTR stack = gcvNULL;
+    gctINT acquired = 0;
+#if gcdSECURE_USER
+    gctUINT32_PTR hint;
+#endif
+#if gcdDUMP_COMMAND
+    gctPOINTER dataPointer;
+    gctSIZE_T dataBytes;
+#endif
+    gctPOINTER flushPointer;
+    gctSIZE_T flushSize;
+    gctBOOL semaAcquired = gcvFALSE;
+    gctINT32 atomValue;
+    gctBOOL atomIncremented = gcvFALSE;
+    gctBOOL powerAcquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x Context=0x%x",
+                   Command, CommandBuffer, Context);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+#if gcdNULL_DRIVER == 2
+    /* Do nothing with infinite hardware. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+#endif
+
+    gcmkONERROR(
+        _AddMap(Command->os,
+                CommandBuffer,
+                gcmSIZEOF(struct _gcoCMDBUF),
+                (gctPOINTER *) &commandBuffer,
+                &stack));
+    gcmkVERIFY_OBJECT(commandBuffer, gcvOBJ_COMMANDBUFFER);
+    gcmkONERROR(
+        _AddMap(Command->os,
+                Context,
+                gcmSIZEOF(struct _gcoCONTEXT),
+                (gctPOINTER *) &context,
+                &stack));
+    gcmkVERIFY_OBJECT(context, gcvOBJ_CONTEXT);
+
+    /* 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. */
+    gcmkONERROR(gckOS_AtomIncrement(Command->os,
+                                    Command->atomCommit,
+                                    &atomValue));
+    atomIncremented = gcvTRUE;
+
+    /* Release the power mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Command->os, hardware->powerMutex));
+    powerAcquired = gcvFALSE;
+
+    /* 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;
+
+    /* Acquire the context switching mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Command->os,
+                           Command->mutexContext,
+                           gcvINFINITE));
+
+    ++acquired;
+
+    /* Reserved slot in the context or command buffer. */
+    gcmkONERROR(
+        gckHARDWARE_PipeSelect(hardware, gcvNULL, 0, &bytes));
+
+    /* Test if we need to switch to this context. */
+    if ((context->id != 0)
+    &&  (context->id != Command->currentContext)
+    )
+    {
+        /* Map the context buffer. */
+        gcmkONERROR(
+            _AddMap(Command->os,
+                    context->logical,
+                    context->bufferSize,
+                    (gctPOINTER *) &logical,
+                    &stack));
+
+#if gcdSECURE_USER
+        /* Map the hint array. */
+        gcmkONERROR(
+            _AddMap(Command->os,
+                    context->hintArray,
+                    context->hintCount * gcmSIZEOF(gctUINT32),
+                    (gctPOINTER *) &hint,
+                    &stack));
+
+        /* Loop while we have valid hints. */
+        while (*hint != 0)
+        {
+            /* Map handle into physical address. */
+            gcmkONERROR(
+                gckKERNEL_MapLogicalToPhysical(
+                    Command->kernel,
+                    Process,
+                    (gctPOINTER *) (logical + *hint)));
+
+            /* Next hint. */
+            ++hint;
+        }
+#endif
+
+        /* See if we have to check pipes. */
+        if (context->pipe2DIndex != 0)
+        {
+            /* See if we are in the correct pipe. */
+            if (context->initialPipe == Command->pipeSelect)
+            {
+                gctUINT32 reserved = bytes;
+                gctUINT8_PTR nop   = logical;
+
+                /* Already in the correct pipe, fill context buffer with NOP. */
+                while (reserved > 0)
+                {
+                    bytes = reserved;
+                    gcmkONERROR(
+                        gckHARDWARE_Nop(hardware, nop, &bytes));
+
+                    gcmkASSERT(reserved >= bytes);
+                    reserved -= bytes;
+                    nop      += bytes;
+                }
+            }
+            else
+            {
+                /* Switch to the correct pipe. */
+                gcmkONERROR(
+                    gckHARDWARE_PipeSelect(hardware,
+                                           logical,
+                                           context->initialPipe,
+                                           &bytes));
+            }
+        }
+
+        /* Save initial link pointer. */
+        initialLink = logical;
+        initialSize = context->bufferSize;
+
+        /* Save initial buffer to flush. */
+        flushPointer = initialLink;
+        flushSize    = initialSize;
+
+        /* Save pointer to next link. */
+        gcmkONERROR(
+            _AddMap(Command->os,
+                    context->link,
+                    8,
+                    &link,
+                    &stack));
+
+        /* Start parsing CommandBuffer. */
+        buffer = commandBuffer;
+
+        /* Mark context buffer as used. */
+        if (context->inUse != gcvNULL)
+        {
+            gctBOOL_PTR inUse;
+
+            gcmkONERROR(
+                _AddMap(Command->os,
+                        (gctPOINTER) context->inUse,
+                        gcmSIZEOF(gctBOOL),
+                        (gctPOINTER *) &inUse,
+                        &stack));
+
+            *inUse = gcvTRUE;
+        }
+    }
+
+    else
+    {
+        /* Test if this is a new context. */
+        if (context->id == 0)
+        {
+            /* Generate unique ID for the context buffer. */
+            context->id = ++ Command->contextCounter;
+
+            if (context->id == 0)
+            {
+                /* Context counter overflow (wow!) */
+                gcmkONERROR(gcvSTATUS_TOO_COMPLEX);
+            }
+        }
+
+        /* Map the command buffer. */
+        gcmkONERROR(
+            _AddMap(Command->os,
+                    commandBuffer->logical,
+                    commandBuffer->offset,
+                    (gctPOINTER *) &logical,
+                    &stack));
+
+#if gcdSECURE_USER
+        /* Map the hint table. */
+        gcmkONERROR(
+            _AddMap(Command->os,
+                    commandBuffer->hintCommit,
+                    commandBuffer->offset - commandBuffer->startOffset,
+                    (gctPOINTER *) &hint,
+                    &stack));
+
+        /* Walk while we have valid hints. */
+        while (*hint != 0)
+        {
+            /* Map the handle to a physical address. */
+            gcmkONERROR(
+                gckKERNEL_MapLogicalToPhysical(
+                    Command->kernel,
+                    Process,
+                    (gctPOINTER *) (logical + *hint)));
+
+            /* Next hint. */
+            ++hint;
+        }
+#endif
+
+        if (context->entryPipe == Command->pipeSelect)
+        {
+            gctUINT32 reserved = Command->reservedHead;
+            gctUINT8_PTR nop   = logical + commandBuffer->startOffset;
+
+            /* Already in the correct pipe, fill context buffer with NOP. */
+            while (reserved > 0)
+            {
+                bytes = reserved;
+                gcmkONERROR(
+                    gckHARDWARE_Nop(hardware, nop, &bytes));
+
+                gcmkASSERT(reserved >= bytes);
+                reserved -= bytes;
+                nop      += bytes;
+            }
+        }
+        else
+        {
+            /* Switch to the correct pipe. */
+            gcmkONERROR(
+                gckHARDWARE_PipeSelect(hardware,
+                                       logical + commandBuffer->startOffset,
+                                       context->entryPipe,
+                                       &bytes));
+        }
+
+        /* Save initial link pointer. */
+        initialLink = logical + commandBuffer->startOffset;
+        initialSize = commandBuffer->offset
+                    - commandBuffer->startOffset
+                    + Command->reservedTail;
+
+        /* Save initial buffer to flush. */
+        flushPointer = initialLink;
+        flushSize    = initialSize;
+
+        /* Save pointer to next link. */
+        link = logical + commandBuffer->offset;
+
+        /* No more data. */
+        buffer = gcvNULL;
+    }
+
+#if gcdDUMP_COMMAND
+    dataPointer = initialLink;
+    dataBytes   = initialSize;
+#endif
+
+    /* Loop through all remaining command buffers. */
+    if (buffer != gcvNULL)
+    {
+        /* Map the command buffer. */
+        gcmkONERROR(
+            _AddMap(Command->os,
+                    buffer->logical,
+                    buffer->offset + Command->reservedTail,
+                    (gctPOINTER *) &logical,
+                    &stack));
+
+#if gcdSECURE_USER
+        /* Map the hint table. */
+        gcmkONERROR(
+            _AddMap(Command->os,
+                    buffer->hintCommit,
+                    buffer->offset - buffer->startOffset,
+                    (gctPOINTER *) &hint,
+                    &stack));
+
+        /* Walk while we have valid hints. */
+        while (*hint != 0)
+        {
+            /* Map the handle to a physical address. */
+            gcmkONERROR(
+                gckKERNEL_MapLogicalToPhysical(
+                    Command->kernel,
+                    Process,
+                    (gctPOINTER *) (logical + *hint)));
+
+            /* Next hint. */
+            ++hint;
+        }
+#endif
+
+        /* First slot becomes a NOP. */
+        {
+            gctUINT32 reserved = Command->reservedHead;
+            gctUINT8_PTR nop   = logical + buffer->startOffset;
+
+            /* Already in the correct pipe, fill context buffer with NOP. */
+            while (reserved > 0)
+            {
+                bytes = reserved;
+                gcmkONERROR(
+                    gckHARDWARE_Nop(hardware, nop, &bytes));
+
+                gcmkASSERT(reserved >= bytes);
+                reserved -= bytes;
+                nop      += bytes;
+            }
+        }
+
+        /* Generate the LINK to this command buffer. */
+        gcmkONERROR(
+            gckHARDWARE_Link(hardware,
+                             link,
+                             logical + buffer->startOffset,
+                             buffer->offset
+                             - buffer->startOffset
+                             + Command->reservedTail,
+                             &bytes));
+
+        /* Flush the initial buffer. */
+        gcmkONERROR(gckOS_CacheFlush(Command->os,
+                                     Process,
+                                     flushPointer,
+                                     flushSize));
+
+        /* Save new flush pointer. */
+        flushPointer = logical + buffer->startOffset;
+        flushSize    = buffer->offset
+                     - buffer->startOffset
+                     + Command->reservedTail;
+
+#if gcdDUMP_COMMAND
+        _DumpCommand(Command, dataPointer, dataBytes);
+        dataPointer = logical + buffer->startOffset;
+        dataBytes   = buffer->offset - buffer->startOffset
+                    + Command->reservedTail;
+#endif
+
+        /* Save pointer to next link. */
+        link = logical + buffer->offset;
+    }
+
+    /* Compute number of bytes required for WAIT/LINK. */
+    gcmkONERROR(
+        gckHARDWARE_WaitLink(hardware,
+                             gcvNULL,
+                             Command->offset,
+                             &bytes,
+                             gcvNULL,
+                             gcvNULL));
+
+    lastRun = bytes;
+
+    /* Grab the command queue mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Command->os,
+                           Command->mutexQueue,
+                           gcvINFINITE));
+
+    ++acquired;
+
+    /* Compute number of bytes left in current command queue. */
+    bytes = Command->pageSize - Command->offset;
+
+    if (bytes < lastRun)
+    {
+        /* Create a new command queue. */
+        gcmkONERROR(_NewQueue(Command));
+
+        /* Adjust run size with any extra commands inserted. */
+        lastRun += Command->offset;
+    }
+
+    /* Get current offset. */
+    offset = Command->offset;
+
+    /* Append WAIT/LINK in command queue. */
+    bytes = Command->pageSize - offset;
+
+    gcmkONERROR(
+        gckHARDWARE_WaitLink(hardware,
+                             (gctUINT8 *) Command->logical + offset,
+                             offset,
+                             &bytes,
+                             &wait,
+                             &waitSize));
+
+    /* Flush the cache for the wait/link. */
+    gcmkONERROR(gckOS_CacheFlush(Command->os,
+                                 gcvNULL,
+                                 (gctUINT8 *) Command->logical + offset,
+                                 bytes));
+
+#if gcdDUMP_COMMAND
+    _DumpCommand(Command, (gctUINT8 *) Command->logical + offset, bytes);
+#endif
+
+    /* Adjust offset. */
+    offset += bytes;
+
+    if (Command->newQueue)
+    {
+        /* Compute fetch location and size for a new command queue. */
+        fetchAddress = Command->logical;
+        fetchSize    = offset;
+    }
+    else
+    {
+        /* Compute fetch location and size for an existing command queue. */
+        fetchAddress = (gctUINT8 *) Command->logical + Command->offset;
+        fetchSize    = offset - Command->offset;
+    }
+
+    bytes = 8;
+
+    /* Link in WAIT/LINK. */
+    gcmkONERROR(
+        gckHARDWARE_Link(hardware,
+                         link,
+                         fetchAddress,
+                         fetchSize,
+                         &bytes));
+
+    /* Flush the cache for the command buffer. */
+    gcmkONERROR(gckOS_CacheFlush(Command->os,
+                                 Process,
+                                 flushPointer,
+                                 flushSize));
+
+#if gcdDUMP_COMMAND
+    _DumpCommand(Command, dataPointer, dataBytes);
+#endif
+
+    /* Execute the entire sequence. */
+    gcmkONERROR(
+        gckHARDWARE_Link(hardware,
+                         Command->wait,
+                         initialLink,
+                         initialSize,
+                         &Command->waitSize));
+
+    /* Flush the cache for the link. */
+    gcmkONERROR(gckOS_CacheFlush(Command->os,
+                                 gcvNULL,
+                                 Command->wait,
+                                 Command->waitSize));
+
+#if gcdDUMP_COMMAND
+    _DumpCommand(Command, Command->wait, Command->waitSize);
+#endif
+
+    /* Update command queue offset. */
+    Command->offset   = offset;
+    Command->newQueue = gcvFALSE;
+
+    /* Update address of last WAIT. */
+    Command->wait     = wait;
+    Command->waitSize = waitSize;
+
+    /* Update context and pipe select. */
+    Command->currentContext = context->id;
+    Command->pipeSelect     = context->currentPipe;
+
+    /* Update queue tail pointer. */
+    gcmkONERROR(
+        gckHARDWARE_UpdateQueueTail(hardware,
+                                    Command->logical,
+                                    Command->offset));
+
+#if gcdDUMP_COMMAND
+    gcmkPRINT("@[kernel.commit]");
+#endif
+
+    /* Release the command queue mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+    --acquired;
+
+    /* Release the context switching mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+    --acquired;
+
+    /* Release the power management semaphore. */
+    gcmkONERROR(gckOS_ReleaseSemaphore(Command->os, Command->powerSemaphore));
+    semaAcquired = gcvFALSE;
+
+    /* Submit events if asked for. */
+    if (Command->submit)
+    {
+        /* Submit events. */
+        status = gckEVENT_Submit(Command->kernel->event, gcvFALSE);
+
+        if (gcmIS_SUCCESS(status))
+        {
+            /* Success. */
+            Command->submit = gcvFALSE;
+        }
+        else
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_COMMAND,
+                           "gckEVENT_Submit returned %d",
+                           status);
+        }
+    }
+
+    /* Success. */
+    status = gcvSTATUS_OK;
+
+OnError:
+    if (acquired > 1)
+    {
+        /* Release the command queue mutex. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+    }
+
+    if (acquired > 0)
+    {
+        /* Release the context switching mutex. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+    }
+
+    if (semaAcquired)
+    {
+        /* Release the power management semaphore. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseSemaphore(Command->os, Command->powerSemaphore));
+    }
+
+    if (atomIncremented)
+    {
+        /* Decrement the commit atom. */
+        gcmkVERIFY_OK(gckOS_AtomDecrement(Command->os,
+                                          Command->atomCommit,
+                                          &atomValue));
+    }
+
+    /* Unmap all mapped pointers. */
+    while (stack != gcvNULL)
+    {
+        gcsMAPPED_PTR map = stack;
+        stack             = map->next;
+
+        gcmkVERIFY_OK(
+            gckOS_UnmapUserPointer(Command->os,
+                                   map->pointer,
+                                   map->bytes,
+                                   map->kernelPointer));
+
+        gcmkVERIFY_OK(
+            gckOS_Free(Command->os, map));
+    }
+
+    if (powerAcquired)
+    {
+        /* Release the power mutex. */
+        gcmkONERROR(gckOS_ReleaseMutex(Command->os, hardware->powerMutex));
+    }
+
+    /* Return status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  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 requiredBytes, bytes;
+    gctBOOL acquired = gcvFALSE;
+    gctBOOL semaAcquired = gcvTRUE;
+    gctINT32 atomValue;
+    gctBOOL atomIncremented = gcvFALSE;
+    gctBOOL powerAcquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    /* Grab the power mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(Command->os,
+                                   Command->kernel->hardware->powerMutex,
+                                   gcvINFINITE));
+    powerAcquired = gcvTRUE;
+
+    /* Increment the commit atom. */
+    gcmkONERROR(
+        gckOS_AtomIncrement(Command->os, Command->atomCommit, &atomValue));
+    atomIncremented = gcvTRUE;
+
+    /* Release the power mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Command->os,
+                                   Command->kernel->hardware->powerMutex));
+    powerAcquired = gcvFALSE;
+
+    /* Notify the system the GPU has a commit. */
+    gcmkONERROR(gckOS_Broadcast(Command->os,
+                                Command->kernel->hardware,
+                                gcvBROADCAST_GPU_COMMIT));
+
+    /* Grab 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));
+    acquired = gcvTRUE;
+
+    /* Compute number of bytes required for WAIT/LINK. */
+    gcmkONERROR(
+        gckHARDWARE_WaitLink(Command->kernel->hardware,
+                             gcvNULL,
+                             Command->offset + gcmALIGN(RequestedBytes,
+                                                        Command->alignment),
+                             &requiredBytes,
+                             gcvNULL,
+                             gcvNULL));
+
+    /* Compute total number of bytes required. */
+    requiredBytes += gcmALIGN(RequestedBytes, Command->alignment);
+
+    /* Compute number of bytes available in command queue. */
+    bytes = Command->pageSize - Command->offset;
+
+    if (bytes < requiredBytes)
+    {
+        /* Create a new command queue. */
+        gcmkONERROR(_NewQueue(Command));
+
+        /* Recompute number of bytes available in command queue. */
+        bytes = Command->pageSize - Command->offset;
+
+        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:
+    if (acquired)
+    {
+        /* Release command queue mutex on error. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+    }
+
+    if (semaAcquired)
+    {
+        /* Release the power management semaphore. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseSemaphore(Command->os, Command->powerSemaphore));
+    }
+
+    if (atomIncremented)
+    {
+        /* Decrement the commit atom. */
+        gcmkVERIFY_OK(
+            gckOS_AtomDecrement(Command->os, Command->atomCommit, &atomValue));
+    }
+
+    if (powerAcquired)
+    {
+        /* Release the power mutex. */
+        gcmkONERROR(gckOS_ReleaseMutex(Command->os,
+                                       Command->kernel->hardware->powerMutex));
+    }
+
+    /* Return status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckCOMMAND_Release
+**
+**  Release a previously reserved command queue.  The command FIFO mutex will be
+**  released.
+**
+**  INPUT:
+**
+**      gckCOMMAND Command
+**          Pointer to an gckCOMMAND object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Release(
+    IN gckCOMMAND Command
+    )
+{
+    gceSTATUS status;
+    gctINT32 atomValue;
+
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    /* Release the command queue mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+
+    /* Release the power management semaphore. */
+    gcmkONERROR(gckOS_ReleaseSemaphore(Command->os, Command->powerSemaphore));
+
+    /* Decrement the commit atom. */
+    gcmkONERROR(
+        gckOS_AtomDecrement(Command->os, Command->atomCommit, &atomValue));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+
+OnError:
+    /* Return the 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
+    )
+{
+    gctUINT32 offset;
+    gctPOINTER address;
+    gctSIZE_T bytes;
+    gceSTATUS status;
+    gctPOINTER wait;
+    gctSIZE_T waitBytes;
+    gctINT32 atomValue;
+
+    gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+    /* Compute offset for WAIT/LINK. */
+    offset = Command->offset + RequestedBytes;
+
+    /* Compute number of byts left in command queue. */
+    bytes = Command->pageSize - offset;
+
+    /* Append WAIT/LINK in command queue. */
+    gcmkONERROR(
+        gckHARDWARE_WaitLink(Command->kernel->hardware,
+                             (gctUINT8 *) Command->logical + offset,
+                             offset,
+                             &bytes,
+                             &wait,
+                             &waitBytes));
+
+    if (Command->newQueue)
+    {
+        /* For a new command queue, point to the start of the command
+        ** queue and include both the commands inserted at the head of it
+        ** and the WAIT/LINK. */
+        address = Command->logical;
+        bytes  += offset;
+    }
+    else
+    {
+        /* For an existing command queue, point to the current offset and
+        ** include the WAIT/LINK. */
+        address = (gctUINT8 *) Command->logical + Command->offset;
+        bytes  += RequestedBytes;
+    }
+
+    /* Flush the cache. */
+    gcmkONERROR(gckOS_CacheFlush(Command->os, gcvNULL, address, bytes));
+
+#if gcdDUMP_COMMAND
+    _DumpCommand(Command, address, bytes);
+#endif
+
+    /* Convert the last WAIT into a LINK. */
+    gcmkONERROR(gckHARDWARE_Link(Command->kernel->hardware,
+                                 Command->wait,
+                                 address,
+                                 bytes,
+                                 &Command->waitSize));
+
+    /* Flush the cache. */
+    gcmkONERROR(gckOS_CacheFlush(Command->os,
+                                 gcvNULL,
+                                 Command->wait,
+                                 Command->waitSize));
+
+#if gcdDUMP_COMMAND
+    _DumpCommand(Command, Command->wait, 8);
+#endif
+
+    /* Update the pointer to the last WAIT. */
+    Command->wait     = wait;
+    Command->waitSize = waitBytes;
+
+    /* Update the command queue. */
+    Command->offset  += bytes;
+    Command->newQueue = gcvFALSE;
+
+    /* Update queue tail pointer. */
+    gcmkONERROR(
+        gckHARDWARE_UpdateQueueTail(Command->kernel->hardware,
+                                    Command->logical,
+                                    Command->offset));
+
+#if gcdDUMP_COMMAND
+    gcmkPRINT("@[kernel.execute]");
+#endif
+
+    /* Release the command queue mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+
+    /* Release the power management semaphore. */
+    gcmkONERROR(gckOS_ReleaseSemaphore(Command->os, Command->powerSemaphore));
+
+    /* Submit events if asked for. */
+    if (Command->submit)
+    {
+        /* Submit events. */
+        status = gckEVENT_Submit(Command->kernel->event, gcvFALSE);
+
+        if (gcmIS_SUCCESS(status))
+        {
+            /* Success. */
+            Command->submit = gcvFALSE;
+        }
+        else
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_COMMAND,
+                           "gckEVENT_Submit returned %d",
+                           status);
+        }
+    }
+
+    /* Decrement the commit atom. */
+    gcmkONERROR(
+        gckOS_AtomDecrement(Command->os, Command->atomCommit, &atomValue));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Release the command queue mutex. */
+    gcmkVERIFY_OK(
+        gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+
+    /* 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.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Stall(
+    IN gckCOMMAND Command
+    )
+{
+    gckOS os;
+    gckHARDWARE hardware;
+    gckEVENT event;
+    gceSTATUS status;
+    gctSIGNAL signal = gcvNULL;
+    gctUINT timer = 0;
+
+    gcmkHEADER_ARG("Command=0x%x", Command);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+#if gcdNULL_DRIVER == 2
+    /* Do nothing with infinite hardware. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+#endif
+
+    /* 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. */
+    event = Command->kernel->event;
+    gcmkVERIFY_OBJECT(event, gcvOBJ_EVENT);
+
+    /* Allocate the signal. */
+    gcmkONERROR(
+        gckOS_CreateSignal(os, gcvTRUE, &signal));
+
+    /* Append the EVENT command to trigger the signal. */
+    gcmkONERROR(gckEVENT_Signal(event,
+                                signal,
+                                gcvKERNEL_PIXEL));
+
+    /* Submit the event queue. */
+    gcmkONERROR(gckEVENT_Submit(event, gcvTRUE));
+
+#if gcdDUMP_COMMAND
+    gcmkPRINT("@[kernel.stall]");
+#endif
+
+    if (status == gcvSTATUS_CHIP_NOT_READY)
+    {
+        /* Error. */
+        goto OnError;
+    }
+
+    do
+    {
+        /* Wait for the signal. */
+        status = gckOS_WaitSignal(os, signal, 250);
+
+        if (status == gcvSTATUS_TIMEOUT)
+        {
+#if gcdDEBUG
+            gctUINT32 idle;
+
+            /* Read idle register. */
+            gcmkVERIFY_OK(
+                gckHARDWARE_GetIdle(Command->kernel->hardware,
+                                    gcvFALSE,
+                                    &idle));
+
+            gcmkTRACE(gcvLEVEL_ERROR,
+                      "%s(%d): idle=%08x",
+                      __FUNCTION__, __LINE__, idle);
+
+            gcmkVERIFY_OK(
+                gckOS_MemoryBarrier(os, gcvNULL));
+
+#ifdef __QNXNTO__
+            gctUINT32 reg_cmdbuf_fetch;
+            gctUINT32 reg_intr;
+
+            gcmkVERIFY_OK(
+                    gckOS_ReadRegister(Command->kernel->hardware->os, 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_ReadRegister(Command->kernel->hardware->os, 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 += 250;
+        }
+    }
+    while (gcmIS_ERROR(status)
+#if gcdGPU_TIMEOUT
+           && (timer < gcdGPU_TIMEOUT)
+#endif
+           );
+
+    /* Bail out on timeout. */
+    if (gcmIS_ERROR(status))
+    {
+        /* Broadcast the stuck GPU. */
+        gcmkONERROR(gckOS_Broadcast(os,
+                                    Command->kernel->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:
+    /* Free the signal. */
+    if (signal != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
diff --git a/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_event.c b/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_event.c
new file mode 100644 (file)
index 0000000..08e8100
--- /dev/null
@@ -0,0 +1,1481 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_user_context.h"
+
+#define _GC_OBJ_ZONE    gcvZONE_EVENT
+
+#define gcdEVENT_ALLOCATION_COUNT       (4096 / gcmSIZEOF(gcsHAL_INTERFACE))
+#define gcdEVENT_MIN_THRESHOLD          4
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+**  _GetEvent
+**
+**  Get an empty event ID.
+**
+**  INPUT:
+**
+**      gckEVENT Event
+**          Pointer to an gckEVENT object.
+**
+**  OUTPUT:
+**
+**      gctUINT8 * EventID
+**          Pointer to a variable that receives an empty event ID.
+*/
+static gceSTATUS
+_GetEvent(
+    IN gckEVENT Event,
+    OUT gctUINT8 * EventID,
+    IN gceKERNEL_WHERE Source
+    )
+{
+    gctINT i, id;
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Event=0x%x Source=%d", Event, Source);
+
+    /* Grab the queue mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(Event->os,
+                                   Event->mutexQueue,
+                                   gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Walk through all events. */
+    id = Event->lastID;
+    for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+    {
+        if (Event->queues[id].head == gcvNULL)
+        {
+            *EventID = (gctUINT8) id;
+
+            Event->lastID = (id + 1) % gcmCOUNTOF(Event->queues);
+
+            /* Save time stamp of event. */
+            Event->queues[id].stamp  = ++(Event->stamp);
+            Event->queues[id].source = Source;
+
+            /* Release the queue mutex. */
+            gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+
+            /* Success. */
+            gcmkFOOTER_ARG("*EventID=%u", *EventID);
+            return gcvSTATUS_OK;
+        }
+
+        id = (id + 1) % gcmCOUNTOF(Event->queues);
+    }
+
+    /* Release the queue mutex. */
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+    acquired = gcvFALSE;
+
+    /* Out of resources. */
+    gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+
+OnError:
+    if (acquired)
+    {
+        /* Release the queue mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+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->mutexQueue, 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->mutexQueue));
+    }
+
+    /* 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 event = gcvNULL;
+    int i;
+    gcsEVENT_PTR record;
+
+    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),
+                       (gctPOINTER *) &event));
+
+    /* Initialize the gckEVENT object. */
+    event->object.type = gcvOBJ_EVENT;
+    event->kernel      = Kernel;
+    event->os          = os;
+    event->mutexQueue  = gcvNULL;
+    event->freeList    = gcvNULL;
+    event->freeCount   = 0;
+    event->freeMutex   = gcvNULL;
+    event->list.head   = gcvNULL;
+    event->list.tail   = gcvNULL;
+    event->listMutex   = gcvNULL;
+    event->lastID      = 0;
+
+    /* Create the mutexes. */
+    gcmkONERROR(
+        gckOS_CreateMutex(os, &event->mutexQueue));
+
+    gcmkONERROR(
+        gckOS_CreateMutex(os, &event->freeMutex));
+
+    gcmkONERROR(
+        gckOS_CreateMutex(os, &event->listMutex));
+
+    /* Create a bunch of event reccords. */
+    for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; ++i)
+    {
+        /* Allocate an event record. */
+        gcmkONERROR(
+            gckOS_Allocate(os, gcmSIZEOF(gcsEVENT), (gctPOINTER *) &record));
+
+        /* Push it on the free list. */
+        record->next      = event->freeList;
+        event->freeList   = record;
+        event->freeCount += 1;
+    }
+
+    /* Zero out the entire event queue. */
+    for (i = 0; i < gcmCOUNTOF(event->queues); ++i)
+    {
+        event->queues[i].head = gcvNULL;
+    }
+
+    /* Zero out the time stamp. */
+    event->stamp = 0;
+
+    /* No events to handle. */
+    event->pending = 0;
+
+    /* Return pointer to the gckEVENT object. */
+    *Event = event;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Event=0x%x", *Event);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (event != gcvNULL)
+    {
+        if (event->mutexQueue != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(os, event->mutexQueue));
+        }
+
+        if (event->freeMutex != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(os, event->freeMutex));
+        }
+
+        if (event->listMutex != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(os, event->listMutex));
+        }
+
+        while (event->freeList != gcvNULL)
+        {
+            record          = event->freeList;
+            event->freeList = record->next;
+
+            gcmkVERIFY_OK(gckOS_Free(os, record));
+        }
+
+        gcmkVERIFY_OK(gckOS_Free(os, event));
+    }
+
+    /* 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;
+
+    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->mutexQueue));
+
+    /* Free all free events. */
+    while (Event->freeList != gcvNULL)
+    {
+        record          = Event->freeList;
+        Event->freeList = record->next;
+
+        gcmkVERIFY_OK(gckOS_Free(Event->os, record));
+    }
+
+    /* Delete the free mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->freeMutex));
+
+    /* Free all pending events. */
+    while (Event->list.head != gcvNULL)
+    {
+        record           = Event->list.head;
+        Event->list.head = record->next;
+
+        gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_EVENT,
+                       "Event record 0x%x is still pending for %d.",
+                       record, Event->list.source);
+        gcmkVERIFY_OK(gckOS_Free(Event->os, record));
+    }
+
+    /* Delete the list mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->listMutex));
+
+    /* Mark the gckEVENT object as unknown. */
+    Event->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the gckEVENT object. */
+    gcmkVERIFY_OK(gckOS_Free(Event->os, Event));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+gckEVENT_AllocateRecord(
+    IN gckEVENT Event,
+    IN gctBOOL AllocateAllowed,
+    OUT gcsEVENT_PTR * Record
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gctINT i;
+    gcsEVENT_PTR record;
+
+    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->freeCount < gcdEVENT_MIN_THRESHOLD)
+    )
+    {
+        /* Allocate a bunch of records. */
+        for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; ++i)
+        {
+            /* Allocate an event record. */
+            status = gckOS_Allocate(Event->os,
+                                    gcmSIZEOF(gcsEVENT),
+                                    (gctPOINTER *) &record);
+
+            if (gcmIS_ERROR(status))
+            {
+                gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_EVENT,
+                               "Out of memory allocating event records.");
+                break;
+            }
+
+            /* Acquire the mutex. */
+            gcmkONERROR(gckOS_AcquireMutex(Event->os,
+                                           Event->freeMutex,
+                                           gcvINFINITE));
+            acquired = gcvTRUE;
+
+            /* Push it on the free list. */
+            record->next      = Event->freeList;
+            Event->freeList   = record;
+            Event->freeCount += 1;
+
+            /* Release the mutex. */
+            gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+        }
+    }
+
+    /* Acquire the mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    *Record           = Event->freeList;
+    Event->freeList   = Event->freeList->next;
+    Event->freeCount -= 1;
+
+    /* Release the mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Record=0x%x", gcmOPT_POINTER(Record));
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+    }
+
+    /* Return the status. */
+    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->freeMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Push the record on the free list. */
+    Record->next      = Event->freeList;
+    Event->freeList   = Record;
+    Event->freeCount += 1;
+
+    /* Release the mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return gcvSTATUS_OK;
+}
+
+static 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;
+
+    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);
+
+    switch (FromWhere)
+    {
+    case gcvKERNEL_COMMAND:
+    case gcvKERNEL_PIXEL:
+        /* Check if the requested source matches the list. */
+        if ((Event->list.head   != gcvNULL)
+        &&  (Event->list.source != FromWhere)
+        )
+        {
+            /* No match - auto-submit the list. */
+            status = gckEVENT_Submit(Event, gcvFALSE);
+
+            if (status == gcvSTATUS_OUT_OF_RESOURCES)
+            {
+                /* When we are out of resources, just convert to submit from
+                ** PIXEL. */
+                Event->list.source = FromWhere = gcvKERNEL_PIXEL;
+            }
+
+            else
+            {
+                /* Check for error. */
+                gcmkONERROR(status);
+            }
+        }
+        break;
+
+    default:
+        /* Invalid argument. */
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    /* Allocate a free record. */
+    gcmkONERROR(gckEVENT_AllocateRecord(Event, AllocateAllowed, &record));
+
+    /* Copy the event interface into the record. */
+    gcmkONERROR(gckOS_MemCopy(&record->event,
+                              Interface,
+                              gcmSIZEOF(record->event)));
+
+    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)
+        );
+
+    record->next = gcvNULL;
+
+    /* Acquire the mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->listMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    if (Event->list.head == gcvNULL)
+    {
+        /* List doesn't exist yet. */
+        Event->list.head = record;
+        Event->list.tail = record;
+    }
+    else
+    {
+        /* Append to the current list. */
+        Event->list.tail->next = record;
+        Event->list.tail       = record;
+    }
+
+    /* Mark the source of this event. */
+    Event->list.source = FromWhere;
+
+    /* Release the mutex. */
+    gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->listMutex));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->listMutex));
+    }
+
+    if (record != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
+    }
+
+    /* 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_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.
+*/
+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_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.
+**
+*/
+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;
+#else
+    iface.u.Signal.auxSignal = gcvNULL;
+    iface.u.Signal.process   = gcvNULL;
+#endif
+
+    /* 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_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.
+*/
+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;
+}
+
+gceSTATUS
+gckEVENT_Commit(
+    IN gckEVENT Event,
+    IN gcsQUEUE_PTR Queue
+    )
+{
+    gceSTATUS status;
+    gcsQUEUE_PTR record = gcvNULL, next;
+
+    gcmkHEADER_ARG("Event=0x%x Queue=0x%x", Event, Queue);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+    /* Loop while there are records in the queue. */
+    while (Queue != gcvNULL)
+    {
+        /* Map record into kernel memory. */
+        gcmkONERROR(gckOS_MapUserPointer(Event->os,
+                                         Queue,
+                                         gcmSIZEOF(gcsQUEUE),
+                                         (gctPOINTER *) &record));
+
+        /* Append event record to event queue. */
+        gcmkONERROR(
+            gckEVENT_AddList(Event, &record->iface, gcvKERNEL_PIXEL, gcvTRUE));
+
+        /* Next record in the queue. */
+        next = record->next;
+
+        /* 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));
+
+    /* Success */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Roll back. */
+    if (record != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckOS_UnmapUserPointer(Event->os,
+                                             Queue,
+                                             gcmSIZEOF(gcsQUEUE),
+                                             (gctPOINTER *) record));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckEVENT_Interrupt(
+    IN gckEVENT Event,
+    IN gctUINT32 Data
+    )
+{
+    gcmkHEADER_ARG("Event=0x%x Data=%08x", Event, Data);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+    /* Combine current interrupt status with pending flags. */
+    Event->pending |= Data;
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+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;
+    gctBOOL empty = gcvFALSE, idle = gcvFALSE;
+
+    gcmkHEADER_ARG("Event=0x%x", Event);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+    for (;;)
+    {
+        /* Suspend interrupts. */
+        gcmkONERROR(gckOS_SuspendInterrupt(Event->os));
+        suspended = gcvTRUE;
+
+        /* Get current interrupts. */
+        pending = Event->pending;
+
+        /* Resume interrupts. */
+        gcmkONERROR(gckOS_ResumeInterrupt(Event->os));
+        suspended = gcvFALSE;
+
+        if (pending == 0)
+        {
+            /* No more pending interrupts - done. */
+            break;
+        }
+
+        gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+                       "Pending interrupts 0x%08x", pending);
+
+        queue = gcvNULL;
+
+#if gcdDEBUG
+        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);
+            }
+        }
+#endif
+
+        /* 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;
+                }
+            }
+        }
+
+        if (queue == gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_EVENT,
+                           "Interrupts 0x08x are not pending.", pending);
+
+            /* Suspend interrupts. */
+            gcmkONERROR(gckOS_SuspendInterrupt(Event->os));
+            suspended = gcvTRUE;
+
+            /* Mark pending interrupts as handled. */
+            Event->pending &= ~pending;
+
+            /* Resume interrupts. */
+            gcmkONERROR(gckOS_ResumeInterrupt(Event->os));
+            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(gcvLEVEL_ERROR,
+                          "Event %d lost (stamp %llu)",
+                          i, Event->queues[i].stamp);
+
+                /* Use this event instead. */
+                queue = &Event->queues[i];
+                mask  = 0;
+            }
+        }
+
+        /* Walk all events for this interrupt. */
+        while (queue->head != gcvNULL)
+        {
+            gcsEVENT_PTR event;
+#ifndef __QNXNTO__
+            gctPOINTER logical;
+#endif
+
+            event       = queue->head;
+
+            /* Dispatch on event type. */
+            switch (event->event.command)
+            {
+            case gcvHAL_FREE_NON_PAGED_MEMORY:
+                /* Free non-paged memory. */
+                status = gckOS_FreeNonPagedMemory(
+                            Event->os,
+                            event->event.u.FreeNonPagedMemory.bytes,
+                            event->event.u.FreeNonPagedMemory.physical,
+                            event->event.u.FreeNonPagedMemory.logical);
+                break;
+
+            case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+                /* Unmap the user memory. */
+                status = gckOS_FreeContiguous(
+                            Event->os,
+                            event->event.u.FreeContiguousMemory.physical,
+                            event->event.u.FreeContiguousMemory.logical,
+                            event->event.u.FreeContiguousMemory.bytes);
+                break;
+
+            case gcvHAL_FREE_VIDEO_MEMORY:
+#ifdef __QNXNTO__
+                node = event->event.u.FreeVideoMemory.node;
+                if ((node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+                &&  (node->VidMem.logical != gcvNULL)
+                )
+                {
+                    gcmkERR_BREAK(
+                        gckKERNEL_UnmapVideoMemory(event->kernel,
+                                                   node->VidMem.logical,
+                                                   event->event.pid,
+                                                   node->VidMem.bytes));
+                    node->VidMem.logical = gcvNULL;
+                }
+#endif
+
+                /* Free video memory. */
+                status = gckVIDMEM_Free(event->event.u.FreeVideoMemory.node);
+                break;
+
+            case gcvHAL_WRITE_DATA:
+#ifndef __QNXNTO__
+                /* Convert physical into logical address. */
+                gcmkERR_BREAK(
+                    gckOS_MapPhysical(Event->os,
+                                      event->event.u.WriteData.address,
+                                      gcmSIZEOF(gctUINT32),
+                                      &logical));
+
+                /* Write data. */
+                gcmkERR_BREAK(
+                    gckOS_WriteMemory(Event->os,
+                                      logical,
+                                      event->event.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)
+                                          event->event.u.WriteData.address,
+                                      event->event.u.WriteData.data));
+#endif
+                break;
+
+            case gcvHAL_UNLOCK_VIDEO_MEMORY:
+                /* Unlock. */
+                status = gckVIDMEM_Unlock(event->event.u.UnlockVideoMemory.node,
+                                          event->event.u.UnlockVideoMemory.type,
+                                          gcvNULL);
+                break;
+
+            case gcvHAL_SIGNAL:
+#ifdef __QNXNTO__
+                if ((event->event.u.Signal.coid == 0)
+                &&  (event->event.u.Signal.rcvid == 0)
+                )
+                {
+                    /* Kernel signal. */
+                    gcmkERR_BREAK(
+                        gckOS_Signal(Event->os,
+                                     event->event.u.Signal.signal,
+                                     gcvTRUE));
+                }
+                else
+                {
+                    /* User signal. */
+                    gcmkERR_BREAK(
+                        gckOS_UserSignal(Event->os,
+                                         event->event.u.Signal.signal,
+                                         event->event.u.Signal.rcvid,
+                                         event->event.u.Signal.coid));
+                }
+#else
+                /* Set signal. */
+                if (event->event.u.Signal.process == gcvNULL)
+                {
+                    /* Kernel signal. */
+                    gcmkERR_BREAK(
+                        gckOS_Signal(Event->os,
+                                     event->event.u.Signal.signal,
+                                     gcvTRUE));
+                }
+                else
+                {
+                    /* User signal. */
+                    gcmkERR_BREAK(
+                        gckOS_UserSignal(Event->os,
+                                         event->event.u.Signal.signal,
+                                         event->event.u.Signal.process));
+                }
+
+                gcmkASSERT(event->event.u.Signal.auxSignal == gcvNULL);
+#endif
+                break;
+
+            case gcvHAL_UNMAP_USER_MEMORY:
+                /* Unmap the user memory. */
+                status =
+                    gckOS_UnmapUserMemory(Event->os,
+                                          event->event.u.UnmapUserMemory.memory,
+                                          event->event.u.UnmapUserMemory.size,
+                                          event->event.u.UnmapUserMemory.info,
+                                          event->event.u.UnmapUserMemory.address);
+                break;
+
+            default:
+                /* Invalid argument. */
+                gcmkFATAL("Unknown event type: %d", event->event.command);
+                status = gcvSTATUS_INVALID_ARGUMENT;
+                break;
+            }
+
+            /* Make sure there are no errors generated. */
+            gcmkASSERT(gcmNO_ERROR(status));
+
+            /* Pop the event from the event queue. */
+            gcmkONERROR(
+                gckOS_AcquireMutex(Event->os, Event->mutexQueue, gcvINFINITE));
+            acquired = gcvTRUE;
+
+            /* Unlink head from chain. */
+            queue->head = event->next;
+
+            gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+            acquired = gcvFALSE;
+
+            /* Free the event. */
+            gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, event));
+        }
+
+        gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+                       "Handled interrupt 0x%08x", mask);
+
+        /* Suspend interrupts. */
+        gcmkONERROR(gckOS_SuspendInterrupt(Event->os));
+        suspended = gcvTRUE;
+
+        /* Mark pending interrupt as handled. */
+        Event->pending &= ~mask;
+
+        /* Resume interrupts. */
+        gcmkONERROR(gckOS_ResumeInterrupt(Event->os));
+        suspended = gcvFALSE;
+    }
+
+    /* 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:
+    if (acquired)
+    {
+        /* Release mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+    }
+
+    if (suspended)
+    {
+        /* Resume interrupts. */
+        gcmkVERIFY_OK(gckOS_ResumeInterrupt(Event->os));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckEVENT_Submit(
+    IN gckEVENT Event,
+    IN gctBOOL Wait
+    )
+{
+    gctUINT8 id = 0xFF;
+    gctSIZE_T bytes;
+    gctPOINTER buffer;
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gctBOOL reserved = gcvFALSE;
+#if gcdGPU_TIMEOUT
+    gctUINT32 timer = 0;
+#endif
+
+    gcmkHEADER_ARG("Event=0x%x Wait=%d", Event, Wait);
+
+    /* Only process if we have events queued. */
+    if (Event->list.head != gcvNULL)
+    {
+        for (;;)
+        {
+            /* Allocate an event ID. */
+            status = _GetEvent(Event, &id, Event->list.source);
+
+            if (gcmIS_ERROR(status))
+            {
+                /* Out of resources? */
+                if (Wait && (status == 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)
+                    {
+                        /* Try to call any outstanding events. */
+                        gcmkONERROR(
+                            gckHARDWARE_Interrupt(Event->kernel->hardware,
+                                                  gcvTRUE));
+                    }
+                    else if (timer > gcdGPU_TIMEOUT)
+                    {
+                        /* Broadcast GPU stuck. */
+                        gcmkONERROR(gckOS_Broadcast(Event->os,
+                                                    Event->kernel->hardware,
+                                                    gcvBROADCAST_GPU_STUCK));
+
+                        /* Bail out. */
+                        gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
+                    }
+#endif
+                }
+                else
+                {
+                    gcmkONERROR(status);
+                }
+            }
+            else
+            {
+                /* Got en event ID. */
+                break;
+            }
+        }
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_EVENT, "Using id=%d", id);
+
+        /* Acquire the list mutex. */
+        gcmkONERROR(gckOS_AcquireMutex(Event->os,
+                                       Event->listMutex,
+                                       gcvINFINITE));
+        acquired = gcvTRUE;
+
+        /* Copy event list to event ID queue. */
+        Event->queues[id].source = Event->list.source;
+        Event->queues[id].head   = Event->list.head;
+
+        /* Get process ID. */
+        gcmkONERROR(gckOS_GetProcessID(&Event->queues[id].processID));
+
+        /* Mark event list as empty. */
+        Event->list.head = gcvNULL;
+
+        /* Release the list mutex. */
+        gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->listMutex));
+        acquired = gcvFALSE;
+
+#if gcdNULL_DRIVER == 2
+        /* 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(Event->kernel->command,
+                                       bytes,
+                                       &buffer,
+                                       &bytes));
+        reserved = gcvTRUE;
+
+        /* 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(Event->kernel->command, bytes));
+        reserved = gcvFALSE;
+#endif
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Need to unroll the mutex acquire. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->listMutex));
+    }
+
+    if (reserved)
+    {
+        /* Need to release the command buffer. */
+        gcmkVERIFY_OK(gckCOMMAND_Release(Event->kernel->command));
+    }
+
+    if (id != 0xFF)
+    {
+        /* Need to unroll the event allocation. */
+        Event->queues[id].head = gcvNULL;
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
diff --git a/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_heap.c b/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_heap.c
new file mode 100644 (file)
index 0000000..e14e1c9
--- /dev/null
@@ -0,0 +1,1056 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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 gcdDEBUG
+       /* 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 gcdDEBUG
+       gctUINT64                                       timeStamp;
+#endif
+
+#if VIVANTE_PROFILER || gcdDEBUG
+       /* Profile information. */
+       gctUINT32                                       allocCount;
+       gctUINT64                                       allocBytes;
+       gctUINT64                                       allocBytesMax;
+       gctUINT64                                       allocBytesTotal;
+       gctUINT32                                       heapCount;
+       gctUINT32                                       heapCountMax;
+       gctUINT64                                       heapMemory;
+       gctUINT64                                       heapMemoryMax;
+#endif
+};
+
+/*******************************************************************************
+***** Static Support Functions *************************************************
+*******************************************************************************/
+
+#if gcdDEBUG
+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 || gcdDEBUG
+                       /* 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;
+
+       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),
+                                                        (gctPOINTER *) &heap));
+
+       /* Initialize the gckHEAP object. */
+       heap->object.type    = gcvOBJ_HEAP;
+       heap->os             = Os;
+       heap->allocationSize = AllocationSize;
+       heap->heap           = gcvNULL;
+#if gcdDEBUG
+       heap->timeStamp      = 0;
+#endif
+
+#if VIVANTE_PROFILER || gcdDEBUG
+       /* 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 gcdDEBUG
+       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 gcdDEBUG
+               /* 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 gcdDEBUG
+       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))
+       {
+               /* 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)
+                               {
+                                       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 gcdDEBUG
+                               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 || gcdDEBUG
+       /* 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 gcdDEBUG
+       used->timeStamp = ++Heap->timeStamp;
+#endif
+
+#if VIVANTE_PROFILER || gcdDEBUG
+       /* 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 || gcdDEBUG
+       /* 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 ****************************************************************
+*******************************************************************************/
+
+#if defined gcdHAL_TEST
+
+#include <stdlib.h>
+#define gcmRANDOM(n) (rand() % n)
+
+typedef struct
+{
+       gctSIZE_T       bytes;
+       gctPOINTER      memory;
+}
+gcskHEAP_TEST;
+
+gceSTATUS
+gckHEAP_Test(
+       IN gckHEAP Heap,
+       IN gctSIZE_T Vectors,
+       IN gctSIZE_T MaxSize
+       )
+{
+       gctSIZE_T nodeCount = MaxSize / 4;
+       gcskHEAP_TEST * nodes = gcvNULL;
+       gctSIZE_T bytes, index, i;
+       gceSTATUS status, failure = gcvSTATUS_OK;
+       gctUINT8_PTR memory;
+       gcskHEAP_PTR heap, current;
+
+       /* Allocate the node array. */
+       gcmkONERROR(
+               gckOS_AllocateMemory(Heap->os,
+                                                        nodeCount * gcmSIZEOF(gcskHEAP_TEST),
+                                                        (gctPOINTER *) &nodes));
+
+       /* Mark all nodes as free. */
+       gcmkONERROR(
+               gckOS_ZeroMemory(nodes, nodeCount * gcmSIZEOF(gcskHEAP_TEST)));
+
+       gcmkONERROR(gckHEAP_ProfileStart(Heap));
+
+       /* Loop through all vectors. */
+       while (Vectors-- > 0)
+       {
+               /* Get a random index. */
+               index = gcmRANDOM(nodeCount);
+
+               /* Test if we need to allocate pages. */
+               if (nodes[index].bytes == 0)
+               {
+                       /* Generate a random byte size. */
+                       do
+                       {
+                               bytes = gcmALIGN(gcmRANDOM(MaxSize), gcmSIZEOF(gctSIZE_T));
+                       }
+                       while (bytes == 0);
+
+                       /* Allocate pages. */
+                       status = gckHEAP_Allocate(Heap, bytes, (gctPOINTER *) &memory);
+
+                       if (gcmIS_SUCCESS(status))
+                       {
+                               /* Mark node as allocated. */
+                               nodes[index].bytes  = bytes;
+                               nodes[index].memory = memory;
+
+                               /* Put signature in the memory. */
+                               for (i = 0; i < bytes; i += gcmSIZEOF(gctSIZE_T))
+                               {
+                                       *(gctSIZE_T_PTR) (memory + i) = index;
+                               }
+                       }
+                       else
+                       {
+                               gcmkTRACE(gcvLEVEL_WARNING,
+                                                 "%s(%d): Failed to allocate %lu bytes",
+                                                 __FUNCTION__, __LINE__, bytes);
+                       }
+               }
+               else
+               {
+                       /* Verify the memory. */
+                       memory = nodes[index].memory;
+                       for (i = 0; i < nodes[index].bytes; i += gcmSIZEOF(gctSIZE_T))
+                       {
+                               if (*(gctSIZE_T_PTR) (memory + i) != index)
+                               {
+                                       gcmkFATAL("%s(%d): Corruption detected at index %lu",
+                                                         __FUNCTION__, __LINE__, index);
+
+                                       failure = gcvSTATUS_HEAP_CORRUPTED;
+                               }
+                       }
+
+                       /* Free the memory. */
+                       status = gckHEAP_Free(Heap, memory);
+
+                       if (gcmIS_ERROR(status))
+                       {
+                               gcmkFATAL("%s(%d): Cannot free %lu bytes at 0x%x (index=%lu)",
+                                                 __FUNCTION__, __LINE__,
+                                                 nodes[index].bytes, memory, index);
+
+                               failure = status;
+                       }
+
+                       /* Mark the node as free. */
+                       nodes[index].bytes = 0;
+               }
+
+               /* Verify the heap chain. */
+               i = 0;
+               for (current = Heap->heap; current != gcvNULL; current = current->next)
+               {
+                       gctSIZE_T j;
+                       for (heap = Heap->heap, j = 0; j < i; heap = heap->next, ++j)
+                       {
+                               if (heap == current)
+                               {
+                                       gcmkFATAL("%s(%d): Linked list corrupted for heap 0x%x",
+                                                         __FUNCTION__, __LINE__, current);
+
+                                       failure = gcvSTATUS_HEAP_CORRUPTED;
+                               }
+                       }
+
+                       if (heap != current)
+                       {
+                               gcmkFATAL("%s(%d): Linked list corrupted for heap 0x%x",
+                                                 __FUNCTION__, __LINE__, current);
+
+                               failure = gcvSTATUS_HEAP_CORRUPTED;
+                       }
+
+                       ++i;
+               }
+       }
+
+       /* Walk the entire array of nodes. */
+       for (index = 0; index < nodeCount; ++index)
+       {
+               /* Test if we need to free pages. */
+               if (nodes[index].bytes != 0)
+               {
+                       /* Verify the memory. */
+                       memory = nodes[index].memory;
+                       for (i = 0; i < nodes[index].bytes; i += gcmSIZEOF(gctSIZE_T))
+                       {
+                               if (*(gctSIZE_T_PTR) (memory + i) != index)
+                               {
+                                       gcmkFATAL("%s(%d): Corruption detected at page %lu",
+                                                         __FUNCTION__, __LINE__, index);
+
+                                       failure = gcvSTATUS_HEAP_CORRUPTED;
+                               }
+                       }
+
+                       /* Free the memory. */
+                       status = gckHEAP_Free(Heap, memory);
+
+                       if (gcmIS_ERROR(status))
+                       {
+                               gcmkFATAL("%s(%d): Cannot free %u bytes at 0x%x (index=%lu)",
+                                                 __FUNCTION__, __LINE__,
+                                                 nodes[index].bytes, memory, index);
+
+                               failure = status;
+                       }
+               }
+       }
+
+       /* Perform garbage collection. */
+       gcmkONERROR(_CompactKernelHeap(Heap));
+
+       /* Show profiling. */
+       gcmkONERROR(gckHEAP_ProfileEnd(Heap, "Profile"));
+
+       /* Verify we did not loose any nodes. */
+       if (Heap->heap != gcvNULL)
+       {
+               gcmkFATAL("%s(%d): Detected leaking in the heap.",
+                                 __FUNCTION__, __LINE__);
+
+               failure = gcvSTATUS_HEAP_CORRUPTED;
+       }
+
+OnError:
+       /* Roll back. */
+       if (nodes != gcvNULL)
+       {
+               gcmkVERIFY_OK(
+                       gckOS_FreeMemory(Heap->os, nodes));
+       }
+
+       /* Return the status. */
+       gcmkFOOTER();
+       return status;
+}
+#endif
+
diff --git a/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_mmu.c b/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_mmu.c
new file mode 100644 (file)
index 0000000..ed77149
--- /dev/null
@@ -0,0 +1,928 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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;
+
+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] = (~0U << 8) | 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;
+}
+
+/*******************************************************************************
+**
+**     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;
+
+       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), (gctPOINTER *) &mmu));
+
+       /* Initialize the gckMMU object. */
+       mmu->object.type      = gcvOBJ_MMU;
+       mmu->os               = os;
+       mmu->hardware         = hardware;
+       mmu->pageTableMutex   = gcvNULL;
+       mmu->pageTableLogical = gcvNULL;
+#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
+
+       /* Allocate the page table (not more than 256 kB). */
+       mmu->pageTableSize = gcmMIN(MmuSize, 256 << 10);
+       gcmkONERROR(
+               gckOS_AllocateContiguous(os,
+                                                                gcvFALSE,
+                                                                &mmu->pageTableSize,
+                                                                &mmu->pageTablePhysical,
+                                                                (gctPOINTER *) &mmu->pageTableLogical));
+
+       /* 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));
+
+       /* 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(gckOS_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, gcvNULL));
+       }
+#endif
+
+       /* 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(gckOS_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 (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;
+
+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
+       )
+{
+       gctUINT32_PTR pageTable;
+
+       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);
+
+       /* Convert the pointer. */
+       pageTable = (gctUINT32_PTR) PageTable;
+
+       if (PageCount == 1)
+       {
+               /* Single page node. */
+               pageTable[0] = (~0U << 8) | 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;
+}
+
+#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 gckMMU Mmu,
+    IN gctHANDLE Handle
+    )
+{
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+    gcuVIDMEM_NODE_PTR curr, next;
+
+    gcmkHEADER_ARG("Mmu=0x%x Handle=0x%x", Mmu, Handle);
+
+    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.handle == Handle)
+        {
+            while (curr->Virtual.locked > 0 || curr->Virtual.unlockPending)
+            {
+                gcmkONERROR(gckVIDMEM_Unlock(curr, gcvSURF_TYPE_UNKNOWN, gcvNULL, gcvNULL));
+            }
+
+            gcmkVERIFY_OK(gckVIDMEM_Free(curr, gcvNULL));
+        }
+    }
+
+    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 ******************************
+******************************************************************************/
+
+#if defined gcdHAL_TEST
+
+#include <stdlib.h>
+#define gcmRANDOM(n) (rand() % n)
+
+typedef struct
+{
+       gctSIZE_T pageCount;
+       gctUINT32_PTR pageTable;
+}
+gcsMMU_TEST;
+
+gceSTATUS
+gckMMU_Test(
+       IN gckMMU Mmu,
+       IN gctSIZE_T Vectors,
+       IN gctINT MaxSize
+       )
+{
+       const gctINT nodeCount = MaxSize / 4;
+       gcsMMU_TEST * nodes = gcvNULL;
+       gceSTATUS status, failure = gcvSTATUS_OK;
+       gctSIZE_T i, count;
+       gctUINT32_PTR pageTable;
+       gctINT index;
+
+       /* Allocate the node array. */
+       gcmkONERROR(
+               gckOS_Allocate(Mmu->os,
+                                          nodeCount * gcmSIZEOF(gcsMMU_TEST),
+                                          (gctPOINTER *) &nodes));
+
+       /* Mark all nodes as free. */
+       gcmkONERROR(
+               gckOS_ZeroMemory(nodes, nodeCount * gcmSIZEOF(gcsMMU_TEST)));
+
+       /* Loop through all vectors. */
+       while (Vectors-- > 0)
+       {
+               /* Get a random index. */
+               index = gcmRANDOM(nodeCount);
+
+               /* Test if we need to allocate pages. */
+               if (nodes[index].pageCount == 0)
+               {
+                       /* Generate a random page count. */
+                       do
+                       {
+                               count = gcmRANDOM(MaxSize);
+                       }
+                       while (count == 0);
+
+                       /* Allocate pages. */
+                       status = gckMMU_AllocatePages(Mmu,
+                                                                                 count,
+                                                                                 (gctPOINTER *) &pageTable,
+                                                                                 gcvNULL);
+
+                       if (gcmIS_SUCCESS(status))
+                       {
+                               /* Mark node as allocated. */
+                               nodes[index].pageCount = count;
+                               nodes[index].pageTable = pageTable;
+
+                               /* Put signature in the page table. */
+                               for (i = 0; i < count; ++i)
+                               {
+                                       pageTable[i] = (index << 8) | gcvMMU_USED;
+                               }
+                       }
+                       else
+                       {
+                               gcmkTRACE(gcvLEVEL_WARNING,
+                                                "gckMMU_Test: Failed to allocate %u pages",
+                                                count);
+                       }
+               }
+               else
+               {
+                       /* Verify the page table. */
+                       pageTable = nodes[index].pageTable;
+                       for (i = 0; i < nodes[index].pageCount; ++i)
+                       {
+                               if (pageTable[i] != ((index << 8) | gcvMMU_USED))
+                               {
+                                       gcmkFATAL("gckMMU_Test: Corruption detected at page %u",
+                                                        index);
+
+                                       failure = gcvSTATUS_HEAP_CORRUPTED;
+                               }
+                       }
+
+                       /* Free the pages. */
+                       status = gckMMU_FreePages(Mmu, pageTable, nodes[index].pageCount);
+
+                       if (gcmIS_ERROR(status))
+                       {
+                               gcmkFATAL("gckMMU_Test: Cannot free %u pages at 0x%x (index=%u)",
+                                                nodes[index].pageCount, pageTable, index);
+
+                               failure = status;
+                       }
+
+                       /* Mark the node as free. */
+                       nodes[index].pageCount = 0;
+               }
+       }
+
+       /* Walk the entire array of nodes. */
+       for (index = 0; index < nodeCount; ++index)
+       {
+               /* Test if we need to free pages. */
+               if (nodes[index].pageCount != 0)
+               {
+                       /* Verify the page table. */
+                       pageTable = nodes[index].pageTable;
+                       for (i = 0; i < nodes[index].pageCount; ++i)
+                       {
+                               if (pageTable[i] != ((index << 8) | gcvMMU_USED))
+                               {
+                                       gcmkFATAL("gckMMU_Test: Corruption detected at page %u",
+                                                        index);
+
+                                       failure = gcvSTATUS_HEAP_CORRUPTED;
+                               }
+                       }
+
+                       /* Free the pages. */
+                       status = gckMMU_FreePages(Mmu, pageTable, nodes[index].pageCount);
+
+                       if (gcmIS_ERROR(status))
+                       {
+                               gcmkFATAL("gckMMU_Test: Cannot free %u pages at 0x%x (index=%u)",
+                                                nodes[index].pageCount, pageTable, index);
+
+                               failure = status;
+                       }
+               }
+       }
+
+       /* Perform garbage collection. */
+       gcmkONERROR(_Collect(Mmu));
+
+       /* Verify we did not loose any nodes. */
+       if ((Mmu->heapList != 0)
+       ||  ((Mmu->pageTableLogical[0] & 0xFF) != gcvMMU_FREE)
+       ||  (Mmu->pageTableEntries != (Mmu->pageTableLogical[0] >> 8))
+       )
+       {
+               gcmkFATAL("gckMMU_Test: Detected leaking in the page table.");
+
+               failure = gcvSTATUS_HEAP_CORRUPTED;
+       }
+
+OnError:
+       /* Free the array of nodes. */
+       if (nodes != gcvNULL)
+       {
+               gcmkVERIFY_OK(gckOS_Free(Mmu->os, nodes));
+       }
+
+       /* Return test status. */
+       return failure;
+}
+#endif
+
diff --git a/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_precomp.h b/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_precomp.h
new file mode 100644 (file)
index 0000000..0379a75
--- /dev/null
@@ -0,0 +1,32 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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/staging/rk29/vivante/hal/kernel/gc_hal_kernel_video_memory.c b/drivers/staging/rk29/vivante/hal/kernel/gc_hal_kernel_video_memory.c
new file mode 100644 (file)
index 0000000..3adb5c6
--- /dev/null
@@ -0,0 +1,1754 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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;
+
+    /* 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),
+                                   (gctPOINTER *) &node)))
+    {
+        /* Error. */
+        return gcvFALSE;
+    }
+
+    /* 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__
+    node->VidMem.logical   = gcvNULL;
+    node->VidMem.handle    = 0;
+#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;
+
+    /* Save pointer to next node. */
+    node = Node->VidMem.next;
+
+    /* 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;
+    }
+
+    /* 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. */
+    return gckOS_Free(Os, node);
+}
+
+/******************************************************************************\
+******************************* 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,
+#ifdef __QNXNTO__
+    IN gctHANDLE Handle,
+#endif
+    OUT gcuVIDMEM_NODE_PTR * Node
+    )
+{
+    gckOS os;
+    gceSTATUS status;
+    gcuVIDMEM_NODE_PTR node = gcvNULL;
+
+    gcmkHEADER_ARG("Kernel=0x%x Bytes=%lu", Kernel, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+#ifdef __QNXNTO__
+    gcmkVERIFY_ARGUMENT(Handle != gcvNULL);
+#endif
+
+    /* 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), (gctPOINTER *) &node));
+
+    /* Initialize gcuVIDMEM_NODE union for virtual memory. */
+    node->Virtual.kernel        = Kernel;
+    node->Virtual.contiguous    = Contiguous;
+    node->Virtual.locked        = 0;
+    node->Virtual.logical       = gcvNULL;
+    node->Virtual.pageTable     = gcvNULL;
+    node->Virtual.mutex         = gcvNULL;
+#ifdef __QNXNTO__
+    node->Virtual.next          = gcvNULL;
+    node->Virtual.unlockPending = gcvFALSE;
+    node->Virtual.freePending   = gcvFALSE;
+    node->Virtual.handle        = Handle;
+#else
+    node->Virtual.pending       = gcvFALSE;
+#endif
+
+    /* 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(gckOS_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;
+
+    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));
+
+    /* Free virtual memory. */
+    gcmkVERIFY_OK(
+            gckOS_FreePagedMemory(os,
+                                  Node->Virtual.physical,
+                                  Node->Virtual.bytes));
+#endif
+
+    /* Delete the mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(os, Node->Virtual.mutex));
+
+    if (Node->Virtual.pageTable != gcvNULL)
+    {
+        /* Free the pages. */
+        gcmkVERIFY_OK(gckMMU_FreePages(Node->Virtual.kernel->mmu,
+                                       Node->Virtual.pageTable,
+                                       Node->Virtual.pageCount));
+    }
+
+    /* Delete the gcuVIDMEM_NODE union. */
+    gcmkVERIFY_OK(gckOS_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;
+
+    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),
+                       (gctPOINTER *) &memory));
+
+    /* 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;
+
+    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),
+                           (gctPOINTER *) &node));
+
+        /* 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__
+        node->VidMem.logical   = gcvNULL;
+        node->VidMem.handle    = 0;
+#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;
+
+    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(gckOS_Free(Os, memory->sentinel[i].VidMem.next));
+        }
+
+        /* Free the object. */
+        gcmkVERIFY_OK(gckOS_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(gckOS_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(gckOS_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,
+#ifdef __QNXNTO__
+    IN gctHANDLE Handle,
+#endif
+    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);
+#ifdef __QNXNTO__
+    gcmkVERIFY_ARGUMENT(Handle != gcvNULL);
+#endif
+
+    /* Compute linear size. */
+    bytes = Width * Height * Depth * BytesPerPixel;
+
+    /* Allocate through linear function. */
+#ifdef __QNXNTO__
+    gcmkONERROR(
+        gckVIDMEM_AllocateLinear(Memory, bytes, Alignment, Type, Handle, Node));
+#else
+    gcmkONERROR(
+        gckVIDMEM_AllocateLinear(Memory, bytes, Alignment, Type, Node));
+#endif
+
+    /* 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 OUT gctUINT32_PTR Alignment
+    )
+{
+    gcuVIDMEM_NODE_PTR node;
+    gctUINT32 alignment;
+
+    /* 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)
+    {
+        /* 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)
+        {
+            /* This node is big enough. */
+            *Alignment = alignment;
+            return node;
+        }
+    }
+
+    /* 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,
+#ifdef __QNXNTO__
+    IN gctHANDLE Handle,
+#endif
+    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);
+#ifdef __QNXNTO__
+    gcmkVERIFY_ARGUMENT(Handle != gcvNULL);
+#endif
+
+    /* Acquire the mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
+
+    acquired = gcvTRUE;
+
+    if (Bytes > Memory->freeBytes)
+    {
+        /* Not enough memory. */
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    /* Find the default bank for this surface type. */
+    gcmkASSERT((gctINT) Type < gcmCOUNTOF(Memory->mapping));
+    bank      = Memory->mapping[Type];
+    alignment = Alignment;
+
+    /* Find a free node in the default bank. */
+    node = _FindNode(Memory, bank, Bytes, &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, &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, &alignment);
+            if (node != gcvNULL)
+            {
+                break;
+            }
+        }
+    }
+
+    if (node == gcvNULL)
+    {
+        /* Out of memory. */
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    /* 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__
+    node->VidMem.logical   = gcvNULL;
+    node->VidMem.handle    = Handle;
+#endif
+
+    /* Adjust the number of free bytes. */
+    Memory->freeBytes -= node->VidMem.bytes;
+
+    /* 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
+    )
+{
+    gckVIDMEM memory = gcvNULL;
+    gcuVIDMEM_NODE_PTR node;
+    gceSTATUS status;
+    gctBOOL acquired = gcvFALSE;
+
+    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)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_VIDMEM,
+                           "Node 0x%x is locked (%d)",
+                           Node, Node->VidMem.locked);
+
+            /* Node is locked. */
+            gcmkONERROR(gcvSTATUS_MEMORY_LOCKED);
+        }
+
+        /* Extract pointer to gckVIDMEM object owning the node. */
+        memory = Node->VidMem.memory;
+
+        /* Acquire the mutex. */
+        gcmkONERROR(
+            gckOS_AcquireMutex(memory->os, memory->mutex, gcvINFINITE));
+
+        acquired = gcvTRUE;
+
+#ifdef __QNXNTO__
+        /* Reset handle to 0. */
+        Node->VidMem.logical = gcvNULL;
+        Node->VidMem.handle = 0;
+
+        /* Don't try to a 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->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));
+
+        /* Success. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+    /*************************** Virtual Memory *******************************/
+
+    /* Verify the gckKERNEL object pointer. */
+    gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
+
+#ifdef __QNXNTO__
+    if (!Node->Virtual.unlockPending && (Node->Virtual.locked > 0))
+#else
+    if (!Node->Virtual.pending && (Node->Virtual.locked > 0))
+#endif
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_VIDMEM,
+                       "gckVIDMEM_Free: Virtual node 0x%x is locked (%d)",
+                       Node, Node->Virtual.locked);
+
+        /* Node is locked. */
+        gcmkONERROR(gcvSTATUS_MEMORY_LOCKED);
+    }
+
+#ifdef __QNXNTO__
+    if (!Node->Virtual.freePending) { if (Node->Virtual.unlockPending)
+#else
+    if (Node->Virtual.pending)
+#endif
+    {
+        gcmkASSERT(Node->Virtual.locked == 1);
+
+        /* Schedule the node to be freed. */
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                       "gckVIDMEM_Free: Scheduling node 0x%x to be freed later",
+                       Node);
+
+        /* Schedule the video memory to be freed again. */
+        gcmkONERROR(gckEVENT_FreeVideoMemory(Node->Virtual.kernel->event,
+                                             Node,
+                                             gcvKERNEL_PIXEL));
+
+#ifdef __QNXNTO__
+        Node->Virtual.freePending = gcvTRUE; }
+#endif
+
+        /* Success. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_SKIP;
+    }
+
+    else
+    {
+        /* Free the virtual memory. */
+        gcmkVERIFY_OK(gckOS_FreePagedMemory(Node->Virtual.kernel->os,
+                                            Node->Virtual.physical,
+                                            Node->Virtual.bytes));
+
+        /* Destroy the gcuVIDMEM_NODE union. */
+        gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node));
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->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 gckVIDMEM Memory,
+    IN gctHANDLE Handle
+    )
+{
+    gceSTATUS status;
+    gctBOOL mutex = gcvFALSE;
+    gcuVIDMEM_NODE_PTR node;
+    gctINT i;
+    gctUINT32 nodeCount = 0, byteCount = 0;
+    gctBOOL again;
+
+    gcmkHEADER_ARG("Memory=0x%x Handle=0x%x", Memory, Handle);
+
+    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.handle == Handle)
+                {
+                    /* Unlock video memory. */
+                    while (gckVIDMEM_Unlock(node, gcvSURF_TYPE_UNKNOWN, gcvNULL, gcvNULL)
+                        != gcvSTATUS_MEMORY_UNLOCKED)
+                        ;
+
+                    nodeCount++;
+                    byteCount += node->VidMem.bytes;
+
+                    /* Free video memory. */
+                    gcmkVERIFY_OK(gckVIDMEM_Free(node, gcvNULL));
+
+                    /*
+                     * Freeing may cause a merge which will invalidate our iteration.
+                     * Don't be clever, just restart.
+                     */
+                    again = gcvTRUE;
+
+                    break;
+                }
+            }
+        }
+        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 it's hardware specific address.
+**
+**  INPUT:
+**
+**      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 gcuVIDMEM_NODE_PTR Node,
+    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)
+    {
+        /* Increment the lock count. */
+        Node->VidMem.locked ++;
+
+        /* Return the address of the node. */
+        *Address = Node->VidMem.memory->baseAddress
+                 + Node->VidMem.offset
+                 + Node->VidMem.alignment;
+
+        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;
+
+        /* Increment the lock count. */
+        if (Node->Virtual.locked ++ == 0)
+        {
+            /* Is this node pending for a final unlock? */
+#ifdef __QNXNTO__
+            if (!Node->Virtual.contiguous && Node->Virtual.unlockPending)
+#else
+            if (!Node->Virtual.contiguous && Node->Virtual.pending)
+#endif
+            {
+                /* Make sure we have a page table. */
+                gcmkASSERT(Node->Virtual.pageTable != gcvNULL);
+
+                /* Remove pending unlock. */
+#ifdef __QNXNTO__
+                Node->Virtual.unlockPending = gcvFALSE;
+#else
+                Node->Virtual.pending = gcvFALSE;
+#endif
+            }
+
+            /* First lock - create a page table. */
+            gcmkASSERT(Node->Virtual.pageTable == gcvNULL);
+
+            /* Make sure we mark our node as not flushed. */
+#ifdef __QNXNTO__
+            Node->Virtual.unlockPending = gcvFALSE;
+#else
+            Node->Virtual.pending = gcvFALSE;
+#endif
+
+            /* Lock the allocated pages. */
+#ifdef __QNXNTO__
+            gcmkONERROR(
+                gckOS_LockPages(os,
+                                Node->Virtual.physical,
+                                Node->Virtual.bytes,
+                                Node->Virtual.userPID,
+                                &Node->Virtual.logical,
+                                &Node->Virtual.pageCount));
+#else
+            gcmkONERROR(
+                gckOS_LockPages(os,
+                                Node->Virtual.physical,
+                                Node->Virtual.bytes,
+                                &Node->Virtual.logical,
+                                &Node->Virtual.pageCount));
+#endif
+
+            locked = gcvTRUE;
+
+            if (Node->Virtual.contiguous)
+            {
+                /* Get physical address directly */
+                gcmkONERROR(gckOS_GetPhysicalAddress(os,
+                                    Node->Virtual.logical,
+                                    &Node->Virtual.address));
+            }
+            else
+            {
+                /* Allocate pages inside the MMU. */
+                gcmkONERROR(
+                    gckMMU_AllocatePages(Node->Virtual.kernel->mmu,
+                                         Node->Virtual.pageCount,
+                                         &Node->Virtual.pageTable,
+                                         &Node->Virtual.address));
+
+                /* Map the pages. */
+#ifdef __QNXNTO__
+                gcmkONERROR(
+                    gckOS_MapPages(os,
+                                   Node->Virtual.physical,
+                                   Node->Virtual.logical,
+                                   Node->Virtual.pageCount,
+                                   Node->Virtual.pageTable));
+#else
+                gcmkONERROR(
+                    gckOS_MapPages(os,
+                                   Node->Virtual.physical,
+                                   Node->Virtual.pageCount,
+                                   Node->Virtual.pageTable));
+#endif
+
+                gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                               "Mapped virtual node 0x%x to 0x%08X",
+                               Node,
+                               Node->Virtual.address);
+            }
+        }
+
+        /* Return hardware address. */
+        *Address = Node->Virtual.address;
+
+        /* 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.pageTable != gcvNULL)
+        {
+            /* Free the pages from the MMU. */
+            gcmkVERIFY_OK(
+                gckMMU_FreePages(Node->Virtual.kernel->mmu,
+                                 Node->Virtual.pageTable,
+                                 Node->Virtual.pageCount));
+
+            Node->Virtual.pageTable = gcvNULL;
+        }
+
+        /* Unlock the pages. */
+#ifdef __QNXNTO__
+        gcmkVERIFY_OK(
+            gckOS_UnlockPages(os,
+                              Node->Virtual.physical,
+                              Node->Virtual.userPID,
+                              Node->Virtual.bytes,
+                              Node->Virtual.logical));
+#else
+        gcmkVERIFY_OK(
+            gckOS_UnlockPages(os,
+                              Node->Virtual.physical,
+                              Node->Virtual.bytes,
+                              Node->Virtual.logical));
+#endif
+    }
+
+    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:
+**
+**      gcuVIDMEM_NODE_PTR Node
+**          Pointer to a locked gcuVIDMEM_NODE union.
+**
+**      gceSURF_TYPE Type
+**          Type of surface to unlock.
+**
+**      gctSIZE_T * CommandSize
+**          Pointer to a variable specifying the number of bytes in the command
+**          buffer specified by 'Commands'.  If gcvNULL, there is no command
+**          buffer and the video memory shoud be unlocked synchronously.
+**
+**      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 gcuVIDMEM_NODE_PTR Node,
+    IN gceSURF_TYPE Type,
+    IN OUT gctBOOL * Asynchroneous
+    )
+{
+    gceSTATUS status;
+    gckKERNEL kernel;
+    gckHARDWARE hardware;
+    gctPOINTER buffer;
+    gctSIZE_T requested, bufferSize;
+    gckCOMMAND command = gcvNULL;
+    gceKERNEL_FLUSH flush;
+    gckOS os = gcvNULL;
+    gctBOOL acquired = gcvFALSE;
+    gctBOOL needRelease = gcvFALSE;
+    gctBOOL pendingUnlock = gcvFALSE;
+
+    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. */
+            gcmkONERROR(gcvSTATUS_MEMORY_UNLOCKED);
+        }
+
+        /* Decrement the lock count. */
+        Node->VidMem.locked --;
+
+        if (Asynchroneous != gcvNULL)
+        {
+            /* No need for any events. */
+            *Asynchroneous = gcvFALSE;
+        }
+    }
+
+    /*************************** Virtual Memory *******************************/
+
+    else
+    {
+        /* Verify the gckKERNEL object pointer. */
+        kernel = Node->Virtual.kernel;
+        gcmkVERIFY_OBJECT(kernel, gcvOBJ_KERNEL);
+
+        /* Verify the gckHARDWARE object pointer. */
+        hardware = Node->Virtual.kernel->hardware;
+        gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+        /* Verify the gckCOMMAND object pointer. */
+        command = Node->Virtual.kernel->command;
+        gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
+        if (Asynchroneous == gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                           "gckVIDMEM_Unlock: Unlocking virtual node 0x%x (%d)",
+                           Node,
+                           Node->Virtual.locked);
+
+            /* Get the gckOS object pointer. */
+            os = kernel->os;
+            gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+            /* Grab the mutex. */
+            gcmkONERROR(
+                gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
+
+            /* 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.  We also need to stall to make sure the flush has
+            ** happened.  However - when we get to this point we are inside
+            ** the interrupt handler and we cannot just gckCOMMAND_Wait
+            ** because it will wait forever.  So - what we do here is we
+            ** verify the type of the surface, flush the appropriate cache,
+            ** mark the node as flushed, and issue another unlock to unmap
+            ** the MMU. */
+            if (!Node->Virtual.contiguous
+            &&  (Node->Virtual.locked == 1)
+#ifdef __QNXTO__
+            &&  !Node->Virtual.unlockPending
+#else
+            &&  !Node->Virtual.pending
+#endif
+            )
+            {
+                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)
+                {
+                    gcmkONERROR(
+                        gckCOMMAND_Reserve(command,
+                                           requested,
+                                           &buffer,
+                                           &bufferSize));
+
+                    needRelease = gcvTRUE;
+
+                    gcmkONERROR(gckHARDWARE_Flush(hardware,
+                                                  flush,
+                                                  buffer,
+                                                  &bufferSize));
+
+                    gcmkONERROR(
+                        gckEVENT_Unlock(Node->Virtual.kernel->event,
+                                        gcvKERNEL_PIXEL,
+                                        Node,
+                                        Type));
+
+                    /* Mark node as pending. */
+#ifdef __QNXNTO__
+                    Node->Virtual.unlockPending = gcvTRUE;
+#else
+                    Node->Virtual.pending = gcvTRUE;
+#endif
+
+                    needRelease = gcvFALSE;
+
+                    gcmkONERROR(gckCOMMAND_Execute(command, requested));
+
+                    pendingUnlock = gcvTRUE;
+                }
+            }
+
+            if (!pendingUnlock)
+            {
+                               if (Node->Virtual.locked == 0)
+                               {
+                                       status = gcvSTATUS_MEMORY_UNLOCKED;
+                                       goto OnError;
+                               }
+
+                /* Decrement lock count. */
+                -- Node->Virtual.locked;
+
+                /* See if we can unlock the resources. */
+                if (Node->Virtual.locked == 0)
+                {
+                    /* Unlock the pages. */
+#ifdef __QNXNTO__
+                    gcmkONERROR(
+                        gckOS_UnlockPages(os,
+                                          Node->Virtual.physical,
+                                          Node->Virtual.userPID,
+                                          Node->Virtual.bytes,
+                                          Node->Virtual.logical));
+#else
+                    gcmkONERROR(
+                        gckOS_UnlockPages(os,
+                                          Node->Virtual.physical,
+                                          Node->Virtual.bytes,
+                                          Node->Virtual.logical));
+#endif
+
+                    /* Free the page table. */
+                    if (Node->Virtual.pageTable != gcvNULL)
+                    {
+                        gcmkONERROR(
+                            gckMMU_FreePages(Node->Virtual.kernel->mmu,
+                                             Node->Virtual.pageTable,
+                                             Node->Virtual.pageCount));
+
+                        /* Mark page table as freed. */
+                        Node->Virtual.pageTable = gcvNULL;
+                    }
+
+                    /* Mark node as unlocked. */
+#ifdef __QNXTO
+                    Node->Virtual.unlockPending = gcvFALSE;
+#else
+                    Node->Virtual.pending = gcvFALSE;
+#endif
+                }
+
+                gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                               "Unmapped virtual node 0x%x from 0x%08X",
+                               Node, Node->Virtual.address);
+            }
+
+            /* Release the mutex. */
+            gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+        }
+
+        else
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                           "Scheduled unlock for virtual node 0x%x",
+                           Node);
+
+            /* Schedule the surface to be unlocked. */
+            *Asynchroneous = gcvTRUE;
+        }
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Asynchroneous=%d", gcmOPT_VALUE(Asynchroneous));
+    return gcvSTATUS_OK;
+
+OnError:
+    if (needRelease)
+    {
+        gcmkVERIFY_OK(gckCOMMAND_Release(command));
+    }
+
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+    }
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+#ifdef __QNXNTO__
+/* Set the allocating process' PID for this node. */
+gceSTATUS
+gckVIDMEM_SetPID(
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctUINT32 Pid
+    )
+{
+    if (Node != gcvNULL)
+    {
+        if (Node->VidMem.memory->object.type != gcvOBJ_VIDMEM)
+        {
+            Node->Virtual.userPID = Pid;
+        }
+
+    }
+    else
+    {
+        return gcvSTATUS_INVALID_OBJECT;
+    }
+
+    return gcvSTATUS_OK;
+}
+#endif
+
diff --git a/drivers/staging/rk29/vivante/hal/kernel/makefile.linux b/drivers/staging/rk29/vivante/hal/kernel/makefile.linux
new file mode 100644 (file)
index 0000000..d4dc5bb
--- /dev/null
@@ -0,0 +1,59 @@
+##############################################################################
+#  
+#    Copyright (C) 2005 - 2010 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 architecture dependent kernel HAL layer.
+#
+#
+
+
+################################################################################
+# Include common definitions.
+
+include $(AQROOT)/makefile.linux.def
+
+################################################################################
+# Define a shortcut for the main target.
+
+STATIC = 1
+TARGET_NAME = libhalkernel.a
+
+################################################################################
+# Supply additional include directories.
+
+INCLUDE += -I$(AQROOT)/hal/inc
+INCLUDE += -I$(AQROOT)/hal/user
+INCLUDE += -I$(AQARCH)/hal/kernel
+
+CFLAGS += $(INCLUDE) -Werror -ansi
+
+################################################################################
+# Describe object files.
+
+OBJECTS = $(OBJ_DIR)/gc_hal_kernel_command.o \
+          $(OBJ_DIR)/gc_hal_kernel_event.o \
+          $(OBJ_DIR)/gc_hal_kernel_heap.o \
+          $(OBJ_DIR)/gc_hal_kernel.o \
+          $(OBJ_DIR)/gc_hal_kernel_mmu.o \
+          $(OBJ_DIR)/gc_hal_kernel_video_memory.o
+
+include $(AQROOT)/common.target
diff --git a/drivers/staging/rk29/vivante/hal/makefile.linux b/drivers/staging/rk29/vivante/hal/makefile.linux
new file mode 100644 (file)
index 0000000..08596c6
--- /dev/null
@@ -0,0 +1,47 @@
+##############################################################################
+#  
+#    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+#  
+#    The material in this file is confidential and contains trade secrets
+#    of Vivante Corporation. This is proprietary information owned by
+#    Vivante Corporation. No part of this work may be disclosed, 
+#    reproduced, copied, transmitted, or used in any way for any purpose, 
+#    without the express written permission of Vivante Corporation.
+#  
+##############################################################################
+#  
+#    Auto-generated file on 10/12/2010. Do not edit!!!
+#  
+##############################################################################
+
+
+
+#
+# Linux build file for the user level HAL libraries.
+#
+
+
+
+################################################################################
+# Define make command.
+
+MAKE = make --makefile=makefile.linux
+
+
+################################################################################
+# Define build directories.
+
+HAL_USER_DRV_ARCH      := $(AQARCH)/hal/user
+ifeq ($(QNX), 1)
+HAL_USER_DRV_OS        := $(AQROOT)/hal/os/qnx/user
+else
+HAL_USER_DRV_OS        := $(AQROOT)/hal/os/linux/user
+endif
+HAL_USER_DRV_MAIN      := $(AQROOT)/hal/user
+
+$(HAL_USER_DRV_MAIN): $(HAL_USER_DRV_ARCH) $(HAL_USER_DRV_OS)
+
+MODULES        := $(HAL_USER_DRV_ARCH) $(HAL_USER_DRV_OS) $(HAL_USER_DRV_MAIN)
+MAIN_MODULE    = $(HAL_USER_DRV_MAIN)
+
+include $(AQROOT)/common.node
diff --git a/drivers/staging/rk29/vivante/hal/os/libGAL.def.mak b/drivers/staging/rk29/vivante/hal/os/libGAL.def.mak
new file mode 100644 (file)
index 0000000..1a5a8df
--- /dev/null
@@ -0,0 +1,540 @@
+##############################################################################
+#  
+#    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+#  
+#    The material in this file is confidential and contains trade secrets
+#    of Vivante Corporation. This is proprietary information owned by
+#    Vivante Corporation. No part of this work may be disclosed, 
+#    reproduced, copied, transmitted, or used in any way for any purpose, 
+#    without the express written permission of Vivante Corporation.
+#  
+##############################################################################
+#  
+#    Auto-generated file on 10/12/2010. Do not edit!!!
+#  
+##############################################################################
+
+
+"$(DEFFILE)" : $(AQROOT)\hal\os\libGAL.def.mak
+    @copy << "$(DEFFILE)"
+;
+; !! Do not edit this file - it is automatically generated !!
+;
+
+LIBRARY libGAL
+
+EXPORTS
+       ;gcoOS
+       gcoOS_SetDebugLevel
+       gcoOS_SetDebugZone
+       gcoOS_SetDebugFile
+       gcoOS_SetDebugZones
+       gcoOS_SetDebugLevelZone
+       gcoOS_SetDebugShaderFiles
+       gcoOS_DebugFatal
+       gcoOS_DebugTrace
+       gcoOS_DebugTraceZone
+       gcoOS_Print
+       gcoOS_DebugBreak
+       gcoOS_Verify
+       gcoOS_Construct
+       gcoOS_Destroy
+       gcoOS_QueryVideoMemory
+       gcoOS_Allocate
+       gcoOS_Free
+       gcoOS_AllocateNonPagedMemory
+       gcoOS_FreeNonPagedMemory
+       gcoOS_AllocateContiguous
+       gcoOS_FreeContiguous
+       gcoOS_CreateMutex
+       gcoOS_DeleteMutex
+       gcoOS_AcquireMutex
+       gcoOS_ReleaseMutex
+       gcoOS_CreateSignal
+       gcoOS_DestroySignal
+       gcoOS_Signal
+       gcoOS_WaitSignal
+       gcoOS_DeviceControl
+       gcoOS_Open
+       gcoOS_Close
+       gcoOS_Read
+       gcoOS_Write
+       gcoOS_Seek
+       gcoOS_SetPos
+       gcoOS_GetPos
+       gcoOS_MemCopy
+       gcoOS_ZeroMemory
+       gcoOS_MemFill
+       gcoOS_StrLen
+       gcoOS_StrFindReverse
+       gcoOS_StrCopySafe
+       gcoOS_StrCatSafe
+       gcoOS_StrCmp
+       gcoOS_StrNCmp
+       gcoOS_StrToFloat
+       gcoOS_StrToInt
+       gcoOS_MemCmp
+       gcoOS_PrintStrSafe
+       gcoOS_PrintStrVSafe
+       gcoOS_MapUserMemory
+       gcoOS_UnmapUserMemory
+       gcoOS_StrDup
+       gcoOS_LoadLibrary
+       gcoOS_FreeLibrary
+       gcoOS_GetProcAddress
+       gcoOS_Delay
+       gcoOS_GetCurrentProcessID
+       gcoOS_AtomConstruct
+       gcoOS_AtomDestroy
+       gcoOS_AtomIncrement
+       gcoOS_AtomDecrement
+       gcoOS_GetTicks
+       gcoOS_GetTime
+       gcoOS_GetCPUTime
+       gcoOS_GetMemoryUsage
+       gcoOS_GetBaseAddress
+       gcoOS_ReadRegister
+       gcoOS_WriteRegister
+
+!IFNDEF VIVANTE_NO_3D
+       ; gcsMEM
+       gcfMEM_InitFSMemPool
+       gcfMEM_FreeFSMemPool
+       gcfMEM_FSMemPoolGetANode
+       gcfMEM_FSMemPoolFreeANode
+       gcfMEM_FSMemPoolFreeAList
+       gcfMEM_InitAFSMemPool
+       gcfMEM_FreeAFSMemPool
+       gcfMEM_AFSMemPoolGetANode
+       gcfMEM_AFSMemPoolFreeANode
+!ENDIF
+
+       ; gcoHAL
+       gcoHAL_Construct
+       gcoHAL_Destroy
+       gcoHAL_IsFeatureAvailable
+       gcoHAL_QueryChipIdentity
+       gcoHAL_Call
+       gcoHAL_QueryVideoMemory
+       gcoHAL_MapMemory
+       gcoHAL_UnmapMemory
+       gcoHAL_ScheduleUnmapMemory
+       gcoHAL_ScheduleUnmapUserMemory
+       gcoHAL_Commit
+       gcoHAL_QueryTiled
+       gcoHAL_Get2DEngine
+       gcoHAL_Get3DEngine
+       gcoHAL_GetVGEngine
+       gcoHAL_GetDump
+       gcoHAL_ScheduleEvent
+!IFNDEF VIVANTE_NO_3D
+       gcoHAL_QueryTargetCaps
+       gcoHAL_SetDepthOnly
+       gcoHAL_QueryShaderCaps
+       gcoHAL_QueryTextureCaps
+       gcoHAL_QueryStreamCaps
+!ENDIF
+       gcoHAL_ProfileStart
+       gcoHAL_ProfileEnd
+       gcoHAL_Compact
+       gcoHAL_SetPowerManagementState
+       gcoHAL_QueryPowerManagementState
+       gcoHAL_DestroySurface
+
+       ; gcoDUMP       
+       gcoDUMP_Construct
+       gcoDUMP_Destroy
+       gcoDUMP_Control
+       gcoDUMP_IsEnabled
+       gcoDUMP_AddSurface
+       gcoDUMP_FrameBegin
+       gcoDUMP_FrameEnd
+       gcoDUMP_DumpData
+       gcoDUMP_Delete
+       gcfDump
+
+       ; gcoSURF
+       gcoSURF_Construct
+       gcoSURF_Destroy
+       gcoSURF_MapUserSurface
+       gcoSURF_GetSize
+       gcoSURF_GetAlignedSize
+       gcoSURF_GetFormat
+       gcoSURF_Lock
+       gcoSURF_Unlock
+       gcoSURF_Fill
+       gcoSURF_Blend
+       gcoSURF_SetClipping
+       gcoSURF_Clear2D
+       gcoSURF_Line
+       gcoSURF_Blit
+       gcoSURF_MonoBlit
+       gcoSURF_FilterBlit
+       gcoSURF_EnableAlphaBlend
+       gcoSURF_DisableAlphaBlend
+       gcoSURF_CopyPixels
+       gcoSURF_ReadPixel
+       gcoSURF_WritePixel
+       gcoSURF_QueryFormat
+       gcoSURF_Flush
+       gcoSURF_SetColorType
+       gcoSURF_GetColorType
+       gcoSURF_SetRotation
+       gcoSURF_ConstructWrapper
+       gcoSURF_SetBuffer
+       gcoSURF_SetWindow
+       gcoSURF_ReferenceSurface
+       gcoSURF_SetOrientation
+       gcoSURF_QueryOrientation
+       gcoSURF_QueryReferenceCount
+
+!IFNDEF VIVANTE_NO_3D
+       gcoSURF_IsTileStatusSupported
+       gcoSURF_EnableTileStatus
+       gcoSURF_DisableTileStatus
+       gcoSURF_SetSamples
+       gcoSURF_GetSamples
+       gcoSURF_Copy
+       gcoSURF_Clear
+       gcoSURF_ClearRect
+       gcoSURF_Resample
+       gcoSURF_Resolve
+       gcoSURF_ResolveRect
+       depr_gcoSURF_Resolve
+       depr_gcoSURF_ResolveRect
+       gcoSURF_SetResolvability
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+       ; gcoINDEX
+       gcoINDEX_Construct
+       gcoINDEX_Destroy
+       gcoINDEX_Lock
+       gcoINDEX_Unlock
+       gcoINDEX_Load
+       gcoINDEX_Bind
+       gcoINDEX_BindOffset
+       gcoINDEX_Free
+       gcoINDEX_Upload
+       gcoINDEX_UploadOffset
+       gcoINDEX_QueryCaps
+       gcoINDEX_GetIndexRange
+       gcoINDEX_SetDynamic
+       gcoINDEX_UploadDynamic
+!ENDIF
+
+       ; gco2D
+       gco2D_Construct
+       gco2D_Destroy
+       gco2D_SetBrushLimit
+       gco2D_FlushBrush
+       gco2D_LoadSolidBrush
+       gco2D_SetMonochromeSource
+       gco2D_SetColorSource
+       gco2D_SetColorSourceEx
+       gco2D_SetColorSourceAdvanced
+       gco2D_SetMaskedSource
+       gco2D_SetMaskedSourceEx
+       gco2D_SetSource
+       gco2D_SetClipping
+       gco2D_SetTarget
+       gco2D_SetTargetEx
+       gco2D_SetStretchFactors
+       gco2D_SetStretchRectFactors
+       gco2D_ConstructSingleColorBrush
+       gco2D_ConstructMonochromeBrush
+       gco2D_ConstructColorBrush
+       gco2D_Clear
+       gco2D_Line
+       gco2D_ColorLine
+       gco2D_Blit
+       gco2D_BatchBlit
+       gco2D_StretchBlit
+       gco2D_MonoBlit
+       gco2D_SetKernelSize
+       gco2D_SetFilterType
+       gco2D_SetUserFilterKernel
+       gco2D_EnableUserFilterPasses
+       gco2D_FreeFilterBuffer
+       gco2D_FilterBlit
+       gco2D_FilterBlitEx
+       gco2D_EnableAlphaBlend
+       gco2D_EnableAlphaBlendAdvanced
+       gco2D_SetPorterDuffBlending
+       gco2D_DisableAlphaBlend
+       gco2D_GetPackSize
+       gco2D_Flush
+       gco2D_LoadPalette
+       gco2D_SetBitBlitMirror
+       gco2D_SetTransparencyAdvanced
+       gco2D_SetSourceColorKeyAdvanced
+       gco2D_SetSourceColorKeyRangeAdvanced
+       gco2D_SetTargetColorKeyAdvanced
+       gco2D_SetTargetColorKeyRangeAdvanced
+       gco2D_SetYUVColorMode
+       gco2D_SetSourceGlobalColorAdvanced
+       gco2D_SetTargetGlobalColorAdvanced
+       gco2D_SetPixelMultiplyModeAdvanced
+       gco2D_SetAutoFlushCycles
+       gco2D_ProfileEngine
+       gco2D_GetMaximumDataCount
+
+
+!IFNDEF VIVANTE_NO_3D
+       gco3D_Construct
+       gco3D_Destroy
+       gco3D_SetAPI
+       gco3D_SetTarget
+       gco3D_SetDepth
+       gco3D_SetViewport
+       gco3D_SetScissors
+       gco3D_SetClearColor
+       gco3D_SetClearColorX
+       gco3D_SetClearColorF
+       gco3D_SetClearDepthX
+       gco3D_SetClearDepthF
+       gco3D_SetClearStencil
+       gco3D_Clear
+       gco3D_ClearRect
+       gco3D_ClearTileStatus
+       gco3D_ClearHzTileStatus
+       gco3D_SetShading
+       gco3D_EnableBlending
+       gco3D_SetBlendFunction
+       gco3D_SetBlendMode
+       gco3D_SetBlendColor
+       gco3D_SetBlendColorX
+       gco3D_SetBlendColorF
+       gco3D_SetCulling
+       gco3D_SetPointSizeEnable
+       gco3D_SetPointSprite
+       gco3D_SetFill
+       gco3D_SetDepthCompare
+       gco3D_EnableDepthWrite
+       gco3D_SetDepthRangeX
+       gco3D_SetDepthMode
+       gco3D_SetDepthRangeF
+       gco3D_SetLastPixelEnable
+       gco3D_SetDepthScaleBiasX
+       gco3D_SetDepthScaleBiasF
+       gco3D_EnableDither
+       gco3D_SetColorWrite
+       gco3D_SetEarlyDepth
+       gco3D_SetDepthOnly
+       gco3D_SetStencilMode
+       gco3D_SetStencilMask
+       gco3D_SetStencilWriteMask
+       gco3D_SetStencilReference
+       gco3D_SetStencilCompare
+       gco3D_SetStencilPass
+       gco3D_SetStencilFail
+       gco3D_SetStencilDepthFail
+       gco3D_SetAlphaTest
+       gco3D_SetAlphaCompare
+       gco3D_SetAlphaReference
+       gco3D_SetAlphaReferenceX
+       gco3D_SetAlphaReferenceF
+       gco3D_SetAntiAliasLine
+       gco3D_SetAALineTexSlot
+       gco3D_SetAALineWidth
+       gco3D_DrawPrimitives
+       gco3D_DrawPrimitivesOffset
+       gco3D_DrawIndexedPrimitives
+       gco3D_DrawIndexedPrimitivesOffset
+       gco3D_SetAntiAlias
+       gco3D_WriteBuffer
+       gco3D_SetFragmentConfiguration
+       gco3D_EnableTextureStage
+       gco3D_SetTextureColorMask
+       gco3D_SetTextureAlphaMask
+       gco3D_SetFragmentColorX
+       gco3D_SetFragmentColorF
+       gco3D_SetFogColorX
+       gco3D_SetFogColorF
+       gco3D_SetTetxureColorX
+       gco3D_SetTetxureColorF
+       gco3D_SetColorTextureFunction
+       gco3D_SetAlphaTextureFunction
+       gco3D_Semaphore
+       gco3D_SetCentroids
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+       ; gcoTEXTURE
+       gcoTEXTURE_Construct
+       gcoTEXTURE_ConstructSized
+       gcoTEXTURE_Destroy
+       gcoTEXTURE_Upload
+       gcoTEXTURE_UploadSub
+       gcoTEXTURE_UploadCompressed
+       gcoTEXTURE_GetMipMap
+       gcoTEXTURE_GetMipMapFace
+       gcoTEXTURE_AddMipMap
+       gcoTEXTURE_AddMipMapFromClient
+       gcoTEXTURE_AddMipMapFromSurface
+       gcoTEXTURE_SetEndianHint
+       gcoTEXTURE_SetAddressingMode
+       gcoTEXTURE_SetBorderColor
+       gcoTEXTURE_SetBorderColorX
+       gcoTEXTURE_SetBorderColorF
+       gcoTEXTURE_SetMinFilter
+       gcoTEXTURE_SetMagFilter
+       gcoTEXTURE_SetMipFilter
+       gcoTEXTURE_SetLODBiasX
+       gcoTEXTURE_SetLODBiasF
+       gcoTEXTURE_SetLODMinX
+       gcoTEXTURE_SetLODMinF
+       gcoTEXTURE_SetLODMaxX
+       gcoTEXTURE_SetLODMaxF
+       gcoTEXTURE_Bind
+       gcoTEXTURE_Flush
+       gcoTEXTURE_QueryCaps
+       gcoTEXTURE_GetClosestFormat
+       gcoTEXTURE_Disable
+       gcoTEXTURE_RenderIntoMipMap
+       gcoTEXTURE_IsRenderable
+       gcoTEXTURE_IsComplete
+!ENDIF
+
+       ; gcsRECT
+       gcsRECT_Height
+       gcsRECT_Width
+       gcsRECT_Set
+
+!IFNDEF VIVANTE_NO_3D
+       ; gcoHARDWARE
+       gcoHARDWARE_QueryTextureCaps
+       gcoHARDWARE_QueryShaderCaps
+       gcoHARDWARE_QueryIndexCaps
+       gcoHARDWARE_QueryStreamCaps
+!ENDIF
+
+       ; gcoBRUSH
+       gcoBRUSH_Destroy
+
+!IFNDEF VIVANTE_NO_3D
+       ; gcSHADER
+       gcOptimizeShader
+       gcLinkShaders
+       gcLoadShaders
+       gcSaveProgram
+       gcSHADER_Construct
+       gcSHADER_Destroy
+       gcSHADER_AddUniform
+       gcSHADER_AddSource
+       gcSHADER_AddSourceAttributeIndexed
+       gcSHADER_AddSourceUniformIndexed
+       gcSHADER_AddSourceSamplerIndexed
+       gcSHADER_AddOpcodeIndexed
+       gcSHADER_AddSourceIndexed
+       gcSHADER_AddAttribute
+       gcSHADER_AddOutput
+       gcSHADER_AddOutputIndexed
+       gcSHADER_AddSourceAttribute
+       gcSHADER_AddSourceConstant
+       gcSHADER_AddSourceUniform
+       gcSHADER_AddLabel
+       gcSHADER_AddOpcode
+       gcSHADER_AddOpcode2
+       gcSHADER_AddOpcodeConditional
+       gcSHADER_AddVariable
+       gcSHADER_Pack
+       gcSHADER_Load
+       gcSHADER_Save
+       gcSHADER_GetUniform
+       gcSHADER_GetUniformCount
+       gcSHADER_GetAttribute
+       gcSHADER_GetAttributeCount
+       gcSHADER_GetPositionAttribute
+       gcSHADER_GetVariable
+       gcSHADER_GetVariableCount
+       gcSHADER_AddFunction
+       gcSHADER_BeginFunction
+       gcSHADER_EndFunction
+       gcSHADER_SetOptimizationOption
+       gcSHADER_GetPositionAttribute
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+       ; gcATTRIBUTE
+       gcATTRIBUTE_GetName
+       gcATTRIBUTE_GetType     
+       gcATTRIBUTE_IsEnabled
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+       ; gcFUNCTION
+       gcFUNCTION_AddArgument
+       gcFUNCTION_GetArgument
+       gcFUNCTION_GetLabel
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+       ; gcUNIFORM
+       gcUNIFORM_GetName
+       gcUNIFORM_GetType
+       gcUNIFORM_GetSampler
+       gcUNIFORM_SetValue
+       gcUNIFORM_SetValueX
+       gcUNIFORM_SetValueF
+!ENDIF
+       
+!IFNDEF VIVANTE_NO_3D
+       ; gcoSTREAM
+       gcoSTREAM_Construct
+       gcoSTREAM_Destroy
+       gcoSTREAM_Upload
+       gcoSTREAM_SetStride
+       gcoSTREAM_Lock
+       gcoSTREAM_Unlock
+       gcoSTREAM_Reserve
+       gcoSTREAM_Flush
+       gcoSTREAM_SetDynamic
+       gcoSTREAM_UploadDynamic
+!ENDIF
+       
+!IFNDEF VIVANTE_NO_3D
+       ; gcoVERTEX
+       gcoVERTEX_Construct
+       gcoVERTEX_Destroy
+       gcoVERTEX_Reset
+       gcoVERTEX_EnableAttribute
+       gcoVERTEX_DisableAttribute
+       gcoVERTEX_Bind
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+       ; gcoBUFFER
+       gcoBUFFER_Construct
+       gcoBUFFER_Destroy
+       gcoBUFFER_Reserve
+       gcoBUFFER_Write
+       gcoBUFFER_Commit
+!ENDIF
+
+!IFNDEF VIVANTE_NO_PROFILER
+       ; gcoPROFILER
+       ;gcoPROFILER_Initialize
+       ;gcoPROFILER_Destroy
+       ;gcoPROFILER_EndFrame
+       ;gcoPROFILER_ShaderFS
+       ;gcoPROFILER_ShaderVS
+!ENDIF
+
+       ; gcoMATH
+       gcoMATH_Log2in5dot5
+       gcoMATH_Sine
+       gcoMATH_Cosine
+       gcoMATH_Floor
+       gcoMATH_Ceiling
+       gcoMATH_SquareRoot
+       gcoMATH_Log2
+       gcoMATH_Power
+       gcoMATH_Modulo
+       gcoMATH_ArcCosine
+       gcoMATH_Absolute
+       gcoMATH_Exp
+       gcoMATH_UInt2Float
+       gcoMATH_Float2UInt
+       gcoMATH_Multiply
+<<
diff --git a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_debug.c b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_debug.c
new file mode 100644 (file)
index 0000000..3577a39
--- /dev/null
@@ -0,0 +1,449 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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/spinlock.h"
+#include <stdarg.h>
+
+/*
+    gcdBUFFERED_OUTPUT
+
+    When set to non-zero, all output is collected into a buffer with the
+    specified size.  Once the buffer gets full, or the token "$$FLUSH$$" has
+    been received, the debug buffer will be printed to the console.
+*/
+#define gcdBUFFERED_OUTPUT  0
+
+/******************************************************************************\
+******************************** Debug Variables *******************************
+\******************************************************************************/
+
+static gceSTATUS  _lastError  = gcvSTATUS_OK;
+static gctUINT32  _debugLevel = gcvLEVEL_WARNING;
+static gctUINT32  _debugZones = gcvZONE_ALL;
+static gctINT     _indent     = 0;
+static spinlock_t _lock       = SPIN_LOCK_UNLOCKED;
+
+static void
+OutputDebugString(
+    IN gctCONST_STRING String
+    )
+{
+#if gcdBUFFERED_OUTPUT
+    static gctCHAR outputBuffer[gcdBUFFERED_OUTPUT];
+    static gctINT outputBufferIndex = 0;
+    gctINT n, i;
+
+    n = (String != gcvNULL) ? strlen(String) + 1 : 0;
+
+    if ((n == 0) || (outputBufferIndex + n > gcmSIZEOF(outputBuffer)))
+    {
+        for (i = 0; i < outputBufferIndex; i += strlen(outputBuffer + i) + 1)
+        {
+            printk(outputBuffer + i);
+        }
+
+        outputBufferIndex = 0;
+    }
+
+    if (n > 0)
+    {
+        memcpy(outputBuffer + outputBufferIndex, String, n);
+        outputBufferIndex += n;
+    }
+#else
+    if (String != gcvNULL)
+    {
+        printk(String);
+    }
+#endif
+}
+
+static void
+_Print(
+    IN gctCONST_STRING Message,
+    IN va_list Arguments
+    )
+{
+    char buffer[1024];
+    int i, n;
+
+    if (strcmp(Message, "$$FLUSH$$") == 0)
+    {
+       spin_lock(&_lock);
+       {
+               OutputDebugString(gcvNULL);
+        }
+        spin_unlock(&_lock);
+        return;
+    }
+
+    if (strncmp(Message, "--", 2) == 0)
+    {
+        if (_indent == 0)
+        {
+            printk("ERROR: _indent=0\n");
+        }
+
+        _indent -= 2;
+    }
+
+    for (i = 0; i < _indent; ++i)
+    {
+        buffer[i] = ' ';
+    }
+
+    /* Print message to buffer. */
+    n = vsnprintf(buffer + i, sizeof(buffer) - i, Message, Arguments);
+    if ((n <= 0) || (buffer[i + n - 1] != '\n'))
+    {
+        /* Append new-line. */
+        strncat(buffer, "\n", sizeof(buffer));
+    }
+
+    /* Output to debugger. */
+       spin_lock(&_lock);
+       {
+       OutputDebugString(buffer);
+    }
+    spin_unlock(&_lock);
+
+    if (strncmp(Message, "++", 2) == 0)
+    {
+        _indent += 2;
+    }
+}
+
+/******************************************************************************\
+********************************* Debug Macros *********************************
+\******************************************************************************/
+
+#define _DEBUGPRINT(Message) \
+{ \
+    va_list arguments; \
+    \
+    va_start(arguments, Message); \
+    _Print(Message, arguments); \
+    va_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,
+    ...
+    )
+{
+    _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+**  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;
+    }
+
+    _DEBUGPRINT(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;
+    }
+
+    _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+**  gckOS_DebugBreak
+**
+**  Break into the debugger.
+**
+**  INPUT:
+**
+**      Nothing.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+void
+gckOS_DebugBreak(
+    void
+    )
+{
+    gckOS_DebugTrace(gcvLEVEL_ERROR, "gckOS_DebugBreak");
+}
+
+/*******************************************************************************
+**
+**  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,
+    ...
+    )
+{
+    _DEBUGPRINT(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;
+}
+
diff --git a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_device.c b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_device.c
new file mode 100644 (file)
index 0000000..51ab04d
--- /dev/null
@@ -0,0 +1,836 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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>
+
+#define _GC_OBJ_ZONE    gcvZONE_DEVICE
+
+#ifdef FLAREON
+static struct dove_gpio_irq_handler gc500_handle;
+#endif
+
+/******************************************************************************\
+******************************** gckGALDEVICE Code *******************************
+\******************************************************************************/
+
+gceSTATUS
+gckGALDEVICE_AllocateMemory(
+    IN gckGALDEVICE Device,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER *Logical,
+    OUT gctPHYS_ADDR *Physical,
+    OUT gctUINT32 *PhysAddr
+    )
+{
+    gceSTATUS status;
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+    gcmkVERIFY_ARGUMENT(PhysAddr != NULL);
+
+    status = gckOS_AllocateContiguous(Device->os,
+                      gcvFALSE,
+                      &Bytes,
+                      Physical,
+                      Logical);
+
+    if (gcmIS_ERROR(status))
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                       "gckGALDEVICE_AllocateMemory: error status->0x%x",
+                       status);
+
+        return status;
+    }
+
+    *PhysAddr = ((PLINUX_MDL)*Physical)->dmaHandle - Device->baseAddress;
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                   "gckGALDEVICE_AllocateMemory: phys_addr->0x%x phsical->0x%x Logical->0x%x",
+                   (gctUINT32)*Physical,
+                   (gctUINT32)*PhysAddr,
+                   (gctUINT32)*Logical);
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckGALDEVICE_FreeMemory(
+    IN gckGALDEVICE Device,
+    IN gctPOINTER Logical,
+    IN gctPHYS_ADDR Physical)
+{
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    return gckOS_FreeContiguous(Device->os,
+                    Physical,
+                    Logical,
+                    ((PLINUX_MDL)Physical)->numPages*PAGE_SIZE);
+}
+
+irqreturn_t isrRoutine(int irq, void *ctxt)
+{
+    gckGALDEVICE device = (gckGALDEVICE) ctxt;
+    int handled = 0;
+
+    /* Call kernel interrupt notification. */
+    if (gckKERNEL_Notify(device->kernel,
+                        gcvNOTIFY_INTERRUPT,
+                        gcvTRUE) == gcvSTATUS_OK)
+    {
+        device->dataReady = gcvTRUE;
+
+        up(&device->sema);
+
+        handled = 1;
+    }
+
+    return IRQ_RETVAL(handled);
+}
+
+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->sema);
+        device->dataReady = gcvFALSE;
+
+        if (device->killThread == gcvTRUE)
+        {
+            /* The daemon exits. */
+            while (!kthread_should_stop())
+            {
+                gckOS_Delay(device->os, 1);
+            }
+
+            return 0;
+        }
+        else
+        {
+            gckKERNEL_Notify(device->kernel, gcvNOTIFY_INTERRUPT, gcvFALSE);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    gctINT ret;
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    if (Device->irqLine == 0)
+    {
+        return 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->irqLine,
+                isrRoutine,
+                IRQF_DISABLED,
+                "galcore interrupt service",
+                Device);
+#endif
+
+
+    if (ret != 0) {
+        gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_DRIVER,
+                "[galcore] gckGALDEVICE_Setup_ISR: "
+                "Could not register irq line->%d",
+                Device->irqLine);
+
+        Device->isrInitialized = gcvFALSE;
+
+        return gcvSTATUS_GENERIC_IO;
+    }
+
+    Device->isrInitialized = gcvTRUE;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_DRIVER,
+                "[galcore] gckGALDEVICE_Setup_ISR: "
+                "Setup the irq line->%d",
+                Device->irqLine);
+
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    /* release the irq */
+    if (Device->isrInitialized)
+    {
+#ifdef FLAREON
+        dove_gpio_free (DOVE_GPIO0_7, "galcore interrupt service");
+#else
+        free_irq(Device->irqLine, Device);
+#endif
+    }
+
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckGALDEVICE_Start_Thread
+**
+**  Start the daemon thread.
+**
+**  INPUT:
+**
+**      gckGALDEVICE Device
+**          Pointer to an gckGALDEVICE object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+**
+**  RETURNS:
+**
+**      gcvSTATUS_OK
+**          Start successfully.
+**      gcvSTATUS_GENERIC_IO
+**          Start failed.
+*/
+gceSTATUS
+gckGALDEVICE_Start_Thread(
+    IN gckGALDEVICE Device
+    )
+{
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    /* start the kernel thread */
+    Device->threadCtxt = kthread_run(threadRoutine,
+                    Device,
+                    "galcore daemon thread");
+
+    Device->threadInitialized = gcvTRUE;
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                    gcvZONE_DRIVER,
+                    "[galcore] gckGALDEVICE_Start_Thread: "
+                    "Start the daemon thread.");
+
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckGALDEVICE_Stop_Thread
+**
+**  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_Thread(
+    gckGALDEVICE Device
+    )
+{
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    /* stop the thread */
+    if (Device->threadInitialized)
+    {
+        Device->killThread = gcvTRUE;
+        up(&Device->sema);
+
+        kthread_stop(Device->threadCtxt);
+    }
+
+    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
+    )
+{
+    /* start the daemon thread */
+    gcmkVERIFY_OK(gckGALDEVICE_Start_Thread(Device));
+
+    /* setup the isr routine */
+    gcmkVERIFY_OK(gckGALDEVICE_Setup_ISR(Device));
+
+    /* Switch to SUSPEND power state. */
+    gcmkVERIFY_OK(
+        gckHARDWARE_SetPowerManagementState(Device->kernel->hardware,
+                                            gcvPOWER_SUSPEND_ATPOWERON));
+
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    /* Switch to ON power state. */
+    gcmkVERIFY_OK(
+        gckHARDWARE_SetPowerManagementState(Device->kernel->hardware,
+                                            gcvPOWER_ON));
+
+    if (Device->isrInitialized)
+    {
+        gckGALDEVICE_Release_ISR(Device);
+    }
+
+    if (Device->threadInitialized)
+    {
+        gckGALDEVICE_Stop_Thread(Device);
+    }
+
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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 gctUINT32 ContiguousBase,
+    IN gctSIZE_T ContiguousSize,
+    IN gctSIZE_T BankSize,
+    IN gctINT FastClear,
+    IN gctINT Compression,
+    IN gctUINT32 BaseAddress,
+    IN gctINT Signal,
+    OUT gckGALDEVICE *Device
+    )
+{
+    gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
+    gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
+    gctUINT32 horizontalTileSize, verticalTileSize;
+    gctUINT32 physAddr;
+    gctUINT32 physical;
+    gckGALDEVICE device;
+    gceSTATUS status;
+
+    gcmkTRACE(gcvLEVEL_VERBOSE, "[galcore] Enter gckGALDEVICE_Construct");
+
+    /* Allocate device structure. */
+    device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL);
+    if (!device)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                      "[galcore] gckGALDEVICE_Construct: Can't allocate memory.");
+
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+    memset(device, 0, sizeof(struct _gckGALDEVICE));
+
+    physical = RegisterMemBase;
+
+    /* Set up register memory region */
+    if (physical != 0)
+    {
+        /* Request a region. */
+        request_mem_region(RegisterMemBase, RegisterMemSize, "galcore register region");
+        device->registerBase = (gctPOINTER) ioremap_nocache(RegisterMemBase,
+                                                        RegisterMemSize);
+        if (!device->registerBase)
+    {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                      "[galcore] gckGALDEVICE_Construct: Unable to map location->0x%lX for size->%ld",
+              RegisterMemBase,
+              RegisterMemSize);
+
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+
+        physical += RegisterMemSize;
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                    gcvZONE_DRIVER,
+                    "[galcore] gckGALDEVICE_Construct: "
+                    "RegisterBase after mapping Address->0x%x is 0x%x",
+                    (gctUINT32)RegisterMemBase,
+                    (gctUINT32)device->registerBase);
+    }
+
+    /* construct the gckOS object */
+    device->baseAddress = BaseAddress;
+    gcmkVERIFY_OK(gckOS_Construct(device, &device->os));
+
+    /* construct the gckKERNEL object. */
+    gcmkVERIFY_OK(gckKERNEL_Construct(device->os, device, &device->kernel));
+
+    gcmkVERIFY_OK(gckHARDWARE_SetFastClear(device->kernel->hardware,
+                                          FastClear,
+                                          Compression));
+
+    /* query the ceiling of the system memory */
+    gcmkVERIFY_OK(gckHARDWARE_QuerySystemMemory(device->kernel->hardware,
+                    &device->systemMemorySize,
+                    &device->systemMemoryBaseAddress));
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                    gcvZONE_DRIVER,
+                    "[galcore] gckGALDEVICE_Construct: "
+                    "Will be trying to allocate contiguous memory of 0x%x bytes",
+                    (gctUINT32)device->systemMemoryBaseAddress);
+
+#if COMMAND_PROCESSOR_VERSION == 1
+    /* start the command queue */
+    gcmkVERIFY_OK(gckCOMMAND_Start(device->kernel->command));
+#endif
+
+    /* initialize the thread daemon */
+    sema_init(&device->sema, 0);
+
+    device->threadInitialized = gcvFALSE;
+    device->killThread = gcvFALSE;
+
+    /* initialize the isr */
+    device->isrInitialized = gcvFALSE;
+    device->dataReady = gcvFALSE;
+    device->irqLine = IrqLine;
+
+    device->signal = Signal;
+
+    /* query the amount of video memory */
+    gcmkVERIFY_OK(gckHARDWARE_QueryMemory(device->kernel->hardware,
+                    &device->internalSize,
+                    &internalBaseAddress,
+                    &internalAlignment,
+                    &device->externalSize,
+                    &externalBaseAddress,
+                    &externalAlignment,
+                    &horizontalTileSize,
+                    &verticalTileSize));
+
+    /* set up the internal memory region */
+    if (device->internalSize > 0)
+    {
+        gceSTATUS status = gckVIDMEM_Construct(device->os,
+                    internalBaseAddress,
+                    device->internalSize,
+                    internalAlignment,
+                    0,
+                    &device->internalVidMem);
+
+        if (gcmIS_ERROR(status))
+        {
+            /* error, remove internal heap */
+            device->internalSize = 0;
+        }
+        else
+        {
+            /* map internal memory */
+            device->internalPhysical  = (gctPHYS_ADDR)physical;
+            device->internalLogical   = (gctPOINTER)ioremap_nocache(
+                    physical, device->internalSize);
+
+            gcmkASSERT(device->internalLogical != NULL);
+
+            physical += device->internalSize;
+        }
+    }
+
+    if (device->externalSize > 0)
+    {
+        /* create the external memory heap */
+        gceSTATUS status = gckVIDMEM_Construct(device->os,
+                    externalBaseAddress,
+                    device->externalSize,
+                    externalAlignment,
+                    0,
+                    &device->externalVidMem);
+
+        if (gcmIS_ERROR(status))
+        {
+            /* error, remove internal heap */
+            device->externalSize = 0;
+        }
+        else
+        {
+            /* map internal memory */
+            device->externalPhysical = (gctPHYS_ADDR)physical;
+            device->externalLogical = (gctPOINTER)ioremap_nocache(
+                    physical, device->externalSize);
+
+            gcmkASSERT(device->externalLogical != NULL);
+
+            physical += device->externalSize;
+        }
+    }
+
+    /* set up the contiguous memory */
+    device->contiguousSize = ContiguousSize;
+
+    if (ContiguousBase == 0)
+    {
+        status = gcvSTATUS_OUT_OF_MEMORY;
+
+        while (device->contiguousSize > 0)
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO, gcvZONE_DRIVER,
+                "[galcore] gckGALDEVICE_Construct: Will be trying to allocate contiguous memory of %ld bytes",
+                device->contiguousSize
+                );
+
+            /* allocate contiguous memory */
+            status = gckGALDEVICE_AllocateMemory(
+                device,
+                device->contiguousSize,
+                &device->contiguousBase,
+                &device->contiguousPhysical,
+                &physAddr
+                );
+
+            if (gcmIS_SUCCESS(status))
+            {
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_INFO, gcvZONE_DRIVER,
+                    "[galcore] gckGALDEVICE_Construct: Contiguous allocated size->0x%08X Virt->0x%08lX physAddr->0x%08X",
+                    device->contiguousSize,
+                    device->contiguousBase,
+                    physAddr
+                    );
+
+                status = gckVIDMEM_Construct(
+                    device->os,
+                    physAddr | device->systemMemoryBaseAddress,
+                    device->contiguousSize,
+                    64,
+                    BankSize,
+                    &device->contiguousVidMem
+                    );
+
+                if (gcmIS_SUCCESS(status))
+                {
+                    device->contiguousMapped = gcvFALSE;
+
+                    /* success, abort loop */
+                    gcmkTRACE_ZONE(
+                        gcvLEVEL_INFO, gcvZONE_DRIVER,
+                        "Using %u bytes of contiguous memory.",
+                        device->contiguousSize
+                        );
+
+                    break;
+                }
+
+                gcmkVERIFY_OK(gckGALDEVICE_FreeMemory(
+                    device,
+                    device->contiguousBase,
+                    device->contiguousPhysical
+                    ));
+
+                device->contiguousBase = NULL;
+            }
+
+            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, roll back. */
+            device->contiguousVidMem = gcvNULL;
+            device->contiguousSize   = 0;
+        }
+        else
+        {
+            /* Map the contiguous memory. */
+            request_mem_region(
+                ContiguousBase,
+                ContiguousSize,
+                "galcore managed memory"
+                );
+
+            device->contiguousPhysical = (gctPHYS_ADDR) ContiguousBase;
+            device->contiguousSize     = ContiguousSize;
+            device->contiguousBase     = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize);
+            device->contiguousMapped   = gcvTRUE;
+
+            if (device->contiguousBase == gcvNULL)
+            {
+                /* Error, roll back. */
+                gcmkVERIFY_OK(gckVIDMEM_Destroy(device->contiguousVidMem));
+                device->contiguousVidMem = gcvNULL;
+                device->contiguousSize   = 0;
+
+                status = gcvSTATUS_OUT_OF_RESOURCES;
+            }
+        }
+    }
+
+    *Device = device;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                  "[galcore] gckGALDEVICE_Construct: Initialized device->%p contiguous->%lu @ %p (0x%08X)",
+          device,
+          device->contiguousSize,
+          device->contiguousBase,
+          device->contiguousPhysical);
+
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckGALDEVICE_Destroy
+**
+**  Class destructor.
+**
+**  INPUT:
+**
+**      Nothing.
+**
+**  OUTPUT:
+**
+**      Nothing.
+**
+**  RETURNS:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Destroy(
+    gckGALDEVICE Device)
+{
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    gcmkTRACE(gcvLEVEL_VERBOSE, "[ENTER] gckGALDEVICE_Destroy");
+
+    /* Destroy the gckKERNEL object. */
+    gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernel));
+
+    if (Device->internalVidMem != gcvNULL)
+    {
+        /* destroy the internal heap */
+        gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
+
+        /* unmap the internal memory */
+        iounmap(Device->internalLogical);
+    }
+
+    if (Device->externalVidMem != gcvNULL)
+    {
+        /* destroy the internal heap */
+        gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
+
+        /* unmap the external memory */
+        iounmap(Device->externalLogical);
+    }
+
+    if (Device->contiguousVidMem != gcvNULL)
+    {
+        /* Destroy the contiguous heap */
+        gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
+
+    if (Device->contiguousMapped)
+    {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                  "[galcore] gckGALDEVICE_Destroy: "
+              "Unmapping contiguous memory->0x%08lX",
+              Device->contiguousBase);
+
+        iounmap(Device->contiguousBase);
+    }
+    else
+    {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                  "[galcore] gckGALDEVICE_Destroy: "
+              "Freeing contiguous memory->0x%08lX",
+              Device->contiguousBase);
+
+            gcmkVERIFY_OK(gckGALDEVICE_FreeMemory(Device,
+                         Device->contiguousBase,
+                         Device->contiguousPhysical));
+        }
+    }
+
+    if (Device->registerBase)
+    {
+        iounmap(Device->registerBase);
+    }
+
+    /* Destroy the gckOS object. */
+    gcmkVERIFY_OK(gckOS_Destroy(Device->os));
+
+    kfree(Device);
+
+    gcmkTRACE(gcvLEVEL_VERBOSE, "[galcore] Leave gckGALDEVICE_Destroy");
+
+    return gcvSTATUS_OK;
+}
+
diff --git a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_device.h b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_device.h
new file mode 100644 (file)
index 0000000..75c86f8
--- /dev/null
@@ -0,0 +1,148 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_
+
+#define gcdkUSE_MEMORY_RECORD          1
+
+#ifdef ANDROID
+#define gcdkREPORT_VIDMEM_LEAK         0
+#else
+#define gcdkREPORT_VIDMEM_LEAK         1
+#endif
+
+/******************************************************************************\
+******************************* gckGALDEVICE Structure *******************************
+\******************************************************************************/
+
+typedef struct _gckGALDEVICE
+{
+       /* Objects. */
+       gckOS                           os;
+       gckKERNEL                       kernel;
+
+       /* 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                      registerBase;
+       gctSIZE_T                       registerSize;
+       gctUINT32                       baseAddress;
+
+       /* IRQ management. */
+       gctINT                          irqLine;
+       gctBOOL                         isrInitialized;
+       gctBOOL                         dataReady;
+
+       /* Thread management. */
+       struct task_struct      *threadCtxt;
+       struct semaphore        sema;
+       gctBOOL                         threadInitialized;
+       gctBOOL                         killThread;
+
+       /* Signal management. */
+       gctINT                          signal;
+}
+* gckGALDEVICE;
+
+#if gcdkUSE_MEMORY_RECORD
+typedef struct MEMORY_RECORD
+{
+       gcuVIDMEM_NODE_PTR              node;
+
+       struct MEMORY_RECORD *  prev;
+       struct MEMORY_RECORD *  next;
+}
+MEMORY_RECORD, * MEMORY_RECORD_PTR;
+#endif
+
+typedef struct _gcsHAL_PRIVATE_DATA
+{
+    gckGALDEVICE               device;
+    gctPOINTER                 mappedMemory;
+       gctPOINTER                      contiguousLogical;
+
+#if gcdkUSE_MEMORY_RECORD
+       MEMORY_RECORD           memoryRecordList;
+#endif
+}
+gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
+
+gceSTATUS gckGALDEVICE_Setup_ISR(
+       IN gckGALDEVICE Device
+       );
+
+gceSTATUS gckGALDEVICE_Release_ISR(
+       IN gckGALDEVICE Device
+       );
+
+gceSTATUS gckGALDEVICE_Start_Thread(
+       IN gckGALDEVICE Device
+       );
+
+gceSTATUS gckGALDEVICE_Stop_Thread(
+       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 gctUINT32 ContiguousBase,
+       IN gctSIZE_T ContiguousSize,
+       IN gctSIZE_T BankSize,
+       IN gctINT FastClear,
+       IN gctINT Compression,
+       IN gctUINT32 BaseAddress,
+       IN gctINT Signal,
+       OUT gckGALDEVICE *Device
+       );
+
+gceSTATUS gckGALDEVICE_Destroy(
+       IN gckGALDEVICE Device
+       );
+
+#endif /* __gc_hal_kernel_device_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c
new file mode 100644 (file)
index 0000000..ce27af5
--- /dev/null
@@ -0,0 +1,804 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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 <linux/device.h>
+#include <linux/miscdevice.h>
+
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_user_context.h"
+
+#if USE_PLATFORM_DRIVER
+#include <linux/platform_device.h>
+#endif
+
+MODULE_DESCRIPTION("Vivante Graphics Driver");
+MODULE_LICENSE("GPL");
+
+struct class *gpuClass;
+
+static gckGALDEVICE galDevice;
+
+static int major = 199;
+module_param(major, int, 0644);
+
+int irqLine = 0;
+module_param(irqLine, int, 0644);
+
+long registerMemBase = 0x80000000;
+module_param(registerMemBase, long, 0644);
+
+ulong registerMemSize = 256 << 10;
+module_param(registerMemSize, ulong, 0644);
+
+long contiguousSize = 4 << 20;
+module_param(contiguousSize, long, 0644);
+
+ulong contiguousBase = 0;
+module_param(contiguousBase, ulong, 0644);
+
+long bankSize = 32 << 20;
+module_param(bankSize, long, 0644);
+
+int fastClear = -1;
+module_param(fastClear, int, 0644);
+
+int compression = -1;
+module_param(compression, int, 0644);
+
+int signal = 48;
+module_param(signal, int, 0644);
+
+ulong baseAddress = 0;
+module_param(baseAddress, ulong, 0644);
+
+int showArgs = 0;
+module_param(showArgs, int, 0644);
+
+static int drv_open(struct inode *inode, struct file *filp);
+static int drv_release(struct inode *inode, struct file *filp);
+static int drv_ioctl(struct inode *inode, struct file *filp,
+                     unsigned int ioctlCode, unsigned long arg);
+static int drv_mmap(struct file * filp, struct vm_area_struct * vma);
+
+struct file_operations driver_fops =
+{
+    .open      = drv_open,
+    .release   = drv_release,
+    .ioctl     = drv_ioctl,
+    .mmap      = drv_mmap,
+};
+
+int drv_open(struct inode *inode, struct file* filp)
+{
+    gcsHAL_PRIVATE_DATA_PTR    private;
+
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+                 "Entering drv_open\n");
+
+    private = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL);
+
+    if (private == gcvNULL)
+    {
+       return -ENOTTY;
+    }
+
+    private->device                            = galDevice;
+    private->mappedMemory              = gcvNULL;
+       private->contiguousLogical      = gcvNULL;
+
+#if gcdkUSE_MEMORY_RECORD
+       private->memoryRecordList.prev = &private->memoryRecordList;
+       private->memoryRecordList.next = &private->memoryRecordList;
+#endif
+
+       /* A process gets attached. */
+       gcmkVERIFY_OK(
+               gckKERNEL_AttachProcess(galDevice->kernel, gcvTRUE));
+
+    if (!galDevice->contiguousMapped)
+    {
+       gcmkVERIFY_OK(gckOS_MapMemory(galDevice->os,
+                                                                       galDevice->contiguousPhysical,
+                                                                       galDevice->contiguousSize,
+                                                                       &private->contiguousLogical));
+    }
+
+    filp->private_data = private;
+
+    return 0;
+}
+
+extern void
+OnProcessExit(
+       IN gckOS Os,
+       IN gckKERNEL Kernel
+       );
+
+int drv_release(struct inode* inode, struct file* filp)
+{
+    gcsHAL_PRIVATE_DATA_PTR    private;
+    gckGALDEVICE                       device;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                 "Entering drv_close\n");
+
+    private = filp->private_data;
+    gcmkASSERT(private != gcvNULL);
+
+    device = private->device;
+
+#if gcdkUSE_MEMORY_RECORD
+       FreeAllMemoryRecord(galDevice->os, &private->memoryRecordList);
+
+#ifdef ANDROID
+       gcmkVERIFY_OK(gckOS_Delay(galDevice->os, 1000));
+#else
+       gcmkVERIFY_OK(gckCOMMAND_Stall(device->kernel->command));
+#endif
+#endif
+
+    if (!device->contiguousMapped)
+    {
+               if (private->contiguousLogical != gcvNULL)
+               {
+                       gcmkVERIFY_OK(gckOS_UnmapMemory(galDevice->os,
+                                                                                       galDevice->contiguousPhysical,
+                                                                                       galDevice->contiguousSize,
+                                                                                       private->contiguousLogical));
+               }
+    }
+
+       /* A process gets detached. */
+       gcmkVERIFY_OK(
+               gckKERNEL_AttachProcess(galDevice->kernel, gcvFALSE));
+
+    kfree(private);
+    filp->private_data = NULL;
+
+    return 0;
+}
+
+int drv_ioctl(struct inode *inode,
+             struct file *filp,
+             unsigned int ioctlCode,
+             unsigned long arg)
+{
+    gcsHAL_INTERFACE iface;
+    gctUINT32 copyLen;
+    DRIVER_ARGS drvArgs;
+    gckGALDEVICE device;
+    gceSTATUS status;
+    gcsHAL_PRIVATE_DATA_PTR private;
+
+    private = filp->private_data;
+
+    if (private == gcvNULL)
+    {
+       gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                     "[galcore] drv_ioctl: private_data is NULL\n");
+
+       return -ENOTTY;
+    }
+
+    device = private->device;
+
+    if (device == gcvNULL)
+    {
+       gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                     "[galcore] drv_ioctl: device is NULL\n");
+
+       return -ENOTTY;
+    }
+
+    if (ioctlCode != IOCTL_GCHAL_INTERFACE
+               && ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE)
+    {
+        /* Unknown command. Fail the I/O. */
+        return -ENOTTY;
+    }
+
+    /* Get the drvArgs to begin with. */
+    copyLen = copy_from_user(&drvArgs,
+                            (void *) arg,
+                            sizeof(DRIVER_ARGS));
+
+    if (copyLen != 0)
+    {
+       /* The input buffer is not big enough. So fail the I/O. */
+        return -ENOTTY;
+    }
+
+    /* Now bring in the gcsHAL_INTERFACE structure. */
+    if ((drvArgs.InputBufferSize  != sizeof(gcsHAL_INTERFACE))
+    ||  (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE))
+    )
+    {
+       return -ENOTTY;
+    }
+
+    copyLen = copy_from_user(&iface,
+                            drvArgs.InputBuffer,
+                            sizeof(gcsHAL_INTERFACE));
+
+    if (copyLen != 0)
+    {
+        /* The input buffer is not big enough. So fail the I/O. */
+        return -ENOTTY;
+    }
+
+#if gcdkUSE_MEMORY_RECORD
+       if (iface.command == gcvHAL_EVENT_COMMIT)
+       {
+               MEMORY_RECORD_PTR mr;
+               gcsQUEUE_PTR queue = iface.u.Event.queue;
+
+               while (queue != gcvNULL)
+               {
+                       gcsQUEUE_PTR record, next;
+
+                       /* Map record into kernel memory. */
+                       gcmkERR_BREAK(gckOS_MapUserPointer(device->os,
+                                                                                         queue,
+                                                                                         gcmSIZEOF(gcsQUEUE),
+                                                                                         (gctPOINTER *) &record));
+
+                       switch (record->iface.command)
+                       {
+                       case gcvHAL_FREE_VIDEO_MEMORY:
+                               mr = FindMemoryRecord(device->os,
+                                                                       &private->memoryRecordList,
+                                                                       record->iface.u.FreeVideoMemory.node);
+
+                               if (mr != gcvNULL)
+                               {
+                                       DestoryMemoryRecord(device->os, mr);
+                               }
+                               else
+                               {
+                                       printk("*ERROR* Invalid video memory (%p) for free\n",
+                                               record->iface.u.FreeVideoMemory.node);
+                               }
+                break;
+
+                       default:
+                               break;
+                       }
+
+                       /* Next record in the queue. */
+                       next = record->next;
+
+                       /* Unmap record from kernel memory. */
+                       gcmkERR_BREAK(gckOS_UnmapUserPointer(device->os,
+                                                                                               queue,
+                                                                                               gcmSIZEOF(gcsQUEUE),
+                                                                                               (gctPOINTER *) record));
+                       queue = next;
+               }
+       }
+#endif
+
+    status = gckKERNEL_Dispatch(device->kernel,
+               (ioctlCode == IOCTL_GCHAL_INTERFACE) , &iface);
+
+    if (gcmIS_ERROR(status))
+    {
+       gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DRIVER,
+                     "[galcore] gckKERNEL_Dispatch returned %d.\n",
+                     status);
+    }
+
+    else if (gcmIS_ERROR(iface.status))
+    {
+       gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DRIVER,
+                     "[galcore] IOCTL %d returned %d.\n",
+                     iface.command,
+                     iface.status);
+    }
+
+    /* See if this was a LOCK_VIDEO_MEMORY command. */
+    else if (iface.command == gcvHAL_LOCK_VIDEO_MEMORY)
+    {
+       /* Special case for mapped memory. */
+       if (private->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 *)  private->mappedMemory + offset;
+               }
+    }
+#if gcdkUSE_MEMORY_RECORD
+       else if (iface.command == gcvHAL_ALLOCATE_VIDEO_MEMORY)
+       {
+               CreateMemoryRecord(device->os,
+                                                       &private->memoryRecordList,
+                                                       iface.u.AllocateVideoMemory.node);
+       }
+       else if (iface.command == gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY)
+       {
+               CreateMemoryRecord(device->os,
+                                                       &private->memoryRecordList,
+                                                       iface.u.AllocateLinearVideoMemory.node);
+       }
+       else if (iface.command == gcvHAL_FREE_VIDEO_MEMORY)
+       {
+               MEMORY_RECORD_PTR mr;
+
+               mr = FindMemoryRecord(device->os,
+                                                       &private->memoryRecordList,
+                                                       iface.u.FreeVideoMemory.node);
+
+               if (mr != gcvNULL)
+               {
+                       DestoryMemoryRecord(device->os, mr);
+               }
+               else
+               {
+                       printk("*ERROR* Invalid video memory for free\n");
+               }
+       }
+#endif
+
+    /* Copy data back to the user. */
+    copyLen = copy_to_user(drvArgs.OutputBuffer,
+                          &iface,
+                          sizeof(gcsHAL_INTERFACE));
+
+    if (copyLen != 0)
+    {
+       /* The output buffer is not big enough. So fail the I/O. */
+        return -ENOTTY;
+    }
+
+    return 0;
+}
+
+static int drv_mmap(struct file * filp, struct vm_area_struct * vma)
+{
+    gcsHAL_PRIVATE_DATA_PTR private = filp->private_data;
+    gckGALDEVICE device;
+    int ret;
+    unsigned long size = vma->vm_end - vma->vm_start;
+
+    if (private == gcvNULL)
+    {
+       return -ENOTTY;
+    }
+
+    device = private->device;
+
+    if (device == gcvNULL)
+    {
+        return -ENOTTY;
+    }
+
+    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+    vma->vm_flags    |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND;
+    vma->vm_pgoff     = 0;
+
+    if (device->contiguousMapped)
+    {
+       ret = io_remap_pfn_range(vma,
+                                vma->vm_start,
+                                (gctUINT32) device->contiguousPhysical >> PAGE_SHIFT,
+                                size,
+                                vma->vm_page_prot);
+
+       private->mappedMemory = (ret == 0) ? (gctPOINTER) vma->vm_start : gcvNULL;
+
+       return ret;
+    }
+    else
+    {
+       return -ENOTTY;
+    }
+}
+
+
+static struct miscdevice miscdev = {
+    .name = "galcore",
+    .fops = &driver_fops,
+    .minor = MISC_DYNAMIC_MINOR,
+};
+
+
+
+
+#if !USE_PLATFORM_DRIVER
+static int __init drv_init(void)
+#else
+static int drv_init(void)
+#endif
+{
+    int ret;
+    gckGALDEVICE device;
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+    struct clk * clk = NULL;
+#endif
+
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+                 "Entering drv_init\n");
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+    clk = clk_get(NULL, "GCCLK");
+    if (IS_ERR(clk))
+    {
+        int retval = PTR_ERR(clk);
+        printk("clk get error: %d\n", retval);
+        return -ENODEV;
+    }
+
+    /* APMU_GC_156M, APMU_GC_624M, APMU_GC_PLL2, APMU_GC_PLL2_DIV2 currently */
+    if (clk_set_rate(clk, 624000000))
+    {
+               gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                     "[galcore] Can't set core clock.");
+        return -EAGAIN;
+    }
+    clk_enable(clk);
+#endif
+
+       if (showArgs)
+       {
+               printk("galcore options:\n");
+               printk("  irqLine         = %d\n",      irqLine);
+               printk("  registerMemBase = 0x%08lX\n", registerMemBase);
+               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);
+       }
+
+    /* Create the GAL device. */
+    gcmkVERIFY_OK(gckGALDEVICE_Construct(irqLine,
+                                       registerMemBase,
+                                       registerMemSize,
+                                       contiguousBase,
+                                       contiguousSize,
+                                       bankSize,
+                                       fastClear,
+                                       compression,
+                                       baseAddress,
+                                       signal,
+                                       &device));
+
+    /* Start the GAL device. */
+    if (gcmIS_ERROR(gckGALDEVICE_Start(device)))
+    {
+       gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                     "[galcore] Can't start the gal device.\n");
+
+       /* Roll back. */
+       gckGALDEVICE_Stop(device);
+       gckGALDEVICE_Destroy(device);
+
+       return -1;
+    }
+
+
+#if 1
+    ret = misc_register(&miscdev);
+    if (ret < 0)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                     "[galcore] Could not register misc.\n");
+
+       /* Roll back. */
+       gckGALDEVICE_Stop(device);
+       gckGALDEVICE_Destroy(device);
+
+        return -1;
+    }
+    galDevice = device;
+#else
+
+    /* Register the character device. */
+    ret = register_chrdev(major, DRV_NAME, &driver_fops);
+    if (ret < 0)
+    {
+       gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                     "[galcore] Could not allocate major number for mmap.\n");
+
+       /* Roll back. */
+       gckGALDEVICE_Stop(device);
+       gckGALDEVICE_Destroy(device);
+
+       return -1;
+    }
+    else
+    {
+       if (major == 0)
+       {
+           major = ret;
+       }
+    }
+
+    galDevice = device;
+
+       gpuClass = class_create(THIS_MODULE, "graphics_class");
+       if (IS_ERR(gpuClass)) {
+       gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                                         "Failed to create the class.\n");
+               return -1;
+       }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+       device_create(gpuClass, NULL, MKDEV(major, 0), NULL, "galcore");
+#else
+       device_create(gpuClass, NULL, MKDEV(major, 0), "galcore");
+#endif
+#endif
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                 "[galcore] irqLine->%ld, contiguousSize->%lu, memBase->0x%lX\n",
+                 irqLine,
+                 contiguousSize,
+                 registerMemBase);
+
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+                 "[galcore] driver registered successfully.\n");
+
+    return 0;
+}
+
+#if !USE_PLATFORM_DRIVER
+static void __exit drv_exit(void)
+#else
+static void drv_exit(void)
+#endif
+{
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+    struct clk * clk = NULL;
+#endif
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+                 "[galcore] Entering drv_exit\n");
+
+#if 1
+    misc_deregister(&miscdev);
+#else
+
+       device_destroy(gpuClass, MKDEV(major, 0));
+       class_destroy(gpuClass);
+
+    unregister_chrdev(major, DRV_NAME);
+#endif
+
+    gckGALDEVICE_Stop(galDevice);
+    gckGALDEVICE_Destroy(galDevice);
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+    clk = clk_get(NULL, "GCCLK");
+    clk_disable(clk);
+#endif
+}
+
+#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;
+       res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,"gpu_irq");
+       if (!res) {
+               printk(KERN_ERR "%s: No irq line supplied.\n",__FUNCTION__);
+               goto gpu_probe_fail;
+       }
+       irqLine = res->start;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,"gpu_base");
+       if (!res) {
+               printk(KERN_ERR "%s: No register base supplied.\n",__FUNCTION__);
+               goto gpu_probe_fail;
+       }
+       registerMemBase = res->start;
+       registerMemSize = res->end - res->start;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,"gpu_mem");
+       if (!res) {
+               printk(KERN_ERR "%s: No memory base supplied.\n",__FUNCTION__);
+               goto gpu_probe_fail;
+       }
+       contiguousBase  = res->start;
+       contiguousSize  = res->end-res->start;
+
+       ret = drv_init();
+       if(!ret) {
+               platform_set_drvdata(pdev,galDevice);
+               return ret;
+       }
+
+gpu_probe_fail:
+       printk(KERN_INFO "Failed to register gpu driver.\n");
+       return ret;
+}
+
+static int __devinit gpu_remove(struct platform_device *pdev)
+{
+       drv_exit();
+
+       return 0;
+}
+
+static int __devinit gpu_suspend(struct platform_device *dev, pm_message_t state)
+{
+       gceSTATUS status;
+       gckGALDEVICE device;
+
+       device = platform_get_drvdata(dev);
+
+       status = gckHARDWARE_SetPowerManagementState(device->kernel->hardware, gcvPOWER_OFF);
+
+       if (gcmIS_ERROR(status))
+       {
+               return -1;
+       }
+
+       return 0;
+}
+
+static int __devinit gpu_resume(struct platform_device *dev)
+{
+       gceSTATUS status;
+       gckGALDEVICE device;
+
+       device = platform_get_drvdata(dev);
+
+       status = gckHARDWARE_SetPowerManagementState(device->kernel->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
+#ifndef 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
+#endif
+
+static int __init gpu_init(void)
+{
+       int ret = 0;
+
+#if 0   //add by dkm
+#ifndef CONFIG_DOVE_GPU
+       gpu_resources[0].start = gpu_resources[0].end = irqLine;
+
+       gpu_resources[1].start = registerMemBase;
+       gpu_resources[1].end   = registerMemBase + registerMemSize;
+
+       gpu_resources[2].start = contiguousBase;
+       gpu_resources[2].end   = contiguousBase + contiguousSize;
+
+       /* 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 del_dev;
+       }
+#endif
+#endif
+       ret = platform_driver_register(&gpu_driver);
+       if (!ret)
+       {
+               goto out;
+       }
+
+#if 0   //add by dkm
+#ifndef CONFIG_DOVE_GPU
+del_dev:
+       platform_device_del(gpu_device);
+put_dev:
+       platform_device_put(gpu_device);
+#endif
+#endif
+
+out:
+       return ret;
+
+}
+
+static void __exit gpu_exit(void)
+{
+       platform_driver_unregister(&gpu_driver);
+#if 0   //add by dkm
+#ifndef CONFIG_DOVE_GPU
+       platform_device_unregister(gpu_device);
+#endif
+#endif
+}
+
+module_init(gpu_init);
+module_exit(gpu_exit);
+
+#endif
+
diff --git a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_linux.c b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_linux.c
new file mode 100644 (file)
index 0000000..36546c9
--- /dev/null
@@ -0,0 +1,411 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_MapVideoMemory(
+       IN gckKERNEL Kernel,
+       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;
+
+    /* 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
+               {
+                       mdl = (PLINUX_MDL) device->contiguousPhysical;
+
+                       mdlMap = FindMdlMap(mdl, current->tgid);
+                       gcmkASSERT(mdlMap);
+
+                       logical = (gctPOINTER) mdlMap->vmaAddr;
+               }
+
+               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_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/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_linux.h b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_linux.h
new file mode 100644 (file)
index 0000000..de767ea
--- /dev/null
@@ -0,0 +1,89 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_os.c
new file mode 100644 (file)
index 0000000..9f63033
--- /dev/null
@@ -0,0 +1,5698 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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>
+#ifdef NO_DMA_COHERENT
+#include <linux/dma-mapping.h>
+#endif /* NO_DMA_COHERENT */
+
+#if !USE_NEW_LINUX_SIGNAL
+#define USER_SIGNAL_TABLE_LEN_INIT  64
+#endif
+
+#define _GC_OBJ_ZONE    gcvZONE_OS
+
+#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))
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+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;
+
+    gctUINT32                   baseAddress;
+
+    /* Kernel process ID. */
+    gctUINT32                   kernelProcessID;
+
+#if !USE_NEW_LINUX_SIGNAL
+    /* 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;
+#endif
+};
+
+#if !USE_NEW_LINUX_SIGNAL
+typedef struct _gcsSIGNAL
+{
+    /* Kernel sync primitive. */
+    struct completion event;
+
+    /* Manual reset flag. */
+    gctBOOL manualReset;
+
+    /* The reference counter. */
+    atomic_t ref;
+
+    /* The owner of the signal. */
+    gctHANDLE process;
+}
+gcsSIGNAL;
+
+typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
+#endif
+
+typedef struct _gcsPageInfo * gcsPageInfo_PTR;
+
+typedef struct _gcsPageInfo
+{
+    struct page **pages;
+    gctUINT32_PTR pageTable;
+}
+gcsPageInfo;
+
+static PLINUX_MDL
+_CreateMdl(
+    IN gctINT PID
+    )
+{
+    PLINUX_MDL  mdl;
+
+    mdl = (PLINUX_MDL)kmalloc(sizeof(struct _LINUX_MDL), GFP_ATOMIC);
+    if (mdl == gcvNULL) return gcvNULL;
+
+    mdl->pid    = PID;
+    mdl->maps   = gcvNULL;
+    mdl->prev   = gcvNULL;
+    mdl->next   = gcvNULL;
+
+    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;
+
+    /* 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);
+
+    return gcvSTATUS_OK;
+}
+
+static PLINUX_MDL_MAP
+_CreateMdlMap(
+    IN PLINUX_MDL Mdl,
+    IN gctINT PID
+    )
+{
+    PLINUX_MDL_MAP  mdlMap;
+
+    mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_ATOMIC);
+    if (mdlMap == gcvNULL) return gcvNULL;
+
+    mdlMap->pid     = PID;
+    mdlMap->vmaAddr = gcvNULL;
+    mdlMap->vma     = gcvNULL;
+
+    mdlMap->next    = Mdl->maps;
+    Mdl->maps       = mdlMap;
+
+    return mdlMap;
+}
+
+static gceSTATUS
+_DestroyMdlMap(
+    IN PLINUX_MDL Mdl,
+    IN PLINUX_MDL_MAP MdlMap
+    )
+{
+    PLINUX_MDL_MAP  prevMdlMap;
+
+    /* 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);
+
+    return gcvSTATUS_OK;
+}
+
+extern PLINUX_MDL_MAP
+FindMdlMap(
+    IN PLINUX_MDL Mdl,
+    IN gctINT PID
+    )
+{
+    PLINUX_MDL_MAP  mdlMap;
+
+    mdlMap = Mdl->maps;
+
+    while (mdlMap != gcvNULL)
+    {
+        if (mdlMap->pid == PID) return mdlMap;
+
+        mdlMap = mdlMap->next;
+    }
+
+    return gcvNULL;
+}
+
+void
+FreeProcessMemoryOnExit(
+    IN gckOS Os,
+    IN gckKERNEL Kernel
+    )
+{
+    PLINUX_MDL      mdl, nextMdl;
+    PLINUX_MDL_MAP  mdlMap;
+
+    MEMORY_LOCK(Os);
+
+    mdl = Os->mdlHead;
+
+    while (mdl != gcvNULL)
+    {
+        if (mdl != Os->mdlTail)
+        {
+            nextMdl = mdl->next;
+        }
+        else
+        {
+            nextMdl = gcvNULL;
+        }
+
+        if (mdl->pagedMem)
+        {
+            mdlMap = mdl->maps;
+
+            if (mdlMap != gcvNULL
+                && mdlMap->pid == current->tgid
+                && mdlMap->next == gcvNULL)
+            {
+                MEMORY_UNLOCK(Os);
+
+                gcmkVERIFY_OK(gckOS_FreePagedMemory(Os, mdl, mdl->numPages * PAGE_SIZE));
+
+                MEMORY_LOCK(Os);
+
+                nextMdl = Os->mdlHead;
+            }
+        }
+
+        mdl = nextMdl;
+    }
+
+    MEMORY_UNLOCK(Os);
+}
+
+void
+PrintInfoOnExit(
+    IN gckOS Os,
+    IN gckKERNEL Kernel
+    )
+{
+    PLINUX_MDL      mdl, nextMdl;
+    PLINUX_MDL_MAP  mdlMap;
+
+    MEMORY_LOCK(Os);
+
+    mdl = Os->mdlHead;
+
+    while (mdl != gcvNULL)
+    {
+        if (mdl != Os->mdlTail)
+        {
+            nextMdl = mdl->next;
+        }
+        else
+        {
+            nextMdl = gcvNULL;
+        }
+
+        printk("Unfreed mdl: %p, pid: %d -> pagedMem: %s, addr: %p, dmaHandle: 0x%x, pages: %d",
+            mdl,
+            mdl->pid,
+            mdl->pagedMem? "true" : "false",
+            mdl->addr,
+            mdl->dmaHandle,
+            mdl->numPages);
+
+        mdlMap = mdl->maps;
+
+        while (mdlMap != gcvNULL)
+        {
+            printk("\tmap: %p, pid: %d -> vmaAddr: %p, vma: %p",
+                    mdlMap,
+                    mdlMap->pid,
+                    mdlMap->vmaAddr,
+                    mdlMap->vma);
+
+            mdlMap = mdlMap->next;
+        }
+
+        mdl = nextMdl;
+    }
+
+    MEMORY_UNLOCK(Os);
+}
+
+void
+OnProcessExit(
+    IN gckOS Os,
+    IN gckKERNEL Kernel
+    )
+{
+    /* PrintInfoOnExit(Os, Kernel); */
+
+#ifdef ANDROID
+    FreeProcessMemoryOnExit(Os, Kernel);
+#endif
+}
+
+/*******************************************************************************
+**
+**  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;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Os != gcvNULL);
+
+    /* Allocate the gckOS object. */
+    os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_ATOMIC);
+
+    if (os == gcvNULL)
+    {
+        /* 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 the gckHEAP object. */
+    gcmkONERROR(gckHEAP_Construct(os, gcdHEAP_SIZE, &os->heap));
+
+    os->mdlHead = os->mdlTail = gcvNULL;
+
+    /* Find the base address of the physical memory. */
+    os->baseAddress = os->device->baseAddress;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+                  "Physical base address set to 0x%08X.",
+                  os->baseAddress);
+
+    /* Get the kernel process ID. */
+    gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
+
+#if !USE_NEW_LINUX_SIGNAL
+    /*
+     * 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. */
+        status = gcvSTATUS_OUT_OF_MEMORY;
+        goto OnError;
+    }
+
+    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;
+#endif
+
+    /* Return pointer to the gckOS object. */
+    *Os = os;
+
+    /* Success. */
+    return gcvSTATUS_OK;
+
+OnError:
+#if !USE_NEW_LINUX_SIGNAL
+    /* 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));
+    }
+#endif
+
+    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));
+    }
+
+    kfree(os);
+
+    /* Return the error. */
+    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;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+#if !USE_NEW_LINUX_SIGNAL
+    /*
+     * Destroy the signal manager.
+     */
+
+    /* Destroy the mutex. */
+    gcmkVERIFY_OK(
+        gckOS_DeleteMutex(Os, Os->signal.lock));
+
+    /* Free the signal table. */
+    kfree(Os->signal.table);
+#endif
+
+    if (Os->heap != NULL)
+    {
+        /* Mark gckHEAP as gone. */
+        heap     = Os->heap;
+        Os->heap = NULL;
+
+        /* 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));
+
+    gcmkPRINT("$$FLUSH$$");
+
+    /* Mark the gckOS object as unknown. */
+    Os->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the gckOS object. */
+    kfree(Os);
+
+    /* Success. */
+    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 != NULL);
+
+    /* Do we have a heap? */
+    if (Os->heap != NULL)
+    {
+        /* 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;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Memory != NULL);
+
+    //gcmkHEADER_ARG("Os=0x%x Memory=0x%x", Os, memory);
+
+    /* Do we have a heap? */
+    if (Os->heap != NULL)
+    {
+        /* 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 != NULL);
+
+    memory = (gctPOINTER) kmalloc(Bytes, GFP_ATOMIC);
+
+    if (memory == NULL)
+    {
+        /* Out of memory. */
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    /* Return pointer to the memory allocation. */
+    *Memory = memory;
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Memory=%p", *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=%p", Memory);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Memory != NULL);
+
+    /* 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;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != 0);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+    MEMORY_LOCK(Os);
+
+    mdlMap = FindMdlMap(mdl, current->tgid);
+
+    if (mdlMap == gcvNULL)
+    {
+        mdlMap = _CreateMdlMap(mdl, current->tgid);
+
+        if (mdlMap == gcvNULL)
+        {
+            MEMORY_UNLOCK(Os);
+
+            return gcvSTATUS_OUT_OF_MEMORY;
+        }
+    }
+
+    if (mdlMap->vmaAddr == gcvNULL)
+    {
+        down_write(&current->mm->mmap_sem);
+
+        mdlMap->vmaAddr = (char *)do_mmap_pgoff(NULL,
+                    0L,
+                    mdl->numPages * PAGE_SIZE,
+                    PROT_READ | PROT_WRITE,
+                    MAP_SHARED,
+                    0);
+
+        if (mdlMap->vmaAddr == gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+                gcvZONE_OS,
+                "gckOS_MapMemory: do_mmap_pgoff error");
+
+            gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+                gcvZONE_OS,
+                "[gckOS_MapMemory] mdl->numPages: %d",
+                "[gckOS_MapMemory] mdl->vmaAddr: 0x%x",
+                mdl->numPages,
+                mdlMap->vmaAddr
+                );
+
+            up_write(&current->mm->mmap_sem);
+
+            MEMORY_UNLOCK(Os);
+
+            return gcvSTATUS_OUT_OF_MEMORY;
+        }
+
+        mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+        if (!mdlMap->vma)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+                    gcvZONE_OS,
+                    "gckOS_MapMemory: find_vma error.");
+
+            mdlMap->vmaAddr = gcvNULL;
+
+            up_write(&current->mm->mmap_sem);
+
+            MEMORY_UNLOCK(Os);
+
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+
+#ifndef NO_DMA_COHERENT
+        if (dma_mmap_coherent(NULL,
+                    mdlMap->vma,
+                    mdl->addr,
+                    mdl->dmaHandle,
+                    mdl->numPages * PAGE_SIZE) < 0)
+        {
+            up_write(&current->mm->mmap_sem);
+
+            gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+                    gcvZONE_OS,
+                    "gckOS_MapMemory: dma_mmap_coherent error.");
+
+            mdlMap->vmaAddr = gcvNULL;
+
+            MEMORY_UNLOCK(Os);
+
+            return 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) < 0)
+        {
+            up_write(&current->mm->mmap_sem);
+
+            gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+                    gcvZONE_OS,
+                    "gckOS_MapMemory: remap_pfn_range error.");
+
+            mdlMap->vmaAddr = gcvNULL;
+
+            MEMORY_UNLOCK(Os);
+
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+#endif
+
+        up_write(&current->mm->mmap_sem);
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    *Logical = mdlMap->vmaAddr;
+
+    gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_OS,
+                "gckOS_MapMemory: User Mapped address for 0x%x is 0x%x pid->%d",
+                (gctUINT32)mdl->addr,
+                (gctUINT32)*Logical,
+                mdlMap->pid);
+
+    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
+    )
+{
+    PLINUX_MDL_MAP          mdlMap;
+    PLINUX_MDL              mdl = (PLINUX_MDL)Physical;
+    struct task_struct *    task;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != 0);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_UnmapMemory");
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_UnmapMemory Will be unmapping 0x%x mdl->0x%x",
+                (gctUINT32)Logical,
+                (gctUINT32)mdl);
+
+    MEMORY_LOCK(Os);
+
+    if (Logical)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+            gcvZONE_OS,
+            "[gckOS_UnmapMemory] Logical: 0x%x",
+            Logical
+            );
+
+        mdlMap = FindMdlMap(mdl, current->tgid);
+
+        if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
+        {
+            MEMORY_UNLOCK(Os);
+
+            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,
+                        "Can't find the task with pid->%d. No unmapping",
+                        mdlMap->pid);
+        }
+
+        gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    /* Success. */
+    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;
+    PLINUX_MDL_MAP  mdlMap = 0;
+    gctSTRING       addr;
+
+#ifdef NO_DMA_COHERENT
+    struct page *   page;
+    long            size, order;
+    gctPOINTER      vaddr;
+#endif
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT((Bytes != NULL) && (*Bytes > 0));
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_AllocateNonPagedMemory");
+
+    /* 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(current->tgid);
+
+    if (mdl == gcvNULL)
+    {
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    mdl->pagedMem = 0;
+    mdl->numPages = numPages;
+
+    MEMORY_LOCK(Os);
+
+#ifndef NO_DMA_COHERENT
+    addr = dma_alloc_coherent(NULL,
+                mdl->numPages * PAGE_SIZE,
+                &mdl->dmaHandle,
+                GFP_ATOMIC);
+#else
+    size    = mdl->numPages * PAGE_SIZE;
+    order   = get_order(size);
+    page    = alloc_pages(GFP_KERNEL | GFP_DMA, order);
+
+    if (page == gcvNULL)
+    {
+        MEMORY_UNLOCK(Os);
+
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    vaddr           = (gctPOINTER)page_address(page);
+    addr            = ioremap_nocache(virt_to_phys(vaddr), size);
+    mdl->dmaHandle  = virt_to_phys(vaddr);
+    mdl->kaddr      = vaddr;
+
+#if ENABLE_ARM_L2_CACHE
+    dma_cache_maint(vaddr, size, DMA_FROM_DEVICE);
+#endif
+
+    while (size > 0)
+    {
+        SetPageReserved(virt_to_page(vaddr));
+
+        vaddr   += PAGE_SIZE;
+        size    -= PAGE_SIZE;
+    }
+#endif
+
+    if (addr == gcvNULL)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "galcore: Can't allocate memorry for size->0x%x",
+                (gctUINT32)bytes);
+
+        gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+        MEMORY_UNLOCK(Os);
+
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    if ((Os->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000))
+    {
+        mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
+                       | (Os->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, current->tgid);
+
+        if (mdlMap == gcvNULL)
+        {
+            gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+            MEMORY_UNLOCK(Os);
+
+            return 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 (mdlMap->vmaAddr == gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "galcore: do_mmap_pgoff error");
+
+            up_write(&current->mm->mmap_sem);
+
+            gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+            gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+            MEMORY_UNLOCK(Os);
+
+            return gcvSTATUS_OUT_OF_MEMORY;
+        }
+
+        mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+        if (mdlMap->vma == gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "find_vma error");
+
+            up_write(&current->mm->mmap_sem);
+
+            gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+            gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+            MEMORY_UNLOCK(Os);
+
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+
+#ifndef NO_DMA_COHERENT
+        if (dma_mmap_coherent(NULL,
+                mdlMap->vma,
+                mdl->addr,
+                mdl->dmaHandle,
+                mdl->numPages * PAGE_SIZE) < 0)
+        {
+            up_write(&current->mm->mmap_sem);
+
+            gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "dma_mmap_coherent error");
+
+            gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+            gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+            MEMORY_UNLOCK(Os);
+
+            return 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))
+        {
+            up_write(&current->mm->mmap_sem);
+
+            gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                    gcvZONE_OS,
+                    "remap_pfn_range error");
+
+            gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+            gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+            MEMORY_UNLOCK(Os);
+
+            return 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);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_AllocateNonPagedMemory: "
+                "Bytes->0x%x, Mdl->%p, Logical->0x%x dmaHandle->0x%x",
+                (gctUINT32)bytes,
+                mdl,
+                (gctUINT32)mdl->addr,
+                mdl->dmaHandle);
+
+    if (InUserSpace)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "vmaAddr->0x%x pid->%d",
+                (gctUINT32)mdlMap->vmaAddr,
+                mdlMap->pid);
+    }
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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 */
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Physical != 0);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_FreeNonPagedMemory");
+
+    /* 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));
+
+    iounmap(mdl->addr);
+#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_INFO,
+                                gcvZONE_OS,
+                                "gckOS_FreeNonPagedMemory: "
+                                "Unmap Failed ->Mdl->0x%x Logical->0x%x vmaAddr->0x%x",
+                                (gctUINT32)mdl,
+                                (gctUINT32)mdl->addr,
+                                (gctUINT32)mdlMap->vmaAddr);
+                }
+
+                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);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_FreeNonPagedMemory: "
+                "Mdl->0x%x Logical->0x%x",
+                (gctUINT32)mdl,
+                (gctUINT32)mdl->addr);
+
+    gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+    /* Success. */
+    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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Data != NULL);
+
+    *Data = readl((gctUINT8 *)Os->device->registerBase + Address);
+
+    /* Success. */
+    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
+    )
+{
+    writel(Data, (gctUINT8 *)Os->device->registerBase + Address);
+
+    /* Success. */
+    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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(PageSize != NULL);
+
+    /* Return the page size. */
+    *PageSize = (gctSIZE_T) PAGE_SIZE;
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_GetPhysicalAddressProcess
+**
+**  Get the physical system address of a corresponding virtual address for a
+**  given process.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER Logical
+**          Logical address.
+**
+**      gctUINT ProcessID
+**          Procedd 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 gctUINT ProcessID,
+    OUT gctUINT32 * Address
+    )
+{
+    return gckOS_GetPhysicalAddress(Os, Logical, Address);
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    PLINUX_MDL      mdl;
+    PLINUX_MDL_MAP  mdlMap;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    /*
+     * Try to search the address in our list.
+     * This could be an mmaped memory.
+      * Search in our list.
+      */
+
+    MEMORY_LOCK(Os);
+
+    mdl = Os->mdlHead;
+
+    while (mdl != gcvNULL)
+    {
+        /* Check for the logical address match. */
+        if (mdl->addr
+            && (gctUINT32)Logical >= (gctUINT32)mdl->addr
+            && (gctUINT32)Logical < ((gctUINT32)mdl->addr + mdl->numPages*PAGE_SIZE))
+        {
+            if (mdl->dmaHandle)
+            {
+                /* The memory was from coherent area. */
+                *Address = (gctUINT32)mdl->dmaHandle
+                            + (gctUINT32)((gctUINT32)Logical - (gctUINT32)mdl->addr);
+            }
+            else if (mdl->pagedMem)
+            {
+                if (mdl->contiguous)
+                {
+                    *Address = (gctUINT32)virt_to_phys(mdl->addr)
+                                + ((gctUINT32)Logical - (gctUINT32)mdl->addr);
+                }
+                else
+                {
+                    *Address = page_to_phys(vmalloc_to_page((gctSTRING)mdl->addr
+                                + ((gctUINT32)Logical - (gctUINT32)mdl->addr)));
+                }
+            }
+            else
+            {
+                *Address = (gctUINT32)virt_to_phys(mdl->addr)
+                            + ((gctUINT32)Logical - (gctUINT32)mdl->addr);
+            }
+            break;
+        }
+
+        mdlMap = FindMdlMap(mdl, current->tgid);
+
+        /* Is the given address within that range. */
+        if (mdlMap != gcvNULL
+            && mdlMap->vmaAddr != gcvNULL
+            && Logical >= mdlMap->vmaAddr
+            && Logical < (mdlMap->vmaAddr + mdl->numPages * PAGE_SIZE))
+        {
+            if (mdl->dmaHandle)
+            {
+                /* The memory was from coherent area. */
+                *Address = (gctUINT32)mdl->dmaHandle
+                            + (gctUINT32)((gctUINT32)Logical
+                            - (gctUINT32)mdlMap->vmaAddr);
+            }
+            else if (mdl->pagedMem)
+            {
+                if (mdl->contiguous)
+                {
+                    *Address = (gctUINT32)virt_to_phys(mdl->addr)
+                                + (gctUINT32)(Logical - mdlMap->vmaAddr);
+                }
+                else
+                {
+                    *Address = page_to_phys(vmalloc_to_page((gctSTRING)mdl->addr
+                                + ((gctUINT32)Logical - (gctUINT32)mdlMap->vmaAddr)));
+                }
+            }
+            else
+            {
+                /* Return the kernel virtual pointer based on this. */
+                *Address = (gctUINT32)virt_to_phys(mdl->addr)
+                            + (gctUINT32)(Logical - mdlMap->vmaAddr);
+            }
+            break;
+        }
+
+        mdl = mdl->next;
+    }
+
+    /* Subtract base address to get a GPU physical address. */
+    gcmkASSERT(*Address >= Os->baseAddress);
+    *Address -= Os->baseAddress;
+
+    MEMORY_UNLOCK(Os);
+
+    if (mdl == gcvNULL)
+    {
+        return gcvSTATUS_INVALID_ARGUMENT;
+    }
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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;
+
+    /* 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->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 == NULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+                          "gckOS_MapMemory: Failed to ioremap");
+
+            MEMORY_UNLOCK(Os);
+
+            /* Out of resources. */
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+
+        /* Return pointer to mapped memory. */
+        *Logical = logical;
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+                  "gckOS_MapPhysical: "
+                  "Physical->0x%X Bytes->0x%X Logical->0x%X MappingFound->%d",
+                  (gctUINT32) Physical,
+                  (gctUINT32) Bytes,
+                  (gctUINT32) *Logical,
+                   mdl ? 1 : 0);
+
+    /* Success. */
+    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;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+    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);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                    gcvZONE_OS,
+                    "gckOS_UnmapPhysical: "
+                    "Logical->0x%x Bytes->0x%x MappingFound(?)->%d",
+                    (gctUINT32)Logical,
+                    (gctUINT32)Bytes,
+                    mdl ? 1 : 0);
+
+    /* Success. */
+    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
+    )
+{
+    /* Validate the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+    /* Allocate a FAST_MUTEX structure. */
+    *Mutex = (gctPOINTER)kmalloc(sizeof(struct semaphore), GFP_KERNEL);
+
+    if (*Mutex == gcvNULL)
+    {
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    /* Initialize the semaphore.. Come up in unlocked state. */
+    init_MUTEX(*Mutex);
+
+    /* Return status. */
+    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
+    )
+{
+    /* Validate the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+    /* Delete the fast mutex. */
+    kfree(Mutex);
+
+    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
+    )
+{
+    /* Validate the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+    if (Timeout == gcvINFINITE)
+    {
+        down((struct semaphore *) Mutex);
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+
+    while (gcvTRUE)
+    {
+        /* Try to acquire the fast mutex. */
+        if (!down_trylock((struct semaphore *) Mutex))
+        {
+            /* Success. */
+            return gcvSTATUS_OK;
+        }
+
+               if (Timeout-- == 0) break;
+
+        /* Wait for 1 millisecond. */
+        gcmkVERIFY_OK(gckOS_Delay(Os, 1));
+    }
+
+    /* 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
+    )
+{
+    /* Validate the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+    /* Release the fast mutex. */
+    up((struct semaphore *) Mutex);
+
+    /* Success. */
+    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
+    )
+{
+    /* 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. */
+    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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    /* Exchange the pair of pointers. */
+    *OldValue = (gctPOINTER) atomic_xchg((atomic_t *) Target, (int) NewValue);
+
+    /* Success. */
+    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(gckOS_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_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
+    )
+{
+    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 the 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;
+
+    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. */
+    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
+    )
+{
+    /* Verify thearguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    mb();
+
+    /* Success. */
+    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
+    )
+{
+    return gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical);
+}
+
+/*******************************************************************************
+**
+**  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;
+    gctSTRING addr;
+    gctSIZE_T bytes;
+
+    gcmkHEADER_ARG("Os=0x%0x Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+
+    bytes = gcmALIGN(Bytes, PAGE_SIZE);
+
+    numPages = GetPageCount(bytes, 0);
+
+    MEMORY_LOCK(Os);
+
+    if (Contiguous)
+    {
+        addr = (char *)__get_free_pages(GFP_ATOMIC | GFP_DMA, GetOrder(numPages));
+    }
+    else
+    {
+        addr = vmalloc(bytes);
+    }
+
+    if (!addr)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_AllocatePagedMemoryEx: "
+                "Can't allocate memorry for size->0x%x",
+                (gctUINT32)bytes);
+
+        MEMORY_UNLOCK(Os);
+
+        gcmkHEADER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    mdl = _CreateMdl(current->tgid);
+
+    if (mdl == gcvNULL)
+    {
+        if (Contiguous)
+        {
+            free_pages((unsigned int) addr, GetOrder(mdl->numPages));
+        }
+        else
+        {
+            vfree(addr);
+        }
+
+        MEMORY_UNLOCK(Os);
+
+        gcmkHEADER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+        return 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((void *)(((unsigned long)addr) + i * PAGE_SIZE));
+        }
+        else
+        {
+            page = vmalloc_to_page((void *)(((unsigned long)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);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+                   "%s: Bytes=%lu Mdl=0x%08x Logical=0x%08x",
+                   __FUNCTION__, bytes, mdl, mdl->addr);
+
+    /* Success. */
+    gcmkHEADER_ARG("*Physical=0x%08x", *Physical);
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_FreePagedMemory");
+
+    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));
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_FreePagedMemory: Bytes->0x%x, Mdl->0x%x",
+                (gctUINT32)Bytes,
+                (gctUINT32)mdl);
+
+    /* Success. */
+    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.
+**
+**  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,
+    OUT gctPOINTER * Logical,
+    OUT gctSIZE_T * PageCount
+    )
+{
+    PLINUX_MDL      mdl;
+    PLINUX_MDL_MAP  mdlMap;
+    gctSTRING       addr;
+    unsigned long   start;
+    unsigned long   pfn;
+    gctINT          i;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+    gcmkVERIFY_ARGUMENT(PageCount != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_LockPages");
+
+    mdl = (PLINUX_MDL) Physical;
+
+    MEMORY_LOCK(Os);
+
+    mdlMap = FindMdlMap(mdl, current->tgid);
+
+    if (mdlMap == gcvNULL)
+    {
+        mdlMap = _CreateMdlMap(mdl, current->tgid);
+
+        if (mdlMap == gcvNULL)
+        {
+            MEMORY_UNLOCK(Os);
+
+            return gcvSTATUS_OUT_OF_MEMORY;
+        }
+    }
+
+    if (mdlMap->vmaAddr == gcvNULL)
+    {
+        down_write(&current->mm->mmap_sem);
+
+        mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(NULL,
+                        0L,
+                        mdl->numPages * PAGE_SIZE,
+                        PROT_READ | PROT_WRITE,
+                        MAP_SHARED,
+                        0);
+
+        up_write(&current->mm->mmap_sem);
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                        gcvZONE_OS,
+                        "gckOS_LockPages: "
+                        "vmaAddr->0x%x for phys_addr->0x%x",
+                        (gctUINT32)mdlMap->vmaAddr,
+                        (gctUINT32)mdl);
+
+        if (mdlMap->vmaAddr == gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                        gcvZONE_OS,
+                        "gckOS_LockPages: do_mmap_pgoff error");
+
+            MEMORY_UNLOCK(Os);
+
+            return gcvSTATUS_OUT_OF_MEMORY;
+        }
+
+        mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+        if (mdlMap->vma == gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                        gcvZONE_OS,
+                        "find_vma error");
+
+            mdlMap->vmaAddr = gcvNULL;
+
+            MEMORY_UNLOCK(Os);
+
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+
+        mdlMap->vma->vm_flags |= VM_RESERVED;
+        /* Make this mapping non-cached. */
+        mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
+
+        addr = mdl->addr;
+
+        /* Now map all the vmalloc pages to this user address. */
+        down_write(&current->mm->mmap_sem);
+
+        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,
+                            "gckOS_LockPages: unable to mmap ret");
+
+                mdlMap->vmaAddr = gcvNULL;
+
+                MEMORY_UNLOCK(Os);
+
+                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,
+                                "gckOS_LockPages: "
+                                "gctPHYS_ADDR->0x%x Logical->0x%x Unable to map addr->0x%x to start->0x%x",
+                                (gctUINT32)Physical,
+                                (gctUINT32)*Logical,
+                                (gctUINT32)addr,
+                                (gctUINT32)start);
+
+                    mdlMap->vmaAddr = gcvNULL;
+
+                    MEMORY_UNLOCK(Os);
+
+                    return gcvSTATUS_OUT_OF_MEMORY;
+                }
+
+                start += PAGE_SIZE;
+                addr += PAGE_SIZE;
+            }
+        }
+
+        up_write(&current->mm->mmap_sem);
+    }
+
+    /* 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);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_LockPages: "
+                "gctPHYS_ADDR->0x%x Bytes->0x%x Logical->0x%x pid->%d",
+                (gctUINT32)Physical,
+                (gctUINT32)Bytes,
+                (gctUINT32)*Logical,
+                mdlMap->pid);
+
+    /* Success. */
+    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
+    )
+{
+    PLINUX_MDL  mdl;
+    gctUINT32*  table;
+    gctSTRING   addr;
+    gctINT      i = 0;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+    gcmkVERIFY_ARGUMENT(PageCount > 0);
+    gcmkVERIFY_ARGUMENT(PageTable != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_MapPages");
+
+    /* Convert pointer to MDL. */
+    mdl = (PLINUX_MDL)Physical;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_MapPages: "
+                "Physical->0x%x PageCount->0x%x PagedMemory->?%d",
+                (gctUINT32)Physical,
+                (gctUINT32)PageCount,
+                mdl->pagedMem);
+
+    MEMORY_LOCK(Os);
+
+    table = (gctUINT32 *)PageTable;
+
+     /* 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 (mdl->contiguous)
+            {
+                *table++ = virt_to_phys(addr);
+            }
+            else
+            {
+                *table++ = page_to_phys(vmalloc_to_page(addr));
+            }
+
+            addr += 4096;
+            i++;
+        }
+    }
+    else
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                    gcvZONE_OS,
+                    "We should not get this call for Non Paged Memory!");
+
+        while (PageCount-- > 0)
+        {
+            *table++ = (gctUINT32)virt_to_phys(addr);
+            addr += 4096;
+        }
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+    /* Make sure there is already a mapping...*/
+    gcmkVERIFY_ARGUMENT(mdl->addr != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_UnlockPages");
+
+    MEMORY_LOCK(Os);
+
+    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);
+                do_munmap(task->mm, (unsigned long)Logical, mdl->numPages * PAGE_SIZE);
+                up_write(&task->mm->mmap_sem);
+            }
+
+            mdlMap->vmaAddr = gcvNULL;
+        }
+
+        mdlMap = mdlMap->next;
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    /* Success. */
+    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
+    )
+{
+    /* Same as non-paged memory for now. */
+    return gckOS_AllocateNonPagedMemory(Os,
+                InUserSpace,
+                Bytes,
+                Physical,
+                Logical
+                );
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    /* Same of non-paged memory for now. */
+    return gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical);
+}
+
+/******************************************************************************
+**
+**  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
+    )
+{
+    gceSTATUS status;
+
+    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->kernel;
+
+        /* 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. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+#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_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "Failed to allocate memory at line %d in %s.",
+            __LINE__, __FILE__
+            );
+
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    len = copy_from_user(buf, Pointer, Size);
+    if (len != 0)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "Failed to copy data from user at line %d in %s.",
+            __LINE__, __FILE__
+            );
+
+        if (buf != gcvNULL)
+        {
+            kfree(buf);
+        }
+
+        return gcvSTATUS_GENERIC_IO;
+    }
+
+    *KernelPointer = buf;
+#else
+    *KernelPointer = Pointer;
+#endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
+
+    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
+    )
+{
+#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_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "Failed to copy data to user at line %d in %s.",
+            __LINE__, __FILE__
+            );
+        return gcvSTATUS_GENERIC_IO;
+    }
+#endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
+
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Address != NULL);
+
+    /* Write memory. */
+    writel(Data, (gctUINT8 *)Address);
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+#if USE_NEW_LINUX_SIGNAL
+    return gcvSTATUS_NOT_SUPPORTED;
+#else
+    gcsSIGNAL_PTR signal;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Signal != NULL);
+
+    /* Create an event structure. */
+    signal = (gcsSIGNAL_PTR)kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL);
+
+    if (signal == gcvNULL)
+    {
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    signal->manualReset = ManualReset;
+
+    init_completion(&signal->event);
+
+    atomic_set(&signal->ref, 1);
+
+    *Signal = (gctSIGNAL) signal;
+
+    return gcvSTATUS_OK;
+#endif
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+#if USE_NEW_LINUX_SIGNAL
+    return gcvSTATUS_NOT_SUPPORTED;
+#else
+    gcsSIGNAL_PTR signal;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Signal != NULL);
+
+    signal = (gcsSIGNAL_PTR) Signal;
+
+    if (atomic_dec_and_test(&signal->ref))
+    {
+         /* Free the sgianl. */
+        kfree(Signal);
+    }
+
+    /* Success. */
+    return gcvSTATUS_OK;
+#endif
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+#if USE_NEW_LINUX_SIGNAL
+    return gcvSTATUS_NOT_SUPPORTED;
+#else
+    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;
+
+    /* Set the new state of the event. */
+    if (signal->manualReset)
+    {
+        if (State)
+        {
+            /* Set the event to a signaled state. */
+            complete_all(&signal->event);
+        }
+        else
+        {
+            /* Set the event to an unsignaled state. */
+            INIT_COMPLETION(signal->event);
+        }
+    }
+    else
+    {
+        if (State)
+        {
+            /* Set the event to a signaled state. */
+            complete(&signal->event);
+
+        }
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+#endif
+}
+
+#if USE_NEW_LINUX_SIGNAL
+/*******************************************************************************
+**
+**  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;
+    gctINT result;
+    struct task_struct * task;
+    struct siginfo info;
+
+    task = FIND_TASK_BY_PID((pid_t) Process);
+
+    if (task != gcvNULL)
+    {
+        /* Fill in the siginfo structure. */
+        info.si_signo = Os->device->signal;
+        info.si_errno = 0;
+        info.si_code  = __SI_CODE(__SI_RT, SI_KERNEL);
+        info.si_ptr   = Signal;
+
+        /* Send the signal. */
+        if ((result = send_sig_info(Os->device->signal, &info, task)) < 0)
+        {
+            status = gcvSTATUS_GENERIC_IO;
+
+            gcmkTRACE(gcvLEVEL_ERROR,
+                     "%s(%d): send_sig_info failed.",
+                     __FUNCTION__, __LINE__);
+        }
+        else
+        {
+            /* Success. */
+            status = gcvSTATUS_OK;
+        }
+    }
+    else
+    {
+        status = gcvSTATUS_GENERIC_IO;
+
+        gcmkTRACE(gcvLEVEL_ERROR,
+                 "%s(%d): find_task_by_pid failed.",
+                 __FUNCTION__, __LINE__);
+    }
+
+    /* Return status. */
+    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
+    )
+{
+    return gcvSTATUS_NOT_SUPPORTED;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    return gcvSTATUS_NOT_SUPPORTED;
+}
+
+#else
+
+/*******************************************************************************
+**
+**  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=%d Process=0x%x",
+                   Os, (gctINT) Signal, Process);
+
+    /* Map the signal into kernel space. */
+    gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
+
+    /* Signal. */
+    status = gckOS_Signal(Os, signal, gcvTRUE);
+    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;
+    gcsSIGNAL_PTR signal;
+    gctUINT timeout;
+    gctUINT rc;
+
+    gcmkHEADER_ARG("Os=0x%x Signal=0x%x Wait=%u", Os, Signal, Wait);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+    signal = (gcsSIGNAL_PTR) Signal;
+
+    /* Convert wait to milliseconds. */
+    timeout = (Wait == gcvINFINITE) ? MAX_SCHEDULE_TIMEOUT : Wait*HZ/1000;
+
+    /* Linux bug ? */
+    if (!signal->manualReset && timeout == 0) timeout = 1;
+
+    rc = wait_for_completion_interruptible_timeout(&signal->event, timeout);
+    status = ((rc == 0) && !signal->event.done) ? gcvSTATUS_TIMEOUT
+                                                : gcvSTATUS_OK;
+
+    /* Return status. */
+    gcmkFOOTER();
+    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_INVALID_ARGUMENT);
+        }
+    }
+    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_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;
+    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) current->tgid;
+
+    table[currentID] = signal;
+
+    /* Plus 1 to avoid NULL 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_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "gckOS_DestroyUserSignal: invalid signal->%d.",
+            (gctINT) SignalID
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    SignalID -= 1;
+
+    signal = Os->signal.table[SignalID];
+
+    if (signal == gcvNULL)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "gckOS_DestroyUserSignal: signal is NULL."
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    /* Check to see if the process is the owner of the signal. */
+    if (signal->process != (gctHANDLE) current->tgid)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "gckOS_DestroyUserSignal: process id doesn't match. ",
+            "signal->process: %d, current->tgid: %d",
+            signal->process,
+            current->tgid);
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    gcmkONERROR(
+        gckOS_DestroySignal(Os, signal));
+
+    /* Update the table. */
+    Os->signal.table[SignalID] = gcvNULL;
+    if (Os->signal.unused++ == 0)
+    {
+        Os->signal.currentID = SignalID;
+    }
+
+    gcmkVERIFY_OK(
+        gckOS_ReleaseMutex(Os, Os->signal.lock));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkONERROR(
+            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_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "gckOS_WaitSignal: invalid signal.",
+            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_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "gckOS_WaitSignal: signal is NULL."
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    if (signal->process != (gctHANDLE) current->tgid)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "gckOS_WaitUserSignal: process id doesn't match. "
+            "signal->process: %d, current->tgid: %d",
+            signal->process,
+            current->tgid);
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+
+do{
+    status = gckOS_WaitSignal(Os, signal, Wait==gcvINFINITE?5000:Wait);
+if(Wait==gcvINFINITE&&status==gcvSTATUS_TIMEOUT){gcmkPRINT("$$FLUSH$$");}
+}while(status==gcvSTATUS_TIMEOUT&&Wait==gcvINFINITE);
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkONERROR(
+            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_ZONE(gcvLEVEL_ERROR,  gcvZONE_OS,
+                       "gckOS_WaitSignal: invalid signal->%d.", 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_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "gckOS_WaitSignal: signal is NULL."
+            );
+
+        gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+    }
+
+    if (signal->process != (gctHANDLE) current->tgid)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "gckOS_DestroyUserSignal: process id doesn't match. ",
+            "signal->process: %d, current->tgid: %d",
+            signal->process,
+            current->tgid);
+
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    status = gckOS_Signal(Os, signal, State);
+
+    /* Success. */
+    gcmkFOOTER();
+    return status;
+
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkONERROR(
+            gckOS_ReleaseMutex(Os, Os->signal.lock));
+    }
+
+    /* Return the staus. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckOS_CleanProcessSignal(
+    gckOS Os,
+    gctHANDLE Process
+    )
+{
+    gctINT signal;
+
+    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
+            ));
+
+        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
+        ));
+
+    return gcvSTATUS_OK;
+}
+
+#endif /* USE_NEW_LINUX_SIGNAL */
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    gceSTATUS status;
+    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);
+
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+        gcvZONE_OS,
+        "[gckOS_MapUserMemory] enter."
+        );
+
+    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,
+            "[gckOS_MapUserMemory] pageCount: %d.",
+            pageCount
+            );
+
+        /* Invalid argument. */
+        if (pageCount == 0)
+        {
+            return gcvSTATUS_INVALID_ARGUMENT;
+        }
+
+        /* Overflow. */
+        if ((memory + Size) < memory)
+        {
+            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,
+                    NULL
+                    );
+        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_alloc(current->mm, pgd, memory);
+                    if (pud)
+                    {
+                        pmd_t * pmd = pmd_alloc(current->mm, pud, memory);
+                        if (pmd)
+                        {
+                            pte = pte_offset_map_lock(current->mm, pmd, memory, &ptl);
+                            if (!pte)
+                            {
+                                break;
+                            }
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        break;
+                    }
+
+                    pfn      = pte_pfn(*pte);
+                    *Address = ((pfn << PAGE_SHIFT) | (((unsigned long)Memory) & ~PAGE_MASK))
+                                - Os->baseAddress;
+                    *Info    = gcvNULL;
+
+                    pte_unmap_unlock(pte, ptl);
+
+                    /* Release page info struct. */
+                    if (info != gcvNULL)
+                    {
+                        /* Free the page info struct. */
+                        kfree(info);
+                    }
+
+                    if (pages != gcvNULL)
+                    {
+                        /* Free the page table. */
+                        kfree(pages);
+                    }
+
+                    MEMORY_MAP_UNLOCK(Os);
+
+                    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 the data cache. */
+#ifdef ANDROID
+            dma_sync_single_for_device(
+                        gcvNULL,
+                        page_to_phys(pages[i]),
+                        PAGE_SIZE,
+                        DMA_TO_DEVICE);
+#else
+            flush_dcache_page(pages[i]);
+#endif
+        }
+
+        /* Allocate pages inside the page table. */
+        gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernel->mmu,
+                                          pageCount * (PAGE_SIZE/4096),
+                                          (gctPOINTER *) &pageTable,
+                                          &address));
+
+        /* Fill the page table. */
+        for (i = 0; i < pageCount; i++)
+        {
+            /* Get the physical address from page struct. */
+            pageTable[i * (PAGE_SIZE/4096)] = page_to_phys(pages[i]);
+
+            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,
+                "[gckOS_MapUserMemory] pages[%d]: 0x%x, pageTable[%d]: 0x%x.",
+                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,
+            "[gckOS_MapUserMemory] info->pages: 0x%x, info->pageTable: 0x%x, info: 0x%x.",
+            info->pages,
+            info->pageTable,
+            info
+            );
+
+        /* Return address. */
+        *Address = address + (memory & ~PAGE_MASK);
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO,
+            gcvZONE_OS,
+            "[gckOS_MapUserMemory] Address: 0x%x.",
+            *Address
+            );
+
+        /* Success. */
+        status = gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    if (gcmIS_ERROR(status))
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "[gckOS_MapUserMemory] error occured: %d.",
+            status
+            );
+
+        /* Release page array. */
+        if (result > 0 && pages != gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+                gcvZONE_OS,
+                "[gckOS_MapUserMemory] error: page table is freed."
+                );
+
+            for (i = 0; i < result; i++)
+            {
+                if (pages[i] == gcvNULL)
+                {
+                    break;
+                }
+#ifdef ANDROID
+                dma_sync_single_for_device(
+                            gcvNULL,
+                            page_to_phys(pages[i]),
+                            PAGE_SIZE,
+                            DMA_FROM_DEVICE);
+#endif
+                page_cache_release(pages[i]);
+            }
+        }
+
+        if (pages != gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+                gcvZONE_OS,
+                "[gckOS_MapUserMemory] error: pages is freed."
+                );
+
+            /* Free the page table. */
+            kfree(pages);
+            info->pages = gcvNULL;
+        }
+
+        /* Release page info struct. */
+        if (info != gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+                gcvZONE_OS,
+                "[gckOS_MapUserMemory] error: info is freed."
+                );
+
+            /* Free the page info struct. */
+            kfree(info);
+            *Info = gcvNULL;
+        }
+    }
+
+    MEMORY_MAP_UNLOCK(Os);
+
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+        gcvZONE_OS,
+        "[gckOS_MapUserMemory] leave."
+        );
+
+    /* Return the status. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    gceSTATUS status;
+    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);
+
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+        gcvZONE_OS,
+        "[gckOS_UnmapUserMemory] enter."
+        );
+
+    do
+    {
+        info = (gcsPageInfo_PTR) Info;
+
+        if (info == gcvNULL)
+        {
+            return gcvSTATUS_OK;
+        }
+
+        pages = info->pages;
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO,
+            gcvZONE_OS,
+            "[gckOS_UnmapUserMemory] info: 0x%x, pages: 0x%x.",
+            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,
+            "[gckOS_UnmapUserMemory] memory: 0x%x, pageCount: %d, pageTable: 0x%x.",
+            memory,
+            pageCount,
+            info->pageTable
+            );
+
+        MEMORY_MAP_LOCK(Os);
+
+        /* Free the pages from the MMU. */
+        gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernel->mmu,
+                                      info->pageTable,
+                                      pageCount * (PAGE_SIZE/4096)
+                                      ));
+
+        /* Release the page cache. */
+        for (i = 0; i < pageCount; i++)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "[gckOS_UnmapUserMemory] pages[%d]: 0x%x.",
+                i,
+                pages[i]
+                );
+
+            if (!PageReserved(pages[i]))
+            {
+                SetPageDirty(pages[i]);
+            }
+
+#ifdef ANDROID
+            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. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+    /* Return base address. */
+    *BaseAddress = Os->baseAddress;
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+    IN gckOS Os
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    disable_irq(Os->device->irqLine);
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+    IN gckOS Os
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    enable_irq(Os->device->irqLine);
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_MemCopy(
+        IN gctPOINTER Destination,
+        IN gctCONST_POINTER Source,
+        IN gctSIZE_T Bytes
+        )
+{
+        gcmkVERIFY_ARGUMENT(Destination != NULL);
+        gcmkVERIFY_ARGUMENT(Source != NULL);
+        gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+        memcpy(Destination, Source, Bytes);
+
+        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;
+}
+
+#if gcdkUSE_MEMORY_RECORD
+MEMORY_RECORD_PTR
+CreateMemoryRecord(
+    gckOS Os,
+    MEMORY_RECORD_PTR List,
+    gcuVIDMEM_NODE_PTR Node
+    )
+{
+    MEMORY_RECORD_PTR   mr;
+
+    mr = (MEMORY_RECORD_PTR)kmalloc(sizeof(struct MEMORY_RECORD), GFP_ATOMIC);
+    if (mr == gcvNULL) return gcvNULL;
+
+    MEMORY_LOCK(Os);
+
+    mr->node            = Node;
+
+    mr->prev            = List->prev;
+    mr->next            = List;
+    List->prev->next    = mr;
+    List->prev          = mr;
+
+    MEMORY_UNLOCK(Os);
+
+    return mr;
+}
+
+void
+DestoryMemoryRecord(
+    gckOS Os,
+    MEMORY_RECORD_PTR Mr
+    )
+{
+    MEMORY_LOCK(Os);
+
+    Mr->prev->next      = Mr->next;
+    Mr->next->prev      = Mr->prev;
+
+    MEMORY_UNLOCK(Os);
+
+    kfree(Mr);
+}
+
+MEMORY_RECORD_PTR
+FindMemoryRecord(
+    gckOS Os,
+    MEMORY_RECORD_PTR List,
+    gcuVIDMEM_NODE_PTR Node
+    )
+{
+    MEMORY_RECORD_PTR mr;
+
+    MEMORY_LOCK(Os);
+
+    mr = List->next;
+
+    while (mr != List)
+    {
+        if (mr->node == Node)
+        {
+            MEMORY_UNLOCK(Os);
+
+            return mr;
+        }
+
+        mr = mr->next;
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    return gcvNULL;
+}
+
+void
+FreeAllMemoryRecord(
+    gckOS Os,
+    MEMORY_RECORD_PTR List
+    )
+{
+    MEMORY_RECORD_PTR mr;
+    gctUINT i = 0;
+
+    MEMORY_LOCK(Os);
+
+    while (List->next != List)
+    {
+        mr = List->next;
+
+        mr->prev->next      = mr->next;
+        mr->next->prev      = mr->prev;
+
+        i++;
+
+        MEMORY_UNLOCK(Os);
+
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+                gcvZONE_OS,
+                "Unfreed %s memory: node: %p",
+                (mr->node->VidMem.memory->object.type == gcvOBJ_VIDMEM)?
+                    "video" : (mr->node->Virtual.contiguous)?
+                        "contiguous" : "virtual",
+                mr->node);
+
+        while (gcvTRUE)
+        {
+            if (mr->node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+            {
+                if (mr->node->VidMem.locked == 0) break;
+            }
+            else
+            {
+                if (mr->node->Virtual.locked == 0) break;
+            }
+
+            gckVIDMEM_Unlock(mr->node, gcvSURF_TYPE_UNKNOWN, gcvNULL);
+        }
+
+        gckVIDMEM_Free(mr->node);
+
+        kfree(mr);
+
+        MEMORY_LOCK(Os);
+    }
+
+    MEMORY_UNLOCK(Os);
+
+    if (i > 0)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+                gcvZONE_OS,
+                "======== Total %d unfreed video/contiguous/virtual memory ========", i);
+    }
+}
+#endif
+
+/*******************************************************************************
+**  gckOS_CacheFlush
+**
+**  Flush 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.
+**
+**      gctHANDLE Process
+**          Process handle Logical belongs to or gcvNULL if Logical belongs to
+**          the kernel.
+**
+**      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 gctHANDLE Process,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**  gckOS_CacheInvalidate
+**
+**  Flush 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.
+**
+**      gctHANDLE Process
+**          Process handle Logical belongs to or gcvNULL if Logical belongs to
+**          the kernel.
+**
+**      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 gctHANDLE Process,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    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;
+    gctUINT32 idle = 0, dma = 0, axi = 0, read0 = 0, read1 = 0, write = 0;
+
+    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));
+
+        break;
+
+    case gcvBROADCAST_GPU_COMMIT:
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
+
+        /* Put GPU ON. */
+        gcmkONERROR(
+            gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON));
+        break;
+
+    case gcvBROADCAST_GPU_STUCK:
+               gcmkONERROR(gckHARDWARE_GetIdle(Hardware, gcvFALSE, &idle));
+        gcmkONERROR(gckOS_ReadRegister(Os, 0x00C, &axi));
+               gcmkONERROR(gckOS_ReadRegister(Os, 0x664, &dma));
+        gcmkPRINT("!!FATAL!! GPU Stuck");
+        gcmkPRINT("  idle=0x%08X axi=0x%08X cmd=0x%08X", idle, axi, dma);
+
+        if (Hardware->chipFeatures & (1 << 4))
+        {
+            gcmkONERROR(gckOS_ReadRegister(Os, 0x43C, &read0));
+            gcmkONERROR(gckOS_ReadRegister(Os, 0x440, &read1));
+            gcmkONERROR(gckOS_ReadRegister(Os, 0x444, &write));
+            gcmkPRINT("  read0=0x%08X read1=0x%08X write=0x%08X",
+                      read0, read1, write);
+        }
+
+        gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
+        break;
+
+    case gcvBROADCAST_AXI_BUS_ERROR:
+        gcmkONERROR(gckHARDWARE_GetIdle(Hardware, gcvFALSE, &idle));
+        gcmkONERROR(gckOS_ReadRegister(Os, 0x00C, &axi));
+        gcmkONERROR(gckOS_ReadRegister(Os, 0x664, &dma));
+        gcmkPRINT("!!FATAL!! AXI Bus Error");
+        gcmkPRINT("  idle=0x%08X axi=0x%08X cmd=0x%08X", idle, axi, dma);
+
+        if (Hardware->chipFeatures & (1 << 4))
+        {
+            gcmkONERROR(gckOS_ReadRegister(Os, 0x43C, &read0));
+            gcmkONERROR(gckOS_ReadRegister(Os, 0x440, &read1));
+            gcmkONERROR(gckOS_ReadRegister(Os, 0x444, &write));
+            gcmkPRINT("  read0=0x%08X read1=0x%08X write=0x%08X",
+                      read0, read1, write);
+        }
+
+        gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
+        break;
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+********************************** 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;
+
+    gcmkHEADER_ARG("Os=0x%x", Os);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+    /* Allocate the semaphore structure. */
+    gcmkONERROR(
+        gckOS_Allocate(Os, gcmSIZEOF(struct semaphore), (gctPOINTER *) &sem));
+
+    /* 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%x", Os);
+
+    /* 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_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
+    )
+{
+    gceSTATUS status;
+
+    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. */
+    gcmkONERROR(gckOS_Free(Os, Semaphore));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    gcmkHEADER();
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(ProcessID != gcvNULL);
+
+    /* Get process ID. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+    *ProcessID = task_tgid_vnr(current);
+#else
+    *ProcessID = current->tgid;
+#endif
+
+    /* Success. */
+    gcmkFOOTER_ARG("*ProcessID=%u", *ProcessID);
+    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
+    )
+{
+    gcmkHEADER();
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(ThreadID != gcvNULL);
+
+    /* Get thread ID. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+    *ThreadID = task_pid_vnr(current);
+#else
+    *ThreadID = current->pid;
+#endif
+
+    /* Success. */
+    gcmkFOOTER_ARG("*ThreadID=%u", *ThreadID);
+    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;
+}
+
diff --git a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_os.h b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_os.h
new file mode 100644 (file)
index 0000000..087b55e
--- /dev/null
@@ -0,0 +1,106 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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, *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
+       );
+
+#ifdef gcdkUSE_MEMORY_RECORD
+MEMORY_RECORD_PTR
+CreateMemoryRecord(
+       gckOS Os,
+       MEMORY_RECORD_PTR List,
+       gcuVIDMEM_NODE_PTR Node
+       );
+
+void
+DestoryMemoryRecord(
+       gckOS Os,
+       MEMORY_RECORD_PTR Mr
+       );
+
+MEMORY_RECORD_PTR
+FindMemoryRecord(
+       gckOS Os,
+       MEMORY_RECORD_PTR List,
+       gcuVIDMEM_NODE_PTR Node
+       );
+
+void
+FreeAllMemoryRecord(
+       gckOS Os,
+       MEMORY_RECORD_PTR List
+       );
+#endif
+
+#endif /* __gc_hal_kernel_os_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/os/qnx/inc/gc_hal_common_qnx.h b/drivers/staging/rk29/vivante/hal/os/qnx/inc/gc_hal_common_qnx.h
new file mode 100644 (file)
index 0000000..a5d1bfe
--- /dev/null
@@ -0,0 +1,79 @@
+/****************************************************************************
+*
+*    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+*
+*    The material in this file is confidential and contains trade secrets
+*    of Vivante Corporation. This is proprietary information owned by
+*    Vivante Corporation. No part of this work may be disclosed,
+*    reproduced, copied, transmitted, or used in any way for any purpose,
+*    without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+*    Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+/*
+ * gc_hal_common_qnx.h
+ *
+ *  Created on: Jul 7, 2010
+ *      Author: tarang
+ */
+
+#ifndef GC_HAL_COMMON_QNX_H_
+#define GC_HAL_COMMON_QNX_H_
+
+/******************************************************************************\
+******************************* QNX Control Codes ******************************
+\******************************************************************************/
+#ifndef _IOMGR_VIVANTE
+#define _IOMGR_VIVANTE                                         (_IOMGR_PRIVATE_BASE + 0x301)
+#endif
+
+/*******************************************************************************
+**     Signal management.
+**
+**     Is much simpler in Neutrino versus Linux :-)
+**
+**     Neutrino pulses are equivalent to RT signals (queued, small payload) except
+**     they are explicitly received on a channel. We therefore dedicate a thread
+**     to handle them.
+**
+**     We don't use RT signals because:
+**     1. They can be delivered on any thread.
+**     2. We don't support SA_RESTART so blocking kernel calls can fail. It would be
+**        impossible to robustly handle this condition in all libraries.
+**
+**     Only downside is that more information needs to be passed between client/server
+**     (signals require only PID, pulses require connection ID and receive ID).
+*/
+
+typedef struct _gcsSIGNAL
+{
+       /* Pointer to gcoOS object. */
+       gcoOS                   os;
+
+       /* Signaled state. */
+       gctBOOL                 state;
+
+       /* Manual reset flag. */
+       gctBOOL                 manual;
+
+       /* Mutex. */
+       pthread_mutex_t mutex;
+
+       /* Condition. */
+       pthread_cond_t  condition;
+
+       /* Number of signals pending in the command queue. */
+       gctINT                  pending;
+
+       /* Number of signals received. */
+       gctINT                  received;
+}
+gcsSIGNAL;
+
+#endif /* GC_HAL_COMMON_QNX_H_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_debug.c b/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_debug.c
new file mode 100644 (file)
index 0000000..e8ca7e6
--- /dev/null
@@ -0,0 +1,435 @@
+/****************************************************************************
+*
+*    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+*
+*    The material in this file is confidential and contains trade secrets
+*    of Vivante Corporation. This is proprietary information owned by
+*    Vivante Corporation. No part of this work may be disclosed,
+*    reproduced, copied, transmitted, or used in any way for any purpose,
+*    without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+*    Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_qnx.h"
+#include <stdarg.h>
+
+/*
+       gcdBUFFERED_OUTPUT
+
+       When set to non-zero, all output is collected into a buffer with the
+       specified size.  Once the buffer gets full, or the token "$$FLUSH$$" has
+       been received, the debug buffer will be printed to the console.
+*/
+#define gcdBUFFERED_OUTPUT     0
+
+/******************************************************************************\
+******************************** Debug Variables *******************************
+\******************************************************************************/
+
+static gceSTATUS _lastError  = gcvSTATUS_OK;
+static gctUINT32 _debugLevel = gcvLEVEL_ERROR;
+static gctUINT32 _debugZones = gcvZONE_NONE;
+static gctINT    _indent     = 0;
+
+static void
+OutputDebugString(
+       IN gctCONST_STRING String
+       )
+{
+#if gcdBUFFERED_OUTPUT
+       static gctCHAR outputBuffer[gcdBUFFERED_OUTPUT];
+       static gctINT outputBufferIndex = 0;
+       gctINT n, i;
+
+       n = (String != gcvNULL) ? strlen(String) + 1 : 0;
+
+       if ((n == 0) || (outputBufferIndex + n > gcmSIZEOF(outputBuffer)))
+       {
+               for (i = 0; i < outputBufferIndex; i += strlen(outputBuffer + i) + 1)
+               {
+                       printf(outputBuffer + i);
+               }
+
+               outputBufferIndex = 0;
+       }
+
+       if (n > 0)
+       {
+               memcpy(outputBuffer + outputBufferIndex, String, n);
+               outputBufferIndex += n;
+       }
+#else
+       if (String != gcvNULL)
+       {
+               printf(String);
+       }
+#endif
+}
+
+static void
+_Print(
+       IN gctCONST_STRING Message,
+       IN va_list Arguments
+       )
+{
+       char buffer[1024];
+       int i, n;
+
+       if (strcmp(Message, "$$FLUSH$$") == 0)
+       {
+               OutputDebugString(gcvNULL);
+               return;
+       }
+
+       if (strncmp(Message, "--", 2) == 0)
+       {
+               if (_indent == 0)
+               {
+                       printf("ERROR: _indent=0\n");
+               }
+
+               _indent -= 2;
+       }
+
+       for (i = 0; i < _indent; ++i)
+       {
+               buffer[i] = ' ';
+       }
+
+       /* Print message to buffer. */
+       n = vsnprintf(buffer + i, sizeof(buffer) - i, Message, Arguments);
+       if ((n <= 0) || (buffer[i + n - 1] != '\n'))
+       {
+               /* Append new-line. */
+               strncat(buffer, "\n", sizeof(buffer));
+       }
+
+       /* Output to debugger. */
+       OutputDebugString(buffer);
+
+       if (strncmp(Message, "++", 2) == 0)
+       {
+               _indent += 2;
+       }
+}
+
+/******************************************************************************\
+********************************* Debug Macros *********************************
+\******************************************************************************/
+
+#define _DEBUGPRINT(Message) \
+{ \
+       va_list arguments; \
+       \
+       va_start(arguments, Message); \
+       _Print(Message, arguments); \
+       va_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,
+       ...
+       )
+{
+       _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+**     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;
+       }
+
+       _DEBUGPRINT(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;
+       }
+
+       _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+**     gckOS_DebugBreak
+**
+**     Break into the debugger.
+**
+**     INPUT:
+**
+**             Nothing.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+void
+gckOS_DebugBreak(
+       void
+       )
+{
+       gckOS_DebugTrace(gcvLEVEL_ERROR, "gckOS_DebugBreak");
+}
+
+/*******************************************************************************
+**
+**     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,
+       ...
+       )
+{
+       _DEBUGPRINT(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;
+}
+
diff --git a/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_device.c b/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_device.c
new file mode 100644 (file)
index 0000000..0ca6f4f
--- /dev/null
@@ -0,0 +1,812 @@
+/****************************************************************************
+*
+*    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+*
+*    The material in this file is confidential and contains trade secrets
+*    of Vivante Corporation. This is proprietary information owned by
+*    Vivante Corporation. No part of this work may be disclosed,
+*    reproduced, copied, transmitted, or used in any way for any purpose,
+*    without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+*    Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+
+#include "gc_hal_kernel_qnx.h"
+#include <sys/mman.h>
+#include <sys/siginfo.h>
+
+#define _GC_OBJ_ZONE   gcvZONE_DEVICE
+
+/******************************************************************************\
+******************************** gckGALDEVICE Code *******************************
+\******************************************************************************/
+
+gceSTATUS
+gckGALDEVICE_AllocateMemory(
+       IN gckGALDEVICE Device,
+       IN gctSIZE_T Bytes,
+    OUT gctPOINTER *Logical,
+    OUT gctPHYS_ADDR *Physical,
+    OUT gctUINT32 *PhysAddr
+       )
+{
+       gceSTATUS status;
+
+       gcmkVERIFY_ARGUMENT(Device != NULL);
+       gcmkVERIFY_ARGUMENT(Logical != NULL);
+       gcmkVERIFY_ARGUMENT(Physical != NULL);
+       gcmkVERIFY_ARGUMENT(PhysAddr != NULL);
+
+       status = gckOS_AllocateContiguous(Device->os,
+                                         gcvFALSE,
+                                         &Bytes,
+                                         Physical,
+                                         Logical);
+
+       if (gcmIS_ERROR(status))
+       {
+               gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                                  "gckGALDEVICE_AllocateMemory: error status->0x%x",
+                                  status);
+
+               return status;
+       }
+
+       *PhysAddr = (gctUINT32)(*(off_t*) Physical) - Device->baseAddress;
+       gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                          "gckGALDEVICE_AllocateMemory: phys_addr->0x%x phsical->0x%x Logical->0x%x",
+                          (gctUINT32)*Physical,
+                                  (gctUINT32)*PhysAddr,
+                                  (gctUINT32)*Logical);
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckGALDEVICE_FreeMemory(
+       IN gckGALDEVICE Device,
+       IN gctPOINTER Logical,
+       IN gctPHYS_ADDR Physical)
+{
+       gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    return gckOS_FreeContiguous(Device->os,
+                                                               Physical,
+                                                               Logical,
+                                                               0);
+}
+
+/* TODO. fix global sigevent to be part of device. */
+struct sigevent irqEvent;
+
+const struct sigevent* isrRoutine(void* arg, int id)
+{
+    gckGALDEVICE device = (gckGALDEVICE)arg;
+
+       /* Call kernel interrupt notification. */
+    if (gckKERNEL_Notify(device->kernel,
+                                                gcvNOTIFY_INTERRUPT,
+                                                gcvTRUE) == gcvSTATUS_OK)
+    {
+               InterruptUnmask(device->irqLine, device->irqId);
+
+               return &irqEvent;
+    }
+
+    return gcvNULL;
+}
+
+static void* threadRoutine(void *ctxt)
+{
+    gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+       gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                               "Starting ISR Thread with irq:%d\n",
+                               device->irqLine);
+
+       SIGEV_INTR_INIT(&irqEvent);
+
+       /* Obtain I/O privileges */
+       ThreadCtl( _NTO_TCTL_IO, 0 );
+
+       device->irqId = InterruptAttach(device->irqLine,
+                                                                       isrRoutine,
+                                                                       (void*)device,
+                                                                       gcmSIZEOF(struct _gckGALDEVICE),
+                                                                       0);
+
+       gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                               gcvZONE_DRIVER,
+                               "irqId:%d\n",
+                               device->irqId);
+
+       if (device->irqId < 0) {
+               gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                               gcvZONE_DRIVER,
+               "[galcore] gckGALDEVICE_Setup_ISR: "
+                               "Could not register irq line->%d\n",
+                               device->irqLine);
+
+               device->isrInitialized = gcvFALSE;
+
+               return (void *)1;
+       }
+
+       printf("[Interrupt] Attached irqLine %d with id %d.\n",
+               device->irqLine, device->irqId);
+
+       device->isrInitialized = gcvTRUE;
+
+       while (1)
+       {
+               if (InterruptWait(0, NULL) == -1)
+               {
+                       printf("[Interrupt] IST exiting\n");
+                       /* Either something is wrong or the thread got canceled */
+                       InterruptUnmask(device->irqLine, device->irqId);
+                       pthread_exit(NULL);
+               }
+
+               gckKERNEL_Notify(device->kernel, gcvNOTIFY_INTERRUPT, gcvFALSE);
+    }
+
+    return (void *)0;
+}
+
+/*******************************************************************************
+**
+**     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
+       )
+{
+       return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**     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
+       )
+{
+       gcmkVERIFY_ARGUMENT(Device != NULL);
+
+       return gcvSTATUS_OK;
+}
+
+
+int
+gsl_free_interrupts()
+{
+
+       return 0;
+}
+/*******************************************************************************
+**
+**     gckGALDEVICE_Start_Thread
+**
+**     Start the daemon thread.
+**
+**     INPUT:
+**
+**             gckGALDEVICE Device
+**                     Pointer to an gckGALDEVICE object.
+**
+**     OUTPUT:
+**
+**             Nothing.
+**
+**     RETURNS:
+**
+**             gcvSTATUS_OK
+**                     Start successfully.
+**             gcvSTATUS_GENERIC_IO
+**                     Start failed.
+*/
+gceSTATUS
+gckGALDEVICE_Start_Thread(
+       IN gckGALDEVICE Device
+       )
+{
+       pthread_attr_t attr;
+       struct sched_param sched;
+       gctINT ret;
+       gcmkVERIFY_ARGUMENT(Device != NULL);
+
+       gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                                 gcvZONE_DRIVER,
+                                 "[galcore] gckGALDEVICE_Start_Thread: Creating threadRoutine\n");
+
+       pthread_attr_init(&attr);
+       pthread_attr_getschedparam(&attr, &sched);
+       sched.sched_priority += 10;
+       pthread_attr_setschedparam(&attr, &sched);
+       pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+
+       /* Start the interrupt service thread */
+       if ((ret = pthread_create(&Device->threadCtxt, &attr, threadRoutine, Device)) != 0)
+       {
+               gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+                                         gcvZONE_DRIVER,
+                                         "[galcore] gckGALDEVICE_Start_Thread: Failed with code %d\n",
+                                         ret);
+
+               return gcvSTATUS_OUT_OF_RESOURCES;
+       }
+
+       pthread_setname_np(Device->threadCtxt, "galcore-IST");
+
+       Device->threadInitialized = gcvTRUE;
+       gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                                       gcvZONE_DRIVER,
+                                       "[galcore] gckGALDEVICE_Start_Thread: "
+                                       "Start the daemon thread.\n");
+
+       return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+**     gckGALDEVICE_Stop_Thread
+**
+**     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_Thread(
+       gckGALDEVICE Device
+       )
+{
+       gcmkVERIFY_ARGUMENT(Device != NULL);
+
+       /* stop the thread */
+       if (Device->threadInitialized)
+       {
+               InterruptDetach(Device->irqId);
+               Device->irqId = 0;
+               ConnectDetach(Device->coid);
+               Device->coid = 0;
+               ChannelDestroy(Device->chid);
+               Device->chid = 0;
+
+               pthread_cancel(Device->threadCtxt);
+               pthread_join(Device->threadCtxt, NULL);
+               Device->threadCtxt = 0;
+
+               Device->threadInitialized = gcvFALSE;
+               Device->isrInitialized = gcvFALSE;
+       }
+
+       return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**     gckGALDEVICE_Start
+**
+**     Start the gal device, including the following actions: setup the isr routine
+**  and start the daemon thread.
+**
+**     INPUT:
+**
+**             gckGALDEVICE Device
+**                     Pointer to an gckGALDEVICE object.
+**
+**     OUTPUT:
+**
+**             Nothing.
+**
+**     RETURNS:
+**
+**             gcvSTATUS_OK
+**                     Start successfully.
+*/
+gceSTATUS
+gckGALDEVICE_Start(
+       IN gckGALDEVICE Device
+       )
+{
+       gceSTATUS ret;
+       /* Start the daemon thread. */
+       gcmkVERIFY_OK((ret = gckGALDEVICE_Start_Thread(Device)));
+
+       return ret;
+}
+
+/*******************************************************************************
+**
+**     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
+    )
+{
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    if (Device->threadInitialized)
+    {
+       gckGALDEVICE_Stop_Thread(Device);
+    }
+
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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 gctUINT32 ContiguousBase,
+    IN gctSIZE_T ContiguousSize,
+    IN gctSIZE_T BankSize,
+    IN gctINT FastClear,
+       IN gctINT Compression,
+       IN gctUINT32 BaseAddress,
+    OUT gckGALDEVICE *Device
+    )
+{
+    gctUINT32 internalBaseAddress, internalAlignment;
+    gctUINT32 externalBaseAddress, externalAlignment;
+    gctUINT32 horizontalTileSize, verticalTileSize;
+    gctUINT32 physAddr;
+    gctUINT32 physical;
+    gckGALDEVICE device;
+    gceSTATUS status;
+
+    gcmkTRACE(gcvLEVEL_VERBOSE, "[galcore] Enter gckGALDEVICE_Construct\n");
+
+    /* Allocate device structure. */
+    device = calloc(1, sizeof(struct _gckGALDEVICE));
+    if (!device)
+    {
+       gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                     "[galcore] gckGALDEVICE_Construct: Can't allocate memory.\n");
+
+       return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    physical = RegisterMemBase;
+
+    /* Set up register memory region */
+    if (physical != 0)
+    {
+       /* Request a region. */
+               device->registerBase = (gctPOINTER)mmap_device_io(RegisterMemSize, RegisterMemBase);
+
+        if ((uintptr_t)device->registerBase == MAP_DEVICE_FAILED)
+               {
+           gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                         "[galcore] gckGALDEVICE_Construct: Unable to map location->0x%lX for size->%ld\n",
+                                         RegisterMemBase,
+                                         RegisterMemSize);
+
+           return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+
+       physical += RegisterMemSize;
+
+               gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                                       gcvZONE_DRIVER,
+                               "[galcore] gckGALDEVICE_Construct: "
+                                       "RegisterBase after mapping Address->0x%x is 0x%x\n",
+                               (gctUINT32)RegisterMemBase,
+                                       (gctUINT32)device->registerBase);
+    }
+
+       /* construct the gckOS object */
+       device->baseAddress = BaseAddress;
+       gcmkONERROR(
+                       gckOS_Construct(device, &device->os));
+
+    /* construct the gckKERNEL object. */
+       gcmkONERROR(
+                       gckKERNEL_Construct(device->os, device, &device->kernel));
+
+       gcmkONERROR(
+                       gckHARDWARE_SetFastClear(device->kernel->hardware,
+                                                                         FastClear,
+                                                                                 Compression));
+
+    /* query the ceiling of the system memory */
+       gcmkONERROR(
+                       gckHARDWARE_QuerySystemMemory(device->kernel->hardware,
+                                       &device->systemMemorySize,
+                    &device->systemMemoryBaseAddress));
+
+       gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                                       gcvZONE_DRIVER,
+                                       "[galcore] gckGALDEVICE_Construct: "
+                               "Will be trying to allocate contiguous memory of 0x%x bytes\n",
+                               (gctUINT32)device->systemMemoryBaseAddress);
+
+#if COMMAND_PROCESSOR_VERSION == 1
+    /* start the command queue */
+    gcmkVERIFY_OK(gckCOMMAND_Start(device->kernel->command));
+#endif
+
+    /* initialize the thread daemon */
+       memset(&device->isrLock, 0, sizeof(device->isrLock));
+
+       device->threadInitialized = gcvFALSE;
+       device->killThread = gcvFALSE;
+
+       /* initialize the isr */
+       device->isrInitialized = gcvFALSE;
+       device->dataReady = gcvFALSE;
+       device->irqLine = IrqLine;
+
+       /* query the amount of video memory */
+    gcmkVERIFY_OK(gckHARDWARE_QueryMemory(device->kernel->hardware,
+                    &device->internalSize,
+                    &internalBaseAddress,
+                    &internalAlignment,
+                    &device->externalSize,
+                    &externalBaseAddress,
+                    &externalAlignment,
+                    &horizontalTileSize,
+                    &verticalTileSize));
+
+       /* set up the internal memory region */
+    if (device->internalSize > 0)
+    {
+        gceSTATUS status = gckVIDMEM_Construct(device->os,
+                    internalBaseAddress,
+                    device->internalSize,
+                    internalAlignment,
+                    0,
+                    &device->internalVidMem);
+
+        if (gcmIS_ERROR(status))
+        {
+            /* error, remove internal heap */
+            device->internalSize = 0;
+        }
+        else
+        {
+            /* map internal memory */
+            device->internalPhysical  = (gctPHYS_ADDR)physical;
+                       device->internalLogical = (gctPOINTER)mmap_device_io(device->internalSize, physical);
+
+            gcmkASSERT(device->internalLogical != NULL);
+
+                       physical += device->internalSize;
+        }
+    }
+
+    if (device->externalSize > 0)
+    {
+        /* create the external memory heap */
+        gceSTATUS status = gckVIDMEM_Construct(device->os,
+                                       externalBaseAddress,
+                                       device->externalSize,
+                                       externalAlignment,
+                                       0,
+                                       &device->externalVidMem);
+
+        if (gcmIS_ERROR(status))
+        {
+            /* error, remove internal heap */
+            device->externalSize = 0;
+        }
+        else
+        {
+            /* map internal memory */
+            device->externalPhysical = (gctPHYS_ADDR)physical;
+                       device->externalLogical = (gctPOINTER)mmap_device_io(device->externalSize, physical);
+
+                       gcmkASSERT(device->externalLogical != NULL);
+
+                       physical += device->externalSize;
+        }
+    }
+
+       /* set up the contiguous memory */
+    device->contiguousSize = ContiguousSize;
+
+       if (ContiguousBase == 0)
+       {
+               status = gcvSTATUS_OUT_OF_MEMORY;
+
+               while (device->contiguousSize > 0)
+               {
+                       gcmkTRACE_ZONE(
+                               gcvLEVEL_INFO, gcvZONE_DRIVER,
+                               "[galcore] gckGALDEVICE_Construct: Will be trying to allocate contiguous memory of %ld bytes\n",
+                               device->contiguousSize
+                               );
+
+                       /* allocate contiguous memory */
+                       status = gckGALDEVICE_AllocateMemory(
+                               device,
+                               device->contiguousSize,
+                               &device->contiguousBase,
+                               &device->contiguousPhysical,
+                               &physAddr
+                               );
+
+                       if (gcmIS_SUCCESS(status))
+                       {
+                       gcmkTRACE_ZONE(
+                                       gcvLEVEL_INFO, gcvZONE_DRIVER,
+                                       "[galcore] gckGALDEVICE_Construct: Contiguous allocated size->0x%08X Virt->0x%08lX physAddr->0x%08X\n",
+                                       device->contiguousSize,
+                                       device->contiguousBase,
+                                       physAddr
+                                       );
+
+                               status = gckVIDMEM_Construct(
+                                       device->os,
+                                       physAddr | device->systemMemoryBaseAddress,
+                                       device->contiguousSize,
+                                       64,
+                                       BankSize,
+                                       &device->contiguousVidMem
+                                       );
+
+                               if (gcmIS_SUCCESS(status))
+                               {
+                                       device->contiguousMapped = gcvFALSE;
+
+                                       /* success, abort loop */
+                                       gcmkTRACE_ZONE(
+                                               gcvLEVEL_INFO, gcvZONE_DRIVER,
+                                               "Using %u bytes of contiguous memory.\n",
+                                               device->contiguousSize
+                                               );
+
+                                       break;
+                               }
+
+                               gcmkVERIFY_OK(gckGALDEVICE_FreeMemory(
+                                       device,
+                                       device->contiguousBase,
+                                       device->contiguousPhysical
+                                       ));
+
+                               device->contiguousBase = NULL;
+                       }
+
+                       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, roll back. */
+                       device->contiguousVidMem = gcvNULL;
+                       device->contiguousSize   = 0;
+               }
+               else
+               {
+                       /* Map the contiguous memory. */
+                       device->contiguousPhysical = (gctPHYS_ADDR) ContiguousBase;
+                       device->contiguousSize     = ContiguousSize;
+                       device->contiguousBase     = (gctPOINTER) mmap_device_io(ContiguousSize, ContiguousBase);
+                       device->contiguousMapped   = gcvTRUE;
+
+                       if (device->contiguousBase == gcvNULL)
+                       {
+                       /* Error, roll back. */
+                               gcmkVERIFY_OK(gckVIDMEM_Destroy(device->contiguousVidMem));
+                               device->contiguousVidMem = gcvNULL;
+                               device->contiguousSize   = 0;
+
+                               status = gcvSTATUS_OUT_OF_RESOURCES;
+                       }
+               }
+       }
+
+    *Device = device;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                 "[galcore] gckGALDEVICE_Construct: Initialized device->0x%x contiguous->%lu @ 0x%x (0x%08X)\n",
+                                 device,
+                                 device->contiguousSize,
+                                 device->contiguousBase,
+                                 device->contiguousPhysical);
+
+    return gcvSTATUS_OK;
+OnError:
+       /* Roll back. */
+
+       /* Destroy the gckKERNEL object. */
+       if ( Device != gcvNULL)
+       {
+               gcmkVERIFY_OK(gckGALDEVICE_Destroy(*Device));
+       }
+
+       /* Return the status. */
+       return status;
+}
+
+/*******************************************************************************
+**
+**     gckGALDEVICE_Destroy
+**
+**     Class destructor.
+**
+**     INPUT:
+**
+**             Nothing.
+**
+**     OUTPUT:
+**
+**             Nothing.
+**
+**     RETURNS:
+**
+**             Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Destroy(
+       gckGALDEVICE Device)
+{
+       gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    gcmkTRACE(gcvLEVEL_VERBOSE, "[ENTER] gckGALDEVICE_Destroy\n");
+
+    /* Destroy the gckKERNEL object. */
+    gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernel));
+
+    if (Device->internalVidMem != gcvNULL)
+    {
+        /* destroy the internal heap */
+        gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
+
+               /* unmap the internal memory */
+               munmap_device_io((uintptr_t)Device->internalLogical, Device->internalSize);
+    }
+
+    if (Device->externalVidMem != gcvNULL)
+    {
+        /* destroy the internal heap */
+        gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
+
+        /* unmap the external memory */
+               munmap_device_io((uintptr_t)Device->externalLogical, Device->externalSize);
+    }
+
+    if (Device->contiguousVidMem != gcvNULL)
+    {
+        /* Destroy the contiguous heap */
+        gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
+
+               if (Device->contiguousMapped)
+               {
+                       gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                                 "[galcore] gckGALDEVICE_Destroy: "
+                         "Unmapping contiguous memory->0x%08lX\n",
+                         Device->contiguousBase);
+
+                       munmap_device_io((uintptr_t)Device->contiguousBase, Device->contiguousSize);
+               }
+               else
+               {
+           gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                         "[galcore] gckGALDEVICE_Destroy: "
+                         "Freeing contiguous memory->0x%08lX\n",
+                         Device->contiguousBase);
+
+           gcmkVERIFY_OK(gckGALDEVICE_FreeMemory(Device,
+                                                Device->contiguousBase,
+                                                Device->contiguousPhysical));
+       }
+    }
+
+    if (Device->registerBase)
+    {
+               munmap_device_io((uintptr_t)Device->registerBase, Device->registerSize);
+    }
+
+    /* Destroy the gckOS object. */
+    gcmkVERIFY_OK(gckOS_Destroy(Device->os));
+
+    free(Device);
+
+    gcmkTRACE(gcvLEVEL_VERBOSE, "[galcore] Leave gckGALDEVICE_Destroy\n");
+
+    return gcvSTATUS_OK;
+}
+
diff --git a/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_device.h b/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_device.h
new file mode 100644 (file)
index 0000000..fea4157
--- /dev/null
@@ -0,0 +1,123 @@
+/****************************************************************************
+*
+*    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+*
+*    The material in this file is confidential and contains trade secrets
+*    of Vivante Corporation. This is proprietary information owned by
+*    Vivante Corporation. No part of this work may be disclosed,
+*    reproduced, copied, transmitted, or used in any way for any purpose,
+*    without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+*    Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_device_h_
+#define __gc_hal_kernel_device_h_
+
+/******************************************************************************\
+******************************* gckGALDEVICE Structure *******************************
+\******************************************************************************/
+
+#define GALCORE_INTERRUPT_PULSE 0x5D
+
+typedef struct _gckGALDEVICE
+{
+       /* Objects. */
+       gckOS                           os;
+       gckKERNEL                       kernel;
+
+       /* 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                      registerBase;
+       gctSIZE_T                       registerSize;
+       gctUINT32                       baseAddress;
+
+       /* IRQ management. */
+       gctINT                          irqLine;
+       gctINT                          irqId;
+       gctBOOL                         isrInitialized;
+       gctBOOL                         dataReady;
+       intrspin_t                      isrLock;
+       struct sigevent         event;
+       int                                     chid;
+       int                                     coid;
+
+       /* Thread management. */
+       pthread_t                       threadCtxt;
+       gctBOOL                         threadInitialized;
+       gctBOOL                         killThread;
+}
+* gckGALDEVICE;
+
+typedef struct _gcsHAL_PRIVATE_DATA
+{
+    gckGALDEVICE               device;
+    gctPOINTER                 mappedMemory;
+       gctPOINTER                      contiguousLogical;
+}
+gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
+
+gceSTATUS gckGALDEVICE_Setup_ISR(
+       IN gckGALDEVICE Device
+       );
+
+gceSTATUS gckGALDEVICE_Release_ISR(
+       IN gckGALDEVICE Device
+       );
+
+gceSTATUS gckGALDEVICE_Start_Thread(
+       IN gckGALDEVICE Device
+       );
+
+gceSTATUS gckGALDEVICE_Stop_Thread(
+       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 gctUINT32 ContiguousBase,
+       IN gctSIZE_T ContiguousSize,
+       IN gctSIZE_T BankSize,
+       IN gctINT FastClear,
+       IN gctINT Compression,
+       IN gctUINT32 BaseAddress,
+       OUT gckGALDEVICE *Device
+       );
+
+gceSTATUS gckGALDEVICE_Destroy(
+       IN gckGALDEVICE Device
+       );
+
+#endif /* __gc_hal_kernel_device_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_driver.c b/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_driver.c
new file mode 100644 (file)
index 0000000..0b27992
--- /dev/null
@@ -0,0 +1,1367 @@
+/****************************************************************************
+*
+*    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+*
+*    The material in this file is confidential and contains trade secrets
+*    of Vivante Corporation. This is proprietary information owned by
+*    Vivante Corporation. No part of this work may be disclosed,
+*    reproduced, copied, transmitted, or used in any way for any purpose,
+*    without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+*    Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_qnx.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_user_context.h"
+
+# include <winmgr/gpu.h>
+
+static gckGALDEVICE galDevice;
+
+/* GN TODO take these from the graphics.conf file. */
+#ifdef MMP2
+int irqLine = 8;
+long registerMemBase = 0xd420d000;
+#else
+int irqLine = 48;
+long registerMemBase = 0xf1840000;
+#endif
+
+/* Configurable Memory sizes. */
+unsigned long contiguousSize =  ( 64 << 20);                   /* Video memory pool. */
+unsigned int internalPoolSize = ( 16 << 20);                   /* Kernel local memory pool. */
+unsigned int sharedPoolSize =   (  8 << 20);                   /* Shared per-client memory pool initial size. */
+unsigned long registerMemSize = (256 << 10);                   /* GPU register memory size. */
+
+/* ContiguousBase should be 0,
+ * for video memory to be allocated from the memory pool. */
+unsigned long contiguousBase = 0;
+long bankSize = 0;
+int fastClear = -1;
+int compression = -1;
+unsigned long baseAddress = 0;
+
+/* Global video memory pool. */
+typedef struct _gcsMEM_POOL
+{
+       gctINT32 freePage;
+       gctSIZE_T pageCount;
+       gctUINT32 pageSize;
+       gctUINT32 poolSize;
+       pthread_mutex_t mutex;
+       gctUINT32 addr;
+       gctUINT32 paddr;
+       gckPAGE_USAGE pageUsage;
+       gctCHAR fdName[64];
+       gctINT fd;
+} gcsMEM_POOL;
+
+gcsMEM_POOL memPool;
+
+/* Pointer to list of shared memory pools. */
+gckSHM_POOL shmPoolList;
+pthread_mutex_t shmPoolListMutex;
+
+/* Resource Manager Globals. */
+struct _gcsRESMGR_GLOBALS
+{
+       dispatch_t *dpp;
+       dispatch_context_t *ctp;
+       int id;
+       thread_pool_attr_t pool_attr;
+       thread_pool_t *tpp;
+       pthread_t root;
+} resmgr_globals;
+
+win_gpu_2_cm_iface_t *g_qnx_gpu_2_cm_iface = 0;
+static resmgr_connect_funcs_t connect_funcs;
+static resmgr_io_funcs_t io_funcs;
+static iofunc_attr_t attr;
+
+gceSTATUS gckVIDMEM_FreeHandleMemory(IN gckVIDMEM Memory, IN gctHANDLE Handle);
+
+gceSTATUS
+drv_mempool_init()
+{
+       off64_t paddr;
+       void* addr;
+       size_t pcontig;
+
+       /* Default 4KB page size. */
+       memPool.pageSize = __PAGESIZE;
+
+       /* Compute number of pages. */
+       memPool.pageCount = (contiguousSize + internalPoolSize) / memPool.pageSize;
+       gcmkASSERT(memPool.pageCount <= 65536);
+
+       /* Align memPoolSize to page size. */
+       memPool.poolSize = memPool.pageCount * memPool.pageSize;
+
+    /* Allocate a single chunk of physical memory.
+        * Zero memory with MAP_ANON so we don't leak any sensitive information by chance. */
+       snprintf(memPool.fdName, sizeof(memPool.fdName), "galcore:vidmem:%d", getpid());
+    memPool.fd = shm_open(memPool.fdName, O_RDWR|O_CREAT, 0777);
+    if (memPool.fd == -1) {
+        fprintf(stderr, "galcore:%s[%d]: shm_open failed\n", __FUNCTION__, __LINE__);
+        return gcvSTATUS_GENERIC_IO;
+    }
+
+    shm_unlink(memPool.fdName);
+
+    if (shm_ctl_special(memPool.fd, SHMCTL_ANON|SHMCTL_PHYS, 0, memPool.poolSize, 0x9) == -1) {
+        fprintf(stderr, "galcore:%s[%d]: shm_ctl_special failed\n", __FUNCTION__, __LINE__);
+        close(memPool.fd);
+        memPool.fd = -1;
+        return gcvSTATUS_GENERIC_IO;
+    }
+
+    addr = mmap64(0, memPool.poolSize, PROT_READ|PROT_WRITE, MAP_SHARED, memPool.fd, 0);
+    if (addr == MAP_FAILED) {
+        fprintf(stderr, "galcore:%s[%d]: mmap64 failed\n", __FUNCTION__, __LINE__);
+        close(memPool.fd);
+        memPool.fd = -1;
+        return gcvSTATUS_GENERIC_IO;
+    }
+       memPool.addr = (gctUINT32)addr;
+
+       if (mem_offset64(addr, NOFD, memPool.poolSize, &paddr, &pcontig) == -1)
+       {
+           fprintf(stderr, "galcore:%s[%d]: mem_offset64 failed\n", __FUNCTION__, __LINE__);
+               munmap(addr, memPool.poolSize);
+               close(memPool.fd);
+               memPool.fd = -1;
+               memPool.addr = NULL;
+        return gcvSTATUS_GENERIC_IO;
+       }
+
+       /* TODO. Truncating 64bit value. */
+       memPool.paddr = (gctUINT32)paddr;
+
+    printf( "Mempool Map addr range[%x-%x]\n", memPool.addr, memPool.addr +  memPool.poolSize);
+       printf( "Mempool Map paddr range[%x-%x]\n", memPool.paddr, memPool.paddr +  memPool.poolSize );
+
+       /* Allocate the page usage array and Initialize all pages to free. */
+       memPool.pageUsage = (gckPAGE_USAGE)calloc(
+                       memPool.pageCount,
+                       sizeof(struct _gckPAGE_USAGE));
+
+       if (memPool.pageUsage == gcvNULL)
+       {
+        fprintf( stderr, "malloc failed: %s\n", strerror( errno ) );
+               munmap(addr, memPool.poolSize);
+               close(memPool.fd);
+               memPool.fd = -1;
+               memPool.addr = NULL;
+               memPool.paddr = 0;
+               return gcvSTATUS_GENERIC_IO;
+       }
+
+       /* The first page is free.*/
+       memPool.freePage = 0;
+
+       /* Initialize the semaphore. */
+       if (pthread_mutex_init(&memPool.mutex, NULL) != EOK)
+       {
+               free(memPool.pageUsage);
+               munmap(addr, memPool.poolSize);
+               close(memPool.fd);
+               memPool.fd = -1;
+               memPool.addr = NULL;
+               memPool.paddr = 0;
+               return gcvSTATUS_GENERIC_IO;
+       }
+
+       return gcvSTATUS_OK;
+}
+
+void
+drv_mempool_destroy()
+{
+       pthread_mutex_destroy(&memPool.mutex);
+       free(memPool.pageUsage);
+       memPool.pageUsage = NULL;
+       munmap((void*)memPool.addr, memPool.poolSize);
+       close(memPool.fd);
+       memPool.fd = -1;
+       memPool.addr = NULL;
+       memPool.paddr = 0;
+}
+
+gctINT
+drv_mempool_get_fileDescriptor()
+{
+    return memPool.fd;
+}
+
+gctUINT32
+drv_mempool_get_basePAddress()
+{
+       return memPool.paddr;
+}
+
+gctUINT32
+drv_mempool_get_baseAddress()
+{
+       return memPool.addr;
+}
+
+gctUINT32
+drv_mempool_get_page_size()
+{
+       return memPool.pageSize;
+}
+
+gceSTATUS
+drv_mempool_mem_offset(
+       IN gctPOINTER Logical,
+       OUT gctUINT32 * Address)
+{
+       gctUINT32 logical = (gctUINT32)Logical;
+
+       if ( Address == gcvNULL )
+               return gcvSTATUS_INVALID_ARGUMENT;
+
+       if ( logical < memPool.addr
+               ||      logical > (memPool.addr + memPool.poolSize))
+               return gcvSTATUS_INVALID_ARGUMENT;
+
+       *Address = (logical - memPool.addr) + memPool.paddr;
+
+       return gcvSTATUS_OK;
+}
+
+/* Allocate pages from mapped shared memory.
+   Return Physical and Logical addresses.
+*/
+void
+drv_mempool_alloc_contiguous(
+       IN gctUINT32 Bytes,
+       OUT gctPHYS_ADDR * Physical,
+       OUT gctPOINTER * Logical
+       )
+{
+       gctSIZE_T i, j;
+       gctSIZE_T pageCount;
+
+       pthread_mutex_lock(&memPool.mutex);
+
+       /* Compute the number of required pages. */
+       pageCount = gcmALIGN(Bytes, drv_mempool_get_page_size()) / drv_mempool_get_page_size();
+
+       if ( (pageCount <= 0) || (memPool.freePage < 0) )
+       {
+               *Physical = gcvNULL;
+               *Logical = gcvNULL;
+               pthread_mutex_unlock(&memPool.mutex);
+               /* No free pages left. */
+               return;
+       }
+
+       /* Try finding enough contiguous free pages. */
+       for (i = memPool.freePage; i < memPool.pageCount;)
+       {
+               /* All pages behind this free page should be free. */
+               gctSIZE_T j;
+               for (j = 1; j < pageCount; ++j)
+               {
+                       if (memPool.pageUsage[i + j].pageCount != 0)
+                       {
+                               /* Bail out if page is allocated. */
+                               break;
+                       }
+               }
+
+               if (j == pageCount)
+               {
+                       /* We found a spot that has enough free pages. */
+                       break;
+               }
+
+               /* Move to the page after the allocated page. */
+               i += j + 1;
+
+               /* Find the next free page. */
+               while ((i < memPool.pageCount) && (memPool.pageUsage[i].pageCount != 0))
+               {
+                       ++i;
+               }
+       }
+
+       if (i >= memPool.pageCount)
+       {
+               *Physical = gcvNULL;
+               *Logical = gcvNULL;
+               pthread_mutex_unlock(&memPool.mutex);
+               /* Not enough contiguous pages. */
+               return;
+       }
+
+       /* Check if we allocate from the first free page. */
+       if (i == memPool.freePage)
+       {
+               /* Move first free page to beyond the contiguous request. */
+               memPool.freePage = i + pageCount;
+
+               /* Find first free page. */
+               while ( (memPool.freePage < memPool.pageCount) &&
+                               (memPool.pageUsage[memPool.freePage].pageCount != 0) )
+               {
+                       ++memPool.freePage;
+               }
+
+               if (memPool.freePage >= memPool.pageCount)
+               {
+                       /* No more free pages. */
+                       memPool.freePage = -1;
+               }
+       }
+
+       /* Walk all pages. */
+       for (j = 0; j < pageCount; ++j)
+       {
+               /* Store page count in each pageUsage to mark page is allocated. */
+               memPool.pageUsage[i+j].pageCount = pageCount;
+       }
+
+       gcmkTRACE(gcvLEVEL_INFO, "Allocated %u contiguous pages from 0x%X\n",
+               pageCount, i);
+
+       /* Success. */
+       *Physical = (gctPHYS_ADDR)(i * memPool.pageSize + (gctUINT32)memPool.paddr);
+       *Logical = (gctPOINTER)(i * memPool.pageSize + (gctUINT32)memPool.addr);
+
+       pthread_mutex_unlock(&memPool.mutex);
+}
+
+int drv_mempool_free(gctPOINTER Logical)
+{
+       gctUINT16 pageCount;
+       gctSIZE_T i;
+       gctINT32 pageIndex;
+
+       gcmkTRACE(gcvLEVEL_INFO, "Freeing pages @ %x\n", Logical);
+
+       pthread_mutex_lock(&memPool.mutex);
+
+       pageIndex = ((gctUINT32)Logical - (gctUINT32)memPool.addr) / memPool.pageSize;
+
+       /* Verify the memory is valid and unlocked. */
+       if ( (pageIndex < 0) || (pageIndex >= memPool.pageCount) )
+       {
+               pthread_mutex_unlock(&memPool.mutex);
+               gcmkTRACE(gcvLEVEL_ERROR, "Invalid page index @ %d\n", pageIndex);
+               return -1;
+       }
+
+       pageCount = memPool.pageUsage[pageIndex].pageCount;
+
+       /* Mark all used pages as free. */
+       for (i = 0; i < pageCount; ++i)
+       {
+               gcmkASSERT(memPool.pageUsage[i + pageIndex].pageCount == pageCount);
+
+               memPool.pageUsage[i + pageIndex].pageCount = 0;
+       }
+
+       /* Update first free page. */
+       if ( (memPool.freePage < 0) || (pageIndex < memPool.freePage) )
+       {
+               memPool.freePage = pageIndex;
+       }
+
+       pthread_mutex_unlock(&memPool.mutex);
+
+       gcmkTRACE(gcvLEVEL_INFO, "Free'd %u contiguos pages from 0x%X @ 0x%x\n",
+               pageCount, pageIndex);
+
+       return 1;
+}
+
+/*
+ * Initialize shm pool list and mutex.
+ */
+gceSTATUS
+drv_shm_init()
+{
+       shmPoolList = gcvNULL;
+       pthread_mutex_init(&shmPoolListMutex, 0);
+       return gcvSTATUS_OK;
+/*     resmgr_globals.shmpool = gcvNULL;
+       return pthread_mutex_init(&resmgr_globals.shmMutex, 0);*/
+}
+
+gceSTATUS
+drv_shm_destroy()
+{
+       gckSHM_POOL shmPool;
+       gctUINT32 count = 0;
+
+       pthread_mutex_destroy(&shmPoolListMutex);
+
+       shmPool = shmPoolList;
+       while (shmPool != gcvNULL)
+       {
+               /* Remove this pool from the list. */
+               drv_shmpool_destroy(shmPool);
+
+               shmPool = shmPool->nextPool;
+               count++;
+       }
+
+       return gcvSTATUS_OK;
+/*     resmgr_globals.shmpool = gcvNULL;
+       return pthread_mutex_destroy(&resmgr_globals.shmMutex);*/
+}
+
+/*
+ * Get the shm pool associated with this Handle and PID and lock it.
+ * Create one, if not present.
+ */
+gckSHM_POOL
+drv_shm_acquire_pool(
+               IN gctUINT32 Pid,
+               IN gctHANDLE Handle
+               )
+{
+       gckSHM_POOL shmPool, tail = gcvNULL;
+
+       pthread_mutex_lock(&shmPoolListMutex);
+
+       shmPool = shmPoolList;
+       while (shmPool != gcvNULL)
+       {
+               if (shmPool->Handle == Handle && shmPool->pid == Pid)
+               {
+                       pthread_mutex_unlock(&shmPoolListMutex);
+                       return shmPool;
+               }
+
+               tail = shmPool;
+               shmPool = shmPool->nextPool;
+       }
+
+       /* TODO: Start with smaller shmMemory pool size and increase on demand. */
+       /* Default 4KB page size. */
+       shmPool = drv_shmpool_create(Pid, Handle, sharedPoolSize, __PAGESIZE);
+
+       /* Add this pool to tail. */
+       if ( shmPool != gcvNULL )
+       {
+               if (tail != gcvNULL )
+               {
+                       tail->nextPool = shmPool;
+               }
+               else
+               {
+                       /* Set this pool as head. */
+                       shmPoolList = shmPool;
+               }
+
+               shmPool->nextPool = gcvNULL;
+       }
+       else
+       {
+               /* Failed to create new shmPool. */
+       }
+
+       pthread_mutex_unlock(&shmPoolListMutex);
+       return shmPool;
+}
+
+/*
+ * Get the shm pool associated with this Logical pointer.
+ */
+gckSHM_POOL
+drv_shm_acquire_pool2(
+               IN gctPOINTER Logical
+               )
+{
+       gckSHM_POOL shmPool, tail = gcvNULL;
+
+       pthread_mutex_lock(&shmPoolListMutex);
+
+       shmPool = shmPoolList;
+       while (shmPool != gcvNULL)
+       {
+               /* Check if this address is in range of this shmPool. */
+               if (shmPool->Logical <= (gctUINT32)Logical &&
+                       (shmPool->Logical + shmPool->pageCount * shmPool->pageSize) > (gctUINT32)Logical)
+               {
+                       pthread_mutex_unlock(&shmPoolListMutex);
+                       return shmPool;
+               }
+
+               tail = shmPool;
+               shmPool = shmPool->nextPool;
+       }
+
+       /* Failed to find associated shmPool. */
+       pthread_mutex_unlock(&shmPoolListMutex);
+       return shmPool;
+}
+
+/*
+ * Remove the shm pool associated with this ocb.
+ */
+gceSTATUS
+drv_shm_remove_pool(
+               IN gctHANDLE Handle
+               )
+{
+       gckSHM_POOL shmPool, prev = gcvNULL;
+
+       pthread_mutex_lock(&shmPoolListMutex);
+
+       shmPool = shmPoolList;
+
+       while (shmPool != gcvNULL)
+       {
+               /* Remove this pool from the list. */
+               if (shmPool->Handle == Handle)
+               {
+                       if (prev == gcvNULL)
+                       {
+                               shmPoolList = shmPool->nextPool;
+                       }
+                       else
+                       {
+                               prev->nextPool = shmPool->nextPool;
+                       }
+
+                       drv_shmpool_destroy(shmPool);
+
+                       pthread_mutex_unlock(&shmPoolListMutex);
+                       return gcvSTATUS_OK;
+               }
+
+               prev = shmPool;
+               shmPool = shmPool->nextPool;
+       }
+
+       pthread_mutex_unlock(&shmPoolListMutex);
+
+       return gcvSTATUS_INVALID_ARGUMENT;
+}
+
+gceSTATUS
+drv_shmpool_mem_offset(
+       IN gctPOINTER Logical,
+       OUT gctUINT32 * Address)
+{
+       gctUINT32 logical = (gctUINT32)Logical;
+       gckSHM_POOL shmPool;
+
+       if ( Address == gcvNULL )
+               return gcvSTATUS_INVALID_ARGUMENT;
+
+       pthread_mutex_lock(&shmPoolListMutex);
+
+       shmPool = shmPoolList;
+       while (shmPool != gcvNULL)
+       {
+               if ( (logical >= shmPool->Logical)
+                       &&      (logical < (shmPool->Logical + shmPool->pageCount * shmPool->pageSize)))
+               {
+                       *Address = (logical - shmPool->Logical ) + shmPool->Physical;
+                       pthread_mutex_unlock(&shmPoolListMutex);
+                       return gcvSTATUS_OK;
+               }
+
+               shmPool = shmPool->nextPool;
+       }
+
+       pthread_mutex_unlock(&shmPoolListMutex);
+
+       return gcvSTATUS_INVALID_ARGUMENT;
+}
+
+/* Initialize a shm pool with this ocb. */
+gckSHM_POOL drv_shmpool_create(
+               IN gctUINT32 Pid,
+               IN gctHANDLE Handle,
+               IN gctUINT32 PoolSize,
+               IN gctUINT32 PageSize)
+{
+       int rc, poolSize;
+       void* addr;
+       char shm_file_name[20] = "shm_galcore";
+       gctUINT32 i, pid;
+       gckSHM_POOL shm = (gckSHM_POOL) calloc(1, sizeof(struct _gckSHM_POOL));
+
+       /* Compute number of pages. */
+       shm->pageSize = PageSize;
+       shm->pageCount = PoolSize / shm->pageSize;
+       gcmkASSERT(shm->pageCount <= 65536);
+
+       /* Align poolSize to pageSize. */
+       poolSize = shm->pageCount * shm->pageSize;
+
+       shm->pid = Pid;
+       shm->Handle = Handle;
+
+       /* Initialize the semaphore. */
+       if (pthread_mutex_init(&shm->mutex, NULL) != EOK)
+       {
+        fprintf( stderr, "pthread_mutex_init failed: %s\n", strerror( errno ) );
+               free(shm);
+               return gcvNULL;
+       }
+
+       /* Create a pseudo unique name, so as to not open
+        * the same file twice from different threads at the same time. */
+       pid = Pid;
+       i = strlen(shm_file_name);
+       while(pid)
+       {
+               shm_file_name[i++] = (char)(pid % 10 + '0');
+               pid /= 10;
+       }
+       shm_file_name[i] = '\0';
+
+       shm->fd = shm_open(shm_file_name, O_RDWR | O_CREAT, 0777);
+       if (shm->fd == -1) {
+               free(shm);
+               return gcvNULL;
+       }
+
+       shm_unlink(shm_file_name);
+
+       /* Special flags for this shm, to make it write buffered. */
+       rc = shm_ctl_special(shm->fd,
+                                                SHMCTL_ANON | SHMCTL_PHYS /*| SHMCTL_LAZYWRITE*/,
+                                                0,
+                                                poolSize,
+                                                0x9);
+       if (rc == -1) {
+               close(shm->fd);
+               free(shm);
+               return gcvNULL;
+       }
+
+       /* Map this memory inside user and galcore. */
+       addr = mmap64_join(Pid,
+                                          0,
+                                          poolSize,
+                                          PROT_READ | PROT_WRITE,
+                                          MAP_SHARED,
+                                          shm->fd,
+                                          0);
+       if (addr == MAP_FAILED)
+       {
+               free(shm);
+               return gcvNULL;
+       }
+
+       /* TODO: Dont close fd if need to truncate shm later. */
+       rc = close(shm->fd);
+       if (rc == -1) {
+               free(shm);
+               return gcvNULL;
+       }
+
+       shm->Logical = (gctUINT32) addr;
+
+       /* fd should be NOFD here, to get physical address. */
+       rc = mem_offset( addr, NOFD, 1, (off_t *)&shm->Physical, NULL);
+       if (rc == -1) {
+               free(shm);
+               return gcvNULL;
+       }
+
+    /* TODO: MLOCK may or may not be needed!. */
+    mlock((void*)shm->Logical, poolSize);
+
+       /* Allocate the page usage array and Initialize all pages to free. */
+    shm->pageUsage = (gckPAGE_USAGE)calloc(shm->pageCount, sizeof(struct _gckPAGE_USAGE));
+       if (shm->pageUsage == gcvNULL)
+       {
+               munmap((void*)shm->Logical, poolSize);
+               munmap_peer(Pid, (void*)shm->Logical, poolSize);
+               free(shm);
+               return gcvNULL;
+       }
+
+       /* The first page is free. */
+       shm->freePage = 0;
+
+       return shm;
+}
+
+void
+drv_shmpool_destroy(
+               IN gckSHM_POOL ShmPool)
+{
+       if (ShmPool)
+       {
+               int poolSize = ShmPool->pageCount * ShmPool->pageSize;
+               if (ShmPool->pageUsage)
+                       free(ShmPool->pageUsage);
+               if (ShmPool->Logical)
+               {
+                       munmap((void*)ShmPool->Logical, poolSize);
+                       munmap_peer(ShmPool->pid, (void*)ShmPool->Logical, poolSize);
+               }
+       }
+}
+
+gctUINT32
+drv_shmpool_get_BaseAddress(
+               IN gckSHM_POOL ShmPool
+               )
+{
+       gcmkASSERT(ShmPool != 0);
+
+       if (!ShmPool)
+               return 0;
+
+       return ShmPool->Logical;
+}
+
+gctUINT32
+drv_shmpool_get_page_size(
+               IN gckSHM_POOL ShmPool
+               )
+{
+       gcmkASSERT(ShmPool != 0);
+
+       if (!ShmPool)
+               return 0;
+
+       return ShmPool->pageSize;
+}
+
+/* Allocate pages from mapped shared memory.
+   Return Logical user address.
+*/
+gctPOINTER
+drv_shmpool_alloc_contiguous(
+               IN gctUINT32 Pid,
+               IN gctHANDLE Handle,
+               IN gctUINT32 Bytes
+               )
+{
+       gctSIZE_T i, j;
+       int pageSize;
+       gctSIZE_T pageCount;
+       gckSHM_POOL shmPool = drv_shm_acquire_pool(Pid, Handle);
+
+       if (shmPool == gcvNULL)
+       {
+               return gcvNULL;
+       }
+       /* Compute the number of required pages. */
+       pageSize = drv_shmpool_get_page_size(shmPool);
+       if ( pageSize == 0 )
+       {
+               /* Invalid pageSize. */
+               return gcvNULL;
+       }
+
+       pageCount = gcmALIGN(Bytes, pageSize) / pageSize;
+
+       if ( (pageCount <= 0) || (shmPool->freePage < 0) )
+       {
+               /* No free pages left. */
+               return gcvNULL;
+       }
+
+       if ( (pageCount <= 0) || (shmPool->freePage < 0) )
+       {
+               /* No free pages left. */
+               return gcvNULL;
+       }
+
+       /* Try finding enough contiguous free pages. */
+       for (i = shmPool->freePage; i < shmPool->pageCount;)
+       {
+               /* All pages behind this free page should be free. */
+               gctSIZE_T j;
+               for (j = 1; j < pageCount; ++j)
+               {
+                       if (shmPool->pageUsage[i + j].pageCount != 0)
+                       {
+                               /* Bail out if page is allocated. */
+                               break;
+                       }
+               }
+
+               if (j == pageCount)
+               {
+                       /* We found a spot that has enough free pages. */
+                       break;
+               }
+
+               /* Move to the page after the allocated page. */
+               i += j + 1;
+
+               /* Find the next free page. */
+               while ((i < shmPool->pageCount) && (shmPool->pageUsage[i].pageCount != 0))
+               {
+                       ++i;
+               }
+       }
+
+       if (i >= shmPool->pageCount)
+       {
+               /* Not enough contiguous pages. */
+               return gcvNULL;
+       }
+
+       /* Check if we allocate from the first free page. */
+       if (i == shmPool->freePage)
+       {
+               /* Move first free page to beyond the contiguous request. */
+               shmPool->freePage = i + pageCount;
+
+               /* Find first free page. */
+               while ( (shmPool->freePage < shmPool->pageCount) &&
+                               (shmPool->pageUsage[shmPool->freePage].pageCount != 0) )
+               {
+                       ++shmPool->freePage;
+               }
+
+               if (shmPool->freePage >= shmPool->pageCount)
+               {
+                       /* No more free pages. */
+                       shmPool->freePage = -1;
+               }
+       }
+
+       /* Walk all pages. */
+       for (j = 0; j < pageCount; ++j)
+       {
+               /* Store page count in each pageUsage to mark page is allocated. */
+               shmPool->pageUsage[i+j].pageCount = pageCount;
+       }
+
+       gcmkTRACE(gcvLEVEL_INFO, "Allocated %u contiguos pages from 0x%X\n",
+               pageCount, i);
+
+       /* Success. */
+       return (gctPOINTER)(i * shmPool->pageSize + shmPool->Logical);
+}
+
+gctUINT32
+drv_shmpool_free(
+               IN gctPOINTER Logical
+               )
+{
+       gctUINT16 pageCount;
+       gctSIZE_T i;
+       gctINT32 pageIndex;
+       gckSHM_POOL shmPool = drv_shm_acquire_pool2(Logical);
+
+       if (shmPool == gcvNULL)
+       {
+               gcmkTRACE(gcvLEVEL_ERROR, "Invalid Logical addr: %x.\n", Logical);
+               return 0;
+       }
+
+       pageIndex = ((gctUINT32)Logical - shmPool->Logical)/shmPool->pageSize;
+
+       gcmkTRACE(gcvLEVEL_INFO, "Freeing pages @ %d\n", pageIndex);
+
+       /* Verify the memory is valid and unlocked. */
+       if ( (pageIndex < 0) || (pageIndex >= shmPool->pageCount) )
+       {
+               gcmkTRACE(gcvLEVEL_ERROR, "Invalid page index @ %d\n", pageIndex);
+
+               return 0;
+       }
+
+       pageCount = shmPool->pageUsage[pageIndex].pageCount;
+
+       /* Mark all used pages as free. */
+       for (i = 0; i < pageCount; ++i)
+       {
+               gcmkASSERT(shmPool->pageUsage[i + pageIndex].pageCount == pageCount);
+
+               shmPool->pageUsage[i + pageIndex].pageCount = 0;
+       }
+
+       /* Update first free page. */
+       if ( (shmPool->freePage < 0) || (pageIndex < shmPool->freePage) )
+       {
+               shmPool->freePage = pageIndex;
+       }
+
+       gcmkTRACE(gcvLEVEL_INFO, "Free'd %u contiguos pages from 0x%X @ 0x%x\n",
+               pageCount, pageIndex);
+
+       return 1;
+}
+
+int drv_msg(resmgr_context_t *ctp,
+                       io_msg_t *msg,
+                       RESMGR_OCB_T *ocb)
+{
+       gcsDRIVER_ARGS *drvArgs = (gcsDRIVER_ARGS *)msg;
+    int rc;
+    gceSTATUS status;
+    gcsQUEUE_PTR queue;
+
+#define UNLOCK_RESMGR
+#ifdef UNLOCK_RESMGR
+       iofunc_attr_unlock(&attr);
+#endif
+
+    if ((drvArgs->iomsg.i.type != _IO_MSG)
+       || (drvArgs->iomsg.i.mgrid != _IOMGR_VIVANTE)
+       || (drvArgs->iomsg.i.subtype != IOCTL_GCHAL_INTERFACE
+           && drvArgs->iomsg.i.subtype != IOCTL_GCHAL_KERNEL_INTERFACE
+               && drvArgs->iomsg.i.subtype != IOCTL_GCHAL_TERMINATE))
+    {
+        /* Unknown command. Fail the I/O. */
+#ifdef UNLOCK_RESMGR
+       iofunc_attr_lock(&attr);
+#endif
+               rc = ENOSYS;
+               if (ctp->info.scoid != -1)
+                       return _RESMGR_STATUS(ctp, rc);
+               return _RESMGR_NOREPLY;
+    }
+
+       if (drvArgs->iomsg.i.subtype == IOCTL_GCHAL_TERMINATE)
+       {
+               /* terminate the resource manager */
+               pthread_kill(resmgr_globals.root, SIGTERM);
+#ifdef UNLOCK_RESMGR
+               iofunc_attr_lock(&attr);
+#endif
+               return _RESMGR_NOREPLY;
+       }
+
+       /* Save channel handle and pid for later functions. */
+       drvArgs->iface.handle = (gctHANDLE)ocb;
+       drvArgs->iface.pid = (gctUINT32)ctp->info.pid;
+
+       /* Store receive ID with signal event so that we can later respond via pulse. */
+       switch (drvArgs->iface.command)
+       {
+       case gcvHAL_SIGNAL:
+               printf("Setup rcvid as:%d\n", ctp->rcvid);
+           drvArgs->iface.u.Signal.rcvid = ctp->rcvid;
+        break;
+
+    case gcvHAL_EVENT_COMMIT:
+        for (queue = drvArgs->iface.u.Event.queue; queue != gcvNULL; queue = queue->next)
+        {
+            if (queue->iface.command == gcvHAL_SIGNAL)
+            {
+                queue->iface.u.Signal.rcvid = ctp->rcvid;
+            }
+        }
+        break;
+
+    default:
+        break;
+       }
+
+       status = gckKERNEL_Dispatch(galDevice->kernel,
+                                                               (drvArgs->iomsg.i.subtype == IOCTL_GCHAL_INTERFACE),
+                                                               &drvArgs->iface);
+
+       if (gcmIS_ERROR(status))
+       {
+               gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DRIVER,
+                                 "[galcore] gckKERNEL_Dispatch returned %d.\n",
+                         status);
+       }
+       else if (gcmIS_ERROR(drvArgs->iface.status))
+       {
+               gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DRIVER,
+                                 "[galcore] IOCTL %d returned %d.\n",
+                         drvArgs->iface.command,
+                         drvArgs->iface.status);
+       }
+
+       /* Reply data back to the user. */
+       MsgReply(ctp->rcvid, EOK, (gctPOINTER) &drvArgs->iface, sizeof(gcsHAL_INTERFACE));
+
+#ifdef UNLOCK_RESMGR
+       iofunc_attr_lock(&attr);
+#endif
+
+       gcmkTRACE(gcvLEVEL_INFO, "Replied message with command %d, status %d\n",
+               drvArgs->iface.command,
+               drvArgs->iface.status);
+
+    return (_RESMGR_NOREPLY);
+}
+
+static int drv_init(void)
+{
+       /* TODO: Enable clock by driver support? */
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+                 "Entering drv_init\n");
+
+    /* Create the GAL device. */
+    gcmkVERIFY_OK(gckGALDEVICE_Construct(irqLine,
+                   registerMemBase,
+                                       registerMemSize,
+                                       contiguousBase,
+                                       contiguousSize,
+                                       bankSize,
+                                       fastClear,
+                                       compression,
+                                       baseAddress,
+                                       &galDevice));
+
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+                 "galcore device constructed.\n");
+
+    /* Start the GAL device. */
+    if (gcmIS_ERROR(gckGALDEVICE_Start(galDevice)))
+    {
+       gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                     "[galcore] Can't start the gal device.\n");
+
+       /* Roll back. */
+       gckGALDEVICE_Stop(galDevice);
+       gckGALDEVICE_Destroy(galDevice);
+
+       return -1;
+    }
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                 "[galcore] irqLine->%ld, contiguousSize->%lu, memBase->0x%lX\n",
+                 irqLine,
+                 contiguousSize,
+                 registerMemBase);
+
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+                 "[galcore] driver registered successfully.\n");
+
+    return 0;
+}
+
+static void drv_exit(void)
+{
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+                 "[galcore] Entering drv_exit\n");
+
+    gckGALDEVICE_Stop(galDevice);
+    gckGALDEVICE_Destroy(galDevice);
+
+}
+
+/* Invoked by OS, when a connection is closed or dies. */
+int
+drv_close_ocb(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb)
+{
+       gckVIDMEM videoMemory;
+       gceSTATUS status;
+
+       /* Free virtual memory owned by this client. */
+       gckMMU_FreeHandleMemory(galDevice->kernel->mmu, (gctHANDLE)ocb);
+
+       /* Free system memory owned by the client. */
+       status = gckKERNEL_GetVideoMemoryPool(galDevice->kernel, gcvPOOL_SYSTEM, &videoMemory);
+
+       if (status == gcvSTATUS_OK)
+       {
+               gckVIDMEM_FreeHandleMemory(videoMemory,
+                                                                  (gctHANDLE)ocb);
+       }
+
+       /* Free shared memory and its mapping. */
+       drv_shm_remove_pool(ocb);
+
+       return iofunc_close_ocb_default(ctp, reserved, ocb);
+}
+
+int gpu_init()
+{
+       /* Declare variables we'll be using. */
+       resmgr_attr_t resmgr_attr;
+       sigset_t  sigset;
+       int rc;
+
+       if (drv_mempool_init() != gcvSTATUS_OK)
+       {
+               fprintf(stderr, "drv_mempool_init failed.");
+               goto fail_001;
+       }
+
+       if (drv_shm_init() != gcvSTATUS_OK)
+       {
+               fprintf(stderr, "drv_mempool_init failed.");
+               goto fail_002;
+       }
+
+       if (drv_init() != 0)
+       {
+               fprintf(stderr, "drv_init failed.");
+               goto fail_003;
+       }
+
+       /* initialize dispatch interface */
+       if((resmgr_globals.dpp = dispatch_create()) == NULL)
+       {
+               fprintf(stderr, "Unable to allocate dispatch handle.\n");
+               goto fail_004;
+       }
+
+       /* initialize resource manager attributes */
+       memset(&resmgr_attr, 0, sizeof resmgr_attr);
+       resmgr_attr.nparts_max = 1;
+       resmgr_attr.msg_max_size = 2048;
+
+       /* initialize functions for handling messages */
+       iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs,
+                       _RESMGR_IO_NFUNCS, &io_funcs);
+
+       /* Register io handling functions. */
+       io_funcs.msg = drv_msg;
+       io_funcs.close_ocb = drv_close_ocb;
+
+
+       /* initialize attribute structure used by the device */
+       iofunc_attr_init(&attr, S_IFNAM | 0666, 0, 0);
+
+       /* attach our device name */
+       resmgr_globals.id = resmgr_attach(
+                       resmgr_globals.dpp,/* dispatch handle */
+                       &resmgr_attr,                   /* resource manager attrs */
+                       GAL_DEV,                                /* device name */
+                       _FTYPE_ANY,                             /* open type */
+                       _RESMGR_FLAG_SELF,              /* flags */
+                       &connect_funcs,                 /* connect routines */
+                       &io_funcs,                              /* I/O routines */
+                       &attr);                                 /* handle */
+       if (resmgr_globals.id == -1) {
+               fprintf(stderr, "Unable to attach name.\n");
+        goto fail_005;
+       }
+
+    /* Prevent signals from affecting resmgr threads. */
+    sigfillset(&sigset);
+    sigdelset(&sigset, SIGTERM);
+    pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+
+    /* initialize thread pool attributes */
+    memset(&resmgr_globals.pool_attr, 0, sizeof(resmgr_globals.pool_attr));
+    resmgr_globals.pool_attr.handle = resmgr_globals.dpp;
+    resmgr_globals.pool_attr.context_alloc = resmgr_context_alloc;
+    resmgr_globals.pool_attr.block_func = resmgr_block;
+    resmgr_globals.pool_attr.unblock_func = resmgr_unblock;
+    resmgr_globals.pool_attr.handler_func = resmgr_handler;
+    resmgr_globals.pool_attr.context_free = resmgr_context_free;
+    resmgr_globals.pool_attr.lo_water = 2;
+    resmgr_globals.pool_attr.hi_water = 4;
+    resmgr_globals.pool_attr.increment = 1;
+    resmgr_globals.pool_attr.maximum = 50;
+#if (defined(_NTO_VERSION) && (_NTO_VERSION >= 650))
+       resmgr_globals.pool_attr.tid_name = "galcore-message-handler";
+#endif
+
+    /* allocate a thread pool handle */
+    resmgr_globals.tpp = thread_pool_create(&resmgr_globals.pool_attr, POOL_FLAG_EXIT_SELF);
+    if (resmgr_globals.tpp == NULL)
+       {
+        goto fail_006;
+    }
+
+    rc = pthread_create(NULL, resmgr_globals.pool_attr.attr, (void * (*)(void *))thread_pool_start, resmgr_globals.tpp);
+    if (rc != 0)
+       {
+        goto fail_007;
+    }
+
+       /* TODO: gpu_suspend, gpu_resume */
+
+       return EXIT_SUCCESS;
+
+fail_007:
+    thread_pool_destroy(resmgr_globals.tpp);
+fail_006:
+    resmgr_detach(resmgr_globals.dpp, resmgr_globals.id, 0);
+fail_005:
+    dispatch_destroy(resmgr_globals.dpp);
+fail_004:
+    drv_exit();
+fail_003:
+       drv_shm_destroy();
+fail_002:
+       drv_mempool_destroy();
+fail_001:
+    return EXIT_FAILURE;
+}
+
+int gpu_fini()
+{
+    thread_pool_destroy(resmgr_globals.tpp);
+    resmgr_detach(resmgr_globals.dpp, resmgr_globals.id, 0);
+    dispatch_destroy(resmgr_globals.dpp);
+    drv_exit();
+    drv_shm_destroy();
+       drv_mempool_destroy();
+       return EXIT_SUCCESS;
+}
+
+#ifndef QNX_USE_OLD_FRAMEWORK
+
+int GPU_Startup(win_gpu_2_cm_iface_t *iface)
+{
+    g_qnx_gpu_2_cm_iface = iface;
+       return gpu_init();
+}
+
+int GPU_Shutdown()
+{
+    g_qnx_gpu_2_cm_iface = NULL;
+       return gpu_fini();
+}
+
+void win_gpu_module_getfuncs(win_cm_2_gpu_iface_t *iface)
+{
+       iface->init = GPU_Startup;
+       iface->fini = GPU_Shutdown;
+}
+
+#else /* QNX_USE_OLD_FRAMEWORK */
+
+int drv_resmgr_loop()
+{
+    sigset_t  sigset;
+    siginfo_t info;
+
+       resmgr_globals.root = pthread_self();
+
+    /* Background ourselves */
+    procmgr_daemon(EXIT_SUCCESS, PROCMGR_DAEMON_NODEVNULL |
+                                                                PROCMGR_DAEMON_NOCHDIR |
+                                                                PROCMGR_DAEMON_NOCLOSE);
+
+    /*
+     * This thread ignores all signals except SIGTERM. On receipt of
+     * a SIGTERM, we shut everything down and exit.
+     */
+    sigemptyset(&sigset);
+    sigaddset(&sigset, SIGTERM);
+
+    while (1)
+       {
+        if (SignalWaitinfo(&sigset, &info) == -1)
+            continue;
+        if (info.si_signo == SIGTERM)
+               {
+            break;
+               }
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int    drv_start_cmd()
+{
+    int rc;
+
+    printf("Starting up...\n");
+       fflush(stdout);
+
+    pthread_setname_np(pthread_self(), "vivante-monitor");
+
+       if ((rc = gpu_init()) != EXIT_SUCCESS)
+       {
+               fprintf(stderr, "Initialization failed!, Exiting.");
+        exit(EXIT_FAILURE);
+       }
+
+       printf("Running galcore...\n");
+       fflush(stdout);
+    rc = drv_resmgr_loop();
+    printf("Shutting down galcore...\n");
+       fflush(stdout);
+
+       gpu_fini();
+
+       return EXIT_SUCCESS;
+}
+
+int drv_stop_cmd()
+{
+    gcsDRIVER_ARGS args;
+    int fd, rc;
+
+       /* Open the gpu device. */
+    fd = open(DRV_NAME, O_RDONLY);
+    if (fd == -1)
+       {
+        fprintf(stderr, "Could not connect to " DRV_NAME);
+        return EXIT_FAILURE;
+    }
+
+       /* Send the term message. */
+    args.iomsg.i.type    = _IO_MSG;
+    args.iomsg.i.subtype = IOCTL_GCHAL_TERMINATE;
+    args.iomsg.i.mgrid   = _IOMGR_VIVANTE;
+    args.iomsg.i.combine_len = sizeof(io_msg_t);
+
+    do {
+        rc = MsgSend_r(fd, &args, args.iomsg.i.combine_len, NULL, 0);
+    } while ((rc * -1) == EINTR);
+
+       return EXIT_SUCCESS;
+}
+
+int main(int argc, char **argv)
+{
+       enum { start, stop } cmd = start;
+    int i;
+       int rc = EXIT_FAILURE;
+
+    /* Process command lines -start, -stop, -c (file), -d [file]. */
+    for (i = 1; i < argc; i++)
+       {
+        if (stricmp(argv[i], "-start") == 0)
+               {
+            cmd = start;
+        }
+               else if (strcmp(argv[i], "-stop") == 0)
+               {
+            cmd = stop;
+        }
+               else if (strncmp(argv[i], "-poolsize=", strlen("-poolsize=")) == 0)
+               {
+                       /* The syntax of the poolsize option is -poolsize=(number).
+                        * All we need is to convert the number that starts after the '='.*/
+                       contiguousSize = atoi(argv[i] + strlen("-poolsize="));
+                       if (contiguousSize <= 0)
+                       {
+                               fprintf(stderr, "%s: poolsize needs to be a positive number\n", strerror(errno));
+                               return rc;
+                       }
+               }
+               else
+               {
+            fprintf(stderr, "%s: bad command line\n", argv[0]);
+            return rc;
+        }
+    }
+
+    switch (cmd)
+       {
+        case start:
+                       /* Elevate thread priority to do IO. */
+                       ThreadCtl(_NTO_TCTL_IO, 0);
+                       rc = drv_start_cmd();
+            break;
+
+        case stop:
+            rc = drv_stop_cmd();
+            break;
+    }
+
+    return rc;
+}
+
+#endif /* QNX_USE_OLD_FRAMEWORK */
+
diff --git a/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_os.c b/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_os.c
new file mode 100644 (file)
index 0000000..0416ca8
--- /dev/null
@@ -0,0 +1,3008 @@
+/****************************************************************************
+*
+*    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+*
+*    The material in this file is confidential and contains trade secrets
+*    of Vivante Corporation. This is proprietary information owned by
+*    Vivante Corporation. No part of this work may be disclosed,
+*    reproduced, copied, transmitted, or used in any way for any purpose,
+*    without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+*    Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_qnx.h"
+
+
+
+# include <winmgr/gpu.h>
+
+#define USE_VMALLOC 0
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+#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))
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+struct _gckOS
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Heap. */
+    gckHEAP                     heap;
+
+    /* Pointer to device */
+    gckGALDEVICE                device;
+
+    /* Memory management */
+    gctPOINTER                  memoryLock;
+    gctPOINTER                  memoryMapLock;
+    gctPOINTER                  mempoolBaseAddress;
+    gctPOINTER                  mempoolBasePAddress;
+    gctUINT32                   mempoolPageSize;
+
+    gctUINT32                   baseAddress;
+
+    /* Atomic operation lock. */
+    gctPOINTER                  atomicOperationLock;
+};
+
+
+typedef struct _gcskSIGNAL
+{
+    pthread_mutex_t *mutex;
+
+    /* Manual reset flag. */
+    gctBOOL manualReset;
+}
+gcskSIGNAL;
+
+typedef struct _gcskSIGNAL *    gcskSIGNAL_PTR;
+
+
+/*******************************************************************************
+**
+**  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;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Os != gcvNULL);
+
+    /* Allocate the gckOS object. */
+    os = (gckOS) malloc(gcmSIZEOF(struct _gckOS));
+
+    if (os == gcvNULL)
+    {
+        /* Out of memory. */
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    /* Zero the memory. */
+    memset(os, 0, 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 the gckHEAP object. */
+    gcmkONERROR(
+        gckHEAP_Construct(os, gcdHEAP_SIZE, &os->heap));
+
+    /* Find the base address of the physical memory. */
+    os->baseAddress = os->device->baseAddress;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+                  "Physical base address set to 0x%08X.\n",
+                  os->baseAddress);
+
+    os->mempoolBaseAddress = (gctPOINTER) drv_mempool_get_baseAddress();
+    os->mempoolBasePAddress = (gctPOINTER) drv_mempool_get_basePAddress();
+    os->mempoolPageSize = drv_mempool_get_page_size();
+
+
+    /* Initialize the atomic operations lock. */
+    gcmkONERROR(
+        gckOS_CreateMutex(os, &os->atomicOperationLock));
+
+    /* Return pointer to the gckOS object. */
+    *Os = os;
+
+    /* Success. */
+    return gcvSTATUS_OK;
+
+OnError:
+    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->atomicOperationLock != gcvNULL)
+    {
+        gcmkVERIFY_OK(
+            gckOS_DeleteMutex(os, os->atomicOperationLock));
+    }
+
+    free(os);
+
+    /* Return the error. */
+    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;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    if (Os->heap != NULL)
+    {
+        /* Mark gckHEAP as gone. */
+        heap     = Os->heap;
+        Os->heap = NULL;
+
+        /* 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 the atomic operation lock. */
+    gcmkVERIFY_OK(
+        gckOS_DeleteMutex(Os, Os->atomicOperationLock));
+
+    /* Mark the gckOS object as unknown. */
+    Os->object.type = gcvOBJ_UNKNOWN;
+
+    /* Free the gckOS object. */
+    free(Os);
+
+    /* Success. */
+    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 != NULL);
+
+    /* Do we have a heap? */
+    if (Os->heap != NULL)
+    {
+        /* 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;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Memory != NULL);
+
+    /* Do we have a heap? */
+    if (Os->heap != NULL)
+    {
+        /* Free from the heap. */
+        gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
+    }
+    else
+    {
+        gcmkONERROR(gckOS_FreeMemory(Os, Memory));
+    }
+
+    /* Success. */
+    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 != NULL);
+
+    memory = (gctPOINTER) calloc(1, Bytes);
+
+    if (memory == NULL)
+    {
+        /* 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 != NULL);
+
+    /* Free the memory from the OS pool. */
+    free(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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != 0);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "Enter gckOS_MapMemory\n");
+
+    MEMORY_LOCK(Os);
+
+    /* Map physical address. */
+    *Logical = mmap64(0,
+        Bytes,
+        PROT_READ | PROT_WRITE,
+        MAP_PHYS | MAP_SHARED,
+        NOFD,
+        (off_t)Physical);
+
+    MEMORY_UNLOCK(Os);
+
+    if (*Logical == MAP_FAILED)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "gckOS_MapMemory: mmap error: %s\n",
+            strerror(errno));
+
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_OS,
+                "gckOS_MapMemory: User Mapped address for 0x%x is 0x%x\n",
+                (gctUINT32)Physical,
+                (gctUINT32)*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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != 0);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_UnmapMemory\n");
+
+    if (Logical)
+    {
+        gctUINT32 res;
+        gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+            gcvZONE_OS,
+            "[gckOS_UnmapMemory] Logical: 0x%x\n",
+            Logical
+            );
+
+        MEMORY_LOCK(Os);
+
+        res = munmap(Logical, Bytes);
+
+        MEMORY_UNLOCK(Os);
+
+        if (res == -1)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+                gcvZONE_OS,
+                "gckOS_UnmapMemory: munmap error: %s\n",
+                strerror(errno));
+
+            return gcvSTATUS_INVALID_ARGUMENT;
+        }
+    }
+
+    /* Success. */
+    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
+    )
+{
+
+    if (InUserSpace)
+    {
+        /* TODO: Make a separate OS call for allocating from shared memory pool. */
+        *Logical = drv_shmpool_alloc_contiguous((gctUINT32)Physical, (gctHANDLE)Logical, *Bytes);
+
+        if (*Logical == gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_AllocateNonPagedMemory: Out of memory.");
+
+            *Bytes = 0;
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+
+        /* Used to distinguish from memory allocated in kernel space. */
+        *((gctUINT32*)Physical) = 0;
+    }
+    else
+    {
+        drv_mempool_alloc_contiguous(*Bytes, Physical, Logical);
+
+        if (*Physical == gcvNULL || *Logical == gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_AllocateNonPagedMemory: Out of memory.");
+
+            *Bytes = 0;
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+    }
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_AllocateNonPagedMemory: "
+                "Bytes->0x%x, Logical->0x%x Physical->0x%x\n",
+                (gctUINT32)*Bytes,
+                *Logical,
+                *Physical);
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    int rc;
+
+    if (Physical)
+    {
+        rc = drv_mempool_free(Logical);
+    }
+    else
+    {
+        rc = drv_shmpool_free(Logical);
+    }
+
+    if (rc == -1)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                    gcvZONE_OS,
+                    "gckOS_FreeNonPagedMemory: "
+                    "Unmap Failed Logical->0x%x, Bytes->%d, Physical->0x%x\n",
+                    (gctUINT32)Logical,
+                    Bytes,
+                    (gctUINT32)Physical);
+        return gcvSTATUS_INVALID_ARGUMENT;
+    }
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_FreeNonPagedMemory: "
+                "Logical->0x%x Physical->0x%x\n",
+                (gctUINT32)Logical,
+                (gctUINT32)Physical);
+
+    /* Success. */
+    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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Data != NULL);
+
+    *Data = (gctUINT32)in32((uintptr_t) ((gctUINT8 *)Os->device->registerBase + Address));
+
+    /* Success. */
+    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
+    )
+{
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_WriteRegister: "
+                "Writing to physical address [%x] = %x\n",
+                (gctUINT8 *)Os->device->registerBase,
+                Data);
+
+    out32((uintptr_t) ((gctUINT8 *)Os->device->registerBase + Address), (uint32_t)Data);
+
+    /* Success. */
+    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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(PageSize != NULL);
+
+    /* Return the page size. */
+    *PageSize = (gctSIZE_T) __PAGESIZE;
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_GetPhysicalAddressProcess
+**
+**  Get the physical system address of a corresponding virtual address for a
+**  given process.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      gctPOINTER Logical
+**          Logical address.
+**
+**      gctUINT ProcessID
+**          Procedd 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 gctUINT ProcessID,
+    OUT gctUINT32 * Address
+    )
+{
+    return gckOS_GetPhysicalAddress(Os, Logical, Address);
+}
+
+/*******************************************************************************
+**
+**  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
+**          Pointer to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS gckOS_GetPhysicalAddress(
+    IN gckOS Os,
+    IN gctPOINTER Logical,
+    OUT gctUINT32 * Address
+    )
+{
+
+    gctUINT32 res;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    if ( drv_mempool_mem_offset(Logical, Address) != gcvSTATUS_OK)
+    {
+        if ( drv_shmpool_mem_offset(Logical, Address) != gcvSTATUS_OK)
+        {
+            printf("Warning, using mem_offset for Logical:%x!\n", (gctUINT32) Logical);
+
+            MEMORY_LOCK(Os);
+
+            /* TODO: mem_offset in QNX works only for memory that is allocated
+               contiguosly using gckOS_AllocateContiguous(). */
+            res = mem_offset( Logical, NOFD, 1, (off_t *)Address, NULL);
+
+            if (res == -1)
+            {
+                MEMORY_UNLOCK(Os);
+
+                gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                            gcvZONE_OS,
+                            "gckOS_GetPhysicalAddress: "
+                            "Unable to get physical address for 0x%x\n",
+                            (gctUINT32)Logical);
+
+                return gcvSTATUS_INVALID_ARGUMENT;
+            }
+
+            MEMORY_UNLOCK(Os);
+        }
+    }
+
+    /* Subtract base address to get a GPU physical address. */
+    gcmASSERT(*Address >= Os->baseAddress);
+    *Address -= Os->baseAddress;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                    gcvZONE_OS,
+                    "gckOS_GetPhysicalAddress: Logical->0x%x Physical->0x%x\n",
+                    (gctUINT32)Logical,
+                    (gctUINT32)*Address);
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    gctUINT32 physical;
+
+    /* 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->baseAddress;
+
+    /* Map physical address. */
+    *Logical = mmap64(0,
+        Bytes,
+        PROT_READ | PROT_WRITE,
+        MAP_PHYS | MAP_SHARED | MAP_NOINIT,
+        NOFD,
+        (off_t)physical);
+
+    MEMORY_UNLOCK(Os);
+
+    if (*Logical == MAP_FAILED)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "gckOS_MapMemory: mmap error: %s\n",
+            strerror(errno));
+
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+                  "gckOS_MapPhysical: "
+                  "Physical->0x%X Bytes->0x%X Logical->0x%X\n",
+                  (gctUINT32) Physical,
+                  (gctUINT32) Bytes,
+                  (gctUINT32) *Logical);
+
+    /* Success. */
+    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
+    )
+{
+    gctUINT32 res;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+    MEMORY_LOCK(Os);
+
+    res = munmap(Logical, Bytes);
+
+    MEMORY_UNLOCK(Os);
+
+    if (res == -1)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+            gcvZONE_OS,
+            "gckOS_UnmapMemory: munmap error: %s\n",
+            strerror(errno));
+
+        return gcvSTATUS_INVALID_ARGUMENT;
+    }
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                    gcvZONE_OS,
+                    "gckOS_UnmapPhysical: "
+                    "Logical->0x%x Bytes->0x%x\n",
+                    (gctUINT32)Logical,
+                    (gctUINT32)Bytes);
+
+    /* Success. */
+    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
+    )
+{
+    gctUINT32 res;
+
+    /* Validate the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+    /* Allocate a FAST_MUTEX structure. */
+    *Mutex = (gctPOINTER) malloc(sizeof(pthread_mutex_t));
+
+    if (*Mutex == gcvNULL)
+    {
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    /* Initialize the semaphore.. Come up in unlocked state. */
+    res = pthread_mutex_init((pthread_mutex_t *)(*Mutex), NULL);
+    if (res != EOK)
+    {
+        return gcvSTATUS_OUT_OF_RESOURCES;
+    }
+
+    /* Return status. */
+    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
+    )
+{
+    gctUINT32 res;
+
+    /* Validate the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+    res = pthread_mutex_destroy((pthread_mutex_t *)(Mutex));
+
+    if (res != EOK)
+    {
+        return gcvSTATUS_INVALID_ARGUMENT;
+    }
+
+    /* Delete the fast mutex. */
+    free(Mutex);
+
+    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
+    )
+{
+    /* Validate the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+    if (Timeout == gcvINFINITE)
+    {
+        pthread_mutex_lock((pthread_mutex_t *) Mutex);
+
+        /* Success. */
+        return gcvSTATUS_OK;
+    }
+
+    while (Timeout-- > 0)
+    {
+        /* Try to acquire the fast mutex. */
+        if (!pthread_mutex_trylock((pthread_mutex_t *) Mutex))
+        {
+            /* Success. */
+            return gcvSTATUS_OK;
+        }
+
+        /* Wait for 1 millisecond. */
+        gcmkVERIFY_OK(gckOS_Delay(Os, 1));
+    }
+
+    /* 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
+    )
+{
+    /* Validate the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+    /* Release the fast mutex. */
+    pthread_mutex_unlock((pthread_mutex_t *) Mutex);
+
+    /* Success. */
+    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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    /* Acquire atomic operation lock. */
+    gcmkVERIFY_OK(gckOS_AcquireMutex(Os,
+                                    Os->atomicOperationLock,
+                                    gcvINFINITE));
+
+    /* Exchange the pair of 32-bit values. */
+    *OldValue = *Target;
+    *Target = NewValue;
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->atomicOperationLock));
+
+    /* Success. */
+    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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    /* Acquire atomic operation lock. */
+    gcmkVERIFY_OK(gckOS_AcquireMutex(Os,
+                                    Os->atomicOperationLock,
+                                    gcvINFINITE));
+
+    /* Exchange the pair of pointers. */
+    *OldValue = *Target;
+    *Target = NewValue;
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->atomicOperationLock));
+
+    /* Success. */
+    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
+    )
+{
+    /* Schedule delay. */
+    delay(Delay);
+
+    /* Success. */
+    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
+    )
+{
+    /* Verify thearguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    __cpu_membarrier();
+
+    /* Success. */
+    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
+    )
+{
+    return gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical);
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    int rc, fd, shm_ctl_flags = SHMCTL_ANON | SHMCTL_LAZYWRITE;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_AllocatePagedMemory\n");
+
+    if (Contiguous)
+    {
+        shm_ctl_flags |= SHMCTL_PHYS;
+    }
+
+    /* Lock down, to avoid opening same shm file twice. */
+    MEMORY_LOCK(Os);
+
+    fd = shm_open("shm_gal", O_RDWR | O_CREAT, 0777);
+    if (fd == -1) {
+        printf("shm_open failed. error %s\n", strerror( errno ) );
+        return gcvSTATUS_GENERIC_IO;
+    }
+
+    /* Free to use the same name for next create shm object after shm_unlink. */
+    shm_unlink("shm_gal");
+
+    MEMORY_UNLOCK(Os);
+
+    /* Special flags for this shm, to make it write buffered. */
+    /* Virtual memory doesn't need to be physically contiguous. */
+    /* Allocations would be page aligned. */
+    rc = shm_ctl_special(fd,
+                         SHMCTL_ANON /*| SHMCTL_PHYS*/ | SHMCTL_LAZYWRITE,
+                         0,
+                         Bytes,
+                         0x9);
+    if (rc == -1) {
+        printf("shm_ctl_special failed. error %s\n", strerror( errno ) );
+        close(fd);
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    /* Use the fd as the handle for the physical memory just allocated. */
+    *Physical = (gctPHYS_ADDR) fd;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_AllocatePagedMemory: "
+                "Bytes->0x%x, Physical->0x%x\n",
+                (gctUINT32)Bytes,
+                (gctUINT32)*Physical);
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    int rc;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_FreePagedMemory\n");
+
+    rc = close((gctINT)Physical);
+    if ( rc == -1 )
+    {
+        printf("gckOS_FreePagedMemory failed. error: %s\n", strerror( errno ) );
+        return gcvSTATUS_GENERIC_IO;
+    }
+
+    /* Success. */
+    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.
+**
+**  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.
+*/
+gceSTATUS gckOS_LockPages(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctUINT32 Pid,
+    OUT gctPOINTER * Logical,
+    OUT gctSIZE_T * PageCount
+    )
+{
+    void* addr;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+    gcmkVERIFY_ARGUMENT(PageCount != NULL);
+    gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_LockPages\n");
+
+    /* Map this memory inside user and galcore. */
+    addr = mmap64_join(Pid,
+                       0,
+                       Bytes,
+                       PROT_READ | PROT_WRITE,
+                       MAP_SHARED,
+                       (int)Physical,
+                       0);
+
+    if (addr == MAP_FAILED)
+    {
+        printf("gckOS_LockPages: couldn't map memory of size %d, Pid: %x [errno %s]",
+                (gctUINT32)Bytes, Pid, strerror( errno ) );
+        return gcvSTATUS_GENERIC_IO;
+    }
+
+    /* TODO: MLOCK may or may not be needed!. */
+    mlock((void*)addr, Bytes);
+
+    *Logical = (gctPOINTER)addr;
+    *PageCount = (gcmALIGN(Bytes, __PAGESIZE)) / __PAGESIZE;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_LockPages: "
+                "gctPHYS_ADDR->0x%x Bytes->0x%x Logical->0x%x pid->%d\n",
+                (gctUINT32)Physical,
+                (gctUINT32)Bytes,
+                (gctUINT32)*Logical,
+                Pid);
+
+    /* Success. */
+    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 gctPOINTER Logical,
+    IN gctSIZE_T PageCount,
+    IN gctPOINTER PageTable
+    )
+{
+    gctUINT32* table;
+    gctPOINTER addr;
+    size_t contigLen = 0;
+    off_t offset;
+    gctUINT32 bytes;
+    int rc;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+    gcmkVERIFY_ARGUMENT(PageCount > 0);
+    gcmkVERIFY_ARGUMENT(PageTable != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_MapPages\n");
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_MapPages: "
+                "Physical->0x%x PageCount->0x%x Logical->0x%x\n",
+                (gctUINT32)Physical,
+                (gctUINT32)PageCount,
+                (gctUINT32)Logical);
+
+    addr = Logical;
+    table = (gctUINT32 *)PageTable;
+    bytes = PageCount * __PAGESIZE;
+
+    /* Try to get the user pages so DMA can happen. */
+    while (PageCount > 0)
+    {
+        /* fd should be NOFD here, to get physical address. */
+        rc = mem_offset( addr, NOFD, bytes, &offset, &contigLen);
+        if (rc == -1) {
+            printf("gckOS_MapPages: mem_offset failed: %s\n", strerror( errno ) );
+            return gcvSTATUS_GENERIC_IO;
+        }
+
+        gcmASSERT(contigLen > 0);
+
+        while(contigLen > 0)
+        {
+            *table++ = (gctUINT32) offset;
+            offset += 4096;
+            addr += 4096;
+            contigLen -= 4096;
+            bytes -= 4096;
+            PageCount--;
+        }
+    }
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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 gctUINT32 Pid,
+    IN gctSIZE_T Bytes,
+    IN gctPOINTER Logical
+    )
+{
+    int rc = 0;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != NULL);
+    gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "in gckOS_UnlockPages\n");
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_MapPages: "
+                "Physical->0x%x Bytes->0x%x Logical->0x%x Pid->0x%x\n",
+                (gctUINT32)Physical,
+                (gctUINT32)Bytes,
+                (gctUINT32)Logical,
+                (gctUINT32)Pid);
+
+    rc = munmap((void*)Logical, Bytes);
+    if (rc == -1) {
+        printf("munmap failed: %s\n", strerror( errno ) );
+        return gcvSTATUS_GENERIC_IO;
+    }
+
+    rc = munmap_peer(Pid, (void*)Logical, Bytes);
+    if (rc == -1) {
+        printf("munmap_peer failed: %s\n", strerror( errno ) );
+        return gcvSTATUS_GENERIC_IO;
+    }
+
+    /* Success. */
+    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
+    )
+{
+    /* Same as non-paged memory for now. */
+    return gckOS_AllocateNonPagedMemory(Os,
+                InUserSpace,
+                Bytes,
+                Physical,
+                Logical
+                );
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    /* Same of non-paged memory for now. */
+    return gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical);
+}
+
+/******************************************************************************
+**
+**  gckOS_GetKernelLogical
+**
+**  Return the kernel logical pointer that corresponds 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
+    )
+{
+    gceSTATUS status;
+
+    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->kernel;
+
+        /* 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. */
+        return gcvSTATUS_OK;
+    }
+    while (gcvFALSE);
+
+    /* Return status. */
+    return status;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    /* A pointer is assumed to be allocated from its shared memory object.
+       Which is mapped by both user and kernel at the same vitual address. */
+    /* TODO: Check if Pointer is a valid pointer? */
+    *KernelPointer = Pointer;
+
+    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
+    )
+{
+    /* Nothing to unmap. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_MapUserPhysical
+**
+**  Map a physical address from the user process into the kernel address space.
+**  The physical address should be obtained by user from gckOS_AllocateNonPagedMemory.
+**
+**  INPUT:
+**
+**      gckOS Os
+**          Pointer to an gckOS object.
+**
+**      IN gctPHYS_ADDR Phys,
+**          Physical address of memory that needs to be mapped.
+**
+**  OUTPUT:
+**
+**      gctPHYS_ADDR * KernelPointer
+**          Pointer to a variable receiving the mapped pointer in kernel address
+**          space.
+*/
+gceSTATUS
+gckOS_MapUserPhysical(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Phys,
+    OUT gctPHYS_ADDR * KernelPointer
+    )
+{
+    /* A gctPHYS_ADDR is assumed to be allocated from physical memory pool. */
+    /* Dont call this function for pointers already in kernel space. */
+    printf("ERROR: %s Not supported.\n", __FUNCTION__);
+    *KernelPointer = (gctPHYS_ADDR)0xDEADBEEF;
+
+    return gcvSTATUS_NOT_SUPPORTED;
+}
+
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Address != NULL);
+
+    /* Write memory. */
+    *(gctUINT32 *)Address = Data;
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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.
+**          Nonsignaled state in QNX is mutex acquired (not free).
+**
+**  OUTPUT:
+**
+**      gctSIGNAL * Signal
+**          Pointer to a variable receiving the created gctSIGNAL.
+*/
+gceSTATUS
+gckOS_CreateSignal(
+    IN gckOS Os,
+    IN gctBOOL ManualReset,
+    OUT gctSIGNAL * Signal
+    )
+{
+    gcskSIGNAL_PTR signal;
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Os=0x%x ManualReset=0x%x", Os, ManualReset);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Signal != NULL);
+
+    /* Create an event structure. */
+    signal = (gcskSIGNAL_PTR) malloc(sizeof(gcskSIGNAL));
+
+    if (signal == gcvNULL)
+    {
+        gcmFOOTER_NO();
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    signal->manualReset = ManualReset;
+
+    status = gckOS_CreateMutex(Os, (gctPOINTER *)(&signal->mutex));
+
+    if (gcmIS_ERROR(status))
+    {
+        /* Error. */
+        free(signal);
+        gcmFOOTER();
+        return status;
+    }
+
+    *Signal = (gctSIGNAL) signal;
+
+    /* Success. */
+    gcmkFOOTER_ARG("Os=0x%x Signal=0x%x", Os, 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
+    )
+{
+
+    gceSTATUS status = gcvSTATUS_OK;
+    gcskSIGNAL_PTR signal;
+
+    gcmkHEADER_ARG("Os=0x%x Signal=0x%x", Os, Signal);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Signal != NULL);
+
+    signal = (gcskSIGNAL_PTR) Signal;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Signal != NULL);
+
+    if (signal != gcvNULL )
+    {
+        status = gckOS_DeleteMutex(Os, (gctPOINTER)(signal->mutex));
+
+        free(signal);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    gcskSIGNAL_PTR signal;
+    gceSTATUS status = gcvSTATUS_OK;
+
+    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 = (gcskSIGNAL_PTR) Signal;
+
+    /* Set the new state of the event. */
+    if (signal->manualReset && State)
+    {
+        /* Set the event to a signaled state. */
+        gckOS_ReleaseMutex(Os,(gctPOINTER *)(&signal->mutex));
+    }
+    else
+    {
+        gckOS_AcquireMutex(Os, (gctPOINTER *)(&signal->mutex), gcvINFINITE);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  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 gctINT Rcvid,
+    IN gctINT Coid
+    )
+{
+    gctINT rc;
+    struct sigevent event;
+
+    SIGEV_PULSE_INIT( &event, Coid, SIGEV_PULSE_PRIO_INHERIT, _PULSE_CODE_MINAVAIL, Signal);
+
+    rc = MsgDeliverEvent_r(Rcvid, &event);
+    if (rc != EOK)
+    {
+        gcmkTRACE(gcvLEVEL_INFO,
+                 "%s(%d): Sent signal to (receive ID = %d, connect ID = %d).",
+                 __FUNCTION__, __LINE__, Rcvid, Coid);
+
+        gcmkTRACE(gcvLEVEL_ERROR,
+                 "%s(%d): MsgDeliverEvent failed (%d).",
+                 __FUNCTION__, __LINE__, rc);
+
+;
+
+        return gcvSTATUS_GENERIC_IO;
+    }
+
+    /* Return status. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  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;
+
+    gcskSIGNAL_PTR signal;
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+    signal = (gcskSIGNAL_PTR) Signal;
+
+    status = gckOS_AcquireMutex(Os, (gctPOINTER *)(&signal->mutex), Wait);
+
+    /* If manualReset is true, use gckOS_Signal to acquire mutex again. */
+    if (signal->manualReset)
+    {
+        status = gckOS_ReleaseMutex(Os, (gctPOINTER *)(&signal->mutex));
+    }
+
+    /* Return 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
+    )
+{
+    printf("ERROR: %s Not supported.\n", __FUNCTION__);
+    return gcvSTATUS_NOT_SUPPORTED;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Size > 0);
+    gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+        gcvZONE_OS,
+        "[gckOS_MapUserMemory] enter.\n"
+        );
+
+    printf("ERROR: %s Not supported.\n", __FUNCTION__);
+
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+        gcvZONE_OS,
+        "[gckOS_MapUserMemory] leave.\n"
+        );
+
+    /* Return the status. */
+    return gcvSTATUS_NOT_SUPPORTED;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Size > 0);
+    gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+
+    gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+        gcvZONE_OS,
+        "[gckOS_UnmapUserMemory] enter.\n"
+        );
+
+    printf("ERROR: %s Not supported.\n", __FUNCTION__);
+
+    /* Return the status. */
+    return gcvSTATUS_NOT_SUPPORTED;
+}
+
+/*******************************************************************************
+**
+**  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
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+    /* Return base address. */
+    *BaseAddress = Os->baseAddress;
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+    IN gckOS Os
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    InterruptLock(&Os->device->isrLock);
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+    IN gckOS Os
+    )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    InterruptUnlock(&Os->device->isrLock);
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_NotifyIdle(
+    IN gckOS Os,
+    IN gctBOOL Idle
+    )
+{
+    /* TODO */
+    return gcvSTATUS_OK;
+}
+
+/* Perform a memory copy. */
+gceSTATUS
+gckOS_MemCopy(
+        IN gctPOINTER Destination,
+        IN gctCONST_POINTER Source,
+        IN gctSIZE_T Bytes
+        )
+{
+        gcmkVERIFY_ARGUMENT(Destination != NULL);
+        gcmkVERIFY_ARGUMENT(Source != NULL);
+        gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+        memcpy(Destination, Source, Bytes);
+
+        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_AllocateNonPagedMemoryShmPool(
+    IN gckOS Os,
+    IN gctBOOL InUserSpace,
+    IN gctUINT32 Pid,
+    IN gctHANDLE Handle,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctPHYS_ADDR * Physical,
+    OUT gctPOINTER * Logical
+    )
+{
+
+    if (InUserSpace)
+    {
+        *Logical = drv_shmpool_alloc_contiguous(Pid, Handle, *Bytes);
+
+        if (*Logical == gcvNULL)
+        {
+            gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_AllocateNonPagedMemory: Out of memory.");
+
+            *Bytes = 0;
+            return gcvSTATUS_OUT_OF_RESOURCES;
+        }
+
+        /* Used to distinguish from memory allocated in kernel space. */
+        *((gctUINT32*)Physical) = 0;
+    }
+    else
+    {
+        return gcvSTATUS_INVALID_ARGUMENT;
+    }
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO,
+                gcvZONE_OS,
+                "gckOS_AllocateNonPagedMemoryShmPool: "
+                "Bytes->0x%x, Logical->0x%x Physical->0x%x\n",
+                (gctUINT32)*Bytes,
+                *Logical,
+                *Physical);
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+int
+memmgr_peer_sendnc(pid_t pid, int coid, void *smsg, size_t sbytes, void *rmsg, size_t rbytes )
+{
+    mem_peer_t  peer;
+    iov_t       siov[2];
+    int         rc;
+
+    peer.i.type = _MEM_PEER;
+    peer.i.peer_msg_len = sizeof(peer);
+    peer.i.pid = pid;
+
+    SETIOV(siov + 0, &peer, sizeof peer);
+    SETIOV(siov + 1, smsg, sbytes);
+
+    do {
+        rc = MsgSendvsnc(coid, siov, 2, rmsg, rbytes);
+    } while (rc == -1 && errno == EINTR);
+
+    return rc;
+}
+
+void *
+_mmap2_peer(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off,
+        unsigned align, unsigned pre_load, void **base, size_t *size) {
+    mem_map_t msg;
+
+    msg.i.type = _MEM_MAP;
+    msg.i.zero = 0;
+    msg.i.addr = (uintptr_t)addr;
+    msg.i.len = len;
+    msg.i.prot = prot;
+    msg.i.flags = flags;
+    msg.i.fd = fd;
+    msg.i.offset = off;
+    msg.i.align = align;
+    msg.i.preload = pre_load;
+    msg.i.reserved1 = 0;
+    if (memmgr_peer_sendnc(pid, MEMMGR_COID, &msg.i, sizeof msg.i, &msg.o, sizeof msg.o) == -1) {
+        return MAP_FAILED;
+    }
+    if (base) {
+        *base = (void *)(uintptr_t)msg.o.real_addr;
+    }
+    if (size) {
+        *size = msg.o.real_size;
+    }
+    return (void *)(uintptr_t)msg.o.addr;
+}
+
+void *
+mmap64_peer(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off) {
+    return _mmap2_peer(pid, addr, len, prot, flags, fd, off, 0, 0, 0, 0);
+}
+
+int
+munmap_flags_peer(pid_t pid, void *addr, size_t len, unsigned flags) {
+    mem_ctrl_t msg;
+
+    msg.i.type = _MEM_CTRL;
+    msg.i.subtype = _MEM_CTRL_UNMAP;
+    msg.i.addr = (uintptr_t)addr;
+    msg.i.len = len;
+    msg.i.flags = flags;
+    return memmgr_peer_sendnc(pid, MEMMGR_COID, &msg.i, sizeof msg.i, 0, 0);
+}
+
+int
+munmap_peer(pid_t pid, void *addr, size_t len) {
+    return munmap_flags_peer(pid, addr, len, 0);
+}
+
+int
+mem_offset64_peer(pid_t pid, const uintptr_t addr, size_t len,
+                off64_t *offset, size_t *contig_len) {
+    int rc;
+
+    struct _peer_mem_off {
+        struct _mem_peer peer;
+        struct _mem_offset msg;
+    };
+    typedef union {
+        struct _peer_mem_off i;
+        struct _mem_offset_reply o;
+    } memoffset_peer_t;
+    memoffset_peer_t msg;
+
+    msg.i.peer.type = _MEM_PEER;
+    msg.i.peer.peer_msg_len = sizeof(msg.i.peer);
+    msg.i.peer.pid = pid;
+    msg.i.peer.reserved1 = 0;
+
+    msg.i.msg.type = _MEM_OFFSET;
+    msg.i.msg.subtype = _MEM_OFFSET_PHYS;
+    msg.i.msg.addr = addr;
+    msg.i.msg.reserved = -1;
+    msg.i.msg.len = len;
+
+    do {
+        rc = MsgSendnc(MEMMGR_COID, &msg.i, sizeof msg.i, &msg.o, sizeof msg.o);
+    } while (rc == -1 && errno == EINTR);
+
+    if (rc == -1) {
+        return -1;
+    }
+
+    *offset = msg.o.offset;
+    *contig_len = msg.o.size;
+
+    return 0;
+}
+
+#if defined(__X86__)
+#define CPU_VADDR_SERVER_HINT 0x30000000u
+#elif defined(__ARM__)
+#define CPU_VADDR_SERVER_HINT 0x20000000u
+#else
+#error NO CPU SOUP FOR YOU!
+#endif
+
+/*
+ * map the object into both client and server at the same virtual address
+ */
+void *
+mmap64_join(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off) {
+    void *svaddr, *cvaddr = MAP_FAILED;
+    uintptr_t hint = (uintptr_t)addr;
+    uintptr_t start_hint = hint;
+
+    if ( hint == (uintptr_t)0 )
+    {
+        hint = (uintptr_t)CPU_VADDR_SERVER_HINT;
+    }
+
+    do {
+        svaddr = mmap64( (void *)hint, len, prot, flags, fd, off );
+        if ( svaddr == MAP_FAILED ) {
+            break;
+        }
+        if ( svaddr == cvaddr ) {
+            return svaddr;
+        }
+
+        cvaddr = mmap64_peer( pid, svaddr, len, prot, MAP_FIXED | flags, fd, off );
+        if ( cvaddr == MAP_FAILED ) {
+            break;
+        }
+        if ( svaddr == cvaddr ) {
+            return svaddr;
+        }
+
+        if ( munmap( svaddr, len ) == -1 ) {
+            svaddr = MAP_FAILED;
+            break;
+        }
+
+        svaddr = mmap64( cvaddr, len, prot, flags, fd, off );
+        if ( svaddr == MAP_FAILED ) {
+            break;
+        }
+        if ( svaddr == cvaddr ) {
+            return svaddr;
+        }
+
+        if ( munmap( svaddr, len ) == -1 ) {
+            svaddr = MAP_FAILED;
+            break;
+        }
+        if ( munmap_peer( pid, cvaddr, len ) == -1 ) {
+            cvaddr = MAP_FAILED;
+            break;
+        }
+        hint += __PAGESIZE;
+
+    } while(hint != start_hint); /* do we really want to wrap all the way */
+
+    if ( svaddr != MAP_FAILED ) {
+        munmap( svaddr, len );
+    }
+    if ( cvaddr != MAP_FAILED ) {
+        munmap_peer( pid, cvaddr, len );
+    }
+
+    return MAP_FAILED;
+}
+
+/*******************************************************************************
+**  gckOS_CacheFlush
+**
+**  Flush 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.
+**
+**      gctHANDLE Process
+**          Process handle Logical belongs to or gcvNULL if Logical belongs to
+**          the kernel.
+**
+**      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 gctHANDLE Process,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**  gckOS_CacheInvalidate
+**
+**  Flush 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.
+**
+**      gctHANDLE Process
+**          Process handle Logical belongs to or gcvNULL if Logical belongs to
+**          the kernel.
+**
+**      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 gctHANDLE Process,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** Broadcast interface.
+*/
+
+gceSTATUS
+gckOS_Broadcast(
+    IN gckOS Os,
+    IN gckHARDWARE Hardware,
+    IN gceBROADCAST Reason
+    )
+{
+    return gcvSTATUS_OK;
+}
+
diff --git a/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_os.h b/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_os.h
new file mode 100644 (file)
index 0000000..92791d9
--- /dev/null
@@ -0,0 +1,163 @@
+/****************************************************************************
+*
+*    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+*
+*    The material in this file is confidential and contains trade secrets
+*    of Vivante Corporation. This is proprietary information owned by
+*    Vivante Corporation. No part of this work may be disclosed,
+*    reproduced, copied, transmitted, or used in any way for any purpose,
+*    without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+*    Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+
+/*
+ * Os.h
+ *
+ *  Created on: Feb 2, 2010
+ *      Author: Tarang Vaish
+ */
+
+#ifndef __gc_hal_kernel_os_h_
+#define __gc_hal_kernel_os_h_
+
+typedef struct
+{
+       io_msg_t iomsg;
+       gcsHAL_INTERFACE iface;
+} gcsDRIVER_ARGS;
+
+struct _gckPAGE_USAGE
+{
+       gctUINT16 pageCount;
+};
+
+struct _gckSHM_POOL
+{
+       gctHANDLE Handle;
+       gctINT32 fd;
+       gctUINT32 pid;
+       gctUINT32 freePage;
+       gctUINT32 pageCount;
+       gctUINT32 pageSize;
+       pthread_mutex_t mutex;
+       gctUINT32 Logical;
+       gctUINT32 Physical;
+       struct _gckPAGE_USAGE* pageUsage;
+       struct _gckSHM_POOL* nextPool;
+};
+
+typedef struct _gckSHM_POOL* gckSHM_POOL;
+typedef struct _gckPAGE_USAGE* gckPAGE_USAGE;
+
+gceSTATUS
+drv_mempool_init();
+
+void
+drv_mempool_destroy();
+
+void
+drv_mempool_alloc_contiguous(
+       IN gctUINT32 Bytes,
+       OUT gctPHYS_ADDR * Physical,
+       OUT gctPOINTER * Logical
+       );
+
+int
+drv_mempool_free(
+               IN gctPOINTER Logical
+               );
+
+gctUINT32
+drv_mempool_get_baseAddress();
+
+gctUINT32
+drv_mempool_get_basePAddress();
+
+gctUINT32
+drv_mempool_get_page_size();
+
+gctINT
+drv_mempool_get_fileDescriptor();
+
+gceSTATUS
+drv_mempool_mem_offset(
+       IN gctPOINTER Logical,
+       OUT gctUINT32 * Address);
+
+/* Shared memory pool functions. */
+gckSHM_POOL drv_shmpool_create(
+               IN gctUINT32 Pid,
+               IN gctHANDLE Handle,
+               IN gctUINT32 PoolSize,
+               IN gctUINT32 PageSize);
+void
+drv_shmpool_destroy(
+               IN gckSHM_POOL ShmPool);
+
+gckSHM_POOL
+drv_shm_acquire_pool(
+               IN gctUINT32 Pid,
+               IN gctHANDLE Handle
+               );
+
+gckSHM_POOL
+drv_shm_acquire_pool2(
+               IN gctPOINTER Logical
+               );
+
+gceSTATUS
+drv_shm_remove_pool(
+               IN gctHANDLE Handle
+               );
+
+gctUINT32
+drv_shmpool_get_BaseAddress(
+               IN gckSHM_POOL ShmPool
+               );
+
+gctUINT32
+drv_shmpool_get_page_size(
+               IN gckSHM_POOL ShmPool
+               );
+
+gceSTATUS
+drv_shmpool_mem_offset(
+       IN gctPOINTER Logical,
+       OUT gctUINT32 * Address);
+
+gctPOINTER
+drv_shmpool_alloc_contiguous(
+               IN gctUINT32 Pid,
+               IN gctHANDLE Handle,
+               IN gctUINT32 Bytes
+               );
+
+gctUINT32
+drv_shmpool_free(
+               IN gctPOINTER Logical
+               );
+
+void *
+mmap64_join(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off);
+
+int
+mem_offset64_peer(pid_t pid, const uintptr_t addr, size_t len,
+                               off64_t *offset, size_t *contig_len);
+
+int
+munmap_peer(pid_t pid, void *addr, size_t len);
+
+void *
+mmap64_peer(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off);
+
+#endif /* __gc_hal_kernel_os_h_ */
+
+
diff --git a/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_qnx.c b/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_qnx.c
new file mode 100644 (file)
index 0000000..7c848de
--- /dev/null
@@ -0,0 +1,401 @@
+/****************************************************************************
+*
+*    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+*
+*    The material in this file is confidential and contains trade secrets
+*    of Vivante Corporation. This is proprietary information owned by
+*    Vivante Corporation. No part of this work may be disclosed,
+*    reproduced, copied, transmitted, or used in any way for any purpose,
+*    without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+*    Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_qnx.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=0x%x", 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=0x%x Pool=0x%x", 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=0x%x", *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
+**
+**     Map video memory 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.
+**
+**             gctUINT32 Pid
+**                     Process ID of the current process.
+**
+**             gctUINT32 Bytes
+**                     Number of bytes to map.
+**
+**     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,
+       IN gctUINT32 Pid,
+       IN gctUINT32 Bytes,
+       OUT gctPOINTER * Logical
+       )
+{
+    off64_t offset = (off64_t)Address - (off64_t)drv_mempool_get_basePAddress();
+
+    gcmkHEADER_ARG("Kernel=0x%x InUserSpace=%d Address=%08x",
+                          Kernel, InUserSpace, Address);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    *Logical = (gctPOINTER)mmap64_peer(Pid, gcvNULL, Bytes,
+               PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOINIT,
+               drv_mempool_get_fileDescriptor(), offset);
+    if (*Logical == MAP_FAILED) {
+        *Logical = NULL;
+        return gcvSTATUS_INVALID_ADDRESS;
+    }
+
+    /* Success. */
+       return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**     gckKERNEL_UnmapVideoMemory
+**
+**     Unmap video memory for the current process.
+**
+**     INPUT:
+**
+**             gckKERNEL Kernel
+**                     Pointer to an gckKERNEL object.
+**
+**             gctUINT32 Address
+**                     Hardware specific memory address.
+**
+**             gctUINT32 Pid
+**                     Process ID of the current process.
+**
+**             gctUINT32 Bytes
+**                     Number of bytes to map.
+**
+**     OUTPUT:
+**
+**             Nothing.
+*/
+gceSTATUS
+gckKERNEL_UnmapVideoMemory(
+       IN gckKERNEL Kernel,
+       IN gctPOINTER Logical,
+       IN gctUINT32 Pid,
+       IN gctUINT32 Bytes
+       )
+{
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    if (munmap_peer(Pid, Logical, Bytes) == -1)
+    {
+       return gcvSTATUS_INVALID_ADDRESS;
+    }
+
+    /* Success. */
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**     gckKERNEL_Notify
+**
+**     This function is called by clients to notify the gckKERNEL 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=0x%x 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=0x%x", 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 = -1;
+
+       /* Success. */
+       gcmkFOOTER_ARG("Settings->signal=%d", Settings->signal);
+       return gcvSTATUS_OK;
+}
+
+
diff --git a/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_qnx.h b/drivers/staging/rk29/vivante/hal/os/qnx/kernel/gc_hal_kernel_qnx.h
new file mode 100644 (file)
index 0000000..79f7619
--- /dev/null
@@ -0,0 +1,58 @@
+/****************************************************************************
+*
+*    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+*
+*    The material in this file is confidential and contains trade secrets
+*    of Vivante Corporation. This is proprietary information owned by
+*    Vivante Corporation. No part of this work may be disclosed,
+*    reproduced, copied, transmitted, or used in any way for any purpose,
+*    without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+*    Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_qnx_h_
+#define __gc_hal_kernel_qnx_h_
+
+#define _QNX_SOURCE
+
+#include <errno.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/iofunc.h>
+#include <sys/dispatch.h>
+#include <sys/procmgr.h>
+#include <sys/memmsg.h>
+#include <fcntl.h>
+#include <sys/syspage.h>
+#include <hw/inout.h>
+#include <atomic.h>
+
+#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"
+#include "../inc/gc_hal_common_qnx.h"
+
+#define _WIDE(string)                          L##string
+#define WIDE(string)                           _WIDE(string)
+
+#define countof(a)                                     (sizeof(a) / sizeof(a[0]))
+
+#ifndef GAL_DEV
+#define GAL_DEV        "/dev/galcore"
+#endif
+
+#endif /* __gc_hal_kernel_qnx_h_ */
+
diff --git a/drivers/staging/rk29/vivante/hal/os/qnx/kernel/makefile.linux b/drivers/staging/rk29/vivante/hal/os/qnx/kernel/makefile.linux
new file mode 100644 (file)
index 0000000..59c5c48
--- /dev/null
@@ -0,0 +1,78 @@
+##############################################################################
+#  
+#    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+#  
+#    The material in this file is confidential and contains trade secrets
+#    of Vivante Corporation. This is proprietary information owned by
+#    Vivante Corporation. No part of this work may be disclosed, 
+#    reproduced, copied, transmitted, or used in any way for any purpose, 
+#    without the express written permission of Vivante Corporation.
+#  
+##############################################################################
+#  
+#    Auto-generated file on 10/12/2010. Do not edit!!!
+#  
+##############################################################################
+
+
+#
+# Qnx build file for kernel HAL layer.
+#
+
+################################################################################
+# Include common definitions.
+
+include $(AQROOT)/makefile.linux.def
+
+################################################################################
+# Define a shortcut for the main target.
+
+#ifeq ($(STATIC_LINK),1)
+    STATIC = 1
+#else
+    DYNAMIC = 1
+#endif
+PROGRAM := 1
+
+#ifeq ($(STATIC), 1)
+    TARGET_NAME = galcore.a
+#else
+    TARGET_NAME = galcore
+#endif
+
+################################################################################
+# Installation directory
+INSTALL_DIR := $(SDK_DIR)/drivers
+
+################################################################################
+# Supply additional include directories.
+
+INCLUDE += -I$(AQROOT)/hal/inc
+INCLUDE += -I$(AQROOT)/hal/user
+INCLUDE += -I$(AQROOT)/hal/kernel
+INCLUDE += -I$(AQARCH)/hal/kernel
+INCLUDE += -I$(AQARCH)/hal/kernel
+CFLAGS += $(INCLUDE)
+CFLAGS += -fPIC
+
+################################################################################
+# Supply necessary libraries.
+
+# Specify Vivante library paths.
+LIBS += -L $(AQARCH)/hal/kernel/$(OBJ_DIR)
+LIBS += -L $(AQROOT)/hal/kernel/$(OBJ_DIR)
+LIBS += -l halarchkernel -l halkernel 
+
+################################################################################
+# Describe object files.
+
+OBJECTS = \
+          $(OBJ_DIR)/gc_hal_kernel_driver.o \
+          $(OBJ_DIR)/gc_hal_kernel_os.o \
+          $(OBJ_DIR)/gc_hal_kernel_qnx.o \
+          $(OBJ_DIR)/gc_hal_kernel_device.o \
+          $(OBJ_DIR)/gc_hal_kernel_debug.o \
+
+include $(AQROOT)/common.target
+
+
diff --git a/drivers/staging/rk29/vivante/hal/os/qnx/makefile.linux b/drivers/staging/rk29/vivante/hal/os/qnx/makefile.linux
new file mode 100644 (file)
index 0000000..0c0cd88
--- /dev/null
@@ -0,0 +1,40 @@
+##############################################################################
+#  
+#    Copyright (c) 2005 - 2010 by Vivante Corp.  All rights reserved.
+#  
+#    The material in this file is confidential and contains trade secrets
+#    of Vivante Corporation. This is proprietary information owned by
+#    Vivante Corporation. No part of this work may be disclosed, 
+#    reproduced, copied, transmitted, or used in any way for any purpose, 
+#    without the express written permission of Vivante Corporation.
+#  
+##############################################################################
+#  
+#    Auto-generated file on 10/12/2010. Do not edit!!!
+#  
+##############################################################################
+
+
+#
+# QNX build file for the kernel level HAL libraries.
+#
+
+################################################################################
+# Define make command.
+MAKE = make --makefile=makefile.linux
+
+
+################################################################################
+# Define build directories.
+
+HAL_KERNEL_DRV_ARCH    := $(AQARCH)/hal/kernel
+HAL_KERNEL_DRV_OS      := $(AQROOT)/hal/os/qnx/kernel
+HAL_KERNEL_DRV_MAIN    := $(AQROOT)/hal/kernel
+
+$(HAL_KERNEL_DRV_OS): $(HAL_KERNEL_DRV_ARCH) $(HAL_KERNEL_DRV_MAIN)
+
+MODULES        := $(HAL_KERNEL_DRV_ARCH) $(HAL_KERNEL_DRV_OS) $(HAL_KERNEL_DRV_MAIN)
+MAIN_MODULE    = $(HAL_KERNEL_DRV_OS)
+
+include $(AQROOT)/common.node
+
diff --git a/drivers/staging/rk29/vivante/hal/user/gc_hal_user_context.h b/drivers/staging/rk29/vivante/hal/user/gc_hal_user_context.h
new file mode 100644 (file)
index 0000000..d2c805e
--- /dev/null
@@ -0,0 +1,170 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2010 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_context_h_
+#define __gc_hal_user_context_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* gcoCONTEXT structure that hold the current context. */
+struct _gcoCONTEXT
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gcoOS object. */
+    gcoOS                       os;
+
+    /* Pointer to gcoHARDWARE object. */
+    gcoHARDWARE                 hardware;
+
+    /* Context ID. */
+    gctUINT64                   id;
+
+    /* State mapping. */
+    gctUINT32_PTR               map;
+    gctSIZE_T                   stateCount;
+
+    /* State hinting. */
+    gctUINT8_PTR                hint;
+    gctUINT8                    hintValue;
+    gctSIZE_T                   hintCount;
+
+    /* Context buffer. */
+    gctUINT32_PTR               buffer;
+    gctUINT32                   pipe3DIndex;
+    gctUINT32                   pipe2DIndex;
+    gctUINT32                   linkIndex;
+    gctUINT32                   inUseIndex;
+    gctSIZE_T                   bufferSize;
+
+    /* Context buffer used for commitment. */
+    gctSIZE_T                   bytes;
+    gctPHYS_ADDR                physical;
+    gctPOINTER                  logical;
+
+    /* Pointer to final LINK command. */
+    gctPOINTER                  link;
+
+    /* Requested pipe select for context. */
+    gctUINT32                   initialPipe;
+    gctUINT32                   entryPipe;
+    gctUINT32                   currentPipe;
+
+    /* Flag to specify whether PostCommit needs to be called. */
+    gctBOOL                     postCommit;
+
+    /* Busy flag. */
+    volatile gctBOOL *          inUse;
+
+    /* Variables used for building state buffer. */
+    gctUINT32                   lastAddress;
+    gctSIZE_T                   lastSize;
+    gctUINT32                   lastIndex;
+    gctBOOL                     lastFixed;
+
+    /* Hint array. */
+    gctUINT32_PTR               hintArray;
+    gctUINT32_PTR               hintIndex;
+};
+
+struct _gcoCMDBUF
+{
+    /* The object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gcoOS object. */
+    gcoOS                       os;
+
+    /* Pointer to gcoHARDWARE object. */
+    gcoHARDWARE                 hardware;
+
+    /* 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;
+
+#if gcdSECURE_USER
+    /* Table of offsets that define the physical addresses to be mapped. */
+    gctUINT32_PTR               hintTable;
+
+    /* Current index into map table. */
+    gctUINT32_PTR               hintIndex;
+
+    /* Commit index for map table. */
+    gctUINT32_PTR               hintCommit;
+#endif
+};
+
+typedef struct _gcsQUEUE * gcsQUEUE_PTR;
+
+typedef struct _gcsQUEUE
+{
+    /* Pointer to next gcsQUEUE structure. */
+    gcsQUEUE_PTR                next;
+
+#ifdef __QNXNTO__
+    /* Size of this object. */
+    gctSIZE_T                   bytes;
+#endif
+
+    /* Event information. */
+    gcsHAL_INTERFACE            iface;
+}
+gcsQUEUE;
+
+/* Event queue. */
+struct _gcoQUEUE
+{
+    /* The object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to gcoOS object. */
+    gcoOS                       os;
+
+    /* Pointer to current event queue. */
+    gcsQUEUE_PTR                head;
+    gcsQUEUE_PTR                tail;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_user_context_h_ */
+