]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
gpu: vivante: Update driver from Freescale 3.10.53-1.1-ga BSP
authorLothar Waßmann <LW@KARO-electronics.de>
Tue, 3 Feb 2015 12:45:41 +0000 (13:45 +0100)
committerLothar Waßmann <LW@KARO-electronics.de>
Tue, 3 Feb 2015 12:45:41 +0000 (13:45 +0100)
73 files changed:
drivers/mxc/gpu-viv/Kbuild
drivers/mxc/gpu-viv/config
drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.c [moved from drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c with 60% similarity]
drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.h [moved from drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.h with 83% similarity]
drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c [moved from drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c with 77% similarity]
drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h [moved from drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h with 74% similarity]
drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_recorder.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.c [moved from drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.c with 99% similarity]
drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.h [moved from drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.h with 97% similarity]
drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.c [moved from drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c with 97% similarity]
drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.h [moved from drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h with 98% similarity]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h [deleted file]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_security_interface.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h
drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_array.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_iommu.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_probe.c [moved from drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c with 62% similarity]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h
drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c [new file with mode: 0644]
drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config [new file with mode: 0644]

index 2b277d6f4ee75701e5464f6c1d19afb8f2635c9f..c39444cdd1b98cddd44d2c9d13bb67b38bb7e23f 100644 (file)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-#    Copyright (C) 2005 - 2013 by Vivante Corp.
+#    Copyright (C) 2005 - 2014 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
 #
 
 AQROOT := $(srctree)/drivers/mxc/gpu-viv
-AQARCH := $(AQROOT)/arch/XAQ2
-AQVGARCH := $(AQROOT)/arch/GC350
 
 include $(AQROOT)/config
 
 KERNEL_DIR ?= $(TOOL_DIR)/kernel
 
 OS_KERNEL_DIR   := hal/os/linux/kernel
-ARCH_KERNEL_DIR := arch/$(notdir $(AQARCH))/hal/kernel
-ARCH_VG_KERNEL_DIR := arch/$(notdir $(AQVGARCH))/hal/kernel
+ARCH_KERNEL_DIR := hal/kernel/arch
+ARCH_VG_KERNEL_DIR := hal/kernel/archvg
 HAL_KERNEL_DIR  := hal/kernel
 
+# Check and include platform config.
+ifneq ($(PLATFORM),)
+
+# Get platform config path.
+PLATFORM_CONFIG ?= $(AQROOT)/$(OS_KERNEL_DIR)/platform/$(PLATFORM).config
+
+# Check whether it exists.
+PLATFORM_CONFIG := $(wildcard $(PLATFORM_CONFIG))
+
+# Include it if exists.
+ifneq ($(PLATFORM_CONFIG),)
+include $(PLATFORM_CONFIG)
+endif
+
+endif
+
+MODULE_NAME ?= galcore
+CUSTOMER_ALLOCATOR_OBJS    ?=
+ALLOCATOR_ARRAY_H_LOCATION ?= $(OS_KERNEL_DIR)/allocator/default/
+
 EXTRA_CFLAGS += -Werror
 
 OBJS := $(OS_KERNEL_DIR)/gc_hal_kernel_device.o \
-        $(OS_KERNEL_DIR)/gc_hal_kernel_driver.o \
         $(OS_KERNEL_DIR)/gc_hal_kernel_linux.o \
         $(OS_KERNEL_DIR)/gc_hal_kernel_math.o \
         $(OS_KERNEL_DIR)/gc_hal_kernel_os.o \
-        $(OS_KERNEL_DIR)/gc_hal_kernel_debugfs.o
+        $(OS_KERNEL_DIR)/gc_hal_kernel_debugfs.o \
+        $(OS_KERNEL_DIR)/gc_hal_kernel_allocator.o \
+
+ifneq ($(CONFIG_IOMMU_SUPPORT),)
+OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_iommu.o
+endif
+
+ifneq ($(PLATFORM),)
+OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_probe.o
+OBJS += $(OS_KERNEL_DIR)/platform/$(PLATFORM).o
+else
+OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_driver.o
+endif
 
 OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
         $(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
@@ -58,6 +87,10 @@ OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
 OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_context.o \
         $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o
 
+ifeq ($(VIVANTE_ENABLE_3D), 1)
+OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_recorder.o
+endif
+
 ifeq ($(VIVANTE_ENABLE_VG), 1)
 OBJS +=\
           $(HAL_KERNEL_DIR)/gc_hal_kernel_vg.o\
@@ -69,9 +102,20 @@ OBJS +=\
 endif
 
 ifneq ($(CONFIG_SYNC),)
+EXTRA_CFLAGS += -Idrivers/staging/android
+
 OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_sync.o
 endif
 
+ifeq ($(SECURITY), 1)
+OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_security_channel.o \
+        $(HAL_KERNEL_DIR)/gc_hal_kernel_security.o
+endif
+
+ifneq ($(CUSTOMER_ALLOCATOR_OBJS),)
+OBJS += $(CUSTOMER_ALLOCATOR_OBJS)
+endif
+
 ifeq ($(KERNELRELEASE), )
 
 .PHONY: all clean install
@@ -93,12 +137,6 @@ 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
@@ -123,15 +161,9 @@ else
 EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=0
 endif
 
-
 EXTRA_CFLAGS += -DVIVANTE_PROFILER=1
 EXTRA_CFLAGS += -DVIVANTE_PROFILER_CONTEXT=1
 
-
-ifeq ($(ANDROID), 1)
-EXTRA_CFLAGS += -DANDROID=1
-endif
-
 ifeq ($(ENABLE_GPU_CLOCK_BY_DRIVER), 1)
 EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=1
 else
@@ -144,12 +176,6 @@ else
 EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=0
 endif
 
-ifeq ($(NO_USER_DIRECT_ACCESS_FROM_KERNEL), 1)
-EXTRA_CFLAGS += -DNO_USER_DIRECT_ACCESS_FROM_KERNEL=1
-else
-EXTRA_CFLAGS += -DNO_USER_DIRECT_ACCESS_FROM_KERNEL=0
-endif
-
 ifeq ($(FORCE_ALL_VIDEO_MEMORY_CACHED), 1)
 EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=1
 else
@@ -174,26 +200,28 @@ else
 EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=0
 endif
 
-ifeq ($(SUPPORT_SWAP_RECTANGLE), 1)
-EXTRA_CFLAGS += -DgcdSUPPORT_SWAP_RECTANGLE=1
+ifeq ($(CONFIG_SMP), y)
+EXTRA_CFLAGS += -DgcdSMP=1
 else
-EXTRA_CFLAGS += -DgcdSUPPORT_SWAP_RECTANGLE=0
+EXTRA_CFLAGS += -DgcdSMP=0
 endif
 
-ifeq ($(VIVANTE_ENABLE_VG), 1)
-EXTRA_CFLAGS += -DgcdENABLE_VG=1
+ifeq ($(VIVANTE_ENABLE_3D),0)
+EXTRA_CFLAGS += -DgcdENABLE_3D=0
 else
-EXTRA_CFLAGS += -DgcdENABLE_VG=0
+EXTRA_CFLAGS += -DgcdENABLE_3D=1
 endif
 
-ifeq ($(CONFIG_SMP), y)
-EXTRA_CFLAGS += -DgcdSMP=1
+ifeq ($(VIVANTE_ENABLE_2D),0)
+EXTRA_CFLAGS += -DgcdENABLE_2D=0
 else
-EXTRA_CFLAGS += -DgcdSMP=0
+EXTRA_CFLAGS += -DgcdENABLE_2D=1
 endif
 
-ifeq ($(VIVANTE_NO_3D),1)
-EXTRA_CFLAGS += -DVIVANTE_NO_3D
+ifeq ($(VIVANTE_ENABLE_VG),0)
+EXTRA_CFLAGS += -DgcdENABLE_VG=0
+else
+EXTRA_CFLAGS += -DgcdENABLE_VG=1
 endif
 
 ifeq ($(ENABLE_OUTER_CACHE_PATCH), 1)
@@ -216,17 +244,25 @@ ifeq ($(USE_BANK_ALIGNMENT), 1)
     endif
 endif
 
-ifneq ($(CONFIG_SYNC),)
-EXTRA_CFLAGS += -DgcdANDROID_NATIVE_FENCE_SYNC=1
+ifeq ($(gcdFPGA_BUILD), 1)
+EXTRA_CFLAGS += -DgcdFPGA_BUILD=1
+else
+EXTRA_CFLAGS += -DgcdFPGA_BUILD=0
+endif
+
+ifeq ($(SECURITY), 1)
+EXTRA_CFLAGS += -DgcdSECURITY=1
 endif
 
 EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc
 EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
-EXTRA_CFLAGS += -I$(AQARCH)/hal/kernel
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/arch
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc
 EXTRA_CFLAGS += -I$(AQROOT)/hal/os/linux/kernel
+EXTRA_CFLAGS += -I$(AQROOT)/$(ALLOCATOR_ARRAY_H_LOCATION)
 
 ifeq ($(VIVANTE_ENABLE_VG), 1)
-EXTRA_CFLAGS += -I$(AQVGARCH)/hal/kernel
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/archvg
 endif
 
 obj-$(CONFIG_MXC_GPU_VIV) += galcore.o
index cdd143e03e5133a996541aa4fecad6b4d264861b..94841414a07ac28516d442571fbe3baf84d9596c 100644 (file)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-#    Copyright (C) 2005 - 2013 by Vivante Corp.
+#    Copyright (C) 2005 - 2014 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
 
 ARCH_TYPE                         ?= arm
 SDK_DIR                           ?= $(AQROOT)/build/sdk
-USE_3D_VG                         ?= 1
+VIVANTE_ENABLE_3D                 ?= 1
+VIVANTE_ENABLE_2D                 ?= 1
+VIVANTE_ENABLE_VG              ?= 1
 FORCE_ALL_VIDEO_MEMORY_CACHED     ?= 0
 NONPAGED_MEMORY_CACHEABLE         ?= 0
 NONPAGED_MEMORY_BUFFERABLE        ?= 1
 CACHE_FUNCTION_UNIMPLEMENTED      ?= 0
-VIVANTE_ENABLE_VG                 ?= 1
-NO_USER_DIRECT_ACCESS_FROM_KERNEL ?= 1
-VIVANTE_NO_3D                     ?= 0
 ENABLE_OUTER_CACHE_PATCH          ?= 1
 USE_BANK_ALIGNMENT                ?= 1
 BANK_BIT_START                    ?= 13
 BANK_BIT_END                      ?= 15
 BANK_CHANNEL_BIT                  ?= 12
-ENABLE_GPU_CLOCK_BY_DRIVER        = 1
-
+PLATFORM                          ?= freescale/gc_hal_kernel_platform_imx6q14
similarity index 60%
rename from drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c
rename to drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.c
index e277a21a6097dda703709e53da559c20477775f2..08644a7cf5e52e7ac12b556413eb3fd9a55383cc 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
         gcvFALSE, gcvTRUE                                                      \
         )
 
+#define _STATE_COUNT_OFFSET_HINT(reg, offset, count)                           \
+    _State(\
+        Context, index, \
+        (reg ## _Address >> 2) + offset, \
+        reg ## _ResetValue, \
+        count, \
+        gcvFALSE, gcvTRUE                                                      \
+        )
+
 #define _STATE_X(reg)                                                          \
     _State(\
         Context, index, \
         gcvTRUE, gcvFALSE                                                      \
         )
 
+#define _STATE_INIT_VALUE(reg, value)                                          \
+    _State(\
+        Context, index, \
+        reg ## _Address >> 2, \
+        value, \
+        reg ## _Count, \
+        gcvFALSE, gcvFALSE                                                     \
+        )
+
 #define _CLOSE_RANGE()                                                         \
     _TerminateStateBlock(Context, index)
 
 #define gcdSTATE_MASK \
     (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 | 0xC0FFEE & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))))
 
-#if !defined(VIVANTE_NO_3D)
-static gctSIZE_T
+#if gcdENABLE_3D
+static gctUINT32
 _TerminateStateBlock(
     IN gckCONTEXT Context,
-    IN gctSIZE_T Index
+    IN gctUINT32 Index
     )
 {
     gctUINT32_PTR buffer;
-    gctSIZE_T align;
+    gctUINT32 align;
 
     /* Determine if we need alignment. */
     align = (Index & 1) ? 1 : 0;
@@ -156,13 +174,37 @@ _TerminateStateBlock(
 #endif
 
 
-static gctSIZE_T
+#if (gcdENABLE_3D || gcdENABLE_2D)
+static gctUINT32
 _FlushPipe(
     IN gckCONTEXT Context,
-    IN gctSIZE_T Index,
+    IN gctUINT32 Index,
     IN gcePIPE_SELECT Pipe
     )
 {
+    gctBOOL fcFlushStall;
+    gctUINT32 flushSlots;
+    gctBOOL iCacheInvalidate;
+
+    fcFlushStall
+        = gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_FC_FLUSH_STALL);
+
+    iCacheInvalidate
+        = ((((gctUINT32) (Context->hardware->identity.chipMinorFeatures3)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))));
+
+    flushSlots = 6;
+
+    if (fcFlushStall)
+    {
+        /* Flush tile status cache. */
+        flushSlots += 6;
+    }
+
+    if (iCacheInvalidate)
+    {
+        flushSlots += 12;
+    }
+
     if (Context->buffer != gcvNULL)
     {
         gctUINT32_PTR buffer;
@@ -182,7 +224,7 @@ _FlushPipe(
                 :   ((((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 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+                  | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 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)));
 
         /* Semaphore from FE to PE. */
         *buffer++
@@ -198,20 +240,106 @@ _FlushPipe(
         *buffer++
             = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
 
-        *buffer
+        *buffer++
             = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
             | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+        if (fcFlushStall)
+        {
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0594) & ((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++
+                = ((((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)));
+
+            /* Semaphore from FE to PE. */
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+            /* Stall from FE to PE. */
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+        }
+
+        if (iCacheInvalidate)
+        {
+            /* Invalidate I$ after pipe is stalled */
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0218) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x021A) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 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 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0218) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 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)));
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x021A) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 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 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+
+            /* Semaphore from FE to PE. */
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+            /* Stall from FE to PE. */
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+        }
     }
 
-    /* Flushing 3D pipe takes 6 slots. */
-    return 6;
+    /* Number of slots taken by flushing pipe. */
+    return flushSlots;
 }
+#endif
 
-#if !defined(VIVANTE_NO_3D)
-static gctSIZE_T
+#if gcdENABLE_3D
+static gctUINT32
 _SemaphoreStall(
     IN gckCONTEXT Context,
-    IN gctSIZE_T Index
+    IN gctUINT32 Index
     )
 {
     if (Context->buffer != gcvNULL)
@@ -245,13 +373,16 @@ _SemaphoreStall(
 }
 #endif
 
-static gctSIZE_T
+#if (gcdENABLE_3D || gcdENABLE_2D)
+static gctUINT32
 _SwitchPipe(
     IN gckCONTEXT Context,
-    IN gctSIZE_T Index,
+    IN gctUINT32 Index,
     IN gcePIPE_SELECT Pipe
     )
 {
+    gctUINT32 slots = 6;
+
     if (Context->buffer != gcvNULL)
     {
         gctUINT32_PTR buffer;
@@ -265,29 +396,51 @@ _SwitchPipe(
             | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
             | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
 
-        *buffer
+        *buffer++
             = (Pipe == gcvPIPE_2D)
                 ? 0x1
                 : 0x0;
+
+        /* Semaphore from FE to PE. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+        /* Stall from FE to PE. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
     }
 
-    return 2;
+    Context->pipeSelectBytes = slots * gcmSIZEOF(gctUINT32);
+
+    return slots;
 }
+#endif
 
-#if !defined(VIVANTE_NO_3D)
-static gctSIZE_T
+#if gcdENABLE_3D
+static gctUINT32
 _State(
     IN gckCONTEXT Context,
-    IN gctSIZE_T Index,
+    IN gctUINT32 Index,
     IN gctUINT32 Address,
     IN gctUINT32 Value,
-    IN gctSIZE_T Size,
+    IN gctUINT32 Size,
     IN gctBOOL FixedPoint,
     IN gctBOOL Hinted
     )
 {
     gctUINT32_PTR buffer;
-    gctSIZE_T align, i;
+    gctUINT32 align;
+    gctUINT32 i;
 
     /* Determine if we need alignment. */
     align = (Index & 1) ? 1 : 0;
@@ -335,13 +488,13 @@ _State(
             }
 
             /* Walk all the states. */
-            for (i = 0; i < Size; i += 1)
+            for (i = 0; i < (gctUINT32)Size; i += 1)
             {
                 /* Set state to uninitialized value. */
                 buffer[Index + 1 + i] = Value;
 
                 /* Set index in state mapping table. */
-                Context->map[Address + i].index = Index + 1 + i;
+                Context->map[Address + i].index = (gctUINT)Index + 1 + i;
 
 #if gcdSECURE_USER
                 /* Save hint. */
@@ -354,8 +507,8 @@ _State(
         }
 
         /* Save information for this LoadState. */
-        Context->lastIndex   = Index;
-        Context->lastAddress = Address + Size;
+        Context->lastIndex   = (gctUINT)Index;
+        Context->lastAddress = Address + (gctUINT32)Size;
         Context->lastSize    = Size;
         Context->lastFixed   = FixedPoint;
 
@@ -371,13 +524,13 @@ _State(
             ((((gctUINT32) (buffer[Context->lastIndex])) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Context->lastSize + Size) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
 
         /* Walk all the states. */
-        for (i = 0; i < Size; i += 1)
+        for (i = 0; i < (gctUINT32)Size; i += 1)
         {
             /* Set state to uninitialized value. */
             buffer[Index + i] = Value;
 
             /* Set index in state mapping table. */
-            Context->map[Address + i].index = Index + i;
+            Context->map[Address + i].index = (gctUINT)Index + i;
 
 #if gcdSECURE_USER
             /* Save hint. */
@@ -390,22 +543,22 @@ _State(
     }
 
     /* Update last address and size. */
-    Context->lastAddress += Size;
+    Context->lastAddress += (gctUINT32)Size;
     Context->lastSize    += Size;
 
     /* Return number of slots required. */
     return Size;
 }
 
-static gctSIZE_T
+static gctUINT32
 _StateMirror(
     IN gckCONTEXT Context,
     IN gctUINT32 Address,
-    IN gctSIZE_T Size,
+    IN gctUINT32 Size,
     IN gctUINT32 AddressMirror
     )
 {
-    gctSIZE_T i;
+    gctUINT32 i;
 
     /* Process when buffer is set. */
     if (Context->buffer != gcvNULL)
@@ -424,19 +577,21 @@ _StateMirror(
 }
 #endif
 
+#if (gcdENABLE_3D || gcdENABLE_2D)
 static gceSTATUS
 _InitializeContextBuffer(
     IN gckCONTEXT Context
     )
 {
     gctUINT32_PTR buffer;
-    gctSIZE_T index;
+    gctUINT32 index;
 
-#if !defined(VIVANTE_NO_3D)
+#if gcdENABLE_3D
+    gctBOOL halti0, halti1, halti2, halti3;
     gctUINT i;
-    gctUINT vertexUniforms, fragmentUniforms;
+    gctUINT vertexUniforms, fragmentUniforms, vsConstBase, psConstBase, constMax;
+    gctBOOL unifiedUniform;
     gctUINT fe2vsCount;
-    gctBOOL halti0;
 #endif
 
     /* Reset the buffer index. */
@@ -455,20 +610,31 @@ _InitializeContextBuffer(
     /* Build 2D states. *******************************************************/
 
 
-#if !defined(VIVANTE_NO_3D)
+#if gcdENABLE_3D
     /**************************************************************************/
     /* Build 3D states. *******************************************************/
+
     halti0 = (((((gctUINT32) (Context->hardware->identity.chipMinorFeatures1)) >> (0 ? 23:23)) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1)))))) );
+    halti1 = (((((gctUINT32) (Context->hardware->identity.chipMinorFeatures2)) >> (0 ? 11:11)) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1)))))) );
+    halti2 = (((((gctUINT32) (Context->hardware->identity.chipMinorFeatures4)) >> (0 ? 16:16)) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) );
+    halti3 = (((((gctUINT32) (Context->hardware->identity.chipMinorFeatures5)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) );
 
-    /* Query shader support. */
-    gcmkVERIFY_OK(gckHARDWARE_QueryShaderCaps(
-        Context->hardware, &vertexUniforms, &fragmentUniforms, gcvNULL));
+    /* Query how many uniforms can support for non-unified uniform mode. */
+    {if (Context->hardware->identity.numConstants > 256){    unifiedUniform = gcvTRUE;    vsConstBase  = 0xC000;    psConstBase  = 0xC000;    constMax     = Context->hardware->identity.numConstants;    vertexUniforms   = 256;    fragmentUniforms   = constMax - vertexUniforms;}else if (Context->hardware->identity.numConstants == 256){    if (Context->hardware->identity.chipModel == gcv2000 && Context->hardware->identity.chipRevision == 0x5118)    {        unifiedUniform = gcvFALSE;        vsConstBase  = 0x1400;        psConstBase  = 0x1C00;        vertexUniforms   = 256;        fragmentUniforms   = 64;        constMax     = 320;    }    else    {        unifiedUniform = gcvFALSE;        vsConstBase  = 0x1400;        psConstBase  = 0x1C00;        vertexUniforms   = 256;        fragmentUniforms   = 256;        constMax     = 512;    }}else{    unifiedUniform = gcvFALSE;    vsConstBase  = 0x1400;    psConstBase  = 0x1C00;    vertexUniforms   = 168;    fragmentUniforms   = 64;    constMax     = 232;}};
 
-    /* Store the 3D entry index. */
-    Context->entryOffset3D = index * gcmSIZEOF(gctUINT32);
+#if !gcdENABLE_UNIFIED_CONSTANT
+    if (Context->hardware->identity.numConstants > 256)
+    {
+        unifiedUniform = gcvTRUE;
+    }
+    else
+    {
+        unifiedUniform = gcvFALSE;
+    }
+#endif
 
-    /* Flush 2D pipe. */
-    index += _FlushPipe(Context, index, gcvPIPE_2D);
+    /* Store the 3D entry index. */
+    Context->entryOffset3D = (gctUINT)index * gcmSIZEOF(gctUINT32);
 
     /* Switch to 3D pipe. */
     index += _SwitchPipe(Context, index, gcvPIPE_3D);
@@ -489,14 +655,15 @@ _InitializeContextBuffer(
     index += _State(Context, index, 0x0382C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x03834 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x03838 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x03854 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x0384C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
 
     /* Front End states. */
-       fe2vsCount = 12;
-       if ((((((gctUINT32) (Context->hardware->identity.chipMinorFeatures1)) >> (0 ? 23:23)) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1)))))) ))
-       {
-               fe2vsCount = 16;
-       }
+    fe2vsCount = 12;
+    if (halti0)
+    {
+        fe2vsCount = 16;
+    }
     index += _State(Context, index, 0x00600 >> 2, 0x00000000, fe2vsCount, gcvFALSE, gcvFALSE);
     index += _CLOSE_RANGE();
 
@@ -506,6 +673,7 @@ _InitializeContextBuffer(
     index += _State(Context, index, 0x00650 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00680 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
     index += _State(Context, index, 0x006A0 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00674 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00670 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00678 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x0067C >> 2, 0xFFFFFFFF, 1, gcvFALSE, gcvFALSE);
@@ -514,22 +682,44 @@ _InitializeContextBuffer(
     index += _State(Context, index, 0x00740 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00780 >> 2, 0x3F800000, 16, gcvFALSE, gcvFALSE);
 
+    if (halti2)
+    {
+        index += _State(Context, index, 0x14600 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x14640 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x14680 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+    }
+
+    /* This register is programed by all chips, which program all DECODE_SELECT as VS
+    ** except SAMPLER_DECODE_SELECT.
+    */
+    index += _State(Context, index, 0x00860 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    if (((((gctUINT32) (Context->hardware->identity.chipMinorFeatures3)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))))
+    {
+        /* I-Cache states. */
+        index += _State(Context, index, 0x00868 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x0086C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x0304C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x01028 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+        index += _CLOSE_RANGE();
+
+        if (halti3)
+        {
+            index += _State(Context, index, 0x00890 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+            index += _State(Context, index, 0x0104C >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+            index += _CLOSE_RANGE();
+        }
+    }
+
     /* Vertex Shader states. */
-    index += _State(Context, index, 0x00800 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00804 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00808 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x0080C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00810 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00820 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00830 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
-    index += _State(Context, index, 0x00838 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
-    if (Context->hardware->identity.instructionCount <= 256)
-    {
-        index += _State(Context, index, 0x04000 >> 2, 0x00000000, 1024, gcvFALSE, gcvFALSE);
-    }
 
     index += _CLOSE_RANGE();
-    index += _State(Context, index, 0x05000 >> 2, 0x00000000, vertexUniforms * 4, gcvFALSE, gcvFALSE);
 
     /* Primitive Assembly states. */
     index += _State(Context, index, 0x00A00 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
@@ -543,14 +733,20 @@ _InitializeContextBuffer(
     index += _State(Context, index, 0x00A28 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00A2C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00A30 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
-    index += _State(Context, index, 0x00A40 >> 2, 0x00000000, 10, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00A40 >> 2, 0x00000000, Context->hardware->identity.varyingsCount, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00A34 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00A38 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00A3C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00A80 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00A84 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
     index += _State(Context, index, 0x00A8C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00A88 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
 
+#if gcdMULTI_GPU
+    index += _State(Context, index, 0x03A00 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x03A04 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x03A08 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+#endif
     /* Setup states. */
     index += _State(Context, index, 0x00C00 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
     index += _State(Context, index, 0x00C04 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
@@ -569,21 +765,22 @@ _InitializeContextBuffer(
     index += _State(Context, index, 0x00E04 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00E40 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00E08 >> 2, 0x00000031, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00E24 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x00E20 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    if (halti2)
+    {
+        index += _State(Context, index, 0x00E0C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    }
 
     /* Pixel Shader states. */
-    index += _State(Context, index, 0x01000 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x01004 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x01008 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x0100C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x01010 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
-    index += _State(Context, index, 0x01018 >> 2, 0x01000000, 1, gcvFALSE, gcvFALSE);
-    if (Context->hardware->identity.instructionCount <= 256)
-    {
-        index += _State(Context, index, 0x06000 >> 2, 0x00000000, 1024, gcvFALSE, gcvFALSE);
-    }
+    index += _State(Context, index, 0x01030 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
 
     index += _CLOSE_RANGE();
-    index += _State(Context, index, 0x07000 >> 2, 0x00000000, fragmentUniforms * 4, gcvFALSE, gcvFALSE);
 
     /* Texture states. */
     index += _State(Context, index, 0x02000 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
@@ -612,21 +809,38 @@ _InitializeContextBuffer(
     index += _State(Context, index, (0x02740 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
     index += _CLOSE_RANGE();
 
-    if ((((((gctUINT32) (Context->hardware->identity.chipMinorFeatures2)) >> (0 ? 11:11)) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1)))))) ))
+    if ((((((gctUINT32) (Context->hardware->identity.chipMinorFeatures1)) >> (0 ? 22:22)) & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1)))))) ))
+    {
+        /*
+         * Linear stride LODn will overwrite LOD0 on GC880,GC2000.
+         * And only LOD0 is valid for this register.
+         */
+        gctUINT count = halti1 ? 14 : 1;
+
+        for (i = 0; i < 12; i += 1)
+        {
+            index += _State(Context, index, (0x02C00 >> 2) + i * 16, 0x00000000, count, gcvFALSE, gcvFALSE);
+        }
+    }
+
+    if (halti1)
     {
         gctUINT texBlockCount;
+        gctUINT gcregTXLogSizeResetValue;
+
+        /* Enable the integer filter pipe for all texture samplers
+           so that the floating point filter clock will shut off until
+           we start using the floating point filter.
+        */
+        gcregTXLogSizeResetValue = ((((gctUINT32) (0x00000000)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 29:29) - (0 ? 29:29) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 29:29) - (0 ? 29:29) + 1))))))) << (0 ? 29:29))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 29:29) - (0 ? 29:29) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 29:29) - (0 ? 29:29) + 1))))))) << (0 ? 29:29)));
 
         /* New texture block. */
         index += _State(Context, index, 0x10000 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
         index += _State(Context, index, 0x10080 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
-        index += _State(Context, index, 0x10100 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10100 >> 2, gcregTXLogSizeResetValue, 32, gcvFALSE, gcvFALSE);
         index += _State(Context, index, 0x10180 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
         index += _State(Context, index, 0x10200 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
         index += _State(Context, index, 0x10280 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
-        for (i = 0; i < 256 / 16; i += 1)
-        {
-            index += _State(Context, index, (0x02C00 >> 2) + i * 16, 0x00000000, 14, gcvFALSE, gcvFALSE);
-        }
         index += _State(Context, index, 0x10300 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
         index += _State(Context, index, 0x10380 >> 2, 0x00321000, 32, gcvFALSE, gcvFALSE);
         index += _State(Context, index, 0x10400 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
@@ -638,21 +852,33 @@ _InitializeContextBuffer(
             index += _State(Context, index, 0x12400 >> 2, 0x00000000, 256, gcvFALSE, gcvFALSE);
         }
 
-        if ((Context->hardware->identity.chipModel == gcv2000)
-         && (Context->hardware->identity.chipRevision == 0x5108))
-        {
-            texBlockCount = 12;
-        }
-        else
-        {
-            texBlockCount = ((512) >> (4));
-        }
+        texBlockCount = ((512) >> (4));
+
         for (i = 0; i < texBlockCount; i += 1)
         {
             index += _State(Context, index, (0x10800 >> 2) + (i << 4), 0x00000000, 14, gcvFALSE, gcvTRUE);
         }
     }
 
+    if (halti2)
+    {
+        index += _State(Context, index, 0x10700 >> 2, 0x00000F00, 32, gcvFALSE, gcvFALSE);
+    }
+
+    if (halti3)
+    {
+        index += _State(Context, index, 0x10780 >> 2, 0x00030000, 32, gcvFALSE, gcvFALSE);
+    }
+
+    /* ASTC */
+    if ((((((gctUINT32) (Context->hardware->identity.chipMinorFeatures4)) >> (0 ? 13:13)) & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1)))))) ))
+    {
+        index += _State(Context, index, 0x10500 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10580 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10600 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x10680 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+    }
+
     /* YUV. */
     index += _State(Context, index, 0x01678 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x0167C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
@@ -676,47 +902,117 @@ _InitializeContextBuffer(
     index += _State(Context, index, 0x00918 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x0091C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x00924 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    if (((((gctUINT32) (Context->hardware->identity.chipMinorFeatures3)) >> (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))))))))
+    {
+        index += _State(Context, index, 0x00940 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x00944 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x00948 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x0094C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x00950 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x00954 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    }
+
     index += _CLOSE_RANGE();
 
-       if (Context->hardware->identity.instructionCount > 1024)
-       {
-               /* New Shader instruction memory. */
-               index += _State(Context, index, 0x0085C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
-               index += _State(Context, index, 0x0101C >> 2, 0x00000100, 1, gcvFALSE, gcvFALSE);
-               index += _State(Context, index, 0x00860 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
-               index += _CLOSE_RANGE();
-
-               for (i = 0;
-                    i < Context->hardware->identity.instructionCount << 2;
-                    i += 256 << 2
-                    )
-               {
-                       index += _State(Context, index, (0x20000 >> 2) + i, 0x00000000, 256 << 2, gcvFALSE, gcvFALSE);
-                       index += _CLOSE_RANGE();
-               }
-       }
-       else if (Context->hardware->identity.instructionCount > 256)
-       {
-               /* New Shader instruction memory. */
-               index += _State(Context, index, 0x0085C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
-               index += _State(Context, index, 0x0101C >> 2, 0x00000100, 1, gcvFALSE, gcvFALSE);
-               index += _CLOSE_RANGE();
-
-               /* VX instruction memory. */
-               for (i = 0;
-                    i < Context->hardware->identity.instructionCount << 2;
-                    i += 256 << 2
-                    )
-               {
-                       index += _State(Context, index, (0x0C000 >> 2) + i, 0x00000000, 256 << 2, gcvFALSE, gcvFALSE);
-                       index += _CLOSE_RANGE();
-               }
-
-               _StateMirror(Context, 0x08000 >> 2, Context->hardware->identity.instructionCount << 2 , 0x0C000 >> 2);
-       }
+    if (!halti3)
+    {
+        if (Context->hardware->identity.instructionCount > 1024)
+        {
+            /* New Shader instruction PC registers. */
+            index += _State(Context, index, 0x0085C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+            index += _State(Context, index, 0x0101C >> 2, 0x00000100, 1, gcvFALSE, gcvFALSE);
+            index += _CLOSE_RANGE();
+
+            for (i = 0;
+                 i < Context->hardware->identity.instructionCount << 2;
+                 i += 256 << 2
+                 )
+            {
+                index += _State(Context, index, (0x20000 >> 2) + i, 0x00000000, 256 << 2, gcvFALSE, gcvFALSE);
+                index += _CLOSE_RANGE();
+            }
+        }
+        else if (Context->hardware->identity.instructionCount > 256)
+        {
+            /* New Shader instruction PC registers. */
+            index += _State(Context, index, 0x0085C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+            index += _State(Context, index, 0x0101C >> 2, 0x00000100, 1, gcvFALSE, gcvFALSE);
+            index += _CLOSE_RANGE();
+
+            /* VX instruction memory. */
+            for (i = 0;
+                 i < Context->hardware->identity.instructionCount << 2;
+                 i += 256 << 2
+                 )
+            {
+                index += _State(Context, index, (0x0C000 >> 2) + i, 0x00000000, 256 << 2, gcvFALSE, gcvFALSE);
+                index += _CLOSE_RANGE();
+            }
+
+            _StateMirror(Context, 0x08000 >> 2, Context->hardware->identity.instructionCount << 2 , 0x0C000 >> 2);
+        }
+        else /* if (Context->hardware->identity.instructionCount <= 256) */
+        {
+            /* old shader instruction PC registers */
+            index += _State(Context, index, 0x00800 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+            index += _State(Context, index, 0x00838 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+            index += _CLOSE_RANGE();
+
+            index += _State(Context, index, 0x01000 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+            index += _State(Context, index, 0x01018 >> 2, 0x01000000, 1, gcvFALSE, gcvFALSE);
+            index += _CLOSE_RANGE();
+
+            index += _State(Context, index, 0x04000 >> 2, 0x00000000, 1024, gcvFALSE, gcvFALSE);
+            index += _CLOSE_RANGE();
+            index += _State(Context, index, 0x06000 >> 2, 0x00000000, 1024, gcvFALSE, gcvFALSE);
+            index += _CLOSE_RANGE();
+        }
+    }
+    /* I cache use the new instruction PC registers */
+    else
+    {
+        /* New Shader instruction PC registers. */
+        index += _State(Context, index, 0x0085C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x0101C >> 2, 0x00000100, 1, gcvFALSE, gcvFALSE);
+        index += _CLOSE_RANGE();
+    }
+
+    if (unifiedUniform)
+    {
+        gctINT numConstants = Context->hardware->identity.numConstants;
+
+        index += _State(Context, index, 0x01024 >> 2, 0x00000100, 1, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x00864 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+        index += _CLOSE_RANGE();
+
+        for (i = 0;
+             numConstants > 0;
+             i += 256 << 2,
+             numConstants -= 256
+             )
+        {
+            if (numConstants >= 256)
+            {
+                index += _State(Context, index, (0x30000 >> 2) + i, 0x00000000, 256 << 2, gcvFALSE, gcvFALSE);
+            }
+            else
+            {
+                index += _State(Context, index, (0x30000 >> 2) + i, 0x00000000, numConstants << 2, gcvFALSE, gcvFALSE);
+            }
+            index += _CLOSE_RANGE();
+        }
+    }
+#if gcdENABLE_UNIFIED_CONSTANT
+    else
+#endif
+    {
+        index += _State(Context, index, 0x05000 >> 2, 0x00000000, vertexUniforms * 4, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x07000 >> 2, 0x00000000, fragmentUniforms * 4, gcvFALSE, gcvFALSE);
+    }
 
     /* Store the index of the "XD" entry. */
-    Context->entryOffsetXDFrom3D = index * gcmSIZEOF(gctUINT32);
+    Context->entryOffsetXDFrom3D = (gctUINT)index * gcmSIZEOF(gctUINT32);
 
 
     /* Pixel Engine states. */
@@ -757,16 +1053,31 @@ _InitializeContextBuffer(
     else
     {
         index += _State(Context, index, (0x01460 >> 2) + (0 << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
+    }
+
+    if (Context->hardware->identity.pixelPipes > 1 || halti0)
+    {
+        index += _State(Context, index, (0x01480 >> 2) + (0 << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
+    }
+
+    for (i = 0; i < 3; i++)
+    {
+        index += _State(Context, index, (0x01500 >> 2) + (i << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
+    }
 
-        for (i = 0; i < 2; i++)
+    if (halti2)
+    {
+        for (i = 0; i < 7; i++)
         {
-            index += _State(Context, index, (0x01500 >> 2) + (i << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
+          index += _State(Context, index, (0x14800 >> 2) + (i << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
         }
+        index += _State(Context, index, 0x14900 >> 2, 0x00000000, 7, gcvFALSE, gcvFALSE);
     }
 
-    if (Context->hardware->identity.pixelPipes > 1 || halti0)
+
+    if (halti3)
     {
-        index += _State(Context, index, (0x01480 >> 2) + (0 << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
+        index += _State(Context, index, 0x014BC >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     }
 
     /* Resolve states. */
@@ -783,7 +1094,7 @@ _InitializeContextBuffer(
     index += _State(Context, index, 0x016B4 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
     index += _CLOSE_RANGE();
 
-    if (Context->hardware->identity.pixelPipes > 1)
+    if ((Context->hardware->identity.pixelPipes > 1) || halti1)
     {
         index += _State(Context, index, (0x016C0 >> 2) + (0 << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
 
@@ -792,6 +1103,49 @@ _InitializeContextBuffer(
         index += _State(Context, index, 0x01700 >> 2, 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvFALSE);
     }
 
+#if gcd3DBLIT
+    index += _State(Context, index, (0x14000 >> 2) + (0 << 1), 0x00000000, 2, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x14008 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x1400C >> 2, 0x0001C800, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14010 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x14014 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, (0x14018 >> 2) + (0 << 1), 0x00000000, 2, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x14020 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+    index += _State(Context, index, 0x14024 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14028 >> 2, 0x0001C800, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x1402C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14030 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14034 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14038 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x1403C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14040 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14044 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14048 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x1404C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14050 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14058 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x1405C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14054 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14100 >> 2, 0x00000000, 64, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14200 >> 2, 0x00000000, 64, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14064 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14068 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    index += _State(Context, index, 0x1406C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14070 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14074 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14078 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x1407C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14080 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14084 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14088 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x1408C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14090 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+    index += _State(Context, index, 0x14094 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+    index += _State(Context, index, 0x14098 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+#endif
+
     /* Tile status. */
     index += _State(Context, index, 0x01654 >> 2, 0x00200000, 1, gcvFALSE, gcvFALSE);
 
@@ -810,8 +1164,34 @@ _InitializeContextBuffer(
     index += _State(Context, index, 0x01720 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
     index += _State(Context, index, 0x01740 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
     index += _State(Context, index, 0x01760 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+
+
+    if (halti2)
+    {
+        index += _State(Context, index, 0x01780 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, 0x016BC >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, (0x017A0 >> 2) + 1, 0x00000000, 7, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, (0x017C0 >> 2) + 1, 0x00000000, 7, gcvFALSE, gcvTRUE);
+        index += _State(Context, index, (0x017E0 >> 2) + 1, 0x00000000, 7, gcvFALSE, gcvTRUE);
+        index += _State(Context, index, (0x01A00 >> 2) + 1, 0x00000000, 7, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, (0x01A20 >> 2) + 1, 0x00000000, 7, gcvFALSE, gcvFALSE);
+        index += _State(Context, index, (0x01A40 >> 2) + 1, 0x00000000, 7, gcvFALSE, gcvFALSE);
+    }
+
     index += _CLOSE_RANGE();
 
+    if(((((gctUINT32) (Context->hardware->identity.chipMinorFeatures4)) >> (0 ? 25:25) & ((gctUINT32) ((((1 ? 25:25) - (0 ? 25:25) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:25) - (0 ? 25:25) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 25:25) - (0 ? 25:25) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:25) - (0 ? 25:25) + 1))))))))
+    {
+        index += _State(Context, index, 0x03860 >> 2, 0x6, 1, gcvFALSE, gcvFALSE);
+        index += _CLOSE_RANGE();
+    }
+
+    if (halti3)
+    {
+        index += _State(Context, index, 0x01A80 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
+        index += _CLOSE_RANGE();
+    }
+
     /* Semaphore/stall. */
     index += _SemaphoreStall(Context, index);
 #endif
@@ -819,7 +1199,7 @@ _InitializeContextBuffer(
     /**************************************************************************/
     /* Link to another address. ***********************************************/
 
-    Context->linkIndex3D = index;
+    Context->linkIndex3D = (gctUINT)index;
 
     if (buffer != gcvNULL)
     {
@@ -841,7 +1221,7 @@ _InitializeContextBuffer(
     /* Pipe switch for the case where neither 2D nor 3D are used. *************/
 
     /* Store the 3D entry index. */
-    Context->entryOffsetXDFrom2D = index * gcmSIZEOF(gctUINT32);
+    Context->entryOffsetXDFrom2D = (gctUINT)index * gcmSIZEOF(gctUINT32);
 
     /* Flush 2D pipe. */
     index += _FlushPipe(Context, index, gcvPIPE_2D);
@@ -850,7 +1230,7 @@ _InitializeContextBuffer(
     index += _SwitchPipe(Context, index, gcvPIPE_3D);
 
     /* Store the location of the link. */
-    Context->linkIndexXD = index;
+    Context->linkIndexXD = (gctUINT)index;
 
     if (buffer != gcvNULL)
     {
@@ -874,6 +1254,7 @@ _InitializeContextBuffer(
     /* Success. */
     return gcvSTATUS_OK;
 }
+#endif
 
 static gceSTATUS
 _DestroyContext(
@@ -914,24 +1295,26 @@ _DestroyContext(
             /* Free state delta map. */
             if (buffer->logical != gcvNULL)
             {
-#if gcdVIRTUAL_COMMAND_BUFFER
-                gcmkONERROR(gckEVENT_DestroyVirtualCommandBuffer(
-                    Context->hardware->kernel->eventObj,
-                    Context->totalSize,
-                    buffer->physical,
-                    buffer->logical,
-                    gcvKERNEL_PIXEL
-                    ));
-
-#else
-                gcmkONERROR(gckEVENT_FreeContiguousMemory(
-                    Context->hardware->kernel->eventObj,
-                    Context->totalSize,
-                    buffer->physical,
-                    buffer->logical,
-                    gcvKERNEL_PIXEL
-                    ));
-#endif
+                if (Context->hardware->kernel->virtualCommandBuffer)
+                {
+                    gcmkONERROR(gckEVENT_DestroyVirtualCommandBuffer(
+                        Context->hardware->kernel->eventObj,
+                        Context->totalSize,
+                        buffer->physical,
+                        buffer->logical,
+                        gcvKERNEL_PIXEL
+                        ));
+                }
+                else
+                {
+                    gcmkONERROR(gckEVENT_FreeContiguousMemory(
+                        Context->hardware->kernel->eventObj,
+                        Context->totalSize,
+                        buffer->physical,
+                        buffer->logical,
+                        gcvKERNEL_PIXEL
+                        ));
+                }
 
                 buffer->logical = gcvNULL;
             }
@@ -951,10 +1334,27 @@ _DestroyContext(
         }
 #endif
         /* Free record array copy. */
+#if REMOVE_DUPLICATED_COPY_FROM_USER
+        if (Context->recordArrayMap != gcvNULL)
+        {
+            gcsRECORD_ARRAY_MAP_PTR map = Context->recordArrayMap;
+
+            do
+            {
+                /* Free record array. */
+                gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, map->kData));
+                map = map->next;
+            }
+            while (map != Context->recordArrayMap);
+
+            gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->recordArrayMap));
+        }
+#else
         if (Context->recordArray != gcvNULL)
         {
             gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->recordArray));
         }
+#endif
 
         /* Free the state mapping. */
         if (Context->map != gcvNULL)
@@ -1001,6 +1401,7 @@ OnError:
 **          Pointer to a variable thet will receive the gckCONTEXT object
 **          pointer.
 */
+#if (gcdENABLE_3D || gcdENABLE_2D)
 gceSTATUS
 gckCONTEXT_Construct(
     IN gckOS Os,
@@ -1011,9 +1412,10 @@ gckCONTEXT_Construct(
 {
     gceSTATUS status;
     gckCONTEXT context = gcvNULL;
-    gctSIZE_T allocationSize;
+    gctUINT32 allocationSize;
     gctUINT i;
     gctPOINTER pointer = gcvNULL;
+    gctUINT32 address;
 
     gcmkHEADER_ARG("Os=0x%08X Hardware=0x%08X", Os, Hardware);
 
@@ -1044,7 +1446,7 @@ gckCONTEXT_Construct(
     context->hardware    = Hardware;
 
 
-#if defined(VIVANTE_NO_3D)
+#if !gcdENABLE_3D
     context->entryPipe = gcvPIPE_2D;
     context->exitPipe  = gcvPIPE_2D;
 #elif gcdCMD_NO_2D_CONTEXT
@@ -1081,7 +1483,7 @@ gckCONTEXT_Construct(
     /* Compute the size of the record array. **********************************/
 
     context->recordArraySize
-        = gcmSIZEOF(gcsSTATE_DELTA_RECORD) * context->stateCount;
+        = gcmSIZEOF(gcsSTATE_DELTA_RECORD) * (gctUINT)context->stateCount;
 
 
     if (context->stateCount > 0)
@@ -1127,6 +1529,8 @@ gckCONTEXT_Construct(
         /* Allocate a context buffer. */
         gcsCONTEXT_PTR buffer;
 
+        gctSIZE_T totalSize = context->totalSize;
+
         /* Allocate the context buffer structure. */
         gcmkONERROR(gckOS_Allocate(
             Os,
@@ -1169,26 +1573,43 @@ gckCONTEXT_Construct(
             ));
 
         /* Create a new physical context buffer. */
-#if gcdVIRTUAL_COMMAND_BUFFER
-        gcmkONERROR(gckKERNEL_AllocateVirtualCommandBuffer(
-            context->hardware->kernel,
-            gcvFALSE,
-            &context->totalSize,
-            &buffer->physical,
-            &pointer
-            ));
+        if (context->hardware->kernel->virtualCommandBuffer)
+        {
+            gcmkONERROR(gckKERNEL_AllocateVirtualCommandBuffer(
+                context->hardware->kernel,
+                gcvFALSE,
+                &totalSize,
+                &buffer->physical,
+                &pointer
+                ));
 
-#else
-        gcmkONERROR(gckOS_AllocateContiguous(
-            Os,
-            gcvFALSE,
-            &context->totalSize,
-            &buffer->physical,
-            &pointer
-            ));
-#endif
+            gcmkONERROR(gckKERNEL_GetGPUAddress(
+                context->hardware->kernel,
+                pointer,
+                gcvFALSE,
+                &address
+                ));
+        }
+        else
+        {
+            gcmkONERROR(gckOS_AllocateContiguous(
+                Os,
+                gcvFALSE,
+                &totalSize,
+                &buffer->physical,
+                &pointer
+                ));
+
+            gcmkONERROR(gckHARDWARE_ConvertLogical(
+                context->hardware,
+                pointer,
+                gcvFALSE,
+                &address
+                ));
+        }
 
         buffer->logical = pointer;
+        buffer->address = address;
 
         /* Set gckEVENT object pointer. */
         buffer->eventObj = Hardware->kernel->eventObj;
@@ -1207,16 +1628,16 @@ gckCONTEXT_Construct(
         if (context->linkIndexXD != 0)
         {
             gctPOINTER xdLink;
-            gctUINT8_PTR xdEntryLogical;
-            gctSIZE_T xdEntrySize;
-            gctSIZE_T linkBytes;
+            gctUINT32 xdEntryAddress;
+            gctUINT32 xdEntrySize;
+            gctUINT32 linkBytes;
 
             /* Determine LINK parameters. */
             xdLink
                 = &buffer->logical[context->linkIndexXD];
 
-            xdEntryLogical
-                = (gctUINT8_PTR) buffer->logical
+            xdEntryAddress
+                = buffer->address
                 + context->entryOffsetXDFrom3D;
 
             xdEntrySize
@@ -1225,14 +1646,14 @@ gckCONTEXT_Construct(
 
             /* Query LINK size. */
             gcmkONERROR(gckHARDWARE_Link(
-                Hardware, gcvNULL, gcvNULL, 0, &linkBytes
+                Hardware, gcvNULL, 0, 0, &linkBytes
                 ));
 
             /* Generate a LINK. */
             gcmkONERROR(gckHARDWARE_Link(
                 Hardware,
                 xdLink,
-                xdEntryLogical,
+                xdEntryAddress,
                 xdEntrySize,
                 &linkBytes
                 ));
@@ -1291,6 +1712,7 @@ OnError:
     gcmkFOOTER();
     return status;
 }
+#endif
 
 /******************************************************************************\
 **
@@ -1355,7 +1777,7 @@ gckCONTEXT_Update(
     IN gcsSTATE_DELTA_PTR StateDelta
     )
 {
-#ifndef VIVANTE_NO_3D
+#if gcdENABLE_3D
     gceSTATUS status = gcvSTATUS_OK;
     gcsSTATE_DELTA _stateDelta;
     gckKERNEL kernel;
@@ -1367,6 +1789,9 @@ gckCONTEXT_Update(
     gcsSTATE_DELTA_PTR kDelta = gcvNULL;
     gcsSTATE_DELTA_RECORD_PTR record;
     gcsSTATE_DELTA_RECORD_PTR recordArray = gcvNULL;
+#if REMOVE_DUPLICATED_COPY_FROM_USER
+    gcsRECORD_ARRAY_MAP_PTR recordArrayMap = gcvNULL;
+#endif
     gctUINT elementCount;
     gctUINT address;
     gctUINT32 mask;
@@ -1393,6 +1818,36 @@ gckCONTEXT_Update(
     gcmkONERROR(gckOS_QueryNeedCopy(Context->os, ProcessID, &needCopy));
 
     /* Allocate the copy buffer for the user record array. */
+#if REMOVE_DUPLICATED_COPY_FROM_USER
+    if (needCopy && (Context->recordArrayMap == gcvNULL))
+    {
+        /* Allocate enough maps. */
+        gcmkONERROR(gckOS_Allocate(
+            Context->os,
+            gcmSIZEOF(gcsRECORD_ARRAY_MAP_PTR) * gcdCONTEXT_BUFFER_COUNT,
+            (gctPOINTER *) &Context->recordArrayMap
+            ));
+
+        for (i = 0; i < gcdCONTEXT_BUFFER_COUNT; i++)
+        {
+            /* Next mapping id. */
+            gctUINT n = (i + 1) % gcdCONTEXT_BUFFER_COUNT;
+
+            recordArrayMap = &Context->recordArrayMap[i];
+
+            /* Allocate the buffer. */
+            gcmkONERROR(gckOS_Allocate(
+                Context->os,
+                Context->recordArraySize,
+                (gctPOINTER *) &recordArrayMap->kData
+                ));
+
+            /* Initialize fields. */
+            recordArrayMap->key  = 0;
+            recordArrayMap->next = &Context->recordArrayMap[n];
+        }
+    }
+#else
     if (needCopy && (Context->recordArray == gcvNULL))
     {
         /* Allocate the buffer. */
@@ -1402,6 +1857,7 @@ gckCONTEXT_Update(
             (gctPOINTER *) &Context->recordArray
             ));
     }
+#endif
 
     /* Get the current context buffer. */
     buffer = Context->buffer;
@@ -1417,10 +1873,10 @@ gckCONTEXT_Update(
     gcmkONERROR(gckKERNEL_GetProcessDBCache(kernel, ProcessID, &cache));
 #endif
 
-#if gcmIS_DEBUG(gcdDEBUG_CODE) && 1 && !defined(VIVANTE_NO_3D)
+#if gcmIS_DEBUG(gcdDEBUG_CODE) && 1 && gcdENABLE_3D
     /* Update current context token. */
     buffer->logical[Context->map[0x0E14].index]
-        = gcmPTR2INT(Context);
+        = (gctUINT32)gcmPTR2INT32(Context);
 #endif
 
     /* Are there any pending deltas? */
@@ -1446,6 +1902,58 @@ gckCONTEXT_Update(
                 (gctPOINTER *) &kDelta
                 ));
 
+#if REMOVE_DUPLICATED_COPY_FROM_USER
+            if (needCopy)
+            {
+                recordArray    = gcvNULL;
+                recordArrayMap = Context->recordArrayMap;
+
+                do
+                {
+                    /* Check if recordArray is alreay opened. */
+                    if (recordArrayMap->key == kDelta->recordArray)
+                    {
+                        /* Found. */
+                        recordArray = recordArrayMap->kData;
+                        break;
+                    }
+
+                    recordArrayMap = recordArrayMap->next;
+                }
+                while (recordArrayMap != Context->recordArrayMap);
+
+                if (recordArray == gcvNULL)
+                {
+                    while (recordArrayMap->key != 0)
+                    {
+                        /* Found an empty slot. */
+                        recordArrayMap = recordArrayMap->next;
+                    }
+
+                    /* Get access to the state records. */
+                    gcmkONERROR(gckOS_CopyFromUserData(
+                        kernel->os,
+                        recordArrayMap->kData,
+                        gcmUINT64_TO_PTR(kDelta->recordArray),
+                        Context->recordArraySize
+                        ));
+
+                    /* Save user pointer as key. */
+                    recordArrayMap->key = kDelta->recordArray;
+                    recordArray         = recordArrayMap->kData;
+                }
+            }
+            else
+            {
+                /* Get access to the state records. */
+                gcmkONERROR(gckOS_MapUserPointer(
+                    kernel->os,
+                    gcmUINT64_TO_PTR(kDelta->recordArray),
+                    Context->recordArraySize,
+                    (gctPOINTER *) &recordArray
+                    ));
+            }
+#else
             /* Get access to the state records. */
             gcmkONERROR(gckKERNEL_OpenUserData(
                 kernel, needCopy,
@@ -1453,6 +1961,7 @@ gckCONTEXT_Update(
                 gcmUINT64_TO_PTR(kDelta->recordArray), Context->recordArraySize,
                 (gctPOINTER *) &recordArray
                 ));
+#endif
 
             /* Merge all pending states. */
             for (j = 0; j < kDelta->recordCount; j += 1)
@@ -1487,22 +1996,6 @@ gckCONTEXT_Update(
                 /* Skip the state if not mapped. */
                 if (index == 0)
                 {
-#if gcdDEBUG
-                    if ((address != 0x0594)
-                     && (address != 0x0E00)
-                     && (address != 0x0E03)
-                        )
-                    {
-#endif
-                        gcmkTRACE(
-                            gcvLEVEL_ERROR,
-                            "%s(%d): State 0x%04X is not mapped.\n",
-                            __FUNCTION__, __LINE__,
-                            address
-                            );
-#if gcdDEBUG
-                    }
-#endif
                     continue;
                 }
 
@@ -1561,6 +2054,28 @@ gckCONTEXT_Update(
             /* Get the next state delta. */
             nDelta = gcmUINT64_TO_PTR(kDelta->next);
 
+#if REMOVE_DUPLICATED_COPY_FROM_USER
+            if (needCopy)
+            {
+                if (kDelta->refCount == 0)
+                {
+                    /* No other reference, reset the mapping. */
+                    recordArrayMap->key = 0;
+                }
+            }
+            else
+            {
+                /* Close access to the state records. */
+                gcmkONERROR(gckOS_UnmapUserPointer(
+                    kernel->os,
+                    gcmUINT64_TO_PTR(kDelta->recordArray),
+                    Context->recordArraySize,
+                    (gctPOINTER *) recordArray
+                    ));
+
+                recordArray = gcvNULL;
+            }
+#else
             /* Get access to the state records. */
             gcmkONERROR(gckKERNEL_CloseUserData(
                 kernel, needCopy,
@@ -1568,6 +2083,7 @@ gckCONTEXT_Update(
                 gcmUINT64_TO_PTR(kDelta->recordArray), Context->recordArraySize,
                 (gctPOINTER *) &recordArray
                 ));
+#endif
 
             /* Close access to the current state delta. */
             gcmkONERROR(gckKERNEL_CloseUserData(
@@ -1678,10 +2194,10 @@ gckCONTEXT_Update(
         /* Get the next context buffer. */
         buffer = buffer->next;
 
-               if (buffer == gcvNULL)
-               {
-                       gcmkONERROR(gcvSTATUS_NOT_FOUND);
-               }
+        if (buffer == gcvNULL)
+        {
+            gcmkONERROR(gcvSTATUS_NOT_FOUND);
+        }
     }
     while (Context->buffer != buffer);
 
@@ -1707,15 +2223,15 @@ gckCONTEXT_Update(
 
 OnError:
     /* Get access to the state records. */
-       if (kDelta != gcvNULL)
-       {
+    if (kDelta != gcvNULL)
+    {
         gcmkVERIFY_OK(gckKERNEL_CloseUserData(
             kernel, needCopy,
             gcvFALSE,
             gcmUINT64_TO_PTR(kDelta->recordArray), Context->recordArraySize,
             (gctPOINTER *) &recordArray
             ));
-       }
+    }
 
     /* Close access to the current state delta. */
     gcmkVERIFY_OK(gckKERNEL_CloseUserData(
@@ -1733,3 +2249,69 @@ OnError:
 #endif
 }
 
+gceSTATUS
+gckCONTEXT_MapBuffer(
+    IN gckCONTEXT Context,
+    OUT gctUINT32 *Physicals,
+    OUT gctUINT64 *Logicals,
+    OUT gctUINT32 *Bytes
+    )
+{
+    gceSTATUS status;
+    int i = 0;
+    gctSIZE_T pageCount;
+    gckVIRTUAL_COMMAND_BUFFER_PTR commandBuffer;
+    gckKERNEL kernel = Context->hardware->kernel;
+    gctPOINTER logical;
+    gctPHYS_ADDR physical;
+
+    gcsCONTEXT_PTR buffer;
+
+    gcmkHEADER();
+
+    gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
+
+    buffer = Context->buffer;
+
+    for (i = 0; i < gcdCONTEXT_BUFFER_COUNT; i++)
+    {
+        if (kernel->virtualCommandBuffer)
+        {
+            commandBuffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)buffer->physical;
+            physical = commandBuffer->physical;
+
+            gcmkONERROR(gckOS_CreateUserVirtualMapping(
+                kernel->os,
+                physical,
+                Context->totalSize,
+                &logical,
+                &pageCount));
+        }
+        else
+        {
+            physical = buffer->physical;
+
+            gcmkONERROR(gckOS_MapMemory(
+                kernel->os,
+                physical,
+                Context->totalSize,
+                &logical));
+        }
+
+        Physicals[i] = gcmPTR_TO_NAME(physical);
+
+        Logicals[i] = gcmPTR_TO_UINT64(logical);
+
+        buffer = buffer->next;
+    }
+
+    *Bytes = (gctUINT)Context->totalSize;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
similarity index 83%
rename from drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.h
rename to drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.h
index 5d2c7c77ee9083c4bb0923adbdb878695e67ac99..29e6a5321e0da00e1cac1adefb640bf8b35092c4 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -24,6 +24,9 @@
 
 #include "gc_hal_kernel_buffer.h"
 
+/* Exprimental optimization. */
+#define REMOVE_DUPLICATED_COPY_FROM_USER 1
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -61,6 +64,9 @@ typedef struct _gcsCONTEXT
     /* Logical address of the context buffer. */
     gctUINT32_PTR               logical;
 
+    /* Hardware address of the context buffer. */
+    gctUINT32                   address;
+
     /* Pointer to the LINK commands. */
     gctPOINTER                  link2D;
     gctPOINTER                  link3D;
@@ -76,6 +82,20 @@ typedef struct _gcsCONTEXT
 }
 gcsCONTEXT;
 
+typedef struct _gcsRECORD_ARRAY_MAP * gcsRECORD_ARRAY_MAP_PTR;
+struct  _gcsRECORD_ARRAY_MAP
+{
+    /* User pointer key. */
+    gctUINT64                   key;
+
+    /* Kernel memory buffer. */
+    gcsSTATE_DELTA_RECORD_PTR   kData;
+
+    /* Next map. */
+    gcsRECORD_ARRAY_MAP_PTR     next;
+
+};
+
 /* gckCONTEXT structure that hold the current context. */
 struct _gckCONTEXT
 {
@@ -89,14 +109,14 @@ struct _gckCONTEXT
     gckHARDWARE                 hardware;
 
     /* Command buffer alignment. */
-    gctSIZE_T                   alignment;
-    gctSIZE_T                   reservedHead;
-    gctSIZE_T                   reservedTail;
+    gctUINT32                   alignment;
+    gctUINT32                   reservedHead;
+    gctUINT32                   reservedTail;
 
     /* Context buffer metrics. */
     gctSIZE_T                   stateCount;
-    gctSIZE_T                   totalSize;
-    gctSIZE_T                   bufferSize;
+    gctUINT32                   totalSize;
+    gctUINT32                   bufferSize;
     gctUINT32                   linkIndex2D;
     gctUINT32                   linkIndex3D;
     gctUINT32                   linkIndexXD;
@@ -118,7 +138,11 @@ struct _gckCONTEXT
 
     /* A copy of the user record array. */
     gctUINT                     recordArraySize;
+#if REMOVE_DUPLICATED_COPY_FROM_USER
+    gcsRECORD_ARRAY_MAP_PTR     recordArrayMap;
+#else
     gcsSTATE_DELTA_RECORD_PTR   recordArray;
+#endif
 
     /* Requested pipe select for context. */
     gcePIPE_SELECT              entryPipe;
@@ -130,6 +154,8 @@ struct _gckCONTEXT
     gctUINT32                   lastIndex;
     gctBOOL                     lastFixed;
 
+    gctUINT32                   pipeSelectBytes;
+
     /* Hint array. */
 #if gcdSECURE_USER
     gctBOOL_PTR                 hint;
similarity index 77%
rename from drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
rename to drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c
index e8ad2ea3e0318624140abafbc852ef640999127d..3a225a9a208db1e5ca94b58495714a339590e342 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 #include "gc_hal_kernel_context.h"
 #endif
 
+#define gcdDISABLE_FE_L2    1
+
 #define _GC_OBJ_ZONE    gcvZONE_HARDWARE
 
+#define gcmSEMAPHORESTALL(buffer) \
+        do \
+        { \
+            /* Arm the PE-FE Semaphore. */ \
+            *buffer++ \
+                = gcmSETFIELDVALUE(0, AQ_COMMAND_LOAD_STATE_COMMAND, OPCODE, LOAD_STATE) \
+                | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, COUNT, 1) \
+                | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, ADDRESS, 0x0E02); \
+            \
+            *buffer++ \
+                = gcmSETFIELDVALUE(0, AQ_SEMAPHORE, SOURCE, FRONT_END) \
+                | gcmSETFIELDVALUE(0, AQ_SEMAPHORE, DESTINATION, PIXEL_ENGINE);\
+            \
+            /* STALL FE until PE is done flushing. */ \
+            *buffer++ \
+                = gcmSETFIELDVALUE(0, STALL_COMMAND, OPCODE, STALL); \
+            \
+            *buffer++ \
+                = gcmSETFIELDVALUE(0, STALL_STALL, SOURCE, FRONT_END) \
+                | gcmSETFIELDVALUE(0, STALL_STALL, DESTINATION, PIXEL_ENGINE); \
+        } while(0)
+
 typedef struct _gcsiDEBUG_REGISTERS * gcsiDEBUG_REGISTERS_PTR;
 typedef struct _gcsiDEBUG_REGISTERS
 {
@@ -39,10 +63,20 @@ typedef struct _gcsiDEBUG_REGISTERS
 }
 gcsiDEBUG_REGISTERS;
 
-extern int gpu3DMinClock;
 /******************************************************************************\
 ********************************* Support Code *********************************
 \******************************************************************************/
+static gctBOOL
+_IsHardwareMatch(
+    IN gckHARDWARE Hardware,
+    IN gctINT32 ChipModel,
+    IN gctUINT32 ChipRevision
+    )
+{
+    return ((Hardware->identity.chipModel == ChipModel) &&
+            (Hardware->identity.chipRevision == ChipRevision));
+}
+
 static gceSTATUS
 _ResetGPU(
     IN gckHARDWARE Hardware,
@@ -72,7 +106,9 @@ _IdentifyHardware(
     gctUINT32 numConstants = 0;
     gctUINT32 bufferSize = 0;
     gctUINT32 varyingsCount = 0;
-    gctBOOL useHZ;
+#if gcdMULTI_GPU
+    gctUINT32 gpuCoreCount = 0;
+#endif
 
     gcmkHEADER_ARG("Os=0x%x", Os);
 
@@ -101,12 +137,9 @@ _IdentifyHardware(
                                  0x00020,
                                  (gctUINT32_PTR) &Identity->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 (((Identity->chipModel & 0xFF00) == 0x0400)
-          && (Identity->chipModel != 0x0420))
+          && (Identity->chipModel != 0x0420)
+          && (Identity->chipModel != 0x0428))
         {
             Identity->chipModel = (gceCHIPMODEL) (Identity->chipModel & 0x0400);
         }
@@ -141,6 +174,11 @@ _IdentifyHardware(
                 Identity->chipRevision = 0x1051;
             }
         }
+
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Os, Core,
+                                 0x000A8,
+                                 &Identity->productID));
     }
 
     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
@@ -162,7 +200,7 @@ _IdentifyHardware(
                              0x0001C,
                              &Identity->chipFeatures));
 
-#ifndef VIVANTE_NO_3D
+#if gcdENABLE_3D
     /* Disable fast clear on GC700. */
     if (Identity->chipModel == gcv700)
     {
@@ -181,6 +219,7 @@ _IdentifyHardware(
         Identity->chipMinorFeatures2 = 0;
         Identity->chipMinorFeatures3 = 0;
         Identity->chipMinorFeatures4 = 0;
+        Identity->chipMinorFeatures5 = 0;
     }
     else
     {
@@ -213,20 +252,18 @@ _IdentifyHardware(
                                      0x00088,
                                      &Identity->chipMinorFeatures3));
 
-            /*The BG2 chip has no compression supertiled, and the bit of GCMinorFeature3BugFixes15 is n/a*/
-            if(Identity->chipModel == gcv1000 && Identity->chipRevision == 0x5036)
-            {
-                Identity->chipMinorFeatures3
-                    = ((((gctUINT32) (Identity->chipMinorFeatures3)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
-                Identity->chipMinorFeatures3
-                    = ((((gctUINT32) (Identity->chipMinorFeatures3)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27)));
-            }
 
             /* Read chip minor featuress register #4. */
             gcmkONERROR(
                 gckOS_ReadRegisterEx(Os, Core,
                                      0x00094,
                                      &Identity->chipMinorFeatures4));
+
+            /* Read chip minor featuress register #5. */
+            gcmkONERROR(
+                gckOS_ReadRegisterEx(Os, Core,
+                                     0x000A0,
+                                     &Identity->chipMinorFeatures5));
         }
         else
         {
@@ -235,6 +272,7 @@ _IdentifyHardware(
             Identity->chipMinorFeatures2 = 0;
             Identity->chipMinorFeatures3 = 0;
             Identity->chipMinorFeatures4 = 0;
+            Identity->chipMinorFeatures5 = 0;
         }
     }
 
@@ -256,53 +294,17 @@ _IdentifyHardware(
     /* Exception for GC1000, revision 5035 &  GC800, revision 4612 */
     if (((Identity->chipModel == gcv1000) && ((Identity->chipRevision == 0x5035)
                                            || (Identity->chipRevision == 0x5036)
-                                           || (Identity->chipRevision == 0x5037)))
-        || ((Identity->chipModel == gcv800) && (Identity->chipRevision == 0x4612))
-     || ((Identity->chipModel == gcv860) && (Identity->chipRevision == 0x4647)))
+                                           || (Identity->chipRevision == 0x5037)
+                                           || (Identity->chipRevision == 0x5039)
+                                           || (Identity->chipRevision >= 0x5040)))
+    || ((Identity->chipModel == gcv800) && (Identity->chipRevision == 0x4612))
+    || ((Identity->chipModel == gcv600) && (Identity->chipRevision >= 0x4650))
+    || ((Identity->chipModel == gcv860) && (Identity->chipRevision == 0x4647))
+    || ((Identity->chipModel == gcv400) && (Identity->chipRevision >= 0x4633)))
     {
         Identity->superTileMode = 1;
     }
 
-    if (Identity->chipModel == gcv4000 && Identity->chipRevision == 0x5245)
-    {
-        useHZ = ((((gctUINT32) (Identity->chipMinorFeatures3)) >> (0 ? 26:26) & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))))
-             || ((((gctUINT32) (Identity->chipMinorFeatures3)) >> (0 ? 8:8) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))));
-    }
-    else
-    {
-        useHZ = gcvFALSE;
-    }
-
-    if (useHZ)
-    {
-        /* Disable EZ. */
-        Identity->chipFeatures
-            = ((((gctUINT32) (Identity->chipFeatures)) & ~(((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)));
-    }
-
-    /* Disable HZ when EZ is present for older chips. */
-    else if (!((((gctUINT32) (Identity->chipFeatures)) >> (0 ? 16:16) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))))
-    {
-        /* Disable HIERARCHICAL_Z. */
-        Identity->chipMinorFeatures
-            = ((((gctUINT32) (Identity->chipMinorFeatures)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27)));
-    }
-
-    /* Disable rectangle primitive when chip is gc880_5_1_0_rc6*/
-    if ((Identity->chipModel == gcv880) && (Identity->chipRevision == 0x5106))
-    {
-        /* Disable rectangle primitive. */
-        Identity->chipMinorFeatures2
-            = ((((gctUINT32) (Identity->chipMinorFeatures2)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
-    }
-
-    if ((Identity->chipModel == gcv800) && (Identity->chipRevision == 0x4605))
-    {
-        /* Correct feature bit: RTL does not have such feature. */
-        Identity->chipFeatures
-            = ((((gctUINT32) (Identity->chipFeatures)) & ~(((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)));
-    }
-
     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
                    "Identity: chipFeatures=0x%08X",
                    Identity->chipFeatures);
@@ -327,13 +329,17 @@ _IdentifyHardware(
                    "Identity: chipMinorFeatures4=0x%08X",
                    Identity->chipMinorFeatures4);
 
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                   "Identity: chipMinorFeatures5=0x%08X",
+                   Identity->chipMinorFeatures5);
+
     /***************************************************************************
     ** Get chip specs.
     */
 
     if (((((gctUINT32) (Identity->chipMinorFeatures)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))))
     {
-        gctUINT32 specs, specs2, specs3;
+        gctUINT32 specs, specs2, specs3, specs4;
 
         /* Read gcChipSpecs register. */
         gcmkONERROR(
@@ -342,7 +348,6 @@ _IdentifyHardware(
                                  &specs));
 
         /* 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)))))) );
@@ -367,6 +372,39 @@ _IdentifyHardware(
                                  &specs3));
 
         varyingsCount          = (((((gctUINT32) (specs3)) >> (0 ? 8:4)) & ((gctUINT32) ((((1 ? 8:4) - (0 ? 8:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:4) - (0 ? 8:4) + 1)))))) );
+#if gcdMULTI_GPU
+        gpuCoreCount           = (((((gctUINT32) (specs3)) >> (0 ? 2:0)) & ((gctUINT32) ((((1 ? 2:0) - (0 ? 2:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:0) - (0 ? 2:0) + 1)))))) );
+#endif
+
+        /* Read gcChipSpecs4 register. */
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Os, Core,
+                                 0x0009C,
+                                 &specs4));
+
+
+        streamCount            = (((((gctUINT32) (specs4)) >> (0 ? 16:12)) & ((gctUINT32) ((((1 ? 16:12) - (0 ? 16:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:12) - (0 ? 16:12) + 1)))))) );
+        if (streamCount == 0)
+        {
+            /* Extract stream count from older register. */
+            streamCount        = (((((gctUINT32) (specs)) >> (0 ? 3:0)) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1)))))) );
+        }
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "Identity: chipSpecs1=0x%08X",
+                       specs);
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "Identity: chipSpecs2=0x%08X",
+                       specs2);
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "Identity: chipSpecs3=0x%08X",
+                       specs3);
+
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "Identity: chipSpecs4=0x%08X",
+                       specs4);
     }
 
     /* Get the number of pixel pipes. */
@@ -456,11 +494,10 @@ _IdentifyHardware(
         {
             Identity->instructionCount = 512;
         }
-    }
-
-    if (((((gctUINT32) (Identity->chipMinorFeatures3)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))))
-    {
-        Identity->instructionCount = 512;
+        else if (((((gctUINT32) (Identity->chipMinorFeatures3)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))))
+        {
+            Identity->instructionCount = 512;
+        }
     }
 
     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
@@ -487,9 +524,7 @@ _IdentifyHardware(
 
      if (varyingsCount != 0)
      {
-         /* Bug 4480. */
-         /*Identity->varyingsCount = varyingsCount;*/
-         Identity->varyingsCount = 12;
+         Identity->varyingsCount = varyingsCount;
      }
      else if (((((gctUINT32) (Identity->chipMinorFeatures1)) >> (0 ? 23:23) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))))
      {
@@ -501,14 +536,57 @@ _IdentifyHardware(
      }
 
      /* For some cores, it consumes two varying for position, so the max varying vectors should minus one. */
-     if ((Identity->chipModel == gcv4000 && Identity->chipRevision == 0x5222) ||
+     if ((Identity->chipModel == gcv5000 && Identity->chipRevision == 0x5434) ||
+         (Identity->chipModel == gcv4000 && Identity->chipRevision == 0x5222) ||
          (Identity->chipModel == gcv4000 && Identity->chipRevision == 0x5208) ||
+         (Identity->chipModel == gcv4000 && Identity->chipRevision == 0x5245) ||
+         (Identity->chipModel == gcv3000 && Identity->chipRevision == 0x5435) ||
+         (Identity->chipModel == gcv2200 && Identity->chipRevision == 0x5244) ||
+         (Identity->chipModel == gcv1500 && Identity->chipRevision == 0x5246) ||
          ((Identity->chipModel == gcv2100 || Identity->chipModel == gcv2000) && Identity->chipRevision == 0x5108) ||
          (Identity->chipModel == gcv880 && (Identity->chipRevision == 0x5107 || Identity->chipRevision == 0x5106)))
      {
          Identity->varyingsCount -= 1;
      }
 
+    Identity->chip2DControl = 0;
+    if (Identity->chipModel == gcv320)
+    {
+        gctUINT32 data;
+
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Os,
+                                 Core,
+                                 0x0002C,
+                                 &data));
+
+        if ((data != 33956864) &&
+            ((Identity->chipRevision == 0x5007) ||
+            (Identity->chipRevision == 0x5220)))
+        {
+            Identity->chip2DControl |= 0xFF &
+                (Identity->chipRevision == 0x5220 ? 8 :
+                (Identity->chipRevision == 0x5007 ? 12 : 0));
+        }
+
+        if  (Identity->chipRevision == 0x5007)
+        {
+            /* Disable splitting rectangle. */
+            Identity->chip2DControl |= 0x100;
+
+            /* Enable 2D Flush. */
+            Identity->chip2DControl |= 0x200;
+        }
+    }
+
+#if gcdMULTI_GPU
+#if gcdMULTI_GPU > 1
+     Identity->gpuCoreCount = gpuCoreCount + 1;
+#else
+     Identity->gpuCoreCount = 1;
+#endif
+#endif
+
     /* Success. */
     gcmkFOOTER();
     return gcvSTATUS_OK;
@@ -519,6 +597,99 @@ OnError:
     return status;
 }
 
+#define gcdDEBUG_MODULE_CLOCK_GATING   0
+#define gcdDISABLE_MODULE_CLOCK_GATING 0
+#define gcdDISABLE_FE_CLOCK_GATING     0
+#define gcdDISABLE_PE_CLOCK_GATING     0
+#define gcdDISABLE_SH_CLOCK_GATING     0
+#define gcdDISABLE_PA_CLOCK_GATING     0
+#define gcdDISABLE_SE_CLOCK_GATING     0
+#define gcdDISABLE_RA_CLOCK_GATING     0
+#define gcdDISABLE_RA_EZ_CLOCK_GATING  0
+#define gcdDISABLE_RA_HZ_CLOCK_GATING  0
+#define gcdDISABLE_TX_CLOCK_GATING     0
+
+#if gcdDEBUG_MODULE_CLOCK_GATING
+gceSTATUS
+_ConfigureModuleLevelClockGating(
+    gckHARDWARE Hardware
+    )
+{
+    gctUINT32 data;
+
+    gcmkVERIFY_OK(
+        gckOS_ReadRegisterEx(Hardware->os,
+                             Hardware->core,
+                             Hardware->powerBaseAddress
+                             + 0x00104,
+                             &data));
+
+#if gcdDISABLE_FE_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)));
+#endif
+
+#if gcdDISABLE_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)));
+#endif
+
+#if gcdDISABLE_SH_CLOCK_GATING
+    data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)));
+#endif
+
+#if gcdDISABLE_PA_CLOCK_GATING
+    data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+#endif
+
+#if gcdDISABLE_SE_CLOCK_GATING
+    data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+#endif
+
+#if gcdDISABLE_RA_CLOCK_GATING
+    data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+#endif
+
+#if gcdDISABLE_TX_CLOCK_GATING
+    data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7)));
+#endif
+
+#if gcdDISABLE_RA_EZ_CLOCK_GATING
+    data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)));
+#endif
+
+#if gcdDISABLE_RA_HZ_CLOCK_GATING
+    data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17)));
+#endif
+
+    gcmkVERIFY_OK(
+        gckOS_WriteRegisterEx(Hardware->os,
+                              Hardware->core,
+                              Hardware->powerBaseAddress
+                              + 0x00104,
+                              data));
+
+#if gcdDISABLE_MODULE_CLOCK_GATING
+    gcmkVERIFY_OK(
+        gckOS_ReadRegisterEx(Hardware->os,
+                             Hardware->core,
+                             Hardware->powerBaseAddress +
+                             0x00100,
+                             &data));
+
+    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) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+
+    gcmkVERIFY_OK(
+        gckOS_WriteRegisterEx(Hardware->os,
+                              Hardware->core,
+                              Hardware->powerBaseAddress
+                              + 0x00100,
+                              data));
+#endif
+
+    return gcvSTATUS_OK;
+}
+#endif
+
 #if gcdPOWEROFF_TIMEOUT
 void
 _PowerTimerFunction(
@@ -689,7 +860,7 @@ _FlushCache(
     )
 {
     gceSTATUS status;
-    gctSIZE_T bytes, requested;
+    gctUINT32 bytes, requested;
     gctPOINTER buffer;
 
     /* Get the size of the flush command. */
@@ -718,6 +889,22 @@ OnError:
     return status;
 }
 
+gctBOOL
+_IsGPUIdle(
+    IN gctUINT32 Idle
+    )
+{
+   return  (((((gctUINT32) (Idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) )
+        && (((((gctUINT32) (Idle)) >> (0 ? 1:1)) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 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)))))) )
+        && (((((gctUINT32) (Idle)) >> (0 ? 4:4)) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1)))))) )
+        && (((((gctUINT32) (Idle)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) )
+        && (((((gctUINT32) (Idle)) >> (0 ? 6:6)) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1)))))) )
+        && (((((gctUINT32) (Idle)) >> (0 ? 7:7)) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1)))))) )
+        && (((((gctUINT32) (Idle)) >> (0 ? 2:2)) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) )
+        ;
+}
+
 /******************************************************************************\
 ****************************** gckHARDWARE API code *****************************
 \******************************************************************************/
@@ -752,8 +939,10 @@ gckHARDWARE_Construct(
     gceSTATUS status;
     gckHARDWARE hardware = gcvNULL;
     gctUINT16 data = 0xff00;
-    gctUINT32 axi_ot;
     gctPOINTER pointer = gcvNULL;
+#if gcdMULTI_GPU_AFFINITY
+    gctUINT32 control;
+#endif
 
     gcmkHEADER_ARG("Os=0x%x", Os);
 
@@ -791,26 +980,32 @@ gckHARDWARE_Construct(
         hardware->type = gcvHARDWARE_VG;
         break;
 
+    case gcv200:
     case gcv300:
     case gcv320:
+    case gcv328:
     case gcv420:
+    case gcv428:
         hardware->type = gcvHARDWARE_2D;
-        /*set outstanding limit*/
-        gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00414, &axi_ot));
-        axi_ot = (axi_ot & (~0xFF)) | 0x10;
-        gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00414, axi_ot));
         break;
 
     default:
+#if gcdMULTI_GPU_AFFINITY
+        hardware->type = (Core == gcvCORE_MAJOR) ? gcvHARDWARE_3D : gcvHARDWARE_OCL;
+#else
         hardware->type = gcvHARDWARE_3D;
-        if(hardware->identity.chipModel == gcv880)
+#endif
+
+        if(hardware->identity.chipModel == gcv880 && hardware->identity.chipRevision == 0x5107)
         {
             /*set outstanding limit*/
+            gctUINT32 axi_ot;
             gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00414, &axi_ot));
-            axi_ot = (axi_ot & (~0xFF)) | 0x10;
+            axi_ot = (axi_ot & (~0xFF)) | 0x00010;
             gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00414, axi_ot));
         }
 
+
         if ((((((gctUINT32) (hardware->identity.chipFeatures)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) ))
         {
             hardware->type = (gceHARDWARE_TYPE) (hardware->type | gcvHARDWARE_2D);
@@ -832,6 +1027,25 @@ gckHARDWARE_Construct(
             "_ResetGPU failed: status=%d\n", status);
     }
 
+#if gcdMULTI_GPU
+    gcmkONERROR(gckOS_WriteRegisterEx(Os,
+                                      Core,
+                                      0x0055C,
+#if gcdDISABLE_FE_L2
+                                      0x00FFFFFF));
+#else
+                                      0x00FFFF05));
+#endif
+
+#elif gcdMULTI_GPU_AFFINITY
+    control = ((((gctUINT32) (0x00FF0A05)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27)));
+
+    gcmkONERROR(gckOS_WriteRegisterEx(Os,
+                                      Core,
+                                      0x0055C,
+                                      control));
+#endif
+
     hardware->powerMutex = gcvNULL;
 
     hardware->mmuVersion
@@ -861,6 +1075,7 @@ gckHARDWARE_Construct(
     hardware->clockState      = gcvTRUE;
     hardware->powerState      = gcvTRUE;
     hardware->lastWaitLink    = ~0U;
+    hardware->lastEnd         = ~0U;
     hardware->globalSemaphore = gcvNULL;
 #if gcdENABLE_FSCALE_VAL_ADJUST
     hardware->powerOnFscaleVal = 64;
@@ -881,6 +1096,7 @@ gckHARDWARE_Construct(
 #endif
 
     gcmkONERROR(gckOS_AtomConstruct(Os, &hardware->pageTableDirty));
+    gcmkONERROR(gckOS_AtomConstruct(Os, &hardware->pendingEvent));
 
 #if gcdLINK_QUEUE_SIZE
     hardware->linkQueue.front = 0;
@@ -894,6 +1110,21 @@ gckHARDWARE_Construct(
     /* Disable profiler by default */
     hardware->gpuProfiler = gcvFALSE;
 
+#if defined(LINUX) || defined(__QNXNTO__) || defined(UNDERCE)
+    if (hardware->mmuVersion)
+    {
+        hardware->endAfterFlushMmuCache = gcvTRUE;
+    }
+    else
+#endif
+    {
+        hardware->endAfterFlushMmuCache = gcvFALSE;
+    }
+
+    gcmkONERROR(gckOS_QueryOption(Os, "mmu", (gctUINT32_PTR)&hardware->enableMMU));
+
+    hardware->minFscaleValue = 1;
+
     /* Return pointer to the gckHARDWARE object. */
     *Hardware = hardware;
 
@@ -934,6 +1165,11 @@ OnError:
             gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
         }
 
+        if (hardware->pendingEvent != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pendingEvent));
+        }
+
         gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, hardware));
     }
 
@@ -983,6 +1219,15 @@ gckHARDWARE_Destroy(
 
     gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pageTableDirty));
 
+    gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pendingEvent));
+
+    gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+        Hardware->os,
+        Hardware->functionBytes,
+        Hardware->functionPhysical,
+        Hardware->functionLogical
+        ));
+
     /* Mark the object as unknown. */
     Hardware->object.type = gcvOBJ_UNKNOWN;
 
@@ -1053,6 +1298,8 @@ gckHARDWARE_InitializeHardware(
     gctUINT32 baseAddress;
     gctUINT32 chipRev;
     gctUINT32 control;
+    gctUINT32 data;
+    gctUINT32 regPMC = 0;
 
     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
 
@@ -1128,10 +1375,7 @@ gckHARDWARE_InitializeHardware(
                                       0x00424,
                                       baseAddress));
 
-#if !VIVANTE_PROFILER
     {
-        gctUINT32 data;
-
         gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
                                          Hardware->core,
                                          Hardware->powerBaseAddress +
@@ -1156,80 +1400,75 @@ gckHARDWARE_InitializeHardware(
                                           + 0x00100,
                                           data));
 
-#ifndef VIVANTE_NO_3D
+#if gcdENABLE_3D
         /* Disable PE clock gating on revs < 5.0 when HZ is present without a
         ** bug fix. */
         if ((Hardware->identity.chipRevision < 0x5000)
+        &&  gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HZ)
         &&  ((((gctUINT32) (Hardware->identity.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->identity.chipMinorFeatures)) >> (0 ? 27:27) & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))))
         )
         {
-            gcmkONERROR(
-                gckOS_ReadRegisterEx(Hardware->os,
-                                     Hardware->core,
-                                     Hardware->powerBaseAddress
-                                     + 0x00104,
-                                     &data));
+            if (regPMC == 0)
+            {
+                gcmkONERROR(
+                    gckOS_ReadRegisterEx(Hardware->os,
+                                         Hardware->core,
+                                         Hardware->powerBaseAddress
+                                         + 0x00104,
+                                         &regPMC));
+            }
 
             /* Disable PE clock gating. */
-            data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)));
-
-            gcmkONERROR(
-                gckOS_WriteRegisterEx(Hardware->os,
-                                      Hardware->core,
-                                      Hardware->powerBaseAddress
-                                      + 0x00104,
-                                      data));
+            regPMC = ((((gctUINT32) (regPMC)) & ~(((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)));
         }
 
 #endif
     }
-#endif
 
-    /* Special workaround for this core
-    ** Make sure pulse eater kicks in only when SH is idle */
     if (Hardware->identity.chipModel == gcv4000 &&
-        Hardware->identity.chipRevision == 0x5208)
+        ((Hardware->identity.chipRevision == 0x5208) || (Hardware->identity.chipRevision == 0x5222)))
     {
-               gcmkONERROR(
+        gcmkONERROR(
             gckOS_WriteRegisterEx(Hardware->os,
                                   Hardware->core,
                                   0x0010C,
                                   ((((gctUINT32) (0x01590880)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))) << (0 ? 23:23))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))) << (0 ? 23:23)))));
     }
 
-    if ((gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI2) == gcvFALSE)
-     || (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI2) && (Hardware->identity.chipRevision < 0x5422))
-    )
+    if (Hardware->identity.chipModel == gcv1000 &&
+        (Hardware->identity.chipRevision == 0x5039 ||
+        Hardware->identity.chipRevision == 0x5040))
     {
-        gctUINT32 data;
-
-        gcmkONERROR(
-            gckOS_ReadRegisterEx(Hardware->os,
-                                 Hardware->core,
-                                 Hardware->powerBaseAddress
-                                 + 0x00104,
-                                 &data));
-
-
-        data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) << (0 ? 15:15))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) << (0 ? 15:15)));
+        gctUINT32 pulseEater;
 
+        pulseEater = ((((gctUINT32) (0x01590880)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)));
 
         gcmkONERROR(
             gckOS_WriteRegisterEx(Hardware->os,
                                   Hardware->core,
-                                  Hardware->powerBaseAddress
-                                  + 0x00104,
-                                  data));
+                                  0x0010C,
+                                  ((((gctUINT32) (pulseEater)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17)))));
     }
 
-    /* Special workaround for this core
-    ** Make sure FE and TX are on different buses */
-    if ((Hardware->identity.chipModel == gcv2000)
-    &&  (Hardware->identity.chipRevision  == 0x5108))
+    if ((gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI2) == gcvSTATUS_FALSE)
+     || (Hardware->identity.chipRevision < 0x5422)
+    )
     {
-        gctUINT32 data;
+        if (regPMC == 0)
+        {
+            gcmkONERROR(
+                gckOS_ReadRegisterEx(Hardware->os,
+                                     Hardware->core,
+                                     Hardware->powerBaseAddress
+                                     + 0x00104,
+                                     &regPMC));
+        }
+
+        regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) << (0 ? 15:15))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) << (0 ? 15:15)));
+    }
 
+    if (_IsHardwareMatch(Hardware, gcv2000, 0x5108))
+    {
         gcmkONERROR(
             gckOS_ReadRegisterEx(Hardware->os,
                                  Hardware->core,
@@ -1247,58 +1486,64 @@ gckHARDWARE_InitializeHardware(
                                   data));
     }
 
-    /* Test if MMU is initialized. */
-    if ((Hardware->kernel      != gcvNULL)
-    &&  (Hardware->kernel->mmu != gcvNULL)
-    )
+    gcmkONERROR(
+        gckHARDWARE_SetMMU(Hardware,
+                           Hardware->kernel->mmu->pageTableLogical));
+
+    if (Hardware->identity.chipModel >= gcv400
+    &&  Hardware->identity.chipModel != gcv420)
     {
-        /* Reset MMU. */
-        if (Hardware->mmuVersion == 0)
+        if (regPMC == 0)
         {
-            gcmkONERROR(
-                    gckHARDWARE_SetMMU(Hardware,
-                        Hardware->kernel->mmu->pageTableLogical));
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Hardware->os,
+                                 Hardware->core,
+                                 Hardware->powerBaseAddress
+                                 + 0x00104,
+                                 &regPMC));
         }
+
+        /* Disable PA clock gating. */
+        regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
     }
 
-    if (Hardware->identity.chipModel >= gcv400
-    &&  Hardware->identity.chipModel != gcv420
-    &&  (((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 15:15) & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) != gcvTRUE)
-    )
+    /* Limit 2D outstanding request. */
+    if (_IsHardwareMatch(Hardware, gcv880, 0x5107))
     {
-               gctUINT32 data;
+        gctUINT32 axi_ot;
+        gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00414, &axi_ot));
+        axi_ot = (axi_ot & (~0xFF)) | 0x00010;
+        gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00414, axi_ot));
+    }
+
+    if (Hardware->identity.chip2DControl & 0xFF)
+    {
+        gctUINT32 data;
 
         gcmkONERROR(
             gckOS_ReadRegisterEx(Hardware->os,
                                  Hardware->core,
-                                 Hardware->powerBaseAddress
-                                 + 0x00104,
+                                 0x00414,
                                  &data));
 
-        /* Disable PA clock gating. */
-        data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+        data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (Hardware->identity.chip2DControl & 0xFF) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)));
 
         gcmkONERROR(
             gckOS_WriteRegisterEx(Hardware->os,
                                   Hardware->core,
-                                  Hardware->powerBaseAddress
-                                  + 0x00104,
+                                  0x00414,
                                   data));
     }
 
-#if gcdHZ_L2_DISALBE
-    /* Disable HZ-L2. */
-    if (((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 26:26) & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) == gcvTRUE ||
-            ((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 8:8) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) == gcvTRUE)
+    if (_IsHardwareMatch(Hardware, gcv1000, 0x5035))
     {
-               gctUINT32 data;
-
         gcmkONERROR(
             gckOS_ReadRegisterEx(Hardware->os,
                                  Hardware->core,
                                  0x00414,
                                  &data));
 
+        /* Disable HZ-L2. */
         data = ((((gctUINT32) (data)) & ~(((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)));
 
         gcmkONERROR(
@@ -1307,51 +1552,88 @@ gckHARDWARE_InitializeHardware(
                                   0x00414,
                                   data));
     }
-#endif
 
-    /* Limit 2D outstanding request. */
-    if(Hardware->identity.chipModel == gcv880)
+    if (_IsHardwareMatch(Hardware, gcv4000, 0x5222))
     {
-        gctUINT32 axi_ot;
-        gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00414, &axi_ot));
-        axi_ot = (axi_ot & (~0xFF)) | 0x10;
-        gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00414, axi_ot));
+        if (regPMC == 0)
+        {
+        gcmkONERROR(
+            gckOS_ReadRegisterEx(Hardware->os,
+                                 Hardware->core,
+                                 Hardware->powerBaseAddress
+                                 + 0x00104,
+                                 &regPMC));
+        }
+
+        /* Disable TX clock gating. */
+        regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7)));
     }
 
-    if ((Hardware->identity.chipModel == gcv320)
-        && ((Hardware->identity.chipRevision == 0x5007)
-        || (Hardware->identity.chipRevision == 0x5220)))
+    if (_IsHardwareMatch(Hardware, gcv880, 0x5106))
     {
-               gctUINT32 data;
+        Hardware->kernel->timeOut = 140 * 1000;
+    }
 
+    if (regPMC == 0)
+    {
         gcmkONERROR(
             gckOS_ReadRegisterEx(Hardware->os,
                                  Hardware->core,
-                                 0x0002C,
-                                 &data));
-        if (data != 33956864)
-        {
-            gcmkONERROR(
-                gckOS_ReadRegisterEx(Hardware->os,
+                                 Hardware->powerBaseAddress
+                                 + 0x00104,
+                                 &regPMC));
+    }
+
+    /* Disable RA HZ clock gating. */
+    regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17)));
+
+    /* Disable RA EZ clock gating. */
+    regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)));
+
+    if (regPMC != 0)
+    {
+        gcmkONERROR(
+            gckOS_WriteRegisterEx(Hardware->os,
+                                  Hardware->core,
+                                  Hardware->powerBaseAddress
+                                  + 0x00104,
+                                  regPMC));
+    }
+
+    if (_IsHardwareMatch(Hardware, gcv2000, 0x5108)
+     || _IsHardwareMatch(Hardware, gcv320, 0x5007)
+     || _IsHardwareMatch(Hardware, gcv880, 0x5106)
+     || _IsHardwareMatch(Hardware, gcv400, 0x4645)
+    )
+    {
+        /* Update GPU AXI cache atttribute. */
+        gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                          Hardware->core,
+                                          0x00008,
+                                          0x00002200));
+    }
+
+
+    if ((Hardware->identity.chipRevision > 0x5420)
+     && gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_PIPE_3D))
+    {
+        gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
                                      Hardware->core,
-                                     0x00414,
+                                     0x0010C,
                                      &data));
 
-            data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (Hardware->identity.chipRevision == 0x5220 ? 8 : (Hardware->identity.chipRevision == 0x5007 ? 16 : 0)) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)));
+        /* Disable internal DFS. */
+        data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1))))))) << (0 ? 18:18))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1))))))) << (0 ? 18:18)));
 
-            gcmkONERROR(
-                gckOS_WriteRegisterEx(Hardware->os,
+        gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
                                       Hardware->core,
-                                      0x00414,
+                                      0x0010C,
                                       data));
-        }
     }
 
-    /* Update GPU AXI cache atttribute. */
-    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
-                                      Hardware->core,
-                                      0x00008,
-                                      0x00002200));
+#if gcdDEBUG_MODULE_CLOCK_GATING
+    _ConfigureModuleLevelClockGating(Hardware);
+#endif
 
     /* Success. */
     gcmkFOOTER_NO();
@@ -1539,6 +1821,7 @@ gckHARDWARE_QueryChipIdentity(
     Identity->chipMinorFeatures2 = Hardware->identity.chipMinorFeatures2;
     Identity->chipMinorFeatures3 = Hardware->identity.chipMinorFeatures3;
     Identity->chipMinorFeatures4 = Hardware->identity.chipMinorFeatures4;
+    Identity->chipMinorFeatures5 = Hardware->identity.chipMinorFeatures5;
 
     /* Return chip specs. */
     Identity->streamCount            = Hardware->identity.streamCount;
@@ -1553,6 +1836,12 @@ gckHARDWARE_QueryChipIdentity(
     Identity->bufferSize             = Hardware->identity.bufferSize;
     Identity->varyingsCount          = Hardware->identity.varyingsCount;
     Identity->superTileMode          = Hardware->identity.superTileMode;
+#if gcdMULTI_GPU
+    Identity->gpuCoreCount           = Hardware->identity.gpuCoreCount;
+#endif
+    Identity->chip2DControl          = Hardware->identity.chip2DControl;
+
+    Identity->productID              = Hardware->identity.productID;
 
     /* Success. */
     gcmkFOOTER_NO();
@@ -1643,8 +1932,8 @@ gckHARDWARE_SplitMemory(
 **      gckHARDWARE Hardware
 **          Pointer to the gckHARDWARE object.
 **
-**      gctPOINTER Logical
-**          Logical address of command buffer.
+**      gctUINT32 Address
+**          Hardware address of command buffer.
 **
 **      gctSIZE_T Bytes
 **          Number of bytes for the prefetch unit (until after the first LINK).
@@ -1656,40 +1945,18 @@ gckHARDWARE_SplitMemory(
 gceSTATUS
 gckHARDWARE_Execute(
     IN gckHARDWARE Hardware,
-    IN gctPOINTER Logical,
-#ifdef __QNXNTO__
-    IN gctPOINTER Physical,
-    IN gctBOOL PhysicalAddresses,
-#endif
+    IN gctUINT32 Address,
     IN gctSIZE_T Bytes
     )
 {
     gceSTATUS status;
-    gctUINT32 address = 0, control;
+    gctUINT32 control;
 
-    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Bytes=%lu",
-                   Hardware, Logical, Bytes);
+    gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Bytes=%lu",
+                   Hardware, Address, Bytes);
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
-    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
-
-#ifdef __QNXNTO__
-    if (PhysicalAddresses && (Hardware->mmuVersion == 0))
-    {
-        /* 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(
@@ -1697,7 +1964,7 @@ gckHARDWARE_Execute(
 
     /* Write address register. */
     gcmkONERROR(
-        gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00654, address));
+        gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00654, Address));
 
     /* Build control register. */
     control = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)))
@@ -1715,7 +1982,7 @@ gckHARDWARE_Execute(
 
     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
                   "Started command buffer @ 0x%08x",
-                  address);
+                  Address);
 
     /* Success. */
     gcmkFOOTER_NO();
@@ -1772,9 +2039,9 @@ gckHARDWARE_WaitLink(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
     IN gctUINT32 Offset,
-    IN OUT gctSIZE_T * Bytes,
+    IN OUT gctUINT32 * Bytes,
     OUT gctUINT32 * WaitOffset,
-    OUT gctSIZE_T * WaitSize
+    OUT gctUINT32 * WaitSize
     )
 {
     static const gctUINT waitCount = 200;
@@ -1782,7 +2049,7 @@ gckHARDWARE_WaitLink(
     gceSTATUS status;
     gctUINT32 address;
     gctUINT32_PTR logical;
-    gctSIZE_T bytes;
+    gctUINT32 bytes;
 
     gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=0x%08x *Bytes=%lu",
                    Hardware, Logical, Offset, gcmOPT_VALUE(Bytes));
@@ -1791,13 +2058,12 @@ gckHARDWARE_WaitLink(
     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
     gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
 
-    /* Compute number of bytes required. */
-#if gcd6000_SUPPORT
-    bytes = gcmALIGN(Offset + 96, 8) - Offset;
+#if gcdMULTI_GPU && !gcdDISABLE_FE_L2
+    bytes = gcmALIGN(Offset + 40, 8) - Offset;
 #else
+    /* Compute number of bytes required. */
     bytes = gcmALIGN(Offset + 16, 8) - Offset;
 #endif
-
     /* Cast the input pointer. */
     logical = (gctUINT32_PTR) Logical;
 
@@ -1811,7 +2077,7 @@ gckHARDWARE_WaitLink(
         }
 
         /* Convert logical into hardware specific address. */
-        gcmkONERROR(gckHARDWARE_ConvertLogical(Hardware, logical, &address));
+        gcmkONERROR(gckHARDWARE_ConvertLogical(Hardware, logical, gcvFALSE, &address));
 
         /* Store the WAIT/LINK address. */
         Hardware->lastWaitLink = address;
@@ -1821,99 +2087,45 @@ gckHARDWARE_WaitLink(
             = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
             | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (waitCount) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
 
-#if gcd6000_SUPPORT
-        /* Send FE-PE sempahore token. */
-        logical[2]
-            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
-
-        logical[3]
-            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+#if gcdMULTI_GPU && !gcdDISABLE_FE_L2
+        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) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                   | gcvCORE_3D_0_MASK;
 
-        /* Send FE-PE stall token. */
-        logical[4]
-            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+        logical[3] = 0;
 
-        logical[5]
-            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
-
-        /*************************************************************/
-        /* Enable chip ID 0. */
-        logical[6] =
-            ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-            | (1 << 0);
-
-        /* Send semaphore from FE to ChipID 1. */
-        logical[8] =
-              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
-
-        logical[9] =
-              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)));
-
-        /* Send semaphore from FE to ChipID 1. */
-        logical[10] =
-              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
-
-        logical[11] =
-              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)));
-
-        /*************************************************************/
-        /* Enable chip ID 1. */
-        logical[12] =
-            ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-            | (1 << 1);
-
-        /* Send semaphore from FE to ChipID 1. */
-        logical[14] =
-              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+        /* LoadState(AQFlush, 1), flush. */
+        logical[4] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                   | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 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[15] =
-              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)));
+        logical[5] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
 
-        /* Wait for semaphore from ChipID 0. */
-        logical[16] =
-              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+        logical[6] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                   | gcvCORE_3D_ALL_MASK;
 
-        logical[17] =
-              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)));
+        logical[7] = 0;
 
-        /*************************************************************/
-        /* Enable all chips. */
-        logical[18] =
-            ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-            | (0xFFFF);
+        /* Append LINK(2, address). */
+        logical[8] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (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)));
 
-        /* LoadState(AQFlush, 1), flush. */
-        logical[20]
-            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+        logical[9] = address;
 
-        logical[21]
-            = ((((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)));
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_HARDWARE,
+            "0x%08x: WAIT %u", address, waitCount
+            );
 
-        /* Append LINK(2, address). */
-        logical[22]
-            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                        "0x%x: FLUSH 0x%x", address + 8, logical[3]);
 
-        logical[23] = address;
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_HARDWARE,
+            "0x%08x: LINK 0x%08x, #%lu",
+            address + 16, address, bytes
+            );
 #else
+
         /* Append LINK(2, address). */
         logical[2]
             = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
@@ -1932,7 +2144,6 @@ gckHARDWARE_WaitLink(
             address + 8, address, bytes
             );
 #endif
-
         if (WaitOffset != gcvNULL)
         {
             /* Return the offset pointer to WAIT command. */
@@ -1942,7 +2153,11 @@ gckHARDWARE_WaitLink(
         if (WaitSize != gcvNULL)
         {
             /* Return number of bytes used by the WAIT command. */
+#if gcdMULTI_GPU && !gcdDISABLE_FE_L2
+            *WaitSize = 32;
+#else
             *WaitSize = 8;
+#endif
         }
     }
 
@@ -1994,10 +2209,11 @@ gceSTATUS
 gckHARDWARE_End(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     )
 {
     gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+    gctUINT32 address;
     gceSTATUS status;
 
     gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
@@ -2024,6 +2240,10 @@ gckHARDWARE_End(
         /* Make sure the CPU writes out the data to memory. */
         gcmkONERROR(
             gckOS_MemoryBarrier(Hardware->os, Logical));
+
+        gcmkONERROR(gckHARDWARE_ConvertLogical(Hardware, logical, gcvFALSE, &address));
+
+        Hardware->lastEnd = address;
     }
 
     if (Bytes != gcvNULL)
@@ -2042,43 +2262,20 @@ OnError:
     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.
-*/
+#if gcdMULTI_GPU
 gceSTATUS
-gckHARDWARE_Nop(
+gckHARDWARE_ChipEnable(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
+    IN gceCORE_3D_MASK ChipEnable,
     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));
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x ChipEnable=0x%x *Bytes=%lu",
+                   Hardware, Logical, ChipEnable, gcmOPT_VALUE(Bytes));
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
@@ -2092,15 +2289,16 @@ gckHARDWARE_Nop(
             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)));
+        /* Append CHIPENABLE. */
+        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) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                   | ChipEnable;
 
-        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: NOP", Logical);
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: CHIPENABLE 0x%x", Logical, ChipEnable);
     }
 
     if (Bytes != gcvNULL)
     {
-        /* Return number of bytes required by the NOP command. */
+        /* Return number of bytes required by the CHIPENABLE command. */
         *Bytes = 8;
     }
 
@@ -2113,12 +2311,13 @@ OnError:
     gcmkFOOTER();
     return status;
 }
+#endif
 
 /*******************************************************************************
 **
-**  gckHARDWARE_Wait
+**  gckHARDWARE_Nop
 **
-**  Append a WAIT command at the specified location in the command queue.
+**  Append a NOP command at the specified location in the command queue.
 **
 **  INPUT:
 **
@@ -2127,13 +2326,10 @@ OnError:
 **
 **      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.
+**          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 WAIT command.  If
+**          Pointer to the number of bytes available for the NOP command.  If
 **          'Logical' is gcvNULL, this argument will be ignored.
 **
 **  OUTPUT:
@@ -2143,26 +2339,22 @@ OnError:
 **          for the NOP command.  If 'Bytes' is gcvNULL, nothing will be returned.
 */
 gceSTATUS
-gckHARDWARE_Wait(
+gckHARDWARE_Nop(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
-    IN gctUINT32 Count,
     IN OUT gctSIZE_T * Bytes
     )
 {
+    gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
     gceSTATUS status;
-    gctUINT32_PTR logical;
 
-    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Count=%u *Bytes=%lu",
-                   Hardware, Logical, Count, gcmOPT_VALUE(Bytes));
+    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));
 
-    /* Cast the input pointer. */
-    logical = (gctUINT32_PTR) Logical;
-
     if (Logical != gcvNULL)
     {
         if (*Bytes < 8)
@@ -2171,30 +2363,15 @@ gckHARDWARE_Wait(
             gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
         }
 
-        /* Append WAIT. */
-        logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-                   | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
-
-#if gcmIS_DEBUG(gcdDEBUG_TRACE)
-        {
-            gctUINT32 address;
-
-            /* Convert logical into hardware specific address. */
-            gcmkONERROR(gckHARDWARE_ConvertLogical(
-                Hardware, logical, &address
-                ));
+        /* 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%08x: WAIT %u", address, Count
-                );
-        }
-#endif
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: NOP", Logical);
     }
 
     if (Bytes != gcvNULL)
     {
-        /* Return number of bytes required by the WAIT command. */
+        /* Return number of bytes required by the NOP command. */
         *Bytes = 8;
     }
 
@@ -2247,7 +2424,7 @@ gckHARDWARE_Event(
     IN gctPOINTER Logical,
     IN gctUINT8 Event,
     IN gceKERNEL_WHERE FromWhere,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     )
 {
     gctUINT size;
@@ -2263,6 +2440,10 @@ gckHARDWARE_Event(
     gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
     gcmkVERIFY_ARGUMENT(Event < 32);
 
+#if gcdMULTI_GPU
+    if (FromWhere == gcvKERNEL_COMMAND) FromWhere = gcvKERNEL_PIXEL;
+#endif
+
     /* Determine the size of the command. */
 
     size = (Hardware->extraEventStates && (FromWhere == gcvKERNEL_PIXEL))
@@ -2328,6 +2509,13 @@ gckHARDWARE_Event(
             logical[6] = 0;
             logical[7] = 0;
         }
+
+#if gcdINTERRUPT_STATISTIC
+        if (Event < gcmCOUNTOF(Hardware->kernel->eventObj->queues))
+        {
+            gckOS_AtomSetMask(Hardware->pendingEvent, 1 << Event);
+        }
+#endif
     }
 
     if (Bytes != gcvNULL)
@@ -2381,7 +2569,7 @@ gckHARDWARE_PipeSelect(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
     IN gcePIPE_SELECT Pipe,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     )
 {
     gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
@@ -2490,8 +2678,8 @@ OnError:
 **          the LINK command at or gcvNULL just to query the size of the LINK
 **          command.
 **
-**      gctPOINTER FetchAddress
-**          Logical address of destination of LINK.
+**      gctUINT32 FetchAddress
+**          Hardware address of destination of LINK.
 **
 **      gctSIZE_T FetchSize
 **          Number of bytes in destination of LINK.
@@ -2510,14 +2698,13 @@ gceSTATUS
 gckHARDWARE_Link(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
-    IN gctPOINTER FetchAddress,
-    IN gctSIZE_T FetchSize,
-    IN OUT gctSIZE_T * Bytes
+    IN gctUINT32 FetchAddress,
+    IN gctUINT32 FetchSize,
+    IN OUT gctUINT32 * Bytes
     )
 {
     gceSTATUS status;
     gctSIZE_T bytes;
-    gctUINT32 address;
     gctUINT32 link;
     gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
 
@@ -2538,19 +2725,15 @@ gckHARDWARE_Link(
             gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
         }
 
-        /* Convert logical address to hardware address. */
-        gcmkONERROR(
-            gckHARDWARE_ConvertLogical(Hardware, FetchAddress, &address));
-
         gcmkONERROR(
-            gckOS_WriteMemory(Hardware->os, logical + 1, address));
+            gckOS_WriteMemory(Hardware->os, logical + 1, FetchAddress));
 
         /* 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;
+        bytes = gcmALIGN(FetchAddress + FetchSize, 64) - FetchAddress;
 
         /* Append LINK(bytes / 8), FetchAddress. */
         link = ((((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)))
@@ -2563,10 +2746,24 @@ gckHARDWARE_Link(
         gcmkONERROR(
             gckOS_MemoryBarrier(Hardware->os, logical));
 
-#if gcdLINK_QUEUE_SIZE && gcdVIRTUAL_COMMAND_BUFFER
-        if (address >= 0x80000000)
+#if gcdLINK_QUEUE_SIZE && !gcdPROCESS_ADDRESS_SPACE
+        if ((Hardware->kernel->virtualCommandBuffer)
+         && (Hardware->kernel->stuckDump > 2)
+        )
         {
-            gckLINKQUEUE_Enqueue(&Hardware->linkQueue, address, address + bytes);
+            gctBOOL in;
+
+            gcmkVERIFY_OK(gckCOMMAND_AddressInKernelCommandBuffer(
+                Hardware->kernel->command, FetchAddress, &in));
+
+            if (in == gcvFALSE)
+            {
+                /* Record user command buffer and context buffer link
+                ** information for stuck dump.
+                **/
+                gckLINKQUEUE_Enqueue(
+                    &Hardware->linkQueue, FetchAddress, FetchAddress + (gctUINT)bytes);
+            }
         }
 #endif
     }
@@ -2628,14 +2825,22 @@ gckHARDWARE_UpdateQueueTail(
         gckOS_MemoryBarrier(Hardware->os, Logical));
 
     /* Notify gckKERNEL object of change. */
+#if gcdMULTI_GPU
     gcmkONERROR(
         gckKERNEL_Notify(Hardware->kernel,
+                         0,
                          gcvNOTIFY_COMMAND_QUEUE,
                          gcvFALSE));
+#else
+    gcmkONERROR(
+        gckKERNEL_Notify(Hardware->kernel,
+                         gcvNOTIFY_COMMAND_QUEUE,
+                         gcvFALSE));
+#endif
 
     if (status == gcvSTATUS_CHIP_NOT_READY)
     {
-        gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
+        gcmkONERROR(gcvSTATUS_DEVICE);
     }
 
     /* Success. */
@@ -2662,6 +2867,9 @@ OnError:
 **      gctPOINTER Logical
 **          Logical address to convert.
 **
+**      gctBOOL InUserSpace
+**          gcvTRUE if the memory in user space.
+**
 **      gctUINT32* Address
 **          Return hardware specific address.
 **
@@ -2673,6 +2881,7 @@ gceSTATUS
 gckHARDWARE_ConvertLogical(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
+    IN gctBOOL InUserSpace,
     OUT gctUINT32 * Address
     )
 {
@@ -2680,94 +2889,28 @@ gckHARDWARE_ConvertLogical(
     gceSTATUS status;
     gctUINT32 baseAddress;
 
-    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x", Hardware, Logical);
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x InUserSpace=%d",
+                   Hardware, Logical, InUserSpace);
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
     gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
     gcmkVERIFY_ARGUMENT(Address != gcvNULL);
 
-#if gcdVIRTUAL_COMMAND_BUFFER
-    status = gckKERNEL_GetGPUAddress(Hardware->kernel, Logical, Address);
-
-    if (status == gcvSTATUS_INVALID_ADDRESS)
-#endif
+    /* Convert logical address into a physical address. */
+    if (InUserSpace)
     {
-        /* Convert logical address into a physical address. */
-        gcmkONERROR(
-            gckOS_GetPhysicalAddress(Hardware->os, Logical, &address));
-
-        /* For old MMU, get GPU address according to baseAddress. */
-        if (Hardware->mmuVersion == 0)
-        {
-            gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
-
-            /* Subtract base address to get a GPU address. */
-            gcmkASSERT(address >= baseAddress);
-            address -= baseAddress;
-        }
-
-        /* Return hardware specific address. */
-        *Address = (Hardware->mmuVersion == 0)
-                 ? ((((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)))
-                 : address;
+        gcmkONERROR(gckOS_UserLogicalToPhysical(Hardware->os, Logical, &address));
+    }
+    else
+    {
+        gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, Logical, &address));
     }
-
-    /* Success. */
-    gcmkFOOTER_ARG("*Address=0x%08x", *Address);
-    return gcvSTATUS_OK;
-
-OnError:
-    /* Return the status. */
-    gcmkFOOTER();
-    return status;
-}
-
-/*******************************************************************************
-**
-**  gckHARDWARE_ConvertPhysical
-**
-**  Convert a physical address into a hardware specific address.
-**
-**  INPUT:
-**
-**      gckHARDWARE Hardware
-**          Pointer to an gckHARDWARE object.
-**
-**      gctPHYS_ADDR Physical
-**          Physical address to convert.
-**
-**      gctUINT32* Address
-**          Return hardware specific address.
-**
-**  OUTPUT:
-**
-**      Nothing.
-*/
-gceSTATUS
-gckHARDWARE_ConvertPhysical(
-    IN gckHARDWARE Hardware,
-    IN gctPHYS_ADDR Physical,
-    OUT gctUINT32 * Address
-    )
-{
-    gctUINT32 address;
-    gctUINT32 baseAddress;
-
-    gcmkHEADER_ARG("Hardware=0x%x Physical=0x%x", Hardware, Physical);
-
-    /* Verify the arguments. */
-    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
-    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
-    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
-
-    address = gcmPTR2INT(Physical);
 
     /* For old MMU, get GPU address according to baseAddress. */
     if (Hardware->mmuVersion == 0)
     {
-        gcmkVERIFY_OK(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
+        gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
 
         /* Subtract base address to get a GPU address. */
         gcmkASSERT(address >= baseAddress);
@@ -2780,9 +2923,14 @@ gckHARDWARE_ConvertPhysical(
                | ((((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)))
              : address;
 
-    /* Return the status. */
+    /* Success. */
     gcmkFOOTER_ARG("*Address=0x%08x", *Address);
     return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
 }
 
 /*******************************************************************************
@@ -2810,11 +2958,14 @@ gckHARDWARE_ConvertPhysical(
 gceSTATUS
 gckHARDWARE_Interrupt(
     IN gckHARDWARE Hardware,
+#if gcdMULTI_GPU
+    IN gctUINT CoreId,
+#endif
     IN gctBOOL InterruptValid
     )
 {
     gckEVENT eventObj;
-    gctUINT32 data;
+    gctUINT32 data = 0;
     gceSTATUS status;
 
     gcmkHEADER_ARG("Hardware=0x%x InterruptValid=%d", Hardware, InterruptValid);
@@ -2829,11 +2980,31 @@ gckHARDWARE_Interrupt(
     if (InterruptValid)
     {
         /* Read AQIntrAcknowledge register. */
+#if gcdMULTI_GPU
+        if (Hardware->core == gcvCORE_MAJOR)
+        {
+            gcmkONERROR(
+                gckOS_ReadRegisterByCoreId(Hardware->os,
+                                           Hardware->core,
+                                           CoreId,
+                                           0x00010,
+                                           &data));
+        }
+        else
+        {
+            gcmkONERROR(
+                gckOS_ReadRegisterEx(Hardware->os,
+                                     Hardware->core,
+                                     0x00010,
+                                     &data));
+        }
+#else
         gcmkONERROR(
             gckOS_ReadRegisterEx(Hardware->os,
                                  Hardware->core,
                                  0x00010,
                                  &data));
+#endif
 
         if (data == 0)
         {
@@ -2842,14 +3013,23 @@ gckHARDWARE_Interrupt(
         }
         else
         {
+
+#if gcdINTERRUPT_STATISTIC
+            gckOS_AtomClearMask(Hardware->pendingEvent, data);
+#endif
+
             /* Inform gckEVENT of the interrupt. */
-            status = gckEVENT_Interrupt(eventObj, data);
+            status = gckEVENT_Interrupt(eventObj,
+#if gcdMULTI_GPU
+                                        CoreId,
+#endif
+                                        data);
         }
     }
     else
     {
-        /* Handle events. */
-        status = gckEVENT_Notify(eventObj, 0);
+            /* Handle events. */
+            status = gckEVENT_Notify(eventObj, 0);
     }
 
 OnError:
@@ -2885,9 +3065,9 @@ OnError:
 gceSTATUS
 gckHARDWARE_QueryCommandBuffer(
     IN gckHARDWARE Hardware,
-    OUT gctSIZE_T * Alignment,
-    OUT gctSIZE_T * ReservedHead,
-    OUT gctSIZE_T * ReservedTail
+    OUT gctUINT32 * Alignment,
+    OUT gctUINT32 * ReservedHead,
+    OUT gctUINT32 * ReservedTail
     )
 {
     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
@@ -2971,7 +3151,7 @@ gckHARDWARE_QuerySystemMemory(
     return gcvSTATUS_OK;
 }
 
-#ifndef VIVANTE_NO_3D
+#if gcdENABLE_3D
 /*******************************************************************************
 **
 **  gckHARDWARE_QueryShaderCaps
@@ -2992,61 +3172,47 @@ gckHARDWARE_QuerySystemMemory(
 **          Pointer to a variable receiving the number of uniforms in the
 **          fragment shader.
 **
-**      gctUINT * Varyings
-**          Pointer to a variable receiving the maimum number of varyings.
+**      gctBOOL * UnifiedUnforms
+**          Pointer to a variable receiving whether the uniformas are unified.
 */
 gceSTATUS
 gckHARDWARE_QueryShaderCaps(
     IN gckHARDWARE Hardware,
     OUT gctUINT * VertexUniforms,
     OUT gctUINT * FragmentUniforms,
-    OUT gctUINT * Varyings
+    OUT gctBOOL * UnifiedUnforms
     )
 {
+    gctBOOL unifiedConst;
     gctUINT32 vsConstMax;
     gctUINT32 psConstMax;
+    gctUINT32 vsConstBase;
+    gctUINT32 psConstBase;
+    gctUINT32 ConstMax;
 
     gcmkHEADER_ARG("Hardware=0x%x VertexUniforms=0x%x "
-                   "FragmentUniforms=0x%x Varyings=0x%x",
+                   "FragmentUniforms=0x%x UnifiedUnforms=0x%x",
                    Hardware, VertexUniforms,
-                   FragmentUniforms, Varyings);
+                   FragmentUniforms, UnifiedUnforms);
 
-    if ((Hardware->identity.chipModel == gcv2000)
-     && (Hardware->identity.chipRevision == 0x5118))
-    {
-        vsConstMax   = 256;
-        psConstMax   = 64;
-    }
-    else if (Hardware->identity.numConstants > 256)
-    {
-        vsConstMax   = 256;
-        psConstMax   = 256;
-    }
-    else if (Hardware->identity.numConstants == 256)
-    {
-        vsConstMax   = 256;
-        psConstMax   = 256;
-    }
-    else
-    {
-        vsConstMax   = 168;
-        psConstMax   = 64;
-    }
+    {if (Hardware->identity.numConstants > 256){    unifiedConst = gcvTRUE;    vsConstBase  = 0xC000;    psConstBase  = 0xC000;    ConstMax     = Hardware->identity.numConstants;    vsConstMax   = 256;    psConstMax   = ConstMax - vsConstMax;}else if (Hardware->identity.numConstants == 256){    if (Hardware->identity.chipModel == gcv2000 && Hardware->identity.chipRevision == 0x5118)    {        unifiedConst = gcvFALSE;        vsConstBase  = 0x1400;        psConstBase  = 0x1C00;        vsConstMax   = 256;        psConstMax   = 64;        ConstMax     = 320;    }    else    {        unifiedConst = gcvFALSE;        vsConstBase  = 0x1400;        psConstBase  = 0x1C00;        vsConstMax   = 256;        psConstMax   = 256;        ConstMax     = 512;    }}else{    unifiedConst = gcvFALSE;    vsConstBase  = 0x1400;    psConstBase  = 0x1C00;    vsConstMax   = 168;    psConstMax   = 64;    ConstMax     = 232;}};
 
     if (VertexUniforms != gcvNULL)
     {
+        /* Return the vs shader const count. */
         *VertexUniforms = vsConstMax;
     }
 
     if (FragmentUniforms != gcvNULL)
     {
+        /* Return the ps shader const count. */
         *FragmentUniforms = psConstMax;
     }
 
-    if (Varyings != gcvNULL)
+    if (UnifiedUnforms != gcvNULL)
     {
-               /* Return the shader varyings count. */
-        *Varyings = Hardware->identity.varyingsCount;
+        /* Return whether the uniformas are unified. */
+        *UnifiedUnforms = unifiedConst;
     }
 
     /* Success. */
@@ -3081,65 +3247,109 @@ gckHARDWARE_SetMMU(
 {
     gceSTATUS status;
     gctUINT32 address = 0;
-    gctUINT32 baseAddress;
+    gctUINT32 idle;
+    gctUINT32 timer = 0, delay = 1;
 
     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));
+    if (Hardware->mmuVersion == 0)
+    {
+        gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
 
-    /* Also get the base address - we need a real physical address. */
-    gcmkONERROR(
-        gckOS_GetBaseAddress(Hardware->os, &baseAddress));
+        /* Convert the logical address into physical address. */
+        gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, Logical, &address));
 
-    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
-                   "Setting page table to 0x%08X",
-                   address + baseAddress);
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                       "Setting page table to 0x%08X",
+                       address);
 
-    /* Write the AQMemoryFePageTable register. */
-    gcmkONERROR(
-        gckOS_WriteRegisterEx(Hardware->os,
-                              Hardware->core,
-                              0x00400,
-                              address + baseAddress));
+        /* Write the AQMemoryFePageTable register. */
+        gcmkONERROR(
+            gckOS_WriteRegisterEx(Hardware->os,
+                                  Hardware->core,
+                                  0x00400,
+                                  address));
 
-    /* Write the AQMemoryRaPageTable register. */
-    gcmkONERROR(
-        gckOS_WriteRegisterEx(Hardware->os,
-                              Hardware->core,
-                              0x00410,
-                              address + baseAddress));
+        /* Write the AQMemoryRaPageTable register. */
+        gcmkONERROR(
+            gckOS_WriteRegisterEx(Hardware->os,
+                                  Hardware->core,
+                                  0x00410,
+                                  address));
 
-    /* Write the AQMemoryTxPageTable register. */
-    gcmkONERROR(
-        gckOS_WriteRegisterEx(Hardware->os,
-                              Hardware->core,
-                              0x00404,
-                              address + baseAddress));
+        /* Write the AQMemoryTxPageTable register. */
+        gcmkONERROR(
+            gckOS_WriteRegisterEx(Hardware->os,
+                                  Hardware->core,
+                                  0x00404,
+                                  address));
 
 
-    /* Write the AQMemoryPePageTable register. */
-    gcmkONERROR(
-        gckOS_WriteRegisterEx(Hardware->os,
-                              Hardware->core,
-                              0x00408,
-                              address + baseAddress));
+        /* Write the AQMemoryPePageTable register. */
+        gcmkONERROR(
+            gckOS_WriteRegisterEx(Hardware->os,
+                                  Hardware->core,
+                                  0x00408,
+                                  address));
 
-    /* Write the AQMemoryPezPageTable register. */
-    gcmkONERROR(
-        gckOS_WriteRegisterEx(Hardware->os,
-                              Hardware->core,
-                              0x0040C,
-                              address + baseAddress));
+        /* Write the AQMemoryPezPageTable register. */
+        gcmkONERROR(
+            gckOS_WriteRegisterEx(Hardware->os,
+                                  Hardware->core,
+                                  0x0040C,
+                                  address));
+    }
+    else if (Hardware->enableMMU == gcvTRUE)
+    {
+        /* Execute prepared command sequence. */
+        gcmkONERROR(gckHARDWARE_Execute(
+            Hardware,
+            Hardware->functions[gcvHARDWARE_FUNCTION_MMU].address,
+            Hardware->functions[gcvHARDWARE_FUNCTION_MMU].bytes
+            ));
+
+        /* Wait until MMU configure finishes. */
+        do
+        {
+            gckOS_Delay(Hardware->os, delay);
+
+            gcmkONERROR(gckOS_ReadRegisterEx(
+                Hardware->os,
+                Hardware->core,
+                0x00004,
+                &idle));
+
+            timer += delay;
+            delay *= 2;
+
+#if gcdGPU_TIMEOUT
+            if (timer >= Hardware->kernel->timeOut)
+            {
+                /* Even if hardware is not reset correctly, let software
+                ** continue to avoid software stuck. Software will timeout again
+                ** and try to recover GPU in next timeout.
+                */
+                gcmkONERROR(gcvSTATUS_DEVICE);
+            }
+#endif
+        }
+        while (!(((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ));
+
+        /* Enable MMU. */
+        gcmkONERROR(gckOS_WriteRegisterEx(
+            Hardware->os,
+            Hardware->core,
+            0x0018C,
+            ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (gcvTRUE) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+            ));
+    }
 
     /* Return the status. */
     gcmkFOOTER_NO();
-    return status;
+    return gcvSTATUS_OK;
 
 OnError:
     /* Return the status. */
@@ -3170,8 +3380,7 @@ gckHARDWARE_FlushMMU(
     gceSTATUS status;
     gckCOMMAND command;
     gctUINT32_PTR buffer;
-    gctSIZE_T bufferSize;
-    gctBOOL commitEntered = gcvFALSE;
+    gctUINT32 bufferSize;
     gctPOINTER pointer = gcvNULL;
     gctUINT32 flushSize;
     gctUINT32 count;
@@ -3185,10 +3394,6 @@ gckHARDWARE_FlushMMU(
     /* Verify the gckCOMMAND object pointer. */
     command = Hardware->kernel->command;
 
-    /* Acquire the command queue. */
-    gcmkONERROR(gckCOMMAND_EnterCommit(command, gcvFALSE));
-    commitEntered = gcvTRUE;
-
     /* Flush the memory controller. */
     if (Hardware->mmuVersion == 0)
     {
@@ -3222,7 +3427,7 @@ gckHARDWARE_FlushMMU(
 
         buffer = (gctUINT32_PTR) pointer;
 
-        count = (bufferSize - flushSize + 7) >> 3;
+        count = ((gctUINT)bufferSize - flushSize + 7) >> 3;
 
         gcmkONERROR(gckOS_GetPhysicalAddress(command->os, buffer, &physical));
 
@@ -3236,7 +3441,6 @@ gckHARDWARE_FlushMMU(
             = ((((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 ? 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 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)))
             | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 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)))
             | ((((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)));
 
@@ -3304,80 +3508,60 @@ gckHARDWARE_FlushMMU(
         gcmkONERROR(gckCOMMAND_Execute(command, flushSize));
     }
 
-    /* Release the command queue. */
-    gcmkONERROR(gckCOMMAND_ExitCommit(command, gcvFALSE));
-    commitEntered = gcvFALSE;
-
     /* Success. */
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 
 OnError:
-    if (commitEntered)
-    {
-        /* Release the command queue mutex. */
-        gcmkVERIFY_OK(gckCOMMAND_ExitCommit(Hardware->kernel->command,
-                                            gcvFALSE));
-    }
 
     /* Return the status. */
     gcmkFOOTER();
     return status;
 }
 
-/*******************************************************************************
-**
-**  gckHARDWARE_SetMMUv2
-**
-**  Set the page table base address.
-**
-**  INPUT:
-**
-**      gckHARDWARE Harwdare
-**          Pointer to an gckHARDWARE object.
-**
-**  OUTPUT:
-**
-**      Nothing.
-*/
 gceSTATUS
-gckHARDWARE_SetMMUv2(
+gckHARDWARE_SetMMUStates(
     IN gckHARDWARE Hardware,
-    IN gctBOOL Enable,
     IN gctPOINTER MtlbAddress,
     IN gceMMU_MODE Mode,
     IN gctPOINTER SafeAddress,
-    IN gctBOOL FromPower
+    IN gctPOINTER Logical,
+    IN OUT gctUINT32 * Bytes
     )
 {
     gceSTATUS status;
     gctUINT32 config, address;
-    gckCOMMAND command;
     gctUINT32_PTR buffer;
-    gctSIZE_T bufferSize;
-    gctBOOL commitEntered = gcvFALSE;
-    gctPOINTER pointer = gcvNULL;
-    gctBOOL acquired = gcvFALSE;
+    gctBOOL ace;
+    gctUINT32 reserveBytes = 16 + 4 * 4;
+
     gctBOOL config2D;
-    gctSIZE_T configSize;
 
-    gcmkHEADER_ARG("Hardware=0x%x Enable=%d", Hardware, Enable);
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    gcmkVERIFY_ARGUMENT(Hardware->mmuVersion != 0);
+
+    ace = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_ACE);
+
+    if (ace)
+    {
+        reserveBytes += 8;
+    }
 
     config2D =  gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_PIPE_3D)
              && gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_PIPE_2D);
 
-    configSize = 4 * 4;
-
     if (config2D)
     {
-        configSize +=
+        reserveBytes +=
             /* Pipe Select. */
             4 * 4
             /* Configure MMU States. */
-          + 4 * 4;
+          + 4 * 4
+            /* Semaphore stall */
+          + 4 * 8;
     }
 
     /* Convert logical address into physical address. */
@@ -3392,166 +3576,395 @@ gckHARDWARE_SetMMUv2(
         gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
     }
 
-    switch (Mode)
+    switch (Mode)
+    {
+    case gcvMMU_MODE_1K:
+        if (config & 0x3FF)
+        {
+            gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+        }
+
+        config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+        break;
+
+    case gcvMMU_MODE_4K:
+        if (config & 0xFFF)
+        {
+            gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+        }
+
+        config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+        break;
+
+    default:
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+
+    if (Logical != gcvNULL)
+    {
+        buffer = Logical;
+
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+        *buffer++ = config;
+
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0060) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+        *buffer++ = address;
+
+        if (ace)
+        {
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0068) & ((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++ = 0;
+        }
+
+        do{*buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));} while(0);;
+
+        if (config2D)
+        {
+            /* LoadState(AQPipeSelect, 1), pipe. */
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+            *buffer++ = 0x1;
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+            *buffer++ = config;
+
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0060) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+            *buffer++ = address;
+
+            do{*buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));} while(0);;
+
+            /* LoadState(AQPipeSelect, 1), pipe. */
+            *buffer++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+            *buffer++ = 0x0;
+
+            do{*buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));} while(0);;
+        }
+
+    }
+
+    if (Bytes != gcvNULL)
+    {
+        *Bytes = reserveBytes;
+    }
+
+    /* Return the status. */
+    gcmkFOOTER_NO();
+    return status;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+#if gcdPROCESS_ADDRESS_SPACE
+/*******************************************************************************
+**
+**  gckHARDWARE_ConfigMMU
+**
+**  Append a MMU Configuration command sequence at the specified location in the command
+**  queue. That command sequence consists of mmu configuration, LINK and WAIT/LINK.
+**  LINK is fetched and paresed with new mmu configuration.
+**
+**  If MMU Configuration is not changed between commit, change last WAIT/LINK to
+**  link to ENTRY.
+**
+**  -+-----------+-----------+-----------------------------------------
+**   | WAIT/LINK | WAIT/LINK |
+**  -+-----------+-----------+-----------------------------------------
+**         |          /|\
+**        \|/          |
+**    +--------------------+
+**    | ENTRY | ... | LINK |
+**    +--------------------+
+**
+**  If MMU Configuration is changed between commit, change last WAIT/LINK to
+**  link to MMU CONFIGURATION command sequence, and there are an EVNET and
+**  an END at the end of this command sequence, when interrupt handler
+**  receives this event, it will start FE at ENTRY to continue the command
+**  buffer execution.
+**
+**  -+-----------+-------------------+---------+---------+-----------+--
+**   | WAIT/LINK | MMU CONFIGURATION |  EVENT  |  END    | WAIT/LINK |
+**  -+-----------+-------------------+---------+---------+-----------+--
+**        |            /|\                                   /|\
+**        +-------------+                                     |
+**                                          +--------------------+
+**                                          | ENTRY | ... | LINK |
+**                                          +--------------------+
+**  INPUT:
+**
+**      gckHARDWARE Hardware
+**          Pointer to an gckHARDWARE object.
+**
+**      gctPOINTER Logical
+**          Pointer to the current location inside the command queue to append
+**          command sequence at or gcvNULL just to query the size of the
+**          command sequence.
+**
+**      gctPOINTER MtlbLogical
+**          Pointer to the current Master TLB.
+**
+**      gctUINT32 Offset
+**          Offset into command buffer required for alignment.
+**
+**      gctSIZE_T * Bytes
+**          Pointer to the number of bytes available for the 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 command sequence.  If 'Bytes' is gcvNULL, nothing will
+**          be returned.
+**
+**      gctUINT32 * WaitLinkOffset
+**          Pointer to a variable that will receive the offset of the WAIT/LINK command
+**          from the specified logcial pointer.
+**          If 'WaitLinkOffset' is gcvNULL nothing will be returned.
+**
+**      gctSIZE_T * WaitLinkBytes
+**          Pointer to a variable that will receive the number of bytes used by
+**          the WAIT command.
+**          If 'WaitLinkBytes' is gcvNULL nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_ConfigMMU(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gctPOINTER MtlbLogical,
+    IN gctUINT32 Offset,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctSIZE_T * WaitLinkOffset,
+    OUT gctSIZE_T * WaitLinkBytes
+    )
+{
+    gceSTATUS status;
+    gctSIZE_T bytes, bytesAligned;
+    gctUINT32 config;
+    gctUINT32_PTR buffer = (gctUINT32_PTR) Logical;
+    gctUINT32 physical;
+    gctUINT32 event;
+
+    gcmkHEADER_ARG("Hardware=0x%08X Logical=0x%08x MtlbLogical=0x%08X",
+                   Hardware, Logical, MtlbLogical);
+
+    bytes
+        /* Flush cache states. */
+        = 18 * 4
+        /* MMU configuration states. */
+        + 6 * 4
+        /* EVENT. */
+        + 2 * 4
+        /* END. */
+        + 2 * 4
+        /* WAIT/LINK. */
+        + 4 * 4;
+
+    /* Compute number of bytes required. */
+    bytesAligned = gcmALIGN(Offset + bytes, 8) - Offset;
+
+    if (buffer != gcvNULL)
     {
-    case gcvMMU_MODE_1K:
-        if (config & 0x3FF)
+        if (MtlbLogical == gcvNULL)
         {
-            gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
         }
 
-        config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
-
-        break;
+        /* Get physical address of this command buffer segment. */
+        gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, buffer, &physical));
 
-    case gcvMMU_MODE_4K:
-        if (config & 0xFFF)
-        {
-            gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
-        }
+        /* Get physical address of Master TLB. */
+        gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, MtlbLogical, &config));
 
-        config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+        config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+                | ((((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)));
 
-        break;
+        /* Flush cache. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
 
-    default:
-        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
-    }
+        *buffer++
+            = ((((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 ? 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 ? 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 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 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)))
+            | ((((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)));
 
-    /* Verify the gckCOMMAND object pointer. */
-    command = Hardware->kernel->command;
+        /* Flush tile status cache. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0594) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
 
-    /* Acquire the command queue. */
-    gcmkONERROR(gckCOMMAND_EnterCommit(command, FromPower));
-    commitEntered = gcvTRUE;
+        *buffer++
+            = ((((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)));
 
-    gcmkONERROR(gckCOMMAND_Reserve(
-        command, configSize, &pointer, &bufferSize
-        ));
+        /* Arm the PE-FE Semaphore. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
 
-    buffer = pointer;
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
 
-    buffer[0]
-        = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
-        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+        /* STALL FE until PE is done flushing. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
 
-    buffer[1] = config;
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
 
-    buffer[2]
-        = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0060) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
-        | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+        /* LINK to next slot to flush FE FIFO. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (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) (4) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
 
-    buffer[3] = address;
+        *buffer++
+            = physical + 10 * gcmSIZEOF(gctUINT32);
 
-    if (config2D)
-    {
-        /* LoadState(AQPipeSelect, 1), pipe. */
-        buffer[4]
+        /* Configure MMU. */
+        *buffer++
             = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
             | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
 
-        buffer[5] = 0x1;
+        *buffer++
+            = (((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) &  ((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))));
 
-        buffer[6]
+        /* Arm the PE-FE Semaphore. */
+        *buffer++
             = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
 
-        buffer[7] = config;
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
 
-        buffer[8]
-            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0060) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+        /* STALL FE until PE is done flushing. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
 
-        buffer[9] = address;
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
 
-        /* LoadState(AQPipeSelect, 1), pipe. */
-        buffer[10]
+        /* LINK to next slot to flush FE FIFO. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (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) (5) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+        *buffer++
+            = physical + 18 * 4;
+
+        *buffer++
             = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
-            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
             | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
 
-        buffer[11] = 0x0;
-    }
-
-    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
-        "Setup MMU: config=%08x, Safe Address=%08x\n.", config, address);
+        *buffer++
+            = config;
 
-    gcmkONERROR(gckCOMMAND_Execute(command, configSize));
+        /* Arm the PE-FE Semaphore. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
 
-    if (FromPower == gcvFALSE)
-    {
-        /* Acquire global semaphore to suspend power management until MMU
-        ** is enabled. And acquired it before gckCOMMAND_ExitCommit to
-        ** make sure GPU keeps ON. */
-        gcmkONERROR(
-            gckOS_AcquireSemaphore(Hardware->os, Hardware->globalSemaphore));
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
 
-        acquired = gcvTRUE;
-    }
+        /* STALL FE until PE is done flushing. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
 
-    /* Release the command queue. */
-    gcmkONERROR(gckCOMMAND_ExitCommit(command, FromPower));
-    commitEntered = gcvFALSE;
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
 
-    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
-        "call gckCOMMAND_Stall to make sure the config is done.\n ");
+        /* Event 29. */
+        *buffer++
+            = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+            | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (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)));
 
-    gcmkONERROR(gckCOMMAND_Stall(command, FromPower));
+        event = ((((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)));
+        event = ((((gctUINT32) (event)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (29) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
 
-    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
-        "Enable MMU through GCREG_MMU_CONTROL.");
+        *buffer++
+            = event;
 
-    /* Enable MMU. */
-    gcmkONERROR(
-        gckOS_WriteRegisterEx(Hardware->os,
-                              Hardware->core,
-                              0x0018C,
-                              ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (Enable) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))));
+        /* Append END. */
+        *buffer++
+           = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+    }
 
-    if (FromPower == gcvFALSE)
+    if (Bytes != gcvNULL)
     {
-        /* Relase global semaphore. */
-        gcmkVERIFY_OK(
-            gckOS_ReleaseSemaphore(Hardware->os, Hardware->globalSemaphore));
-
-        acquired = gcvFALSE;
+        *Bytes = bytesAligned;
     }
 
-    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
-        "call gckCOMMAND_Stall to check MMU available.\n");
-
-    gcmkONERROR(gckCOMMAND_Stall(command, FromPower));
-
-    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
-        "The MMU is available.\n");
-
-    /* Return the status. */
-    gcmkFOOTER_NO();
-    return status;
-
-OnError:
-    if (commitEntered)
+    if (WaitLinkOffset != gcvNULL)
     {
-        /* Release the command queue mutex. */
-        gcmkVERIFY_OK(gckCOMMAND_ExitCommit(Hardware->kernel->command,
-                                            FromPower));
+        *WaitLinkOffset = bytes - 4 * 4;
     }
 
-    if (acquired)
+    if (WaitLinkBytes != gcvNULL)
     {
-        gcmkVERIFY_OK(
-            gckOS_ReleaseSemaphore(Hardware->os, Hardware->globalSemaphore));
+#if gcdMULTI_GPU
+        *WaitLinkBytes = 40;
+#else
+        *WaitLinkBytes = 4 * 4;
+#endif
     }
 
-    /* Return the status. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
     gcmkFOOTER();
     return status;
 }
+#endif
 
 /*******************************************************************************
 **
@@ -3608,6 +4021,7 @@ gckHARDWARE_GetIdle(
     gceSTATUS status;
     gctUINT32 idle = 0;
     gctINT retry, poll, pollCount;
+    gctUINT32 address;
 
     gcmkHEADER_ARG("Hardware=0x%x Wait=%d", Hardware, Wait);
 
@@ -3629,8 +4043,17 @@ gckHARDWARE_GetIdle(
             gcmkONERROR(
                 gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00004, &idle));
 
+            /* Read the current FE address. */
+            gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                             Hardware->core,
+                                             0x00664,
+                                             &address));
+
+
             /* 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)))))) ))
+            if (_IsGPUIdle(idle)
+             && (address == Hardware->lastEnd + 8)
+             )
             {
                 /* FE is idle. */
                 break;
@@ -3638,7 +4061,7 @@ gckHARDWARE_GetIdle(
         }
 
         /* 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)))))) ))
+        if (Wait && !_IsGPUIdle(idle))
         {
             /* Wait a little. */
             gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
@@ -3656,6 +4079,13 @@ gckHARDWARE_GetIdle(
     /* Return idle to caller. */
     *Data = idle;
 
+#if defined(EMULATOR)
+    /* Wait a little while until CModel FE gets END.
+     * END is supposed to be appended by caller.
+     */
+    gckOS_Delay(gcvNULL, 100);
+#endif
+
     /* Success. */
     gcmkFOOTER_ARG("*Data=0x%08x", *Data);
     return gcvSTATUS_OK;
@@ -3672,15 +4102,17 @@ gckHARDWARE_Flush(
     IN gckHARDWARE Hardware,
     IN gceKERNEL_FLUSH Flush,
     IN gctPOINTER Logical,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     )
 {
     gctUINT32 pipe;
     gctUINT32 flush = 0;
+    gctBOOL flushTileStatus;
     gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
     gceSTATUS status;
-    gctBOOL fcFlushStall;
-    gctUINT32 reserveBytes = 8;
+    gctUINT32 reserveBytes
+        /* Semaphore/Stall */
+        = 4 * gcmSIZEOF(gctUINT32);
 
     gcmkHEADER_ARG("Hardware=0x%x Flush=0x%x Logical=0x%x *Bytes=%lu",
                    Hardware, Flush, Logical, gcmOPT_VALUE(Bytes));
@@ -3691,15 +4123,8 @@ gckHARDWARE_Flush(
     /* Get current pipe. */
     pipe = Hardware->kernel->command->pipeSelect;
 
-    fcFlushStall
-        = ((((gctUINT32) (Hardware->identity.chipMinorFeatures1)) >> (0 ? 31:31) & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))))
-        && (Flush == gcvFLUSH_ALL)
-        ;
-
-    if (fcFlushStall)
-    {
-        reserveBytes += 8;
-    }
+    /* Flush tile status cache. */
+    flushTileStatus = Flush & gcvFLUSH_TILE_STATUS;
 
     /* Flush 3D color cache. */
     if ((Flush & gcvFLUSH_COLOR) && (pipe == 0x0))
@@ -3717,7 +4142,6 @@ gckHARDWARE_Flush(
     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 |= ((((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)));
     }
 
     /* Flush 2D cache. */
@@ -3726,8 +4150,27 @@ gckHARDWARE_Flush(
         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)));
     }
 
+#if gcdMULTI_GPU
+    /* Flush L2 cache. */
+    if ((Flush & gcvFLUSH_L2) && (pipe == 0x0))
+    {
+        flush |= ((((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)));
+    }
+#endif
+
+    /* Determine reserve bytes. */
+    if (flush)
+    {
+        reserveBytes += 2 * gcmSIZEOF(gctUINT32);
+    }
+
+    if (flushTileStatus)
+    {
+        reserveBytes += 2 * gcmSIZEOF(gctUINT32);
+    }
+
     /* See if there is a valid flush. */
-    if (flush == 0)
+    if ((flush == 0) && (flushTileStatus == gcvFALSE))
     {
         if (Bytes != gcvNULL)
         {
@@ -3747,29 +4190,52 @@ gckHARDWARE_Flush(
                 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)));
+            if (flush)
+            {
+                /* Append LOAD_STATE to AQFlush. */
+                *logical++
+                    = ((((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;
+                *logical++
+                    = flush;
 
-            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
-                           "0x%x: FLUSH 0x%x", logical, flush);
+                gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+                        "0x%x: FLUSH 0x%x", logical - 1, flush);
+            }
 
-            if (fcFlushStall)
+            if (flushTileStatus)
             {
-                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) (0x0594) & ((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] = ((((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)));
+                *logical++
+                    = ((((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) (0x0594) & ((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++
+                    = ((((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)));
 
                 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
-                               "0x%x: FLUSH 0x%x", logical + 3, logical[3]);
+                               "0x%x: FLUSH TILE STATUS 0x%x", logical - 1, logical[-1]);
             }
 
+            /* Semaphore. */
+            *logical++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+            *logical++
+                = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+                | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+            /* Stall. */
+            *logical++
+                = ((((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++
+                = ((((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) (0x05 & ((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)));
         }
 
         if (Bytes != gcvNULL)
@@ -3796,7 +4262,7 @@ gckHARDWARE_SetFastClear(
     IN gctINT Compression
     )
 {
-#ifndef VIVANTE_NO_3D
+#if gcdENABLE_3D
     gctUINT32 debug;
     gceSTATUS status;
 
@@ -3896,6 +4362,7 @@ _PowerEnum(gceCHIPPOWERSTATE State)
         gcmSTRING(gcvPOWER_SUSPEND_BROADCAST),
         gcmSTRING(gcvPOWER_OFF_BROADCAST),
         gcmSTRING(gcvPOWER_OFF_RECOVERY),
+        gcmSTRING(gcvPOWER_OFF_TIMEOUT),
         gcmSTRING(gcvPOWER_ON_AUTO)
     };
 
@@ -3934,7 +4401,7 @@ gckHARDWARE_SetPowerManagementState(
     gckOS os;
     gctUINT flag, clock;
     gctPOINTER buffer;
-    gctSIZE_T bytes, requested;
+    gctUINT32 bytes, requested;
     gctBOOL acquired = gcvFALSE;
     gctBOOL mutexAcquired = gcvFALSE;
     gctBOOL stall = gcvTRUE;
@@ -4060,12 +4527,6 @@ gckHARDWARE_SetPowerManagementState(
     command = Hardware->kernel->command;
     gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
 
-    if (Hardware->powerManagement == gcvFALSE)
-    {
-        gcmkFOOTER_NO();
-        return gcvSTATUS_OK;
-    }
-
     /* Start profiler. */
     gcmkPROFILE_INIT(freq, time);
 
@@ -4136,6 +4597,14 @@ gckHARDWARE_SetPowerManagementState(
         break;
     }
 
+    if (Hardware->powerManagement == gcvFALSE
+     && State != gcvPOWER_ON
+    )
+    {
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
     /* Get current process and thread IDs. */
     gcmkONERROR(gckOS_GetProcessID(&process));
     gcmkONERROR(gckOS_GetThreadID(&thread));
@@ -4156,30 +4625,14 @@ gckHARDWARE_SetPowerManagementState(
                 gcmkFOOTER_NO();
                 return gcvSTATUS_OK;
             }
-            else if (State == gcvPOWER_IDLE || State == gcvPOWER_SUSPEND)
+            else if (State != gcvPOWER_ON)
             {
                 /* Called from IST,
                 ** so waiting here will cause deadlock,
                 ** if lock holder call gckCOMMAND_Stall() */
-                gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
-            }
-#if gcdPOWEROFF_TIMEOUT
-            else if(State == gcvPOWER_OFF && timeout == gcvTRUE)
-            {
-                /*
-                ** try to aqcuire the mutex with more milliseconds,
-                ** flush_delayed_work should be running with timeout,
-                ** so waiting here will cause deadlock */
-                status = gckOS_AcquireMutex(os, Hardware->powerMutex, gcdPOWEROFF_TIMEOUT);
-
-                if (status == gcvSTATUS_TIMEOUT)
-                {
-                    gckOS_Print("GPU Timer deadlock, exit by timeout!!!!\n");
-
-                    gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
-                }
+                status = gcvSTATUS_INVALID_REQUEST;
+                goto OnError;
             }
-#endif
             else
             {
                 /* Acquire the power mutex. */
@@ -4215,16 +4668,16 @@ gckHARDWARE_SetPowerManagementState(
 
     if (State == gcvPOWER_SUSPEND && Hardware->chipPowerState == gcvPOWER_OFF && broadcast)
     {
-#if gcdPOWER_SUSNPEND_WHEN_IDLE
-       /* Do nothing */
+#if gcdPOWER_SUSPEND_WHEN_IDLE
+    /* Do nothing */
 
-       /* Release the power mutex. */
+        /* Release the power mutex. */
         gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
 
-               gcmkFOOTER_NO();
+           gcmkFOOTER_NO();
         return gcvSTATUS_OK;
 #else
-       /* Clock should be on when switch power from off to suspend */
+    /* Clock should be on when switch power from off to suspend */
         clock = ((((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))) |
@@ -4481,7 +4934,11 @@ gckHARDWARE_SetPowerManagementState(
             commitEntered = gcvFALSE;
 
             /* Wait to finish all commands. */
+#if gcdMULTI_GPU
+            gcmkONERROR(gckCOMMAND_Stall(command, gcvTRUE, gcvCORE_3D_ALL_MASK));
+#else
             gcmkONERROR(gckCOMMAND_Stall(command, gcvTRUE));
+#endif
         }
     }
 
@@ -4561,7 +5018,7 @@ gckHARDWARE_SetPowerManagementState(
         if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
         {
             if (Hardware->identity.chipModel == gcv4000
-            && Hardware->identity.chipRevision == 0x5208)
+            && ((Hardware->identity.chipRevision == 0x5208) || (Hardware->identity.chipRevision == 0x5222)))
             {
                 clock &= ~2U;
             }
@@ -4642,20 +5099,6 @@ gckHARDWARE_SetPowerManagementState(
             gcmkONERROR(Hardware->startIsr(Hardware->isrContext));
             isrStarted = gcvTRUE;
         }
-
-        /* Set NEW MMU. */
-        if (Hardware->mmuVersion != 0 && configMmu)
-        {
-            gcmkONERROR(
-                    gckHARDWARE_SetMMUv2(
-                        Hardware,
-                        gcvTRUE,
-                        Hardware->kernel->mmu->mtlbLogical,
-                        gcvMMU_MODE_4K,
-                        (gctUINT8_PTR)Hardware->kernel->mmu->mtlbLogical + gcdMMU_MTLB_SIZE,
-                        gcvTRUE
-                        ));
-        }
     }
 
     /* Get time until started. */
@@ -4817,7 +5260,6 @@ gckHARDWARE_QueryPowerManagementState(
 **  gckHARDWARE_SetPowerManagement
 **
 **  Configure GPU power management function.
-**  Only used in driver initialization stage.
 **
 **  INPUT:
 **
@@ -4838,14 +5280,53 @@ gckHARDWARE_SetPowerManagement(
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+    if(!Hardware->powerManagementLock)
+    {
+        gcmkVERIFY_OK(
+            gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE));
 
-    Hardware->powerManagement = PowerManagement;
+        Hardware->powerManagement = PowerManagement;
 
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+    }
     /* Success. */
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 }
 
+/*******************************************************************************
+**
+**  gckHARDWARE_SetPowerManagementLock
+**
+**  Disable dynamic GPU power management switch.
+**  Only used in driver initialization stage.
+**
+**  INPUT:
+**
+**      gckHARDWARE Harwdare
+**          Pointer to an gckHARDWARE object.
+**
+**      gctBOOL Lock
+**          Power Mangement Lock State.
+**
+*/
+gceSTATUS
+gckHARDWARE_SetPowerManagementLock(
+    IN gckHARDWARE Hardware,
+    IN gctBOOL Lock
+    )
+{
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+    Hardware->powerManagementLock = Lock;
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
 /*******************************************************************************
 **
 **  gckHARDWARE_SetGpuProfiler
@@ -4873,6 +5354,29 @@ gckHARDWARE_SetGpuProfiler(
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
 
+    if (GpuProfiler == gcvTRUE)
+    {
+        gctUINT32 data = 0;
+
+        /* Need to disable clock gating when doing profiling. */
+        gcmkVERIFY_OK(
+            gckOS_ReadRegisterEx(Hardware->os,
+                                 Hardware->core,
+                                 Hardware->powerBaseAddress +
+                                 0x00100,
+                                 &data));
+
+        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) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+
+        gcmkVERIFY_OK(
+            gckOS_WriteRegisterEx(Hardware->os,
+                                  Hardware->core,
+                                  Hardware->powerBaseAddress
+                                  + 0x00100,
+                                  data));
+    }
+
     Hardware->gpuProfiler = GpuProfiler;
 
     /* Success. */
@@ -4903,7 +5407,7 @@ gckHARDWARE_SetFscaleValue(
 
     if (Hardware->chipPowerState == gcvPOWER_ON)
     {
-               gctUINT32 data;
+        gctUINT32 data;
 
         gcmkONERROR(
             gckOS_ReadRegisterEx(Hardware->os,
@@ -4979,15 +5483,25 @@ gckHARDWARE_GetFscaleValue(
     )
 {
     *FscaleValue = Hardware->powerOnFscaleVal;
-    if ((gpu3DMinClock > 0) && (gpu3DMinClock <= 64) && (Hardware->core == gcvCORE_MAJOR))
-        *MinFscaleValue = gpu3DMinClock;
-    else
-        *MinFscaleValue = 1;
+    *MinFscaleValue = Hardware->minFscaleValue;
     *MaxFscaleValue = 64;
 
     return gcvSTATUS_OK;
 }
 
+gceSTATUS
+gckHARDWARE_SetMinFscaleValue(
+    IN gckHARDWARE Hardware,
+    IN gctUINT MinFscaleValue
+    )
+{
+    if (MinFscaleValue >= 1 && MinFscaleValue <= 64)
+    {
+        Hardware->minFscaleValue = MinFscaleValue;
+    }
+
+    return gcvSTATUS_OK;
+}
 #endif
 
 #if gcdPOWEROFF_TIMEOUT
@@ -5029,6 +5543,16 @@ gckHARDWARE_QueryIdle(
 {
     gceSTATUS status;
     gctUINT32 idle, address;
+    gctBOOL   isIdle;
+#if gcdMULTI_GPU > 1
+    gctUINT32 idle3D1 = 0;
+    gctUINT32 address3D1;
+    gctBOOL   isIdle3D1 = gcvFALSE;
+#endif
+
+#if gcdINTERRUPT_STATISTIC
+    gctINT32 pendingInterrupt;
+#endif
 
     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
 
@@ -5039,7 +5563,10 @@ gckHARDWARE_QueryIdle(
     /* We are idle when the power is not ON. */
     if (Hardware->chipPowerState != gcvPOWER_ON)
     {
-        *IsIdle = gcvTRUE;
+        isIdle = gcvTRUE;
+#if gcdMULTI_GPU > 1
+        isIdle3D1 = gcvTRUE;
+#endif
     }
 
     else
@@ -5048,6 +5575,18 @@ gckHARDWARE_QueryIdle(
         gcmkONERROR(
             gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00004, &idle));
 
+#if gcdMULTI_GPU > 1
+        if (Hardware->core == gcvCORE_MAJOR)
+        {
+            gcmkONERROR(
+                gckOS_ReadRegisterByCoreId(Hardware->os,
+                                           Hardware->core,
+                                           gcvCORE_3D_1_ID,
+                                           0x00004,
+                                           &idle3D1));
+        }
+#endif
+
         /* 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)
@@ -5059,11 +5598,15 @@ gckHARDWARE_QueryIdle(
         )
         {
             /* Something is busy. */
-            *IsIdle = gcvFALSE;
+            isIdle = gcvFALSE;
         }
 
         else
         {
+#if gcdSECURITY
+            isIdle = gcvTRUE;
+            address = 0;
+#else
             /* Read the current FE address. */
             gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
                                              Hardware->core,
@@ -5072,18 +5615,91 @@ gckHARDWARE_QueryIdle(
 
             /* Test if address is inside the last WAIT/LINK sequence. */
             if ((address >= Hardware->lastWaitLink)
+#if gcdMULTI_GPU
+            &&  (address <= Hardware->lastWaitLink + 40)
+#else
             &&  (address <= Hardware->lastWaitLink + 16)
+#endif
             )
             {
                 /* FE is in last WAIT/LINK and the pipe is idle. */
-                *IsIdle = gcvTRUE;
+                isIdle = gcvTRUE;
             }
             else
             {
                 /* FE is not in WAIT/LINK yet. */
-                *IsIdle = gcvFALSE;
+                isIdle = gcvFALSE;
+            }
+#endif
+        }
+
+#if gcdMULTI_GPU > 1
+        if (Hardware->core == gcvCORE_MAJOR)
+        {
+            /* Pipe must be idle. */
+            if (((((((gctUINT32) (idle3D1)) >> (0 ? 1:1)) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1)))))) ) != 1)
+                ||  ((((((gctUINT32) (idle3D1)) >> (0 ? 3:3)) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) ) != 1)
+                ||  ((((((gctUINT32) (idle3D1)) >> (0 ? 4:4)) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1)))))) ) != 1)
+                ||  ((((((gctUINT32) (idle3D1)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) ) != 1)
+                ||  ((((((gctUINT32) (idle3D1)) >> (0 ? 6:6)) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1)))))) ) != 1)
+                ||  ((((((gctUINT32) (idle3D1)) >> (0 ? 7:7)) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1)))))) ) != 1)
+                ||  ((((((gctUINT32) (idle3D1)) >> (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. */
+                isIdle3D1 = gcvFALSE;
+            }
+
+            else
+            {
+                /* Read the current FE address. */
+                gcmkONERROR(gckOS_ReadRegisterByCoreId(Hardware->os,
+                                                       Hardware->core,
+                                                       gcvCORE_3D_1_ID,
+                                                       0x00664,
+                                                       &address3D1));
+
+                /* Test if address is inside the last WAIT/LINK sequence. */
+                if ((address3D1 >= Hardware->lastWaitLink)
+                    &&  (address3D1 <= Hardware->lastWaitLink + 40)
+                )
+                {
+                    /* FE is in last WAIT/LINK and the pipe is idle. */
+                    isIdle3D1 = gcvTRUE;
+                }
+                else
+                {
+                    /* FE is not in WAIT/LINK yet. */
+                    isIdle3D1 = gcvFALSE;
+                }
             }
         }
+#endif
+
+    }
+
+#if gcdINTERRUPT_STATISTIC
+    gcmkONERROR(gckOS_AtomGet(
+        Hardware->os,
+        Hardware->kernel->eventObj->interruptCount,
+        &pendingInterrupt
+        ));
+
+    if (pendingInterrupt)
+    {
+        isIdle = gcvFALSE;
+    }
+#endif
+
+#if gcdMULTI_GPU > 1
+    if (Hardware->core == gcvCORE_MAJOR)
+    {
+        *IsIdle = (isIdle & isIdle3D1);
+    }
+    else
+#endif
+    {
+        *IsIdle = isIdle;
     }
 
     /* Success. */
@@ -5214,7 +5830,7 @@ OnError:
 gceSTATUS
 gckHARDWARE_QueryProfileRegisters(
     IN gckHARDWARE Hardware,
-    IN gctBOOL   Reset,
+    IN gctBOOL Reset,
     OUT gcsPROFILER_COUNTERS * Counters
     )
 {
@@ -5244,7 +5860,7 @@ gckHARDWARE_QueryProfileRegisters(
 
     gcmkONERROR(
         gckOS_ReadRegisterEx(Hardware->os,
-                            Hardware->core,
+                             Hardware->core,
                              0x0007C,
                              &profiler->gpuIdleCyclesCounter));
 
@@ -5262,14 +5878,14 @@ gckHARDWARE_QueryProfileRegisters(
     profiler->pe_pixel_count_drawn_by_color_pipe = 0;
     profiler->pe_pixel_count_drawn_by_depth_pipe = 0;
 
-     /* Walk through all avaiable pixel pipes. */
+    /* Walk through all avaiable pixel pipes. */
     for (i = 0; i < Hardware->identity.pixelPipes; ++i)
     {
         /* Select proper pipe. */
         gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
-                                           Hardware->core,
-                                           0x00000,
-                                           ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20)))));
+                                          Hardware->core,
+                                          0x00000,
+                                          ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20)))));
 
         /* BW */
         gcmkONERROR(
@@ -5304,20 +5920,18 @@ gckHARDWARE_QueryProfileRegisters(
                                       0x00000,
                                       clock));
 
-    if(Reset){
-            /* Reset counters. */
-            gcmkONERROR(
-                gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
-            gcmkONERROR(
-                gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 0));
-            gcmkONERROR(
-                gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00438, 0));
-            gcmkONERROR(
-                gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00078, 0));
-            gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
+    /* Reset counters. */
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 0));
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00438, 0));
+    gcmkONERROR(
+        gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00078, 0));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
 ));
-    }
 
     /* SH */
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
@@ -5336,9 +5950,9 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profile
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_branch_inst_counter));
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_texld_inst_counter));
-    if(Reset){  gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24)))
-));}
+));
 
     /* PA */
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
@@ -5353,18 +5967,18 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profile
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_trivial_rejected_counter));
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_culled_counter));
-    if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
-));}
+));
 
     /* SE */
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_triangle_count));
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_lines_count));
-    if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))
-));}
+));
 
     /* RA */
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
@@ -5379,9 +5993,9 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profile
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_pipe_cache_miss_counter));
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_prefetch_cache_miss_counter));
-    if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
-));}
+));
 
     /* TX */
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
@@ -5402,9 +6016,9 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profile
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_hit_texel_count));
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_texel_count));
-    if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24)))
-));}
+));
 
     /* MC */
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
@@ -5413,9 +6027,9 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profile
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_IP));
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_write_req_8B_from_pipeline));
-    if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
-));}
+));
 
     /* HI */
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
@@ -5424,9 +6038,9 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profile
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_request_stalled));
     gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_data_stalled));
-    if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478,   ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))
-));}
+));
 
     /* Success. */
     gcmkFOOTER_NO();
@@ -5439,6 +6053,7 @@ OnError:
 }
 #endif
 
+
 #if VIVANTE_PROFILER_CONTEXT
 #define gcmkUPDATE_PROFILE_DATA(data) \
     profilerHistroy->data += profiler->data
@@ -5446,7 +6061,7 @@ OnError:
 gceSTATUS
 gckHARDWARE_QueryContextProfile(
     IN gckHARDWARE Hardware,
-    IN gctBOOL   Reset,
+    IN gctBOOL Reset,
     IN gckCONTEXT Context,
     OUT gcsPROFILER_COUNTERS * Counters
     )
@@ -5470,13 +6085,10 @@ gckHARDWARE_QueryContextProfile(
         profiler, &Context->histroyProfiler, gcmSIZEOF(gcsPROFILER_COUNTERS)
         ));
 
-    if (Reset)
-    {
-        /* Reset counters. */
-        gcmkVERIFY_OK(gckOS_ZeroMemory(
-            &Context->histroyProfiler, gcmSIZEOF(gcsPROFILER_COUNTERS)
-            ));
-    }
+    /* Reset counters. */
+    gcmkVERIFY_OK(gckOS_ZeroMemory(
+        &Context->histroyProfiler, gcmSIZEOF(gcsPROFILER_COUNTERS)
+        ));
 
     gcmkVERIFY_OK(gckOS_ReleaseMutex(
         command->os, command->mutexContextSeq
@@ -5492,6 +6104,21 @@ OnError:
     return status;
 }
 
+static gctUINT32
+CalcDelta(
+    IN gctUINT32 new,
+    IN gctUINT32 old
+    )
+{
+    if (new >= old)
+    {
+        return new - old;
+    }
+    else
+    {
+        return (gctUINT32)((gctUINT64)new + 0x100000000ll - old);
+    }
+}
 
 gceSTATUS
 gckHARDWARE_UpdateContextProfile(
@@ -5503,7 +6130,7 @@ gckHARDWARE_UpdateContextProfile(
     gcsPROFILER_COUNTERS * profiler = &Context->latestProfiler;
     gcsPROFILER_COUNTERS * profilerHistroy = &Context->histroyProfiler;
     gctUINT i, clock;
-    gctUINT32 colorKilled, colorDrawn, depthKilled, depthDrawn;
+    gctUINT32 colorKilled = 0, colorDrawn = 0, depthKilled = 0, depthDrawn = 0;
     gctUINT32 totalRead, totalWrite;
     gceCHIPMODEL chipModel;
     gctUINT32 chipRevision;
@@ -5607,8 +6234,6 @@ gckHARDWARE_UpdateContextProfile(
                                       clock));
 
 
-
-
     /* Reset counters. */
     gcmkONERROR(
         gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
@@ -5628,7 +6253,7 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profile
     if (needResetShader)
     {
         temp = profiler->ps_inst_counter;
-        profiler->ps_inst_counter -= Context->prevPSInstCount;
+        profiler->ps_inst_counter = CalcDelta(temp, Context->prevPSInstCount);
         Context->prevPSInstCount = temp;
     }
     gcmkUPDATE_PROFILE_DATA(ps_inst_counter);
@@ -5638,7 +6263,7 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profile
     if (needResetShader)
     {
         temp = profiler->rendered_pixel_counter;
-        profiler->rendered_pixel_counter -= Context->prevPSPixelCount;
+        profiler->rendered_pixel_counter = CalcDelta(temp, Context->prevPSPixelCount);
         Context->prevPSPixelCount = temp;
     }
     gcmkUPDATE_PROFILE_DATA(rendered_pixel_counter);
@@ -5648,7 +6273,7 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profile
     if (needResetShader)
     {
         temp = profiler->vs_inst_counter;
-        profiler->vs_inst_counter -= Context->prevVSInstCount;
+        profiler->vs_inst_counter = CalcDelta(temp, Context->prevVSInstCount);
         Context->prevVSInstCount = temp;
     }
     gcmkUPDATE_PROFILE_DATA(vs_inst_counter);
@@ -5658,7 +6283,7 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profile
     if (needResetShader)
     {
         temp = profiler->rendered_vertice_counter;
-        profiler->rendered_vertice_counter -= Context->prevVSVertexCount;
+        profiler->rendered_vertice_counter = CalcDelta(temp, Context->prevVSVertexCount);
         Context->prevVSVertexCount = temp;
     }
     gcmkUPDATE_PROFILE_DATA(rendered_vertice_counter);
@@ -5668,7 +6293,7 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profile
     if (needResetShader)
     {
         temp = profiler->vtx_branch_inst_counter;
-        profiler->vtx_branch_inst_counter -= Context->prevVSBranchInstCount;
+        profiler->vtx_branch_inst_counter = CalcDelta(temp, Context->prevVSBranchInstCount);
         Context->prevVSBranchInstCount = temp;
     }
     gcmkUPDATE_PROFILE_DATA(vtx_branch_inst_counter);
@@ -5678,7 +6303,7 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profile
     if (needResetShader)
     {
         temp = profiler->vtx_texld_inst_counter;
-        profiler->vtx_texld_inst_counter -= Context->prevVSTexInstCount;
+        profiler->vtx_texld_inst_counter = CalcDelta(temp, Context->prevVSTexInstCount);
         Context->prevVSTexInstCount = temp;
     }
     gcmkUPDATE_PROFILE_DATA(vtx_texld_inst_counter);
@@ -5688,7 +6313,7 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profile
     if (needResetShader)
     {
         temp = profiler->pxl_branch_inst_counter;
-        profiler->pxl_branch_inst_counter -= Context->prevPSBranchInstCount;
+        profiler->pxl_branch_inst_counter = CalcDelta(temp, Context->prevPSBranchInstCount);
         Context->prevPSBranchInstCount = temp;
     }
     gcmkUPDATE_PROFILE_DATA(pxl_branch_inst_counter);
@@ -5698,7 +6323,7 @@ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profile
     if (needResetShader)
     {
         temp = profiler->pxl_texld_inst_counter;
-        profiler->pxl_texld_inst_counter -= Context->prevPSTexInstCount;
+        profiler->pxl_texld_inst_counter = CalcDelta(temp, Context->prevPSTexInstCount);
         Context->prevPSTexInstCount = temp;
     }
     gcmkUPDATE_PROFILE_DATA(pxl_texld_inst_counter);
@@ -5835,6 +6460,34 @@ OnError:
 }
 #endif
 
+
+#if VIVANTE_PROFILER_NEW
+gceSTATUS
+gckHARDWARE_InitProfiler(
+    IN gckHARDWARE Hardware
+    )
+{
+    gceSTATUS status;
+    gctUINT32 control;
+
+    gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+    gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+                                     Hardware->core,
+                                     0x00000,
+                                     &control));
+    /* Enable debug register. */
+    gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+                                      Hardware->core,
+                                      0x00000,
+                                      ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11)))));
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+#endif
+
 static gceSTATUS
 _ResetGPU(
     IN gckHARDWARE Hardware,
@@ -5927,6 +6580,22 @@ _ResetGPU(
             continue;
         }
 
+#if gcdMULTI_GPU > 1
+        if (Core == gcvCORE_MAJOR)
+        {
+            /* Read idle register. */
+            gcmkONERROR(gckOS_ReadRegisterByCoreId(Os,
+                                                   Core,
+                                                   gcvCORE_3D_1_ID,
+                                                   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;
+            }
+        }
+#endif
         /* Read reset register. */
         gcmkONERROR(gckOS_ReadRegisterEx(Os,
                                          Core,
@@ -5940,6 +6609,24 @@ _ResetGPU(
             continue;
         }
 
+#if gcdMULTI_GPU > 1
+        if (Core == gcvCORE_MAJOR)
+        {
+            /* Read reset register. */
+            gcmkONERROR(gckOS_ReadRegisterByCoreId(Os,
+                                                   Core,
+                                                   gcvCORE_3D_1_ID,
+                                                   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;
+            }
+        }
+#endif
         /* GPU is idle. */
         break;
     }
@@ -5959,97 +6646,42 @@ gckHARDWARE_Reset(
     )
 {
     gceSTATUS status;
-    gckCOMMAND command;
-    gctBOOL acquired = gcvFALSE;
-    gctBOOL mutexAcquired = gcvFALSE;
-    gctUINT32 process, thread;
 
     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
     gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
-    command = Hardware->kernel->command;
-    gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
-
-    if (Hardware->identity.chipRevision < 0x4600)
-    {
-        /* Not supported - we need the isolation bit. */
-        gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
-    }
-
-    status = gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, 0);
-    if (status == gcvSTATUS_TIMEOUT)
-    {
-        gcmkONERROR(gckOS_GetProcessID(&process));
-        gcmkONERROR(gckOS_GetThreadID(&thread));
-
-        if ((Hardware->powerProcess == process)
-        &&  (Hardware->powerThread  == thread))
-        {
-            /* No way to recovery from a error in power management. */
-            gcmkFOOTER_NO();
-            return gcvSTATUS_OK;
-        }
-    }
-    else
-    {
-        mutexAcquired = gcvTRUE;
-    }
-
-    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, gcvTRUE));
-    }
-
-    /* Stop isr, we will start it again when power on GPU. */
-    if (Hardware->stopIsr)
-    {
-        gcmkONERROR(Hardware->stopIsr(Hardware->isrContext));
-    }
 
     /* Hardware reset. */
     status = gckOS_ResetGPU(Hardware->os, Hardware->core);
 
     if (gcmIS_ERROR(status))
     {
+        if (Hardware->identity.chipRevision < 0x4600)
+        {
+            /* Not supported - we need the isolation bit. */
+            gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+        }
+
         /* Soft reset. */
         gcmkONERROR(_ResetGPU(Hardware, Hardware->os, Hardware->core));
     }
 
-    /* Force an OFF to ON power switch. */
-    Hardware->chipPowerState = gcvPOWER_OFF;
+    /* Initialize hardware. */
+    gcmkONERROR(gckHARDWARE_InitializeHardware(Hardware));
 
-    gcmkONERROR(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
-    mutexAcquired = gcvFALSE;
+    /* Jump to address into which GPU should run if it doesn't stuck. */
+    gcmkONERROR(gckHARDWARE_Execute(Hardware, Hardware->kernel->restoreAddress, 16));
+
+    gcmkPRINT("[galcore]: recovery done");
 
     /* Success. */
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 
 OnError:
-    if (acquired)
-    {
-        /* Release the power management semaphore. */
-        gcmkVERIFY_OK(
-            gckOS_ReleaseSemaphore(Hardware->os, command->powerSemaphore));
-    }
-
-    if (mutexAcquired)
-    {
-        gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
-    }
+    gcmkPRINT("[galcore]: Hardware not reset successfully, give up");
 
     /* Return the error. */
     gcmkFOOTER();
@@ -6110,7 +6742,7 @@ gckHARDWARE_NeedBaseAddress(
     /* Make sure this is a load state. */
     if (((((gctUINT32) (State)) >> (0 ? 31:27) & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))))
     {
-#ifndef VIVANTE_NO_3D
+#if gcdENABLE_3D
         /* Get the state address. */
         switch ((((((gctUINT32) (State)) >> (0 ? 15:0)) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1)))))) ))
         {
@@ -6198,7 +6830,7 @@ gckHARDWARE_Compose(
     IN gctUINT8 EventID
     )
 {
-#ifndef VIVANTE_NO_3D
+#if gcdENABLE_3D
     gceSTATUS status;
     gctUINT32_PTR triggerState;
 
@@ -6227,7 +6859,7 @@ gckHARDWARE_Compose(
     /* Flush the cache for the wait/link. */
     gcmkONERROR(gckOS_CacheClean(
         Hardware->os, ProcessID, gcvNULL,
-        Physical, Logical, Offset + Size
+        (gctUINT32)Physical, Logical, Offset + Size
         ));
 #endif
 
@@ -6287,13 +6919,50 @@ gckHARDWARE_IsFeatureAvailable(
             );*/
         available = gcvFALSE;
         break;
+
     case gcvFEATURE_MC20:
         available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures)) >> (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)))))));
         break;
+
+    case gcvFEATURE_EARLY_Z:
+        available = ((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 16:16) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) == (0x0 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))));
+        break;
+
+    case gcvFEATURE_HZ:
+        available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures)) >> (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)))))));
+        break;
+
+    case gcvFEATURE_NEW_HZ:
+        available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 26:26) & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))));
+        break;
+
+    case gcvFEATURE_FAST_MSAA:
+        available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 8:8) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))));
+        break;
+
+    case gcvFEATURE_SMALL_MSAA:
+        available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures4)) >> (0 ? 18:18) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))));
+        break;
+
     case gcvFEATURE_DYNAMIC_FREQUENCY_SCALING:
         /* This feature doesn't apply for 2D cores. */
         available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures2)) >> (0 ? 14:14) & ((gctUINT32) ((((1 ? 14:14) - (0 ? 14:14) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 14:14) - (0 ? 14:14) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 14:14) - (0 ? 14:14) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 14:14) - (0 ? 14:14) + 1)))))))
             &&      ((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 2:2) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))));
+
+        if (Hardware->identity.chipModel == gcv1000 &&
+            (Hardware->identity.chipRevision == 0x5039 ||
+            Hardware->identity.chipRevision == 0x5040))
+        {
+            available = gcvFALSE;
+        }
+        break;
+
+    case gcvFEATURE_ACE:
+        available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 18:18) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))));
+        break;
+
+    case gcvFEATURE_HALTI2:
+        available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures4)) >> (0 ? 16:16) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))));
         break;
 
     case gcvFEATURE_PIPE_2D:
@@ -6301,15 +6970,15 @@ gckHARDWARE_IsFeatureAvailable(
         break;
 
     case gcvFEATURE_PIPE_3D:
-#ifndef VIVANTE_NO_3D
+#if gcdENABLE_3D
         available = ((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 2:2) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) == (0x1  & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))));
 #else
         available = gcvFALSE;
 #endif
         break;
 
-    case gcvFEATURE_HALTI2:
-        available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures4)) >> (0 ? 16:16) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))));
+    case gcvFEATURE_FC_FLUSH_STALL:
+        available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures1)) >> (0 ? 31:31) & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))));
         break;
 
     default:
@@ -6318,8 +6987,8 @@ gckHARDWARE_IsFeatureAvailable(
     }
 
     /* Return result. */
-    gcmkFOOTER_ARG("%d", available ? gcvSTATUS_TRUE : gcvSTATUS_OK);
-    return available ? gcvSTATUS_TRUE : gcvSTATUS_OK;
+    gcmkFOOTER_ARG("%d", available ? gcvSTATUS_TRUE : gcvSTATUS_FALSE);
+    return available ? gcvSTATUS_TRUE : gcvSTATUS_FALSE;
 }
 
 /*******************************************************************************
@@ -6342,10 +7011,15 @@ gckHARDWARE_DumpMMUException(
     IN gckHARDWARE Hardware
     )
 {
-#if !gcdPOWER_SUSNPEND_WHEN_IDLE && !gcdPOWEROFF_TIMEOUT
-    gctUINT32 mmu, mmuStatus, address, i;
-#if gcdDEBUG
-    gctUINT32 mtlb, stlb, offset;
+    gctUINT32 mmu       = 0;
+    gctUINT32 mmuStatus = 0;
+    gctUINT32 address   = 0;
+    gctUINT32 i         = 0;
+    gctUINT32 mtlb      = 0;
+    gctUINT32 stlb      = 0;
+    gctUINT32 offset    = 0;
+#if gcdPROCESS_ADDRESS_SPACE
+    gcsDATABASE_PTR database;
 #endif
 
     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
@@ -6418,16 +7092,23 @@ gckHARDWARE_DumpMMUException(
 
         gckMMU_DumpPageTableEntry(Hardware->kernel->mmu, address);
 
+#if gcdPROCESS_ADDRESS_SPACE
+        for (i = 0; i < gcmCOUNTOF(Hardware->kernel->db->db); ++i)
+        {
+            for (database = Hardware->kernel->db->db[i];
+                    database != gcvNULL;
+                    database = database->next)
+            {
+                gcmkPRINT("    database [%d] :", database->processID);
+                gckMMU_DumpPageTableEntry(database->mmu, address);
+            }
+        }
+#endif
     }
 
-       gcmkFOOTER_NO();
-#else
-    /* If clock could be off automatically, we can't read mmu debug
-    ** register here; build driver with gcdPOWER_SUSPEND_WHEN_IDLE = 0
-    ** and gcdPOWEROFF_TIMEOUT = 0 to make it safe to read mmu register. */
-    gcmkPRINT("[galcore] %s(%d): MMU Exception!", __FUNCTION__, __LINE__);
-#endif
+    gckHARDWARE_DumpGPUState(Hardware);
 
+    gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 }
 
@@ -6507,16 +7188,16 @@ gckHARDWARE_DumpGPUState(
     };
 
     gceSTATUS status;
-    gckKERNEL kernel;
-    gctUINT32 idle, axi;
-    gctUINT32 dmaAddress1, dmaAddress2;
-    gctUINT32 dmaState1, dmaState2;
-    gctUINT32 dmaLow, dmaHigh;
-    gctUINT32 cmdState, cmdDmaState, cmdFetState;
-    gctUINT32 dmaReqState, calState, veReqState;
+    gckKERNEL kernel = gcvNULL;
+    gctUINT32 idle = 0, axi = 0;
+    gctUINT32 dmaAddress1 = 0, dmaAddress2 = 0;
+    gctUINT32 dmaState1 = 0, dmaState2 = 0;
+    gctUINT32 dmaLow = 0, dmaHigh = 0;
+    gctUINT32 cmdState = 0, cmdDmaState = 0, cmdFetState = 0;
+    gctUINT32 dmaReqState = 0, calState = 0, veReqState = 0;
     gctUINT i;
-    gctUINT pipe, pixelPipes;
-    gctUINT32 control, oldControl;
+    gctUINT pipe = 0, pixelPipes = 0;
+    gctUINT32 control = 0, oldControl = 0;
     gckOS os = Hardware->os;
     gceCORE core = Hardware->core;
 
@@ -6600,6 +7281,7 @@ gckHARDWARE_DumpGPUState(
             gcmkPRINT_N(4, "    0x%08X\n", dmaAddress2);
         }
     }
+
     gcmkPRINT_N(4, "  dmaLow   = 0x%08X\n", dmaLow);
     gcmkPRINT_N(4, "  dmaHigh  = 0x%08X\n", dmaHigh);
     gcmkPRINT_N(4, "  dmaState = 0x%08X\n", dmaState2);
@@ -6618,10 +7300,10 @@ gckHARDWARE_DumpGPUState(
         gcmkPRINT_N(4, "  Debug registers of pipe[%d]:\n", pipe);
 
         /* Switch pipe. */
-        gckOS_ReadRegisterEx(os, core, 0x0, &control);
+        gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x0, &control));
         control &= ~(0xF << 20);
         control |= (pipe << 20);
-        gckOS_WriteRegisterEx(os, core, 0x0, control);
+        gcmkONERROR(gckOS_WriteRegisterEx(os, core, 0x0, control));
 
         for (i = 0; i < gcmCOUNTOF(_dbgRegs); i += 1)
         {
@@ -6653,7 +7335,7 @@ gckHARDWARE_DumpGPUState(
     }
 
     /* Restore control. */
-    gckOS_WriteRegisterEx(os, core, 0x0, oldControl);
+    gcmkONERROR(gckOS_WriteRegisterEx(os, core, 0x0, oldControl));
 
     /* dump stack. */
     gckOS_DumpCallStack(os);
@@ -6665,8 +7347,6 @@ OnError:
     return status;
 }
 
-
-#if gcdFRAME_DB
 static gceSTATUS
 gckHARDWARE_ReadPerformanceRegister(
     IN gckHARDWARE Hardware,
@@ -6723,7 +7403,7 @@ gckHARDWARE_GetFrameInfo(
     gctUINT i, clock;
     gcsHAL_FRAME_INFO info;
 #if gcdFRAME_DB_RESET
-       gctUINT reset;
+    gctUINT reset;
 #endif
 
     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
@@ -7062,7 +7742,6 @@ OnError:
     gcmkFOOTER();
     return status;
 }
-#endif
 
 #if gcdDVFS
 #define READ_FROM_EATER1 0
@@ -7254,4 +7933,104 @@ OnError:
 }
 #endif
 
+/*******************************************************************************
+**
+**  gckHARDWARE_PrepareFunctions
+**
+**  Generate command buffer snippets which will be used by gckHARDWARE, by which
+**  gckHARDWARE can manipulate GPU by FE command without using gckCOMMAND to avoid
+**  race condition and deadlock.
+**
+**  Notice:
+**  1. Each snippet can only be executed when GPU is idle.
+**  2. Execution is triggered by AHB (0x658)
+**  3. Each snippet followed by END so software can sync with GPU by checking GPU
+**     idle
+**  4. It is transparent to gckCOMMAND command buffer.
+**
+**  Existing Snippets:
+**  1. MMU Configure
+**     For new MMU, after GPU is reset, FE execute this command sequence to enble MMU.
+*/
+gceSTATUS
+gckHARDWARE_PrepareFunctions(
+    gckHARDWARE Hardware
+    )
+{
+    gceSTATUS status;
+    gckOS os;
+    gctUINT32 offset = 0;
+    gctUINT32 mmuBytes;
+    gctUINT32 endBytes;
+    gctUINT8_PTR logical;
+
+    gcmkHEADER_ARG("%x", Hardware);
+
+    os = Hardware->os;
+
+    gcmkVERIFY_OK(gckOS_GetPageSize(os, &Hardware->functionBytes));
+
+    /* Allocate a command buffer. */
+    gcmkONERROR(gckOS_AllocateNonPagedMemory(
+        os,
+        gcvFALSE,
+        &Hardware->functionBytes,
+        &Hardware->functionPhysical,
+        &Hardware->functionLogical
+        ));
+
+    gcmkONERROR(gckOS_GetPhysicalAddress(
+        os,
+        Hardware->functionLogical,
+        &Hardware->functionAddress
+        ));
+
+    if (Hardware->mmuVersion > 0)
+    {
+        /* MMU configure command sequence. */
+        logical = (gctUINT8_PTR)Hardware->functionLogical + offset;
+
+        Hardware->functions[gcvHARDWARE_FUNCTION_MMU].address
+            = Hardware->functionAddress + offset;
+
+        gcmkONERROR(gckHARDWARE_SetMMUStates(
+            Hardware,
+            Hardware->kernel->mmu->mtlbLogical,
+            gcvMMU_MODE_4K,
+            (gctUINT8_PTR)Hardware->kernel->mmu->mtlbLogical + gcdMMU_MTLB_SIZE,
+            logical,
+            &mmuBytes
+            ));
+
+        offset += mmuBytes;
+
+        logical = (gctUINT8_PTR)Hardware->functionLogical + offset;
+
+        gcmkONERROR(gckHARDWARE_End(
+            Hardware,
+            gcvNULL,
+            &endBytes
+            ));
+
+        gcmkONERROR(gckHARDWARE_End(
+            Hardware,
+            logical,
+            &endBytes
+            ));
+
+        offset += endBytes;
+
+        Hardware->functions[gcvHARDWARE_FUNCTION_MMU].bytes = mmuBytes + endBytes;
+    }
+
+    gcmkASSERT(offset < Hardware->functionBytes);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
 
similarity index 74%
rename from drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h
rename to drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h
index 287ea600a2b3683f409eefe67e01fbf8d5648fca..2ffa1468b5e430cf5fc4ac471de299539e2a82d6 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 extern "C" {
 #endif
 
+typedef enum {
+    gcvHARDWARE_FUNCTION_MMU,
+    gcvHARDWARE_FUNCTION_FLUSH,
+
+    gcvHARDWARE_FUNCTION_NUM,
+}
+gceHARDWARE_FUNCTION;
+
+
+typedef struct _gcsHARWARE_FUNCTION
+{
+    /* Entry of the function. */
+    gctUINT32                   address;
+
+    /* Bytes of the function. */
+    gctUINT32                   bytes;
+}
+gcsHARDWARE_FUNCTION;
+
 /* gckHARDWARE object. */
 struct _gckHARDWARE
 {
@@ -61,6 +80,7 @@ struct _gckHARDWARE
     gctUINT32                   powerThread;
     gceCHIPPOWERSTATE           chipPowerState;
     gctUINT32                   lastWaitLink;
+    gctUINT32                   lastEnd;
     gctBOOL                     clockState;
     gctBOOL                     powerState;
     gctPOINTER                  globalSemaphore;
@@ -71,6 +91,11 @@ struct _gckHARDWARE
 
     gctUINT32                   mmuVersion;
 
+    /* Whether use new MMU. It is meaningless
+    ** for old MMU since old MMU is always enabled.
+    */
+    gctBOOL                     enableMMU;
+
     /* Type */
     gceHARDWARE_TYPE            type;
 
@@ -80,19 +105,32 @@ struct _gckHARDWARE
     gctPOINTER                  powerOffTimer;
 #endif
 
-    gctPOINTER                  pageTableDirty;
-
 #if gcdENABLE_FSCALE_VAL_ADJUST
-    /* FSCALE_VAL when gcvPOWER_ON. */
     gctUINT32                   powerOnFscaleVal;
 #endif
+    gctPOINTER                  pageTableDirty;
 
 #if gcdLINK_QUEUE_SIZE
     struct _gckLINKQUEUE        linkQueue;
 #endif
 
     gctBOOL                     powerManagement;
+    gctBOOL                     powerManagementLock;
     gctBOOL                     gpuProfiler;
+
+    gctBOOL                     endAfterFlushMmuCache;
+
+    gctUINT32                   minFscaleValue;
+
+    gctPOINTER                  pendingEvent;
+
+    /* Function used by gckHARDWARE. */
+    gctPHYS_ADDR                functionPhysical;
+    gctPOINTER                  functionLogical;
+    gctUINT32                   functionAddress;
+    gctSIZE_T                   functionBytes;
+
+    gcsHARDWARE_FUNCTION        functions[gcvHARDWARE_FUNCTION_NUM];
 };
 
 gceSTATUS
@@ -114,20 +152,6 @@ gckHARDWARE_GetFrameInfo(
     OUT gcsHAL_FRAME_INFO * FrameInfo
     );
 
-gceSTATUS
-gckHARDWARE_SetFscaleValue(
-    IN gckHARDWARE Hardware,
-    IN gctUINT32   FscaleValue
-    );
-
-gceSTATUS
-gckHARDWARE_GetFscaleValue(
-    IN gckHARDWARE Hardware,
-    IN gctUINT * FscaleValue,
-    IN gctUINT * MinFscaleValue,
-    IN gctUINT * MaxFscaleValue
-    );
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_recorder.c b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_recorder.c
new file mode 100644 (file)
index 0000000..087fa83
--- /dev/null
@@ -0,0 +1,679 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2014 by Vivante Corp.
+*
+*    This program is free software; you can redistribute it and/or modify
+*    it under the terms of the GNU General Public License as published by
+*    the Free Software Foundation; either version 2 of the license, or
+*    (at your option) any later version.
+*
+*    This program is distributed in the hope that it will be useful,
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+*    GNU General Public License for more details.
+*
+*    You should have received a copy of the GNU General Public License
+*    along with this program; if not write to the Free Software
+*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_context.h"
+
+/*
+ *                          -----------------------
+ *                          HARDWARE STATE RECORDER
+ *                          -----------------------
+ *
+ * State mirror buffer is used to 'mirror' hardware states since hardware
+ * states can't be dumpped. It is a context buffer which stores 'global'
+ * context.
+ *
+ * For each commit, state recorder
+ * 1) Records context buffer (if there is) and command buffers in this commit.
+ * 2) Parse those buffers to estimate the state changed.
+ * 3) Stores result to a mirror buffer.
+ *
+ * == Commit 0 ====================================================================
+ *
+ *      Context Buffer 0
+ *
+ *      Command Buffer 0
+ *
+ *      Mirror Buffer  0  <- Context Buffer 0 + Command Buffer 0
+ *
+ * == Commit 1 ====================================================================
+ *
+ *      Command Buffer 1
+ *
+ *      Mirror Buffer  1  <- Command buffer 1 + Mirror Buffer 0
+ *
+ * == Commit 2 ====================================================================
+ *
+ *      Context Buffer 2 (optional)
+ *
+ *      Command Buffer 2
+ *
+ *      Mirror  Buffer 2  <- Command buffer 2 + Context Buffer 2 + Mirror Buffer 1
+ *
+ * == Commit N ====================================================================
+ *
+ * For Commit N, these buffers are needed to reproduce hardware's behavior in
+ * this commit.
+ *
+ *  Mirror  Buffer [N - 1] : State Mirror accumlated by past commits,
+ *                           which is used to restore hardware state.
+ *  Context Buffer [N]     :
+ *  Command Buffer [N]     : Command buffer executed by hardware in this commit.
+ *
+ *  If sequence of states programming matters, hardware's behavior can't be reproduced,
+ *  but the state values stored in mirror buffer are assuring.
+ */
+
+/* Queue size. */
+#define gcdNUM_RECORDS  6
+
+typedef struct _gcsPARSER_HANDLER * gckPARSER_HANDLER;
+
+typedef void
+(*HandlerFunction)(
+    IN gckPARSER_HANDLER Handler,
+    IN gctUINT32 Addr,
+    IN gctUINT32 Data
+    );
+
+typedef struct _gcsPARSER_HANDLER
+{
+    gctUINT32           type;
+    gctUINT32           cmd;
+    gctPOINTER          private;
+    HandlerFunction     function;
+}
+gcsPARSER_HANDLER;
+
+typedef struct _gcsPARSER * gckPARSER;
+typedef struct _gcsPARSER
+{
+    gctUINT8_PTR        currentCmdBufferAddr;
+
+    /* Current command. */
+    gctUINT32           lo;
+    gctUINT32           hi;
+
+    gctUINT8            cmdOpcode;
+    gctUINT16           cmdAddr;
+    gctUINT32           cmdSize;
+    gctUINT32           cmdRectCount;
+    gctUINT8            skip;
+    gctUINT32           skipCount;
+
+    gctBOOL             allow;
+
+    /* Callback used by parser to handle a command. */
+    gckPARSER_HANDLER   commandHandler;
+}
+gcsPARSER;
+
+typedef struct _gcsMIRROR
+{
+    gctUINT32_PTR       logical[gcdNUM_RECORDS];
+    gctUINT32           bytes;
+    gcsSTATE_MAP_PTR    map;
+    gctUINT32           stateCount;
+}
+gcsMIRROR;
+
+typedef struct _gcsDELTA
+{
+    gctUINT64           commitStamp;
+    gctUINT32_PTR       command;
+    gctUINT32           commandBytes;
+    gctUINT32_PTR       context;
+    gctUINT32           contextBytes;
+}
+gcsDELTA;
+
+typedef struct _gcsRECORDER
+{
+    gckOS               os;
+    gcsMIRROR           mirror;
+    gcsDELTA            deltas[gcdNUM_RECORDS];
+
+    /* Index of current record. */
+    gctUINT             index;
+
+    /* Number of records. */
+    gctUINT             num;
+
+    /* Plugin used by gckPARSER. */
+    gcsPARSER_HANDLER   recorderHandler;
+    gckPARSER           parser;
+}
+gcsRECORDER;
+
+
+/******************************************************************************\
+***************************** Command Buffer Parser ****************************
+\******************************************************************************/
+
+/*
+** Command buffer parser checks command buffer in FE's view to make sure there
+** is no format error.
+**
+** Parser provide a callback mechnisam, so plug-in can be added to implement
+** other functions.
+*/
+
+static void
+_HandleLoadState(
+    IN OUT gckPARSER Parser
+    )
+{
+    gctUINT i;
+    gctUINT32_PTR data = (gctUINT32_PTR)Parser->currentCmdBufferAddr;
+    gctUINT32 cmdAddr = Parser->cmdAddr;
+
+    if (Parser->commandHandler == gcvNULL
+     || Parser->commandHandler->cmd != 0x01
+    )
+    {
+        /* No handler for this command. */
+        return;
+    }
+
+    for (i = 0; i < Parser->cmdSize; i++)
+    {
+        Parser->commandHandler->function(Parser->commandHandler, cmdAddr, *data);
+
+        /* Advance to next state. */
+        cmdAddr++;
+        data++;
+    }
+}
+
+static void
+_GetCommand(
+    IN OUT gckPARSER Parser
+    )
+{
+    gctUINT32 * buffer = (gctUINT32 *)Parser->currentCmdBufferAddr;
+
+    gctUINT16 cmdRectCount;
+    gctUINT16 cmdDataCount;
+
+    Parser->hi = buffer[0];
+    Parser->lo = buffer[1];
+
+    Parser->cmdOpcode = (((((gctUINT32) (Parser->hi)) >> (0 ? 31:27)) & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1)))))) );
+    Parser->cmdRectCount = 1;
+
+    switch (Parser->cmdOpcode)
+    {
+    case 0x01:
+        /* Extract count. */
+        Parser->cmdSize = (((((gctUINT32) (Parser->hi)) >> (0 ? 25:16)) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1)))))) );
+        if (Parser->cmdSize == 0)
+        {
+            /* 0 means 1024. */
+            Parser->cmdSize = 1024;
+        }
+        Parser->skip = (Parser->cmdSize & 0x1) ? 0 : 1;
+
+        /* Extract address. */
+        Parser->cmdAddr = (((((gctUINT32) (Parser->hi)) >> (0 ? 15:0)) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1)))))) );
+
+        Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 4;
+        Parser->skipCount = Parser->cmdSize + Parser->skip;
+        break;
+
+     case 0x05:
+        Parser->cmdSize   = 4;
+        Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
+        break;
+
+    case 0x06:
+        Parser->cmdSize   = 5;
+        Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
+        break;
+
+    case 0x0C:
+        Parser->cmdSize   = 3;
+        Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
+        break;
+
+    case 0x09:
+        Parser->cmdSize   = 2;
+        Parser->cmdAddr   = 0x0F16;
+        Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
+        break;
+
+     case 0x04:
+        Parser->cmdSize = 1;
+        Parser->cmdAddr = 0x0F06;
+
+        cmdRectCount = (((((gctUINT32) (Parser->hi)) >> (0 ? 15:8)) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1)))))) );
+        cmdDataCount = (((((gctUINT32) (Parser->hi)) >> (0 ? 26:16)) & ((gctUINT32) ((((1 ? 26:16) - (0 ? 26:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:16) - (0 ? 26:16) + 1)))))) );
+
+        Parser->skipCount = gcmALIGN(Parser->cmdSize, 2)
+                          + cmdRectCount * 2
+                          + gcmALIGN(cmdDataCount, 2);
+
+        Parser->cmdRectCount = cmdRectCount;
+        break;
+
+    case 0x03:
+        Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
+        Parser->skipCount = 0;
+        break;
+
+    case 0x02:
+        Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
+        Parser->skipCount = 0;
+        break;
+
+    default:
+        /* Unknown command is a risk. */
+        Parser->allow = gcvFALSE;
+        break;
+    }
+}
+
+static void
+_ParseCommand(
+    IN OUT gckPARSER Parser
+    )
+{
+    switch(Parser->cmdOpcode)
+    {
+    case 0x01:
+        _HandleLoadState(Parser);
+        break;
+    case 0x05:
+    case 0x06:
+    case 0x0C:
+        break;
+    case 0x04:
+        break;
+    default:
+        break;
+    }
+
+    /* Advance to next command. */
+    Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr
+                                 + (Parser->skipCount << 2);
+}
+
+gceSTATUS
+gckPARSER_Parse(
+    IN gckPARSER Parser,
+    IN gctUINT8_PTR Buffer,
+    IN gctUINT32 Bytes
+    )
+{
+    gckPARSER parser = Parser;
+    gctUINT8_PTR end = (gctUINT8_PTR)Buffer + Bytes;
+
+    /* Initialize parser. */
+    parser->currentCmdBufferAddr = (gctUINT8_PTR)Buffer;
+    parser->skip = 0;
+    parser->allow = gcvTRUE;
+
+    /* Go through command buffer until reaching the end
+    ** or meeting an error. */
+    do
+    {
+        _GetCommand(parser);
+
+        _ParseCommand(parser);
+    }
+    while ((parser->currentCmdBufferAddr < end) && (parser->allow == gcvTRUE));
+
+    if (parser->allow == gcvFALSE)
+    {
+        /* Error detected. */
+        return gcvSTATUS_NOT_SUPPORTED;
+    }
+
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckPARSER_RegisterCommandHandler
+**
+**  Register a command handler which will be called when parser get a command.
+**
+*/
+gceSTATUS
+gckPARSER_RegisterCommandHandler(
+    IN gckPARSER Parser,
+    IN gckPARSER_HANDLER Handler
+    )
+{
+    Parser->commandHandler = Handler;
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckPARSER_Construct(
+    IN gckOS Os,
+    IN gckPARSER_HANDLER Handler,
+    OUT gckPARSER * Parser
+    )
+{
+    gceSTATUS status;
+    gckPARSER pointer;
+
+    gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsPARSER), (gctPOINTER *)&pointer));
+
+    /* Put it here temp, should have a more general plug-in mechnisam. */
+    pointer->commandHandler = Handler;
+
+    *Parser = pointer;
+
+    return gcvSTATUS_OK;
+
+OnError:
+    return status;
+}
+
+void
+gckPARSER_Destroy(
+    IN gckOS Os,
+    IN gckPARSER Parser
+    )
+{
+    gcmkOS_SAFE_FREE(Os, Parser);
+}
+
+/******************************************************************************\
+**************************** Hardware States Recorder **************************
+\******************************************************************************/
+
+static void
+_RecodeState(
+    IN gckPARSER_HANDLER Handler,
+    IN gctUINT32 Addr,
+    IN gctUINT32 Data
+    )
+{
+    gcmkVERIFY_OK(gckRECORDER_UpdateMirror(Handler->private, Addr, Data));
+}
+
+static gctUINT
+_Previous(
+    IN gctUINT Index
+    )
+{
+    if (Index == 0)
+    {
+        return gcdNUM_RECORDS - 1;
+    }
+
+    return Index - 1;
+}
+
+static gctUINT
+_Next(
+    IN gctUINT Index
+    )
+{
+    return (Index + 1) % gcdNUM_RECORDS;
+}
+
+gceSTATUS
+gckRECORDER_Construct(
+    IN gckOS Os,
+    IN gckHARDWARE Hardware,
+    OUT gckRECORDER * Recorder
+    )
+{
+    gceSTATUS status;
+    gckCONTEXT context = gcvNULL;
+    gckRECORDER recorder = gcvNULL;
+    gctUINT32 mapSize;
+    gctUINT i;
+    gctBOOL virtualCommandBuffer = Hardware->kernel->virtualCommandBuffer;
+
+    /* TODO: We only need context buffer and state map, it should be able to get without construct a
+    ** new context.
+    ** Now it is leaked, since we can't free it when command buffer is gone.
+    */
+
+    /* MMU is not ready now. */
+    Hardware->kernel->virtualCommandBuffer = gcvFALSE;
+
+    gcmkONERROR(gckCONTEXT_Construct(Os, Hardware, 0, &context));
+
+    /* Restore. */
+    Hardware->kernel->virtualCommandBuffer = virtualCommandBuffer;
+
+    gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsRECORDER), (gctPOINTER *)&recorder));
+
+    gckOS_ZeroMemory(recorder, gcmSIZEOF(gcsRECORDER));
+
+    /* Copy state map. */
+    recorder->mirror.stateCount = context->stateCount;
+
+    mapSize = context->stateCount * gcmSIZEOF(gcsSTATE_MAP);
+
+    gcmkONERROR(gckOS_Allocate(Os, mapSize, (gctPOINTER *)&recorder->mirror.map));
+
+    gckOS_MemCopy(recorder->mirror.map, context->map, mapSize);
+
+    /* Copy context buffer. */
+    recorder->mirror.bytes = context->totalSize;
+
+    for (i = 0; i < gcdNUM_RECORDS; i++)
+    {
+        gcmkONERROR(gckOS_Allocate(Os, context->totalSize, (gctPOINTER *)&recorder->mirror.logical[i]));
+        gckOS_MemCopy(recorder->mirror.logical[i], context->buffer->logical, context->totalSize);
+    }
+
+    for (i = 0; i < gcdNUM_RECORDS; i++)
+    {
+        /* TODO : Optimize size. */
+        gcmkONERROR(gckOS_Allocate(Os, gcdCMD_BUFFER_SIZE, (gctPOINTER *)&recorder->deltas[i].command));
+        gcmkONERROR(gckOS_Allocate(Os, context->totalSize, (gctPOINTER *)&recorder->deltas[i].context));
+    }
+
+    recorder->index = 0;
+    recorder->num   = 0;
+
+    /* Initialize Parser plugin. */
+    recorder->recorderHandler.cmd = 0x01;
+    recorder->recorderHandler.private = recorder;
+    recorder->recorderHandler.function = _RecodeState;
+
+    gcmkONERROR(gckPARSER_Construct(Os, &recorder->recorderHandler, &recorder->parser));
+
+    recorder->os = Os;
+
+    *Recorder = recorder;
+
+    return gcvSTATUS_OK;
+
+OnError:
+    if (recorder)
+    {
+        gckRECORDER_Destory(Os, recorder);
+    }
+
+    return status;
+}
+
+gceSTATUS
+gckRECORDER_Destory(
+    IN gckOS Os,
+    IN gckRECORDER Recorder
+    )
+{
+    gctUINT i;
+
+    if (Recorder->mirror.map)
+    {
+        gcmkOS_SAFE_FREE(Os, Recorder->mirror.map);
+    }
+
+    for (i = 0; i < gcdNUM_RECORDS; i++)
+    {
+        if (Recorder->mirror.logical[i])
+        {
+            gcmkOS_SAFE_FREE(Os, Recorder->mirror.logical[i]);
+        }
+    }
+
+    for (i = 0; i < gcdNUM_RECORDS; i++)
+    {
+        if (Recorder->deltas[i].command)
+        {
+            gcmkOS_SAFE_FREE(Os, Recorder->deltas[i].command);
+        }
+
+        if (Recorder->deltas[i].context)
+        {
+            gcmkOS_SAFE_FREE(Os, Recorder->deltas[i].context);
+        }
+    }
+
+    if (Recorder->parser)
+    {
+        gckPARSER_Destroy(Os, Recorder->parser);
+    }
+
+    gcmkOS_SAFE_FREE(Os, Recorder);
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckRECORDER_UpdateMirror(
+    IN gckRECORDER Recorder,
+    IN gctUINT32 State,
+    IN gctUINT32 Data
+    )
+{
+    gctUINT32 index;
+    gcsSTATE_MAP_PTR map = Recorder->mirror.map;
+    gctUINT32_PTR buffer = Recorder->mirror.logical[Recorder->index];
+
+    if (State >= Recorder->mirror.stateCount)
+    {
+        /* Ignore them just like HW does. */
+        return gcvSTATUS_OK;
+    }
+
+    index = map[State].index;
+
+    if (index)
+    {
+        buffer[index] = Data;
+    }
+
+    return gcvSTATUS_OK;
+}
+
+void
+gckRECORDER_AdvanceIndex(
+    IN gckRECORDER Recorder,
+    IN gctUINT64 CommitStamp
+    )
+{
+    /* Get next record. */
+    gctUINT next = (Recorder->index + 1) % gcdNUM_RECORDS;
+
+    /* Record stamp of this commit. */
+    Recorder->deltas[Recorder->index].commitStamp = CommitStamp;
+
+    /* Mirror of next record is mirror of this record and delta in next record. */
+    gckOS_MemCopy(Recorder->mirror.logical[next],
+        Recorder->mirror.logical[Recorder->index], Recorder->mirror.bytes);
+
+    /* Advance to next record. */
+    Recorder->index = next;
+
+    Recorder->num = gcmMIN(Recorder->num + 1, gcdNUM_RECORDS - 1);
+
+
+    /* Reset delta. */
+    Recorder->deltas[Recorder->index].commandBytes = 0;
+    Recorder->deltas[Recorder->index].contextBytes = 0;
+}
+
+void
+gckRECORDER_Record(
+    IN gckRECORDER Recorder,
+    IN gctUINT8_PTR CommandBuffer,
+    IN gctUINT32 CommandBytes,
+    IN gctUINT8_PTR ContextBuffer,
+    IN gctUINT32 ContextBytes
+    )
+{
+    gcsDELTA * delta = &Recorder->deltas[Recorder->index];
+
+    if (CommandBytes != 0xFFFFFFFF)
+    {
+        gckPARSER_Parse(Recorder->parser, CommandBuffer, CommandBytes);
+        gckOS_MemCopy(delta->command, CommandBuffer, CommandBytes);
+        delta->commandBytes = CommandBytes;
+    }
+
+    if (ContextBytes != 0xFFFFFFFF)
+    {
+        gckPARSER_Parse(Recorder->parser, ContextBuffer, ContextBytes);
+        gckOS_MemCopy(delta->context, ContextBuffer, ContextBytes);
+        delta->contextBytes = ContextBytes;
+    }
+}
+
+void
+gckRECORDER_Dump(
+    IN gckRECORDER Recorder
+    )
+{
+    gctUINT last = Recorder->index;
+    gctUINT previous;
+    gctUINT i;
+    gcsMIRROR *mirror = &Recorder->mirror;
+    gcsDELTA *delta;
+    gckOS os = Recorder->os;
+
+    for (i = 0; i < Recorder->num; i++)
+    {
+        last = _Previous(last);
+    }
+
+    for (i = 0; i < Recorder->num; i++)
+    {
+        delta = &Recorder->deltas[last];
+
+        /* Dump record */
+        gcmkPRINT("#[commit %llu]", delta->commitStamp);
+
+        if (delta->commitStamp)
+        {
+            previous = _Previous(last);
+
+            gcmkPRINT("#[mirror]");
+            gckOS_DumpBuffer(os, mirror->logical[previous], mirror->bytes, gceDUMP_BUFFER_CONTEXT, gcvTRUE);
+            gcmkPRINT("@[kernel.execute]");
+        }
+
+        if (delta->contextBytes)
+        {
+            gckOS_DumpBuffer(os, delta->context, delta->contextBytes, gceDUMP_BUFFER_CONTEXT, gcvTRUE);
+            gcmkPRINT("@[kernel.execute]");
+        }
+
+        gckOS_DumpBuffer(os, delta->command, delta->commandBytes, gceDUMP_BUFFER_USER, gcvTRUE);
+        gcmkPRINT("@[kernel.execute]");
+
+        last = _Next(last);
+    }
+}
+
+
similarity index 99%
rename from drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.c
rename to drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.c
index cf40e3f6b7649d209806dfeaef043dc57ae30314..0013e63b9a53f9aeac170ba9cd9a4f0394efae49 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -176,8 +176,8 @@ gckVGCOMMAND_StateCommand(
     IN gctUINT32 Pipe,
     IN gctPOINTER Logical,
     IN gctUINT32 Address,
-    IN gctSIZE_T Count,
-    IN OUT gctSIZE_T * Bytes
+    IN gctUINT32 Count,
+    IN OUT gctUINT32 * Bytes
     )
 {
     gcmkHEADER_ARG("Command=0x%x Pipe=0x%x Logical=0x%x Address=0x%x Count=0x%x Bytes = 0x%x",
@@ -277,7 +277,7 @@ gckVGCOMMAND_RestartCommand(
     IN gctPOINTER Logical,
     IN gctUINT32 FetchAddress,
     IN gctUINT FetchCount,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     )
 {
     gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
@@ -368,7 +368,7 @@ gckVGCOMMAND_FetchCommand(
     IN gctPOINTER Logical,
     IN gctUINT32 FetchAddress,
     IN gctUINT FetchCount,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     )
 {
     gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
@@ -470,7 +470,7 @@ gckVGCOMMAND_CallCommand(
     IN gctPOINTER Logical,
     IN gctUINT32 FetchAddress,
     IN gctUINT FetchCount,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     )
 {
     gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
@@ -542,7 +542,7 @@ gceSTATUS
 gckVGCOMMAND_ReturnCommand(
     IN gckVGCOMMAND Command,
     IN gctPOINTER Logical,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     )
 {
     gcmkHEADER_ARG("Command=0x%x Logical=0x%x  Bytes = 0x%x",
@@ -619,7 +619,7 @@ gckVGCOMMAND_EventCommand(
     IN gctPOINTER Logical,
     IN gceBLOCK Block,
     IN gctINT32 InterruptId,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     )
 {
     gcmkHEADER_ARG("Command=0x%x Logical=0x%x Block=0x%x InterruptId=0x%x Bytes = 0x%x",
@@ -857,7 +857,7 @@ gckVGCOMMAND_EndCommand(
     IN gckVGCOMMAND Command,
     IN gctPOINTER Logical,
     IN gctINT32 InterruptId,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     )
 {
     gcmkHEADER_ARG("Command=0x%x Logical=0x%x InterruptId=0x%x Bytes = 0x%x",
similarity index 97%
rename from drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.h
rename to drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.h
index aa767ee173566e210729e1663371b20ab300d431..22093a9655a8f6ca639137f1e97d5359fd9d99c2 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -254,8 +254,8 @@ gckVGCOMMAND_StateCommand(
     IN gctUINT32 Pipe,
     IN gctPOINTER Logical,
     IN gctUINT32 Address,
-    IN gctSIZE_T Count,
-    IN OUT gctSIZE_T * Bytes
+    IN gctUINT32 Count,
+    IN OUT gctUINT32 * Bytes
     );
 
 /* Form a RESTART command at the specified location in the command buffer. */
@@ -265,7 +265,7 @@ gckVGCOMMAND_RestartCommand(
     IN gctPOINTER Logical,
     IN gctUINT32 FetchAddress,
     IN gctUINT FetchCount,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     );
 
 /* Form a FETCH command at the specified location in the command buffer. */
@@ -275,7 +275,7 @@ gckVGCOMMAND_FetchCommand(
     IN gctPOINTER Logical,
     IN gctUINT32 FetchAddress,
     IN gctUINT FetchCount,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     );
 
 /* Form a CALL command at the specified location in the command buffer. */
@@ -285,7 +285,7 @@ gckVGCOMMAND_CallCommand(
     IN gctPOINTER Logical,
     IN gctUINT32 FetchAddress,
     IN gctUINT FetchCount,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     );
 
 /* Form a RETURN command at the specified location in the command buffer. */
@@ -293,7 +293,7 @@ gceSTATUS
 gckVGCOMMAND_ReturnCommand(
     IN gckVGCOMMAND Command,
     IN gctPOINTER Logical,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     );
 
 /* Form an EVENT command at the specified location in the command buffer. */
@@ -303,7 +303,7 @@ gckVGCOMMAND_EventCommand(
     IN gctPOINTER Logical,
     IN gceBLOCK Block,
     IN gctINT32 InterruptId,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     );
 
 /* Form an END command at the specified location in the command buffer. */
@@ -312,7 +312,7 @@ gckVGCOMMAND_EndCommand(
     IN gckVGCOMMAND Command,
     IN gctPOINTER Logical,
     IN gctINT32 InterruptId,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     );
 
 #endif  /* __gc_hal_kernel_hardware_command_h_ */
similarity index 97%
rename from drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c
rename to drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.c
index a17d2fdb7747ac14ca3860ebb4e330217e3853ab..3cb47dd04b6fc6f9da526bb887f6a1fe5bb7d76e 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -310,9 +310,9 @@ gckVGHARDWARE_Construct(
         hardware->clockState            = gcvTRUE;
         hardware->powerState            = gcvTRUE;
 
-        hardware->powerOffTime          = 0;
 #if gcdPOWEROFF_TIMEOUT
-        hardware->powerOffTimeout = gcdPOWEROFF_TIMEOUT;
+        hardware->powerOffTime          = 0;
+        hardware->powerOffTimeout       = gcdPOWEROFF_TIMEOUT;
 
         gcmkVERIFY_OK(gckOS_CreateTimer(Os,
                                         _VGPowerTimerFunction,
@@ -352,14 +352,16 @@ gckVGHARDWARE_Construct(
     while (gcvFALSE);
 
 #if gcdPOWEROFF_TIMEOUT
-        if (hardware->powerOffTimer != gcvNULL)
-        {
-            gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
-            gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
-        }
+    if (hardware->powerOffTimer != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
+        gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
+    }
 #endif
 
-    if (hardware->pageTableDirty != gcvNULL)
+    gcmkVERIFY_OK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvFALSE, gcvFALSE));
+
+    if (hardware != gcvNULL && hardware->pageTableDirty != gcvNULL)
     {
         gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
     }
@@ -369,8 +371,6 @@ gckVGHARDWARE_Construct(
         gcmkVERIFY_OK(gckOS_Free(Os, hardware));
     }
 
-    gcmkVERIFY_OK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvFALSE, gcvFALSE));
-
     gcmkFOOTER();
     /* Return the status. */
     return status;
@@ -889,7 +889,7 @@ gceSTATUS
 gckVGHARDWARE_Execute(
     IN gckVGHARDWARE Hardware,
     IN gctUINT32 Address,
-    IN gctSIZE_T Count
+    IN gctUINT32 Count
     )
 {
     gceSTATUS status;
@@ -1042,6 +1042,9 @@ gckVGHARDWARE_AlignToTile(
 **      gctPOINTER Logical
 **          Logical address to convert.
 **
+**      gctBOOL InUserSpace
+**          gcvTRUE if the memory in user space.
+**
 **      gctUINT32* Address
 **          Return hardware specific address.
 **
@@ -1053,14 +1056,15 @@ gceSTATUS
 gckVGHARDWARE_ConvertLogical(
     IN gckVGHARDWARE Hardware,
     IN gctPOINTER Logical,
+    IN gctBOOL InUserSpace,
     OUT gctUINT32 * Address
     )
 {
     gctUINT32 address;
     gceSTATUS status;
 
-    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Address=0x%x",
-                   Hardware, Logical, Address);
+    gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x InUserSpace=%d Address=0x%x",
+                   Hardware, Logical, InUserSpace, Address);
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
@@ -1070,9 +1074,18 @@ gckVGHARDWARE_ConvertLogical(
     do
     {
         /* Convert logical address into a physical address. */
-        gcmkERR_BREAK(gckOS_GetPhysicalAddress(
-            Hardware->os, Logical, &address
-            ));
+        if (InUserSpace)
+        {
+            gcmkERR_BREAK(gckOS_UserLogicalToPhysical(
+                Hardware->os, Logical, &address
+                ));
+        }
+        else
+        {
+            gcmkERR_BREAK(gckOS_GetPhysicalAddress(
+                Hardware->os, Logical, &address
+                ));
+        }
 
         /* Return hardware specific address. */
         *Address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
@@ -1174,32 +1187,33 @@ gceSTATUS gckVGHARDWARE_SetMMU(
     do
     {
         /* Convert the logical address into an hardware address. */
-        gcmkERR_BREAK(gckVGHARDWARE_ConvertLogical(Hardware, Logical, &address) );
+        gcmkERR_BREAK(gckVGHARDWARE_ConvertLogical(Hardware, Logical,
+                                      gcvFALSE, &address));
 
         /* Write the AQMemoryFePageTable register. */
         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
                                       0x00400,
-                                      gcmkFIXADDRESS(address)) );
+                                      gcmkFIXADDRESS(address)));
 
         /* Write the AQMemoryTxPageTable register. */
         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
                                       0x00404,
-                                      gcmkFIXADDRESS(address)) );
+                                      gcmkFIXADDRESS(address)));
 
         /* Write the AQMemoryPePageTable register. */
         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
                                       0x00408,
-                                      gcmkFIXADDRESS(address)) );
+                                      gcmkFIXADDRESS(address)));
 
         /* Write the AQMemoryPezPageTable register. */
         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
                                       0x0040C,
-                                      gcmkFIXADDRESS(address)) );
+                                      gcmkFIXADDRESS(address)));
 
         /* Write the AQMemoryRaPageTable register. */
         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
                                       0x00410,
-                                      gcmkFIXADDRESS(address)) );
+                                      gcmkFIXADDRESS(address)));
     }
     while (gcvFALSE);
 
@@ -1436,7 +1450,7 @@ static gceSTATUS _CommandStall(
         gcmkERR_BREAK(gckOS_WaitSignal(
             command->os,
             command->powerStallSignal,
-            gcdGPU_TIMEOUT));
+            command->kernel->kernel->timeOut));
 
 
     }
@@ -1800,17 +1814,10 @@ gckVGHARDWARE_SetPowerManagementState(
         acquired = gcvTRUE;
     }
 
-    if (flag & gcvPOWER_FLAG_STOP)
-    {
-    }
 
     /* Get time until stopped. */
     gcmkPROFILE_QUERY(time, stopTime);
 
-    /* Only process this when hardware is enabled. */
-    if (Hardware->clockState && Hardware->powerState)
-    {
-    }
 
     if (flag & gcvPOWER_FLAG_DELAY)
     {
@@ -1824,7 +1831,10 @@ gckVGHARDWARE_SetPowerManagementState(
 
     if (flag & gcvPOWER_FLAG_INITIALIZE)
     {
+
+        /* Initialize GPU here, replaced by InitializeHardware later */
         gcmkONERROR(gckVGHARDWARE_SetMMU(Hardware, Hardware->kernel->mmu->pageTableLogical));
+        gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(Hardware, -1));
 
         /* Force the command queue to reload the next context. */
         command->currentContext = 0;
@@ -1854,9 +1864,6 @@ gckVGHARDWARE_SetPowerManagementState(
     /* Get time until off. */
     gcmkPROFILE_QUERY(time, offTime);
 
-    if (flag & gcvPOWER_FLAG_START)
-    {
-    }
 
     /* Get time until started. */
     gcmkPROFILE_QUERY(time, startTime);
@@ -2023,6 +2030,7 @@ gckVGHARDWARE_SetPowerManagement(
     return gcvSTATUS_OK;
 }
 
+#if gcdPOWEROFF_TIMEOUT
 gceSTATUS
 gckVGHARDWARE_SetPowerOffTimeout(
     IN gckVGHARDWARE  Hardware,
@@ -2051,6 +2059,7 @@ gckVGHARDWARE_QueryPowerOffTimeout(
     gcmkFOOTER_ARG("*Timeout=%d", *Timeout);
     return gcvSTATUS_OK;
 }
+#endif
 
 gceSTATUS
 gckVGHARDWARE_QueryIdle(
similarity index 98%
rename from drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h
rename to drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.h
index 73d4594d7bc0286e0ae7fc7f2e69f0ddb026218f..ce54910545d7a2194f1fe7cf5fb3265def588b30 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -61,7 +61,6 @@ struct _gckVGHARDWARE
     gctISRMANAGERFUNC           stopIsr;
     gctPOINTER                  isrContext;
     gctPOINTER                  pageTableDirty;
-
 #if gcdPOWEROFF_TIMEOUT
     gctUINT32                   powerOffTime;
     gctUINT32                   powerOffTimeout;
index 879d467e36206292fe3fcce3011b4bedd69da473..b14708d307d4262e6cc7529a035ad215981c3b0f 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -50,7 +50,7 @@ gctCONST_STRING _DispatchText[] =
     gcmDEFINE2TEXT(gcvHAL_FREE_CONTIGUOUS_MEMORY),
     gcmDEFINE2TEXT(gcvHAL_ALLOCATE_VIDEO_MEMORY),
     gcmDEFINE2TEXT(gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY),
-    gcmDEFINE2TEXT(gcvHAL_FREE_VIDEO_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_RELEASE_VIDEO_MEMORY),
     gcmDEFINE2TEXT(gcvHAL_MAP_MEMORY),
     gcmDEFINE2TEXT(gcvHAL_UNMAP_MEMORY),
     gcmDEFINE2TEXT(gcvHAL_MAP_USER_MEMORY),
@@ -68,10 +68,10 @@ gctCONST_STRING _DispatchText[] =
     gcmDEFINE2TEXT(gcvHAL_GET_PROFILE_SETTING),
     gcmDEFINE2TEXT(gcvHAL_SET_PROFILE_SETTING),
     gcmDEFINE2TEXT(gcvHAL_READ_ALL_PROFILE_REGISTERS),
+    gcmDEFINE2TEXT(gcvHAL_PROFILE_REGISTERS_2D),
 #if VIVANTE_PROFILER_PERDRAW
-    gcmDEFINE2TEXT(gcvHAL_READ_PROFILER_REGISTER_SETTING),
+    gcvHAL_READ_PROFILER_REGISTER_SETTING,
 #endif
-    gcmDEFINE2TEXT(gcvHAL_PROFILE_REGISTERS_2D),
     gcmDEFINE2TEXT(gcvHAL_SET_POWER_MANAGEMENT_STATE),
     gcmDEFINE2TEXT(gcvHAL_QUERY_POWER_MANAGEMENT_STATE),
     gcmDEFINE2TEXT(gcvHAL_GET_BASE_ADDRESS),
@@ -86,21 +86,196 @@ gctCONST_STRING _DispatchText[] =
     gcmDEFINE2TEXT(gcvHAL_VERSION),
     gcmDEFINE2TEXT(gcvHAL_CHIP_INFO),
     gcmDEFINE2TEXT(gcvHAL_ATTACH),
-    gcmDEFINE2TEXT(gcvHAL_DETACH)
+    gcmDEFINE2TEXT(gcvHAL_DETACH),
+    gcmDEFINE2TEXT(gcvHAL_COMPOSE),
+    gcmDEFINE2TEXT(gcvHAL_SET_TIMEOUT),
+    gcmDEFINE2TEXT(gcvHAL_GET_FRAME_INFO),
+    gcmDEFINE2TEXT(gcvHAL_QUERY_COMMAND_BUFFER),
+    gcmDEFINE2TEXT(gcvHAL_COMMIT_DONE),
+    gcmDEFINE2TEXT(gcvHAL_DUMP_GPU_STATE),
+    gcmDEFINE2TEXT(gcvHAL_DUMP_EVENT),
+    gcmDEFINE2TEXT(gcvHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER),
+    gcmDEFINE2TEXT(gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER),
+    gcmDEFINE2TEXT(gcvHAL_SET_FSCALE_VALUE),
+    gcmDEFINE2TEXT(gcvHAL_GET_FSCALE_VALUE),
+    gcmDEFINE2TEXT(gcvHAL_NAME_VIDEO_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_IMPORT_VIDEO_MEMORY),
+    gcmDEFINE2TEXT(gcvHAL_QUERY_RESET_TIME_STAMP),
+    gcmDEFINE2TEXT(gcvHAL_READ_REGISTER_EX),
+    gcmDEFINE2TEXT(gcvHAL_WRITE_REGISTER_EX),
+    gcmDEFINE2TEXT(gcvHAL_SYNC_POINT),
+    gcmDEFINE2TEXT(gcvHAL_CREATE_NATIVE_FENCE),
+    gcmDEFINE2TEXT(gcvHAL_DESTROY_MMU),
+    gcmDEFINE2TEXT(gcvHAL_SHBUF),
 };
 #endif
 
-#if gcdENABLE_RECOVERY
+#if gcdGPU_TIMEOUT && gcdINTERRUPT_STATISTIC
 void
-_ResetFinishFunction(
+_MonitorTimerFunction(
     gctPOINTER Data
     )
 {
     gckKERNEL kernel = (gckKERNEL)Data;
+    gctUINT32 pendingInterrupt;
+    gctBOOL reset = gcvFALSE;
+    gctUINT32 mask;
+    gctUINT32 advance = kernel->timeOut/2;
+
+#if gcdENABLE_VG
+    if (kernel->core == gcvCORE_VG)
+    {
+        return;
+    }
+#endif
+
+    if (kernel->monitorTimerStop)
+    {
+        /* Stop. */
+        return;
+    }
+
+    gckOS_AtomGet(kernel->os, kernel->eventObj->interruptCount, &pendingInterrupt);
+
+    if (kernel->monitoring == gcvFALSE)
+    {
+        if (pendingInterrupt)
+        {
+            /* Begin to mointor GPU state. */
+            kernel->monitoring = gcvTRUE;
+
+            /* Record current state. */
+            kernel->lastCommitStamp = kernel->eventObj->lastCommitStamp;
+            kernel->restoreAddress  = kernel->hardware->lastWaitLink;
+            gcmkVERIFY_OK(gckOS_AtomGet(
+                kernel->os,
+                kernel->hardware->pendingEvent,
+                &kernel->restoreMask
+                ));
+
+            /* Clear timeout. */
+            kernel->timer = 0;
+        }
+    }
+    else
+    {
+        if (pendingInterrupt)
+        {
+            gcmkVERIFY_OK(gckOS_AtomGet(
+                kernel->os,
+                kernel->hardware->pendingEvent,
+                &mask
+                ));
+
+            if (kernel->eventObj->lastCommitStamp == kernel->lastCommitStamp
+             && kernel->hardware->lastWaitLink    == kernel->restoreAddress
+             && mask                              == kernel->restoreMask
+            )
+            {
+                /* GPU state is not changed, accumlate timeout. */
+                kernel->timer += advance;
+
+                if (kernel->timer >= kernel->timeOut)
+                {
+                    /* GPU stuck, trigger reset. */
+                    reset = gcvTRUE;
+                }
+            }
+            else
+            {
+                /* GPU state changed, cancel current timeout.*/
+                kernel->monitoring = gcvFALSE;
+            }
+        }
+        else
+        {
+            /* GPU finish all jobs, cancel current timeout*/
+            kernel->monitoring = gcvFALSE;
+        }
+    }
+
+    if (reset)
+    {
+        gckKERNEL_Recovery(kernel);
+
+        /* Work in this timeout is done. */
+        kernel->monitoring = gcvFALSE;
+    }
+
+    gcmkVERIFY_OK(gckOS_StartTimer(kernel->os, kernel->monitorTimer, advance));
+}
+#endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+_MapCommandBuffer(
+    IN gckKERNEL Kernel
+    )
+{
+    gceSTATUS status;
+    gctUINT32 i;
+    gctUINT32 physical;
+    gckMMU mmu;
+
+    gcmkONERROR(gckKERNEL_GetProcessMMU(Kernel, &mmu));
+
+    for (i = 0; i < gcdCOMMAND_QUEUES; i++)
+    {
+        gcmkONERROR(gckOS_GetPhysicalAddress(
+            Kernel->os,
+            Kernel->command->queues[i].logical,
+            &physical
+            ));
+
+        gcmkONERROR(gckMMU_FlatMapping(mmu, physical));
+    }
+
+    return gcvSTATUS_OK;
+
+OnError:
+    return status;
+}
+#endif
+
+void
+_DumpDriverConfigure(
+    IN gckKERNEL Kernel
+    )
+{
+    gcmkPRINT_N(0, "**************************\n");
+    gcmkPRINT_N(0, "***   GPU DRV CONFIG   ***\n");
+    gcmkPRINT_N(0, "**************************\n");
 
-    gckOS_AtomSet(kernel->os, kernel->resetAtom, 0);
+    gcmkPRINT("Galcore version %d.%d.%d.%d\n",
+              gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
+
+    gckOS_DumpParam();
 }
+
+void
+_DumpState(
+    IN gckKERNEL Kernel
+    )
+{
+    /* Dump GPU Debug registers. */
+    gcmkVERIFY_OK(gckHARDWARE_DumpGPUState(Kernel->hardware));
+
+    if (Kernel->virtualCommandBuffer)
+    {
+        gcmkVERIFY_OK(gckCOMMAND_DumpExecutingBuffer(Kernel->command));
+    }
+
+    /* Dump Pending event. */
+    gcmkVERIFY_OK(gckEVENT_Dump(Kernel->eventObj));
+
+    /* Dump Process DB. */
+    gcmkVERIFY_OK(gckKERNEL_DumpProcessDB(Kernel));
+
+#if gcdRECORD_COMMAND
+    /* Dump record. */
+    gckRECORDER_Dump(Kernel->command->recorder);
 #endif
+}
 
 /*******************************************************************************
 **
@@ -164,13 +339,13 @@ gckKERNEL_Construct(
 #if gcdDVFS
     kernel->dvfs         = gcvNULL;
 #endif
+    kernel->monitorTimer = gcvNULL;
 
     /* Initialize the gckKERNEL object. */
     kernel->object.type = gcvOBJ_KERNEL;
     kernel->os          = Os;
     kernel->core        = Core;
 
-
     if (SharedDB == gcvNULL)
     {
         gcmkONERROR(gckOS_Allocate(Os,
@@ -195,10 +370,16 @@ gckKERNEL_Construct(
         /* Construct a database mutex. */
         gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->dbMutex));
 
-        /* Construct a id-pointer database. */
+        /* Construct a video memory name database. */
+        gcmkONERROR(gckKERNEL_CreateIntegerDatabase(kernel, &kernel->db->nameDatabase));
+
+        /* Construct a video memory name database mutex. */
+        gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->nameDatabaseMutex));
+
+        /* Construct a pointer name database. */
         gcmkONERROR(gckKERNEL_CreateIntegerDatabase(kernel, &kernel->db->pointerDatabase));
 
-        /* Construct a id-pointer database mutex. */
+        /* Construct a pointer name database mutex. */
         gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->pointerDatabaseMutex));
     }
     else
@@ -213,19 +394,9 @@ gckKERNEL_Construct(
         kernel->timers[i].stopTime = 0;
     }
 
-    kernel->timeOut      = gcdGPU_TIMEOUT;
-
     /* Save context. */
     kernel->context = Context;
 
-#if gcdVIRTUAL_COMMAND_BUFFER
-    kernel->virtualBufferHead =
-    kernel->virtualBufferTail = gcvNULL;
-
-    gcmkONERROR(
-        gckOS_CreateMutex(Os, (gctPOINTER)&kernel->virtualBufferLock));
-#endif
-
     /* Construct atom holding number of clients. */
     kernel->atomClients = gcvNULL;
     gcmkONERROR(gckOS_AtomConstruct(Os, &kernel->atomClients));
@@ -238,6 +409,8 @@ gckKERNEL_Construct(
         /* Construct the gckMMU object. */
         gcmkONERROR(
             gckVGKERNEL_Construct(Os, Context, kernel, &kernel->vg));
+
+        kernel->timeOut = gcdGPU_TIMEOUT;
     }
     else
 #endif
@@ -249,9 +422,22 @@ gckKERNEL_Construct(
         /* Set pointer to gckKERNEL object in gckHARDWARE object. */
         kernel->hardware->kernel = kernel;
 
-        /* Initialize the hardware. */
-        gcmkONERROR(
-            gckHARDWARE_InitializeHardware(kernel->hardware));
+        kernel->timeOut = kernel->hardware->type == gcvHARDWARE_2D
+                        ? gcdGPU_2D_TIMEOUT
+                        : gcdGPU_TIMEOUT
+                        ;
+
+        /* Initialize virtual command buffer. */
+        /* TODO: Remove platform limitation after porting. */
+#if (defined(LINUX) || defined(__QNXNTO__))
+        kernel->virtualCommandBuffer = gcvTRUE;
+#else
+        kernel->virtualCommandBuffer = gcvFALSE;
+#endif
+
+#if gcdSECURITY
+        kernel->virtualCommandBuffer = gcvFALSE;
+#endif
 
         /* Construct the gckCOMMAND object. */
         gcmkONERROR(
@@ -265,17 +451,13 @@ gckKERNEL_Construct(
         gcmkONERROR(
             gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
 
-#if gcdENABLE_RECOVERY
-        gcmkONERROR(
-            gckOS_AtomConstruct(Os, &kernel->resetAtom));
+        gcmkVERIFY_OK(gckOS_GetTime(&kernel->resetTimeStamp));
 
-        gcmkVERIFY_OK(
-            gckOS_CreateTimer(Os,
-                              (gctTIMERFUNCTION)_ResetFinishFunction,
-                              (gctPOINTER)kernel,
-                              &kernel->resetFlagClearTimer));
-        kernel->resetTimeStamp = 0;
-#endif
+        gcmkONERROR(gckHARDWARE_PrepareFunctions(kernel->hardware));
+
+        /* Initialize the hardware. */
+        gcmkONERROR(
+            gckHARDWARE_InitializeHardware(kernel->hardware));
 
 #if gcdDVFS
         if (gckHARDWARE_IsFeatureAvailable(kernel->hardware,
@@ -297,6 +479,42 @@ gckKERNEL_Construct(
     gcmkONERROR(gckOS_CreateSyncTimeline(Os, &kernel->timeline));
 #endif
 
+    kernel->recovery      = gcvTRUE;
+    kernel->stuckDump     = 1;
+
+    kernel->virtualBufferHead =
+    kernel->virtualBufferTail = gcvNULL;
+
+    gcmkONERROR(
+        gckOS_CreateMutex(Os, (gctPOINTER)&kernel->virtualBufferLock));
+
+#if gcdSECURITY
+    /* Connect to security service for this GPU. */
+    gcmkONERROR(gckKERNEL_SecurityOpen(kernel, kernel->core, &kernel->securityChannel));
+#endif
+
+#if gcdGPU_TIMEOUT && gcdINTERRUPT_STATISTIC
+    if (kernel->timeOut)
+    {
+        gcmkVERIFY_OK(gckOS_CreateTimer(
+            Os,
+            (gctTIMERFUNCTION)_MonitorTimerFunction,
+            (gctPOINTER)kernel,
+            &kernel->monitorTimer
+            ));
+
+        kernel->monitoring  = gcvFALSE;
+
+        kernel->monitorTimerStop = gcvFALSE;
+
+        gcmkVERIFY_OK(gckOS_StartTimer(
+            Os,
+            kernel->monitorTimer,
+            100
+            ));
+    }
+#endif
+
     /* Return pointer to the gckKERNEL object. */
     *Kernel = kernel;
 
@@ -337,19 +555,6 @@ OnError:
             gcmkVERIFY_OK(gckOS_AtomDestroy(Os, kernel->atomClients));
         }
 
-#if gcdENABLE_RECOVERY
-        if (kernel->resetAtom != gcvNULL)
-        {
-            gcmkVERIFY_OK(gckOS_AtomDestroy(Os, kernel->resetAtom));
-        }
-
-        if (kernel->resetFlagClearTimer)
-        {
-            gcmkVERIFY_OK(gckOS_StopTimer(Os, kernel->resetFlagClearTimer));
-            gcmkVERIFY_OK(gckOS_DestroyTimer(Os, kernel->resetFlagClearTimer));
-        }
-#endif
-
         if (kernel->dbCreated && kernel->db != gcvNULL)
         {
             if (kernel->db->dbMutex != gcvNULL)
@@ -361,13 +566,11 @@ OnError:
             gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, kernel->db));
         }
 
-#if gcdVIRTUAL_COMMAND_BUFFER
         if (kernel->virtualBufferLock != gcvNULL)
         {
             /* Destroy the virtual command buffer mutex. */
             gcmkVERIFY_OK(gckOS_DeleteMutex(Os, kernel->virtualBufferLock));
         }
-#endif
 
 #if gcdDVFS
         if (kernel->dvfs)
@@ -384,6 +587,12 @@ OnError:
         }
 #endif
 
+        if (kernel->monitorTimer)
+        {
+            gcmkVERIFY_OK(gckOS_StopTimer(Os, kernel->monitorTimer));
+            gcmkVERIFY_OK(gckOS_DestroyTimer(Os, kernel->monitorTimer));
+        }
+
         gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, kernel));
     }
 
@@ -442,11 +651,14 @@ gckKERNEL_Destroy(
              database = databaseNext)
         {
             databaseNext = database->next;
+
+            gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, database->counterMutex));
             gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, database));
         }
 
         if (Kernel->db->lastDatabase != gcvNULL)
         {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->lastDatabase->counterMutex));
             gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel->db->lastDatabase));
         }
 
@@ -460,12 +672,24 @@ gckKERNEL_Destroy(
         /* Destroy the database mutex. */
         gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->dbMutex));
 
+        /* Destroy video memory name database. */
+        gcmkVERIFY_OK(gckKERNEL_DestroyIntegerDatabase(Kernel, Kernel->db->nameDatabase));
+
+        /* Destroy video memory name database mutex. */
+        gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->nameDatabaseMutex));
+
 
         /* Destroy id-pointer database. */
         gcmkVERIFY_OK(gckKERNEL_DestroyIntegerDatabase(Kernel, Kernel->db->pointerDatabase));
 
         /* Destroy id-pointer database mutex. */
         gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+
+        /* Destroy the database. */
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel->db));
+
+        /* Notify stuck timer to quit. */
+        Kernel->monitorTimerStop = gcvTRUE;
     }
 
 #if gcdENABLE_VG
@@ -487,24 +711,12 @@ gckKERNEL_Destroy(
 
         /* Destroy the gckHARDWARE object. */
         gcmkVERIFY_OK(gckHARDWARE_Destroy(Kernel->hardware));
-
-#if gcdENABLE_RECOVERY
-        gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Kernel->resetAtom));
-
-        if (Kernel->resetFlagClearTimer)
-        {
-            gcmkVERIFY_OK(gckOS_StopTimer(Kernel->os, Kernel->resetFlagClearTimer));
-            gcmkVERIFY_OK(gckOS_DestroyTimer(Kernel->os, Kernel->resetFlagClearTimer));
-        }
-#endif
     }
 
     /* Detsroy the client atom. */
     gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Kernel->atomClients));
 
-#if gcdVIRTUAL_COMMAND_BUFFER
     gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->virtualBufferLock));
-#endif
 
 #if gcdDVFS
     if (Kernel->dvfs)
@@ -518,6 +730,16 @@ gckKERNEL_Destroy(
     gcmkVERIFY_OK(gckOS_DestroySyncTimeline(Kernel->os, Kernel->timeline));
 #endif
 
+#if gcdSECURITY
+    gcmkVERIFY_OK(gckKERNEL_SecurityClose(Kernel->securityChannel));
+#endif
+
+    if (Kernel->monitorTimer)
+    {
+        gcmkVERIFY_OK(gckOS_StopTimer(Kernel->os, Kernel->monitorTimer));
+        gcmkVERIFY_OK(gckOS_DestroyTimer(Kernel->os, Kernel->monitorTimer));
+    }
+
     /* Mark the gckKERNEL object as unknown. */
     Kernel->object.type = gcvOBJ_UNKNOWN;
 
@@ -529,98 +751,6 @@ gckKERNEL_Destroy(
     return gcvSTATUS_OK;
 }
 
-#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/oom.h>
-#include <linux/sched.h>
-#include <linux/notifier.h>
-
-extern struct task_struct *lowmem_deathpending;
-static unsigned long lowmem_deathpending_timeout;
-
-static int force_contiguous_lowmem_shrink(IN gckKERNEL Kernel)
-{
-       struct task_struct *p;
-       struct task_struct *selected = NULL;
-       int tasksize;
-        int ret = -1;
-       int min_adj = 0;
-       int selected_tasksize = 0;
-       int selected_oom_adj;
-       /*
-        * If we already have a death outstanding, then
-        * bail out right away; indicating to vmscan
-        * that we have nothing further to offer on
-        * this pass.
-        *
-        */
-       if (lowmem_deathpending &&
-           time_before_eq(jiffies, lowmem_deathpending_timeout))
-               return 0;
-       selected_oom_adj = min_adj;
-
-       read_lock(&tasklist_lock);
-       for_each_process(p) {
-               struct mm_struct *mm;
-               struct signal_struct *sig;
-                gcuDATABASE_INFO info;
-               int oom_adj;
-
-               task_lock(p);
-               mm = p->mm;
-               sig = p->signal;
-               if (!mm || !sig) {
-                       task_unlock(p);
-                       continue;
-               }
-               oom_adj = sig->oom_adj;
-               if (oom_adj < min_adj) {
-                       task_unlock(p);
-                       continue;
-               }
-
-               tasksize = 0;
-               if (gckKERNEL_QueryProcessDB(Kernel, p->pid, gcvFALSE, gcvDB_VIDEO_MEMORY, &info) == gcvSTATUS_OK){
-                       tasksize += info.counters.bytes / PAGE_SIZE;
-               }
-               if (gckKERNEL_QueryProcessDB(Kernel, p->pid, gcvFALSE, gcvDB_CONTIGUOUS, &info) == gcvSTATUS_OK){
-                       tasksize += info.counters.bytes / PAGE_SIZE;
-               }
-
-               task_unlock(p);
-
-               if (tasksize <= 0)
-                       continue;
-
-               gckOS_Print("<gpu> pid %d (%s), adj %d, size %d \n", p->pid, p->comm, oom_adj, tasksize);
-
-               if (selected) {
-                       if (oom_adj < selected_oom_adj)
-                               continue;
-                       if (oom_adj == selected_oom_adj &&
-                           tasksize <= selected_tasksize)
-                               continue;
-               }
-               selected = p;
-               selected_tasksize = tasksize;
-               selected_oom_adj = oom_adj;
-       }
-       if (selected) {
-               gckOS_Print("<gpu> send sigkill to %d (%s), adj %d, size %d\n",
-                            selected->pid, selected->comm,
-                            selected_oom_adj, selected_tasksize);
-               lowmem_deathpending = selected;
-               lowmem_deathpending_timeout = jiffies + HZ;
-               force_sig(SIGKILL, selected);
-               ret = 0;
-       }
-       read_unlock(&tasklist_lock);
-       return ret;
-}
-
-#endif
-
 /*******************************************************************************
 **
 **  _AllocateMemory
@@ -643,14 +773,16 @@ static int force_contiguous_lowmem_shrink(IN gckKERNEL Kernel)
 **          Pointer to a gcsHAL_INTERFACE structure that receives any data to be
 **          returned.
 */
-static gceSTATUS
-_AllocateMemory(
+gceSTATUS
+gckKERNEL_AllocateLinearMemory(
     IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
     IN OUT gcePOOL * Pool,
     IN gctSIZE_T Bytes,
-    IN gctSIZE_T Alignment,
+    IN gctUINT32 Alignment,
     IN gceSURF_TYPE Type,
-    OUT gcuVIDMEM_NODE_PTR * Node
+    IN gctUINT32 Flag,
+    OUT gctUINT32 * Node
     )
 {
     gcePOOL pool;
@@ -659,7 +791,11 @@ _AllocateMemory(
     gctINT loopCount;
     gcuVIDMEM_NODE_PTR node = gcvNULL;
     gctBOOL tileStatusInVirtual;
-    gctBOOL forceContiguous = gcvFALSE;
+    gctBOOL contiguous = gcvFALSE;
+    gctBOOL cacheable = gcvFALSE;
+    gctSIZE_T bytes = Bytes;
+    gctUINT32 handle = 0;
+    gceDATABASE_TYPE type;
 
     gcmkHEADER_ARG("Kernel=0x%x *Pool=%d Bytes=%lu Alignment=%lu Type=%d",
                    Kernel, *Pool, Bytes, Alignment, Type);
@@ -667,14 +803,18 @@ _AllocateMemory(
     gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
     gcmkVERIFY_ARGUMENT(Bytes != 0);
 
-#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
-_AllocateMemory_Retry:
-#endif
+     /* Get basic type. */
+     Type &= 0xFF;
+
+    /* Check flags. */
+    contiguous = Flag & gcvALLOC_FLAG_CONTIGUOUS;
+    cacheable  = Flag & gcvALLOC_FLAG_CACHEABLE;
+
+AllocateMemory:
+
     /* Get initial pool. */
     switch (pool = *Pool)
     {
-    case gcvPOOL_DEFAULT_FORCE_CONTIGUOUS:
-        forceContiguous = gcvTRUE;
     case gcvPOOL_DEFAULT:
     case gcvPOOL_LOCAL:
         pool      = gcvPOOL_LOCAL_INTERNAL;
@@ -690,12 +830,6 @@ _AllocateMemory_Retry:
         loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
         break;
 
-    case gcvPOOL_DEFAULT_FORCE_CONTIGUOUS_CACHEABLE:
-        pool      = gcvPOOL_CONTIGUOUS;
-        loopCount = 1;
-        forceContiguous = gcvTRUE;
-        break;
-
     default:
         loopCount = 1;
         break;
@@ -707,7 +841,10 @@ _AllocateMemory_Retry:
         {
             /* Create a gcuVIDMEM_NODE for virtual memory. */
             gcmkONERROR(
-                gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, &node));
+                gckVIDMEM_ConstructVirtual(Kernel, Flag | gcvALLOC_FLAG_NON_CONTIGUOUS, Bytes, &node));
+
+            bytes = node->Virtual.bytes;
+            node->Virtual.type = Type;
 
             /* Success. */
             break;
@@ -717,7 +854,7 @@ _AllocateMemory_Retry:
         if (pool == gcvPOOL_CONTIGUOUS)
         {
 #if gcdCONTIGUOUS_SIZE_LIMIT
-            if (Bytes > gcdCONTIGUOUS_SIZE_LIMIT && forceContiguous == gcvFALSE)
+            if (Bytes > gcdCONTIGUOUS_SIZE_LIMIT && contiguous == gcvFALSE)
             {
                 status = gcvSTATUS_OUT_OF_MEMORY;
             }
@@ -725,88 +862,56 @@ _AllocateMemory_Retry:
 #endif
             {
                 /* Create a gcuVIDMEM_NODE from contiguous memory. */
-                status = gckVIDMEM_ConstructVirtual(Kernel, gcvTRUE, Bytes, &node);
+                status = gckVIDMEM_ConstructVirtual(
+                            Kernel,
+                            Flag | gcvALLOC_FLAG_CONTIGUOUS,
+                            Bytes,
+                            &node);
             }
 
-            if (gcmIS_SUCCESS(status) || forceContiguous == gcvTRUE)
+            if (gcmIS_SUCCESS(status))
             {
-                /* Memory allocated. */
-                if(node && forceContiguous == gcvTRUE)
-                {
-                    gctUINT32 physAddr=0;
-                    gctUINT32 baseAddress = 0;
-
-                    gcmkONERROR(
-                        gckOS_LockPages(Kernel->os,
-                                        node->Virtual.physical,
-                                        node->Virtual.bytes,
-                                        gcvFALSE,
-                                        &node->Virtual.logical,
-                                        &node->Virtual.pageCount));
-
-                    /* Convert logical address into a physical address. */
-                    gcmkONERROR(
-                        gckOS_GetPhysicalAddress(Kernel->os,
-                                                 node->Virtual.logical,
-                                                 &physAddr));
-
-                    gcmkONERROR(
-                        gckOS_UnlockPages(Kernel->os,
-                                          node->Virtual.physical,
-                                          node->Virtual.bytes,
-                                          node->Virtual.logical));
-
-                    gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &baseAddress));
-
-                    gcmkASSERT(physAddr >= baseAddress);
-
-                    /* Subtract baseAddress to get a GPU address used for programming. */
-                    physAddr -= baseAddress;
-
-                    if((physAddr & 0x80000000) || ((physAddr + Bytes) & 0x80000000))
-                    {
-                        gckOS_Print("gpu virtual memory 0x%x cannot be allocated in force contiguous request!\n", physAddr);
-
-                        gcmkONERROR(gckVIDMEM_Free(node));
-
-                        node = gcvNULL;
-                    }
-                }
+                bytes = node->Virtual.bytes;
+                node->Virtual.type = Type;
 
+                /* Memory allocated. */
                 break;
             }
         }
 
         else
+        /* gcvPOOL_SYSTEM can't be cacheable. */
+        if (cacheable == gcvFALSE)
         {
             /* Get pointer to gckVIDMEM object for pool. */
-#if gcdUSE_VIDMEM_PER_PID
-            gctUINT32 pid;
-            gckOS_GetProcessID(&pid);
-
-            status = gckKERNEL_GetVideoMemoryPoolPid(Kernel, pool, pid, &videoMemory);
-            if (status == gcvSTATUS_NOT_FOUND)
-            {
-                /* Create VidMem pool for this process. */
-                status = gckKERNEL_CreateVideoMemoryPoolPid(Kernel, pool, pid, &videoMemory);
-            }
-#else
             status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
-#endif
 
             if (gcmIS_SUCCESS(status))
             {
                 /* Allocate memory. */
-                status = gckVIDMEM_AllocateLinear(videoMemory,
-                                                  Bytes,
-                                                  Alignment,
-                                                  Type,
-                                                  &node);
+#if defined(gcdLINEAR_SIZE_LIMIT)
+                /* 512 KB */
+                if (Bytes > gcdLINEAR_SIZE_LIMIT)
+                {
+                    status = gcvSTATUS_OUT_OF_MEMORY;
+                }
+                else
+#endif
+                {
+                    status = gckVIDMEM_AllocateLinear(Kernel,
+                                                      videoMemory,
+                                                      Bytes,
+                                                      Alignment,
+                                                      Type,
+                                                      (*Pool == gcvPOOL_SYSTEM),
+                                                      &node);
+                }
 
                 if (gcmIS_SUCCESS(status))
                 {
                     /* Memory allocated. */
                     node->VidMem.pool = pool;
+                    bytes = node->VidMem.bytes;
                     break;
                 }
             }
@@ -835,15 +940,29 @@ _AllocateMemory_Retry:
         else
         if (pool == gcvPOOL_CONTIGUOUS)
         {
-            tileStatusInVirtual =
-                gckHARDWARE_IsFeatureAvailable(Kernel->hardware,
-                                               gcvFEATURE_MC20);
+#if gcdENABLE_VG
+            if (Kernel->vg)
+            {
+                tileStatusInVirtual = gcvFALSE;
+            }
+            else
+#endif
+            {
+                tileStatusInVirtual =
+                    gckHARDWARE_IsFeatureAvailable(Kernel->hardware,
+                                                   gcvFEATURE_MC20);
+            }
 
             if (Type == gcvSURF_TILE_STATUS && tileStatusInVirtual != gcvTRUE)
             {
                 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
             }
 
+            if (contiguous)
+            {
+                break;
+            }
+
             /* Advance to virtual memory. */
             pool = gcvPOOL_VIRTUAL;
         }
@@ -857,31 +976,68 @@ _AllocateMemory_Retry:
 
     if (node == gcvNULL)
     {
-
-#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
-        if(forceContiguous == gcvTRUE)
+        if (contiguous)
         {
-            if(force_contiguous_lowmem_shrink(Kernel) == 0)
+            /* Broadcast OOM message. */
+            status = gckOS_Broadcast(Kernel->os, Kernel->hardware, gcvBROADCAST_OUT_OF_MEMORY);
+
+            if (gcmIS_SUCCESS(status))
             {
-                 /* Sleep 1 millisecond. */
-                 gckOS_Delay(gcvNULL, 1);
-                 goto _AllocateMemory_Retry;
+                /* Get some memory. */
+                gckOS_Delay(gcvNULL, 1);
+                goto AllocateMemory;
             }
         }
-#endif
+
         /* Nothing allocated. */
         gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
     }
 
+    /* Allocate handle for this video memory. */
+    gcmkONERROR(
+        gckVIDMEM_NODE_Allocate(Kernel, node, Type, pool, &handle));
+
     /* Return node and pool used for allocation. */
-    *Node = node;
+    *Node = handle;
     *Pool = pool;
 
+    /* Encode surface type and pool to database type. */
+    type = gcvDB_VIDEO_MEMORY
+         | (Type << gcdDB_VIDEO_MEMORY_TYPE_SHIFT)
+         | (pool << gcdDB_VIDEO_MEMORY_POOL_SHIFT);
+
+    /* Record in process db. */
+    gcmkONERROR(
+            gckKERNEL_AddProcessDB(Kernel,
+                                   ProcessID,
+                                   type,
+                                   gcmINT2PTR(handle),
+                                   gcvNULL,
+                                   bytes));
+
     /* Return status. */
     gcmkFOOTER_ARG("*Pool=%d *Node=0x%x", *Pool, *Node);
     return gcvSTATUS_OK;
 
 OnError:
+    if (handle)
+    {
+        /* Destroy handle allocated. */
+        gcmkVERIFY_OK(gckVIDMEM_HANDLE_Dereference(Kernel, ProcessID, handle));
+    }
+
+    if (node)
+    {
+        /* Free video memory allocated. */
+        gcmkVERIFY_OK(gckVIDMEM_Free(Kernel, node));
+    }
+
+    /* For some case like chrome with webgl test, it needs too much memory so that it invokes oom_killer
+    * And the case is killed by oom_killer, the user wants not to see the crash and hope the case iteself handles the condition
+    * So the patch reports the out_of_memory to the case */
+    if ( status == gcvSTATUS_OUT_OF_MEMORY && (Flag & gcvALLOC_FLAG_MEMLIMIT) )
+        gcmkPRINT("The running case is out_of_memory");
+
     /* Return the status. */
     gcmkFOOTER();
     return status;
@@ -889,514 +1045,789 @@ OnError:
 
 /*******************************************************************************
 **
-**  gckKERNEL_Dispatch
+**  gckKERNEL_ReleaseVideoMemory
 **
-**  Dispatch a command received from the user HAL layer.
+**  Release handle of a video memory.
 **
 **  INPUT:
 **
 **      gckKERNEL Kernel
 **          Pointer to an gckKERNEL object.
 **
-**      gctBOOL FromUser
-**          whether the call is from the user space.
+**      gctUINT32 ProcessID
+**          ProcessID of current process.
 **
-**      gcsHAL_INTERFACE * Interface
-**          Pointer to a gcsHAL_INTERFACE structure that defines the command to
-**          be dispatched.
+**      gctUINT32 Handle
+**          Handle of video memory.
 **
 **  OUTPUT:
 **
-**      gcsHAL_INTERFACE * Interface
-**          Pointer to a gcsHAL_INTERFACE structure that receives any data to be
-**          returned.
+**          Nothing.
 */
-
 gceSTATUS
-gckKERNEL_Dispatch(
+gckKERNEL_ReleaseVideoMemory(
     IN gckKERNEL Kernel,
-    IN gctBOOL FromUser,
-    IN OUT gcsHAL_INTERFACE * Interface
+    IN gctUINT32 ProcessID,
+    IN gctUINT32 Handle
     )
 {
-    gceSTATUS status = gcvSTATUS_OK;
-    gctSIZE_T bytes;
-    gcuVIDMEM_NODE_PTR node;
-    gctBOOL locked = gcvFALSE;
-    gctPHYS_ADDR physical = gcvNULL;
-    gctPOINTER logical = gcvNULL;
-    gctPOINTER info = gcvNULL;
-    gckCONTEXT context = gcvNULL;
-    gctUINT32 address;
-    gctUINT32 processID;
-    gckKERNEL kernel = Kernel;
-#if gcdSECURE_USER
-    gcskSECURE_CACHE_PTR cache;
-#endif
-    gctBOOL asynchronous;
-    gctPOINTER paddr = gcvNULL;
-#if !USE_NEW_LINUX_SIGNAL
-    gctSIGNAL   signal;
-#endif
-    gceSURF_TYPE type;
+    gceSTATUS status;
+    gckVIDMEM_NODE nodeObject;
+    gceDATABASE_TYPE type;
 
-    gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
-                   Kernel, FromUser, Interface);
+    gcmkHEADER_ARG("Kernel=0x%08X ProcessID=%d Handle=%d",
+                   Kernel, ProcessID, Handle);
 
-    /* Verify the arguments. */
-    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
-    gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+    gcmkONERROR(
+        gckVIDMEM_HANDLE_Lookup(Kernel, ProcessID, Handle, &nodeObject));
 
-#if gcmIS_DEBUG(gcdDEBUG_TRACE)
-    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
-                   "Dispatching command %d (%s)",
-                   Interface->command, _DispatchText[Interface->command]);
-#endif
-#if QNX_SINGLE_THREADED_DEBUGGING
-    gckOS_AcquireMutex(Kernel->os, Kernel->debugMutex, gcvINFINITE);
-#endif
+    type = gcvDB_VIDEO_MEMORY
+         | (nodeObject->type << gcdDB_VIDEO_MEMORY_TYPE_SHIFT)
+         | (nodeObject->pool << gcdDB_VIDEO_MEMORY_POOL_SHIFT);
 
-    /* Get the current process ID. */
-    gcmkONERROR(gckOS_GetProcessID(&processID));
+    gcmkONERROR(
+        gckKERNEL_RemoveProcessDB(Kernel,
+            ProcessID,
+            type,
+            gcmINT2PTR(Handle)));
 
-#if gcdSECURE_USER
-    gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
-#endif
+    gckVIDMEM_HANDLE_Dereference(Kernel, ProcessID, Handle);
 
-    /* Dispatch on command. */
-    switch (Interface->command)
-    {
-    case gcvHAL_GET_BASE_ADDRESS:
-        /* Get base address. */
-        gcmkONERROR(
-            gckOS_GetBaseAddress(Kernel->os,
-                                 &Interface->u.GetBaseAddress.baseAddress));
-        break;
+    gckVIDMEM_NODE_Dereference(Kernel, nodeObject);
 
-    case gcvHAL_QUERY_VIDEO_MEMORY:
-        /* Query video memory size. */
-        gcmkONERROR(gckKERNEL_QueryVideoMemory(Kernel, Interface));
-        break;
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
 
-    case gcvHAL_QUERY_CHIP_IDENTITY:
-        /* Query chip identity. */
-        gcmkONERROR(
-            gckHARDWARE_QueryChipIdentity(
-                Kernel->hardware,
-                &Interface->u.QueryChipIdentity));
-        break;
+OnError:
+    gcmkFOOTER();
+    return status;
+}
 
-    case gcvHAL_MAP_MEMORY:
-        physical = gcmINT2PTR(Interface->u.MapMemory.physical);
+/*******************************************************************************
+**
+**  gckKERNEL_LockVideoMemory
+**
+**      Lock a video memory node. It will generate a cpu virtual address used
+**      by software and a GPU address used by GPU.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gceCORE Core
+**          GPU to which video memory is locked.
+**
+**      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_LockVideoMemory(
+    IN gckKERNEL Kernel,
+    IN gceCORE Core,
+    IN gctUINT32 ProcessID,
+    IN gctBOOL FromUser,
+    IN OUT gcsHAL_INTERFACE * Interface
+    )
+{
+    gceSTATUS status;
+    gckVIDMEM_NODE nodeObject = gcvNULL;
+    gcuVIDMEM_NODE_PTR node   = gcvNULL;
+    gctBOOL locked            = gcvFALSE;
+    gctBOOL asynchronous      = gcvFALSE;
+#ifndef __QNXNTO__
+    gctPOINTER pointer        = gcvNULL;
+#endif
 
-        /* Map memory. */
-        gcmkONERROR(
-            gckKERNEL_MapMemory(Kernel,
-                                physical,
-                                (gctSIZE_T) Interface->u.MapMemory.bytes,
-                                &logical));
+    gcmkHEADER_ARG("Kernel=0x%08X ProcessID=%d",
+                   Kernel, ProcessID);
 
-        Interface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
+    gcmkONERROR(
+        gckVIDMEM_HANDLE_LookupAndReference(Kernel,
+                Interface->u.LockVideoMemory.node,
+                &nodeObject));
 
-        gcmkVERIFY_OK(
-            gckKERNEL_AddProcessDB(Kernel,
-                                   processID, gcvDB_MAP_MEMORY,
-                                   logical,
-                                   physical,
-                                   (gctSIZE_T) Interface->u.MapMemory.bytes));
-        break;
+    node = nodeObject->node;
 
-    case gcvHAL_UNMAP_MEMORY:
-        physical = gcmINT2PTR(Interface->u.UnmapMemory.physical);
+    Interface->u.LockVideoMemory.gid = 0;
 
-        /* Unmap memory. */
-        gcmkONERROR(
-            gckKERNEL_UnmapMemory(Kernel,
-                                  physical,
-                                  (gctSIZE_T) Interface->u.UnmapMemory.bytes,
-                                  gcmUINT64_TO_PTR(Interface->u.UnmapMemory.logical)));
-        gcmkVERIFY_OK(
-            gckKERNEL_RemoveProcessDB(Kernel,
-                                      processID, gcvDB_MAP_MEMORY,
-                                      gcmUINT64_TO_PTR(Interface->u.UnmapMemory.logical)));
-        break;
+    /* Lock video memory. */
+    gcmkONERROR(
+            gckVIDMEM_Lock(Kernel,
+                nodeObject,
+                Interface->u.LockVideoMemory.cacheable,
+                &Interface->u.LockVideoMemory.address,
+                &Interface->u.LockVideoMemory.gid,
+                &Interface->u.LockVideoMemory.physicalAddress));
 
-    case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
-        bytes = (gctSIZE_T) Interface->u.AllocateNonPagedMemory.bytes;
+    locked = gcvTRUE;
 
-        /* Allocate non-paged memory. */
+    if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+    {
+        /* Map video memory address into user space. */
+#ifdef __QNXNTO__
+        if (node->VidMem.logical == gcvNULL)
+        {
+            gcmkONERROR(
+                    gckKERNEL_MapVideoMemory(Kernel,
+                        FromUser,
+                        Interface->u.LockVideoMemory.address,
+                        ProcessID,
+                        node->VidMem.bytes,
+                        &node->VidMem.logical));
+        }
+        gcmkASSERT(node->VidMem.logical != gcvNULL);
+
+        Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->VidMem.logical);
+#else
         gcmkONERROR(
-            gckOS_AllocateNonPagedMemory(
-                Kernel->os,
-                FromUser,
-                &bytes,
-                &physical,
-                &logical));
+                gckKERNEL_MapVideoMemoryEx(Kernel,
+                    Core,
+                    FromUser,
+                    Interface->u.LockVideoMemory.address,
+                    &pointer));
 
-        Interface->u.AllocateNonPagedMemory.bytes    = bytes;
-        Interface->u.AllocateNonPagedMemory.logical  = gcmPTR_TO_UINT64(logical);
-        Interface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
+        Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(pointer);
+#endif
+    }
+    else
+    {
+        Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->Virtual.logical);
 
-        gcmkVERIFY_OK(
-            gckKERNEL_AddProcessDB(Kernel,
-                                   processID, gcvDB_NON_PAGED,
-                                   logical,
-                                   gcmINT2PTR(Interface->u.AllocateNonPagedMemory.physical),
-                                   bytes));
+        /* Success. */
+        status = gcvSTATUS_OK;
+    }
 
-        break;
+#if gcdPROCESS_ADDRESS_SPACE
+    gcmkONERROR(gckVIDMEM_Node_Lock(
+        Kernel,
+        nodeObject,
+        &Interface->u.LockVideoMemory.address
+        ));
+#endif
 
-    case gcvHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER:
-#if gcdVIRTUAL_COMMAND_BUFFER
-        bytes = (gctSIZE_T) Interface->u.AllocateVirtualCommandBuffer.bytes;
 
-        gcmkONERROR(
-            gckKERNEL_AllocateVirtualCommandBuffer(
-                Kernel,
-                FromUser,
-                &bytes,
-                &physical,
-                &logical));
+#if gcdSECURE_USER
+    /* Return logical address as physical address. */
+    Interface->u.LockVideoMemory.address =
+        (gctUINT32)(Interface->u.LockVideoMemory.memory);
+#endif
+    gcmkONERROR(
+        gckKERNEL_AddProcessDB(Kernel,
+            ProcessID, gcvDB_VIDEO_MEMORY_LOCKED,
+            gcmINT2PTR(Interface->u.LockVideoMemory.node),
+            gcvNULL,
+            0));
 
-        Interface->u.AllocateVirtualCommandBuffer.bytes    = bytes;
-        Interface->u.AllocateVirtualCommandBuffer.logical  = gcmPTR_TO_UINT64(logical);
-        Interface->u.AllocateVirtualCommandBuffer.physical = gcmPTR_TO_NAME(physical);
+    gckVIDMEM_HANDLE_Reference(
+        Kernel, ProcessID, (gctUINT32)Interface->u.LockVideoMemory.node);
 
-        gcmkVERIFY_OK(
-            gckKERNEL_AddProcessDB(Kernel,
-                                   processID, gcvDB_COMMAND_BUFFER,
-                                   logical,
-                                   gcmINT2PTR(Interface->u.AllocateVirtualCommandBuffer.physical),
-                                   bytes));
-#else
-        status = gcvSTATUS_NOT_SUPPORTED;
-#endif
-        break;
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
 
-    case gcvHAL_FREE_NON_PAGED_MEMORY:
-        physical = gcmNAME_TO_PTR(Interface->u.FreeNonPagedMemory.physical);
+OnError:
+    if (locked)
+    {
+        /* Roll back the lock. */
+        gcmkVERIFY_OK(gckVIDMEM_Unlock(Kernel,
+                    nodeObject,
+                    gcvSURF_TYPE_UNKNOWN,
+                    &asynchronous));
 
-        /* Unmap user logical out of physical memory first. */
-        gcmkONERROR(gckOS_UnmapUserLogical(Kernel->os,
-                                           physical,
-                                           (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
-                                           gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+        if (gcvTRUE == asynchronous)
+        {
+            /* Bottom Half */
+            gcmkVERIFY_OK(gckVIDMEM_Unlock(Kernel,
+                        nodeObject,
+                        gcvSURF_TYPE_UNKNOWN,
+                        gcvNULL));
+        }
+    }
 
-        /* Free non-paged memory. */
-        gcmkONERROR(
-            gckOS_FreeNonPagedMemory(Kernel->os,
-                                     (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
-                                     physical,
-                                     gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+    if (nodeObject != gcvNULL)
+    {
+        gckVIDMEM_NODE_Dereference(Kernel, nodeObject);
+    }
 
-        gcmkVERIFY_OK(
-            gckKERNEL_RemoveProcessDB(Kernel,
-                                      processID, gcvDB_NON_PAGED,
-                                      gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+    gcmkFOOTER();
+    return status;
+}
 
-#if gcdSECURE_USER
-        gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
-            Kernel,
-            cache,
-            gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical),
-            Interface->u.FreeNonPagedMemory.bytes));
-#endif
+/*******************************************************************************
+**
+**  gckKERNEL_UnlockVideoMemory
+**
+**      Unlock a video memory node.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctUINT32 ProcessID
+**          ProcessID of current process.
+**
+**      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_UnlockVideoMemory(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN OUT gcsHAL_INTERFACE * Interface
+    )
+{
+    gceSTATUS status;
+    gckVIDMEM_NODE nodeObject;
+    gcuVIDMEM_NODE_PTR node;
 
-        gcmRELEASE_NAME(Interface->u.FreeNonPagedMemory.physical);
+    gcmkHEADER_ARG("Kernel=0x%08X ProcessID=%d",
+                   Kernel, ProcessID);
 
-        break;
+    gcmkONERROR(gckVIDMEM_HANDLE_Lookup(
+        Kernel,
+        ProcessID,
+        (gctUINT32)Interface->u.UnlockVideoMemory.node,
+        &nodeObject));
 
-    case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
-        bytes = (gctSIZE_T) Interface->u.AllocateContiguousMemory.bytes;
+    node = nodeObject->node;
 
-        /* Allocate contiguous memory. */
-        gcmkONERROR(gckOS_AllocateContiguous(
-            Kernel->os,
-            FromUser,
-            &bytes,
-            &physical,
-            &logical));
+    /* Unlock video memory. */
+#if gcdSECURE_USER
+    /* Save node information before it disappears. */
+    if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+    {
+        logical = gcvNULL;
+        bytes   = 0;
+    }
+    else
+    {
+        logical = node->Virtual.logical;
+        bytes   = node->Virtual.bytes;
+    }
+#endif
 
-        Interface->u.AllocateContiguousMemory.bytes    = bytes;
-        Interface->u.AllocateContiguousMemory.logical  = gcmPTR_TO_UINT64(logical);
-        Interface->u.AllocateContiguousMemory.physical = gcmPTR_TO_NAME(physical);
-
-        gcmkONERROR(gckHARDWARE_ConvertLogical(
-            Kernel->hardware,
-            gcmUINT64_TO_PTR(Interface->u.AllocateContiguousMemory.logical),
-            &Interface->u.AllocateContiguousMemory.address));
-
-        gcmkVERIFY_OK(gckKERNEL_AddProcessDB(
-            Kernel,
-            processID, gcvDB_CONTIGUOUS,
-            logical,
-            gcmINT2PTR(Interface->u.AllocateContiguousMemory.physical),
-            bytes));
-
-        break;
-
-    case gcvHAL_FREE_CONTIGUOUS_MEMORY:
-        physical = gcmNAME_TO_PTR(Interface->u.FreeContiguousMemory.physical);
-
-        /* Unmap user logical out of physical memory first. */
-        gcmkONERROR(gckOS_UnmapUserLogical(Kernel->os,
-                                           physical,
-                                           (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes,
-                                           gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical)));
-
-        /* Free contiguous memory. */
-        gcmkONERROR(
-            gckOS_FreeContiguous(Kernel->os,
-                                 physical,
-                                 gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical),
-                                 (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes));
-
-        gcmkVERIFY_OK(
-            gckKERNEL_RemoveProcessDB(Kernel,
-                                      processID, gcvDB_CONTIGUOUS,
-                                      gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+    /* Unlock video memory. */
+    gcmkONERROR(gckVIDMEM_Unlock(
+        Kernel,
+        nodeObject,
+        Interface->u.UnlockVideoMemory.type,
+        &Interface->u.UnlockVideoMemory.asynchroneous));
 
 #if gcdSECURE_USER
-        gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
-            Kernel,
-            cache,
-            gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical),
-            Interface->u.FreeContiguousMemory.bytes));
+    /* Flush the translation cache for virtual surfaces. */
+    if (logical != gcvNULL)
+    {
+        gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
+                    cache,
+                    logical,
+                    bytes));
+    }
 #endif
 
-        gcmRELEASE_NAME(Interface->u.FreeContiguousMemory.physical);
-
-        break;
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
 
-    case gcvHAL_ALLOCATE_VIDEO_MEMORY:
+OnError:
+    gcmkFOOTER();
+    return status;
+}
 
-        gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+gceSTATUS
+gckKERNEL_QueryDatabase(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN OUT gcsHAL_INTERFACE * Interface
+    )
+{
+    gceSTATUS status;
+    gctINT i;
+    gcuDATABASE_INFO tmp;
 
-        break;
+    gceDATABASE_TYPE type[3] = {
+        gcvDB_VIDEO_MEMORY | (gcvPOOL_SYSTEM << gcdDB_VIDEO_MEMORY_POOL_SHIFT),
+        gcvDB_VIDEO_MEMORY | (gcvPOOL_CONTIGUOUS << gcdDB_VIDEO_MEMORY_POOL_SHIFT),
+        gcvDB_VIDEO_MEMORY | (gcvPOOL_VIRTUAL << gcdDB_VIDEO_MEMORY_POOL_SHIFT),
+    };
 
-    case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
-        type = Interface->u.AllocateLinearVideoMemory.type;
+    gcmkHEADER();
 
-        /* Allocate memory. */
-        gcmkONERROR(
-            _AllocateMemory(Kernel,
-                            &Interface->u.AllocateLinearVideoMemory.pool,
-                            Interface->u.AllocateLinearVideoMemory.bytes,
-                            Interface->u.AllocateLinearVideoMemory.alignment,
-                            Interface->u.AllocateLinearVideoMemory.type,
-                            &node));
+    /* Query video memory. */
+    gcmkONERROR(
+        gckKERNEL_QueryProcessDB(Kernel,
+                                 Interface->u.Database.processID,
+                                 !Interface->u.Database.validProcessID,
+                                 gcvDB_VIDEO_MEMORY,
+                                 &Interface->u.Database.vidMem));
 
-        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
-        {
-            bytes = node->VidMem.bytes;
-            node->VidMem.type = type;
+    /* Query non-paged memory. */
+    gcmkONERROR(
+        gckKERNEL_QueryProcessDB(Kernel,
+                                 Interface->u.Database.processID,
+                                 !Interface->u.Database.validProcessID,
+                                 gcvDB_NON_PAGED,
+                                 &Interface->u.Database.nonPaged));
 
-            gcmkONERROR(
-                gckKERNEL_AddProcessDB(Kernel,
-                                   processID, gcvDB_VIDEO_MEMORY_RESERVED,
-                                   node,
-                                   gcvNULL,
-                                   bytes));
-        }
-        else
-        {
-            bytes = node->Virtual.bytes;
-            node->Virtual.type = type;
+    /* Query contiguous memory. */
+    gcmkONERROR(
+        gckKERNEL_QueryProcessDB(Kernel,
+                                 Interface->u.Database.processID,
+                                 !Interface->u.Database.validProcessID,
+                                 gcvDB_CONTIGUOUS,
+                                 &Interface->u.Database.contiguous));
 
-            if(node->Virtual.contiguous)
-            {
-                gcmkONERROR(
-                    gckKERNEL_AddProcessDB(Kernel,
-                                   processID, gcvDB_VIDEO_MEMORY_CONTIGUOUS,
-                                   node,
-                                   gcvNULL,
-                                   bytes));
-            }
-            else
-            {
-                gcmkONERROR(
-                    gckKERNEL_AddProcessDB(Kernel,
-                                   processID, gcvDB_VIDEO_MEMORY_VIRTUAL,
-                                   node,
-                                   gcvNULL,
-                                   bytes));
-            }
+    /* Query GPU idle time. */
+    gcmkONERROR(
+        gckKERNEL_QueryProcessDB(Kernel,
+                                 Interface->u.Database.processID,
+                                 !Interface->u.Database.validProcessID,
+                                 gcvDB_IDLE,
+                                 &Interface->u.Database.gpuIdle));
+    for (i = 0; i < 3; i++)
+    {
+        /* Query each video memory pool. */
+        gcmkONERROR(
+            gckKERNEL_QueryProcessDB(Kernel,
+                                     Interface->u.Database.processID,
+                                     !Interface->u.Database.validProcessID,
+                                     type[i],
+                                     &Interface->u.Database.vidMemPool[i]));
+    }
 
-        }
+    /* Query virtual command buffer pool. */
+    gcmkONERROR(
+        gckKERNEL_QueryProcessDB(Kernel,
+                                 Interface->u.Database.processID,
+                                 !Interface->u.Database.validProcessID,
+                                 gcvDB_COMMAND_BUFFER,
+                                 &tmp));
 
-        gcmkONERROR(
-            gckKERNEL_AddProcessDB(Kernel,
-                                   processID, gcvDB_VIDEO_MEMORY,
-                                   node,
-                                   gcvNULL,
-                                   bytes));
+    Interface->u.Database.vidMemPool[2].counters.bytes += tmp.counters.bytes;
+    Interface->u.Database.vidMemPool[2].counters.maxBytes += tmp.counters.maxBytes;
+    Interface->u.Database.vidMemPool[2].counters.totalBytes += tmp.counters.totalBytes;
 
-        /* Get the node. */
-        Interface->u.AllocateLinearVideoMemory.node = gcmPTR_TO_UINT64(node);
-        break;
+    Interface->u.Database.vidMem.counters.bytes += tmp.counters.bytes;
+    Interface->u.Database.vidMem.counters.maxBytes += tmp.counters.maxBytes;
+    Interface->u.Database.vidMem.counters.totalBytes += tmp.counters.totalBytes;
 
-    case gcvHAL_FREE_VIDEO_MEMORY:
-        node = gcmUINT64_TO_PTR(Interface->u.FreeVideoMemory.node);
-#ifdef __QNXNTO__
-        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM
-         && node->VidMem.logical != gcvNULL)
-        {
-            gcmkONERROR(
-                    gckKERNEL_UnmapVideoMemory(Kernel,
-                                               node->VidMem.logical,
-                                               processID,
-                                               node->VidMem.bytes));
-            node->VidMem.logical = gcvNULL;
-        }
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+    gckKERNEL_DumpVidMemUsage(Kernel, Interface->u.Database.processID);
 #endif
-        /* Free video memory. */
-        gcmkONERROR(
-            gckVIDMEM_Free(node));
 
-        gcmkONERROR(
-            gckKERNEL_RemoveProcessDB(Kernel,
-                                      processID, gcvDB_VIDEO_MEMORY,
-                                      node));
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
 
-        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
-        {
-           gcmkONERROR(
-                gckKERNEL_RemoveProcessDB(Kernel,
-                                      processID, gcvDB_VIDEO_MEMORY_RESERVED,
-                                      node));
-        }
-        else if(node->Virtual.contiguous)
-        {
-            gcmkONERROR(
-                gckKERNEL_RemoveProcessDB(Kernel,
-                                      processID, gcvDB_VIDEO_MEMORY_CONTIGUOUS,
-                                      node));
-        }
-        else
-        {
-            gcmkONERROR(
-                gckKERNEL_RemoveProcessDB(Kernel,
-                                      processID, gcvDB_VIDEO_MEMORY_VIRTUAL,
-                                      node));
-        }
+OnError:
+    gcmkFOOTER();
+    return status;
+}
 
-        break;
+gceSTATUS
+gckKERNEL_ConfigPowerManagement(
+    IN gckKERNEL Kernel,
+    IN OUT gcsHAL_INTERFACE * Interface
+)
+{
+    gceSTATUS status;
+    gctBOOL enable = Interface->u.ConfigPowerManagement.enable;
 
-    case gcvHAL_LOCK_VIDEO_MEMORY:
-        node = gcmUINT64_TO_PTR(Interface->u.LockVideoMemory.node);
+    gcmkHEADER();
 
-        /* Lock video memory. */
-        gcmkONERROR(
-            gckVIDMEM_Lock(Kernel,
-                           node,
-                           Interface->u.LockVideoMemory.cacheable,
-                           &Interface->u.LockVideoMemory.address));
+    gcmkONERROR(gckHARDWARE_SetPowerManagement(Kernel->hardware, enable));
 
-        locked = gcvTRUE;
+    if (enable == gcvTRUE)
+    {
+        gcmkONERROR(
+            gckHARDWARE_SetPowerManagementState(Kernel->hardware, gcvPOWER_ON));
+    }
 
-        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
-        {
-            /* Map video memory address into user space. */
-#ifdef __QNXNTO__
-        if (node->VidMem.logical == gcvNULL)
-        {
-            gcmkONERROR(
-                gckKERNEL_MapVideoMemory(Kernel,
-                                         FromUser,
-                                         Interface->u.LockVideoMemory.address,
-                                         processID,
-                                         node->VidMem.bytes,
-                                         &node->VidMem.logical));
-        }
-        gcmkASSERT(node->VidMem.logical != gcvNULL);
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
 
-        Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->VidMem.logical);
-#else
-            gcmkONERROR(
-                gckKERNEL_MapVideoMemory(Kernel,
-                                         FromUser,
-                                         Interface->u.LockVideoMemory.address,
-                                         &logical));
+OnError:
+    gcmkFOOTER();
+    return status;
+}
 
-            Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(logical);
+/*******************************************************************************
+**
+**  gckKERNEL_Dispatch
+**
+**  Dispatch a command received from the user HAL layer.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctBOOL FromUser
+**          whether the call is from the user space.
+**
+**      gcsHAL_INTERFACE * Interface
+**          Pointer to a gcsHAL_INTERFACE structure that defines the command to
+**          be dispatched.
+**
+**  OUTPUT:
+**
+**      gcsHAL_INTERFACE * Interface
+**          Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+**          returned.
+*/
+gceSTATUS
+gckKERNEL_Dispatch(
+    IN gckKERNEL Kernel,
+    IN gctBOOL FromUser,
+    IN OUT gcsHAL_INTERFACE * Interface
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+    gctPHYS_ADDR physical = gcvNULL;
+    gctSIZE_T bytes;
+    gctPOINTER logical = gcvNULL;
+    gctPOINTER info = gcvNULL;
+#if (gcdENABLE_3D || gcdENABLE_2D)
+    gckCONTEXT context = gcvNULL;
 #endif
-        }
-        else
-        {
-            Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->Virtual.logical);
-
-            /* Success. */
-            status = gcvSTATUS_OK;
-        }
-
+    gckKERNEL kernel = Kernel;
+    gctUINT32 address;
+    gctUINT32 processID;
 #if gcdSECURE_USER
-        /* Return logical address as physical address. */
-        Interface->u.LockVideoMemory.address =
-            Interface->u.LockVideoMemory.memory;
+    gcskSECURE_CACHE_PTR cache;
+    gctPOINTER logical;
 #endif
-        gcmkONERROR(
-            gckKERNEL_AddProcessDB(Kernel,
-                                   processID, gcvDB_VIDEO_MEMORY_LOCKED,
-                                   node,
-                                   gcvNULL,
-                                   0));
+    gctUINT32 paddr = gcvINVALID_ADDRESS;
+#if !USE_NEW_LINUX_SIGNAL
+    gctSIGNAL   signal;
+#endif
+    gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
 
-        break;
+    gckVIDMEM_NODE nodeObject;
+    gctBOOL powerMutexAcquired = gcvFALSE;
 
-    case gcvHAL_UNLOCK_VIDEO_MEMORY:
-        /* Unlock video memory. */
-        node = gcmUINT64_TO_PTR(Interface->u.UnlockVideoMemory.node);
+    gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
+                   Kernel, FromUser, Interface);
 
-#if gcdSECURE_USER
-        /* Save node information before it disappears. */
-        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
-        {
-            logical = gcvNULL;
-            bytes   = 0;
-        }
-        else
-        {
-            logical = node->Virtual.logical;
-            bytes   = node->Virtual.bytes;
-        }
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+                   "Dispatching command %d (%s)",
+                   Interface->command, _DispatchText[Interface->command]);
+#endif
+#if QNX_SINGLE_THREADED_DEBUGGING
+    gckOS_AcquireMutex(Kernel->os, Kernel->debugMutex, gcvINFINITE);
 #endif
 
-        /* Unlock video memory. */
-        gcmkONERROR(
-            gckVIDMEM_Unlock(Kernel,
-                             node,
-                             Interface->u.UnlockVideoMemory.type,
-                             &Interface->u.UnlockVideoMemory.asynchroneous));
+    /* Get the current process ID. */
+    gcmkONERROR(gckOS_GetProcessID(&processID));
 
 #if gcdSECURE_USER
-        /* Flush the translation cache for virtual surfaces. */
-        if (logical != gcvNULL)
-        {
-            gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
-                                                          cache,
-                                                          logical,
-                                                          bytes));
-        }
+    gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
 #endif
-        if (Interface->u.UnlockVideoMemory.asynchroneous == gcvFALSE)
-        {
-            /* There isn't a event to unlock this node, remove record now */
-            gcmkONERROR(
-                gckKERNEL_RemoveProcessDB(Kernel,
-                                          processID, gcvDB_VIDEO_MEMORY_LOCKED,
-                                          node));
-        }
-        break;
 
-    case gcvHAL_EVENT_COMMIT:
-        /* Commit an event queue. */
-        gcmkONERROR(
-            gckEVENT_Commit(Kernel->eventObj,
-                            gcmUINT64_TO_PTR(Interface->u.Event.queue)));
-        break;
+    /* 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));
+        break;
+
+    case gcvHAL_MAP_MEMORY:
+        physical = gcmINT2PTR(Interface->u.MapMemory.physical);
+
+        /* Map memory. */
+        gcmkONERROR(
+            gckKERNEL_MapMemory(Kernel,
+                                physical,
+                                (gctSIZE_T) Interface->u.MapMemory.bytes,
+                                &logical));
+
+        Interface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
+
+        gcmkVERIFY_OK(
+            gckKERNEL_AddProcessDB(Kernel,
+                                   processID, gcvDB_MAP_MEMORY,
+                                   logical,
+                                   physical,
+                                   (gctSIZE_T) Interface->u.MapMemory.bytes));
+        break;
+
+    case gcvHAL_UNMAP_MEMORY:
+        physical = gcmINT2PTR(Interface->u.UnmapMemory.physical);
+
+        gcmkVERIFY_OK(
+            gckKERNEL_RemoveProcessDB(Kernel,
+                                      processID, gcvDB_MAP_MEMORY,
+                                      gcmUINT64_TO_PTR(Interface->u.UnmapMemory.logical)));
+
+        /* Unmap memory. */
+        gcmkONERROR(
+            gckKERNEL_UnmapMemory(Kernel,
+                                  physical,
+                                  (gctSIZE_T) Interface->u.UnmapMemory.bytes,
+                                  gcmUINT64_TO_PTR(Interface->u.UnmapMemory.logical)));
+        break;
+
+    case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
+        bytes = (gctSIZE_T) Interface->u.AllocateNonPagedMemory.bytes;
+
+        /* Allocate non-paged memory. */
+        gcmkONERROR(
+            gckOS_AllocateNonPagedMemory(
+                Kernel->os,
+                FromUser,
+                &bytes,
+                &physical,
+                &logical));
+
+        Interface->u.AllocateNonPagedMemory.bytes    = bytes;
+        Interface->u.AllocateNonPagedMemory.logical  = gcmPTR_TO_UINT64(logical);
+        Interface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
+
+        gcmkVERIFY_OK(
+            gckKERNEL_AddProcessDB(Kernel,
+                                   processID, gcvDB_NON_PAGED,
+                                   logical,
+                                   gcmINT2PTR(Interface->u.AllocateNonPagedMemory.physical),
+                                   bytes));
+        break;
+
+    case gcvHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER:
+        bytes = (gctSIZE_T) Interface->u.AllocateVirtualCommandBuffer.bytes;
+
+        gcmkONERROR(
+            gckKERNEL_AllocateVirtualCommandBuffer(
+                Kernel,
+                FromUser,
+                &bytes,
+                &physical,
+                &logical));
+
+        Interface->u.AllocateVirtualCommandBuffer.bytes    = bytes;
+        Interface->u.AllocateVirtualCommandBuffer.logical  = gcmPTR_TO_UINT64(logical);
+        Interface->u.AllocateVirtualCommandBuffer.physical = gcmPTR_TO_NAME(physical);
+
+        gcmkVERIFY_OK(
+            gckKERNEL_AddProcessDB(Kernel,
+                                   processID, gcvDB_COMMAND_BUFFER,
+                                   logical,
+                                   gcmINT2PTR(Interface->u.AllocateVirtualCommandBuffer.physical),
+                                   bytes));
+        break;
+
+    case gcvHAL_FREE_NON_PAGED_MEMORY:
+        physical = gcmNAME_TO_PTR(Interface->u.FreeNonPagedMemory.physical);
+
+        gcmkVERIFY_OK(
+            gckKERNEL_RemoveProcessDB(Kernel,
+                                      processID, gcvDB_NON_PAGED,
+                                      gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+
+        /* Unmap user logical out of physical memory first. */
+        gcmkONERROR(gckOS_UnmapUserLogical(Kernel->os,
+                                           physical,
+                                           (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
+                                           gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+
+        /* Free non-paged memory. */
+        gcmkONERROR(
+            gckOS_FreeNonPagedMemory(Kernel->os,
+                                     (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
+                                     physical,
+                                     gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+
+#if gcdSECURE_USER
+        gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+            Kernel,
+            cache,
+            gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical),
+            (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes));
+#endif
+
+        gcmRELEASE_NAME(Interface->u.FreeNonPagedMemory.physical);
+        break;
+
+    case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
+        bytes = (gctSIZE_T) Interface->u.AllocateContiguousMemory.bytes;
+
+        /* Allocate contiguous memory. */
+        gcmkONERROR(gckOS_AllocateContiguous(
+            Kernel->os,
+            FromUser,
+            &bytes,
+            &physical,
+            &logical));
+
+        Interface->u.AllocateContiguousMemory.bytes    = bytes;
+        Interface->u.AllocateContiguousMemory.logical  = gcmPTR_TO_UINT64(logical);
+        Interface->u.AllocateContiguousMemory.physical = gcmPTR_TO_NAME(physical);
+
+        gcmkONERROR(gckHARDWARE_ConvertLogical(
+            Kernel->hardware,
+            logical,
+            gcvTRUE,
+            &Interface->u.AllocateContiguousMemory.address));
+
+        gcmkVERIFY_OK(gckKERNEL_AddProcessDB(
+            Kernel,
+            processID, gcvDB_CONTIGUOUS,
+            logical,
+            gcmINT2PTR(Interface->u.AllocateContiguousMemory.physical),
+            bytes));
+        break;
+
+    case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+        physical = gcmNAME_TO_PTR(Interface->u.FreeContiguousMemory.physical);
+
+        gcmkVERIFY_OK(
+            gckKERNEL_RemoveProcessDB(Kernel,
+                                      processID, gcvDB_CONTIGUOUS,
+                                      gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+
+        /* Unmap user logical out of physical memory first. */
+        gcmkONERROR(gckOS_UnmapUserLogical(Kernel->os,
+                                           physical,
+                                           (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes,
+                                           gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical)));
+
+        /* Free contiguous memory. */
+        gcmkONERROR(
+            gckOS_FreeContiguous(Kernel->os,
+                                 physical,
+                                 gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical),
+                                 (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes));
+
+#if gcdSECURE_USER
+        gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+            Kernel,
+            cache,
+            gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical),
+            (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes));
+#endif
+
+        gcmRELEASE_NAME(Interface->u.FreeContiguousMemory.physical);
+        break;
+
+    case gcvHAL_ALLOCATE_VIDEO_MEMORY:
+
+        gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+
+        break;
+
+    case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
+        /* Allocate memory. */
+        gcmkONERROR(
+            gckKERNEL_AllocateLinearMemory(Kernel, processID,
+                            &Interface->u.AllocateLinearVideoMemory.pool,
+                            Interface->u.AllocateLinearVideoMemory.bytes,
+                            Interface->u.AllocateLinearVideoMemory.alignment,
+                            Interface->u.AllocateLinearVideoMemory.type,
+                            Interface->u.AllocateLinearVideoMemory.flag,
+                            &Interface->u.AllocateLinearVideoMemory.node));
+        break;
+
+    case gcvHAL_RELEASE_VIDEO_MEMORY:
+        /* Release video memory. */
+        gcmkONERROR(gckKERNEL_ReleaseVideoMemory(
+            Kernel, processID,
+            (gctUINT32)Interface->u.ReleaseVideoMemory.node
+            ));
+        break;
+
+    case gcvHAL_LOCK_VIDEO_MEMORY:
+        /* Lock video memory. */
+        gcmkONERROR(gckKERNEL_LockVideoMemory(Kernel, Kernel->core, processID, FromUser, Interface));
+        break;
+
+    case gcvHAL_UNLOCK_VIDEO_MEMORY:
+        /* Unlock video memory. */
+        gcmkONERROR(gckKERNEL_UnlockVideoMemory(Kernel, processID, Interface));
+        break;
+
+    case gcvHAL_EVENT_COMMIT:
+        /* Commit an event queue. */
+#if gcdMULTI_GPU
+        if (Interface->u.Event.gpuMode == gcvMULTI_GPU_MODE_INDEPENDENT)
+        {
+            gcmkONERROR(
+                gckEVENT_Commit(Kernel->eventObj,
+                                gcmUINT64_TO_PTR(Interface->u.Event.queue),
+                                Interface->u.Event.chipEnable));
+        }
+        else
+        {
+            gcmkONERROR(
+                gckEVENT_Commit(Kernel->eventObj,
+                                gcmUINT64_TO_PTR(Interface->u.Event.queue),
+                                gcvCORE_3D_ALL_MASK));
+        }
+#else
+        gcmkONERROR(
+            gckEVENT_Commit(Kernel->eventObj,
+                            gcmUINT64_TO_PTR(Interface->u.Event.queue)));
+#endif
+        break;
 
     case gcvHAL_COMMIT:
         /* Commit a command and context buffer. */
+#if gcdMULTI_GPU
+        if (Interface->u.Commit.gpuMode == gcvMULTI_GPU_MODE_INDEPENDENT)
+        {
+            gcmkONERROR(
+                gckCOMMAND_Commit(Kernel->command,
+                                  Interface->u.Commit.context ?
+                                      gcmNAME_TO_PTR(Interface->u.Commit.context) : gcvNULL,
+                                  gcmUINT64_TO_PTR(Interface->u.Commit.commandBuffer),
+                                  gcmUINT64_TO_PTR(Interface->u.Commit.delta),
+                                  gcmUINT64_TO_PTR(Interface->u.Commit.queue),
+                                  processID,
+                                  Interface->u.Commit.chipEnable));
+        }
+        else
+        {
+            gcmkONERROR(
+                gckCOMMAND_Commit(Kernel->command,
+                                  Interface->u.Commit.context ?
+                                      gcmNAME_TO_PTR(Interface->u.Commit.context) : gcvNULL,
+                                  gcmUINT64_TO_PTR(Interface->u.Commit.commandBuffer),
+                                  gcmUINT64_TO_PTR(Interface->u.Commit.delta),
+                                  gcmUINT64_TO_PTR(Interface->u.Commit.queue),
+                                  processID,
+                                  gcvCORE_3D_ALL_MASK));
+        }
+#else
         gcmkONERROR(
             gckCOMMAND_Commit(Kernel->command,
                               Interface->u.Commit.context ?
@@ -1405,11 +1836,17 @@ gckKERNEL_Dispatch(
                               gcmUINT64_TO_PTR(Interface->u.Commit.delta),
                               gcmUINT64_TO_PTR(Interface->u.Commit.queue),
                               processID));
+#endif
+
         break;
 
     case gcvHAL_STALL:
         /* Stall the command queue. */
+#if gcdMULTI_GPU
+        gcmkONERROR(gckCOMMAND_Stall(Kernel->command, gcvFALSE, gcvCORE_3D_ALL_MASK));
+#else
         gcmkONERROR(gckCOMMAND_Stall(Kernel->command, gcvFALSE));
+#endif
         break;
 
     case gcvHAL_MAP_USER_MEMORY:
@@ -1437,6 +1874,10 @@ gckKERNEL_Dispatch(
         address = Interface->u.UnmapUserMemory.address;
         info = gcmNAME_TO_PTR(Interface->u.UnmapUserMemory.info);
 
+        gcmkVERIFY_OK(
+            gckKERNEL_RemoveProcessDB(Kernel,
+                                      processID, gcvDB_MAP_USER_MEMORY,
+                                      gcmINT2PTR(Interface->u.UnmapUserMemory.info)));
         /* Unmap user memory. */
         gcmkONERROR(
             gckOS_UnmapUserMemory(Kernel->os,
@@ -1451,15 +1892,10 @@ gckKERNEL_Dispatch(
             Kernel,
             cache,
             gcmUINT64_TO_PTR(Interface->u.UnmapUserMemory.memory),
-            Interface->u.UnmapUserMemory.size));
+            (gctSIZE_T) Interface->u.UnmapUserMemory.size));
 #endif
-        gcmkVERIFY_OK(
-            gckKERNEL_RemoveProcessDB(Kernel,
-                                      processID, gcvDB_MAP_USER_MEMORY,
-                                      gcmINT2PTR(Interface->u.UnmapUserMemory.info)));
 
         gcmRELEASE_NAME(Interface->u.UnmapUserMemory.info);
-
         break;
 
 #if !USE_NEW_LINUX_SIGNAL
@@ -1483,15 +1919,15 @@ gckKERNEL_Dispatch(
             break;
 
         case gcvUSER_SIGNAL_DESTROY:
-            /* Destroy the signal. */
-            gcmkONERROR(
-                gckOS_DestroyUserSignal(Kernel->os,
-                                        Interface->u.UserSignal.id));
-
             gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
                 Kernel,
                 processID, gcvDB_SIGNAL,
                 gcmINT2PTR(Interface->u.UserSignal.id)));
+
+            /* Destroy the signal. */
+            gcmkONERROR(
+                gckOS_DestroyUserSignal(Kernel->os,
+                                        Interface->u.UserSignal.id));
             break;
 
         case gcvUSER_SIGNAL_SIGNAL:
@@ -1503,69 +1939,10 @@ gckKERNEL_Dispatch(
             break;
 
         case gcvUSER_SIGNAL_WAIT:
-#if gcdGPU_TIMEOUT
-            if (Interface->u.UserSignal.wait == gcvINFINITE)
-            {
-                gckHARDWARE hardware;
-                gctUINT32 timer = 0;
-
-                for(;;)
-                {
-                    /* Wait on the signal. */
-                    status = gckOS_WaitUserSignal(Kernel->os,
-                                                  Interface->u.UserSignal.id,
-                                                  gcdGPU_ADVANCETIMER);
-
-                    if (status == gcvSTATUS_TIMEOUT)
-                    {
-                        gcmkONERROR(
-                            gckOS_SignalQueryHardware(Kernel->os,
-                                                      (gctSIGNAL)(gctUINTPTR_T)Interface->u.UserSignal.id,
-                                                      &hardware));
-
-                        if (hardware)
-                        {
-                            /* This signal is bound to a hardware,
-                            ** so the timeout is limited by Kernel->timeOut.
-                            */
-                            timer += gcdGPU_ADVANCETIMER;
-                        }
-
-                        if (timer >= Kernel->timeOut)
-                        {
-                            gcmkONERROR(
-                                gckOS_Broadcast(Kernel->os,
-                                                hardware,
-                                                gcvBROADCAST_GPU_STUCK));
-
-                            timer = 0;
-
-                            /* If a few process try to reset GPU, only one
-                            ** of them can do the real reset, other processes
-                            ** still need to wait for this signal is triggered,
-                            ** which menas reset is finished.
-                            */
-                            continue;
-                        }
-                    }
-                    else
-                    {
-                        /* Bail out on other error. */
-                        gcmkONERROR(status);
-
-                        /* Wait for signal successfully. */
-                        break;
-                    }
-                }
-            }
-            else
-#endif
-            {
-                /* Wait on the signal. */
-                status = gckOS_WaitUserSignal(Kernel->os,
-                                              Interface->u.UserSignal.id,
-                                              Interface->u.UserSignal.wait);
-            }
+            /* Wait on the signal. */
+            status = gckOS_WaitUserSignal(Kernel->os,
+                                          Interface->u.UserSignal.id,
+                                          Interface->u.UserSignal.wait);
 
             break;
 
@@ -1585,15 +1962,15 @@ gckKERNEL_Dispatch(
             break;
 
         case gcvUSER_SIGNAL_UNMAP:
-            /* Destroy the signal. */
-            gcmkONERROR(
-                gckOS_DestroyUserSignal(Kernel->os,
-                                        Interface->u.UserSignal.id));
-
             gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
                 Kernel,
                 processID, gcvDB_SIGNAL,
                 gcmINT2PTR(Interface->u.UserSignal.id)));
+
+            /* Destroy the signal. */
+            gcmkONERROR(
+                gckOS_DestroyUserSignal(Kernel->os,
+                                        Interface->u.UserSignal.id));
             break;
 
         default:
@@ -1631,7 +2008,8 @@ gckKERNEL_Dispatch(
         {
             gceCHIPPOWERSTATE power;
 
-            gckOS_AcquireMutex(Kernel->os, Kernel->hardware->powerMutex, gcvINFINITE);
+            gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->hardware->powerMutex, gcvINFINITE));
+            powerMutexAcquired = gcvTRUE;
             gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
                                                               &power));
             if (power == gcvPOWER_ON)
@@ -1650,6 +2028,7 @@ gckKERNEL_Dispatch(
                 status = gcvSTATUS_CHIP_NOT_READY;
             }
             gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
+            powerMutexAcquired = gcvFALSE;
         }
 #else
         /* No access from user land to read registers. */
@@ -1658,6 +2037,106 @@ gckKERNEL_Dispatch(
 #endif
         break;
 
+#if gcdMULTI_GPU
+    case gcvHAL_READ_REGISTER_EX:
+#if gcdREGISTER_ACCESS_FROM_USER
+        {
+            gceCHIPPOWERSTATE power;
+            gctUINT32 coreId = 0;
+            gctUINT32 coreSelect = Interface->u.ReadRegisterDataEx.coreSelect;
+
+            gckOS_AcquireMutex(Kernel->os, Kernel->hardware->powerMutex, gcvINFINITE);
+            powerMutexAcquired = gcvTRUE;
+            gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
+                    &power));
+            if (power == gcvPOWER_ON)
+            {
+                for (; coreSelect != 0; coreSelect >>= 1, coreId++)
+                {
+                    if (coreSelect & 1UL)
+                    {
+                        /* Read a register. */
+                        gcmkONERROR(
+                            gckOS_ReadRegisterByCoreId(
+                                Kernel->os,
+                                Kernel->core,
+                                coreId,
+                                Interface->u.ReadRegisterDataEx.address,
+                                &Interface->u.ReadRegisterDataEx.data[coreId]));
+                    }
+                }
+            }
+            else
+            {
+                for (coreId = 0; coreId < gcdMULTI_GPU; coreId++)
+                {
+                    /* Chip is in power-state. */
+                    Interface->u.ReadRegisterDataEx.data[coreId] = 0;
+                }
+                status = gcvSTATUS_CHIP_NOT_READY;
+            }
+            gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
+            powerMutexAcquired = gcvFALSE;
+        }
+#else
+        gctUINT32 coreId;
+
+        /* No access from user land to read registers. */
+        for (coreId = 0; coreId < gcdMULTI_GPU; coreId++)
+        {
+            Interface->u.ReadRegisterDataEx.data[coreId] = 0;
+        }
+
+        status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+        break;
+
+    case gcvHAL_WRITE_REGISTER_EX:
+#if gcdREGISTER_ACCESS_FROM_USER
+        {
+            gceCHIPPOWERSTATE power;
+            gctUINT32 coreId = 0;
+            gctUINT32 coreSelect = Interface->u.WriteRegisterDataEx.coreSelect;
+
+            gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->hardware->powerMutex, gcvINFINITE));
+            powerMutexAcquired = gcvTRUE;
+            gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
+                    &power));
+            if (power == gcvPOWER_ON)
+            {
+                for (; coreSelect != 0; coreSelect >>= 1, coreId++)
+                {
+                    if (coreSelect & 1UL)
+                    {
+                        /* Write a register. */
+                        gcmkONERROR(
+                            gckOS_WriteRegisterByCoreId(
+                                Kernel->os,
+                                Kernel->core,
+                                coreId,
+                                Interface->u.WriteRegisterDataEx.address,
+                                Interface->u.WriteRegisterDataEx.data[coreId]));
+                    }
+                }
+            }
+            else
+            {
+                /* Chip is in power-state. */
+                for (coreId = 0; coreId < gcdMULTI_GPU; coreId++)
+                {
+                    Interface->u.WriteRegisterDataEx.data[coreId] = 0;
+                }
+                status = gcvSTATUS_CHIP_NOT_READY;
+            }
+            gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
+            powerMutexAcquired = gcvFALSE;
+        }
+#else
+        status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+        break;
+#endif
+
     case gcvHAL_WRITE_REGISTER:
 #if gcdREGISTER_ACCESS_FROM_USER
         {
@@ -1730,11 +2209,18 @@ gckKERNEL_Dispatch(
 
         status = gcvSTATUS_OK;
         break;
+
     case gcvHAL_SET_PROFILE_SETTING:
 #if VIVANTE_PROFILER
         /* Set profile setting */
         if(Kernel->hardware->gpuProfiler)
+        {
             Kernel->profileEnable = Interface->u.SetProfileSetting.enable;
+#if VIVANTE_PROFILER_NEW
+            if (Kernel->profileEnable)
+                gckHARDWARE_InitProfiler(Kernel->hardware);
+#endif
+        }
         else
         {
             status = gcvSTATUS_NOT_SUPPORTED;
@@ -1763,7 +2249,8 @@ gckKERNEL_Dispatch(
 
     case gcvHAL_RESET:
         /* Reset the hardware. */
-        gckKERNEL_Recovery(Kernel);
+        gcmkONERROR(
+            gckHARDWARE_Reset(Kernel->hardware));
         break;
 
     case gcvHAL_DEBUG:
@@ -1795,58 +2282,57 @@ gckKERNEL_Dispatch(
         break;
 
     case gcvHAL_DUMP_GPU_STATE:
-        /* Dump GPU state */
         {
             gceCHIPPOWERSTATE power;
-            gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
-                                                              &power));
+
+            _DumpDriverConfigure(Kernel);
+
+            gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
+                Kernel->hardware,
+                &power
+                ));
+
             if (power == gcvPOWER_ON)
             {
                 Interface->u.ReadRegisterData.data = 1;
-                gcmkVERIFY_OK(
-                    gckHARDWARE_DumpGPUState(Kernel->hardware));
-#if gcdVIRTUAL_COMMAND_BUFFER
-                gcmkVERIFY_OK(
-                    gckCOMMAND_DumpExecutingBuffer(Kernel->command));
-#endif
+
+                _DumpState(Kernel);
             }
             else
             {
                 Interface->u.ReadRegisterData.data = 0;
                 status = gcvSTATUS_CHIP_NOT_READY;
+
+                gcmkPRINT("[galcore]: Can't dump state if GPU isn't POWER ON.");
             }
         }
         break;
 
     case gcvHAL_DUMP_EVENT:
-        /* Dump GPU event */
-        gcmkVERIFY_OK(gckEVENT_Dump(Kernel->eventObj));
-
-        /* Dump Process DB. */
-        gcmkVERIFY_OK(gckKERNEL_DumpProcessDB(Kernel));
         break;
 
     case gcvHAL_CACHE:
-        node = gcmUINT64_TO_PTR(Interface->u.Cache.node);
-        if (node == gcvNULL)
-        {
-            /* FIXME Surface wrap some memory which is not allocated by us,
-            ** So we don't have physical address to handle outer cache, ignore it*/
-            status = gcvSTATUS_OK;
-            break;
-        }
-        else if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
-        {
-            /* Video memory has no physical handles. */
-            physical = gcvNULL;
-        }
-        else
+
+        logical = gcmUINT64_TO_PTR(Interface->u.Cache.logical);
+
+        if (Interface->u.Cache.node)
         {
-            /* Grab physical handle. */
-            physical = node->Virtual.physical;
+            gcmkONERROR(gckVIDMEM_HANDLE_Lookup(
+                Kernel,
+                processID,
+                Interface->u.Cache.node,
+                &nodeObject));
+
+            if (nodeObject->node->VidMem.memory->object.type == gcvOBJ_VIDMEM
+             || nodeObject->node->Virtual.contiguous
+            )
+            {
+                /* If memory is contiguous, get physical address. */
+                gcmkONERROR(gckOS_GetPhysicalAddress(
+                    Kernel->os, logical, (gctUINT32*)&paddr));
+            }
         }
 
-        logical = gcmUINT64_TO_PTR(Interface->u.Cache.logical);
         bytes = (gctSIZE_T) Interface->u.Cache.bytes;
         switch(Interface->u.Cache.operation)
         {
@@ -1878,10 +2364,10 @@ gckKERNEL_Dispatch(
                                            bytes);
             break;
 
-       case gcvCACHE_MEMORY_BARRIER:
-          status = gckOS_MemoryBarrier(Kernel->os,
-                                        logical);
-          break;
+        case gcvCACHE_MEMORY_BARRIER:
+            status = gckOS_MemoryBarrier(Kernel->os,
+                                         logical);
+            break;
         default:
             status = gcvSTATUS_INVALID_ARGUMENT;
             break;
@@ -1912,7 +2398,7 @@ gckKERNEL_Dispatch(
 
             /* Check truncation overflow. */
             Interface->u.TimeStamp.timeDelta = (gctINT32) timeDelta;
-                       /*bit0~bit30 is available*/
+            /*bit0~bit30 is available*/
             if (timeDelta>>31)
             {
                 Interface->u.TimeStamp.timeDelta = 0;
@@ -1924,64 +2410,7 @@ gckKERNEL_Dispatch(
         break;
 
     case gcvHAL_DATABASE:
-        /* Query video memory. */
-        gcmkONERROR(
-            gckKERNEL_QueryProcessDB(Kernel,
-                                     Interface->u.Database.processID,
-                                     !Interface->u.Database.validProcessID,
-                                     gcvDB_VIDEO_MEMORY,
-                                     &Interface->u.Database.vidMem));
-
-        /* Query non-paged memory. */
-        gcmkONERROR(
-            gckKERNEL_QueryProcessDB(Kernel,
-                                     Interface->u.Database.processID,
-                                     !Interface->u.Database.validProcessID,
-                                     gcvDB_NON_PAGED,
-                                     &Interface->u.Database.nonPaged));
-
-        /* Query contiguous memory. */
-        gcmkONERROR(
-            gckKERNEL_QueryProcessDB(Kernel,
-                                     Interface->u.Database.processID,
-                                     !Interface->u.Database.validProcessID,
-                                     gcvDB_CONTIGUOUS,
-                                     &Interface->u.Database.contiguous));
-
-        /* Query GPU idle time. */
-        gcmkONERROR(
-            gckKERNEL_QueryProcessDB(Kernel,
-                                     Interface->u.Database.processID,
-                                     !Interface->u.Database.validProcessID,
-                                     gcvDB_IDLE,
-                                     &Interface->u.Database.gpuIdle));
-        break;
-
-    case gcvHAL_VIDMEM_DATABASE:
-        /* Query reserved video memory. */
-        gcmkONERROR(
-            gckKERNEL_QueryProcessDB(Kernel,
-                                     Interface->u.VidMemDatabase.processID,
-                                     !Interface->u.VidMemDatabase.validProcessID,
-                                     gcvDB_VIDEO_MEMORY_RESERVED,
-                                     &Interface->u.VidMemDatabase.vidMemResv));
-
-        /* Query contiguous video memory. */
-        gcmkONERROR(
-            gckKERNEL_QueryProcessDB(Kernel,
-                                     Interface->u.VidMemDatabase.processID,
-                                     !Interface->u.VidMemDatabase.validProcessID,
-                                     gcvDB_VIDEO_MEMORY_CONTIGUOUS,
-                                     &Interface->u.VidMemDatabase.vidMemCont));
-
-        /* Query virtual video memory. */
-        gcmkONERROR(
-            gckKERNEL_QueryProcessDB(Kernel,
-                                     Interface->u.VidMemDatabase.processID,
-                                     !Interface->u.VidMemDatabase.validProcessID,
-                                     gcvDB_VIDEO_MEMORY_VIRTUAL,
-                                     &Interface->u.VidMemDatabase.vidMemVirt));
-
+        gcmkONERROR(gckKERNEL_QueryDatabase(Kernel, processID, Interface));
         break;
 
     case gcvHAL_VERSION:
@@ -2003,6 +2432,7 @@ gckKERNEL_Dispatch(
         Interface->u.ChipInfo.types[0] = Kernel->hardware->type;
         break;
 
+#if (gcdENABLE_3D || gcdENABLE_2D)
     case gcvHAL_ATTACH:
         /* Attach user process. */
         gcmkONERROR(
@@ -2014,6 +2444,15 @@ gckKERNEL_Dispatch(
         Interface->u.Attach.stateCount = bytes;
         Interface->u.Attach.context = gcmPTR_TO_NAME(context);
 
+        if (Interface->u.Attach.map == gcvTRUE)
+        {
+            gcmkVERIFY_OK(
+                gckCONTEXT_MapBuffer(context,
+                                     Interface->u.Attach.physicals,
+                                     Interface->u.Attach.logicals,
+                                     &Interface->u.Attach.bytes));
+        }
+
         gcmkVERIFY_OK(
             gckKERNEL_AddProcessDB(Kernel,
                                    processID, gcvDB_CONTEXT,
@@ -2021,18 +2460,19 @@ gckKERNEL_Dispatch(
                                    gcvNULL,
                                    0));
         break;
+#endif
 
     case gcvHAL_DETACH:
-        /* Detach user process. */
-        gcmkONERROR(
-            gckCOMMAND_Detach(Kernel->command,
-                              gcmNAME_TO_PTR(Interface->u.Detach.context)));
-
         gcmkVERIFY_OK(
             gckKERNEL_RemoveProcessDB(Kernel,
                               processID, gcvDB_CONTEXT,
                               gcmINT2PTR(Interface->u.Detach.context)));
 
+        /* Detach user process. */
+        gcmkONERROR(
+            gckCOMMAND_Detach(Kernel->command,
+                              gcmNAME_TO_PTR(Interface->u.Detach.context)));
+
         gcmRELEASE_NAME(Interface->u.Detach.context);
         break;
 
@@ -2049,142 +2489,10 @@ gckKERNEL_Dispatch(
          gckKERNEL_SetTimeOut(Kernel, Interface->u.SetTimeOut.timeOut);
         break;
 
-#if gcdFRAME_DB
     case gcvHAL_GET_FRAME_INFO:
         gcmkONERROR(gckHARDWARE_GetFrameInfo(
-            Kernel->hardware,
-            gcmUINT64_TO_PTR(Interface->u.GetFrameInfo.frameInfo)));
-        break;
-#endif
-
-    case gcvHAL_GET_SHARED_INFO:
-        if (Interface->u.GetSharedInfo.data == gcvNULL)
-        {
-            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
-        }
-        else
-        {
-            gctUINT32 pid    = Interface->u.GetSharedInfo.pid;
-            gctUINT32 dataId = Interface->u.GetSharedInfo.dataId;
-            gctSIZE_T bytes  = Interface->u.GetSharedInfo.bytes;
-            gctPOINTER data  = Interface->u.GetSharedInfo.data;
-            gcsDATABASE_RECORD record;
-
-            /* Find record. */
-            gcmkONERROR(
-                gckKERNEL_FindProcessDB(Kernel,
-                                        pid,
-                                        0,
-                                        gcvDB_SHARED_INFO,
-                                        gcmINT2PTR(dataId),
-                                        &record));
-
-            /* Check memory size. */
-            if (bytes < record.bytes)
-            {
-                /* Insufficient memory to hold shared data. */
-                gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
-            }
-
-            /* Copy to user. */
-            status = gckOS_CopyToUserData(Kernel->os,
-                                          record.physical,
-                                          data,
-                                          record.bytes);
-
-            /*
-             * Remove from process db.
-             * Every time when shared info is taken, the record is erased in
-             * kernel side.
-             */
-            gcmkVERIFY_OK(
-                gckKERNEL_RemoveProcessDB(Kernel,
-                                          pid,
-                                          gcvDB_SHARED_INFO,
-                                          gcmINT2PTR(dataId)));
-            /* Free existed data. */
-            gcmkVERIFY_OK(
-                gckOS_FreeMemory(Kernel->os, record.physical));
-        }
-        break;
-
-    case gcvHAL_SET_SHARED_INFO:
-        {
-            gctUINT32 dataId = Interface->u.SetSharedInfo.dataId;
-            gctPOINTER data  = Interface->u.SetSharedInfo.data;
-            gctUINT32 bytes  = Interface->u.SetSharedInfo.bytes;
-            gctPOINTER memory = gcvNULL;
-            gcsDATABASE_RECORD record;
-
-            if (gcmIS_SUCCESS(gckKERNEL_FindProcessDB(Kernel,
-                                                     processID,
-                                                     0,
-                                                     gcvDB_SHARED_INFO,
-                                                     gcmINT2PTR(dataId),
-                                                     &record)))
-            {
-                /* Find a record with the same id. */
-                if (bytes != record.bytes)
-                {
-                    /* Remove from process db. */
-                    gcmkVERIFY_OK(
-                        gckKERNEL_RemoveProcessDB(Kernel,
-                                                  processID,
-                                                  gcvDB_SHARED_INFO,
-                                                  gcmINT2PTR(dataId)));
-
-                    /* Free existed data. */
-                    gcmkVERIFY_OK(
-                        gckOS_FreeMemory(Kernel->os, record.physical));
-                }
-                else
-                {
-                    /* Re-use allocated memory. */
-                    memory = record.physical;
-                }
-            }
-
-            if ((data == gcvNULL) || (bytes == 0))
-            {
-                /* Nothing to record. */
-                break;
-            }
-
-            if (bytes > 1024)
-            {
-                /* Limite data size. */
-                gcmkONERROR(gcvSTATUS_TOO_COMPLEX);
-            }
-
-            if (memory == gcvNULL)
-            {
-                /* Allocate memory for holding shared data. */
-                gcmkONERROR(
-                    gckOS_AllocateMemory(Kernel->os, bytes, &memory));
-
-                /* Add to process db. */
-                status = gckKERNEL_AddProcessDB(Kernel,
-                                                processID,
-                                                gcvDB_SHARED_INFO,
-                                                gcmINT2PTR(dataId),
-                                                memory,
-                                                bytes);
-
-                if (gcmIS_ERROR(status))
-                {
-                    /* Failed to add process db. Free allocated memory. */
-                    gcmkVERIFY_OK(gckOS_FreeMemory(Kernel->os, memory));
-                    break;
-                }
-            }
-
-            /* Copy shared data to kernel memory. */
-            gcmkONERROR(
-                gckOS_CopyFromUserData(Kernel->os,
-                                       memory,
-                                       data,
-                                       bytes));
-        }
+                    Kernel->hardware,
+                    gcmUINT64_TO_PTR(Interface->u.GetFrameInfo.frameInfo)));
         break;
 
     case gcvHAL_SET_FSCALE_VALUE:
@@ -2206,30 +2514,81 @@ gckKERNEL_Dispatch(
 #endif
         break;
 
-    case gcvHAL_QUERY_RESET_TIME_STAMP:
-#if gcdENABLE_RECOVERY
-        Interface->u.QueryResetTimeStamp.timeStamp = Kernel->resetTimeStamp;
-#else
-        Interface->u.QueryResetTimeStamp.timeStamp = 0;
-#endif
+    case gcvHAL_NAME_VIDEO_MEMORY:
+        gcmkONERROR(gckVIDMEM_NODE_Name(Kernel,
+                                        Interface->u.NameVideoMemory.handle,
+                                        &Interface->u.NameVideoMemory.name));
         break;
 
-#if gcdANDROID_NATIVE_FENCE_SYNC
-    case gcvHAL_SYNC_POINT:
-        {
-            gctSYNC_POINT syncPoint;
+    case gcvHAL_IMPORT_VIDEO_MEMORY:
+        gcmkONERROR(gckVIDMEM_NODE_Import(Kernel,
+                                          Interface->u.ImportVideoMemory.name,
+                                          &Interface->u.ImportVideoMemory.handle));
 
-            switch (Interface->u.SyncPoint.command)
-            {
-            case gcvSYNC_POINT_CREATE:
-                gcmkONERROR(gckOS_CreateSyncPoint(Kernel->os, &syncPoint));
+        gcmkONERROR(
+            gckKERNEL_AddProcessDB(Kernel,
+                                   processID, gcvDB_VIDEO_MEMORY,
+                                   gcmINT2PTR(Interface->u.ImportVideoMemory.handle),
+                                   gcvNULL,
+                                   0));
+        break;
 
-                Interface->u.SyncPoint.syncPoint = gcmPTR_TO_UINT64(syncPoint);
+    case gcvHAL_GET_VIDEO_MEMORY_FD:
+        gcmkONERROR(gckVIDMEM_NODE_GetFd(
+            Kernel,
+            Interface->u.GetVideoMemoryFd.handle,
+            &Interface->u.GetVideoMemoryFd.fd
+            ));
 
-                gcmkVERIFY_OK(
-                    gckKERNEL_AddProcessDB(Kernel,
-                                           processID, gcvDB_SYNC_POINT,
-                                           syncPoint,
+        /* No need to add it to processDB because OS will release all fds when
+        ** process quits.
+        */
+        break;
+
+    case gcvHAL_QUERY_RESET_TIME_STAMP:
+        Interface->u.QueryResetTimeStamp.timeStamp = Kernel->resetTimeStamp;
+        break;
+
+    case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
+        buffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)gcmNAME_TO_PTR(Interface->u.FreeVirtualCommandBuffer.physical);
+
+        gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+            Kernel,
+            processID,
+            gcvDB_COMMAND_BUFFER,
+            gcmUINT64_TO_PTR(Interface->u.FreeVirtualCommandBuffer.logical)));
+
+        gcmkONERROR(gckOS_DestroyUserVirtualMapping(
+            Kernel->os,
+            buffer->physical,
+            (gctSIZE_T)Interface->u.FreeVirtualCommandBuffer.bytes,
+            gcmUINT64_TO_PTR(Interface->u.FreeVirtualCommandBuffer.logical)));
+
+        gcmkONERROR(gckKERNEL_DestroyVirtualCommandBuffer(
+            Kernel,
+            (gctSIZE_T)Interface->u.FreeVirtualCommandBuffer.bytes,
+            (gctPHYS_ADDR)buffer,
+            gcmUINT64_TO_PTR(Interface->u.FreeVirtualCommandBuffer.logical)));
+
+        gcmRELEASE_NAME(Interface->u.FreeVirtualCommandBuffer.physical);
+        break;
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+    case gcvHAL_SYNC_POINT:
+        {
+            gctSYNC_POINT syncPoint;
+
+            switch (Interface->u.SyncPoint.command)
+            {
+            case gcvSYNC_POINT_CREATE:
+                gcmkONERROR(gckOS_CreateSyncPoint(Kernel->os, &syncPoint));
+
+                Interface->u.SyncPoint.syncPoint = gcmPTR_TO_UINT64(syncPoint);
+
+                gcmkVERIFY_OK(
+                    gckKERNEL_AddProcessDB(Kernel,
+                                           processID, gcvDB_SYNC_POINT,
+                                           syncPoint,
                                            gcvNULL,
                                            0));
                 break;
@@ -2269,6 +2628,97 @@ gckKERNEL_Dispatch(
         break;
 #endif
 
+    case gcvHAL_SHBUF:
+        {
+            gctSHBUF shBuf;
+            gctPOINTER uData;
+            gctUINT32 bytes;
+
+            switch (Interface->u.ShBuf.command)
+            {
+            case gcvSHBUF_CREATE:
+                bytes = Interface->u.ShBuf.bytes;
+
+                /* Create. */
+                gcmkONERROR(gckKERNEL_CreateShBuffer(Kernel, bytes, &shBuf));
+
+                Interface->u.ShBuf.id = gcmPTR_TO_UINT64(shBuf);
+
+                gcmkVERIFY_OK(
+                    gckKERNEL_AddProcessDB(Kernel,
+                                           processID,
+                                           gcvDB_SHBUF,
+                                           shBuf,
+                                           gcvNULL,
+                                           0));
+                break;
+
+            case gcvSHBUF_DESTROY:
+                shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+
+                /* Check db first to avoid illegal destroy in the process. */
+                gcmkONERROR(
+                    gckKERNEL_RemoveProcessDB(Kernel,
+                                              processID,
+                                              gcvDB_SHBUF,
+                                              shBuf));
+
+                gcmkONERROR(gckKERNEL_DestroyShBuffer(Kernel, shBuf));
+                break;
+
+            case gcvSHBUF_MAP:
+                shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+
+                /* Map for current process access. */
+                gcmkONERROR(gckKERNEL_MapShBuffer(Kernel, shBuf));
+
+                gcmkVERIFY_OK(
+                    gckKERNEL_AddProcessDB(Kernel,
+                                           processID,
+                                           gcvDB_SHBUF,
+                                           shBuf,
+                                           gcvNULL,
+                                           0));
+                break;
+
+            case gcvSHBUF_WRITE:
+                shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+                uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
+                bytes = Interface->u.ShBuf.bytes;
+
+                /* Write. */
+                gcmkONERROR(
+                    gckKERNEL_WriteShBuffer(Kernel, shBuf, uData, bytes));
+                break;
+
+            case gcvSHBUF_READ:
+                shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+                uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
+                bytes = Interface->u.ShBuf.bytes;
+
+                /* Read. */
+                gcmkONERROR(
+                    gckKERNEL_ReadShBuffer(Kernel,
+                                           shBuf,
+                                           uData,
+                                           bytes,
+                                           &bytes));
+
+                /* Return copied size. */
+                Interface->u.ShBuf.bytes = bytes;
+                break;
+
+            default:
+                gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+                break;
+            }
+        }
+        break;
+
+    case gcvHAL_CONFIG_POWER_MANAGEMENT:
+        gcmkONERROR(gckKERNEL_ConfigPowerManagement(Kernel, Interface));
+        break;
+
     default:
         /* Invalid command. */
         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
@@ -2278,33 +2728,15 @@ OnError:
     /* Save status. */
     Interface->status = status;
 
-    if (gcmIS_ERROR(status))
-    {
-        if (locked)
-        {
-            /* Roll back the lock. */
-            gcmkVERIFY_OK(
-                gckVIDMEM_Unlock(Kernel,
-                                 gcmUINT64_TO_PTR(Interface->u.LockVideoMemory.node),
-                                 gcvSURF_TYPE_UNKNOWN,
-                                 &asynchronous));
-
-            if (gcvTRUE == asynchronous)
-            {
-                /* Bottom Half */
-                gcmkVERIFY_OK(
-                    gckVIDMEM_Unlock(Kernel,
-                                     gcmUINT64_TO_PTR(Interface->u.LockVideoMemory.node),
-                                     gcvSURF_TYPE_UNKNOWN,
-                                     gcvNULL));
-            }
-        }
-    }
-
 #if QNX_SINGLE_THREADED_DEBUGGING
     gckOS_ReleaseMutex(Kernel->os, Kernel->debugMutex);
 #endif
 
+    if (powerMutexAcquired == gcvTRUE)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
+    }
+
     /* Return the status. */
     gcmkFOOTER();
     return status;
@@ -2417,6 +2849,11 @@ gckKERNEL_AttachProcessEx(
             /* Create the process database. */
             gcmkONERROR(gckKERNEL_CreateProcessDB(Kernel, PID));
         }
+
+#if gcdPROCESS_ADDRESS_SPACE
+        /* Map kernel command buffer in the process's own MMU. */
+        gcmkONERROR(_MapCommandBuffer(Kernel));
+#endif
     }
     else
     {
@@ -2433,7 +2870,11 @@ gckKERNEL_AttachProcessEx(
         if (Kernel->vg == gcvNULL)
 #endif
         {
+#if gcdMULTI_GPU
+            status = gckEVENT_Submit(Kernel->eventObj, gcvTRUE, gcvFALSE, gcvCORE_3D_ALL_MASK);
+#else
             status = gckEVENT_Submit(Kernel->eventObj, gcvTRUE, gcvFALSE);
+#endif
 
             if (status == gcvSTATUS_INTERRUPTED && Kernel->eventObj->submitTimer)
             {
@@ -2661,7 +3102,7 @@ gckKERNEL_MapLogicalToPhysical(
 #elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
     {
         gctINT i;
-        gctUINT32 data = gcmPTR2INT(*Data);
+        gctUINT32 data = gcmPTR2INT32(*Data);
         gctUINT32 key, index;
         gcskLOGICAL_CACHE_PTR hash;
 
@@ -2712,56 +3153,593 @@ gckKERNEL_MapLogicalToPhysical(
                                *Data, key);
             }
 
-            /* Insert the slot at the head of the hash list. */
-            slot->nextHash     = hash->nextHash;
-            if (slot->nextHash != gcvNULL)
+            /* Insert the slot at the head of the hash list. */
+            slot->nextHash     = hash->nextHash;
+            if (slot->nextHash != gcvNULL)
+            {
+                slot->nextHash->prevHash = slot;
+            }
+            slot->prevHash     = hash;
+            hash->nextHash     = slot;
+        }
+
+        /* Move slot to head of list. */
+        if (slot != Cache->cache[0].next)
+        {
+            /* Unlink. */
+            slot->prev->next = slot->next;
+            slot->next->prev = slot->prev;
+
+            /* Move to head of chain. */
+            slot->prev       = &Cache->cache[0];
+            slot->next       = Cache->cache[0].next;
+            slot->prev->next = slot;
+            slot->next->prev = slot;
+        }
+    }
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
+    {
+        gctUINT32 index = (gcmPTR2INT32(*Data) % gcdSECURE_CACHE_SLOTS) + 1;
+
+        /* Get cache slot. */
+        slot = &Cache->cache[index];
+
+        /* Check for cache miss. */
+        if (slot->logical != *Data)
+        {
+            /* Initialize the cache line. */
+            slot->logical = *Data;
+
+            /* Map the logical address to a DMA address. */
+            gcmkONERROR(
+                gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
+        }
+    }
+#endif
+
+    /* Return DMA address. */
+    *Data = gcmINT2PTR(slot->dma + (needBase ? baseAddress : 0));
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Data=0x%08x", *Data);
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckKERNEL_FlushTranslationCache(
+    IN gckKERNEL Kernel,
+    IN gcskSECURE_CACHE_PTR Cache,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes
+    )
+{
+    gctINT i;
+    gcskLOGICAL_CACHE_PTR slot;
+    gctUINT8_PTR ptr;
+
+    gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x Logical=0x%x Bytes=%lu",
+                   Kernel, Cache, Logical, Bytes);
+
+    /* Do we need to flush the entire cache? */
+    if (Logical == gcvNULL)
+    {
+        /* Clear all cache slots. */
+        for (i = 1; i <= gcdSECURE_CACHE_SLOTS; ++i)
+        {
+            Cache->cache[i].logical  = gcvNULL;
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+            Cache->cache[i].nextHash = gcvNULL;
+            Cache->cache[i].prevHash = gcvNULL;
+#endif
+}
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+        /* Zero the hash table. */
+        for (i = 0; i < gcmCOUNTOF(Cache->hash); ++i)
+        {
+            Cache->hash[i].nextHash = gcvNULL;
+        }
+#endif
+
+        /* Reset the cache functionality. */
+        Cache->cacheIndex = gcvNULL;
+        Cache->cacheFree  = 1;
+        Cache->cacheStamp = 0;
+    }
+
+    else
+    {
+        gctUINT8_PTR low  = (gctUINT8_PTR) Logical;
+        gctUINT8_PTR high = low + Bytes;
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
+        gcskLOGICAL_CACHE_PTR next;
+
+        /* Walk all used cache slots. */
+        for (i = 1, slot = Cache->cache[0].next;
+             (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+             ++i, slot = next
+        )
+        {
+            /* Save pointer to next slot. */
+            next = slot->next;
+
+            /* Test if this slot falls within the range to flush. */
+            ptr = (gctUINT8_PTR) slot->logical;
+            if ((ptr >= low) && (ptr < high))
+            {
+                /* Unlink slot. */
+                slot->prev->next = slot->next;
+                slot->next->prev = slot->prev;
+
+                /* Append slot to tail of cache. */
+                slot->prev       = Cache->cache[0].prev;
+                slot->next       = &Cache->cache[0];
+                slot->prev->next = slot;
+                slot->next->prev = slot;
+
+                /* Mark slot as empty. */
+                slot->logical = gcvNULL;
+            }
+        }
+
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
+        gcskLOGICAL_CACHE_PTR next;
+
+        for (i = 1, slot = Cache->cache[0].next;
+             (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+             ++i, slot = next)
+        {
+            /* Save pointer to next slot. */
+            next = slot->next;
+
+            /* Test if this slot falls within the range to flush. */
+            ptr = (gctUINT8_PTR) slot->logical;
+            if ((ptr >= low) && (ptr < high))
+            {
+                /* Test if this slot is the current slot. */
+                if (slot == Cache->cacheIndex)
+                {
+                    /* Move to next or previous slot. */
+                    Cache->cacheIndex = (slot->next->logical != gcvNULL)
+                                      ? slot->next
+                                      : (slot->prev->logical != gcvNULL)
+                                      ? slot->prev
+                                      : gcvNULL;
+                }
+
+                /* Unlink slot from cache. */
+                slot->prev->next = slot->next;
+                slot->next->prev = slot->prev;
+
+                /* Insert slot to head of cache. */
+                slot->prev       = &Cache->cache[0];
+                slot->next       = Cache->cache[0].next;
+                slot->prev->next = slot;
+                slot->next->prev = slot;
+
+                /* Mark slot as empty. */
+                slot->logical = gcvNULL;
+                slot->stamp   = 0;
+            }
+        }
+
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+        gctINT j;
+        gcskLOGICAL_CACHE_PTR hash, next;
+
+        /* Walk all hash tables. */
+        for (i = 0, hash = Cache->hash;
+             i < gcmCOUNTOF(Cache->hash);
+             ++i, ++hash)
+        {
+            /* Walk all slots in the hash. */
+            for (j = 0, slot = hash->nextHash;
+                 (j < gcdSECURE_CACHE_SLOTS) && (slot != gcvNULL);
+                 ++j, slot = next)
+            {
+                /* Save pointer to next slot. */
+                next = slot->next;
+
+                /* Test if this slot falls within the range to flush. */
+                ptr = (gctUINT8_PTR) slot->logical;
+                if ((ptr >= low) && (ptr < high))
+                {
+                    /* Unlink slot from hash table. */
+                    if (slot->prevHash == hash)
+                    {
+                        hash->nextHash = slot->nextHash;
+                    }
+                    else
+                    {
+                        slot->prevHash->nextHash = slot->nextHash;
+                    }
+
+                    if (slot->nextHash != gcvNULL)
+                    {
+                        slot->nextHash->prevHash = slot->prevHash;
+                    }
+
+                    /* Unlink slot from cache. */
+                    slot->prev->next = slot->next;
+                    slot->next->prev = slot->prev;
+
+                    /* Append slot to tail of cache. */
+                    slot->prev       = Cache->cache[0].prev;
+                    slot->next       = &Cache->cache[0];
+                    slot->prev->next = slot;
+                    slot->next->prev = slot;
+
+                    /* Mark slot as empty. */
+                    slot->logical  = gcvNULL;
+                    slot->prevHash = gcvNULL;
+                    slot->nextHash = gcvNULL;
+                }
+            }
+        }
+
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
+        gctUINT32 index;
+
+        /* Loop while inside the range. */
+        for (i = 1; (low < high) && (i <= gcdSECURE_CACHE_SLOTS); ++i)
+        {
+            /* Get index into cache for this range. */
+            index = (gcmPTR2INT32(low) % gcdSECURE_CACHE_SLOTS) + 1;
+            slot  = &Cache->cache[index];
+
+            /* Test if this slot falls within the range to flush. */
+            ptr = (gctUINT8_PTR) slot->logical;
+            if ((ptr >= low) && (ptr < high))
+            {
+                /* Remove entry from cache. */
+                slot->logical = gcvNULL;
+            }
+
+            /* Next block. */
+            low += gcdSECURE_CACHE_SLOTS;
+        }
+#endif
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+#endif
+
+/*******************************************************************************
+**
+**  gckKERNEL_Recovery
+**
+**  Try to recover the GPU from a fatal error.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
+gceSTATUS
+gckKERNEL_Recovery(
+    IN gckKERNEL Kernel
+    )
+{
+    gceSTATUS status;
+    gckEVENT eventObj;
+    gckHARDWARE hardware;
+#if gcdSECURE_USER
+    gctUINT32 processID;
+    gcskSECURE_CACHE_PTR cache;
+#endif
+    gctUINT32 mask = 0;
+    gckCOMMAND command;
+    gckENTRYDATA data;
+    gctUINT32 i = 0, count = 0;
+#if gcdINTERRUPT_STATISTIC
+    gctINT32 oldValue;
+#endif
+
+    gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+    /* Validate the arguemnts. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    /* Grab gckEVENT object. */
+    eventObj = Kernel->eventObj;
+    gcmkVERIFY_OBJECT(eventObj, gcvOBJ_EVENT);
+
+    /* Grab gckHARDWARE object. */
+    hardware = Kernel->hardware;
+    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+    /* Grab gckCOMMAND object. */
+    command = Kernel->command;
+    gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
+#if gcdSECURE_USER
+    /* Flush the secure mapping cache. */
+    gcmkONERROR(gckOS_GetProcessID(&processID));
+    gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
+    gcmkONERROR(gckKERNEL_FlushTranslationCache(Kernel, cache, gcvNULL, 0));
+#endif
+
+    if (Kernel->stuckDump == gcdSTUCK_DUMP_MINIMAL)
+    {
+        gcmkPRINT("[galcore]: GPU[%d] hang, automatic recovery.", Kernel->core);
+    }
+    else
+    {
+        _DumpDriverConfigure(Kernel);
+        _DumpState(Kernel);
+    }
+
+    if (Kernel->recovery == gcvFALSE)
+    {
+        gcmkPRINT("[galcore]: Stop driver to keep scene.");
+
+        for (;;)
+        {
+            gckOS_Delay(Kernel->os, 10000);
+        }
+    }
+
+    /* Clear queue. */
+    do
+    {
+        status = gckENTRYQUEUE_Dequeue(&command->queue, &data);
+    }
+    while (status == gcvSTATUS_OK);
+
+    /* Issuing a soft reset for the GPU. */
+    gcmkONERROR(gckHARDWARE_Reset(hardware));
+
+    mask = Kernel->restoreMask;
+
+    for (i = 0; i < 32; i++)
+    {
+        if (mask & (1 << i))
+        {
+            count++;
+        }
+    }
+
+    /* Handle all outstanding events now. */
+#if gcdSMP
+#if gcdMULTI_GPU
+    if (Kernel->core == gcvCORE_MAJOR)
+    {
+        for (i = 0; i < gcdMULTI_GPU; i++)
+        {
+            gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending3D[i], mask));
+        }
+    }
+    else
+    {
+        gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending, mask));
+    }
+#else
+    gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending, mask));
+#endif
+#else
+#if gcdMULTI_GPU
+    if (Kernel->core == gcvCORE_MAJOR)
+    {
+        for (i = 0; i < gcdMULTI_GPU; i++)
+        {
+            eventObj->pending3D[i] = mask;
+        }
+    }
+    else
+    {
+        eventObj->pending = mask;
+    }
+#else
+    eventObj->pending = mask;
+#endif
+#endif
+
+#if gcdINTERRUPT_STATISTIC
+    while (count--)
+    {
+        gcmkONERROR(gckOS_AtomDecrement(
+            Kernel->os,
+            eventObj->interruptCount,
+            &oldValue
+            ));
+    }
+
+    gckOS_AtomClearMask(Kernel->hardware->pendingEvent, mask);
+#endif
+
+    gcmkONERROR(gckEVENT_Notify(eventObj, 1));
+
+    gcmkVERIFY_OK(gckOS_GetTime(&Kernel->resetTimeStamp));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckKERNEL_OpenUserData
+**
+**  Get access to the user data.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctBOOL NeedCopy
+**          The flag indicating whether or not the data should be copied.
+**
+**      gctPOINTER StaticStorage
+**          Pointer to the kernel storage where the data is to be copied if
+**          NeedCopy is gcvTRUE.
+**
+**      gctPOINTER UserPointer
+**          User pointer to the data.
+**
+**      gctSIZE_T Size
+**          Size of the data.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * KernelPointer
+**          Pointer to the kernel pointer that will be pointing to the data.
+*/
+gceSTATUS
+gckKERNEL_OpenUserData(
+    IN gckKERNEL Kernel,
+    IN gctBOOL NeedCopy,
+    IN gctPOINTER StaticStorage,
+    IN gctPOINTER UserPointer,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * KernelPointer
+    )
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG(
+        "Kernel=0x%08X NeedCopy=%d StaticStorage=0x%08X "
+        "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
+        Kernel, NeedCopy, StaticStorage, UserPointer, Size, KernelPointer
+        );
+
+    /* Validate the arguemnts. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(!NeedCopy || (StaticStorage != gcvNULL));
+    gcmkVERIFY_ARGUMENT(UserPointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Size > 0);
+
+    if (NeedCopy)
+    {
+        /* Copy the user data to the static storage. */
+        gcmkONERROR(gckOS_CopyFromUserData(
+            Kernel->os, StaticStorage, UserPointer, Size
+            ));
+
+        /* Set the kernel pointer. */
+        * KernelPointer = StaticStorage;
+    }
+    else
+    {
+        gctPOINTER pointer = gcvNULL;
+
+        /* Map the user pointer. */
+        gcmkONERROR(gckOS_MapUserPointer(
+            Kernel->os, UserPointer, Size, &pointer
+            ));
+
+        /* Set the kernel pointer. */
+        * KernelPointer = pointer;
+    }
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckKERNEL_CloseUserData
+**
+**  Release resources associated with the user data connection opened by
+**  gckKERNEL_OpenUserData.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctBOOL NeedCopy
+**          The flag indicating whether or not the data should be copied.
+**
+**      gctBOOL FlushData
+**          If gcvTRUE, the data is written back to the user.
+**
+**      gctPOINTER UserPointer
+**          User pointer to the data.
+**
+**      gctSIZE_T Size
+**          Size of the data.
+**
+**  OUTPUT:
+**
+**      gctPOINTER * KernelPointer
+**          Kernel pointer to the data.
+*/
+gceSTATUS
+gckKERNEL_CloseUserData(
+    IN gckKERNEL Kernel,
+    IN gctBOOL NeedCopy,
+    IN gctBOOL FlushData,
+    IN gctPOINTER UserPointer,
+    IN gctSIZE_T Size,
+    OUT gctPOINTER * KernelPointer
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+    gctPOINTER pointer;
+
+    gcmkHEADER_ARG(
+        "Kernel=0x%08X NeedCopy=%d FlushData=%d "
+        "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
+        Kernel, NeedCopy, FlushData, UserPointer, Size, KernelPointer
+        );
+
+    /* Validate the arguemnts. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(UserPointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Size > 0);
+
+    /* Get a shortcut to the kernel pointer. */
+    pointer = * KernelPointer;
+
+    if (pointer != gcvNULL)
+    {
+        if (NeedCopy)
+        {
+            if (FlushData)
             {
-                slot->nextHash->prevHash = slot;
+                gcmkONERROR(gckOS_CopyToUserData(
+                    Kernel->os, * KernelPointer, UserPointer, Size
+                    ));
             }
-            slot->prevHash     = hash;
-            hash->nextHash     = slot;
         }
-
-        /* Move slot to head of list. */
-        if (slot != Cache->cache[0].next)
+        else
         {
-            /* Unlink. */
-            slot->prev->next = slot->next;
-            slot->next->prev = slot->prev;
-
-            /* Move to head of chain. */
-            slot->prev       = &Cache->cache[0];
-            slot->next       = Cache->cache[0].next;
-            slot->prev->next = slot;
-            slot->next->prev = slot;
+            /* Unmap record from kernel memory. */
+            gcmkONERROR(gckOS_UnmapUserPointer(
+                Kernel->os,
+                UserPointer,
+                Size,
+                * KernelPointer
+                ));
         }
-    }
-#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
-    {
-        gctUINT32 index = (gcmPTR2INT(*Data) % gcdSECURE_CACHE_SLOTS) + 1;
-
-        /* Get cache slot. */
-        slot = &Cache->cache[index];
-
-        /* Check for cache miss. */
-        if (slot->logical != *Data)
-        {
-            /* Initialize the cache line. */
-            slot->logical = *Data;
 
-            /* Map the logical address to a DMA address. */
-            gcmkONERROR(
-                gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
-        }
+        /* Reset the kernel pointer. */
+        * KernelPointer = gcvNULL;
     }
-#endif
-
-    /* Return DMA address. */
-    *Data = gcmINT2PTR(slot->dma + (needBase ? baseAddress : 0));
-
-    /* Success. */
-    gcmkFOOTER_ARG("*Data=0x%08x", *Data);
-    return gcvSTATUS_OK;
 
 OnError:
     /* Return the status. */
@@ -2769,1065 +3747,1063 @@ OnError:
     return status;
 }
 
-gceSTATUS
-gckKERNEL_FlushTranslationCache(
+void
+gckKERNEL_SetTimeOut(
     IN gckKERNEL Kernel,
-    IN gcskSECURE_CACHE_PTR Cache,
-    IN gctPOINTER Logical,
-    IN gctSIZE_T Bytes
+    IN gctUINT32 timeOut
     )
 {
-    gctINT i;
-    gcskLOGICAL_CACHE_PTR slot;
-    gctUINT8_PTR ptr;
-
-    gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x Logical=0x%x Bytes=%lu",
-                   Kernel, Cache, Logical, Bytes);
-
-    /* Do we need to flush the entire cache? */
-    if (Logical == gcvNULL)
-    {
-        /* Clear all cache slots. */
-        for (i = 1; i <= gcdSECURE_CACHE_SLOTS; ++i)
-        {
-            Cache->cache[i].logical  = gcvNULL;
-
-#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
-            Cache->cache[i].nextHash = gcvNULL;
-            Cache->cache[i].prevHash = gcvNULL;
+    gcmkHEADER_ARG("Kernel=0x%x timeOut=%d", Kernel, timeOut);
+#if gcdGPU_TIMEOUT
+    Kernel->timeOut = timeOut;
 #endif
+    gcmkFOOTER_NO();
 }
 
-#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
-        /* Zero the hash table. */
-        for (i = 0; i < gcmCOUNTOF(Cache->hash); ++i)
-        {
-            Cache->hash[i].nextHash = gcvNULL;
-        }
-#endif
-
-        /* Reset the cache functionality. */
-        Cache->cacheIndex = gcvNULL;
-        Cache->cacheFree  = 1;
-        Cache->cacheStamp = 0;
-    }
-
-    else
-    {
-        gctUINT8_PTR low  = (gctUINT8_PTR) Logical;
-        gctUINT8_PTR high = low + Bytes;
+gceSTATUS
+gckKERNEL_AllocateVirtualCommandBuffer(
+    IN gckKERNEL Kernel,
+    IN gctBOOL InUserSpace,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctPHYS_ADDR * Physical,
+    OUT gctPOINTER * Logical
+    )
+{
+    gckOS os                             = Kernel->os;
+    gceSTATUS status;
+    gctPOINTER logical                   = gcvNULL;
+    gctSIZE_T pageCount;
+    gctSIZE_T bytes                      = *Bytes;
+    gckVIRTUAL_COMMAND_BUFFER_PTR buffer = gcvNULL;
+    gckMMU mmu;
+    gctUINT32 flag = gcvALLOC_FLAG_NON_CONTIGUOUS;
 
-#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
-        gcskLOGICAL_CACHE_PTR next;
+    gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
+                   os, InUserSpace, gcmOPT_VALUE(Bytes));
 
-        /* Walk all used cache slots. */
-        for (i = 1, slot = Cache->cache[0].next;
-             (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
-             ++i, slot = next
-        )
-        {
-            /* Save pointer to next slot. */
-            next = slot->next;
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
+    gcmkVERIFY_ARGUMENT(*Bytes > 0);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
 
-            /* Test if this slot falls within the range to flush. */
-            ptr = (gctUINT8_PTR) slot->logical;
-            if ((ptr >= low) && (ptr < high))
-            {
-                /* Unlink slot. */
-                slot->prev->next = slot->next;
-                slot->next->prev = slot->prev;
+    gcmkONERROR(gckOS_Allocate(os,
+                               sizeof(gckVIRTUAL_COMMAND_BUFFER),
+                               (gctPOINTER)&buffer));
 
-                /* Append slot to tail of cache. */
-                slot->prev       = Cache->cache[0].prev;
-                slot->next       = &Cache->cache[0];
-                slot->prev->next = slot;
-                slot->next->prev = slot;
+    gcmkONERROR(gckOS_ZeroMemory(buffer, sizeof(gckVIRTUAL_COMMAND_BUFFER)));
 
-                /* Mark slot as empty. */
-                slot->logical = gcvNULL;
-            }
-        }
+    buffer->bytes = bytes;
 
-#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
-        gcskLOGICAL_CACHE_PTR next;
+    gcmkONERROR(gckOS_AllocatePagedMemoryEx(os,
+                                            flag,
+                                            bytes,
+                                            gcvNULL,
+                                            &buffer->physical));
 
-        for (i = 1, slot = Cache->cache[0].next;
-             (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
-             ++i, slot = next)
-        {
-            /* Save pointer to next slot. */
-            next = slot->next;
+    if (InUserSpace)
+    {
+        gcmkONERROR(gckOS_CreateUserVirtualMapping(os,
+                                                   buffer->physical,
+                                                   bytes,
+                                                   &logical,
+                                                   &pageCount));
 
-            /* Test if this slot falls within the range to flush. */
-            ptr = (gctUINT8_PTR) slot->logical;
-            if ((ptr >= low) && (ptr < high))
-            {
-                /* Test if this slot is the current slot. */
-                if (slot == Cache->cacheIndex)
-                {
-                    /* Move to next or previous slot. */
-                    Cache->cacheIndex = (slot->next->logical != gcvNULL)
-                                      ? slot->next
-                                      : (slot->prev->logical != gcvNULL)
-                                      ? slot->prev
-                                      : gcvNULL;
-                }
+        *Logical =
+        buffer->userLogical = logical;
+    }
+    else
+    {
+        gcmkONERROR(gckOS_CreateKernelVirtualMapping(os,
+                                                     buffer->physical,
+                                                     bytes,
+                                                     &logical,
+                                                     &pageCount));
 
-                /* Unlink slot from cache. */
-                slot->prev->next = slot->next;
-                slot->next->prev = slot->prev;
+        *Logical =
+        buffer->kernelLogical = logical;
+    }
 
-                /* Insert slot to head of cache. */
-                slot->prev       = &Cache->cache[0];
-                slot->next       = Cache->cache[0].next;
-                slot->prev->next = slot;
-                slot->next->prev = slot;
+    buffer->pageCount = pageCount;
+    buffer->kernel = Kernel;
 
-                /* Mark slot as empty. */
-                slot->logical = gcvNULL;
-                slot->stamp   = 0;
-            }
-        }
+    gcmkONERROR(gckOS_GetProcessID(&buffer->pid));
 
-#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
-        gctINT j;
-        gcskLOGICAL_CACHE_PTR hash, next;
+#if gcdPROCESS_ADDRESS_SPACE
+    gcmkONERROR(gckKERNEL_GetProcessMMU(Kernel, &mmu));
+    buffer->mmu = mmu;
+#else
+    mmu = Kernel->mmu;
+#endif
 
-        /* Walk all hash tables. */
-        for (i = 0, hash = Cache->hash;
-             i < gcmCOUNTOF(Cache->hash);
-             ++i, ++hash)
-        {
-            /* Walk all slots in the hash. */
-            for (j = 0, slot = hash->nextHash;
-                 (j < gcdSECURE_CACHE_SLOTS) && (slot != gcvNULL);
-                 ++j, slot = next)
-            {
-                /* Save pointer to next slot. */
-                next = slot->next;
+    gcmkONERROR(gckMMU_AllocatePages(mmu,
+                                     pageCount,
+                                     &buffer->pageTable,
+                                     &buffer->gpuAddress));
 
-                /* Test if this slot falls within the range to flush. */
-                ptr = (gctUINT8_PTR) slot->logical;
-                if ((ptr >= low) && (ptr < high))
-                {
-                    /* Unlink slot from hash table. */
-                    if (slot->prevHash == hash)
-                    {
-                        hash->nextHash = slot->nextHash;
-                    }
-                    else
-                    {
-                        slot->prevHash->nextHash = slot->nextHash;
-                    }
 
-                    if (slot->nextHash != gcvNULL)
-                    {
-                        slot->nextHash->prevHash = slot->prevHash;
-                    }
+    gcmkONERROR(gckOS_MapPagesEx(os,
+                                 Kernel->core,
+                                 buffer->physical,
+                                 pageCount,
+                                 buffer->gpuAddress,
+                                 buffer->pageTable));
 
-                    /* Unlink slot from cache. */
-                    slot->prev->next = slot->next;
-                    slot->next->prev = slot->prev;
+    gcmkONERROR(gckMMU_Flush(mmu, gcvSURF_INDEX));
 
-                    /* Append slot to tail of cache. */
-                    slot->prev       = Cache->cache[0].prev;
-                    slot->next       = &Cache->cache[0];
-                    slot->prev->next = slot;
-                    slot->next->prev = slot;
+    *Physical = buffer;
 
-                    /* Mark slot as empty. */
-                    slot->logical  = gcvNULL;
-                    slot->prevHash = gcvNULL;
-                    slot->nextHash = gcvNULL;
-                }
-            }
-        }
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+                   "gpuAddress = %x pageCount = %d kernelLogical = %x userLogical=%x",
+                   buffer->gpuAddress, buffer->pageCount,
+                   buffer->kernelLogical, buffer->userLogical);
 
-#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
-        gctUINT32 index;
+    gcmkVERIFY_OK(gckOS_AcquireMutex(os, Kernel->virtualBufferLock, gcvINFINITE));
 
-        /* Loop while inside the range. */
-        for (i = 1; (low < high) && (i <= gcdSECURE_CACHE_SLOTS); ++i)
-        {
-            /* Get index into cache for this range. */
-            index = (gcmPTR2INT(low) % gcdSECURE_CACHE_SLOTS) + 1;
-            slot  = &Cache->cache[index];
+    if (Kernel->virtualBufferHead == gcvNULL)
+    {
+        Kernel->virtualBufferHead =
+        Kernel->virtualBufferTail = buffer;
+    }
+    else
+    {
+        buffer->prev = Kernel->virtualBufferTail;
+        Kernel->virtualBufferTail->next = buffer;
+        Kernel->virtualBufferTail = buffer;
+    }
 
-            /* Test if this slot falls within the range to flush. */
-            ptr = (gctUINT8_PTR) slot->logical;
-            if ((ptr >= low) && (ptr < high))
-            {
-                /* Remove entry from cache. */
-                slot->logical = gcvNULL;
-            }
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Kernel->virtualBufferLock));
 
-            /* Next block. */
-            low += gcdSECURE_CACHE_SLOTS;
-        }
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (buffer->gpuAddress)
+    {
+#if gcdPROCESS_ADDRESS_SPACE
+        gcmkVERIFY_OK(
+            gckMMU_FreePages(mmu, buffer->pageTable, buffer->pageCount));
+#else
+        gcmkVERIFY_OK(
+            gckMMU_FreePages(Kernel->mmu, buffer->pageTable, buffer->pageCount));
 #endif
     }
 
-    /* Success. */
-    gcmkFOOTER_NO();
-    return gcvSTATUS_OK;
+    if (buffer->userLogical)
+    {
+        gcmkVERIFY_OK(
+            gckOS_DestroyUserVirtualMapping(os,
+                                            buffer->physical,
+                                            bytes,
+                                            buffer->userLogical));
+    }
+
+    if (buffer->kernelLogical)
+    {
+        gcmkVERIFY_OK(
+            gckOS_DestroyKernelVirtualMapping(os,
+                                              buffer->physical,
+                                              bytes,
+                                              buffer->kernelLogical));
+    }
+
+    if (buffer->physical)
+    {
+        gcmkVERIFY_OK(gckOS_FreePagedMemory(os, buffer->physical, bytes));
+    }
+
+    gcmkVERIFY_OK(gckOS_Free(os, buffer));
+
+    /* 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
+gckKERNEL_DestroyVirtualCommandBuffer(
+    IN gckKERNEL Kernel,
+    IN gctSIZE_T Bytes,
+    IN gctPHYS_ADDR Physical,
+    IN gctPOINTER Logical
     )
 {
-#if gcdENABLE_RECOVERY
-#define gcdEVENT_MASK 0x3FFFFFFF
-    gceSTATUS status;
-    gckEVENT eventObj;
-    gckHARDWARE hardware;
-#if gcdSECURE_USER
-    gctUINT32 processID;
-    gcskSECURE_CACHE_PTR cache;
-#endif
-    gctUINT32 oldValue;
-    gcmkHEADER_ARG("Kernel=0x%x", Kernel);
-
-    /* Validate the arguemnts. */
-    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
-
-    /* Grab gckEVENT object. */
-    eventObj = Kernel->eventObj;
-    gcmkVERIFY_OBJECT(eventObj, gcvOBJ_EVENT);
-
-    /* Grab gckHARDWARE object. */
-    hardware = Kernel->hardware;
-    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+    gckOS os;
+    gckKERNEL kernel;
+    gckVIRTUAL_COMMAND_BUFFER_PTR buffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)Physical;
 
-#if gcdSECURE_USER
-    /* Flush the secure mapping cache. */
-    gcmkONERROR(gckOS_GetProcessID(&processID));
-    gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
-    gcmkONERROR(gckKERNEL_FlushTranslationCache(Kernel, cache, gcvNULL, 0));
-#endif
+    gcmkHEADER();
+    gcmkVERIFY_ARGUMENT(buffer != gcvNULL);
 
-    gcmkONERROR(
-        gckOS_AtomicExchange(Kernel->os, Kernel->resetAtom, 1, &oldValue));
+    kernel = buffer->kernel;
+    os = kernel->os;
 
-    if (oldValue)
+    if (!buffer->userLogical)
     {
-        /* Some one else will recovery GPU. */
-        return gcvSTATUS_OK;
+        gcmkVERIFY_OK(gckOS_DestroyKernelVirtualMapping(os,
+                                                        buffer->physical,
+                                                        Bytes,
+                                                        Logical));
     }
 
-    gcmkPRINT("[galcore]: GPU[%d] hang, automatic recovery.", Kernel->core);
-
-    /* Start a timer to clear reset flag, before timer is expired,
-    ** other recovery request is ignored. */
+#if !gcdPROCESS_ADDRESS_SPACE
     gcmkVERIFY_OK(
-        gckOS_StartTimer(Kernel->os,
-                         Kernel->resetFlagClearTimer,
-                         gcdGPU_TIMEOUT - 500));
+        gckMMU_FreePages(kernel->mmu, buffer->pageTable, buffer->pageCount));
+#endif
 
+    gcmkVERIFY_OK(gckOS_UnmapPages(os, buffer->pageCount, buffer->gpuAddress));
 
-    /* Try issuing a soft reset for the GPU. */
-    status = gckHARDWARE_Reset(hardware);
-    if (status == gcvSTATUS_NOT_SUPPORTED)
+    gcmkVERIFY_OK(gckOS_FreePagedMemory(os, buffer->physical, Bytes));
+
+    gcmkVERIFY_OK(gckOS_AcquireMutex(os, kernel->virtualBufferLock, gcvINFINITE));
+
+    if (buffer == kernel->virtualBufferHead)
     {
-        /* Switch to OFF power.  The next submit should return the GPU to ON
-        ** state. */
-        gcmkONERROR(
-            gckHARDWARE_SetPowerManagementState(hardware,
-                                                gcvPOWER_OFF_RECOVERY));
+        if ((kernel->virtualBufferHead = buffer->next) == gcvNULL)
+        {
+            kernel->virtualBufferTail = gcvNULL;
+        }
     }
     else
     {
-        /* Bail out on reset error. */
-        gcmkONERROR(status);
-    }
+        buffer->prev->next = buffer->next;
 
-    /* Handle all outstanding events now. */
-#if gcdSMP
-    gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending, gcdEVENT_MASK));
-#else
-    eventObj->pending = gcdEVENT_MASK;
-#endif
-    gcmkONERROR(gckEVENT_Notify(eventObj, 1));
+        if (buffer == kernel->virtualBufferTail)
+        {
+            kernel->virtualBufferTail = buffer->prev;
+        }
+        else
+        {
+            buffer->next->prev = buffer->prev;
+        }
+    }
 
-    /* Again in case more events got submitted. */
-#if gcdSMP
-    gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending, gcdEVENT_MASK));
-#else
-    eventObj->pending = gcdEVENT_MASK;
-#endif
-    gcmkONERROR(gckEVENT_Notify(eventObj, 2));
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, kernel->virtualBufferLock));
 
-    Kernel->resetTimeStamp++;
+    gcmkVERIFY_OK(gckOS_Free(os, buffer));
 
-    /* Success. */
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
-
-OnError:
-    /* Return the status. */
-    gcmkFOOTER();
-    return status;
-#else
-    return gcvSTATUS_OK;
-#endif
 }
 
-/*******************************************************************************
-**
-**  gckKERNEL_OpenUserData
-**
-**  Get access to the user data.
-**
-**  INPUT:
-**
-**      gckKERNEL Kernel
-**          Pointer to an gckKERNEL object.
-**
-**      gctBOOL NeedCopy
-**          The flag indicating whether or not the data should be copied.
-**
-**      gctPOINTER StaticStorage
-**          Pointer to the kernel storage where the data is to be copied if
-**          NeedCopy is gcvTRUE.
-**
-**      gctPOINTER UserPointer
-**          User pointer to the data.
-**
-**      gctSIZE_T Size
-**          Size of the data.
-**
-**  OUTPUT:
-**
-**      gctPOINTER * KernelPointer
-**          Pointer to the kernel pointer that will be pointing to the data.
-*/
 gceSTATUS
-gckKERNEL_OpenUserData(
+gckKERNEL_GetGPUAddress(
+    IN gckKERNEL Kernel,
+    IN gctPOINTER Logical,
+    IN gctBOOL InUserSpace,
+    OUT gctUINT32 * Address
+    )
+{
+    gceSTATUS status;
+    gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
+    gctPOINTER start;
+    gctUINT32 pid;
+
+    gcmkHEADER_ARG("Logical = %x InUserSpace=%d.", Logical, InUserSpace);
+
+    gcmkVERIFY_OK(gckOS_GetProcessID(&pid));
+
+    status = gcvSTATUS_INVALID_ADDRESS;
+
+    gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, Kernel->virtualBufferLock, gcvINFINITE));
+
+    /* Walk all command buffer. */
+    for (buffer = Kernel->virtualBufferHead; buffer != gcvNULL; buffer = buffer->next)
+    {
+        if (InUserSpace)
+        {
+            start = buffer->userLogical;
+        }
+        else
+        {
+            start = buffer->kernelLogical;
+        }
+
+        if (start == gcvNULL)
+        {
+            continue;
+        }
+
+        if (Logical >= start
+        && (Logical < (gctPOINTER)((gctUINT8_PTR)start + buffer->pageCount * 4096))
+        && pid == buffer->pid
+        )
+        {
+            * Address = buffer->gpuAddress + (gctUINT32)((gctUINT8_PTR)Logical - (gctUINT8_PTR)start);
+            status = gcvSTATUS_OK;
+            break;
+        }
+    }
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->virtualBufferLock));
+
+    gcmkFOOTER_NO();
+    return status;
+}
+
+gceSTATUS
+gckKERNEL_QueryGPUAddress(
     IN gckKERNEL Kernel,
-    IN gctBOOL NeedCopy,
-    IN gctPOINTER StaticStorage,
-    IN gctPOINTER UserPointer,
-    IN gctSIZE_T Size,
-    OUT gctPOINTER * KernelPointer
+    IN gctUINT32 GpuAddress,
+    OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
     )
 {
-    gceSTATUS status;
-
-    gcmkHEADER_ARG(
-        "Kernel=0x%08X NeedCopy=%d StaticStorage=0x%08X "
-        "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
-        Kernel, NeedCopy, StaticStorage, UserPointer, Size, KernelPointer
-        );
+    gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
+    gctUINT32 start;
+    gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
 
-    /* Validate the arguemnts. */
-    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
-    gcmkVERIFY_ARGUMENT(!NeedCopy || (StaticStorage != gcvNULL));
-    gcmkVERIFY_ARGUMENT(UserPointer != gcvNULL);
-    gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
-    gcmkVERIFY_ARGUMENT(Size > 0);
+    gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, Kernel->virtualBufferLock, gcvINFINITE));
 
-    if (NeedCopy)
+    /* Walk all command buffers. */
+    for (buffer = Kernel->virtualBufferHead; buffer != gcvNULL; buffer = buffer->next)
     {
-        /* Copy the user data to the static storage. */
-        gcmkONERROR(gckOS_CopyFromUserData(
-            Kernel->os, StaticStorage, UserPointer, Size
-            ));
+        start = (gctUINT32)buffer->gpuAddress;
 
-        /* Set the kernel pointer. */
-        * KernelPointer = StaticStorage;
+        if (GpuAddress >= start && GpuAddress < (start + buffer->pageCount * 4096))
+        {
+            /* Find a range matched. */
+            *Buffer = buffer;
+            status = gcvSTATUS_OK;
+            break;
+        }
     }
-    else
-    {
-        gctPOINTER pointer = gcvNULL;
-
-        /* Map the user pointer. */
-        gcmkONERROR(gckOS_MapUserPointer(
-            Kernel->os, UserPointer, Size, &pointer
-            ));
 
-        /* Set the kernel pointer. */
-        * KernelPointer = pointer;
-    }
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->virtualBufferLock));
 
-OnError:
-    /* Return the status. */
-    gcmkFOOTER();
     return status;
 }
 
-/*******************************************************************************
-**
-**  gckKERNEL_CloseUserData
-**
-**  Release resources associated with the user data connection opened by
-**  gckKERNEL_OpenUserData.
-**
-**  INPUT:
-**
-**      gckKERNEL Kernel
-**          Pointer to an gckKERNEL object.
-**
-**      gctBOOL NeedCopy
-**          The flag indicating whether or not the data should be copied.
-**
-**      gctBOOL FlushData
-**          If gcvTRUE, the data is written back to the user.
-**
-**      gctPOINTER UserPointer
-**          User pointer to the data.
-**
-**      gctSIZE_T Size
-**          Size of the data.
-**
-**  OUTPUT:
-**
-**      gctPOINTER * KernelPointer
-**          Kernel pointer to the data.
-*/
-gceSTATUS
-gckKERNEL_CloseUserData(
-    IN gckKERNEL Kernel,
-    IN gctBOOL NeedCopy,
-    IN gctBOOL FlushData,
-    IN gctPOINTER UserPointer,
-    IN gctSIZE_T Size,
-    OUT gctPOINTER * KernelPointer
+#if gcdLINK_QUEUE_SIZE
+static void
+gckLINKQUEUE_Dequeue(
+    IN gckLINKQUEUE LinkQueue
     )
 {
-    gceSTATUS status = gcvSTATUS_OK;
-    gctPOINTER pointer;
+    gcmkASSERT(LinkQueue->count == gcdLINK_QUEUE_SIZE);
 
-    gcmkHEADER_ARG(
-        "Kernel=0x%08X NeedCopy=%d FlushData=%d "
-        "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
-        Kernel, NeedCopy, FlushData, UserPointer, Size, KernelPointer
-        );
+    LinkQueue->count--;
+    LinkQueue->front = (LinkQueue->front + 1) % gcdLINK_QUEUE_SIZE;
+}
 
-    /* Validate the arguemnts. */
-    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
-    gcmkVERIFY_ARGUMENT(UserPointer != gcvNULL);
-    gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
-    gcmkVERIFY_ARGUMENT(Size > 0);
+void
+gckLINKQUEUE_Enqueue(
+    IN gckLINKQUEUE LinkQueue,
+    IN gctUINT32 start,
+    IN gctUINT32 end
+    )
+{
+    if (LinkQueue->count == gcdLINK_QUEUE_SIZE)
+    {
+        gckLINKQUEUE_Dequeue(LinkQueue);
+    }
 
-    /* Get a shortcut to the kernel pointer. */
-    pointer = * KernelPointer;
+    gcmkASSERT(LinkQueue->count < gcdLINK_QUEUE_SIZE);
 
-    if (pointer != gcvNULL)
-    {
-        if (NeedCopy)
-        {
-            if (FlushData)
-            {
-                gcmkONERROR(gckOS_CopyToUserData(
-                    Kernel->os, * KernelPointer, UserPointer, Size
-                    ));
-            }
-        }
-        else
-        {
-            /* Unmap record from kernel memory. */
-            gcmkONERROR(gckOS_UnmapUserPointer(
-                Kernel->os,
-                UserPointer,
-                Size,
-                * KernelPointer
-                ));
-        }
+    LinkQueue->count++;
 
-        /* Reset the kernel pointer. */
-        * KernelPointer = gcvNULL;
-    }
+    LinkQueue->data[LinkQueue->rear].start = start;
+    LinkQueue->data[LinkQueue->rear].end = end;
 
-OnError:
-    /* Return the status. */
-    gcmkFOOTER();
-    return status;
+    gcmkVERIFY_OK(
+        gckOS_GetProcessID(&LinkQueue->data[LinkQueue->rear].pid));
+
+    LinkQueue->rear = (LinkQueue->rear + 1) % gcdLINK_QUEUE_SIZE;
 }
 
 void
-gckKERNEL_SetTimeOut(
-    IN gckKERNEL Kernel,
-    IN gctUINT32 timeOut
+gckLINKQUEUE_GetData(
+    IN gckLINKQUEUE LinkQueue,
+    IN gctUINT32 Index,
+    OUT gckLINKDATA * Data
     )
 {
-    gcmkHEADER_ARG("Kernel=0x%x timeOut=%d", Kernel, timeOut);
-#if gcdGPU_TIMEOUT
-    Kernel->timeOut = timeOut;
-#endif
-    gcmkFOOTER_NO();
+    gcmkASSERT(Index >= 0 && Index < gcdLINK_QUEUE_SIZE);
+
+    *Data = &LinkQueue->data[(Index + LinkQueue->front) % gcdLINK_QUEUE_SIZE];
 }
+#endif
 
-#if gcdVIRTUAL_COMMAND_BUFFER
+/*
+* gckENTRYQUEUE_Enqueue is called with Command->mutexQueue acquired.
+*/
 gceSTATUS
-gckKERNEL_AllocateVirtualCommandBuffer(
+gckENTRYQUEUE_Enqueue(
     IN gckKERNEL Kernel,
-    IN gctBOOL InUserSpace,
-    IN OUT gctSIZE_T * Bytes,
-    OUT gctPHYS_ADDR * Physical,
-    OUT gctPOINTER * Logical
+    IN gckENTRYQUEUE Queue,
+    IN gctUINT32 physical,
+    IN gctUINT32 bytes
     )
 {
-    gckOS os = Kernel->os;
-    gceSTATUS status;
-    gctPOINTER logical;
-    gctSIZE_T pageCount;
-    gctSIZE_T bytes = *Bytes;
-    gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
-
-    gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
-                   os, InUserSpace, gcmOPT_VALUE(Bytes));
+    gctUINT32 next = (Queue->rear + 1) % gcdENTRY_QUEUE_SIZE;
 
-    /* Verify the arguments. */
-    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
-    gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
-    gcmkVERIFY_ARGUMENT(*Bytes > 0);
-    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
-    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    if (next == Queue->front)
+    {
+        /* Queue is full. */
+        return gcvSTATUS_INVALID_REQUEST;
+    }
 
-    gcmkONERROR(gckOS_Allocate(os,
-                               sizeof(gckVIRTUAL_COMMAND_BUFFER),
-                               (gctPOINTER)&buffer));
+    /* Copy data. */
+    Queue->data[Queue->rear].physical = physical;
+    Queue->data[Queue->rear].bytes = bytes;
 
-    gcmkONERROR(gckOS_ZeroMemory(buffer, sizeof(gckVIRTUAL_COMMAND_BUFFER)));
+    gcmkVERIFY_OK(gckOS_MemoryBarrier(Kernel->os, &Queue->rear));
 
-    gcmkONERROR(gckOS_AllocatePagedMemoryEx(os,
-                                            gcvFALSE,
-                                            bytes,
-                                            &buffer->physical));
+    /* Update rear. */
+    Queue->rear = next;
 
-    if (InUserSpace)
-    {
-        gcmkONERROR(gckOS_LockPages(os,
-                                    buffer->physical,
-                                    bytes,
-                                    gcvFALSE,
-                                    &logical,
-                                    &pageCount));
+    return gcvSTATUS_OK;
+}
 
-        *Logical =
-        buffer->userLogical = logical;
-    }
-    else
+gceSTATUS
+gckENTRYQUEUE_Dequeue(
+    IN gckENTRYQUEUE Queue,
+    OUT gckENTRYDATA * Data
+    )
+{
+    if (Queue->front == Queue->rear)
     {
-        gcmkONERROR(
-            gckOS_CreateKernelVirtualMapping(buffer->physical,
-                                             &pageCount,
-                                             &logical));
-        *Logical =
-        buffer->kernelLogical = logical;
+        /* Queue is empty. */
+        return gcvSTATUS_INVALID_REQUEST;
     }
 
-    buffer->pageCount = pageCount;
-    buffer->kernel = Kernel;
+    /* Copy data. */
+    *Data = &Queue->data[Queue->front];
+
+    /* Update front. */
+    Queue->front = (Queue->front + 1) % gcdENTRY_QUEUE_SIZE;
+
+    return gcvSTATUS_OK;
+}
+
+/******************************************************************************\
+*************************** Pointer - ID translation ***************************
+\******************************************************************************/
+#define gcdID_TABLE_LENGTH 1024
+typedef struct _gcsINTEGERDB * gckINTEGERDB;
+typedef struct _gcsINTEGERDB
+{
+    gckOS                       os;
+    gctPOINTER*                 table;
+    gctPOINTER                  mutex;
+    gctUINT32                   tableLen;
+    gctUINT32                   currentID;
+    gctUINT32                   unused;
+}
+gcsINTEGERDB;
+
+gceSTATUS
+gckKERNEL_CreateIntegerDatabase(
+    IN gckKERNEL Kernel,
+    OUT gctPOINTER * Database
+    )
+{
+    gceSTATUS status;
+    gckINTEGERDB database = gcvNULL;
 
-    gcmkONERROR(gckOS_GetProcessID(&buffer->pid));
+    gcmkHEADER_ARG("Kernel=0x%08X Datbase=0x%08X", Kernel, Database);
 
-    gcmkONERROR(gckMMU_AllocatePages(Kernel->mmu,
-                                     pageCount,
-                                     &buffer->pageTable,
-                                     &buffer->gpuAddress));
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Database != gcvNULL);
 
-    gcmkONERROR(gckOS_MapPagesEx(os,
-                                 Kernel->core,
-                                 buffer->physical,
-                                 pageCount,
-                                 buffer->pageTable));
+    /* Allocate a database. */
+    gcmkONERROR(gckOS_Allocate(
+        Kernel->os, gcmSIZEOF(gcsINTEGERDB), (gctPOINTER *)&database));
 
-    gcmkONERROR(gckMMU_Flush(Kernel->mmu));
+    gcmkONERROR(gckOS_ZeroMemory(database, gcmSIZEOF(gcsINTEGERDB)));
 
-    *Physical = buffer;
+    /* Allocate a pointer table. */
+    gcmkONERROR(gckOS_Allocate(
+        Kernel->os, gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH, (gctPOINTER *)&database->table));
 
-    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
-                   "gpuAddress = %x pageCount = %d kernelLogical = %x userLogical=%x",
-                   buffer->gpuAddress, buffer->pageCount,
-                   buffer->kernelLogical, buffer->userLogical);
+    gcmkONERROR(gckOS_ZeroMemory(database->table, gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH));
 
-    gcmkVERIFY_OK(gckOS_AcquireMutex(os, Kernel->virtualBufferLock, gcvINFINITE));
+    /* Allocate a database mutex. */
+    gcmkONERROR(gckOS_CreateMutex(Kernel->os, &database->mutex));
 
-    if (Kernel->virtualBufferHead == gcvNULL)
-    {
-        Kernel->virtualBufferHead =
-        Kernel->virtualBufferTail = buffer;
-    }
-    else
-    {
-        buffer->prev = Kernel->virtualBufferTail;
-        Kernel->virtualBufferTail->next = buffer;
-        Kernel->virtualBufferTail = buffer;
-    }
+    /* Initialize. */
+    database->currentID = 0;
+    database->unused = gcdID_TABLE_LENGTH;
+    database->os = Kernel->os;
+    database->tableLen = gcdID_TABLE_LENGTH;
 
-    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Kernel->virtualBufferLock));
+    *Database = database;
 
-    gcmkFOOTER_NO();
+    gcmkFOOTER_ARG("*Database=0x%08X", *Database);
     return gcvSTATUS_OK;
 
 OnError:
-    if (buffer->gpuAddress)
-    {
-        gcmkVERIFY_OK(
-            gckMMU_FreePages(Kernel->mmu, buffer->pageTable, buffer->pageCount));
-    }
-
-    if (buffer->userLogical)
-    {
-        gcmkVERIFY_OK(
-            gckOS_UnlockPages(os, buffer->physical, bytes, buffer->userLogical));
-    }
-
-    if (buffer->kernelLogical)
+    /* Rollback. */
+    if (database)
     {
-        gcmkVERIFY_OK(
-            gckOS_DestroyKernelVirtualMapping(buffer->kernelLogical));
-    }
+        if (database->table)
+        {
+            gcmkOS_SAFE_FREE(Kernel->os, database->table);
+        }
 
-    if (buffer->physical)
-    {
-        gcmkVERIFY_OK(gckOS_FreePagedMemory(os, buffer->physical, bytes));
+        gcmkOS_SAFE_FREE(Kernel->os, database);
     }
 
-    gcmkVERIFY_OK(gckOS_Free(os, buffer));
-
-    /* Return the status. */
     gcmkFOOTER();
     return status;
 }
 
 gceSTATUS
-gckKERNEL_DestroyVirtualCommandBuffer(
+gckKERNEL_DestroyIntegerDatabase(
     IN gckKERNEL Kernel,
-    IN gctSIZE_T Bytes,
-    IN gctPHYS_ADDR Physical,
-    IN gctPOINTER Logical
+    IN gctPOINTER Database
     )
 {
-    gckOS os;
-    gckKERNEL kernel;
-    gckVIRTUAL_COMMAND_BUFFER_PTR buffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)Physical;
+    gckINTEGERDB database = Database;
 
-    gcmkHEADER();
-    gcmkVERIFY_ARGUMENT(buffer != gcvNULL);
+    gcmkHEADER_ARG("Kernel=0x%08X Datbase=0x%08X", Kernel, Database);
 
-    kernel = buffer->kernel;
-    os = kernel->os;
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Database != gcvNULL);
 
-    if (buffer->userLogical)
-    {
-        gcmkVERIFY_OK(gckOS_UnlockPages(os, buffer->physical, Bytes, Logical));
-    }
-    else
+    /* Destroy pointer table. */
+    gcmkOS_SAFE_FREE(Kernel->os, database->table);
+
+    /* Destroy database mutex. */
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, database->mutex));
+
+    /* Destroy database. */
+    gcmkOS_SAFE_FREE(Kernel->os, database);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckKERNEL_AllocateIntegerId(
+    IN gctPOINTER Database,
+    IN gctPOINTER Pointer,
+    OUT gctUINT32 * Id
+    )
+{
+    gceSTATUS status;
+    gckINTEGERDB database = Database;
+    gctUINT32 i, unused, currentID, tableLen;
+    gctPOINTER * table;
+    gckOS os = database->os;
+    gctBOOL acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Database=0x%08X Pointer=0x%08X", Database, Pointer);
+
+    gcmkVERIFY_ARGUMENT(Id != gcvNULL);
+
+    gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    if (database->unused < 1)
     {
-        gcmkVERIFY_OK(gckOS_DestroyKernelVirtualMapping(Logical));
+        /* Extend table. */
+        gcmkONERROR(
+            gckOS_Allocate(os,
+                           gcmSIZEOF(gctPOINTER) * (database->tableLen + gcdID_TABLE_LENGTH),
+                           (gctPOINTER *)&table));
+
+        gcmkONERROR(gckOS_ZeroMemory(table + database->tableLen,
+                                     gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH));
+
+        /* Copy data from old table. */
+        gckOS_MemCopy(table,
+                      database->table,
+                      database->tableLen * gcmSIZEOF(gctPOINTER));
+
+        gcmkOS_SAFE_FREE(os, database->table);
+
+        /* Update databse with new allocated table. */
+        database->table = table;
+        database->currentID = database->tableLen;
+        database->tableLen += gcdID_TABLE_LENGTH;
+        database->unused += gcdID_TABLE_LENGTH;
     }
 
-    gcmkVERIFY_OK(
-        gckMMU_FreePages(kernel->mmu, buffer->pageTable, buffer->pageCount));
+    table = database->table;
+    currentID = database->currentID;
+    tableLen = database->tableLen;
+    unused = database->unused;
 
-    gcmkVERIFY_OK(gckOS_FreePagedMemory(os, buffer->physical, Bytes));
+    /* Connect id with pointer. */
+    table[currentID] = Pointer;
 
-    gcmkVERIFY_OK(gckOS_AcquireMutex(os, kernel->virtualBufferLock, gcvINFINITE));
+    *Id = currentID + 1;
 
-    if (buffer == kernel->virtualBufferHead)
+    /* Update the currentID. */
+    if (--unused > 0)
     {
-        if ((kernel->virtualBufferHead = buffer->next) == gcvNULL)
+        for (i = 0; i < tableLen; i++)
         {
-            kernel->virtualBufferTail = gcvNULL;
-        }
-    }
-    else
-    {
-        buffer->prev->next = buffer->next;
+            if (++currentID >= tableLen)
+            {
+                /* Wrap to the begin. */
+                currentID = 0;
+            }
 
-        if (buffer == kernel->virtualBufferTail)
-        {
-            kernel->virtualBufferTail = buffer->prev;
-        }
-        else
-        {
-            buffer->next->prev = buffer->prev;
+            if (table[currentID] == gcvNULL)
+            {
+                break;
+            }
         }
     }
 
-    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, kernel->virtualBufferLock));
+    database->table = table;
+    database->currentID = currentID;
+    database->tableLen = tableLen;
+    database->unused = unused;
 
-    gcmkVERIFY_OK(gckOS_Free(os, buffer));
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+    acquired = gcvFALSE;
 
-    gcmkFOOTER_NO();
+    gcmkFOOTER_ARG("*Id=%d", *Id);
     return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+    }
+
+    gcmkFOOTER();
+    return status;
 }
 
 gceSTATUS
-gckKERNEL_GetGPUAddress(
-    IN gckKERNEL Kernel,
-    IN gctPOINTER Logical,
-    OUT gctUINT32 * Address
+gckKERNEL_FreeIntegerId(
+    IN gctPOINTER Database,
+    IN gctUINT32 Id
     )
 {
     gceSTATUS status;
-    gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
-    gctPOINTER start;
-    gctINT pid;
+    gckINTEGERDB database = Database;
+    gckOS os = database->os;
+    gctBOOL acquired = gcvFALSE;
 
-    gcmkHEADER_ARG("Logical = %x", Logical);
+    gcmkHEADER_ARG("Database=0x%08X Id=%d", Database, Id);
 
-    gckOS_GetProcessID(&pid);
+    gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
+    acquired = gcvTRUE;
 
-    status = gcvSTATUS_INVALID_ADDRESS;
+    if (!(Id > 0 && Id <= database->tableLen))
+    {
+        gcmkONERROR(gcvSTATUS_NOT_FOUND);
+    }
 
-    gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, Kernel->virtualBufferLock, gcvINFINITE));
+    Id -= 1;
 
-    /* Walk all command buffer. */
-    for (buffer = Kernel->virtualBufferHead; buffer != gcvNULL; buffer = buffer->next)
+    database->table[Id] = gcvNULL;
+
+    if (database->unused++ == 0)
     {
-        if (buffer->userLogical)
-        {
-            start = buffer->userLogical;
-        }
-        else
-        {
-            start = buffer->kernelLogical;
-        }
+        database->currentID = Id;
+    }
 
-        if (Logical >= start
-        && (Logical < (start + buffer->pageCount * 4096))
-        && pid == buffer->pid
-        )
-        {
-            * Address = buffer->gpuAddress + (Logical - start);
-            status = gcvSTATUS_OK;
-            break;
-        }
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+    acquired = gcvFALSE;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
     }
 
-    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->virtualBufferLock));
-
-    gcmkFOOTER_NO();
+    gcmkFOOTER();
     return status;
 }
 
 gceSTATUS
-gckKERNEL_QueryGPUAddress(
-    IN gckKERNEL Kernel,
-    IN gctUINT32 GpuAddress,
-    OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
+gckKERNEL_QueryIntegerId(
+    IN gctPOINTER Database,
+    IN gctUINT32 Id,
+    OUT gctPOINTER * Pointer
     )
 {
-    gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
-    gctUINT32 start;
-    gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
+    gceSTATUS status;
+    gckINTEGERDB database = Database;
+    gctPOINTER pointer;
+    gckOS os = database->os;
+    gctBOOL acquired = gcvFALSE;
 
-    gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, Kernel->virtualBufferLock, gcvINFINITE));
+    gcmkHEADER_ARG("Database=0x%08X Id=%d", Database, Id);
+    gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
 
-    /* Walk all command buffers. */
-    for (buffer = Kernel->virtualBufferHead; buffer != gcvNULL; buffer = buffer->next)
+    gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    if (!(Id > 0 && Id <= database->tableLen))
     {
-        start = (gctUINT32)buffer->gpuAddress;
+        gcmkONERROR(gcvSTATUS_NOT_FOUND);
+    }
 
-        if (GpuAddress >= start && GpuAddress < (start + buffer->pageCount * 4096))
-        {
-            /* Find a range matched. */
-            *Buffer = buffer;
-            status = gcvSTATUS_OK;
-            break;
-        }
+    Id -= 1;
+
+    pointer = database->table[Id];
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+    acquired = gcvFALSE;
+
+    if (pointer)
+    {
+        *Pointer = pointer;
+    }
+    else
+    {
+        gcmkONERROR(gcvSTATUS_NOT_FOUND);
     }
 
-    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->virtualBufferLock));
+    gcmkFOOTER_ARG("*Pointer=0x%08X", *Pointer);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+    }
 
+    gcmkFOOTER();
     return status;
 }
-#endif
 
-#if gcdLINK_QUEUE_SIZE
-static void
-gckLINKQUEUE_Dequeue(
-    IN gckLINKQUEUE LinkQueue
+
+gctUINT32
+gckKERNEL_AllocateNameFromPointer(
+    IN gckKERNEL Kernel,
+    IN gctPOINTER Pointer
     )
 {
-    gcmkASSERT(LinkQueue->count == gcdLINK_QUEUE_SIZE);
+    gceSTATUS status;
+    gctUINT32 name;
+    gctPOINTER database = Kernel->db->pointerDatabase;
 
-    LinkQueue->count--;
-    LinkQueue->front = (LinkQueue->front + 1) % gcdLINK_QUEUE_SIZE;
+    gcmkHEADER_ARG("Kernel=0x%X Pointer=0x%X", Kernel, Pointer);
+
+    gcmkONERROR(
+        gckKERNEL_AllocateIntegerId(database, Pointer, &name));
+
+    gcmkFOOTER_ARG("name=%d", name);
+    return name;
+
+OnError:
+    gcmkFOOTER();
+    return 0;
 }
 
-void
-gckLINKQUEUE_Enqueue(
-    IN gckLINKQUEUE LinkQueue,
-    IN gctUINT32 start,
-    IN gctUINT32 end
+gctPOINTER
+gckKERNEL_QueryPointerFromName(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Name
     )
 {
-    if (LinkQueue->count == gcdLINK_QUEUE_SIZE)
-    {
-        gckLINKQUEUE_Dequeue(LinkQueue);
-    }
-
-    gcmkASSERT(LinkQueue->count < gcdLINK_QUEUE_SIZE);
+    gceSTATUS status;
+    gctPOINTER pointer = gcvNULL;
+    gctPOINTER database = Kernel->db->pointerDatabase;
 
-    LinkQueue->count++;
+    gcmkHEADER_ARG("Kernel=0x%X Name=%d", Kernel, Name);
 
-    LinkQueue->data[LinkQueue->rear].start = start;
-    LinkQueue->data[LinkQueue->rear].end = end;
+    /* Lookup in database to get pointer. */
+    gcmkONERROR(gckKERNEL_QueryIntegerId(database, Name, &pointer));
 
-    gcmkVERIFY_OK(
-        gckOS_GetProcessID(&LinkQueue->data[LinkQueue->rear].pid));
+    gcmkFOOTER_ARG("pointer=0x%X", pointer);
+    return pointer;
 
-    LinkQueue->rear = (LinkQueue->rear + 1) % gcdLINK_QUEUE_SIZE;
+OnError:
+    gcmkFOOTER();
+    return gcvNULL;
 }
 
-void
-gckLINKQUEUE_GetData(
-    IN gckLINKQUEUE LinkQueue,
-    IN gctUINT32 Index,
-    OUT gckLINKDATA * Data
+gceSTATUS
+gckKERNEL_DeleteName(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Name
     )
 {
-    gcmkASSERT(Index >= 0 && Index < gcdLINK_QUEUE_SIZE);
+    gctPOINTER database = Kernel->db->pointerDatabase;
 
-    *Data = &LinkQueue->data[(Index + LinkQueue->front) % gcdLINK_QUEUE_SIZE];
+    gcmkHEADER_ARG("Kernel=0x%X Name=0x%X", Kernel, Name);
+
+    /* Free name if exists. */
+    gcmkVERIFY_OK(gckKERNEL_FreeIntegerId(database, Name));
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
 }
-#endif
 
-/******************************************************************************\
-*************************** Pointer - ID translation ***************************
-\******************************************************************************/
-#define gcdID_TABLE_LENGTH 1024
-typedef struct _gcsINTEGERDB * gckINTEGERDB;
-typedef struct _gcsINTEGERDB
+gceSTATUS
+gckKERNEL_SetRecovery(
+    IN gckKERNEL Kernel,
+    IN gctBOOL  Recovery,
+    IN gctUINT32 StuckDump
+    )
 {
-    gckOS                       os;
-    gctPOINTER*                 table;
-    gctPOINTER                  mutex;
-    gctUINT32                   tableLen;
-    gctUINT32                   currentID;
-    gctUINT32                   unused;
+    Kernel->recovery = Recovery;
+
+    if (Recovery == gcvFALSE)
+    {
+        /* Dump stuck information if Recovery is disabled. */
+        Kernel->stuckDump = gcmMAX(StuckDump, gcdSTUCK_DUMP_MIDDLE);
+    }
+
+    return gcvSTATUS_OK;
 }
-gcsINTEGERDB;
 
+
+/*******************************************************************************
+***** Shared Buffer ************************************************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+**  gckKERNEL_CreateShBuffer
+**
+**  Create shared buffer.
+**  The shared buffer can be used across processes. Other process needs call
+**  gckKERNEL_MapShBuffer before use it.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctUINT32 Size
+**          Specify the shared buffer size.
+**
+**  OUTPUT:
+**
+**      gctSHBUF * ShBuf
+**          Pointer to hold return shared buffer handle.
+*/
 gceSTATUS
-gckKERNEL_CreateIntegerDatabase(
+gckKERNEL_CreateShBuffer(
     IN gckKERNEL Kernel,
-    OUT gctPOINTER * Database
+    IN gctUINT32 Size,
+    OUT gctSHBUF * ShBuf
     )
 {
     gceSTATUS status;
-    gckINTEGERDB database = gcvNULL;
+    gcsSHBUF_PTR shBuf = gcvNULL;
 
-    gcmkHEADER_ARG("Kernel=0x%08X Datbase=0x%08X", Kernel, Database);
+    gcmkHEADER_ARG("Kernel=0x%X, Size=%u", Kernel, Size);
 
+    /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
-    gcmkVERIFY_ARGUMENT(Database != gcvNULL);
 
-    /* Allocate a database. */
-    gcmkONERROR(gckOS_Allocate(
-        Kernel->os, gcmSIZEOF(gcsINTEGERDB), (gctPOINTER *)&database));
+    if (Size == 0)
+    {
+        /* Invalid size. */
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
+    else if (Size > 1024)
+    {
+        /* Limite shared buffer size. */
+        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+    }
 
-    gckOS_ZeroMemory(database, gcmSIZEOF(gcsINTEGERDB));
+    /* Create a shared buffer structure. */
+    gcmkONERROR(
+        gckOS_Allocate(Kernel->os,
+                       sizeof (gcsSHBUF),
+                       (gctPOINTER *)&shBuf));
 
-    /* Allocate a pointer table. */
-    gcmkONERROR(gckOS_Allocate(
-        Kernel->os, gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH, (gctPOINTER *)&database->table));
+    /* Initialize shared buffer. */
+    shBuf->id        = 0;
+    shBuf->reference = gcvNULL;
+    shBuf->size      = Size;
+    shBuf->data      = gcvNULL;
 
-    gckOS_ZeroMemory(database->table, gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH);
+    /* Allocate integer id for this shared buffer. */
+    gcmkONERROR(
+        gckKERNEL_AllocateIntegerId(Kernel->db->pointerDatabase,
+                                    shBuf,
+                                    &shBuf->id));
 
-    /* Allocate a database mutex. */
-    gcmkONERROR(gckOS_CreateMutex(Kernel->os, &database->mutex));
+    /* Allocate atom. */
+    gcmkONERROR(gckOS_AtomConstruct(Kernel->os, &shBuf->reference));
 
-    /* Initialize. */
-    database->currentID = 0;
-    database->unused = gcdID_TABLE_LENGTH;
-    database->os = Kernel->os;
-    database->tableLen = gcdID_TABLE_LENGTH;
+    /* Set default reference count to 1. */
+    gcmkVERIFY_OK(gckOS_AtomSet(Kernel->os, shBuf->reference, 1));
 
-    *Database = database;
+    /* Return integer id. */
+    *ShBuf = (gctSHBUF)(gctUINTPTR_T)shBuf->id;
 
-    gcmkFOOTER_ARG("*Database=0x%08X", *Database);
+    gcmkFOOTER_ARG("*ShBuf=%u", shBuf->id);
     return gcvSTATUS_OK;
 
 OnError:
-    /* Rollback. */
-    if (database)
+    /* Error roll back. */
+    if (shBuf != gcvNULL)
     {
-        if (database->table)
+        if (shBuf->id != 0)
         {
-            gcmkOS_SAFE_FREE(Kernel->os, database->table);
+            gcmkVERIFY_OK(
+                gckKERNEL_FreeIntegerId(Kernel->db->pointerDatabase,
+                                        shBuf->id));
         }
 
-        gcmkOS_SAFE_FREE(Kernel->os, database);
+        gcmkOS_SAFE_FREE(Kernel->os, shBuf);
     }
 
     gcmkFOOTER();
     return status;
 }
 
+/*******************************************************************************
+**
+**  gckKERNEL_DestroyShBuffer
+**
+**  Destroy shared buffer.
+**  This will decrease reference of specified shared buffer and do actual
+**  destroy when no reference on it.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctSHBUF ShBuf
+**          Specify the shared buffer to be destroyed.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
 gceSTATUS
-gckKERNEL_DestroyIntegerDatabase(
-    IN gckKERNEL Kernel,
-    IN gctPOINTER Database
-    )
-{
-    gckINTEGERDB database = Database;
-
-    gcmkHEADER_ARG("Kernel=0x%08X Datbase=0x%08X", Kernel, Database);
-
-    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
-    gcmkVERIFY_ARGUMENT(Database != gcvNULL);
-
-    /* Destroy pointer table. */
-    gcmkOS_SAFE_FREE(Kernel->os, database->table);
-
-    /* Destroy database mutex. */
-    gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, database->mutex));
-
-    /* Destroy database. */
-    gcmkOS_SAFE_FREE(Kernel->os, database);
-
-    gcmkFOOTER_NO();
-    return gcvSTATUS_OK;
-}
-
-gceSTATUS
-gckKERNEL_AllocateIntegerId(
-    IN gctPOINTER Database,
-    IN gctPOINTER Pointer,
-    OUT gctUINT32 * Id
+gckKERNEL_DestroyShBuffer(
+    IN gckKERNEL Kernel,
+    IN gctSHBUF ShBuf
     )
 {
     gceSTATUS status;
-    gckINTEGERDB database = Database;
-    gctUINT32 i, unused, currentID, tableLen;
-    gctPOINTER * table;
-    gckOS os = database->os;
+    gcsSHBUF_PTR shBuf;
+    gctINT32 oldValue = 0;
     gctBOOL acquired = gcvFALSE;
 
-    gcmkHEADER_ARG("Database=0x%08X Pointer=0x%08X", Database, Pointer);
+    gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u",
+                   Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf);
 
-    gcmkVERIFY_ARGUMENT(Id != gcvNULL);
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
 
-    gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
+    /* Acquire mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Kernel->os,
+                           Kernel->db->pointerDatabaseMutex,
+                           gcvINFINITE));
     acquired = gcvTRUE;
 
-    if (database->unused < 1)
-    {
-        /* Extend table. */
-        gcmkONERROR(
-            gckOS_Allocate(os,
-                           gcmSIZEOF(gctPOINTER) * (database->tableLen + gcdID_TABLE_LENGTH),
-                           (gctPOINTER *)&table));
-
-        gckOS_ZeroMemory(table + database->tableLen,
-                         gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH);
-
-        /* Copy data from old table. */
-        gckOS_MemCopy(table,
-                      database->table,
-                      database->tableLen * gcmSIZEOF(gctPOINTER));
-
-        gcmkOS_SAFE_FREE(os, database->table);
+    /* Find shared buffer structure. */
+    gcmkONERROR(
+        gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
+                                 (gctUINT32)(gctUINTPTR_T)ShBuf,
+                                 (gctPOINTER)&shBuf));
 
-        /* Update databse with new allocated table. */
-        database->table = table;
-        database->currentID = database->tableLen;
-        database->tableLen += gcdID_TABLE_LENGTH;
-        database->unused += gcdID_TABLE_LENGTH;
-    }
+    gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
 
-    table = database->table;
-    currentID = database->currentID;
-    tableLen = database->tableLen;
-    unused = database->unused;
+    /* Decrease the reference count. */
+    gckOS_AtomDecrement(Kernel->os, shBuf->reference, &oldValue);
 
-    /* Connect id with pointer. */
-    table[currentID] = Pointer;
+    if (oldValue == 1)
+    {
+        /* Free integer id. */
+        gcmkVERIFY_OK(
+            gckKERNEL_FreeIntegerId(Kernel->db->pointerDatabase,
+                                    shBuf->id));
 
-    *Id = currentID + 1;
+        /* Free atom. */
+        gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, shBuf->reference));
 
-    /* Update the currentID. */
-    if (--unused > 0)
-    {
-        for (i = 0; i < tableLen; i++)
+        if (shBuf->data)
         {
-            if (++currentID >= tableLen)
-            {
-                /* Wrap to the begin. */
-                currentID = 0;
-            }
-
-            if (table[currentID] == gcvNULL)
-            {
-                break;
-            }
+            gcmkOS_SAFE_FREE(Kernel->os, shBuf->data);
+            shBuf->data = gcvNULL;
         }
-    }
 
-    database->table = table;
-    database->currentID = currentID;
-    database->tableLen = tableLen;
-    database->unused = unused;
+        /* Free the shared buffer. */
+        gcmkOS_SAFE_FREE(Kernel->os, shBuf);
+    }
 
-    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+    /* Release the mutex. */
+    gcmkVERIFY_OK(
+        gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
     acquired = gcvFALSE;
 
-    gcmkFOOTER_ARG("*Id=%d", *Id);
+    gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 
 OnError:
     if (acquired)
     {
-        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+        /* Release the mutex. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
     }
 
     gcmkFOOTER();
     return status;
 }
 
+/*******************************************************************************
+**
+**  gckKERNEL_MapShBuffer
+**
+**  Map shared buffer into this process so that it can be used in this process.
+**  This will increase reference count on the specified shared buffer.
+**  Call gckKERNEL_DestroyShBuffer to dereference.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctSHBUF ShBuf
+**          Specify the shared buffer to be mapped.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
 gceSTATUS
-gckKERNEL_FreeIntegerId(
-    IN gctPOINTER Database,
-    IN gctUINT32 Id
+gckKERNEL_MapShBuffer(
+    IN gckKERNEL Kernel,
+    IN gctSHBUF ShBuf
     )
 {
     gceSTATUS status;
-    gckINTEGERDB database = Database;
-    gckOS os = database->os;
+    gcsSHBUF_PTR shBuf;
+    gctINT32 oldValue = 0;
     gctBOOL acquired = gcvFALSE;
 
-    gcmkHEADER_ARG("Database=0x%08X Id=%d", Database, Id);
+    gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u",
+                   Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf);
 
-    gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
-    acquired = gcvTRUE;
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
 
-    if (!(Id > 0 && Id <= database->tableLen))
-    {
-        gcmkONERROR(gcvSTATUS_NOT_FOUND);
-    }
+    /* Acquire mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Kernel->os,
+                           Kernel->db->pointerDatabaseMutex,
+                           gcvINFINITE));
+    acquired = gcvTRUE;
 
-    Id -= 1;
+    /* Find shared buffer structure. */
+    gcmkONERROR(
+        gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
+                                 (gctUINT32)(gctUINTPTR_T)ShBuf,
+                                 (gctPOINTER)&shBuf));
 
-    database->table[Id] = gcvNULL;
+    gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
 
-    if (database->unused++ == 0)
-    {
-        database->currentID = Id;
-    }
+    /* Increase the reference count. */
+    gckOS_AtomIncrement(Kernel->os, shBuf->reference, &oldValue);
 
-    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+    /* Release the mutex. */
+    gcmkVERIFY_OK(
+        gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
     acquired = gcvFALSE;
 
     gcmkFOOTER_NO();
@@ -3836,129 +4812,226 @@ gckKERNEL_FreeIntegerId(
 OnError:
     if (acquired)
     {
-        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+        /* Release the mutex. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
     }
 
     gcmkFOOTER();
     return status;
 }
 
+/*******************************************************************************
+**
+**  gckKERNEL_WriteShBuffer
+**
+**  Write user data into shared buffer.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctSHBUF ShBuf
+**          Specify the shared buffer to be written to.
+**
+**      gctPOINTER UserData
+**          User mode pointer to hold the source data.
+**
+**      gctUINT32 ByteCount
+**          Specify number of bytes to write. If this is larger than
+**          shared buffer size, gcvSTATUS_INVALID_ARGUMENT is returned.
+**
+**  OUTPUT:
+**
+**      Nothing.
+*/
 gceSTATUS
-gckKERNEL_QueryIntegerId(
-    IN gctPOINTER Database,
-    IN gctUINT32 Id,
-    OUT gctPOINTER * Pointer
+gckKERNEL_WriteShBuffer(
+    IN gckKERNEL Kernel,
+    IN gctSHBUF ShBuf,
+    IN gctPOINTER UserData,
+    IN gctUINT32 ByteCount
     )
 {
     gceSTATUS status;
-    gckINTEGERDB database = Database;
-    gctPOINTER pointer;
-    gckOS os = database->os;
+    gcsSHBUF_PTR shBuf;
     gctBOOL acquired = gcvFALSE;
 
-    gcmkHEADER_ARG("Database=0x%08X Id=%d", Database, Id);
-    gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
-
-    gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
-    acquired = gcvTRUE;
+    gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u UserData=0x%X ByteCount=%u",
+                   Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf, UserData, ByteCount);
 
-    if (!(Id > 0 && Id <= database->tableLen))
-    {
-        gcmkONERROR(gcvSTATUS_NOT_FOUND);
-    }
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
 
-    Id -= 1;
+    /* Acquire mutex. */
+    gcmkONERROR(
+        gckOS_AcquireMutex(Kernel->os,
+                           Kernel->db->pointerDatabaseMutex,
+                           gcvINFINITE));
+    acquired = gcvTRUE;
 
-    pointer = database->table[Id];
+    /* Find shared buffer structure. */
+    gcmkONERROR(
+        gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
+                                 (gctUINT32)(gctUINTPTR_T)ShBuf,
+                                 (gctPOINTER)&shBuf));
 
-    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
-    acquired = gcvFALSE;
+    gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
 
-    if (pointer)
+    if ((ByteCount > shBuf->size) ||
+        (ByteCount == 0) ||
+        (UserData  == gcvNULL))
     {
-        *Pointer = pointer;
+        /* Exceeds buffer max size or invalid. */
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
     }
-    else
+
+    if (shBuf->data == gcvNULL)
     {
-        gcmkONERROR(gcvSTATUS_NOT_FOUND);
+        /* Allocate buffer data when first time write. */
+        gcmkONERROR(gckOS_Allocate(Kernel->os, ByteCount, &shBuf->data));
     }
 
-    gcmkFOOTER_ARG("*Pointer=0x%08X", *Pointer);
+    /* Copy data from user. */
+    gcmkONERROR(
+        gckOS_CopyFromUserData(Kernel->os,
+                               shBuf->data,
+                               UserData,
+                               ByteCount));
+
+    /* Release the mutex. */
+    gcmkVERIFY_OK(
+        gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+    acquired = gcvFALSE;
+
+    gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 
 OnError:
     if (acquired)
     {
-        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+        /* Release the mutex. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
     }
 
     gcmkFOOTER();
     return status;
 }
 
-
-gctUINT32
-gckKERNEL_AllocateNameFromPointer(
+/*******************************************************************************
+**
+**  gckKERNEL_ReadShBuffer
+**
+**  Read data from shared buffer and copy to user pointer.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctSHBUF ShBuf
+**          Specify the shared buffer to be read from.
+**
+**      gctPOINTER UserData
+**          User mode pointer to save output data.
+**
+**      gctUINT32 ByteCount
+**          Specify number of bytes to read.
+**          If this is larger than shared buffer size, only avaiable bytes are
+**          copied. If smaller, copy requested size.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * BytesRead
+**          Pointer to hold how many bytes actually read from shared buffer.
+*/
+gceSTATUS
+gckKERNEL_ReadShBuffer(
     IN gckKERNEL Kernel,
-    IN gctPOINTER Pointer
+    IN gctSHBUF ShBuf,
+    IN gctPOINTER UserData,
+    IN gctUINT32 ByteCount,
+    OUT gctUINT32 * BytesRead
     )
 {
     gceSTATUS status;
-    gctUINT32 name;
-    gctPOINTER database = Kernel->db->pointerDatabase;
+    gcsSHBUF_PTR shBuf;
+    gctUINT32 bytes;
+    gctBOOL acquired = gcvFALSE;
 
-    gcmkHEADER_ARG("Kernel=0x%X Pointer=0x%X", Kernel, Pointer);
+    gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u UserData=0x%X ByteCount=%u",
+                   Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf, UserData, ByteCount);
 
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
+
+    /* Acquire mutex. */
     gcmkONERROR(
-        gckKERNEL_AllocateIntegerId(database, Pointer, &name));
+        gckOS_AcquireMutex(Kernel->os,
+                           Kernel->db->pointerDatabaseMutex,
+                           gcvINFINITE));
+    acquired = gcvTRUE;
 
-    gcmkFOOTER_ARG("name=%d", name);
-    return name;
+    /* Find shared buffer structure. */
+    gcmkONERROR(
+        gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
+                                 (gctUINT32)(gctUINTPTR_T)ShBuf,
+                                 (gctPOINTER)&shBuf));
 
-OnError:
-    gcmkFOOTER();
-    return 0;
-}
+    gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
 
-gctPOINTER
-gckKERNEL_QueryPointerFromName(
-    IN gckKERNEL Kernel,
-    IN gctUINT32 Name
-    )
-{
-    gceSTATUS status;
-    gctPOINTER pointer = gcvNULL;
-    gctPOINTER database = Kernel->db->pointerDatabase;
+    if (shBuf->data == gcvNULL)
+    {
+        *BytesRead = 0;
 
-    gcmkHEADER_ARG("Kernel=0x%X Name=%d", Kernel, Name);
+        /* No data in shared buffer, skip copy. */
+        status = gcvSTATUS_SKIP;
+        goto OnError;
+    }
+    else if (ByteCount == 0)
+    {
+        /* Invalid size to read. */
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
 
-    /* Lookup in database to get pointer. */
-    gcmkONERROR(gckKERNEL_QueryIntegerId(database, Name, &pointer));
+    /* Determine bytes to copy. */
+    bytes = (ByteCount < shBuf->size) ? ByteCount : shBuf->size;
 
-    gcmkFOOTER_ARG("pointer=0x%X", pointer);
-    return pointer;
+    /* Copy data to user. */
+    gcmkONERROR(
+        gckOS_CopyToUserData(Kernel->os,
+                             shBuf->data,
+                             UserData,
+                             bytes));
 
-OnError:
-    gcmkFOOTER();
-    return gcvNULL;
-}
+    /* Return copied size. */
+    *BytesRead = bytes;
 
-gceSTATUS
-gckKERNEL_DeleteName(
-    IN gckKERNEL Kernel,
-    IN gctUINT32 Name
-    )
-{
-    gctPOINTER database = Kernel->db->pointerDatabase;
+    /* Release the mutex. */
+    gcmkVERIFY_OK(
+        gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+    acquired = gcvFALSE;
 
-    gcmkHEADER_ARG("Kernel=0x%X Name=0x%X", Kernel, Name);
+    gcmkFOOTER_ARG("*BytesRead=%u", bytes);
+    return gcvSTATUS_OK;
 
-    /* Free name if exists. */
-    gcmkVERIFY_OK(gckKERNEL_FreeIntegerId(database, Name));
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(
+            gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+    }
 
-    gcmkFOOTER_NO();
-    return gcvSTATUS_OK;
+    gcmkFOOTER();
+    return status;
 }
+
+
 /*******************************************************************************
 ***** Test Code ****************************************************************
 *******************************************************************************/
index d7ff9cf16372a59913db9c575ab161ca0d9b0aae..93764878a42d1b6cf8e381ae6b8b120e93049295 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 #include "gc_hal_kernel_vg.h"
 #endif
 
+#if gcdSECURITY
+#include "gc_hal_security_interface.h"
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -68,6 +72,21 @@ extern "C" {
 #define gcdMMU_OFFSET_16K_BITS      (32 - gcdMMU_MTLB_BITS - gcdMMU_STLB_16K_BITS)
 #define gcdMMU_OFFSET_16K_MASK      ((1U << gcdMMU_OFFSET_16K_BITS) - 1)
 
+#define gcdMMU_MTLB_PRESENT         0x00000001
+#define gcdMMU_MTLB_EXCEPTION       0x00000002
+#define gcdMMU_MTLB_4K_PAGE         0x00000000
+
+#define gcdMMU_STLB_PRESENT         0x00000001
+#define gcdMMU_STLB_EXCEPTION       0x00000002
+#define gcdMMU_STLB_4K_PAGE         0x00000000
+
+/*******************************************************************************
+***** Stuck Dump Level ********************************************************/
+
+#define gcdSTUCK_DUMP_MINIMAL       1
+#define gcdSTUCK_DUMP_MIDDLE        2
+#define gcdSTUCK_DUMP_MAXIMAL       3
+
 /*******************************************************************************
 ***** Process Secure Cache ****************************************************/
 
@@ -76,6 +95,9 @@ extern "C" {
 #define gcdSECURE_CACHE_HASH        3
 #define gcdSECURE_CACHE_TABLE       4
 
+#define gcvPAGE_TABLE_DIRTY_BIT_OTHER   (1 << 0)
+#define gcvPAGE_TABLE_DIRTY_BIT_FE      (1 << 1)
+
 typedef struct _gcskLOGICAL_CACHE * gcskLOGICAL_CACHE_PTR;
 typedef struct _gcskLOGICAL_CACHE   gcskLOGICAL_CACHE;
 struct _gcskLOGICAL_CACHE
@@ -140,15 +162,19 @@ typedef enum _gceDATABASE_TYPE
     gcvDB_CONTEXT,                      /* Context */
     gcvDB_IDLE,                         /* GPU idle. */
     gcvDB_MAP_MEMORY,                   /* Map memory */
-    gcvDB_SHARED_INFO,                  /* Private data */
     gcvDB_MAP_USER_MEMORY,              /* Map user memory */
     gcvDB_SYNC_POINT,                   /* Sync point. */
-    gcvDB_VIDEO_MEMORY_RESERVED,        /* Reserved video memory */
-    gcvDB_VIDEO_MEMORY_CONTIGUOUS,      /* Contiguous video memory */
-    gcvDB_VIDEO_MEMORY_VIRTUAL,         /* Virtual video memory */
+    gcvDB_SHBUF,                        /* Shared buffer. */
 }
 gceDATABASE_TYPE;
 
+#define gcdDATABASE_TYPE_MASK           0x000000FF
+#define gcdDB_VIDEO_MEMORY_TYPE_MASK    0x0000FF00
+#define gcdDB_VIDEO_MEMORY_TYPE_SHIFT   8
+
+#define gcdDB_VIDEO_MEMORY_POOL_MASK    0x00FF0000
+#define gcdDB_VIDEO_MEMORY_POOL_SHIFT   16
+
 typedef struct _gcsDATABASE_RECORD *    gcsDATABASE_RECORD_PTR;
 typedef struct _gcsDATABASE_RECORD
 {
@@ -184,9 +210,12 @@ typedef struct _gcsDATABASE
     gcsDATABASE_COUNTERS                contiguous;
     gcsDATABASE_COUNTERS                mapUserMemory;
     gcsDATABASE_COUNTERS                mapMemory;
-    gcsDATABASE_COUNTERS                vidMemResv;
-    gcsDATABASE_COUNTERS                vidMemCont;
-    gcsDATABASE_COUNTERS                vidMemVirt;
+    gcsDATABASE_COUNTERS                virtualCommandBuffer;
+
+    gcsDATABASE_COUNTERS                vidMemType[gcvSURF_NUM_TYPES];
+    /* Counter for each video memory pool. */
+    gcsDATABASE_COUNTERS                vidMemPool[gcvPOOL_NUMBER_OF_POOLS];
+    gctPOINTER                          counterMutex;
 
     /* Idle time management. */
     gctUINT64                           lastIdle;
@@ -202,9 +231,22 @@ typedef struct _gcsDATABASE
 
     gctPOINTER                          handleDatabase;
     gctPOINTER                          handleDatabaseMutex;
+
+#if gcdPROCESS_ADDRESS_SPACE
+    gckMMU                              mmu;
+#endif
 }
 gcsDATABASE;
 
+typedef struct _gcsRECORDER * gckRECORDER;
+
+typedef struct _gcsFDPRIVATE *          gcsFDPRIVATE_PTR;
+typedef struct _gcsFDPRIVATE
+{
+    gctINT                              (* release) (gcsFDPRIVATE_PTR Private);
+}
+gcsFDPRIVATE;
+
 /* Create a process database that will contain all its allocations. */
 gceSTATUS
 gckKERNEL_CreateProcessDB(
@@ -266,7 +308,62 @@ gckKERNEL_DumpProcessDB(
     IN gckKERNEL Kernel
     );
 
-/* ID database */
+/* Dump the video memory usage for process specified. */
+gceSTATUS
+gckKERNEL_DumpVidMemUsage(
+    IN gckKERNEL Kernel,
+    IN gctINT32 ProcessID
+    );
+
+gceSTATUS
+gckKERNEL_FindDatabase(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gctBOOL LastProcessID,
+    OUT gcsDATABASE_PTR * Database
+    );
+
+gceSTATUS
+gckKERNEL_FindHandleDatbase(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    OUT gctPOINTER * HandleDatabase,
+    OUT gctPOINTER * HandleDatabaseMutex
+    );
+
+gceSTATUS
+gckKERNEL_GetProcessMMU(
+    IN gckKERNEL Kernel,
+    OUT gckMMU * Mmu
+    );
+
+gceSTATUS
+gckKERNEL_SetRecovery(
+    IN gckKERNEL Kernel,
+    IN gctBOOL   Recovery,
+    IN gctUINT32 StuckDump
+    );
+
+gceSTATUS
+gckMMU_FlatMapping(
+    IN gckMMU Mmu,
+    IN gctUINT32 Physical
+    );
+
+gceSTATUS
+gckMMU_GetPageEntry(
+    IN gckMMU Mmu,
+    IN gctUINT32 Address,
+    IN gctUINT32_PTR *PageTable
+    );
+
+gceSTATUS
+gckMMU_FreePagesEx(
+    IN gckMMU Mmu,
+    IN gctUINT32 Address,
+    IN gctSIZE_T PageCount
+    );
+
 gceSTATUS
 gckKERNEL_CreateIntegerDatabase(
     IN gckKERNEL Kernel,
@@ -299,6 +396,7 @@ gckKERNEL_QueryIntegerId(
     OUT gctPOINTER * Pointer
     );
 
+/* Pointer rename  */
 gctUINT32
 gckKERNEL_AllocateNameFromPointer(
     IN gckKERNEL Kernel,
@@ -356,18 +454,20 @@ struct _gckDB
     gctUINT64                   idleTime;
     gctUINT64                   lastSlowdown;
     gctUINT64                   lastSlowdownIdle;
-    /* ID - Pointer database*/
+    gctPOINTER                  nameDatabase;
+    gctPOINTER                  nameDatabaseMutex;
+
     gctPOINTER                  pointerDatabase;
     gctPOINTER                  pointerDatabaseMutex;
 };
 
-#if gcdVIRTUAL_COMMAND_BUFFER
 typedef struct _gckVIRTUAL_COMMAND_BUFFER * gckVIRTUAL_COMMAND_BUFFER_PTR;
 typedef struct _gckVIRTUAL_COMMAND_BUFFER
 {
     gctPHYS_ADDR                physical;
     gctPOINTER                  userLogical;
     gctPOINTER                  kernelLogical;
+    gctSIZE_T                   bytes;
     gctSIZE_T                   pageCount;
     gctPOINTER                  pageTable;
     gctUINT32                   gpuAddress;
@@ -375,9 +475,11 @@ typedef struct _gckVIRTUAL_COMMAND_BUFFER
     gckVIRTUAL_COMMAND_BUFFER_PTR   next;
     gckVIRTUAL_COMMAND_BUFFER_PTR   prev;
     gckKERNEL                   kernel;
+#if gcdPROCESS_ADDRESS_SPACE
+    gckMMU                      mmu;
+#endif
 }
 gckVIRTUAL_COMMAND_BUFFER;
-#endif
 
 /* gckKERNEL object. */
 struct _gckKERNEL
@@ -412,10 +514,8 @@ struct _gckKERNEL
 #if VIVANTE_PROFILER
     /* Enable profiling */
     gctBOOL                     profileEnable;
-
     /* Clear profile register or not*/
     gctBOOL                     profileCleanRegister;
-
 #endif
 
 #ifdef QNX_SINGLE_THREADED_DEBUGGING
@@ -426,11 +526,7 @@ struct _gckKERNEL
     gckDB                       db;
     gctBOOL                     dbCreated;
 
-#if gcdENABLE_RECOVERY
-    gctPOINTER                  resetFlagClearTimer;
-    gctPOINTER                  resetAtom;
     gctUINT64                   resetTimeStamp;
-#endif
 
     /* Pointer to gckEVENT object. */
     gcsTIMER                    timers[8];
@@ -440,11 +536,13 @@ struct _gckKERNEL
     gckVGKERNEL                 vg;
 #endif
 
-#if gcdVIRTUAL_COMMAND_BUFFER
+    /* Virtual command buffer list. */
     gckVIRTUAL_COMMAND_BUFFER_PTR virtualBufferHead;
     gckVIRTUAL_COMMAND_BUFFER_PTR virtualBufferTail;
     gctPOINTER                    virtualBufferLock;
-#endif
+
+    /* Enable virtual command buffer. */
+    gctBOOL                     virtualCommandBuffer;
 
 #if gcdDVFS
     gckDVFS                     dvfs;
@@ -453,6 +551,29 @@ struct _gckKERNEL
 #if gcdANDROID_NATIVE_FENCE_SYNC
     gctHANDLE                   timeline;
 #endif
+
+    /* Enable recovery. */
+    gctBOOL                     recovery;
+
+    /* Level of dump information after stuck. */
+    gctUINT                     stuckDump;
+
+#if gcdSECURITY
+    gctUINT32                   securityChannel;
+#endif
+
+    /* Timer to monitor GPU stuck. */
+    gctPOINTER                  monitorTimer;
+
+    /* Flag to quit monitor timer. */
+    gctBOOL                     monitorTimerStop;
+
+    /* Monitor states. */
+    gctBOOL                     monitoring;
+    gctUINT32                   lastCommitStamp;
+    gctUINT32                   timer;
+    gctUINT32                   restoreAddress;
+    gctUINT32                   restoreMask;
 };
 
 struct _FrequencyHistory
@@ -486,7 +607,7 @@ struct _gckCOMMAND
     gckOS                       os;
 
     /* Number of bytes per page. */
-    gctSIZE_T                   pageSize;
+    gctUINT32                   pageSize;
 
     /* Current pipe select. */
     gcePIPE_SELECT              pipeSelect;
@@ -518,11 +639,13 @@ struct _gckCOMMAND
         gctSIGNAL               signal;
         gctPHYS_ADDR            physical;
         gctPOINTER              logical;
+        gctUINT32               address;
     }
     queues[gcdCOMMAND_QUEUES];
 
     gctPHYS_ADDR                physical;
     gctPOINTER                  logical;
+    gctUINT32                   address;
     gctUINT32                   offset;
     gctINT                      index;
 #if gcmIS_DEBUG(gcdDEBUG_TRACE)
@@ -538,12 +661,12 @@ struct _gckCOMMAND
     /* Pointer to last WAIT command. */
     gctPHYS_ADDR                waitPhysical;
     gctPOINTER                  waitLogical;
-    gctSIZE_T                   waitSize;
+    gctUINT32                   waitSize;
 
     /* Command buffer alignment. */
-    gctSIZE_T                   alignment;
-    gctSIZE_T                   reservedHead;
-    gctSIZE_T                   reservedTail;
+    gctUINT32                   alignment;
+    gctUINT32                   reservedHead;
+    gctUINT32                   reservedTail;
 
     /* Commit counter. */
     gctPOINTER                  atomCommit;
@@ -560,6 +683,11 @@ struct _gckCOMMAND
     gctUINT                     hintArraySize;
     gctUINT32_PTR               hintArray;
 #endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+    gckMMU                      currentMmu;
+#endif
+    struct _gckENTRYQUEUE       queue;
 };
 
 typedef struct _gcsEVENT *      gcsEVENT_PTR;
@@ -595,6 +723,11 @@ typedef struct _gcsEVENT_QUEUE
     /* Source of the event. */
     gceKERNEL_WHERE             source;
 
+#if gcdMULTI_GPU
+    /* Which chip(s) of the event */
+    gceCORE_3D_MASK             chipEnable;
+#endif
+
     /* Pointer to head of event queue. */
     gcsEVENT_PTR                head;
 
@@ -632,22 +765,35 @@ struct _gckEVENT
 
     /* Time stamp. */
     gctUINT64                   stamp;
-    gctUINT64                   lastCommitStamp;
+    gctUINT32                   lastCommitStamp;
 
     /* Queue mutex. */
     gctPOINTER                  eventQueueMutex;
 
     /* Array of event queues. */
-    gcsEVENT_QUEUE              queues[30];
+    gcsEVENT_QUEUE              queues[29];
     gctUINT8                    lastID;
     gctPOINTER                  freeAtom;
 
     /* Pending events. */
 #if gcdSMP
+#if gcdMULTI_GPU
+    gctPOINTER                  pending3D[gcdMULTI_GPU];
+    gctPOINTER                  pending3DMask[gcdMULTI_GPU];
+    gctPOINTER                  pendingMask;
+#endif
     gctPOINTER                  pending;
 #else
+#if gcdMULTI_GPU
+    volatile gctUINT            pending3D[gcdMULTI_GPU];
+    volatile gctUINT            pending3DMask[gcdMULTI_GPU];
+    volatile gctUINT            pendingMask;
+#endif
     volatile gctUINT            pending;
 #endif
+#if gcdMULTI_GPU
+    gctUINT32                   busy;
+#endif
 
     /* List of free event structures and its mutex. */
     gcsEVENT_PTR                freeEventList;
@@ -663,7 +809,13 @@ struct _gckEVENT
 
     gctPOINTER                  submitTimer;
 
-    volatile gctBOOL            inNotify;
+#if gcdINTERRUPT_STATISTIC
+    gctPOINTER                  interruptCount;
+#endif
+
+#if gcdRECORD_COMMAND
+    gckRECORDER                 recorder;
+#endif
 };
 
 /* Free all events belonging to a process. */
@@ -680,13 +832,29 @@ gckEVENT_Stop(
     IN gctPHYS_ADDR Handle,
     IN gctPOINTER Logical,
     IN gctSIGNAL Signal,
-       IN OUT gctSIZE_T * waitSize
+    IN OUT gctUINT32 * waitSize
     );
 
-gceSTATUS
-gckEVENT_WaitEmpty(
-    IN gckEVENT Event
-    );
+typedef struct _gcsLOCK_INFO * gcsLOCK_INFO_PTR;
+typedef struct _gcsLOCK_INFO
+{
+    gctUINT32                   GPUAddresses[gcdMAX_GPU_COUNT];
+    gctPOINTER                  pageTables[gcdMAX_GPU_COUNT];
+    gctUINT32                   lockeds[gcdMAX_GPU_COUNT];
+    gckKERNEL                   lockKernels[gcdMAX_GPU_COUNT];
+    gckMMU                      lockMmus[gcdMAX_GPU_COUNT];
+}
+gcsLOCK_INFO;
+
+typedef struct _gcsGPU_MAP * gcsGPU_MAP_PTR;
+typedef struct _gcsGPU_MAP
+{
+    gctINT                      pid;
+    gcsLOCK_INFO                lockInfo;
+    gcsGPU_MAP_PTR              prev;
+    gcsGPU_MAP_PTR              next;
+}
+gcsGPU_MAP;
 
 /* gcuVIDMEM_NODE structure. */
 typedef union _gcuVIDMEM_NODE
@@ -706,12 +874,12 @@ typedef union _gcuVIDMEM_NODE
         gcuVIDMEM_NODE_PTR      prevFree;
 
         /* Information for this node. */
-        gctUINT32               offset;
+        gctSIZE_T               offset;
         gctSIZE_T               bytes;
         gctUINT32               alignment;
 
 #ifdef __QNXNTO__
-        /* Client/server vaddr (mapped using mmap_join). */
+        /* Client virtual address. */
         gctPOINTER              logical;
 #endif
 
@@ -725,18 +893,9 @@ typedef union _gcuVIDMEM_NODE
         /* Process ID owning this memory. */
         gctUINT32               processID;
 
-        /* Prevent compositor from freeing until client unlocks. */
-        gctBOOL                 freePending;
-
-        /* */
-        gcsVIDMEM_NODE_SHARED_INFO sharedInfo;
-
-#if gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
+#if gcdENABLE_VG
         gctPOINTER              kernelVirtual;
 #endif
-
-        /* Surface type. */
-        gceSURF_TYPE            type;
     }
     VidMem;
 
@@ -755,6 +914,17 @@ typedef union _gcuVIDMEM_NODE
         /* do_mmap_pgoff address... mapped per-process. */
         gctPOINTER              logical;
 
+#if gcdENABLE_VG
+        /* Physical address of this node, only meaningful when it is contiguous. */
+        gctUINT32               physicalAddress;
+
+        /* Kernel logical of this node. */
+        gctPOINTER              kernelVirtual;
+#endif
+
+        /* Customer private handle */
+        gctUINT32               gid;
+
         /* Page table information. */
         /* Used only when node is not contiguous */
         gctSIZE_T               pageCount;
@@ -766,34 +936,12 @@ typedef union _gcuVIDMEM_NODE
         /* Actual physical address */
         gctUINT32               addresses[gcdMAX_GPU_COUNT];
 
-        /* Mutex. */
-        gctPOINTER              mutex;
-
         /* Locked counter. */
         gctINT32                lockeds[gcdMAX_GPU_COUNT];
 
-#ifdef __QNXNTO__
-        /* Single linked list of nodes. */
-        gcuVIDMEM_NODE_PTR      next;
-
-        /* Unlock pending flag. */
-        gctBOOL                 unlockPendings[gcdMAX_GPU_COUNT];
-
-        /* Free pending flag. */
-        gctBOOL                 freePending;
-#endif
-
         /* Process ID owning this memory. */
         gctUINT32               processID;
 
-        /* Owner process sets freed to true
-         * when it trys to free a locked
-         * node */
-        gctBOOL                 freed;
-
-        /* */
-        gcsVIDMEM_NODE_SHARED_INFO sharedInfo;
-
         /* Surface type. */
         gceSURF_TYPE            type;
     }
@@ -826,14 +974,158 @@ struct _gckVIDMEM
 
     /* The heap mutex. */
     gctPOINTER                  mutex;
+};
+
+typedef struct _gcsVIDMEM_NODE
+{
+    /* Pointer to gcuVIDMEM_NODE. */
+    gcuVIDMEM_NODE_PTR          node;
+
+    /* Mutex to protect node. */
+    gctPOINTER                  mutex;
+
+    /* Reference count. */
+    gctPOINTER                  reference;
+
+    /* Name for client to import. */
+    gctUINT32                   name;
 
-#if gcdUSE_VIDMEM_PER_PID
-    /* The Pid this VidMem belongs to. */
-    gctUINT32                   pid;
+#if gcdPROCESS_ADDRESS_SPACE
+    /* Head of mapping list. */
+    gcsGPU_MAP_PTR              mapHead;
 
-    struct _gckVIDMEM*          next;
+    /* Tail of mapping list. */
+    gcsGPU_MAP_PTR              mapTail;
+
+    gctPOINTER                  mapMutex;
+#endif
+
+    /* Surface Type. */
+    gceSURF_TYPE                type;
+
+    /* Pool from which node is allocated. */
+    gcePOOL                     pool;
+}
+gcsVIDMEM_NODE;
+
+typedef struct _gcsVIDMEM_HANDLE * gckVIDMEM_HANDLE;
+typedef struct _gcsVIDMEM_HANDLE
+{
+    /* Pointer to gckVIDMEM_NODE. */
+    gckVIDMEM_NODE              node;
+
+    /* Handle for current process. */
+    gctUINT32                   handle;
+
+    /* Reference count for this handle. */
+    gctPOINTER                  reference;
+}
+gcsVIDMEM_HANDLE;
+
+typedef struct _gcsSHBUF * gcsSHBUF_PTR;
+typedef struct _gcsSHBUF
+{
+    /* ID. */
+    gctUINT32                   id;
+
+    /* Reference count. */
+    gctPOINTER                  reference;
+
+    /* Data size. */
+    gctUINT32                   size;
+
+    /* Data. */
+    gctPOINTER                  data;
+}
+gcsSHBUF;
+
+gceSTATUS
+gckVIDMEM_HANDLE_Reference(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gctUINT32 Handle
+    );
+
+gceSTATUS
+gckVIDMEM_HANDLE_Dereference(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gctUINT32 Handle
+    );
+
+gceSTATUS
+gckVIDMEM_NODE_Allocate(
+    IN gckKERNEL Kernel,
+    IN gcuVIDMEM_NODE_PTR VideoNode,
+    IN gceSURF_TYPE Type,
+    IN gcePOOL Pool,
+    IN gctUINT32 * Handle
+    );
+
+gceSTATUS
+gckVIDMEM_Node_Lock(
+    IN gckKERNEL Kernel,
+    IN gckVIDMEM_NODE Node,
+    OUT gctUINT32 *Address
+    );
+
+gceSTATUS
+gckVIDMEM_NODE_Unlock(
+    IN gckKERNEL Kernel,
+    IN gckVIDMEM_NODE Node,
+    IN gctUINT32 ProcessID
+    );
+
+gceSTATUS
+gckVIDMEM_NODE_Dereference(
+    IN gckKERNEL Kernel,
+    IN gckVIDMEM_NODE Node
+    );
+
+gceSTATUS
+gckVIDMEM_NODE_Name(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Handle,
+    IN gctUINT32 * Name
+    );
+
+gceSTATUS
+gckVIDMEM_NODE_Import(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Name,
+    IN gctUINT32 * Handle
+    );
+
+gceSTATUS
+gckVIDMEM_HANDLE_LookupAndReference(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Handle,
+    OUT gckVIDMEM_NODE * Node
+    );
+
+gceSTATUS
+gckVIDMEM_HANDLE_Lookup(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gctUINT32 Handle,
+    OUT gckVIDMEM_NODE * Node
+    );
+
+gceSTATUS
+gckVIDMEM_NODE_GetFd(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Handle,
+    OUT gctINT * Fd
+    );
+
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+gckEVENT_DestroyMmu(
+    IN gckEVENT Event,
+    IN gckMMU Mmu,
+    IN gceKERNEL_WHERE FromWhere
+    );
 #endif
-};
 
 /* gckMMU object. */
 struct _gckMMU
@@ -871,26 +1163,54 @@ struct _gckMMU
 
     gctUINT32                   dynamicMappingStart;
 
-#ifdef __QNXNTO__
-    /* Single linked list of all allocated nodes. */
-    gctPOINTER                  nodeMutex;
-    gcuVIDMEM_NODE_PTR          nodeList;
+    gctUINT32_PTR               mapLogical;
+#if gcdPROCESS_ADDRESS_SPACE
+    gctPOINTER                  pageTableDirty[gcdMAX_GPU_COUNT];
+    gctPOINTER                  stlbs;
 #endif
 };
 
-#if gcdVIRTUAL_COMMAND_BUFFER
 gceSTATUS
 gckOS_CreateKernelVirtualMapping(
+    IN gckOS Os,
     IN gctPHYS_ADDR Physical,
-    OUT gctSIZE_T * PageCount,
-    OUT gctPOINTER * Logical
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Logical,
+    OUT gctSIZE_T * PageCount
     );
 
 gceSTATUS
 gckOS_DestroyKernelVirtualMapping(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
     IN gctPOINTER Logical
     );
 
+gceSTATUS
+gckOS_CreateUserVirtualMapping(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Logical,
+    OUT gctSIZE_T * PageCount
+    );
+
+gceSTATUS
+gckOS_DestroyUserVirtualMapping(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctPOINTER Logical
+    );
+
+gceSTATUS
+gckOS_GetFd(
+    IN gctSTRING Name,
+    IN gcsFDPRIVATE_PTR Private,
+    OUT gctINT *Fd
+    );
+
 gceSTATUS
 gckKERNEL_AllocateVirtualCommandBuffer(
     IN gckKERNEL Kernel,
@@ -912,6 +1232,7 @@ gceSTATUS
 gckKERNEL_GetGPUAddress(
     IN gckKERNEL Kernel,
     IN gctPOINTER Logical,
+    IN gctBOOL InUserSpace,
     OUT gctUINT32 * Address
     );
 
@@ -921,7 +1242,6 @@ gckKERNEL_QueryGPUAddress(
     IN gctUINT32 GpuAddress,
     OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
     );
-#endif
 
 gceSTATUS
 gckKERNEL_AttachProcess(
@@ -959,6 +1279,104 @@ gckHARDWARE_QueryIdle(
     OUT gctBOOL_PTR IsIdle
     );
 
+#if gcdSECURITY
+gceSTATUS
+gckKERNEL_SecurityOpen(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 GPU,
+    OUT gctUINT32 *Channel
+    );
+
+/*
+** Close a security service channel
+*/
+gceSTATUS
+gckKERNEL_SecurityClose(
+    IN gctUINT32 Channel
+    );
+
+/*
+** Security service interface.
+*/
+gceSTATUS
+gckKERNEL_SecurityCallService(
+    IN gctUINT32 Channel,
+    IN OUT gcsTA_INTERFACE * Interface
+    );
+
+gceSTATUS
+gckKERNEL_SecurityStartCommand(
+    IN gckKERNEL Kernel
+    );
+
+gceSTATUS
+gckKERNEL_SecurityAllocateSecurityMemory(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Bytes,
+    OUT gctUINT32 * Handle
+    );
+
+gceSTATUS
+gckKERNEL_SecurityExecute(
+    IN gckKERNEL Kernel,
+    IN gctPOINTER Buffer,
+    IN gctUINT32 Bytes
+    );
+
+gceSTATUS
+gckKERNEL_SecurityMapMemory(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 *PhysicalArray,
+    IN gctUINT32 PageCount,
+    OUT gctUINT32 * GPUAddress
+    );
+
+gceSTATUS
+gckKERNEL_SecurityUnmapMemory(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 GPUAddress,
+    IN gctUINT32 PageCount
+    );
+
+#endif
+
+gceSTATUS
+gckKERNEL_CreateShBuffer(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Size,
+    OUT gctSHBUF * ShBuf
+    );
+
+gceSTATUS
+gckKERNEL_DestroyShBuffer(
+    IN gckKERNEL Kernel,
+    IN gctSHBUF ShBuf
+    );
+
+gceSTATUS
+gckKERNEL_MapShBuffer(
+    IN gckKERNEL Kernel,
+    IN gctSHBUF ShBuf
+    );
+
+gceSTATUS
+gckKERNEL_WriteShBuffer(
+    IN gckKERNEL Kernel,
+    IN gctSHBUF ShBuf,
+    IN gctPOINTER UserData,
+    IN gctUINT32 ByteCount
+    );
+
+gceSTATUS
+gckKERNEL_ReadShBuffer(
+    IN gckKERNEL Kernel,
+    IN gctSHBUF ShBuf,
+    IN gctPOINTER UserData,
+    IN gctUINT32 ByteCount,
+    OUT gctUINT32 * BytesRead
+    );
+
+
 /******************************************************************************\
 ******************************* gckCONTEXT Object *******************************
 \******************************************************************************/
@@ -983,6 +1401,14 @@ gckCONTEXT_Update(
     IN gcsSTATE_DELTA_PTR StateDelta
     );
 
+gceSTATUS
+gckCONTEXT_MapBuffer(
+    IN gckCONTEXT Context,
+    OUT gctUINT32 *Physicals,
+    OUT gctUINT64 *Logicals,
+    OUT gctUINT32 *Bytes
+    );
+
 #if gcdLINK_QUEUE_SIZE
 void
 gckLINKQUEUE_Enqueue(
@@ -999,6 +1425,62 @@ gckLINKQUEUE_GetData(
     );
 #endif
 
+gceSTATUS
+gckENTRYQUEUE_Enqueue(
+    IN gckKERNEL Kernel,
+    IN gckENTRYQUEUE Queue,
+    IN gctUINT32 physical,
+    IN gctUINT32 bytes
+    );
+
+gceSTATUS
+gckENTRYQUEUE_Dequeue(
+    IN gckENTRYQUEUE Queue,
+    OUT gckENTRYDATA * Data
+    );
+
+/******************************************************************************\
+****************************** gckRECORDER Object ******************************
+\******************************************************************************/
+gceSTATUS
+gckRECORDER_Construct(
+    IN gckOS Os,
+    IN gckHARDWARE Hardware,
+    OUT gckRECORDER * Recorder
+    );
+
+gceSTATUS
+gckRECORDER_Destory(
+    IN gckOS Os,
+    IN gckRECORDER Recorder
+    );
+
+void
+gckRECORDER_AdvanceIndex(
+    gckRECORDER Recorder,
+    gctUINT64   CommitStamp
+    );
+
+void
+gckRECORDER_Record(
+    gckRECORDER Recorder,
+    gctUINT8_PTR CommandBuffer,
+    gctUINT32 CommandBytes,
+    gctUINT8_PTR ContextBuffer,
+    gctUINT32 ContextBytes
+    );
+
+void
+gckRECORDER_Dump(
+    gckRECORDER Recorder
+    );
+
+gceSTATUS
+gckRECORDER_UpdateMirror(
+    gckRECORDER Recorder,
+    gctUINT32 State,
+    gctUINT32 Data
+    );
 
 #ifdef __cplusplus
 }
index 73dab8117525fa6ce58eda30edce93ae8895feb1..72aa966d6dad0f6750501d5771ef8590f22f3a68 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 #include "gc_hal_kernel_precomp.h"
 #include "gc_hal_kernel_context.h"
 
-#ifdef __QNXNTO__
-#include <sys/slog.h>
-#endif
-
 #define _GC_OBJ_ZONE            gcvZONE_COMMAND
 
 /******************************************************************************\
@@ -105,14 +101,14 @@ _NewQueue(
     Command->index    = newIndex;
     Command->newQueue = gcvTRUE;
     Command->logical  = Command->queues[newIndex].logical;
+    Command->address  = Command->queues[newIndex].address;
     Command->offset   = 0;
 
-    gcmkONERROR(
-        gckOS_GetPhysicalAddress(
-            Command->os,
-            Command->logical,
-            (gctUINT32 *) &Command->physical
-            ));
+    gcmkONERROR(gckOS_GetPhysicalAddress(
+        Command->os,
+        Command->logical,
+        (gctUINT32 *) &Command->physical
+        ));
 
     if (currentIndex != -1)
     {
@@ -326,9 +322,20 @@ _FlushMMU(
     IN gckCOMMAND Command
     )
 {
+#if gcdSECURITY
+    return gcvSTATUS_OK;
+#else
     gceSTATUS status;
     gctUINT32 oldValue;
     gckHARDWARE hardware = Command->kernel->hardware;
+    gctBOOL pause = gcvFALSE;
+
+    gctUINT8_PTR pointer;
+    gctUINT32 eventBytes;
+    gctUINT32 endBytes;
+    gctUINT32 bufferSize;
+    gctUINT32 executeBytes;
+    gctUINT32 waitLinkBytes;
 
     gcmkONERROR(gckOS_AtomicExchange(Command->os,
                                      hardware->pageTableDirty,
@@ -339,14 +346,70 @@ _FlushMMU(
     {
         /* Page Table is upated, flush mmu before commit. */
         gcmkONERROR(gckHARDWARE_FlushMMU(hardware));
+
+        if ((oldValue & gcvPAGE_TABLE_DIRTY_BIT_FE)
+          && (hardware->endAfterFlushMmuCache)
+        )
+        {
+            pause = gcvTRUE;
+        }
+    }
+
+    if (pause)
+    {
+        /* Query size. */
+        gcmkONERROR(gckHARDWARE_Event(hardware, gcvNULL, 0, gcvKERNEL_PIXEL, &eventBytes));
+        gcmkONERROR(gckHARDWARE_End(hardware, gcvNULL, &endBytes));
+
+        executeBytes = eventBytes + endBytes;
+
+        gcmkONERROR(gckHARDWARE_WaitLink(
+            hardware,
+            gcvNULL,
+            Command->offset + executeBytes,
+            &waitLinkBytes,
+            gcvNULL,
+            gcvNULL
+            ));
+
+        /* Reserve space. */
+        gcmkONERROR(gckCOMMAND_Reserve(
+            Command,
+            executeBytes,
+            (gctPOINTER *)&pointer,
+            &bufferSize
+            ));
+
+        /* Append EVENT(29). */
+        gcmkONERROR(gckHARDWARE_Event(
+            hardware,
+            pointer,
+            29,
+            gcvKERNEL_PIXEL,
+            &eventBytes
+            ));
+
+        /* Append END. */
+        pointer += eventBytes;
+        gcmkONERROR(gckHARDWARE_End(hardware, pointer, &endBytes));
+
+        /* Store address to queue. */
+        gcmkONERROR(gckENTRYQUEUE_Enqueue(
+            Command->kernel,
+            &Command->queue,
+            Command->address + Command->offset + executeBytes,
+            waitLinkBytes
+            ));
+
+        gcmkONERROR(gckCOMMAND_Execute(Command, executeBytes));
     }
 
     return gcvSTATUS_OK;
 OnError:
     return status;
+#endif
 }
 
-#if gcdVIRTUAL_COMMAND_BUFFER
 static void
 _DumpBuffer(
     IN gctPOINTER Buffer,
@@ -354,13 +417,12 @@ _DumpBuffer(
     IN gctSIZE_T Size
     )
 {
-    gctINT i, line, left;
+    gctSIZE_T i, line, left;
     gctUINT32_PTR data = Buffer;
 
     line = Size / 32;
     left = Size % 32;
 
-
     for (i = 0; i < line; i++)
     {
         gcmkPRINT("%X : %08X %08X %08X %08X %08X %08X %08X %08X ",
@@ -407,11 +469,11 @@ _DumpBuffer(
 static void
 _DumpKernelCommandBuffer(
     IN gckCOMMAND Command
-)
+    )
 {
     gctINT i;
-    gctUINT32 physical;
-    gctPOINTER entry;
+    gctUINT32 physical = 0;
+    gctPOINTER entry   = gcvNULL;
 
     for (i = 0; i < gcdCOMMAND_QUEUES; i++)
     {
@@ -424,7 +486,6 @@ _DumpKernelCommandBuffer(
         _DumpBuffer(entry, physical, Command->pageSize);
     }
 }
-#endif
 
 /******************************************************************************\
 ****************************** gckCOMMAND API Code ******************************
@@ -458,6 +519,7 @@ gckCOMMAND_Construct(
     gceSTATUS status;
     gctINT i;
     gctPOINTER pointer = gcvNULL;
+    gctSIZE_T pageSize;
 
     gcmkHEADER_ARG("Kernel=0x%x", Kernel);
 
@@ -506,7 +568,9 @@ gckCOMMAND_Construct(
     gcmkONERROR(gckOS_AtomConstruct(os, &command->atomCommit));
 
     /* Get the page size from teh OS. */
-    gcmkONERROR(gckOS_GetPageSize(os, &command->pageSize));
+    gcmkONERROR(gckOS_GetPageSize(os, &pageSize));
+
+    gcmkSAFECASTSIZET(command->pageSize, pageSize);
 
     /* Get process ID. */
     gcmkONERROR(gckOS_GetProcessID(&command->kernelProcessID));
@@ -520,11 +584,18 @@ gckCOMMAND_Construct(
         gcmkONERROR(gckOS_AllocateNonPagedMemory(
             os,
             gcvFALSE,
-            &command->pageSize,
+            &pageSize,
             &command->queues[i].physical,
             &command->queues[i].logical
             ));
 
+        gcmkONERROR(gckHARDWARE_ConvertLogical(
+            Kernel->hardware,
+            command->queues[i].logical,
+            gcvFALSE,
+            &command->queues[i].address
+            ));
+
         gcmkONERROR(gckOS_CreateSignal(
             os, gcvFALSE, &command->queues[i].signal
             ));
@@ -534,6 +605,10 @@ gckCOMMAND_Construct(
             ));
     }
 
+#if gcdRECORD_COMMAND
+    gcmkONERROR(gckRECORDER_Construct(os, Kernel->hardware, &command->recorder));
+#endif
+
     /* No command queue in use yet. */
     command->index    = -1;
     command->logical  = gcvNULL;
@@ -551,6 +626,10 @@ gckCOMMAND_Construct(
     /* END event signal not created. */
     command->endEventSignal = gcvNULL;
 
+    command->queue.front = 0;
+    command->queue.rear = 0;
+    command->queue.count = 0;
+
     /* Return pointer to the gckCOMMAND object. */
     *Command = command;
 
@@ -697,6 +776,10 @@ gckCOMMAND_Destroy(
     }
 #endif
 
+#if gcdRECORD_COMMAND
+    gckRECORDER_Destory(Command->os, Command->recorder);
+#endif
+
     /* Mark object as unknown. */
     Command->object.type = gcvOBJ_UNKNOWN;
 
@@ -867,8 +950,8 @@ gckCOMMAND_Start(
 {
     gceSTATUS status;
     gckHARDWARE hardware;
-    gctUINT32 waitOffset;
-    gctSIZE_T waitLinkBytes;
+    gctUINT32 waitOffset = 0;
+    gctUINT32 waitLinkBytes;
 
     gcmkHEADER_ARG("Command=0x%x", Command);
 
@@ -917,7 +1000,7 @@ gckCOMMAND_Start(
         Command->os,
         Command->kernelProcessID,
         gcvNULL,
-        Command->physical,
+        (gctUINT32)Command->physical,
         Command->logical,
         waitLinkBytes
         ));
@@ -927,19 +1010,16 @@ gckCOMMAND_Start(
     Command->offset   = waitLinkBytes;
     Command->newQueue = gcvFALSE;
 
-    /* Enable command processor. */
-#ifdef __QNXNTO__
-    gcmkONERROR(gckHARDWARE_Execute(
-        hardware,
-        Command->logical,
-        Command->physical,
-        gcvTRUE,
-        waitLinkBytes
-        ));
+#if gcdSECURITY
+    /* Start FE by calling security service. */
+    gckKERNEL_SecurityStartCommand(
+        Command->kernel
+        );
 #else
+    /* Enable command processor. */
     gcmkONERROR(gckHARDWARE_Execute(
         hardware,
-        Command->logical,
+        Command->address,
         waitLinkBytes
         ));
 #endif
@@ -1015,7 +1095,7 @@ gckCOMMAND_Stop(
                                   Command->waitPhysical,
                                   Command->waitLogical,
                                   Command->endEventSignal,
-                                                                 &Command->waitSize));
+                                  &Command->waitSize));
     }
     else
     {
@@ -1024,6 +1104,12 @@ gckCOMMAND_Stop(
             hardware, Command->waitLogical, &Command->waitSize
             ));
 
+#if gcdSECURITY
+        gcmkONERROR(gckKERNEL_SecurityExecute(
+            Command->kernel, Command->waitLogical, 8
+            ));
+#endif
+
         /* Update queue tail pointer. */
         gcmkONERROR(gckHARDWARE_UpdateQueueTail(Command->kernel->hardware,
                                                 Command->logical,
@@ -1035,7 +1121,7 @@ gckCOMMAND_Stop(
             Command->os,
             Command->kernelProcessID,
             gcvNULL,
-            Command->waitPhysical,
+            (gctUINT32)Command->waitPhysical,
             Command->waitLogical,
             Command->waitSize
             ));
@@ -1085,6 +1171,18 @@ OnError:
 **
 **      Nothing.
 */
+#if gcdMULTI_GPU
+gceSTATUS
+gckCOMMAND_Commit(
+    IN gckCOMMAND Command,
+    IN gckCONTEXT Context,
+    IN gcoCMDBUF CommandBuffer,
+    IN gcsSTATE_DELTA_PTR StateDelta,
+    IN gcsQUEUE_PTR EventQueue,
+    IN gctUINT32 ProcessID,
+    IN gceCORE_3D_MASK ChipEnable
+    )
+#else
 gceSTATUS
 gckCOMMAND_Commit(
     IN gckCOMMAND Command,
@@ -1094,6 +1192,7 @@ gckCOMMAND_Commit(
     IN gcsQUEUE_PTR EventQueue,
     IN gctUINT32 ProcessID
     )
+#endif
 {
     gceSTATUS status;
     gctBOOL commitEntered = gcvFALSE;
@@ -1110,31 +1209,53 @@ gckCOMMAND_Commit(
     gcsCONTEXT_PTR contextBuffer;
     struct _gcoCMDBUF _commandBufferObject;
     gctPHYS_ADDR commandBufferPhysical;
-    gctUINT8_PTR commandBufferLogical;
-    gctUINT8_PTR commandBufferLink;
+    gctUINT8_PTR commandBufferLogical = gcvNULL;
+    gctUINT32 commandBufferAddress = 0;
+    gctUINT8_PTR commandBufferLink = gcvNULL;
     gctUINT commandBufferSize;
     gctSIZE_T nopBytes;
-    gctSIZE_T pipeBytes;
-    gctSIZE_T linkBytes;
+    gctUINT32 pipeBytes;
+    gctUINT32 linkBytes;
     gctSIZE_T bytes;
     gctUINT32 offset;
 #if gcdNONPAGED_MEMORY_CACHEABLE
     gctPHYS_ADDR entryPhysical;
 #endif
     gctPOINTER entryLogical;
-    gctSIZE_T entryBytes;
+    gctUINT32 entryAddress;
+    gctUINT32 entryBytes;
 #if gcdNONPAGED_MEMORY_CACHEABLE
     gctPHYS_ADDR exitPhysical;
 #endif
     gctPOINTER exitLogical;
-    gctSIZE_T exitBytes;
+    gctUINT32 exitAddress;
+    gctUINT32 exitBytes;
     gctPHYS_ADDR waitLinkPhysical;
     gctPOINTER waitLinkLogical;
-    gctSIZE_T waitLinkBytes;
+    gctUINT32 waitLinkAddress;
+    gctUINT32 waitLinkBytes;
     gctPHYS_ADDR waitPhysical;
     gctPOINTER waitLogical;
     gctUINT32 waitOffset;
-    gctSIZE_T waitSize;
+    gctUINT32 waitSize;
+
+#ifdef __QNXNTO__
+    gctPOINTER userCommandBufferLogical       = gcvNULL;
+    gctBOOL    userCommandBufferLogicalMapped = gcvFALSE;
+    gctPOINTER userCommandBufferLink          = gcvNULL;
+    gctBOOL    userCommandBufferLinkMapped    = gcvFALSE;
+#endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+    gctSIZE_T mmuConfigureBytes;
+    gctPOINTER mmuConfigureLogical = gcvNULL;
+    gctUINT32 mmuConfigureAddress;
+    gctPOINTER mmuConfigurePhysical = 0;
+    gctSIZE_T mmuConfigureWaitLinkOffset;
+    gckMMU mmu;
+    gctSIZE_T reservedBytes;
+    gctUINT32 oldValue;
+#endif
 
 #if gcdDUMP_COMMAND
     gctPOINTER contextDumpLogical = gcvNULL;
@@ -1150,6 +1271,10 @@ gckCOMMAND_Commit(
 
     gctPOINTER pointer = gcvNULL;
 
+#if gcdMULTI_GPU
+    gctSIZE_T chipEnableBytes;
+#endif
+
     gcmkHEADER_ARG(
         "Command=0x%x CommandBuffer=0x%x ProcessID=%d",
         Command, CommandBuffer, ProcessID
@@ -1158,13 +1283,21 @@ gckCOMMAND_Commit(
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
 
-    if (Command->kernel->core == gcvCORE_2D)
+    if (Command->kernel->hardware->type== gcvHARDWARE_2D)
     {
         /* There is no context for 2D. */
         Context = gcvNULL;
     }
 
-    gcmkONERROR(_FlushMMU(Command));
+#if gcdPROCESS_ADDRESS_SPACE
+    gcmkONERROR(gckKERNEL_GetProcessMMU(Command->kernel, &mmu));
+
+    gcmkONERROR(gckOS_AtomicExchange(Command->os,
+                                     mmu->pageTableDirty[Command->kernel->core],
+                                     0,
+                                     &oldValue));
+#else
+#endif
 
 #if VIVANTE_PROFILER_CONTEXT
     if((Command->kernel->hardware->gpuProfiler) && (Command->kernel->profileEnable))
@@ -1200,9 +1333,9 @@ gckCOMMAND_Commit(
         /* Yes, merge in the deltas. */
         gckCONTEXT_Update(Context, ProcessID, StateDelta);
 
-               /* Update the current context. */
-               Command->currContext = Context;
-       }
+        /* Update the current context. */
+        Command->currContext = Context;
+    }
 #else
     if (needCopy)
     {
@@ -1244,31 +1377,112 @@ gckCOMMAND_Commit(
 
     /* Query the size of LINK command. */
     gcmkONERROR(gckHARDWARE_Link(
-        hardware, gcvNULL, gcvNULL, 0, &linkBytes
+        hardware, gcvNULL, 0, 0, &linkBytes
         ));
 
+#if gcdMULTI_GPU
+    /* Query the size of chip enable command sequence. */
+    gcmkONERROR(gckHARDWARE_ChipEnable(
+        hardware, gcvNULL, 0, &chipEnableBytes
+        ));
+#endif
+
     /* Compute the command buffer entry and the size. */
     commandBufferLogical
         = (gctUINT8_PTR) gcmUINT64_TO_PTR(commandBufferObject->logical)
         +                commandBufferObject->startOffset;
 
-    gcmkONERROR(gckOS_GetPhysicalAddress(
+    /* Get the hardware address. */
+    if (Command->kernel->virtualCommandBuffer)
+    {
+        gcmkONERROR(gckKERNEL_GetGPUAddress(
+            Command->kernel,
+            commandBufferLogical,
+            gcvTRUE,
+            &commandBufferAddress
+            ));
+    }
+    else
+    {
+        gcmkONERROR(gckHARDWARE_ConvertLogical(
+            hardware,
+            commandBufferLogical,
+            gcvTRUE,
+            &commandBufferAddress
+            ));
+    }
+
+    /* Get the physical address. */
+    gcmkONERROR(gckOS_UserLogicalToPhysical(
         Command->os,
         commandBufferLogical,
         (gctUINT32_PTR)&commandBufferPhysical
         ));
 
+#ifdef __QNXNTO__
+    userCommandBufferLogical = (gctPOINTER) commandBufferLogical;
+
+    gcmkONERROR(gckOS_MapUserPointer(
+        Command->os,
+        userCommandBufferLogical,
+        0,
+        &pointer));
+
+    commandBufferLogical = pointer;
+
+    userCommandBufferLogicalMapped = gcvTRUE;
+#endif
+
     commandBufferSize
         = commandBufferObject->offset
         + Command->reservedTail
         - commandBufferObject->startOffset;
 
+    gcmkONERROR(_FlushMMU(Command));
+
     /* Get the current offset. */
     offset = Command->offset;
 
     /* Compute number of bytes left in current kernel command queue. */
     bytes = Command->pageSize - offset;
 
+#if gcdMULTI_GPU
+    if (Command->kernel->core == gcvCORE_MAJOR)
+    {
+        commandBufferSize += chipEnableBytes;
+
+        gcmkONERROR(gckHARDWARE_ChipEnable(
+            hardware,
+            commandBufferLogical + pipeBytes,
+            ChipEnable,
+            &chipEnableBytes
+            ));
+
+        gcmkONERROR(gckHARDWARE_ChipEnable(
+            hardware,
+            commandBufferLogical + commandBufferSize - linkBytes - chipEnableBytes,
+            gcvCORE_3D_ALL_MASK,
+            &chipEnableBytes
+            ));
+    }
+    else
+    {
+        commandBufferSize += nopBytes;
+
+        gcmkONERROR(gckHARDWARE_Nop(
+            hardware,
+            commandBufferLogical + pipeBytes,
+            &nopBytes
+            ));
+
+        gcmkONERROR(gckHARDWARE_Nop(
+            hardware,
+            commandBufferLogical + commandBufferSize - linkBytes - nopBytes,
+            &nopBytes
+            ));
+    }
+#endif
+
     /* Query the size of WAIT/LINK command sequence. */
     gcmkONERROR(gckHARDWARE_WaitLink(
         hardware,
@@ -1296,6 +1510,7 @@ gckCOMMAND_Commit(
     /* Compute the location if WAIT/LINK command sequence. */
     waitLinkPhysical = (gctUINT8_PTR) Command->physical + offset;
     waitLinkLogical  = (gctUINT8_PTR) Command->logical  + offset;
+    waitLinkAddress  =                Command->address  + offset;
 
     /* Context switch required? */
     if (Context == gcvNULL)
@@ -1326,7 +1541,10 @@ gckCOMMAND_Commit(
         entryPhysical = (gctUINT8_PTR) commandBufferPhysical + offset;
 #endif
         entryLogical  =                commandBufferLogical  + offset;
+        entryAddress  =                commandBufferAddress  + offset;
         entryBytes    =                commandBufferSize     - offset;
+
+        Command->currContext = gcvNULL;
     }
     else if (Command->currContext != Context)
     {
@@ -1361,6 +1579,7 @@ gckCOMMAND_Commit(
                     entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
 #endif
                     entryLogical  = (gctUINT8_PTR) contextBuffer->logical  + pipeBytes;
+                    entryAddress  =                contextBuffer->address  + pipeBytes;
                     entryBytes    =                Context->bufferSize     - pipeBytes;
                 }
                 else
@@ -1369,6 +1588,7 @@ gckCOMMAND_Commit(
                     entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
 #endif
                     entryLogical  = (gctUINT8_PTR) contextBuffer->logical;
+                    entryAddress  =                contextBuffer->address;
                     entryBytes    =                Context->bufferSize;
                 }
 
@@ -1407,7 +1627,7 @@ gckCOMMAND_Commit(
                 gcmkONERROR(gckHARDWARE_Link(
                     hardware,
                     contextBuffer->link3D,
-                    commandBufferLogical + offset,
+                    commandBufferAddress + offset,
                     commandBufferSize    - offset,
                     &linkBytes
                     ));
@@ -1431,6 +1651,7 @@ gckCOMMAND_Commit(
                     entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
 #endif
                     entryLogical  = (gctUINT8_PTR) contextBuffer->logical  + pipeBytes;
+                    entryAddress  =                contextBuffer->address  + pipeBytes;
                     entryBytes    =                Context->entryOffset3D  - pipeBytes;
                 }
                 else
@@ -1439,6 +1660,7 @@ gckCOMMAND_Commit(
                     entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
 #endif
                     entryLogical  = (gctUINT8_PTR) contextBuffer->logical;
+                    entryAddress  =                contextBuffer->address;
                     entryBytes    =                Context->entryOffset3D;
                 }
 
@@ -1472,7 +1694,7 @@ gckCOMMAND_Commit(
                 gcmkONERROR(gckHARDWARE_Link(
                     hardware,
                     contextBuffer->link2D,
-                    commandBufferLogical + offset,
+                    commandBufferAddress + offset,
                     commandBufferSize    - offset,
                     &linkBytes
                     ));
@@ -1482,8 +1704,6 @@ gckCOMMAND_Commit(
         /* Not using 2D. */
         else
         {
-            /* Mark 2D as dirty. */
-            Context->dirty2D = gcvTRUE;
 
             /* Store the current context buffer. */
             Context->dirtyBuffer = contextBuffer;
@@ -1501,7 +1721,7 @@ gckCOMMAND_Commit(
                 offset = (Command->pipeSelect == gcvPIPE_3D)
 
                     /* Skip pipe switching sequence. */
-                    ? Context->entryOffset3D + pipeBytes
+                    ? Context->entryOffset3D + Context->pipeSelectBytes
 
                     /* Do not skip pipe switching sequence. */
                     : Context->entryOffset3D;
@@ -1511,6 +1731,7 @@ gckCOMMAND_Commit(
                 entryPhysical = (gctUINT8_PTR) contextBuffer->physical + offset;
 #endif
                 entryLogical  = (gctUINT8_PTR) contextBuffer->logical  + offset;
+                entryAddress  =                contextBuffer->address  + offset;
                 entryBytes    =                Context->bufferSize     - offset;
 
                 /* See if we have to switch pipes between the context
@@ -1540,7 +1761,7 @@ gckCOMMAND_Commit(
                 gcmkONERROR(gckHARDWARE_Link(
                     hardware,
                     contextBuffer->link3D,
-                    commandBufferLogical + offset,
+                    commandBufferAddress + offset,
                     commandBufferSize    - offset,
                     &linkBytes
                     ));
@@ -1566,6 +1787,10 @@ gckCOMMAND_Commit(
                         = (gctUINT8_PTR) contextBuffer->logical
                         + Context->entryOffsetXDFrom3D;
 
+                    entryAddress
+                        = contextBuffer->address
+                        + Context->entryOffsetXDFrom3D;
+
                     entryBytes
                         = Context->bufferSize
                         - Context->entryOffsetXDFrom3D;
@@ -1581,6 +1806,10 @@ gckCOMMAND_Commit(
                         = (gctUINT8_PTR) contextBuffer->logical
                         + Context->entryOffsetXDFrom2D;
 
+                    entryAddress
+                        = contextBuffer->address
+                        + Context->entryOffsetXDFrom2D;
+
                     entryBytes
                         = Context->totalSize
                         - Context->entryOffsetXDFrom2D;
@@ -1613,7 +1842,7 @@ gckCOMMAND_Commit(
                 gcmkONERROR(gckHARDWARE_Link(
                     hardware,
                     contextBuffer->link3D,
-                    commandBufferLogical + offset,
+                    commandBufferAddress + offset,
                     commandBufferSize    - offset,
                     &linkBytes
                     ));
@@ -1626,7 +1855,7 @@ gckCOMMAND_Commit(
             Command->os,
             Command->kernelProcessID,
             gcvNULL,
-            entryPhysical,
+            (gctUINT32)entryPhysical,
             entryLogical,
             entryBytes
             ));
@@ -1639,6 +1868,25 @@ gckCOMMAND_Commit(
         contextDumpLogical = entryLogical;
         contextDumpBytes   = entryBytes;
 #endif
+
+#if gcdSECURITY
+        /* Commit context buffer to trust zone. */
+        gckKERNEL_SecurityExecute(
+            Command->kernel,
+            entryLogical,
+            entryBytes - 8
+            );
+#endif
+
+#if gcdRECORD_COMMAND
+        gckRECORDER_Record(
+            Command->recorder,
+            gcvNULL,
+            0xFFFFFFFF,
+            entryLogical,
+            entryBytes - 8
+            );
+#endif
     }
 
     /* Same context. */
@@ -1665,6 +1913,7 @@ gckCOMMAND_Commit(
                     entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
 #endif
                     entryLogical  = (gctUINT8_PTR) contextBuffer->logical  + pipeBytes;
+                    entryAddress  =                contextBuffer->address  + pipeBytes;
                     entryBytes    =                Context->bufferSize     - pipeBytes;
                 }
                 else
@@ -1673,6 +1922,7 @@ gckCOMMAND_Commit(
                     entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
 #endif
                     entryLogical  = (gctUINT8_PTR) contextBuffer->logical;
+                    entryAddress  =                contextBuffer->address;
                     entryBytes    =                Context->bufferSize;
                 }
 
@@ -1711,7 +1961,7 @@ gckCOMMAND_Commit(
                 gcmkONERROR(gckHARDWARE_Link(
                     hardware,
                     contextBuffer->link3D,
-                    commandBufferLogical + offset,
+                    commandBufferAddress + offset,
                     commandBufferSize    - offset,
                     &linkBytes
                     ));
@@ -1725,6 +1975,7 @@ gckCOMMAND_Commit(
                     entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
 #endif
                     entryLogical  = (gctUINT8_PTR) contextBuffer->logical  + pipeBytes;
+                    entryAddress  =                contextBuffer->address  + pipeBytes;
                     entryBytes    =                Context->entryOffset3D  - pipeBytes;
                 }
                 else
@@ -1733,6 +1984,7 @@ gckCOMMAND_Commit(
                     entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
 #endif
                     entryLogical  = (gctUINT8_PTR) contextBuffer->logical;
+                    entryAddress  =                contextBuffer->address;
                     entryBytes    =                Context->entryOffset3D;
                 }
 
@@ -1763,7 +2015,7 @@ gckCOMMAND_Commit(
                 gcmkONERROR(gckHARDWARE_Link(
                     hardware,
                     contextBuffer->link2D,
-                    commandBufferLogical + offset,
+                    commandBufferAddress + offset,
                     commandBufferSize    - offset,
                     &linkBytes
                     ));
@@ -1793,6 +2045,7 @@ gckCOMMAND_Commit(
                 entryPhysical = (gctUINT8_PTR) contextBuffer->physical + offset;
 #endif
                 entryLogical  = (gctUINT8_PTR) contextBuffer->logical  + offset;
+                entryAddress  =                contextBuffer->address  + offset;
                 entryBytes    =                Context->bufferSize     - offset;
 
                 /* See if we have to switch pipes between the context
@@ -1822,7 +2075,7 @@ gckCOMMAND_Commit(
                 gcmkONERROR(gckHARDWARE_Link(
                     hardware,
                     contextBuffer->link3D,
-                    commandBufferLogical + offset,
+                    commandBufferAddress + offset,
                     commandBufferSize    - offset,
                     &linkBytes
                     ));
@@ -1855,6 +2108,7 @@ gckCOMMAND_Commit(
                 entryPhysical = (gctUINT8_PTR) commandBufferPhysical + offset;
 #endif
                 entryLogical  =                commandBufferLogical  + offset;
+                entryAddress  =                commandBufferAddress  + offset;
                 entryBytes    =                commandBufferSize     - offset;
             }
         }
@@ -1878,7 +2132,9 @@ gckCOMMAND_Commit(
 #if gcdNONPAGED_MEMORY_CACHEABLE
         exitPhysical = Command->physical;
 #endif
+
         exitLogical  = Command->logical;
+        exitAddress  = Command->address;
         exitBytes    = Command->offset + waitLinkBytes;
     }
     else
@@ -1889,6 +2145,7 @@ gckCOMMAND_Commit(
         exitPhysical = waitLinkPhysical;
 #endif
         exitLogical  = waitLinkLogical;
+        exitAddress  = waitLinkAddress;
         exitBytes    = waitLinkBytes;
     }
 
@@ -1914,7 +2171,7 @@ gckCOMMAND_Commit(
         Command->os,
         Command->kernelProcessID,
         gcvNULL,
-        exitPhysical,
+        (gctUINT32)exitPhysical,
         exitLogical,
         exitBytes
         ));
@@ -1925,15 +2182,52 @@ gckCOMMAND_Commit(
         = (gctUINT8_PTR) gcmUINT64_TO_PTR(commandBufferObject->logical)
         +                commandBufferObject->offset;
 
+#ifdef __QNXNTO__
+    userCommandBufferLink = (gctPOINTER) commandBufferLink;
+
+    gcmkONERROR(gckOS_MapUserPointer(
+        Command->os,
+        userCommandBufferLink,
+        0,
+        &pointer));
+
+    commandBufferLink = pointer;
+
+    userCommandBufferLinkMapped = gcvTRUE;
+#endif
+
+#if gcdMULTI_GPU
+    if (Command->kernel->core == gcvCORE_MAJOR)
+    {
+        commandBufferLink += chipEnableBytes;
+    }
+    else
+    {
+        commandBufferLink += nopBytes;
+    }
+#endif
+
     /* Generate a LINK from the end of the command buffer being scheduled
        back to the kernel command queue. */
+#if !gcdSECURITY
     gcmkONERROR(gckHARDWARE_Link(
         hardware,
         commandBufferLink,
-        exitLogical,
+        exitAddress,
         exitBytes,
         &linkBytes
         ));
+#endif
+
+#ifdef __QNXNTO__
+    gcmkONERROR(gckOS_UnmapUserPointer(
+        Command->os,
+        userCommandBufferLink,
+        0,
+        commandBufferLink));
+
+    userCommandBufferLinkMapped = gcvFALSE;
+#endif
 
 #if gcdNONPAGED_MEMORY_CACHEABLE
     /* Flush the command buffer cache. */
@@ -1941,12 +2235,34 @@ gckCOMMAND_Commit(
         Command->os,
         ProcessID,
         gcvNULL,
-        commandBufferPhysical,
+        (gctUINT32)commandBufferPhysical,
         commandBufferLogical,
         commandBufferSize
         ));
 #endif
 
+#if gcdRECORD_COMMAND
+    gckRECORDER_Record(
+        Command->recorder,
+        commandBufferLogical + offset,
+        commandBufferSize - offset - 8,
+        gcvNULL,
+        0xFFFFFFFF
+        );
+
+    gckRECORDER_AdvanceIndex(Command->recorder, Command->commitStamp);
+
+    Command->commitStamp++;
+#endif
+
+#if gcdSECURITY
+    /* Submit command buffer to trust zone. */
+    gckKERNEL_SecurityExecute(
+        Command->kernel,
+        commandBufferLogical + offset,
+        commandBufferSize    - offset - 8
+        );
+#else
     /* Generate a LINK from the previous WAIT/LINK command sequence to the
        entry determined above (either the context or the command buffer).
        This LINK replaces the WAIT instruction from the previous WAIT/LINK
@@ -1955,10 +2271,11 @@ gckCOMMAND_Commit(
     gcmkONERROR(gckHARDWARE_Link(
         hardware,
         Command->waitLogical,
-        entryLogical,
+        entryAddress,
         entryBytes,
         &Command->waitSize
         ));
+#endif
 
 #if gcdNONPAGED_MEMORY_CACHEABLE
     /* Flush the cache for the link. */
@@ -1966,7 +2283,7 @@ gckCOMMAND_Commit(
         Command->os,
         Command->kernelProcessID,
         gcvNULL,
-        Command->waitPhysical,
+        (gctUINT32)Command->waitPhysical,
         Command->waitLogical,
         Command->waitSize
         ));
@@ -2037,7 +2354,11 @@ gckCOMMAND_Commit(
 #if VIVANTE_PROFILER_CONTEXT
     if(sequenceAcquired)
     {
+#if gcdMULTI_GPU
+        gcmkONERROR(gckCOMMAND_Stall(Command, gcvTRUE, ChipEnable));
+#else
         gcmkONERROR(gckCOMMAND_Stall(Command, gcvTRUE));
+#endif
         if (Command->currContext)
         {
             gcmkONERROR(gckHARDWARE_UpdateContextProfile(
@@ -2106,8 +2427,11 @@ gckCOMMAND_Commit(
     }
 
     /* Submit events. */
+#if gcdMULTI_GPU
+    status = gckEVENT_Submit(Command->kernel->eventObj, gcvTRUE, gcvFALSE, ChipEnable);
+#else
     status = gckEVENT_Submit(Command->kernel->eventObj, gcvTRUE, gcvFALSE);
-
+#endif
     if (status == gcvSTATUS_INTERRUPTED)
     {
         gcmkTRACE(
@@ -2122,6 +2446,19 @@ gckCOMMAND_Commit(
         gcmkONERROR(status);
     }
 
+#ifdef __QNXNTO__
+    if (userCommandBufferLogicalMapped)
+    {
+        gcmkONERROR(gckOS_UnmapUserPointer(
+            Command->os,
+            userCommandBufferLogical,
+            0,
+            commandBufferLogical));
+
+        userCommandBufferLogicalMapped = gcvFALSE;
+    }
+#endif
+
     /* Unmap the command buffer pointer. */
     if (commandBufferMapped)
     {
@@ -2171,6 +2508,26 @@ OnError:
     }
 #endif
 
+#ifdef __QNXNTO__
+    if (userCommandBufferLinkMapped)
+    {
+        gcmkONERROR(gckOS_UnmapUserPointer(
+            Command->os,
+            userCommandBufferLink,
+            0,
+            commandBufferLink));
+    }
+
+    if (userCommandBufferLogicalMapped)
+    {
+        gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+            Command->os,
+            userCommandBufferLogical,
+            0,
+            commandBufferLogical));
+    }
+#endif
+
     /* Unmap the command buffer pointer. */
     if (commandBufferMapped)
     {
@@ -2214,14 +2571,14 @@ OnError:
 gceSTATUS
 gckCOMMAND_Reserve(
     IN gckCOMMAND Command,
-    IN gctSIZE_T RequestedBytes,
+    IN gctUINT32 RequestedBytes,
     OUT gctPOINTER * Buffer,
-    OUT gctSIZE_T * BufferSize
+    OUT gctUINT32 * BufferSize
     )
 {
     gceSTATUS status;
-    gctSIZE_T bytes;
-    gctSIZE_T requiredBytes;
+    gctUINT32 bytes;
+    gctUINT32 requiredBytes;
     gctUINT32 requestedAligned;
 
     gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
@@ -2306,7 +2663,7 @@ OnError:
 gceSTATUS
 gckCOMMAND_Execute(
     IN gckCOMMAND Command,
-    IN gctSIZE_T RequestedBytes
+    IN gctUINT32 RequestedBytes
     )
 {
     gceSTATUS status;
@@ -2314,18 +2671,19 @@ gckCOMMAND_Execute(
     gctPHYS_ADDR waitLinkPhysical;
     gctUINT8_PTR waitLinkLogical;
     gctUINT32 waitLinkOffset;
-    gctSIZE_T waitLinkBytes;
+    gctUINT32 waitLinkBytes;
 
     gctPHYS_ADDR waitPhysical;
     gctPOINTER waitLogical;
     gctUINT32 waitOffset;
-    gctSIZE_T waitBytes;
+    gctUINT32 waitBytes;
 
 #if gcdNONPAGED_MEMORY_CACHEABLE
     gctPHYS_ADDR execPhysical;
 #endif
     gctPOINTER execLogical;
-    gctSIZE_T execBytes;
+    gctUINT32 execAddress;
+    gctUINT32 execBytes;
 
     gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
 
@@ -2365,6 +2723,7 @@ gckCOMMAND_Execute(
         execPhysical = Command->physical;
 #endif
         execLogical  = Command->logical;
+        execAddress  = Command->address;
         execBytes    = waitLinkOffset + waitLinkBytes;
     }
     else
@@ -2375,6 +2734,7 @@ gckCOMMAND_Execute(
         execPhysical = (gctUINT8 *) Command->physical + Command->offset;
 #endif
         execLogical  = (gctUINT8 *) Command->logical  + Command->offset;
+        execAddress  =              Command->address  + Command->offset;
         execBytes    = RequestedBytes + waitLinkBytes;
     }
 
@@ -2384,7 +2744,7 @@ gckCOMMAND_Execute(
         Command->os,
         Command->kernelProcessID,
         gcvNULL,
-        execPhysical,
+        (gctUINT32)execPhysical,
         execLogical,
         execBytes
         ));
@@ -2394,7 +2754,7 @@ gckCOMMAND_Execute(
     gcmkONERROR(gckHARDWARE_Link(
         Command->kernel->hardware,
         Command->waitLogical,
-        execLogical,
+        execAddress,
         execBytes,
         &Command->waitSize
         ));
@@ -2405,7 +2765,7 @@ gckCOMMAND_Execute(
         Command->os,
         Command->kernelProcessID,
         gcvNULL,
-        Command->waitPhysical,
+        (gctUINT32)Command->waitPhysical,
         Command->waitLogical,
         Command->waitSize
         ));
@@ -2475,11 +2835,20 @@ OnError:
 **
 **      Nothing.
 */
+#if gcdMULTI_GPU
+gceSTATUS
+gckCOMMAND_Stall(
+    IN gckCOMMAND Command,
+    IN gctBOOL FromPower,
+    IN gceCORE_3D_MASK ChipEnable
+    )
+#else
 gceSTATUS
 gckCOMMAND_Stall(
     IN gckCOMMAND Command,
     IN gctBOOL FromPower
     )
+#endif
 {
 #if gcdNULL_DRIVER
     /* Do nothing with infinite hardware. */
@@ -2516,7 +2885,11 @@ gckCOMMAND_Stall(
     gcmkONERROR(gckEVENT_Signal(eventObject, signal, gcvKERNEL_PIXEL));
 
     /* Submit the event queue. */
+#if gcdMULTI_GPU
+    gcmkONERROR(gckEVENT_Submit(eventObject, gcvTRUE, FromPower, ChipEnable));
+#else
     gcmkONERROR(gckEVENT_Submit(eventObject, gcvTRUE, FromPower));
+#endif
 
 #if gcdDUMP_COMMAND
     gcmkPRINT("@[kernel.stall]");
@@ -2549,47 +2922,9 @@ gckCOMMAND_Stall(
                 __FUNCTION__, __LINE__, idle
                 );
 
-            gcmkONERROR(gckOS_MemoryBarrier(os, gcvNULL));
-
-#ifdef __QNXNTO__
-            gctUINT32 reg_cmdbuf_fetch;
-            gctUINT32 reg_intr;
-
-            gcmkVERIFY_OK(gckOS_ReadRegisterEx(
-                Command->kernel->hardware->os, Command->kernel->core, 0x0664, &reg_cmdbuf_fetch
-                ));
-
-            if (idle == 0x7FFFFFFE)
-            {
-                /*
-                 * GPU is idle so there should not be pending interrupts.
-                 * Just double check.
-                 *
-                 * Note that reading interrupt register clears it.
-                 * That's why we don't read it in all cases.
-                 */
-                gcmkVERIFY_OK(gckOS_ReadRegisterEx(
-                    Command->kernel->hardware->os, Command->kernel->core, 0x10, &reg_intr
-                    ));
-
-                slogf(
-                    _SLOG_SETCODE(1, 0),
-                    _SLOG_CRITICAL,
-                    "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X, interrupt = 0x%X)",
-                    idle, reg_cmdbuf_fetch, reg_intr
-                    );
-            }
-            else
-            {
-                slogf(
-                    _SLOG_SETCODE(1, 0),
-                    _SLOG_CRITICAL,
-                    "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X)",
-                    idle, reg_cmdbuf_fetch
-                    );
-            }
-#endif
+            gcmkVERIFY_OK(gckOS_MemoryBarrier(os, gcvNULL));
 #endif
+
             /* Advance timer. */
             timer += gcdGPU_ADVANCETIMER;
         }
@@ -2599,11 +2934,7 @@ gckCOMMAND_Stall(
         }
 
     }
-    while (gcmIS_ERROR(status)
-#if gcdGPU_TIMEOUT
-           && (timer < Command->kernel->timeOut)
-#endif
-           );
+    while (gcmIS_ERROR(status));
 
     /* Bail out on timeout. */
     if (gcmIS_ERROR(status))
@@ -2658,6 +2989,7 @@ OnError:
 **          Pointer to a variable that will receive the number of states
 **          in the context buffer.
 */
+#if (gcdENABLE_3D || gcdENABLE_2D)
 gceSTATUS
 gckCOMMAND_Attach(
     IN gckCOMMAND Command,
@@ -2712,6 +3044,7 @@ OnError:
     gcmkFOOTER();
     return status;
 }
+#endif
 
 /*******************************************************************************
 **
@@ -2782,7 +3115,6 @@ OnError:
     return status;
 }
 
-#if gcdVIRTUAL_COMMAND_BUFFER
 /*******************************************************************************
 **
 **  gckCOMMAND_DumpExecutingBuffer
@@ -2810,16 +3142,14 @@ gckCOMMAND_DumpExecutingBuffer(
     gctPOINTER entry;
     gckOS os = Command->os;
     gckKERNEL kernel = Command->kernel;
-#if gcdLINK_QUEUE_SIZE
     gctINT pid;
-    gctINT i, rear;
+    gctUINT32 i, rear;
     gctUINT32 start, end;
     gctUINT32 dumpFront, dumpRear;
     gckLINKQUEUE queue = &kernel->hardware->linkQueue;
     gckLINKQUEUE queueMirror;
     gctUINT32 bytes;
     gckLINKDATA linkData;
-#endif
 
     gcmkPRINT("**************************\n");
     gcmkPRINT("**** COMMAND BUF DUMP ****\n");
@@ -2829,214 +3159,265 @@ gckCOMMAND_DumpExecutingBuffer(
 
     gcmkPRINT("DMA Address 0x%08X", gpuAddress);
 
-#if gcdLINK_QUEUE_SIZE
-    /* Duplicate queue because it will be changed.*/
-    gcmkONERROR(gckOS_AllocateMemory(os,
-                                     sizeof(struct _gckLINKQUEUE),
-                                     (gctPOINTER *)&queueMirror));
-
-    gcmkONERROR(gckOS_MemCopy(queueMirror,
-                              queue,
-                              sizeof(struct _gckLINKQUEUE)));
-
-    /* If kernel command buffer link to a context buffer, then link to a user command
-    ** buffer, the second link will be in queue first, so we must fix this.
-    **     In Queue:    C1 U1 U2 C2 U3 U4 U5 C3
-    **         Real: C1 X1 U1 C2 U2 U3 U4 C3 U5
-    ** Command buffer X1 which is after C1 is out of queue, so C1 is meaningless.
-    */
-    for (i = 0; i < gcdLINK_QUEUE_SIZE; i++)
+    if (Command->kernel->stuckDump > gcdSTUCK_DUMP_MIDDLE)
     {
-        gckLINKQUEUE_GetData(queueMirror, i, &linkData);
+        gcmkPRINT("Dump Level is %d", Command->kernel->stuckDump);
 
-        status = gckKERNEL_QueryGPUAddress(kernel, linkData->start, &buffer);
+        /* Duplicate queue because it will be changed.*/
+        gcmkONERROR(gckOS_AllocateMemory(os,
+                                         sizeof(struct _gckLINKQUEUE),
+                                         (gctPOINTER *)&queueMirror));
 
-        if (gcmIS_ERROR(status))
-        {
-            /* Can't find it in virtual command buffer list, ignore it. */
-            continue;
-        }
+        gckOS_MemCopy(queueMirror,
+                                  queue,
+                                  sizeof(struct _gckLINKQUEUE));
 
-        if (buffer->kernelLogical)
+        /* If kernel command buffer link to a context buffer, then link to a user command
+        ** buffer, the second link will be in queue first, so we must fix this.
+        **     In Queue:    C1 U1 U2 C2 U3 U4 U5 C3
+        **         Real: C1 X1 U1 C2 U2 U3 U4 C3 U5
+        ** Command buffer X1 which is after C1 is out of queue, so C1 is meaningless.
+        */
+        for (i = 0; i < gcdLINK_QUEUE_SIZE; i++)
         {
-            /* It is a context buffer. */
-            if (i == 0)
+            gckLINKQUEUE_GetData(queueMirror, i, &linkData);
+
+            status = gckKERNEL_QueryGPUAddress(kernel, linkData->start, &buffer);
+
+            if (gcmIS_ERROR(status))
             {
-                /* The real command buffer is out, so clear this slot. */
-                linkData->start = 0;
-                linkData->end = 0;
-                linkData->pid = 0;
+                /* Can't find it in virtual command buffer list, ignore it. */
+                continue;
             }
-            else
+
+            if (buffer->kernelLogical)
             {
-                /* switch context buffer and command buffer. */
-                struct _gckLINKDATA tmp = *linkData;
-                gckLINKDATA linkDataPrevious;
-
-                gckLINKQUEUE_GetData(queueMirror, i - 1, &linkDataPrevious);
-                *linkData = *linkDataPrevious;
-                *linkDataPrevious = tmp;
-           }
+                /* It is a context buffer. */
+                if (i == 0)
+                {
+                    /* The real command buffer is out, so clear this slot. */
+                    linkData->start = 0;
+                    linkData->end = 0;
+                    linkData->pid = 0;
+                }
+                else
+                {
+                    /* switch context buffer and command buffer. */
+                    struct _gckLINKDATA tmp = *linkData;
+                    gckLINKDATA linkDataPrevious;
+
+                    gckLINKQUEUE_GetData(queueMirror, i - 1, &linkDataPrevious);
+                    *linkData = *linkDataPrevious;
+                    *linkDataPrevious = tmp;
+               }
+            }
         }
-    }
 
-    /* Clear search result. */
-    dumpFront = dumpRear = gcvINFINITE;
+        /* Clear search result. */
+        dumpFront = dumpRear = gcvINFINITE;
 
-    gcmkPRINT("Link Stack:");
+        gcmkPRINT("Link Stack:");
 
-    /* Search stuck address in link queue from rear. */
-    rear = gcdLINK_QUEUE_SIZE - 1;
-    for (i = 0; i < gcdLINK_QUEUE_SIZE; i++)
-    {
-        gckLINKQUEUE_GetData(queueMirror, rear, &linkData);
+        /* Search stuck address in link queue from rear. */
+        rear = gcdLINK_QUEUE_SIZE - 1;
+        for (i = 0; i < gcdLINK_QUEUE_SIZE; i++)
+        {
+            gckLINKQUEUE_GetData(queueMirror, rear, &linkData);
 
-        start = linkData->start;
-        end = linkData->end;
-        pid = linkData->pid;
+            start = linkData->start;
+            end = linkData->end;
+            pid = linkData->pid;
 
-        if (gpuAddress >= start && gpuAddress < end)
-        {
-            /* Find latest matched command buffer. */
-            gcmkPRINT("  %d, [%08X - %08X]", pid, start, end);
+            if (gpuAddress >= start && gpuAddress < end)
+            {
+                /* Find latest matched command buffer. */
+                gcmkPRINT("  %d, [%08X - %08X]", pid, start, end);
 
-            /* Initiliaze dump information. */
-            dumpFront = dumpRear = rear;
-        }
+                /* Initiliaze dump information. */
+                dumpFront = dumpRear = rear;
+            }
 
-        /* Advance to previous one. */
-        rear--;
+            /* Advance to previous one. */
+            rear--;
+
+            if (dumpFront != gcvINFINITE)
+            {
+                break;
+            }
+        }
 
-        if (dumpFront != gcvINFINITE)
+        if (dumpFront == gcvINFINITE)
         {
-            break;
+            /* Can't find matched record in link queue, dump kernel command buffer. */
+            _DumpKernelCommandBuffer(Command);
+
+            /* Free local copy. */
+            gcmkOS_SAFE_FREE(os, queueMirror);
+            return gcvSTATUS_OK;
         }
-    }
 
-    if (dumpFront == gcvINFINITE)
-    {
-        /* Can't find matched record in link queue, dump kernel command buffer. */
-        _DumpKernelCommandBuffer(Command);
+        /* Search the last context buffer linked. */
+        while (rear > 0)
+        {
+            gckLINKQUEUE_GetData(queueMirror, rear, &linkData);
 
-        /* Free local copy. */
-        gcmkOS_SAFE_FREE(os, queueMirror);
-        return gcvSTATUS_OK;
-    }
+            gcmkPRINT("  %d, [%08X - %08X]",
+                      linkData->pid,
+                      linkData->start,
+                      linkData->end);
 
-    /* Search the last context buffer linked. */
-    while (rear >= 0)
-    {
-        gckLINKQUEUE_GetData(queueMirror, rear, &linkData);
+            status = gckKERNEL_QueryGPUAddress(kernel, linkData->start, &buffer);
 
-        gcmkPRINT("  %d, [%08X - %08X]",
-                  linkData->pid,
-                  linkData->start,
-                  linkData->end);
+            if (gcmIS_SUCCESS(status) && buffer->kernelLogical)
+            {
+                /* Find a context buffer. */
+                dumpFront = rear;
+                break;
+            }
 
-        status = gckKERNEL_QueryGPUAddress(kernel, linkData->start, &buffer);
+            rear--;
+        }
 
-        if (gcmIS_SUCCESS(status) && buffer->kernelLogical)
+        if (dumpFront == dumpRear)
         {
-            /* Find a context buffer. */
-            dumpFront = rear;
-            break;
+            /* No context buffer is found, dump all we got.*/
+            dumpFront = 0;
         }
 
-        rear--;
-    }
-
-    /* Dump from last context buffer to last command buffer where hang happens. */
-    for (i = dumpFront; i <= dumpRear; i++)
-    {
-        gckLINKQUEUE_GetData(queueMirror, i, &linkData);
+        /* Dump from last context buffer to last command buffer where hang happens. */
+        for (i = dumpFront; i <= dumpRear; i++)
+        {
+            gckLINKQUEUE_GetData(queueMirror, i, &linkData);
 
-        /* Get gpu address of this command buffer. */
-        gpuAddress = linkData->start;
-        bytes = linkData->end - gpuAddress;
+            /* Get gpu address of this command buffer. */
+            gpuAddress = linkData->start;
+            bytes = linkData->end - gpuAddress;
 
-        /* Get the whole buffer. */
-        status = gckKERNEL_QueryGPUAddress(kernel, gpuAddress, &buffer);
+            /* Get the whole buffer. */
+            status = gckKERNEL_QueryGPUAddress(kernel, gpuAddress, &buffer);
 
-        if (gcmIS_ERROR(status))
-        {
-            gcmkPRINT("Buffer [%08X - %08X] is lost",
-                      linkData->start,
-                      linkData->end);
-            continue;
-        }
+            if (gcmIS_ERROR(status))
+            {
+                gcmkPRINT("Buffer [%08X - %08X] is lost or not belong to current process",
+                          linkData->start,
+                          linkData->end);
+                continue;
+            }
 
-        /* Get kernel logical for dump. */
-        if (buffer->kernelLogical)
-        {
-            /* Get kernel logical directly if it is a context buffer. */
-            entry = buffer->kernelLogical;
-            gcmkPRINT("Context Buffer:");
-        }
-        else
-        {
-            /* Make it accessiable by kernel if it is a user command buffer. */
-            gcmkVERIFY_OK(
-                gckOS_CreateKernelVirtualMapping(buffer->physical,
-                                                 &pageCount,
-                                                 &entry));
-            gcmkPRINT("User Command Buffer:");
-        }
+            /* Get kernel logical for dump. */
+            if (buffer->kernelLogical)
+            {
+                /* Get kernel logical directly if it is a context buffer. */
+                entry = buffer->kernelLogical;
+                gcmkPRINT("Context Buffer:");
+            }
+            else
+            {
+                /* Make it accessiable by kernel if it is a user command buffer. */
+                gcmkVERIFY_OK(
+                    gckOS_CreateKernelVirtualMapping(os,
+                                                     buffer->physical,
+                                                     buffer->bytes,
+                                                     &entry,
+                                                     &pageCount));
+                gcmkPRINT("User Command Buffer:");
+            }
 
-        /* Dump from the entry. */
-        _DumpBuffer(entry + (gpuAddress - buffer->gpuAddress), gpuAddress, bytes);
+            /* Dump from the entry. */
+            _DumpBuffer((gctUINT8_PTR)entry + (gpuAddress - buffer->gpuAddress), gpuAddress, bytes);
 
-        /* Release kernel logical address if neccessary. */
-        if (!buffer->kernelLogical)
-        {
-            gcmkVERIFY_OK(gckOS_DestroyKernelVirtualMapping(entry));
+            /* Release kernel logical address if neccessary. */
+            if (!buffer->kernelLogical)
+            {
+                gcmkVERIFY_OK(
+                    gckOS_DestroyKernelVirtualMapping(os,
+                                                      buffer->physical,
+                                                      buffer->bytes,
+                                                      entry));
+            }
         }
-    }
 
-    /* Free local copy. */
-    gcmkOS_SAFE_FREE(os, queueMirror);
-    return gcvSTATUS_OK;
-OnError:
-    return status;
-#else
-    /* Without link queue information, we don't know the entry of last command
-    ** buffer, just dump the page where GPU stuck. */
-    status = gckKERNEL_QueryGPUAddress(kernel, gpuAddress, &buffer);
-
-    if (gcmIS_SUCCESS(status))
+        /* Free local copy. */
+        gcmkOS_SAFE_FREE(os, queueMirror);
+        return gcvSTATUS_OK;
+    OnError:
+        return status;
+    }
+    else
     {
-        gcmkVERIFY_OK(
-            gckOS_CreateKernelVirtualMapping(buffer->physical, &pageCount, &entry));
+        gcmkPRINT("Dump Level is %d, dump memory near the stuck address",
+                  Command->kernel->stuckDump);
 
-        if (entry)
+        /* Without link queue information, we don't know the entry of last command
+        ** buffer, just dump the page where GPU stuck. */
+        status = gckKERNEL_QueryGPUAddress(kernel, gpuAddress, &buffer);
+
+        if (gcmIS_SUCCESS(status))
         {
-            gctUINT32 offset = gpuAddress - buffer->gpuAddress;
-            gctPOINTER entryDump = entry;
+            gcmkVERIFY_OK(
+                gckOS_CreateKernelVirtualMapping(os,
+                                                 buffer->physical,
+                                                 buffer->bytes,
+                                                 &entry,
+                                                 &pageCount));
 
-            /* Dump one pages. */
-            gctUINT32 bytes = 4096;
+            if (entry)
+            {
+                gctUINT32 offset = gpuAddress - buffer->gpuAddress;
+                gctPOINTER entryDump = entry;
+
+                /* Dump one pages. */
+                gctUINT32 bytes = 4096;
 
-            /* Align to page. */
-            offset &= 0xfffff000;
+                /* Align to page. */
+                offset &= 0xfffff000;
 
-            /* Kernel address of page where stall point stay. */
-            entryDump += offset;
+                /* Kernel address of page where stall point stay. */
+                entryDump = (gctUINT8_PTR)entryDump + offset;
 
-            /* Align to page. */
-            gpuAddress &= 0xfffff000;
+                /* Align to page. */
+                gpuAddress &= 0xfffff000;
 
-            gcmkPRINT("User Command Buffer:\n");
-            _DumpBuffer(entryDump, gpuAddress, bytes);
+                gcmkPRINT("User Command Buffer:\n");
+                _DumpBuffer(entryDump, gpuAddress, bytes);
+            }
+
+            gcmkVERIFY_OK(
+                gckOS_DestroyKernelVirtualMapping(os,
+                                                  buffer->physical,
+                                                  buffer->bytes,
+                                                  entry));
+        }
+        else
+        {
+            _DumpKernelCommandBuffer(Command);
         }
 
-        gcmkVERIFY_OK(
-            gckOS_DestroyKernelVirtualMapping(entry));
+        return gcvSTATUS_OK;
     }
-    else
+}
+
+gceSTATUS
+gckCOMMAND_AddressInKernelCommandBuffer(
+    IN gckCOMMAND Command,
+    IN gctUINT32 Address,
+    OUT gctBOOL *In
+    )
+{
+    gctBOOL in = gcvFALSE;
+    gctINT i;
+
+    for (i = 0; i < gcdCOMMAND_QUEUES; i++)
     {
-        _DumpKernelCommandBuffer(Command);
+        if ((Address >= Command->queues[i].address)
+         && (Address < (Command->queues[i].address + Command->pageSize))
+        )
+        {
+            in = gcvTRUE;
+            break;
+        }
     }
 
+    *In = in;
     return gcvSTATUS_OK;
-#endif
 }
-#endif
index ce2c18a102b6df36374250da36573951d31bfb08..0eafaf6c0e388154572e51168d9c845181c0c857 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -536,7 +536,7 @@ _FreeTaskContainer(
     gcsTASK_CONTAINER_PTR next;
     gcsTASK_CONTAINER_PTR merged;
 
-    gctSIZE_T mergedSize;
+    gctUINT32 mergedSize;
 
     /* Verify arguments. */
     gcmkASSERT(Buffer != gcvNULL);
@@ -605,11 +605,17 @@ _RemoveRecordFromProcesDB(
     IN gcsTASK_HEADER_PTR Task
     )
 {
+    gceSTATUS status;
     gcsTASK_PTR task = (gcsTASK_PTR)((gctUINT8_PTR)Task - sizeof(gcsTASK));
     gcsTASK_FREE_VIDEO_MEMORY_PTR freeVideoMemory;
     gcsTASK_UNLOCK_VIDEO_MEMORY_PTR unlockVideoMemory;
     gctINT pid;
     gctUINT32 size;
+    gctUINT32 handle;
+    gckKERNEL kernel = Command->kernel->kernel;
+    gckVIDMEM_NODE unlockNode = gcvNULL;
+    gckVIDMEM_NODE nodeObject = gcvNULL;
+    gceDATABASE_TYPE type;
 
     /* Get the total size of all tasks. */
     size = task->size;
@@ -623,12 +629,32 @@ _RemoveRecordFromProcesDB(
         case gcvTASK_FREE_VIDEO_MEMORY:
             freeVideoMemory = (gcsTASK_FREE_VIDEO_MEMORY_PTR)Task;
 
+            handle = (gctUINT32)freeVideoMemory->node;
+
+            status = gckVIDMEM_HANDLE_Lookup(
+                Command->kernel->kernel,
+                pid,
+                handle,
+                &nodeObject);
+
+            if (gcmIS_ERROR(status))
+            {
+                return status;
+            }
+
+            gckVIDMEM_HANDLE_Dereference(kernel, pid, handle);
+            freeVideoMemory->node = gcmALL_TO_UINT32(nodeObject);
+
+            type = gcvDB_VIDEO_MEMORY
+                | (nodeObject->type << gcdDB_VIDEO_MEMORY_TYPE_SHIFT)
+                | (nodeObject->pool << gcdDB_VIDEO_MEMORY_POOL_SHIFT);
+
             /* Remove record from process db. */
             gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
                 Command->kernel->kernel,
                 pid,
-                gcvDB_VIDEO_MEMORY,
-                gcmUINT64_TO_PTR(freeVideoMemory->node)));
+                type,
+                gcmINT2PTR(handle)));
 
             /* Advance to next task. */
             size -= sizeof(gcsTASK_FREE_VIDEO_MEMORY);
@@ -645,6 +671,22 @@ _RemoveRecordFromProcesDB(
                 gcvDB_VIDEO_MEMORY_LOCKED,
                 gcmUINT64_TO_PTR(unlockVideoMemory->node)));
 
+            handle = (gctUINT32)unlockVideoMemory->node;
+
+            status = gckVIDMEM_HANDLE_Lookup(
+                Command->kernel->kernel,
+                pid,
+                handle,
+                &unlockNode);
+
+            if (gcmIS_ERROR(status))
+            {
+                return status;
+            }
+
+            gckVIDMEM_HANDLE_Dereference(kernel, pid, handle);
+            unlockVideoMemory->node = gcmPTR_TO_UINT64(unlockNode);
+
             /* Advance to next task. */
             size -= sizeof(gcsTASK_UNLOCK_VIDEO_MEMORY);
             Task = (gcsTASK_HEADER_PTR)(unlockVideoMemory + 1);
@@ -685,6 +727,11 @@ _ScheduleTasks(
         gctINT32 interrupt;
         gctUINT8_PTR eventCommand;
 
+#ifdef __QNXNTO__
+        gcsTASK_PTR oldUserTask = gcvNULL;
+        gctPOINTER pointer;
+#endif
+
         /* Nothing to schedule? */
         if (TaskTable->size == 0)
         {
@@ -782,7 +829,21 @@ _ScheduleTasks(
                 /* Copy tasks. */
                 do
                 {
-                    gcsTASK_HEADER_PTR taskHeader = (gcsTASK_HEADER_PTR) (userTask + 1);
+                    gcsTASK_HEADER_PTR taskHeader;
+
+#ifdef __QNXNTO__
+                    oldUserTask = userTask;
+
+                    gcmkERR_BREAK(gckOS_MapUserPointer(
+                        Command->os,
+                        oldUserTask,
+                        0,
+                        &pointer));
+
+                    userTask = pointer;
+#endif
+
+                    taskHeader = (gcsTASK_HEADER_PTR) (userTask + 1);
 
                     gcmkVERIFY_OK(_RemoveRecordFromProcesDB(Command, taskHeader));
 
@@ -799,7 +860,8 @@ _ScheduleTasks(
                         ((gcsTASK_SIGNAL_PTR)taskHeader)->coid  = TaskTable->coid;
                         ((gcsTASK_SIGNAL_PTR)taskHeader)->rcvid = TaskTable->rcvid;
                     }
-#endif /* __QNXNTO__ */
+#endif
+
                     /* Copy the task data. */
                     gcmkVERIFY_OK(gckOS_MemCopy(
                         kernelTask, taskHeader, userTask->size
@@ -808,6 +870,14 @@ _ScheduleTasks(
                     /* Advance to the next task. */
                     kernelTask += userTask->size;
                     userTask    = userTask->next;
+
+#ifdef __QNXNTO__
+                    gcmkERR_BREAK(gckOS_UnmapUserPointer(
+                        Command->os,
+                        oldUserTask,
+                        0,
+                        pointer));
+#endif
                 }
                 while (userTask != gcvNULL);
 
@@ -887,24 +957,31 @@ _HardwareToKernel(
     gceSTATUS status;
     gckVIDMEM memory;
     gctUINT32 offset;
-#if gcdDYNAMIC_MAP_RESERVED_MEMORY
     gctUINT32 nodePhysical;
-#endif
+    gctPOINTER *logical;
+    gctSIZE_T bytes;
     status = gcvSTATUS_OK;
-    /* Assume a non-virtual node and get the pool manager object. */
+
     memory = Node->VidMem.memory;
 
-#if gcdDYNAMIC_MAP_RESERVED_MEMORY
-    nodePhysical = memory->baseAddress
-                 + Node->VidMem.offset
-                 + Node->VidMem.alignment;
+    if (memory->object.type == gcvOBJ_VIDMEM)
+    {
+        nodePhysical = memory->baseAddress
+                     + (gctUINT32)Node->VidMem.offset
+                     + Node->VidMem.alignment;
+        bytes = Node->VidMem.bytes;
+        logical = &Node->VidMem.kernelVirtual;
+    }
+    else
+    {
+        nodePhysical = Node->Virtual.physicalAddress;
+        bytes = Node->Virtual.bytes;
+        logical = &Node->Virtual.kernelVirtual;
+    }
 
-    if (Node->VidMem.kernelVirtual == gcvNULL)
+    if (*logical == gcvNULL)
     {
-        status = gckOS_MapPhysical(Os,
-                        nodePhysical,
-                        Node->VidMem.bytes,
-                        (gctPOINTER *)&Node->VidMem.kernelVirtual);
+        status = gckOS_MapPhysical(Os, nodePhysical, bytes, logical);
 
         if (gcmkIS_ERROR(status))
         {
@@ -913,19 +990,7 @@ _HardwareToKernel(
     }
 
     offset = Address - nodePhysical;
-    *KernelPointer = (gctPOINTER)((gctUINT8_PTR)Node->VidMem.kernelVirtual + offset);
-#else
-    /* Determine the header offset within the pool it is allocated in. */
-    offset = Address - memory->baseAddress;
-
-    /* Translate the offset into the kernel side pointer. */
-    status = gckOS_GetKernelLogicalEx(
-        Os,
-        gcvCORE_VG,
-        offset,
-        KernelPointer
-        );
-#endif
+    *KernelPointer = (gctPOINTER)((gctUINT8_PTR)(*logical) + offset);
 
     /* Return status. */
     return status;
@@ -940,6 +1005,11 @@ _ConvertUserCommandBufferPointer(
 {
     gceSTATUS status, last;
     gcsCMDBUFFER_PTR mappedUserCommandBuffer = gcvNULL;
+    gckKERNEL kernel = Command->kernel->kernel;
+    gctUINT32 pid;
+    gckVIDMEM_NODE node;
+
+    gckOS_GetProcessID(&pid);
 
     do
     {
@@ -958,10 +1028,16 @@ _ConvertUserCommandBufferPointer(
             = mappedUserCommandBuffer->address
             - mappedUserCommandBuffer->bufferOffset;
 
+        gcmkERR_BREAK(gckVIDMEM_HANDLE_Lookup(
+            kernel,
+            pid,
+            gcmPTR2INT32(mappedUserCommandBuffer->node),
+            &node));
+
         /* Translate the logical address to the kernel space. */
         gcmkERR_BREAK(_HardwareToKernel(
             Command->os,
-            gcmUINT64_TO_PTR(mappedUserCommandBuffer->node),
+            node->node,
             headerAddress,
             (gctPOINTER *) KernelCommandBuffer
             ));
@@ -994,51 +1070,25 @@ _AllocateLinear(
     )
 {
     gceSTATUS status, last;
-    gcuVIDMEM_NODE_PTR node = gcvNULL;
-    gctUINT32 address = (gctUINT32)~0;
+    gctPOINTER logical;
+    gctPHYS_ADDR physical;
+    gctUINT32 address;
+    gctSIZE_T size = Size;
 
     do
     {
-        gcePOOL pool;
-        gctPOINTER logical;
-
-        /* Allocate from the system pool. */
-        pool = gcvPOOL_SYSTEM;
-
-        /* Allocate memory. */
-        gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
-            Command->kernel->kernel, &pool,
-            Size, Alignment,
-            gcvSURF_TYPE_UNKNOWN,
-            &node
-            ));
-
-        /* Do not accept virtual pools for now because we don't handle the
-           kernel pointer translation at the moment. */
-        if (pool == gcvPOOL_VIRTUAL)
-        {
-            status = gcvSTATUS_OUT_OF_MEMORY;
-            break;
-        }
-
-        /* Lock the command buffer. */
-        gcmkERR_BREAK(gckVIDMEM_Lock(
-            Command->kernel->kernel,
-            node,
-            gcvFALSE,
-            &address
-            ));
-
-        /* Translate the logical address to the kernel space. */
-        gcmkERR_BREAK(_HardwareToKernel(
+        gcmkERR_BREAK(gckOS_AllocateContiguous(
             Command->os,
-            node,
-            address,
+            gcvFALSE,
+            &size,
+            &physical,
             &logical
             ));
 
+        gcmkERR_BREAK(gckOS_GetPhysicalAddress(Command->os, logical, &address));
+
         /* Set return values. */
-        * Node    = node;
+        * Node    = physical;
         * Address = address;
         * Logical = logical;
 
@@ -1048,20 +1098,10 @@ _AllocateLinear(
     while (gcvFALSE);
 
     /* Roll back. */
-    if (node != gcvNULL)
+    if (physical != gcvNULL)
     {
-        /* Unlock the command buffer. */
-        if (address != ~0)
-        {
-            gcmkCHECK_STATUS(gckVIDMEM_Unlock(
-                Command->kernel->kernel, node, gcvSURF_TYPE_UNKNOWN, gcvNULL
-                ));
-        }
-
         /* Free the command buffer. */
-        gcmkCHECK_STATUS(gckVIDMEM_Free(
-            node
-            ));
+        gcmkCHECK_STATUS(gckOS_FreeContiguous(Command->os, physical, logical, size));
     }
 
     /* Return status. */
@@ -1071,18 +1111,15 @@ _AllocateLinear(
 static gceSTATUS
 _FreeLinear(
     IN gckVGKERNEL Kernel,
-    IN gcuVIDMEM_NODE_PTR Node
+    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctPOINTER Logical
     )
 {
-    gceSTATUS status;
+    gceSTATUS status = gcvSTATUS_OK;
 
     do
     {
-        /* Unlock the linear buffer. */
-        gcmkERR_BREAK(gckVIDMEM_Unlock(Kernel->kernel, Node, gcvSURF_TYPE_UNKNOWN, gcvNULL));
-
-        /* Free the linear buffer. */
-        gcmkERR_BREAK(gckVIDMEM_Free(Node));
+        gcmkERR_BREAK(gckOS_FreeContiguous(Kernel->os, Node, Logical, 1));
     }
     while (gcvFALSE);
 
@@ -1099,6 +1136,7 @@ _AllocateCommandBuffer(
 {
     gceSTATUS status, last;
     gcuVIDMEM_NODE_PTR node = gcvNULL;
+    gcsCMDBUFFER_PTR commandBuffer = gcvNULL;
 
     do
     {
@@ -1106,22 +1144,21 @@ _AllocateCommandBuffer(
         gctUINT requestedSize;
         gctUINT allocationSize;
         gctUINT32 address = 0;
-        gcsCMDBUFFER_PTR commandBuffer;
         gctUINT8_PTR endCommand;
 
         /* Determine the aligned header size. */
         alignedHeaderSize
-            = gcmALIGN(gcmSIZEOF(gcsCMDBUFFER), Command->info.addressAlignment);
+            = (gctUINT32)gcmALIGN(gcmSIZEOF(gcsCMDBUFFER), Command->info.addressAlignment);
 
         /* Align the requested size. */
         requestedSize
-            = gcmALIGN(Size, Command->info.commandAlignment);
+            = (gctUINT32)gcmALIGN(Size, Command->info.commandAlignment);
 
         /* Determine the size of the buffer to allocate. */
         allocationSize
             = alignedHeaderSize
             + requestedSize
-            + Command->info.staticTailSize;
+            + (gctUINT32)Command->info.staticTailSize;
 
         /* Allocate the command buffer. */
         gcmkERR_BREAK(_AllocateLinear(
@@ -1135,7 +1172,7 @@ _AllocateCommandBuffer(
 
         /* Initialize the structure. */
         commandBuffer->completion    = gcvVACANT_BUFFER;
-        commandBuffer->node          = gcmPTR_TO_UINT64(node);
+        commandBuffer->node          = node;
         commandBuffer->address       = address + alignedHeaderSize;
         commandBuffer->bufferOffset  = alignedHeaderSize;
         commandBuffer->size          = requestedSize;
@@ -1174,7 +1211,7 @@ _AllocateCommandBuffer(
     if (node != gcvNULL)
     {
         /* Free the command buffer. */
-        gcmkCHECK_STATUS(_FreeLinear(Command->kernel, node));
+        gcmkCHECK_STATUS(_FreeLinear(Command->kernel, node, commandBuffer));
     }
 
     /* Return status. */
@@ -1190,7 +1227,7 @@ _FreeCommandBuffer(
     gceSTATUS status;
 
     /* Free the buffer. */
-    status = _FreeLinear(Kernel, gcmUINT64_TO_PTR(CommandBuffer->node));
+    status = _FreeLinear(Kernel, CommandBuffer->node, CommandBuffer);
 
     /* Return status. */
     return status;
@@ -1645,10 +1682,14 @@ _TaskUnlockVideoMemory(
         /* Unlock video memory. */
         gcmkERR_BREAK(gckVIDMEM_Unlock(
             Command->kernel->kernel,
-            gcmUINT64_TO_PTR(task->node),
+            (gckVIDMEM_NODE)gcmUINT64_TO_PTR(task->node),
             gcvSURF_TYPE_UNKNOWN,
             gcvNULL));
 
+        gcmkERR_BREAK(gckVIDMEM_NODE_Dereference(
+            Command->kernel->kernel,
+            gcmUINT64_TO_PTR(task->node)));
+
         /* Update the reference counter. */
         TaskHeader->container->referenceCount -= 1;
 
@@ -1676,7 +1717,9 @@ _TaskFreeVideoMemory(
             = (gcsTASK_FREE_VIDEO_MEMORY_PTR) TaskHeader->task;
 
         /* Free video memory. */
-        gcmkERR_BREAK(gckVIDMEM_Free(gcmUINT64_TO_PTR(task->node)));
+        gcmkERR_BREAK(gckVIDMEM_NODE_Dereference(
+            Command->kernel->kernel,
+            gcmINT2PTR(task->node)));
 
         /* Update the reference counter. */
         TaskHeader->container->referenceCount -= 1;
@@ -1728,6 +1771,7 @@ _TaskUnmapUserMemory(
     )
 {
     gceSTATUS status;
+    gctPOINTER info;
 
     do
     {
@@ -1735,9 +1779,12 @@ _TaskUnmapUserMemory(
         gcsTASK_UNMAP_USER_MEMORY_PTR task
             = (gcsTASK_UNMAP_USER_MEMORY_PTR) TaskHeader->task;
 
+        info = gckKERNEL_QueryPointerFromName(
+                Command->kernel->kernel, gcmALL_TO_UINT32(task->info));
+
         /* Unmap the user memory. */
         gcmkERR_BREAK(gckOS_UnmapUserMemory(
-            Command->os, gcvCORE_VG, task->memory, task->size, task->info, task->address
+            Command->os, gcvCORE_VG, task->memory, task->size, info, task->address
             ));
 
         /* Update the reference counter. */
@@ -1763,12 +1810,18 @@ _EventHandler_Block(
     IN gctBOOL ProcessAll
     )
 {
-    gceSTATUS status, last;
+    gceSTATUS status = gcvSTATUS_OK, last;
 
     gcmkHEADER_ARG("Kernel=0x%x TaskHeader=0x%x ProcessAll=0x%x", Kernel, TaskHeader, ProcessAll);
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
 
+    if (TaskHeader->task == gcvNULL)
+    {
+        gcmkFOOTER();
+        return gcvSTATUS_OK;
+    }
+
     do
     {
         gckVGCOMMAND command;
@@ -3377,6 +3430,14 @@ gckVGCOMMAND_Commit(
 
     gceSTATUS status, last;
 
+#ifdef __QNXNTO__
+    gcsVGCONTEXT_PTR userContext = gcvNULL;
+    gctBOOL userContextMapped = gcvFALSE;
+    gcsTASK_MASTER_TABLE_PTR userTaskTable = gcvNULL;
+    gctBOOL userTaskTableMapped = gcvFALSE;
+    gctPOINTER pointer = gcvNULL;
+#endif
+
     gcmkHEADER_ARG("Command=0x%x Context=0x%x Queue=0x%x EntryCount=0x%x TaskTable=0x%x",
         Command, Context, Queue, EntryCount, TaskTable);
 
@@ -3386,11 +3447,6 @@ gckVGCOMMAND_Commit(
     gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
     gcmkVERIFY_ARGUMENT(EntryCount > 1);
 
-#ifdef __QNXNTO__
-    TaskTable->coid     = Context->coid;
-    TaskTable->rcvid    = Context->rcvid;
-#endif /* __QNXNTO__ */
-
     do
     {
         gctBOOL haveFETasks;
@@ -3407,6 +3463,38 @@ gckVGCOMMAND_Commit(
         gctBOOL previousExecuted;
         gctUINT controlIndex;
 
+#ifdef __QNXNTO__
+        /* Map the context into the kernel space. */
+        userContext = Context;
+
+        gcmkERR_BREAK(gckOS_MapUserPointer(
+            Command->os,
+            userContext,
+            gcmSIZEOF(*userContext),
+            &pointer));
+
+        Context = pointer;
+
+        userContextMapped = gcvTRUE;
+
+        /* Map the taskTable into the kernel space. */
+        userTaskTable = TaskTable;
+
+        gcmkERR_BREAK(gckOS_MapUserPointer(
+            Command->os,
+            userTaskTable,
+            gcmSIZEOF(*userTaskTable),
+            &pointer));
+
+        TaskTable = pointer;
+
+        userTaskTableMapped = gcvTRUE;
+
+        /* Update the signal info. */
+        TaskTable->coid  = Context->coid;
+        TaskTable->rcvid = Context->rcvid;
+#endif
+
         gcmkERR_BREAK(gckVGHARDWARE_SetPowerManagementState(
             Command->hardware, gcvPOWER_ON_AUTO
             ));
@@ -3669,6 +3757,28 @@ gckVGCOMMAND_Commit(
     }
     while (gcvFALSE);
 
+#ifdef __QNXNTO__
+    if (userContextMapped)
+    {
+        /* Unmap the user context. */
+        gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+            Command->os,
+            userContext,
+            gcmSIZEOF(*userContext),
+            Context));
+    }
+
+    if (userTaskTableMapped)
+    {
+        /* Unmap the user taskTable. */
+        gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+            Command->os,
+            userTaskTable,
+            gcmSIZEOF(*userTaskTable),
+            TaskTable));
+    }
+#endif
+
     gcmkFOOTER();
     /* Return status. */
     return status;
index b181f55ec55e71039ae8cdd69f003ebdb5a40fc2..021f6338d1ef6ea8f5d53c265c67a176105c375b 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -27,7 +27,7 @@
 ***** Private fuctions ********************************************************/
 
 #define _GetSlot(database, x) \
-    (gctUINT32)(((gcmPTR_TO_UINT64(x) >> 7) % gcmCOUNTOF(database->list)))
+    (gctUINT32)(gcmPTR_TO_UINT64(x) % gcmCOUNTOF(database->list))
 
 /*******************************************************************************
 **  gckKERNEL_NewDatabase
@@ -97,7 +97,11 @@ gckKERNEL_NewDatabase(
                                    gcmSIZEOF(gcsDATABASE),
                                    &pointer));
 
+        gckOS_ZeroMemory(pointer, gcmSIZEOF(gcsDATABASE));
+
         database = pointer;
+
+        gcmkONERROR(gckOS_CreateMutex(Kernel->os, &database->counterMutex));
     }
 
     /* Insert the database into the hash. */
@@ -154,7 +158,7 @@ OnError:
 **          Pointer to a variable receiving the database structure pointer on
 **          success.
 */
-static gceSTATUS
+gceSTATUS
 gckKERNEL_FindDatabase(
     IN gckKERNEL Kernel,
     IN gctUINT32 ProcessID,
@@ -323,6 +327,18 @@ gckKERNEL_DeleteDatabase(
     /* Keep database as the last database. */
     Kernel->db->lastDatabase = Database;
 
+    /* Destory handle db. */
+    gcmkVERIFY_OK(gckKERNEL_DestroyIntegerDatabase(Kernel, Database->handleDatabase));
+    Database->handleDatabase = gcvNULL;
+    gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Database->handleDatabaseMutex));
+    Database->handleDatabaseMutex = gcvNULL;
+
+#if gcdPROCESS_ADDRESS_SPACE
+    /* Destory process MMU. */
+    gcmkVERIFY_OK(gckEVENT_DestroyMmu(Kernel->eventObj, Database->mmu, gcvKERNEL_PIXEL));
+    Database->mmu = gcvNULL;
+#endif
+
     /* Release the database mutex. */
     gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
 
@@ -476,7 +492,6 @@ gckKERNEL_DeleteRecord(
         gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
     acquired = gcvTRUE;
 
-
     /* Scan the database for this record. */
     for (record = Database->list[slot], previous = gcvNULL;
          record != gcvNULL;
@@ -633,7 +648,6 @@ OnError:
     return status;
 }
 
-
 /*******************************************************************************
 ***** Public API **************************************************************/
 
@@ -689,21 +703,43 @@ gckKERNEL_CreateProcessDB(
     database->mapUserMemory.bytes      = 0;
     database->mapUserMemory.maxBytes   = 0;
     database->mapUserMemory.totalBytes = 0;
-    database->vidMemResv.bytes         = 0;
-    database->vidMemResv.maxBytes      = 0;
-    database->vidMemResv.totalBytes    = 0;
-    database->vidMemCont.bytes         = 0;
-    database->vidMemCont.maxBytes      = 0;
-    database->vidMemCont.totalBytes    = 0;
-    database->vidMemVirt.bytes         = 0;
-    database->vidMemVirt.maxBytes      = 0;
-    database->vidMemVirt.totalBytes    = 0;
+    database->virtualCommandBuffer.bytes = 0;
+    database->virtualCommandBuffer.maxBytes = 0;
+    database->virtualCommandBuffer.totalBytes = 0;
 
     for (i = 0; i < gcmCOUNTOF(database->list); i++)
     {
         database->list[i]              = gcvNULL;
     }
 
+    for (i = 0; i < gcvSURF_NUM_TYPES; i++)
+    {
+        database->vidMemType[i].bytes = 0;
+        database->vidMemType[i].maxBytes = 0;
+        database->vidMemType[i].totalBytes = 0;
+    }
+
+    for (i = 0; i < gcvPOOL_NUMBER_OF_POOLS; i++)
+    {
+        database->vidMemPool[i].bytes = 0;
+        database->vidMemPool[i].maxBytes = 0;
+        database->vidMemPool[i].totalBytes = 0;
+    }
+
+    gcmkASSERT(database->handleDatabase == gcvNULL);
+    gcmkONERROR(
+        gckKERNEL_CreateIntegerDatabase(Kernel, &database->handleDatabase));
+
+    gcmkASSERT(database->handleDatabaseMutex == gcvNULL);
+    gcmkONERROR(
+        gckOS_CreateMutex(Kernel->os, &database->handleDatabaseMutex));
+
+#if gcdPROCESS_ADDRESS_SPACE
+    gcmkASSERT(database->mmu == gcvNULL);
+    gcmkONERROR(
+        gckMMU_Construct(Kernel, gcdMMU_SIZE, &database->mmu));
+#endif
+
 #if gcdSECURE_USER
     {
         gctINT slot;
@@ -807,6 +843,8 @@ gckKERNEL_AddProcessDB(
     gcsDATABASE_PTR database;
     gcsDATABASE_RECORD_PTR record = gcvNULL;
     gcsDATABASE_COUNTERS * count;
+    gctUINT32 vidMemType;
+    gcePOOL vidMemPool;
 
     gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x "
                    "Physical=0x%x Size=%lu",
@@ -815,6 +853,12 @@ gckKERNEL_AddProcessDB(
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
 
+    /* Decode type. */
+    vidMemType = (Type & gcdDB_VIDEO_MEMORY_TYPE_MASK) >> gcdDB_VIDEO_MEMORY_TYPE_SHIFT;
+    vidMemPool = (Type & gcdDB_VIDEO_MEMORY_POOL_MASK) >> gcdDB_VIDEO_MEMORY_POOL_SHIFT;
+
+    Type &= gcdDATABASE_TYPE_MASK;
+
     /* Special case the idle record. */
     if (Type == gcvDB_IDLE)
     {
@@ -914,16 +958,8 @@ gckKERNEL_AddProcessDB(
         count = &database->mapUserMemory;
         break;
 
-    case gcvDB_VIDEO_MEMORY_RESERVED:
-        count = &database->vidMemResv;
-        break;
-
-    case gcvDB_VIDEO_MEMORY_CONTIGUOUS:
-        count = &database->vidMemCont;
-        break;
-
-    case gcvDB_VIDEO_MEMORY_VIRTUAL:
-        count = &database->vidMemVirt;
+    case gcvDB_COMMAND_BUFFER:
+        count = &database->virtualCommandBuffer;
         break;
 
     default:
@@ -931,6 +967,8 @@ gckKERNEL_AddProcessDB(
         break;
     }
 
+    gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, database->counterMutex, gcvINFINITE));
+
     if (count != gcvNULL)
     {
         /* Adjust counters. */
@@ -943,6 +981,33 @@ gckKERNEL_AddProcessDB(
         }
     }
 
+    if (Type == gcvDB_VIDEO_MEMORY)
+    {
+        count = &database->vidMemType[vidMemType];
+
+        /* Adjust counters. */
+        count->totalBytes += Size;
+        count->bytes      += Size;
+
+        if (count->bytes > count->maxBytes)
+        {
+            count->maxBytes = count->bytes;
+        }
+
+        count = &database->vidMemPool[vidMemPool];
+
+        /* Adjust counters. */
+        count->totalBytes += Size;
+        count->bytes      += Size;
+
+        if (count->bytes > count->maxBytes)
+        {
+            count->maxBytes = count->bytes;
+        }
+    }
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, database->counterMutex));
+
     /* Success. */
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
@@ -987,6 +1052,8 @@ gckKERNEL_RemoveProcessDB(
     gceSTATUS status;
     gcsDATABASE_PTR database;
     gctSIZE_T bytes = 0;
+    gctUINT32 vidMemType;
+    gcePOOL vidMempool;
 
     gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
                    Kernel, ProcessID, Type, Pointer);
@@ -995,6 +1062,12 @@ gckKERNEL_RemoveProcessDB(
     gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
     gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
 
+    /* Decode type. */
+    vidMemType = (Type & gcdDB_VIDEO_MEMORY_TYPE_MASK) >> gcdDB_VIDEO_MEMORY_TYPE_SHIFT;
+    vidMempool = (Type & gcdDB_VIDEO_MEMORY_POOL_MASK) >> gcdDB_VIDEO_MEMORY_POOL_SHIFT;
+
+    Type &= gcdDATABASE_TYPE_MASK;
+
     /* Find the database. */
     gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
 
@@ -1002,11 +1075,15 @@ gckKERNEL_RemoveProcessDB(
     gcmkONERROR(
         gckKERNEL_DeleteRecord(Kernel, database, Type, Pointer, &bytes));
 
+    gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, database->counterMutex, gcvINFINITE));
+
     /* Update counters. */
     switch (Type)
     {
     case gcvDB_VIDEO_MEMORY:
         database->vidMem.bytes -= bytes;
+        database->vidMemType[vidMemType].bytes -= bytes;
+        database->vidMemPool[vidMempool].bytes -= bytes;
         break;
 
     case gcvDB_NON_PAGED:
@@ -1025,22 +1102,16 @@ gckKERNEL_RemoveProcessDB(
         database->mapUserMemory.bytes -= bytes;
         break;
 
-    case gcvDB_VIDEO_MEMORY_RESERVED:
-        database->vidMemResv.bytes -= bytes;
-        break;
-
-    case gcvDB_VIDEO_MEMORY_CONTIGUOUS:
-        database->vidMemCont.bytes -= bytes;
-        break;
-
-    case gcvDB_VIDEO_MEMORY_VIRTUAL:
-        database->vidMemVirt.bytes -= bytes;
+    case gcvDB_COMMAND_BUFFER:
+        database->virtualCommandBuffer.bytes -= bytes;
         break;
 
     default:
         break;
     }
 
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, database->counterMutex));
+
     /* Success. */
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
@@ -1140,10 +1211,11 @@ gckKERNEL_DestroyProcessDB(
     gceSTATUS status;
     gcsDATABASE_PTR database;
     gcsDATABASE_RECORD_PTR record, next;
-    gctBOOL asynchronous;
+    gctBOOL asynchronous = gcvTRUE;
+    gckVIDMEM_NODE nodeObject;
     gctPHYS_ADDR physical;
-    gcuVIDMEM_NODE_PTR node;
     gckKERNEL kernel = Kernel;
+    gctUINT32 handle;
     gctUINT32 i;
 
     gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
@@ -1198,8 +1270,18 @@ gckKERNEL_DestroyProcessDB(
         switch (record->type)
         {
         case gcvDB_VIDEO_MEMORY:
+            gcmkERR_BREAK(gckVIDMEM_HANDLE_Lookup(record->kernel,
+                                                  ProcessID,
+                                                  gcmPTR2INT32(record->data),
+                                                  &nodeObject));
+
             /* Free the video memory. */
-            status = gckVIDMEM_Free(gcmUINT64_TO_PTR(record->data));
+            gcmkVERIFY_OK(gckVIDMEM_HANDLE_Dereference(record->kernel,
+                                                       ProcessID,
+                                                       gcmPTR2INT32(record->data)));
+
+            gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(record->kernel,
+                                                     nodeObject));
 
             gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                            "DB: VIDEO_MEMORY 0x%x (status=%d)",
@@ -1215,10 +1297,11 @@ gckKERNEL_DestroyProcessDB(
                                             record->data);
 
             /* Free the non paged memory. */
-            status = gckOS_FreeNonPagedMemory(Kernel->os,
-                                              record->bytes,
-                                              physical,
-                                              record->data);
+            status = gckEVENT_FreeNonPagedMemory(Kernel->eventObj,
+                                                 record->bytes,
+                                                 physical,
+                                                 record->data,
+                                                 gcvKERNEL_PIXEL);
             gcmRELEASE_NAME(record->physical);
 
             gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
@@ -1226,7 +1309,6 @@ gckKERNEL_DestroyProcessDB(
                            record->data, record->bytes, status);
             break;
 
-#if gcdVIRTUAL_COMMAND_BUFFER
         case gcvDB_COMMAND_BUFFER:
             /* Free the command buffer. */
             status = gckEVENT_DestroyVirtualCommandBuffer(record->kernel->eventObj,
@@ -1240,7 +1322,6 @@ gckKERNEL_DestroyProcessDB(
                            "DB: COMMAND_BUFFER 0x%x, bytes=%lu (status=%d)",
                            record->data, record->bytes, status);
             break;
-#endif
 
         case gcvDB_CONTIGUOUS:
             physical = gcmNAME_TO_PTR(record->physical);
@@ -1269,7 +1350,7 @@ gckKERNEL_DestroyProcessDB(
 #else
             /* Free the user signal. */
             status = gckOS_DestroyUserSignal(Kernel->os,
-                                             gcmPTR2INT(record->data));
+                                             gcmPTR2INT32(record->data));
 #endif /* USE_NEW_LINUX_SIGNAL */
 
             gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
@@ -1278,25 +1359,62 @@ gckKERNEL_DestroyProcessDB(
             break;
 
         case gcvDB_VIDEO_MEMORY_LOCKED:
-            node = gcmUINT64_TO_PTR(record->data);
+            handle = gcmPTR2INT32(record->data);
+
+            gcmkERR_BREAK(gckVIDMEM_HANDLE_Lookup(record->kernel,
+                                                  ProcessID,
+                                                  handle,
+                                                  &nodeObject));
+
             /* Unlock what we still locked */
             status = gckVIDMEM_Unlock(record->kernel,
-                                      node,
-                                      gcvSURF_TYPE_UNKNOWN,
+                                      nodeObject,
+                                      nodeObject->type,
                                       &asynchronous);
 
-            if (gcmIS_SUCCESS(status) && (gcvTRUE == asynchronous))
+#if gcdENABLE_VG
+            if (record->kernel->core == gcvCORE_VG)
+            {
+                if (gcmIS_SUCCESS(status) && (gcvTRUE == asynchronous))
+                {
+                    /* TODO: we maybe need to schedule a event here */
+                    status = gckVIDMEM_Unlock(record->kernel,
+                                              nodeObject,
+                                              nodeObject->type,
+                                              gcvNULL);
+                }
+
+                gcmkVERIFY_OK(gckVIDMEM_HANDLE_Dereference(record->kernel,
+                                                           ProcessID,
+                                                           handle));
+
+                gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(record->kernel,
+                                                         nodeObject));
+            }
+            else
+#endif
             {
-                /* TODO: we maybe need to schedule a event here */
-                status = gckVIDMEM_Unlock(record->kernel,
-                                          node,
-                                          gcvSURF_TYPE_UNKNOWN,
-                                          gcvNULL);
+                gcmkVERIFY_OK(gckVIDMEM_HANDLE_Dereference(record->kernel,
+                                                           ProcessID,
+                                                           handle));
+
+                if (gcmIS_SUCCESS(status) && (gcvTRUE == asynchronous))
+                {
+                    status = gckEVENT_Unlock(record->kernel->eventObj,
+                                             gcvKERNEL_PIXEL,
+                                             nodeObject,
+                                             nodeObject->type);
+                }
+                else
+                {
+                    gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(record->kernel,
+                                                             nodeObject));
+                }
             }
 
             gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                            "DB: VIDEO_MEMORY_LOCKED 0x%x (status=%d)",
-                           node, status);
+                           record->data, status);
             break;
 
         case gcvDB_CONTEXT:
@@ -1318,7 +1436,7 @@ gckKERNEL_DestroyProcessDB(
 
             gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                            "DB: MAP MEMORY %d (status=%d)",
-                           gcmPTR2INT(record->data), status);
+                           gcmPTR2INT32(record->data), status);
             break;
 
         case gcvDB_MAP_USER_MEMORY:
@@ -1333,11 +1451,7 @@ gckKERNEL_DestroyProcessDB(
 
             gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                            "DB: MAP USER MEMORY %d (status=%d)",
-                           gcmPTR2INT(record->data), status);
-            break;
-
-        case gcvDB_SHARED_INFO:
-            status = gckOS_FreeMemory(Kernel->os, record->physical);
+                           gcmPTR2INT32(record->data), status);
             break;
 
 #if gcdANDROID_NATIVE_FENCE_SYNC
@@ -1352,10 +1466,15 @@ gckKERNEL_DestroyProcessDB(
             break;
 #endif
 
-        case gcvDB_VIDEO_MEMORY_RESERVED:
-        case gcvDB_VIDEO_MEMORY_CONTIGUOUS:
-        case gcvDB_VIDEO_MEMORY_VIRTUAL:
-            break;//Nothing to do
+        case gcvDB_SHBUF:
+            /* Free shared buffer. */
+            status = gckKERNEL_DestroyShBuffer(Kernel,
+                                               (gctSHBUF) record->data);
+
+            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+                           "DB: SHBUF %u (status=%d)",
+                           (gctUINT32)(gctUINTPTR_T) record->data, status);
+            break;
 
         default:
             gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DATABASE,
@@ -1424,6 +1543,7 @@ gckKERNEL_QueryProcessDB(
 {
     gceSTATUS status;
     gcsDATABASE_PTR database;
+    gcePOOL vidMemPool;
 
     gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Info=0x%x",
                    Kernel, ProcessID, Type, Info);
@@ -1432,69 +1552,110 @@ gckKERNEL_QueryProcessDB(
     gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
     gcmkVERIFY_ARGUMENT(Info != gcvNULL);
 
-    /* Find the database. */
-    gcmkONERROR(
-        gckKERNEL_FindDatabase(Kernel, ProcessID, LastProcessID, &database));
+    /* Deocde pool. */
+    vidMemPool = (Type & gcdDB_VIDEO_MEMORY_POOL_MASK) >> gcdDB_VIDEO_MEMORY_POOL_SHIFT;
 
-    /* Get pointer to counters. */
-    switch (Type)
+    Type &= gcdDATABASE_TYPE_MASK;
+
+    /* Find the database. */
+    if(Type != gcvDB_IDLE)
     {
-    case gcvDB_VIDEO_MEMORY:
-        gckOS_MemCopy(&Info->counters,
-                                  &database->vidMem,
-                                  gcmSIZEOF(database->vidMem));
-        break;
+        gcmkONERROR(
+            gckKERNEL_FindDatabase(Kernel, ProcessID, LastProcessID, &database));
 
-    case gcvDB_NON_PAGED:
-        gckOS_MemCopy(&Info->counters,
-                                  &database->nonPaged,
-                                  gcmSIZEOF(database->vidMem));
-        break;
+        gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, database->counterMutex, gcvINFINITE));
 
-    case gcvDB_CONTIGUOUS:
-        gckOS_MemCopy(&Info->counters,
-                                  &database->contiguous,
-                                  gcmSIZEOF(database->vidMem));
-        break;
+        /* Get pointer to counters. */
+        switch (Type)
+        {
+        case gcvDB_VIDEO_MEMORY:
+            if (vidMemPool != gcvPOOL_UNKNOWN)
+            {
+                gckOS_MemCopy(&Info->counters,
+                              &database->vidMemPool[vidMemPool],
+                              gcmSIZEOF(database->vidMemPool[vidMemPool]));
+            }
+            else
+            {
+                gckOS_MemCopy(&Info->counters,
+                              &database->vidMem,
+                              gcmSIZEOF(database->vidMem));
+            }
+            break;
 
-    case gcvDB_IDLE:
+        case gcvDB_NON_PAGED:
+            gckOS_MemCopy(&Info->counters,
+                                      &database->nonPaged,
+                                      gcmSIZEOF(database->vidMem));
+            break;
+
+        case gcvDB_CONTIGUOUS:
+            gckOS_MemCopy(&Info->counters,
+                                      &database->contiguous,
+                                      gcmSIZEOF(database->vidMem));
+            break;
+
+        case gcvDB_MAP_MEMORY:
+            gckOS_MemCopy(&Info->counters,
+                                      &database->mapMemory,
+                                      gcmSIZEOF(database->mapMemory));
+            break;
+
+        case gcvDB_MAP_USER_MEMORY:
+            gckOS_MemCopy(&Info->counters,
+                                      &database->mapUserMemory,
+                                      gcmSIZEOF(database->mapUserMemory));
+            break;
+
+        case gcvDB_COMMAND_BUFFER:
+            gckOS_MemCopy(&Info->counters,
+                                      &database->virtualCommandBuffer,
+                                      gcmSIZEOF(database->virtualCommandBuffer));
+            break;
+
+        default:
+            break;
+        }
+
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, database->counterMutex));
+    }
+    else
+    {
         Info->time           = Kernel->db->idleTime;
         Kernel->db->idleTime = 0;
-        break;
+    }
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
 
-    case gcvDB_MAP_MEMORY:
-        gckOS_MemCopy(&Info->counters,
-                                  &database->mapMemory,
-                                  gcmSIZEOF(database->mapMemory));
-        break;
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
 
-    case gcvDB_MAP_USER_MEMORY:
-        gckOS_MemCopy(&Info->counters,
-                                  &database->mapUserMemory,
-                                  gcmSIZEOF(database->mapUserMemory));
-        break;
+gceSTATUS
+gckKERNEL_FindHandleDatbase(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    OUT gctPOINTER * HandleDatabase,
+    OUT gctPOINTER * HandleDatabaseMutex
+    )
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database;
 
-    case gcvDB_VIDEO_MEMORY_RESERVED:
-        gckOS_MemCopy(&Info->counters,
-                                  &database->vidMemResv,
-                                  gcmSIZEOF(database->vidMemResv));
-        break;
+    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d",
+                   Kernel, ProcessID);
 
-    case gcvDB_VIDEO_MEMORY_CONTIGUOUS:
-        gckOS_MemCopy(&Info->counters,
-                                  &database->vidMemCont,
-                                  gcmSIZEOF(database->vidMemCont));
-        break;
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
 
-    case gcvDB_VIDEO_MEMORY_VIRTUAL:
-        gckOS_MemCopy(&Info->counters,
-                                  &database->vidMemVirt,
-                                  gcmSIZEOF(database->vidMemVirt));
-        break;
+    /* Find the database. */
+    gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
 
-    default:
-        break;
-    }
+    *HandleDatabase = database->handleDatabase;
+    *HandleDatabaseMutex = database->handleDatabaseMutex;
 
     /* Success. */
     gcmkFOOTER_NO();
@@ -1506,6 +1667,30 @@ OnError:
     return status;
 }
 
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+gckKERNEL_GetProcessMMU(
+    IN gckKERNEL Kernel,
+    OUT gckMMU * Mmu
+    )
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database;
+    gctUINT32 processID;
+
+    gcmkONERROR(gckOS_GetProcessID(&processID));
+
+    gcmkONERROR(gckKERNEL_FindDatabase(Kernel, processID, gcvFALSE, &database));
+
+    *Mmu = database->mmu;
+
+    return gcvSTATUS_OK;
+
+OnError:
+    return status;
+}
+#endif
+
 #if gcdSECURE_USER
 /*******************************************************************************
 **  gckKERNEL_GetProcessDBCache
@@ -1602,3 +1787,75 @@ gckKERNEL_DumpProcessDB(
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 }
+
+void
+_DumpCounter(
+    IN gcsDATABASE_COUNTERS * Counter,
+    IN gctCONST_STRING Name
+    )
+{
+    gcmkPRINT("%s:", Name);
+    gcmkPRINT("  Currently allocated : %10lld", Counter->bytes);
+    gcmkPRINT("  Maximum allocated   : %10lld", Counter->maxBytes);
+    gcmkPRINT("  Total allocated     : %10lld", Counter->totalBytes);
+}
+
+gceSTATUS
+gckKERNEL_DumpVidMemUsage(
+    IN gckKERNEL Kernel,
+    IN gctINT32 ProcessID
+    )
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database;
+    gcsDATABASE_COUNTERS * counter;
+    gctUINT32 i = 0;
+
+    static gctCONST_STRING surfaceTypes[] = {
+        "UNKNOWN",
+        "INDEX",
+        "VERTEX",
+        "TEXTURE",
+        "RENDER_TARGET",
+        "DEPTH",
+        "BITMAP",
+        "TILE_STATUS",
+        "IMAGE",
+        "MASK",
+        "SCISSOR",
+        "HIERARCHICAL_DEPTH",
+    };
+
+    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d",
+                   Kernel, ProcessID);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    /* Find the database. */
+    gcmkONERROR(
+        gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+    gcmkPRINT("VidMem Usage (Process %d):", ProcessID);
+
+    /* Get pointer to counters. */
+    counter = &database->vidMem;
+
+    _DumpCounter(counter, "Total Video Memory");
+
+    for (i = 0; i < gcvSURF_NUM_TYPES; i++)
+    {
+        counter = &database->vidMemType[i];
+
+        _DumpCounter(counter, surfaceTypes[i]);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
index a36de6ec7dc0268cd63e0751230829247798ddc7..b2b078e6c66cc2bc6671b765c0b3005a532e54b1 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -138,7 +138,7 @@ static gctUINT32 _debugZones = gcvZONE_NONE;
 
 #define gcmPTRALIGNMENT(Pointer, Alignemnt) \
 ( \
-    gcmALIGN(gcmPTR2INT(Pointer), Alignemnt) - gcmPTR2INT(Pointer) \
+    gcmALIGN(gcmPTR2INT32(Pointer), Alignemnt) - gcmPTR2INT32(Pointer) \
 )
 
 #if gcdALIGNBYSIZE
@@ -146,7 +146,7 @@ static gctUINT32 _debugZones = gcvZONE_NONE;
         (((Offset) & ((Alignment) - 1)) == 0)
 
 #   define gcmkALIGNPTR(Type, Pointer, Alignment) \
-        Pointer = (Type) gcmINT2PTR(gcmALIGN(gcmPTR2INT(Pointer), Alignment))
+        Pointer = (Type) gcmINT2PTR(gcmALIGN(gcmPTR2INT32(Pointer), Alignment))
 #else
 #   define gcmISALIGNED(Offset, Alignment) \
         gcvTRUE
@@ -502,7 +502,7 @@ _DirectPrint(
     gctARGUMENTS arguments;
 
     gcmkARGUMENTS_START(arguments, Message);
-    len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), Message, arguments);
+    len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), Message, &arguments);
     gcmkARGUMENTS_END(arguments);
 
     buffer[len] = '\0';
@@ -1711,7 +1711,7 @@ _Print(
     IN gctUINT ArgumentSize,
     IN gctBOOL CopyMessage,
     IN gctCONST_STRING Message,
-    IN gctARGUMENTS Arguments
+    IN gctARGUMENTS Arguments
     )
 {
     gcsBUFFERED_OUTPUT_PTR outputBuffer;
@@ -1759,14 +1759,14 @@ _Print(
     {
         gcdOUTPUTCOPY(
             outputBuffer, outputBuffer->indent,
-            Message, ArgumentSize, * (gctPOINTER *) &Arguments
+            Message, ArgumentSize, (gctPOINTER) Arguments
             );
     }
     else
     {
         gcdOUTPUTSTRING(
             outputBuffer, outputBuffer->indent,
-            Message, ArgumentSize, * (gctPOINTER *) &Arguments
+            Message, ArgumentSize, ((gctPOINTER) Arguments)
             );
     }
 
@@ -1794,7 +1794,7 @@ extern volatile unsigned g_nQnxInIsrs;
     { \
         gctARGUMENTS __arguments__; \
         gcmkARGUMENTS_START(__arguments__, Message); \
-        _Print(ArgumentSize, CopyMessage, Message, __arguments__); \
+        _Print(ArgumentSize, CopyMessage, Message, &__arguments__); \
         gcmkARGUMENTS_END(__arguments__); \
     } \
     atomic_sub(&g_nQnxInIsrs, 1); \
@@ -1806,7 +1806,7 @@ extern volatile unsigned g_nQnxInIsrs;
 { \
     gctARGUMENTS __arguments__; \
     gcmkARGUMENTS_START(__arguments__, Message); \
-    _Print(ArgumentSize, CopyMessage, Message, __arguments__); \
+    _Print(ArgumentSize, CopyMessage, Message, &__arguments__); \
     gcmkARGUMENTS_END(__arguments__); \
 }
 
@@ -1940,10 +1940,10 @@ gckOS_DumpBuffer(
     IN gctBOOL CopyMessage
     )
 {
-    gctUINT32 address;
-    gcsBUFFERED_OUTPUT_PTR outputBuffer;
+    gctUINT32 address                   = 0;
+    gcsBUFFERED_OUTPUT_PTR outputBuffer = gcvNULL;
     static gctBOOL userLocked;
-    gctCHAR *buffer = (gctCHAR*)Buffer;
+    gctCHAR *buffer                     = (gctCHAR*)Buffer;
 
     gcmkDECLARE_LOCK(lockHandle);
 
@@ -2441,119 +2441,345 @@ gckOS_DebugFlush(
 }
 gctCONST_STRING
 gckOS_DebugStatus2Name(
-       gceSTATUS status
-       )
+    gceSTATUS status
+    )
 {
-       switch (status)
-       {
-       case gcvSTATUS_OK:
-               return "gcvSTATUS_OK";
-       case gcvSTATUS_TRUE:
-               return "gcvSTATUS_TRUE";
-       case gcvSTATUS_NO_MORE_DATA:
-               return "gcvSTATUS_NO_MORE_DATA";
-       case gcvSTATUS_CACHED:
-               return "gcvSTATUS_CACHED";
-       case gcvSTATUS_MIPMAP_TOO_LARGE:
-               return "gcvSTATUS_MIPMAP_TOO_LARGE";
-       case gcvSTATUS_NAME_NOT_FOUND:
-               return "gcvSTATUS_NAME_NOT_FOUND";
-       case gcvSTATUS_NOT_OUR_INTERRUPT:
-               return "gcvSTATUS_NOT_OUR_INTERRUPT";
-       case gcvSTATUS_MISMATCH:
-               return "gcvSTATUS_MISMATCH";
-       case gcvSTATUS_MIPMAP_TOO_SMALL:
-               return "gcvSTATUS_MIPMAP_TOO_SMALL";
-       case gcvSTATUS_LARGER:
-               return "gcvSTATUS_LARGER";
-       case gcvSTATUS_SMALLER:
-               return "gcvSTATUS_SMALLER";
-       case gcvSTATUS_CHIP_NOT_READY:
-               return "gcvSTATUS_CHIP_NOT_READY";
-       case gcvSTATUS_NEED_CONVERSION:
-               return "gcvSTATUS_NEED_CONVERSION";
-       case gcvSTATUS_SKIP:
-               return "gcvSTATUS_SKIP";
-       case gcvSTATUS_DATA_TOO_LARGE:
-               return "gcvSTATUS_DATA_TOO_LARGE";
-       case gcvSTATUS_INVALID_CONFIG:
-               return "gcvSTATUS_INVALID_CONFIG";
-       case gcvSTATUS_CHANGED:
-               return "gcvSTATUS_CHANGED";
-       case gcvSTATUS_NOT_SUPPORT_DITHER:
-               return "gcvSTATUS_NOT_SUPPORT_DITHER";
-
-       case gcvSTATUS_INVALID_ARGUMENT:
-               return "gcvSTATUS_INVALID_ARGUMENT";
-       case gcvSTATUS_INVALID_OBJECT:
-               return "gcvSTATUS_INVALID_OBJECT";
-       case gcvSTATUS_OUT_OF_MEMORY:
-               return "gcvSTATUS_OUT_OF_MEMORY";
-       case gcvSTATUS_MEMORY_LOCKED:
-               return "gcvSTATUS_MEMORY_LOCKED";
-       case gcvSTATUS_MEMORY_UNLOCKED:
-               return "gcvSTATUS_MEMORY_UNLOCKED";
-       case gcvSTATUS_HEAP_CORRUPTED:
-               return "gcvSTATUS_HEAP_CORRUPTED";
-       case gcvSTATUS_GENERIC_IO:
-               return "gcvSTATUS_GENERIC_IO";
-       case gcvSTATUS_INVALID_ADDRESS:
-               return "gcvSTATUS_INVALID_ADDRESS";
-       case gcvSTATUS_CONTEXT_LOSSED:
-               return "gcvSTATUS_CONTEXT_LOSSED";
-       case gcvSTATUS_TOO_COMPLEX:
-               return "gcvSTATUS_TOO_COMPLEX";
-       case gcvSTATUS_BUFFER_TOO_SMALL:
-               return "gcvSTATUS_BUFFER_TOO_SMALL";
-       case gcvSTATUS_INTERFACE_ERROR:
-               return "gcvSTATUS_INTERFACE_ERROR";
-       case gcvSTATUS_NOT_SUPPORTED:
-               return "gcvSTATUS_NOT_SUPPORTED";
-       case gcvSTATUS_MORE_DATA:
-               return "gcvSTATUS_MORE_DATA";
-       case gcvSTATUS_TIMEOUT:
-               return "gcvSTATUS_TIMEOUT";
-       case gcvSTATUS_OUT_OF_RESOURCES:
-               return "gcvSTATUS_OUT_OF_RESOURCES";
-       case gcvSTATUS_INVALID_DATA:
-               return "gcvSTATUS_INVALID_DATA";
-       case gcvSTATUS_INVALID_MIPMAP:
-               return "gcvSTATUS_INVALID_MIPMAP";
-       case gcvSTATUS_NOT_FOUND:
-               return "gcvSTATUS_NOT_FOUND";
-       case gcvSTATUS_NOT_ALIGNED:
-               return "gcvSTATUS_NOT_ALIGNED";
-       case gcvSTATUS_INVALID_REQUEST:
-               return "gcvSTATUS_INVALID_REQUEST";
-       case gcvSTATUS_GPU_NOT_RESPONDING:
-               return "gcvSTATUS_GPU_NOT_RESPONDING";
-       case gcvSTATUS_TIMER_OVERFLOW:
-               return "gcvSTATUS_TIMER_OVERFLOW";
-       case gcvSTATUS_VERSION_MISMATCH:
-               return "gcvSTATUS_VERSION_MISMATCH";
-       case gcvSTATUS_LOCKED:
-               return "gcvSTATUS_LOCKED";
+    switch (status)
+    {
+    case gcvSTATUS_OK:
+        return "gcvSTATUS_OK";
+    case gcvSTATUS_TRUE:
+        return "gcvSTATUS_TRUE";
+    case gcvSTATUS_NO_MORE_DATA:
+        return "gcvSTATUS_NO_MORE_DATA";
+    case gcvSTATUS_CACHED:
+        return "gcvSTATUS_CACHED";
+    case gcvSTATUS_MIPMAP_TOO_LARGE:
+        return "gcvSTATUS_MIPMAP_TOO_LARGE";
+    case gcvSTATUS_NAME_NOT_FOUND:
+        return "gcvSTATUS_NAME_NOT_FOUND";
+    case gcvSTATUS_NOT_OUR_INTERRUPT:
+        return "gcvSTATUS_NOT_OUR_INTERRUPT";
+    case gcvSTATUS_MISMATCH:
+        return "gcvSTATUS_MISMATCH";
+    case gcvSTATUS_MIPMAP_TOO_SMALL:
+        return "gcvSTATUS_MIPMAP_TOO_SMALL";
+    case gcvSTATUS_LARGER:
+        return "gcvSTATUS_LARGER";
+    case gcvSTATUS_SMALLER:
+        return "gcvSTATUS_SMALLER";
+    case gcvSTATUS_CHIP_NOT_READY:
+        return "gcvSTATUS_CHIP_NOT_READY";
+    case gcvSTATUS_NEED_CONVERSION:
+        return "gcvSTATUS_NEED_CONVERSION";
+    case gcvSTATUS_SKIP:
+        return "gcvSTATUS_SKIP";
+    case gcvSTATUS_DATA_TOO_LARGE:
+        return "gcvSTATUS_DATA_TOO_LARGE";
+    case gcvSTATUS_INVALID_CONFIG:
+        return "gcvSTATUS_INVALID_CONFIG";
+    case gcvSTATUS_CHANGED:
+        return "gcvSTATUS_CHANGED";
+    case gcvSTATUS_NOT_SUPPORT_DITHER:
+        return "gcvSTATUS_NOT_SUPPORT_DITHER";
+
+    case gcvSTATUS_INVALID_ARGUMENT:
+        return "gcvSTATUS_INVALID_ARGUMENT";
+    case gcvSTATUS_INVALID_OBJECT:
+        return "gcvSTATUS_INVALID_OBJECT";
+    case gcvSTATUS_OUT_OF_MEMORY:
+        return "gcvSTATUS_OUT_OF_MEMORY";
+    case gcvSTATUS_MEMORY_LOCKED:
+        return "gcvSTATUS_MEMORY_LOCKED";
+    case gcvSTATUS_MEMORY_UNLOCKED:
+        return "gcvSTATUS_MEMORY_UNLOCKED";
+    case gcvSTATUS_HEAP_CORRUPTED:
+        return "gcvSTATUS_HEAP_CORRUPTED";
+    case gcvSTATUS_GENERIC_IO:
+        return "gcvSTATUS_GENERIC_IO";
+    case gcvSTATUS_INVALID_ADDRESS:
+        return "gcvSTATUS_INVALID_ADDRESS";
+    case gcvSTATUS_CONTEXT_LOSSED:
+        return "gcvSTATUS_CONTEXT_LOSSED";
+    case gcvSTATUS_TOO_COMPLEX:
+        return "gcvSTATUS_TOO_COMPLEX";
+    case gcvSTATUS_BUFFER_TOO_SMALL:
+        return "gcvSTATUS_BUFFER_TOO_SMALL";
+    case gcvSTATUS_INTERFACE_ERROR:
+        return "gcvSTATUS_INTERFACE_ERROR";
+    case gcvSTATUS_NOT_SUPPORTED:
+        return "gcvSTATUS_NOT_SUPPORTED";
+    case gcvSTATUS_MORE_DATA:
+        return "gcvSTATUS_MORE_DATA";
+    case gcvSTATUS_TIMEOUT:
+        return "gcvSTATUS_TIMEOUT";
+    case gcvSTATUS_OUT_OF_RESOURCES:
+        return "gcvSTATUS_OUT_OF_RESOURCES";
+    case gcvSTATUS_INVALID_DATA:
+        return "gcvSTATUS_INVALID_DATA";
+    case gcvSTATUS_INVALID_MIPMAP:
+        return "gcvSTATUS_INVALID_MIPMAP";
+    case gcvSTATUS_NOT_FOUND:
+        return "gcvSTATUS_NOT_FOUND";
+    case gcvSTATUS_NOT_ALIGNED:
+        return "gcvSTATUS_NOT_ALIGNED";
+    case gcvSTATUS_INVALID_REQUEST:
+        return "gcvSTATUS_INVALID_REQUEST";
+    case gcvSTATUS_GPU_NOT_RESPONDING:
+        return "gcvSTATUS_GPU_NOT_RESPONDING";
+    case gcvSTATUS_TIMER_OVERFLOW:
+        return "gcvSTATUS_TIMER_OVERFLOW";
+    case gcvSTATUS_VERSION_MISMATCH:
+        return "gcvSTATUS_VERSION_MISMATCH";
+    case gcvSTATUS_LOCKED:
+        return "gcvSTATUS_LOCKED";
+    case gcvSTATUS_INTERRUPTED:
+        return "gcvSTATUS_INTERRUPTED";
+    case gcvSTATUS_DEVICE:
+        return "gcvSTATUS_DEVICE";
+    case gcvSTATUS_NOT_MULTI_PIPE_ALIGNED:
+        return "gcvSTATUS_NOT_MULTI_PIPE_ALIGNED";
 
     /* Linker errors. */
-       case gcvSTATUS_GLOBAL_TYPE_MISMATCH:
-               return "gcvSTATUS_GLOBAL_TYPE_MISMATCH";
-       case gcvSTATUS_TOO_MANY_ATTRIBUTES:
-               return "gcvSTATUS_TOO_MANY_ATTRIBUTES";
-       case gcvSTATUS_TOO_MANY_UNIFORMS:
-               return "gcvSTATUS_TOO_MANY_UNIFORMS";
-       case gcvSTATUS_TOO_MANY_VARYINGS:
-               return "gcvSTATUS_TOO_MANY_VARYINGS";
-       case gcvSTATUS_UNDECLARED_VARYING:
-               return "gcvSTATUS_UNDECLARED_VARYING";
-       case gcvSTATUS_VARYING_TYPE_MISMATCH:
-               return "gcvSTATUS_VARYING_TYPE_MISMATCH";
-       case gcvSTATUS_MISSING_MAIN:
-               return "gcvSTATUS_MISSING_MAIN";
-       case gcvSTATUS_NAME_MISMATCH:
-               return "gcvSTATUS_NAME_MISMATCH";
-       case gcvSTATUS_INVALID_INDEX:
-               return "gcvSTATUS_INVALID_INDEX";
-       default:
-               return "nil";
-       }
+    case gcvSTATUS_GLOBAL_TYPE_MISMATCH:
+        return "gcvSTATUS_GLOBAL_TYPE_MISMATCH";
+    case gcvSTATUS_TOO_MANY_ATTRIBUTES:
+        return "gcvSTATUS_TOO_MANY_ATTRIBUTES";
+    case gcvSTATUS_TOO_MANY_UNIFORMS:
+        return "gcvSTATUS_TOO_MANY_UNIFORMS";
+    case gcvSTATUS_TOO_MANY_SAMPLER:
+        return "gcvSTATUS_TOO_MANY_SAMPLER";
+    case gcvSTATUS_TOO_MANY_VARYINGS:
+        return "gcvSTATUS_TOO_MANY_VARYINGS";
+    case gcvSTATUS_UNDECLARED_VARYING:
+        return "gcvSTATUS_UNDECLARED_VARYING";
+    case gcvSTATUS_VARYING_TYPE_MISMATCH:
+        return "gcvSTATUS_VARYING_TYPE_MISMATCH";
+    case gcvSTATUS_MISSING_MAIN:
+        return "gcvSTATUS_MISSING_MAIN";
+    case gcvSTATUS_NAME_MISMATCH:
+        return "gcvSTATUS_NAME_MISMATCH";
+    case gcvSTATUS_INVALID_INDEX:
+        return "gcvSTATUS_INVALID_INDEX";
+    case gcvSTATUS_UNIFORM_MISMATCH:
+        return "gcvSTATUS_UNIFORM_MISMATCH";
+    case gcvSTATUS_UNSAT_LIB_SYMBOL:
+        return "gcvSTATUS_UNSAT_LIB_SYMBOL";
+    case gcvSTATUS_TOO_MANY_SHADERS:
+        return "gcvSTATUS_TOO_MANY_SHADERS";
+    case gcvSTATUS_LINK_INVALID_SHADERS:
+        return "gcvSTATUS_LINK_INVALID_SHADERS";
+    case gcvSTATUS_CS_NO_WORKGROUP_SIZE:
+        return "gcvSTATUS_CS_NO_WORKGROUP_SIZE";
+    case gcvSTATUS_LINK_LIB_ERROR:
+        return "gcvSTATUS_LINK_LIB_ERROR";
+    case gcvSTATUS_SHADER_VERSION_MISMATCH:
+        return "gcvSTATUS_SHADER_VERSION_MISMATCH";
+    case gcvSTATUS_TOO_MANY_INSTRUCTION:
+        return "gcvSTATUS_TOO_MANY_INSTRUCTION";
+    case gcvSTATUS_SSBO_MISMATCH:
+        return "gcvSTATUS_SSBO_MISMATCH";
+    case gcvSTATUS_TOO_MANY_OUTPUT:
+        return "gcvSTATUS_TOO_MANY_OUTPUT";
+    case gcvSTATUS_TOO_MANY_INPUT:
+        return "gcvSTATUS_TOO_MANY_INPUT";
+    case gcvSTATUS_NOT_SUPPORT_CL:
+        return "gcvSTATUS_NOT_SUPPORT_CL";
+    case gcvSTATUS_NOT_SUPPORT_INTEGER:
+        return "gcvSTATUS_NOT_SUPPORT_INTEGER";
+
+    /* Compiler errors. */
+    case gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR:
+        return "gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR";
+    case gcvSTATUS_COMPILER_FE_PARSER_ERROR:
+        return "gcvSTATUS_COMPILER_FE_PARSER_ERROR";
+
+    default:
+        return "nil";
+    }
 }
+
+/*******************************************************************************
+***** Binary Trace *************************************************************
+*******************************************************************************/
+
+/*******************************************************************************
+**  _VerifyMessage
+**
+**  Verify a binary trace message, decode it to human readable string and print
+**  it.
+**
+**  ARGUMENTS:
+**
+**      gctCONST_STRING Buffer
+**          Pointer to buffer to store.
+**
+**      gctSIZE_T Bytes
+**          Buffer length.
+*/
+void
+_VerifyMessage(
+    IN gctCONST_STRING Buffer,
+    IN gctSIZE_T Bytes
+    )
+{
+    char arguments[150] = {0};
+    char format[100] = {0};
+
+    gctSTRING function;
+    gctPOINTER args;
+    gctUINT32 numArguments;
+    int i = 0;
+    gctUINT32 functionBytes;
+
+    gcsBINARY_TRACE_MESSAGE_PTR message = (gcsBINARY_TRACE_MESSAGE_PTR)Buffer;
+
+    /* Check signature. */
+    if (message->signature != 0x7FFFFFFF)
+    {
+        gcmkPRINT("Signature error");
+        return;
+    }
+
+    /* Get function name. */
+    function = (gctSTRING)&message->payload;
+    functionBytes = (gctUINT32)strlen(function) + 1;
+
+    /* Get arguments number. */
+    numArguments = message->numArguments;
+
+    /* Get arguments . */
+    args = function + functionBytes;
+
+    /* Prepare format string. */
+    while (numArguments--)
+    {
+        format[i++] = '%';
+        format[i++] = 'x';
+        format[i++] = ' ';
+    }
+
+    format[i] = '\0';
+
+    if (numArguments)
+    {
+        gcmkVSPRINTF(arguments, 150, format, (gctARGUMENTS *) &args);
+    }
+
+    gcmkPRINT("[%d](%d): %s(%d) %s",
+             message->pid,
+             message->tid,
+             function,
+             message->line,
+             arguments);
+}
+
+
+/*******************************************************************************
+**  gckOS_WriteToRingBuffer
+**
+**  Store a buffer to ring buffer.
+**
+**  ARGUMENTS:
+**
+**      gctCONST_STRING Buffer
+**          Pointer to buffer to store.
+**
+**      gctSIZE_T Bytes
+**          Buffer length.
+*/
+void
+gckOS_WriteToRingBuffer(
+    IN gctCONST_STRING Buffer,
+    IN gctSIZE_T Bytes
+    )
+{
+
+}
+
+/*******************************************************************************
+**  gckOS_BinaryTrace
+**
+**  Output a binary trace message.
+**
+**  ARGUMENTS:
+**
+**      gctCONST_STRING Function
+**          Pointer to function name.
+**
+**      gctINT Line
+**          Line number.
+**
+**      gctCONST_STRING Text OPTIONAL
+**          Optional pointer to a descriptive text.
+**
+**      ...
+**          Optional arguments to the descriptive text.
+*/
+void
+gckOS_BinaryTrace(
+    IN gctCONST_STRING Function,
+    IN gctINT Line,
+    IN gctCONST_STRING Text OPTIONAL,
+    ...
+    )
+{
+    static gctUINT32 messageSignature = 0x7FFFFFFF;
+    char buffer[gcdBINARY_TRACE_MESSAGE_SIZE];
+    gctUINT32 numArguments = 0;
+    gctUINT32 functionBytes;
+    gctUINT32 i = 0;
+    gctSTRING payload;
+    gcsBINARY_TRACE_MESSAGE_PTR message = (gcsBINARY_TRACE_MESSAGE_PTR)buffer;
+
+    /* Calculate arguments number. */
+    if (Text)
+    {
+        while (Text[i] != '\0')
+        {
+            if (Text[i] == '%')
+            {
+                numArguments++;
+            }
+            i++;
+        }
+    }
+
+    message->signature    = messageSignature;
+    message->pid          = gcmkGETPROCESSID();
+    message->tid          = gcmkGETTHREADID();
+    message->line         = Line;
+    message->numArguments = numArguments;
+
+    payload = (gctSTRING)&message->payload;
+
+    /* Function name. */
+    functionBytes = (gctUINT32)gcmkSTRLEN(Function) + 1;
+    gcmkMEMCPY(payload, Function, functionBytes);
+
+    /* Advance to next payload. */
+    payload += functionBytes;
+
+    /* Arguments value. */
+    if (numArguments)
+    {
+        gctARGUMENTS p;
+        gcmkARGUMENTS_START(p, Text);
+
+        for (i = 0; i < numArguments; ++i)
+        {
+            gctPOINTER value = gcmkARGUMENTS_ARG(p, gctPOINTER);
+            gcmkMEMCPY(payload, &value, gcmSIZEOF(gctPOINTER));
+            payload += gcmSIZEOF(gctPOINTER);
+        }
+
+        gcmkARGUMENTS_END(p);
+    }
+
+    gcmkASSERT(payload - buffer <= gcdBINARY_TRACE_MESSAGE_SIZE);
+
+
+    /* Send buffer to ring buffer. */
+    gckOS_WriteToRingBuffer(buffer, (gctUINT32)(payload - buffer));
+}
+
index 01f71d8e4176e0c2bfe96d6180bf99f70602dfee..1c6300787fad90f87d8d37eb75b885dd89022a1f 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -249,7 +249,6 @@ OnError:
     if (powerLocked)
     {
         gcmkONERROR(gckOS_ReleaseMutex(hardware->os, hardware->powerMutex));
-        powerLocked = gcvFALSE;
     }
 
     gcmkFOOTER();
@@ -300,41 +299,6 @@ __RemoveRecordFromProcessDB(
                 gcmUINT64_TO_PTR(Record->info.u.FreeContiguousMemory.logical)));
             break;
 
-        case gcvHAL_FREE_VIDEO_MEMORY:
-            gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
-                Event->kernel,
-                Record->processID,
-                gcvDB_VIDEO_MEMORY,
-                gcmUINT64_TO_PTR(Record->info.u.FreeVideoMemory.node)));
-
-            {
-                gcuVIDMEM_NODE_PTR node = (gcuVIDMEM_NODE_PTR)(gcmUINT64_TO_PTR(Record->info.u.FreeVideoMemory.node));
-
-                if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
-                {
-                     gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(Event->kernel,
-                                      Record->processID,
-                                      gcvDB_VIDEO_MEMORY_RESERVED,
-                                      node));
-                }
-                else if(node->Virtual.contiguous)
-                {
-                    gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(Event->kernel,
-                                      Record->processID,
-                                      gcvDB_VIDEO_MEMORY_CONTIGUOUS,
-                                      node));
-                }
-                else
-                {
-                    gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(Event->kernel,
-                                      Record->processID,
-                                      gcvDB_VIDEO_MEMORY_VIRTUAL,
-                                      node));
-                }
-            }
-
-            break;
-
         case gcvHAL_UNLOCK_VIDEO_MEMORY:
             gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
                 Event->kernel,
@@ -369,13 +333,112 @@ __RemoveRecordFromProcessDB(
     return gcvSTATUS_OK;
 }
 
+gceSTATUS
+_ReleaseVideoMemoryHandle(
+    IN gckKERNEL Kernel,
+    IN OUT gcsEVENT_PTR Record,
+    IN OUT gcsHAL_INTERFACE * Interface
+    )
+{
+    gceSTATUS status;
+    gckVIDMEM_NODE nodeObject;
+    gctUINT32 handle;
+
+    switch(Interface->command)
+    {
+    case gcvHAL_UNLOCK_VIDEO_MEMORY:
+        handle = (gctUINT32)Interface->u.UnlockVideoMemory.node;
+
+        gcmkONERROR(gckVIDMEM_HANDLE_Lookup(
+            Kernel, Record->processID, handle, &nodeObject));
+
+        Record->info.u.UnlockVideoMemory.node = gcmPTR_TO_UINT64(nodeObject);
+
+        gckVIDMEM_HANDLE_Dereference(Kernel, Record->processID, handle);
+        break;
+
+    default:
+        break;
+    }
+
+    return gcvSTATUS_OK;
+OnError:
+    return status;
+}
+
+/*******************************************************************************
+**
+**  _QueryFlush
+**
+**  Check the type of surfaces which will be released by current event and
+**  determine the cache needed to flush.
+**
+*/
+static gceSTATUS
+_QueryFlush(
+    IN gckEVENT Event,
+    IN gcsEVENT_PTR Record,
+    OUT gceKERNEL_FLUSH *Flush
+    )
+{
+    gceKERNEL_FLUSH flush = 0;
+    gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
+    gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+    while (Record != gcvNULL)
+    {
+        switch (Record->info.command)
+        {
+        case gcvHAL_UNLOCK_VIDEO_MEMORY:
+            switch(Record->info.u.UnlockVideoMemory.type)
+            {
+            case gcvSURF_TILE_STATUS:
+                flush |= gcvFLUSH_TILE_STATUS;
+                break;
+            case gcvSURF_RENDER_TARGET:
+                flush |= gcvFLUSH_COLOR;
+                break;
+            case gcvSURF_DEPTH:
+                flush |= gcvFLUSH_DEPTH;
+                break;
+            case gcvSURF_TEXTURE:
+                flush |= gcvFLUSH_TEXTURE;
+                break;
+            case gcvSURF_TYPE_UNKNOWN:
+                gcmkASSERT(0);
+                break;
+            default:
+                break;
+            }
+            break;
+        case gcvHAL_UNMAP_USER_MEMORY:
+            *Flush = gcvFLUSH_ALL;
+            return gcvSTATUS_OK;
+
+        default:
+            break;
+        }
+
+        Record = Record->next;
+    }
+
+    *Flush = flush;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
 void
 _SubmitTimerFunction(
     gctPOINTER Data
     )
 {
     gckEVENT event = (gckEVENT)Data;
+#if gcdMULTI_GPU
+    gcmkVERIFY_OK(gckEVENT_Submit(event, gcvTRUE, gcvFALSE, gcvCORE_3D_ALL_MASK));
+#else
     gcmkVERIFY_OK(gckEVENT_Submit(event, gcvTRUE, gcvFALSE));
+#endif
 }
 
 /******************************************************************************\
@@ -468,6 +531,17 @@ gckEVENT_Construct(
 
 #if gcdSMP
     gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->pending));
+
+#if gcdMULTI_GPU
+    for (i = 0; i < gcdMULTI_GPU; i++)
+    {
+        gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->pending3D[i]));
+        gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->pending3DMask[i]));
+    }
+
+    gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->pendingMask));
+#endif
+
 #endif
 
     gcmkVERIFY_OK(gckOS_CreateTimer(os,
@@ -475,6 +549,11 @@ gckEVENT_Construct(
                                     (gctPOINTER)eventObj,
                                     &eventObj->submitTimer));
 
+#if gcdINTERRUPT_STATISTIC
+    gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->interruptCount));
+    gcmkONERROR(gckOS_AtomSet(os,eventObj->interruptCount, 0));
+#endif
+
     /* Return pointer to the gckEVENT object. */
     *Event = eventObj;
 
@@ -519,6 +598,28 @@ OnError:
         {
             gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->pending));
         }
+
+#if gcdMULTI_GPU
+        for (i = 0; i < gcdMULTI_GPU; i++)
+        {
+            if (eventObj->pending3D[i] != gcvNULL)
+            {
+                gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->pending3D[i]));
+            }
+
+            if (eventObj->pending3DMask[i] != gcvNULL)
+            {
+                gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->pending3DMask[i]));
+            }
+        }
+#endif
+#endif
+
+#if gcdINTERRUPT_STATISTIC
+        if (eventObj->interruptCount)
+        {
+            gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->interruptCount));
+        }
 #endif
         gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, eventObj));
     }
@@ -622,6 +723,21 @@ gckEVENT_Destroy(
 
 #if gcdSMP
     gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->pending));
+
+#if gcdMULTI_GPU
+    {
+        gctINT i;
+        for (i = 0; i < gcdMULTI_GPU; i++)
+        {
+            gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->pending3D[i]));
+            gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->pending3DMask[i]));
+        }
+    }
+#endif
+#endif
+
+#if gcdINTERRUPT_STATISTIC
+    gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->interruptCount));
 #endif
 
     /* Mark the gckEVENT object as unknown. */
@@ -658,6 +774,18 @@ gckEVENT_Destroy(
 **      gctUINT8 * EventID
 **          Reserved event ID.
 */
+#define gcdINVALID_EVENT_PTR    ((gcsEVENT_PTR)gcvMAXUINTPTR_T)
+
+#if gcdMULTI_GPU
+gceSTATUS
+gckEVENT_GetEvent(
+    IN gckEVENT Event,
+    IN gctBOOL Wait,
+    OUT gctUINT8 * EventID,
+    IN gceKERNEL_WHERE Source,
+    IN gceCORE_3D_MASK ChipEnable
+    )
+#else
 gceSTATUS
 gckEVENT_GetEvent(
     IN gckEVENT Event,
@@ -665,14 +793,14 @@ gckEVENT_GetEvent(
     OUT gctUINT8 * EventID,
     IN gceKERNEL_WHERE Source
     )
+#endif
 {
     gctINT i, id;
     gceSTATUS status;
     gctBOOL acquired = gcvFALSE;
     gctINT32 free;
-
-#if gcdGPU_TIMEOUT
-    gctUINT32 timer = 0;
+#if gcdMULTI_GPU
+    gctINT j;
 #endif
 
     gcmkHEADER_ARG("Event=0x%x Source=%d", Event, Source);
@@ -699,9 +827,34 @@ gckEVENT_GetEvent(
                 Event->lastID = (gctUINT8) nextID;
 
                 /* Save time stamp of event. */
+                Event->queues[id].head   = gcdINVALID_EVENT_PTR;
                 Event->queues[id].stamp  = ++(Event->stamp);
                 Event->queues[id].source = Source;
 
+#if gcdMULTI_GPU
+                Event->queues[id].chipEnable = ChipEnable;
+
+                if (ChipEnable == gcvCORE_3D_ALL_MASK)
+                {
+                    gckOS_AtomSetMask(Event->pendingMask, (1 << id));
+
+                    for (j = 0; j < gcdMULTI_GPU; j++)
+                    {
+                        gckOS_AtomSetMask(Event->pending3DMask[j], (1 << id));
+                    }
+                }
+                else
+                {
+                    for (j = 0; j < gcdMULTI_GPU; j++)
+                    {
+                        if (ChipEnable & (1 << j))
+                        {
+                            gckOS_AtomSetMask(Event->pending3DMask[j], (1 << id));
+                        }
+                    }
+                }
+#endif
+
                 gcmkONERROR(gckOS_AtomDecrement(Event->os,
                                                 Event->freeAtom,
                                                 &free));
@@ -754,30 +907,6 @@ gckEVENT_GetEvent(
 
         /* Delay a while. */
         gcmkONERROR(gckOS_Delay(Event->os, 1));
-
-#if gcdGPU_TIMEOUT
-        /* Increment the wait timer. */
-        timer += 1;
-
-        if (timer == Event->kernel->timeOut)
-        {
-            /* Try to call any outstanding events. */
-            gcmkONERROR(gckHARDWARE_Interrupt(Event->kernel->hardware,
-                                              gcvTRUE));
-        }
-        else if (timer > Event->kernel->timeOut)
-        {
-            gcmkTRACE_N(
-                gcvLEVEL_ERROR,
-                gcmSIZEOF(gctCONST_STRING) + gcmSIZEOF(gctINT),
-                "%s(%d): no available events\n",
-                __FUNCTION__, __LINE__
-                );
-
-            /* Bail out. */
-            gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
-        }
-#endif
     }
 
 OnError:
@@ -861,7 +990,6 @@ gckEVENT_AllocateRecord(
 
     /* Release the mutex. */
     gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
-    acquired = gcvFALSE;
 
     /* Success. */
     gcmkFOOTER_ARG("*Record=0x%x", gcmOPT_POINTER(Record));
@@ -916,6 +1044,7 @@ gckEVENT_AddList(
     gctBOOL acquired = gcvFALSE;
     gcsEVENT_PTR record = gcvNULL;
     gcsEVENT_QUEUE_PTR queue;
+    gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
     gckKERNEL kernel = Event->kernel;
 
     gcmkHEADER_ARG("Event=0x%x Interface=0x%x",
@@ -933,7 +1062,6 @@ gckEVENT_AddList(
     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)
@@ -942,6 +1070,7 @@ gckEVENT_AddList(
         || (Interface->command == gcvHAL_COMMIT_DONE)
         || (Interface->command == gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER)
         || (Interface->command == gcvHAL_SYNC_POINT)
+        || (Interface->command == gcvHAL_DESTROY_MMU)
         );
 
     /* Validate the source. */
@@ -966,12 +1095,25 @@ gckEVENT_AddList(
     /* Get process ID. */
     gcmkONERROR(gckOS_GetProcessID(&record->processID));
 
+    gcmkONERROR(__RemoveRecordFromProcessDB(Event, record));
+
+    /* Handle is belonged to current process, it must be released now. */
+    if (FromKernel == gcvFALSE)
+    {
+        status = _ReleaseVideoMemoryHandle(Event->kernel, record, Interface);
+
+        if (gcmIS_ERROR(status))
+        {
+            /* Ingore error because there are other events in the queue. */
+            status = gcvSTATUS_OK;
+            goto OnError;
+        }
+    }
+
 #ifdef __QNXNTO__
     record->kernel = Event->kernel;
 #endif
 
-    gcmkONERROR(__RemoveRecordFromProcessDB(Event, record));
-
     /* Acquire the mutex. */
     gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->eventListMutex, gcvINFINITE));
     acquired = gcvTRUE;
@@ -1036,11 +1178,23 @@ gckEVENT_AddList(
                         (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes,
                         gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical)));
         break;
+
+    case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
+        buffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)gcmNAME_TO_PTR(Interface->u.FreeVirtualCommandBuffer.physical);
+        if (buffer->userLogical)
+        {
+            gcmkONERROR(gckOS_DestroyUserVirtualMapping(
+                            Event->os,
+                            buffer->physical,
+                            (gctSIZE_T) Interface->u.FreeVirtualCommandBuffer.bytes,
+                            gcmUINT64_TO_PTR(Interface->u.FreeVirtualCommandBuffer.logical)));
+        }
+        break;
+
     default:
         break;
     }
 
-
     /* Release the mutex. */
     gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
 
@@ -1094,7 +1248,7 @@ gceSTATUS
 gckEVENT_Unlock(
     IN gckEVENT Event,
     IN gceKERNEL_WHERE FromWhere,
-    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctPOINTER Node,
     IN gceSURF_TYPE Type
     )
 {
@@ -1127,61 +1281,6 @@ OnError:
     return status;
 }
 
-/*******************************************************************************
-**
-**  gckEVENT_FreeVideoMemory
-**
-**  Schedule an event to free video memory.
-**
-**  INPUT:
-**
-**      gckEVENT Event
-**          Pointer to an gckEVENT object.
-**
-**      gcuVIDMEM_NODE_PTR VideoMemory
-**          Pointer to a gcuVIDMEM_NODE object to free.
-**
-**      gceKERNEL_WHERE FromWhere
-**          Place in the pipe where the event needs to be generated.
-**
-**  OUTPUT:
-**
-**      Nothing.
-*/
-gceSTATUS
-gckEVENT_FreeVideoMemory(
-    IN gckEVENT Event,
-    IN gcuVIDMEM_NODE_PTR VideoMemory,
-    IN gceKERNEL_WHERE FromWhere
-    )
-{
-    gceSTATUS status;
-    gcsHAL_INTERFACE iface;
-
-    gcmkHEADER_ARG("Event=0x%x VideoMemory=0x%x FromWhere=%d",
-                   Event, VideoMemory, FromWhere);
-
-    /* Verify the arguments. */
-    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
-    gcmkVERIFY_ARGUMENT(VideoMemory != gcvNULL);
-
-    /* Create an event. */
-    iface.command = gcvHAL_FREE_VIDEO_MEMORY;
-    iface.u.FreeVideoMemory.node = gcmPTR_TO_UINT64(VideoMemory);
-
-    /* Append it to the queue. */
-    gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
-
-    /* Success. */
-    gcmkFOOTER_NO();
-    return gcvSTATUS_OK;
-
-OnError:
-    /* Return the status. */
-    gcmkFOOTER();
-    return status;
-}
-
 /*******************************************************************************
 **
 **  gckEVENT_FreeNonPagedMemory
@@ -1461,6 +1560,40 @@ OnError:
     gcmkFOOTER();
     return status;
 }
+
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+gckEVENT_DestroyMmu(
+    IN gckEVENT Event,
+    IN gckMMU Mmu,
+    IN gceKERNEL_WHERE FromWhere
+    )
+{
+    gceSTATUS status;
+    gcsHAL_INTERFACE iface;
+
+    gcmkHEADER_ARG("Event=0x%x FromWhere=%d", Event, FromWhere);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+    iface.command = gcvHAL_DESTROY_MMU;
+    iface.u.DestroyMmu.mmu = gcmPTR_TO_UINT64(Mmu);
+
+    /* Append it to the queue. */
+    gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+#endif
+
 /*******************************************************************************
 **
 **  gckEVENT_Submit
@@ -1486,12 +1619,22 @@ OnError:
 **
 **      Nothing.
 */
+#if gcdMULTI_GPU
+gceSTATUS
+gckEVENT_Submit(
+    IN gckEVENT Event,
+    IN gctBOOL Wait,
+    IN gctBOOL FromPower,
+    IN gceCORE_3D_MASK ChipEnable
+    )
+#else
 gceSTATUS
 gckEVENT_Submit(
     IN gckEVENT Event,
     IN gctBOOL Wait,
     IN gctBOOL FromPower
     )
+#endif
 {
     gceSTATUS status;
     gctUINT8 id = 0xFF;
@@ -1500,14 +1643,37 @@ gckEVENT_Submit(
     gckCOMMAND command = gcvNULL;
     gctBOOL commitEntered = gcvFALSE;
 #if !gcdNULL_DRIVER
-    gctSIZE_T bytes;
+    gctUINT32 bytes;
     gctPOINTER buffer;
 #endif
 
+#if gcdMULTI_GPU
+    gctSIZE_T chipEnableBytes;
+#endif
+
+#if gcdINTERRUPT_STATISTIC
+    gctINT32 oldValue;
+#endif
+
+#if gcdSECURITY
+    gctPOINTER reservedBuffer;
+#endif
+
+    gctUINT32 flushBytes;
+    gctUINT32 executeBytes;
+    gckHARDWARE hardware;
+
+    gceKERNEL_FLUSH flush = gcvFALSE;
+
     gcmkHEADER_ARG("Event=0x%x Wait=%d", Event, Wait);
 
     /* Get gckCOMMAND object. */
     command = Event->kernel->command;
+    hardware = Event->kernel->hardware;
+
+    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+    gckOS_GetTicks(&Event->lastCommitStamp);
 
     /* Are there event queues? */
     if (Event->queueHead != gcvNULL)
@@ -1529,7 +1695,11 @@ gckEVENT_Submit(
             queue = Event->queueHead;
 
             /* Allocate an event ID. */
+#if gcdMULTI_GPU
+            gcmkONERROR(gckEVENT_GetEvent(Event, Wait, &id, queue->source, ChipEnable));
+#else
             gcmkONERROR(gckEVENT_GetEvent(Event, Wait, &id, queue->source));
+#endif
 
             /* Copy event list to event ID queue. */
             Event->queues[id].head   = queue->head;
@@ -1552,40 +1722,120 @@ gckEVENT_Submit(
             gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
             acquired = gcvFALSE;
 
+            /* Determine cache needed to flush. */
+            gcmkVERIFY_OK(_QueryFlush(Event, Event->queues[id].head, &flush));
+
+#if gcdINTERRUPT_STATISTIC
+            gcmkVERIFY_OK(gckOS_AtomIncrement(
+                Event->os,
+                Event->interruptCount,
+                &oldValue
+                ));
+#endif
+
 #if gcdNULL_DRIVER
             /* Notify immediately on infinite hardware. */
             gcmkONERROR(gckEVENT_Interrupt(Event, 1 << id));
 
-            gcmkONERROR(gckEVENT_Notify(Event, 0));
-#else
-            /* Get the size of the hardware event. */
-            gcmkONERROR(gckHARDWARE_Event(Event->kernel->hardware,
-                                          gcvNULL,
-                                          id,
-                                          Event->queues[id].source,
-                                          &bytes));
+            gcmkONERROR(gckEVENT_Notify(Event, 0));
+#else
+            /* Get the size of the hardware event. */
+            gcmkONERROR(gckHARDWARE_Event(
+                hardware,
+                gcvNULL,
+                id,
+                Event->queues[id].source,
+                &bytes
+                ));
+
+            /* Get the size of flush command. */
+            gcmkONERROR(gckHARDWARE_Flush(
+                hardware,
+                flush,
+                gcvNULL,
+                &flushBytes
+                ));
+
+            bytes += flushBytes;
+
+#if gcdMULTI_GPU
+            gcmkONERROR(gckHARDWARE_ChipEnable(
+                hardware,
+                gcvNULL,
+                0,
+                &chipEnableBytes
+                ));
+
+            bytes += chipEnableBytes * 2;
+#endif
+
+            /* Total bytes need to execute. */
+            executeBytes = bytes;
+
+            /* Reserve space in the command queue. */
+            gcmkONERROR(gckCOMMAND_Reserve(command, bytes, &buffer, &bytes));
+#if gcdSECURITY
+            reservedBuffer = buffer;
+#endif
+
+#if gcdMULTI_GPU
+            gcmkONERROR(gckHARDWARE_ChipEnable(
+                hardware,
+                buffer,
+                ChipEnable,
+                &chipEnableBytes
+                ));
+
+            buffer = (gctUINT8_PTR)buffer + chipEnableBytes;
+#endif
+
+            /* Set the flush in the command queue. */
+            gcmkONERROR(gckHARDWARE_Flush(
+                hardware,
+                flush,
+                buffer,
+                &flushBytes
+                ));
 
-            /* Reserve space in the command queue. */
-            gcmkONERROR(gckCOMMAND_Reserve(command,
-                                           bytes,
-                                           &buffer,
-                                           &bytes));
+            /* Advance to next command. */
+            buffer = (gctUINT8_PTR)buffer + flushBytes;
 
             /* Set the hardware event in the command queue. */
-            gcmkONERROR(gckHARDWARE_Event(Event->kernel->hardware,
-                                          buffer,
-                                          id,
-                                          Event->queues[id].source,
-                                          &bytes));
+            gcmkONERROR(gckHARDWARE_Event(
+                hardware,
+                buffer,
+                id,
+                Event->queues[id].source,
+                &bytes
+                ));
+
+            /* Advance to next command. */
+            buffer = (gctUINT8_PTR)buffer + bytes;
+
+#if gcdMULTI_GPU
+            gcmkONERROR(gckHARDWARE_ChipEnable(
+                hardware,
+                buffer,
+                gcvCORE_3D_ALL_MASK,
+                &chipEnableBytes
+                ));
+#endif
 
+#if gcdSECURITY
+            gckKERNEL_SecurityExecute(
+                Event->kernel,
+                reservedBuffer,
+                executeBytes
+                );
+#else
             /* Execute the hardware event. */
-            gcmkONERROR(gckCOMMAND_Execute(command, bytes));
+            gcmkONERROR(gckCOMMAND_Execute(command, executeBytes));
+#endif
 #endif
         }
 
         /* Release the command queue. */
         gcmkONERROR(gckCOMMAND_ExitCommit(command, FromPower));
-        commitEntered = gcvFALSE;
 
 #if !gcdNULL_DRIVER
         gcmkVERIFY_OK(_TryToIdleGPU(Event));
@@ -1597,18 +1847,18 @@ gckEVENT_Submit(
     return gcvSTATUS_OK;
 
 OnError:
-    if (commitEntered)
-    {
-        /* Release the command queue mutex. */
-        gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, FromPower));
-    }
-
     if (acquired)
     {
         /* Need to unroll the mutex acquire. */
         gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
     }
 
+    if (commitEntered)
+    {
+        /* Release the command queue mutex. */
+        gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, FromPower));
+    }
+
     if (id != 0xFF)
     {
         /* Need to unroll the event allocation. */
@@ -1646,11 +1896,20 @@ OnError:
 **
 **      Nothing.
 */
+#if gcdMULTI_GPU
+gceSTATUS
+gckEVENT_Commit(
+    IN gckEVENT Event,
+    IN gcsQUEUE_PTR Queue,
+    IN gceCORE_3D_MASK ChipEnable
+    )
+#else
 gceSTATUS
 gckEVENT_Commit(
     IN gckEVENT Event,
     IN gcsQUEUE_PTR Queue
     )
+#endif
 {
     gceSTATUS status;
     gcsQUEUE_PTR record = gcvNULL, next;
@@ -1719,7 +1978,11 @@ gckEVENT_Commit(
     }
 
     /* Submit the event list. */
+#if gcdMULTI_GPU
+    gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE, ChipEnable));
+#else
     gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE));
+#endif
 
     /* Success */
     gcmkFOOTER_NO();
@@ -1778,7 +2041,11 @@ gckEVENT_Compose(
     gcmkVERIFY_ARGUMENT(Info != gcvNULL);
 
     /* Allocate an event ID. */
+#if gcdMULTI_GPU
+    gcmkONERROR(gckEVENT_GetEvent(Event, gcvTRUE, &id, gcvKERNEL_PIXEL, gcvCORE_3D_ALL_MASK));
+#else
     gcmkONERROR(gckEVENT_GetEvent(Event, gcvTRUE, &id, gcvKERNEL_PIXEL));
+#endif
 
     /* Get process ID. */
     gcmkONERROR(gckOS_GetProcessID(&processID));
@@ -1826,7 +2093,6 @@ gckEVENT_Compose(
         /* Allocate a record. */
         gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
         tailRecord->next = tempRecord;
-        tailRecord = tempRecord;
 
         /* Initialize the record. */
         tempRecord->info.command            = gcvHAL_SIGNAL;
@@ -1841,7 +2107,7 @@ gckEVENT_Compose(
         tempRecord->processID = processID;
     }
 
-       /* Set the event list. */
+    /* Set the event list. */
     Event->queues[id].head = headRecord;
 
     /* Start composition. */
@@ -1882,21 +2148,118 @@ OnError:
 gceSTATUS
 gckEVENT_Interrupt(
     IN gckEVENT Event,
+#if gcdMULTI_GPU
+    IN gctUINT CoreId,
+#endif
     IN gctUINT32 Data
     )
 {
+#if gcdMULTI_GPU
+#if defined(WIN32)
+    gctUINT32 i;
+#endif
+#endif
     gcmkHEADER_ARG("Event=0x%x Data=0x%x", Event, Data);
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
 
+    if (Data & 0x20000000)
+    {
+        gckENTRYDATA data;
+        gctUINT32 idle;
+        Data &= ~0x20000000;
+
+#if gcdMULTI_GPU
+        if (Event->kernel->core == gcvCORE_MAJOR)
+#endif
+        {
+            /* Get first entry information. */
+            gcmkVERIFY_OK(
+                gckENTRYQUEUE_Dequeue(&Event->kernel->command->queue, &data));
+
+            /* Make sure FE is idle. */
+            do
+            {
+                gcmkVERIFY_OK(gckOS_ReadRegisterEx(
+                    Event->os,
+                    Event->kernel->core,
+                    0x4,
+                    &idle));
+            }
+            while (idle != 0x7FFFFFFF);
+
+            /* Start Command Parser. */
+            gcmkVERIFY_OK(gckHARDWARE_Execute(
+                Event->kernel->hardware,
+                data->physical,
+                data->bytes
+                ));
+        }
+    }
+
     /* Combine current interrupt status with pending flags. */
 #if gcdSMP
-    gckOS_AtomSetMask(Event->pending, Data);
+#if gcdMULTI_GPU
+    if (Event->kernel->core == gcvCORE_MAJOR)
+    {
+        gckOS_AtomSetMask(Event->pending3D[CoreId], Data);
+    }
+    else
+#endif
+    {
+        gckOS_AtomSetMask(Event->pending, Data);
+    }
 #elif defined(__QNXNTO__)
-    atomic_set(&Event->pending, Data);
+#if gcdMULTI_GPU
+    if (Event->kernel->core == gcvCORE_MAJOR)
+    {
+        atomic_set(&Event->pending3D[CoreId], Data);
+    }
+    else
+#endif
+    {
+        atomic_set(&Event->pending, Data);
+    }
+#else
+#if gcdMULTI_GPU
+#if defined(WIN32)
+    if (Event->kernel->core == gcvCORE_MAJOR)
+    {
+        for (i = 0; i < gcdMULTI_GPU; i++)
+        {
+            Event->pending3D[i] |= Data;
+        }
+    }
+    else
 #else
-    Event->pending |= Data;
+    if (Event->kernel->core == gcvCORE_MAJOR)
+    {
+        Event->pending3D[CoreId] |= Data;
+    }
+    else
+#endif
+#endif
+    {
+        Event->pending |= Data;
+    }
+#endif
+
+#if gcdINTERRUPT_STATISTIC
+    {
+        gctINT j = 0;
+        gctINT32 oldValue;
+
+        for (j = 0; j < gcmCOUNTOF(Event->queues); j++)
+        {
+            if ((Data & (1 << j)))
+            {
+                gcmkVERIFY_OK(gckOS_AtomDecrement(Event->os,
+                                                  Event->interruptCount,
+                                                  &oldValue));
+            }
+        }
+    }
 #endif
 
     /* Success. */
@@ -1930,11 +2293,16 @@ gckEVENT_Notify(
     gcsEVENT_QUEUE * queue;
     gctUINT mask = 0;
     gctBOOL acquired = gcvFALSE;
-    gcuVIDMEM_NODE_PTR node;
     gctPOINTER info;
     gctSIGNAL signal;
-    gctUINT pending;
+    gctUINT pending = 0;
     gckKERNEL kernel = Event->kernel;
+#if gcdMULTI_GPU
+    gceCORE core = Event->kernel->core;
+    gctUINT32 busy;
+    gctUINT32 oldValue;
+    gctUINT pendingMask;
+#endif
 #if !gcdSMP
     gctBOOL suspended = gcvFALSE;
 #endif
@@ -1945,6 +2313,8 @@ gckEVENT_Notify(
 #if gcdSECURE_USER
     gcskSECURE_CACHE_PTR cache;
 #endif
+    gckVIDMEM_NODE nodeObject;
+    gcuVIDMEM_NODE_PTR node;
 
     gcmkHEADER_ARG("Event=0x%x IDs=0x%x", Event, IDs);
 
@@ -1968,36 +2338,117 @@ gckEVENT_Notify(
         }
     );
 
+#if gcdMULTI_GPU
+    /* Set busy flag. */
+    gckOS_AtomicExchange(Event->os, &Event->busy, 1, &busy);
+    if (busy)
+    {
+        /* Another thread is already busy - abort. */
+        goto OnSuccess;
+    }
+#endif
+
     for (;;)
     {
         gcsEVENT_PTR record;
+#if gcdMULTI_GPU
+        gctUINT32 pend[gcdMULTI_GPU];
+        gctUINT32 pendMask[gcdMULTI_GPU];
+#endif
+
+        /* Grab the mutex queue. */
+        gcmkONERROR(gckOS_AcquireMutex(Event->os,
+                                       Event->eventQueueMutex,
+                                       gcvINFINITE));
+        acquired = gcvTRUE;
 
 #if gcdSMP
-        /* Get current interrupts. */
-        gckOS_AtomGet(Event->os, Event->pending, (gctINT32_PTR)&pending);
+#if gcdMULTI_GPU
+        if (core == gcvCORE_MAJOR)
+        {
+            /* Get current interrupts. */
+            for (i = 0; i < gcdMULTI_GPU; i++)
+            {
+                gckOS_AtomGet(Event->os, Event->pending3D[i], (gctINT32_PTR)&pend[i]);
+                gckOS_AtomGet(Event->os, Event->pending3DMask[i], (gctINT32_PTR)&pendMask[i]);
+            }
+
+            gckOS_AtomGet(Event->os, Event->pendingMask, (gctINT32_PTR)&pendingMask);
+        }
+        else
+#endif
+        {
+            gckOS_AtomGet(Event->os, Event->pending, (gctINT32_PTR)&pending);
+        }
 #else
         /* Suspend interrupts. */
         gcmkONERROR(gckOS_SuspendInterruptEx(Event->os, Event->kernel->core));
         suspended = gcvTRUE;
 
-        /* Get current interrupts. */
-        pending = Event->pending;
+#if gcdMULTI_GPU
+        if (core == gcvCORE_MAJOR)
+        {
+            for (i = 0; i < gcdMULTI_GPU; i++)
+            {
+                /* Get current interrupts. */
+                pend[i] = Event->pending3D[i];
+                pendMask[i] = Event->pending3DMask[i];
+            }
+
+            pendingMask = Event->pendingMask;
+        }
+        else
+#endif
+        {
+            pending = Event->pending;
+        }
 
         /* Resume interrupts. */
         gcmkONERROR(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
         suspended = gcvFALSE;
 #endif
 
+#if gcdMULTI_GPU
+        if (core == gcvCORE_MAJOR)
+        {
+            for (i = 0; i < gcdMULTI_GPU; i++)
+            {
+                gctUINT32 bad_pend = (pend[i] & ~pendMask[i]);
+
+                if (bad_pend != 0)
+                {
+                    gcmkTRACE_ZONE_N(
+                        gcvLEVEL_ERROR, gcvZONE_EVENT,
+                        gcmSIZEOF(bad_pend) + gcmSIZEOF(i),
+                        "Interrupts 0x%x are not unexpected for Core%d.",
+                        bad_pend, i
+                        );
+
+                    gckOS_AtomClearMask(Event->pending3D[i], bad_pend);
+
+                    pend[i] &= pendMask[i];
+                }
+            }
+
+            pending = (pend[0] & pend[1] & pendingMask) /* Check combined events on both GPUs */
+                    | (pend[0] & ~pendingMask)          /* Check individual events on GPU 0   */
+                    | (pend[1] & ~pendingMask);         /* Check individual events on GPU 1   */
+        }
+#endif
+
         if (pending == 0)
         {
+            /* Release the mutex queue. */
+            gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+            acquired = gcvFALSE;
+
             /* No more pending interrupts - done. */
             break;
         }
 
         if (pending & 0x80000000)
         {
-            gckOS_Print("!!!!!!!!!!!!! AXI BUS ERROR !!!!!!!!!!!!!\n");
-            gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_EVENT, "AXI BUS ERROR");
+            gcmkPRINT("AXI BUS ERROR");
             pending &= 0x7FFFFFFF;
         }
 
@@ -2064,23 +2515,70 @@ gckEVENT_Notify(
                 );
 
 #if gcdSMP
-            /* Mark pending interrupts as handled. */
-            gckOS_AtomClearMask(Event->pending, pending);
+#if gcdMULTI_GPU
+            if (core == gcvCORE_MAJOR)
+            {
+                /* Mark pending interrupts as handled. */
+                for (i = 0; i < gcdMULTI_GPU; i++)
+                {
+                    gckOS_AtomClearMask(Event->pending3D[i], pending);
+                    gckOS_AtomClearMask(Event->pending3DMask[i], pending);
+                }
+
+                gckOS_AtomClearMask(Event->pendingMask, pending);
+            }
+            else
+#endif
+            {
+                gckOS_AtomClearMask(Event->pending, pending);
+            }
+
 #elif defined(__QNXNTO__)
-            /* Mark pending interrupts as handled. */
-            atomic_clr((gctUINT32_PTR)&Event->pending, pending);
+#if gcdMULTI_GPU
+            if (core == gcvCORE_MAJOR)
+            {
+                for (i = 0; i < gcdMULTI_GPU; i++)
+                {
+                    atomic_clr((gctUINT32_PTR)&Event->pending3D[i], pending);
+                    atomic_clr((gctUINT32_PTR)&Event->pending3DMask[i], pending);
+                }
+
+                atomic_clr((gctUINT32_PTR)&Event->pendingMask, pending);
+            }
+            else
+#endif
+            {
+                atomic_clr((gctUINT32_PTR)&Event->pending, pending);
+            }
 #else
             /* Suspend interrupts. */
             gcmkONERROR(gckOS_SuspendInterruptEx(Event->os, Event->kernel->core));
             suspended = gcvTRUE;
 
-            /* Mark pending interrupts as handled. */
-            Event->pending &= ~pending;
+#if gcdMULTI_GPU
+            if (core == gcvCORE_MAJOR)
+            {
+                for (i = 0; i < gcdMULTI_GPU; i++)
+                {
+                    /* Mark pending interrupts as handled. */
+                    Event->pending3D[i] &= ~pending;
+                    Event->pending3DMask[i] &= ~pending;
+                }
+            }
+            else
+#endif
+            {
+                Event->pending &= ~pending;
+            }
 
             /* Resume interrupts. */
             gcmkONERROR(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
             suspended = gcvFALSE;
 #endif
+
+            /* Release the mutex queue. */
+            gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+            acquired = gcvFALSE;
             break;
         }
 
@@ -2090,6 +2588,9 @@ gckEVENT_Notify(
             if ((Event->queues[i].head != gcvNULL)
             &&  (Event->queues[i].stamp < queue->stamp)
             &&  (Event->queues[i].source <= queue->source)
+#if gcdMULTI_GPU
+            &&  (Event->queues[i].chipEnable == queue->chipEnable)
+#endif
             )
             {
                 gcmkTRACE_N(
@@ -2118,33 +2619,69 @@ gckEVENT_Notify(
         }
 
 #if gcdSMP
-        /* Mark pending interrupt as handled. */
-        gckOS_AtomClearMask(Event->pending, mask);
+#if gcdMULTI_GPU
+        if (core == gcvCORE_MAJOR)
+        {
+            for (i = 0; i < gcdMULTI_GPU; i++)
+            {
+                /* Mark pending interrupt as handled. */
+                gckOS_AtomClearMask(Event->pending3D[i], mask);
+                gckOS_AtomClearMask(Event->pending3DMask[i], mask);
+            }
+
+            gckOS_AtomClearMask(Event->pendingMask, mask);
+        }
+        else
+#endif
+        {
+            gckOS_AtomClearMask(Event->pending, mask);
+        }
+
 #elif defined(__QNXNTO__)
-        /* Mark pending interrupt as handled. */
-        atomic_clr(&Event->pending, mask);
+#if gcdMULTI_GPU
+        if (core == gcvCORE_MAJOR)
+        {
+            for (i = 0; i < gcdMULTI_GPU; i++)
+            {
+                atomic_clr(&Event->pending3D[i], mask);
+                atomic_clr(&Event->pending3DMask[i], mask);
+            }
+
+            atomic_clr(&Event->pendingMask, mask);
+        }
+        else
+#endif
+        {
+            atomic_clr(&Event->pending, mask);
+        }
 #else
         /* Suspend interrupts. */
         gcmkONERROR(gckOS_SuspendInterruptEx(Event->os, Event->kernel->core));
         suspended = gcvTRUE;
 
-        /* Mark pending interrupt as handled. */
-        Event->pending &= ~mask;
+#if gcdMULTI_GPU
+        if (core == gcvCORE_MAJOR)
+        {
+            for (i = 0; i < gcdMULTI_GPU; i++)
+            {
+                /* Mark pending interrupt as handled. */
+                Event->pending3D[i] &= ~mask;
+                Event->pending3DMask[i] &= ~mask;
+            }
+
+            Event->pendingMask &= ~mask;
+        }
+        else
+#endif
+        {
+            Event->pending &= ~mask;
+        }
 
         /* Resume interrupts. */
         gcmkONERROR(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
         suspended = gcvFALSE;
 #endif
 
-        /* Grab the mutex queue. */
-        gcmkONERROR(gckOS_AcquireMutex(Event->os,
-                                       Event->eventQueueMutex,
-                                       gcvINFINITE));
-        acquired = gcvTRUE;
-
-        /* We are in the notify loop. */
-        Event->inNotify = gcvTRUE;
-
         /* Grab the event head. */
         record = queue->head;
 
@@ -2239,51 +2776,13 @@ gckEVENT_Notify(
                     gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
                         Event->kernel,
                         cache,
-                        gcmUINT64_TO_PTR(record->record.u.FreeContiguousMemory.logical),
-                        (gctSIZE_T) record->record.u.FreeContiguousMemory.bytes));
+                        gcmUINT64_TO_PTR(event->event.u.FreeContiguousMemory.logical),
+                        (gctSIZE_T) event->event.u.FreeContiguousMemory.bytes));
 #endif
                 }
                 gcmRELEASE_NAME(record->info.u.FreeContiguousMemory.physical);
                 break;
 
-            case gcvHAL_FREE_VIDEO_MEMORY:
-                node = gcmUINT64_TO_PTR(record->info.u.FreeVideoMemory.node);
-                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
-                               "gcvHAL_FREE_VIDEO_MEMORY: 0x%x",
-                               node);
-#ifdef __QNXNTO__
-#if gcdUSE_VIDMEM_PER_PID
-                /* Check if the VidMem object still exists. */
-                if (gckKERNEL_GetVideoMemoryPoolPid(record->kernel,
-                                                    gcvPOOL_SYSTEM,
-                                                    record->processID,
-                                                    gcvNULL) == gcvSTATUS_NOT_FOUND)
-                {
-                    /*printf("Vidmem not found for process:%d\n", queue->processID);*/
-                    status = gcvSTATUS_OK;
-                    break;
-                }
-#else
-                if ((node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
-                &&  (node->VidMem.logical != gcvNULL)
-                )
-                {
-                    gcmkERR_BREAK(
-                        gckKERNEL_UnmapVideoMemory(record->kernel,
-                                                   node->VidMem.logical,
-                                                   record->processID,
-                                                   node->VidMem.bytes));
-                    node->VidMem.logical = gcvNULL;
-                }
-#endif
-#endif
-
-                /* Free video memory. */
-                status =
-                    gckVIDMEM_Free(node);
-
-                break;
-
             case gcvHAL_WRITE_DATA:
 #ifndef __QNXNTO__
                 /* Convert physical into logical address. */
@@ -2315,14 +2814,17 @@ gckEVENT_Notify(
                 break;
 
             case gcvHAL_UNLOCK_VIDEO_MEMORY:
-                node = gcmUINT64_TO_PTR(record->info.u.UnlockVideoMemory.node);
-
                 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
                                "gcvHAL_UNLOCK_VIDEO_MEMORY: 0x%x",
-                               node);
+                               record->info.u.UnlockVideoMemory.node);
+
+                nodeObject = gcmUINT64_TO_PTR(record->info.u.UnlockVideoMemory.node);
+
+                node = nodeObject->node;
 
                 /* Save node information before it disappears. */
 #if gcdSECURE_USER
+                node = event->event.u.UnlockVideoMemory.node;
                 if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
                 {
                     logical = gcvNULL;
@@ -2338,7 +2840,7 @@ gckEVENT_Notify(
                 /* Unlock. */
                 status = gckVIDMEM_Unlock(
                     Event->kernel,
-                    node,
+                    nodeObject,
                     record->info.u.UnlockVideoMemory.type,
                     gcvNULL);
 
@@ -2352,6 +2854,16 @@ gckEVENT_Notify(
                         bytes));
                 }
 #endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+                gcmkVERIFY_OK(gckVIDMEM_NODE_Unlock(
+                    Event->kernel,
+                    nodeObject,
+                    record->processID
+                    ));
+#endif
+
+                status = gckVIDMEM_NODE_Dereference(Event->kernel, nodeObject);
                 break;
 
             case gcvHAL_SIGNAL:
@@ -2465,7 +2977,6 @@ gckEVENT_Notify(
                 }
                 break;
 
-#if gcdVIRTUAL_COMMAND_BUFFER
              case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
                  gcmkVERIFY_OK(
                      gckKERNEL_DestroyVirtualCommandBuffer(Event->kernel,
@@ -2475,7 +2986,6 @@ gckEVENT_Notify(
                          ));
                  gcmRELEASE_NAME(record->info.u.FreeVirtualCommandBuffer.physical);
                  break;
-#endif
 
 #if gcdANDROID_NATIVE_FENCE_SYNC
             case gcvHAL_SYNC_POINT:
@@ -2488,6 +2998,12 @@ gckEVENT_Notify(
                 break;
 #endif
 
+#if gcdPROCESS_ADDRESS_SPACE
+            case gcvHAL_DESTROY_MMU:
+                status = gckMMU_Destroy(gcmUINT64_TO_PTR(record->info.u.DestroyMmu.mmu));
+                break;
+#endif
+
             case gcvHAL_COMMIT_DONE:
                 break;
 
@@ -2525,14 +3041,19 @@ gckEVENT_Notify(
                        "Handled interrupt 0x%x", mask);
     }
 
+#if gcdMULTI_GPU
+    /* Clear busy flag. */
+    gckOS_AtomicExchange(Event->os, &Event->busy, 0, &oldValue);
+#endif
+
     if (IDs == 0)
     {
         gcmkONERROR(_TryToIdleGPU(Event));
     }
 
-    /* We are out the notify loop. */
-    Event->inNotify = gcvFALSE;
-
+#if gcdMULTI_GPU
+OnSuccess:
+#endif
     /* Success. */
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
@@ -2552,9 +3073,6 @@ OnError:
     }
 #endif
 
-    /* We are out the notify loop. */
-    Event->inNotify = gcvFALSE;
-
     /* Return the status. */
     gcmkFOOTER();
     return status;
@@ -2713,7 +3231,7 @@ gckEVENT_Stop(
     IN gctPHYS_ADDR Handle,
     IN gctPOINTER Logical,
     IN gctSIGNAL Signal,
-       IN OUT gctSIZE_T * waitSize
+    IN OUT gctUINT32 * waitSize
     )
 {
     gceSTATUS status;
@@ -2729,9 +3247,16 @@ gckEVENT_Stop(
     gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
 
     /* Submit the current event queue. */
+#if gcdMULTI_GPU
+    gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE, gcvCORE_3D_ALL_MASK));
+#else
     gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE));
-
+#endif
+#if gcdMULTI_GPU
+    gcmkONERROR(gckEVENT_GetEvent(Event, gcvTRUE, &id, gcvKERNEL_PIXEL, gcvCORE_3D_ALL_MASK));
+#else
     gcmkONERROR(gckEVENT_GetEvent(Event, gcvTRUE, &id, gcvKERNEL_PIXEL));
+#endif
 
     /* Allocate a record. */
     gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &record));
@@ -2762,7 +3287,7 @@ gckEVENT_Stop(
         Event->os,
         ProcessID,
         gcvNULL,
-        Handle,
+        (gctUINT32)Handle,
         Logical,
         *waitSize
         ));
@@ -2797,10 +3322,6 @@ _PrintRecord(
         gcmkPRINT("      gcvHAL_FREE_CONTIGUOUS_MEMORY");
             break;
 
-    case gcvHAL_FREE_VIDEO_MEMORY:
-        gcmkPRINT("      gcvHAL_FREE_VIDEO_MEMORY");
-            break;
-
     case gcvHAL_WRITE_DATA:
         gcmkPRINT("      gcvHAL_WRITE_DATA");
        break;
@@ -2832,6 +3353,17 @@ _PrintRecord(
                   record->info.u.FreeVirtualCommandBuffer.logical);
         break;
 
+    case gcvHAL_SYNC_POINT:
+        gcmkPRINT("      gcvHAL_SYNC_POINT syncPoint=0x%08x",
+                  gcmUINT64_TO_PTR(record->info.u.SyncPoint.syncPoint));
+
+        break;
+
+    case gcvHAL_DESTROY_MMU:
+        gcmkPRINT("      gcvHAL_DESTORY_MMU mmu=0x%08x",
+                  gcmUINT64_TO_PTR(record->info.u.DestroyMmu.mmu));
+
+        break;
     default:
         gcmkPRINT("      Illegal Event %d", record->info.command);
         break;
@@ -2853,6 +3385,10 @@ gckEVENT_Dump(
     gcsEVENT_QUEUE_PTR queue;
     gcsEVENT_PTR record = gcvNULL;
     gctINT i;
+#if gcdINTERRUPT_STATISTIC
+    gctINT32 pendingInterrupt;
+    gctUINT32 intrAcknowledge;
+#endif
 
     gcmkHEADER_ARG("Event=0x%x", Event);
 
@@ -2860,7 +3396,6 @@ gckEVENT_Dump(
     gcmkPRINT("***  EVENT STATE DUMP  ***\n");
     gcmkPRINT("**************************\n");
 
-
     gcmkPRINT("  Unsumbitted Event:");
     while(queueHead)
     {
@@ -2885,7 +3420,7 @@ gckEVENT_Dump(
     }
 
     gcmkPRINT("  Untriggered Event:");
-    for (i = 0; i < 30; i++)
+    for (i = 0; i < gcmCOUNTOF(Event->queues); i++)
     {
         queue = &Event->queues[i];
         record = queue->head;
@@ -2898,15 +3433,24 @@ gckEVENT_Dump(
         }
     }
 
-    gcmkFOOTER_NO();
-    return gcvSTATUS_OK;
-}
+#if gcdINTERRUPT_STATISTIC
+    gckOS_AtomGet(Event->os, Event->interruptCount, &pendingInterrupt);
+    gcmkPRINT("  Number of Pending Interrupt: %d", pendingInterrupt);
 
-gceSTATUS gckEVENT_WaitEmpty(gckEVENT Event)
-{
-    gctBOOL isEmpty;
+    if (Event->kernel->recovery == 0)
+    {
+        gckOS_ReadRegisterEx(
+            Event->os,
+            Event->kernel->core,
+            0x10,
+            &intrAcknowledge
+            );
 
-    while (Event->inNotify || (gcmIS_SUCCESS(gckEVENT_IsEmpty(Event, &isEmpty)) && !isEmpty)) ;
+        gcmkPRINT("  INTR_ACKNOWLEDGE=0x%x", intrAcknowledge);
+    }
+#endif
 
+    gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 }
+
index a5affb978f4eb7863c2c2662bc212a4f16cb0294..be0a60eb6da93e009ed621d34baa80cb6454f89b 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -33,8 +33,7 @@
 /*******************************************************************************
 ***** Structures ***************************************************************
 *******************************************************************************/
-
-#define gcdIN_USE               ((gcskNODE_PTR) ~0)
+#define gcdIN_USE               ((gcskNODE_PTR)gcvMAXUINTPTR_T)
 
 typedef struct _gcskNODE *      gcskNODE_PTR;
 typedef struct _gcskNODE
index 50bc63e3a88c8410350105cd632ca7e77d06fa4c..5716223b9807b64f96cea0b1b8ebf350a10bed6c 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
index 456ec246241e789eb7532225bd05de175e5ee2f6..7f545f24a6e1d52ad39402c5f08d0979326b0c89 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -35,7 +35,7 @@ gceMMU_TYPE;
 
 #define gcdMMU_TABLE_DUMP       0
 
-#define gcdUSE_MMU_EXCEPTION    0
+#define gcdUSE_MMU_EXCEPTION    1
 
 /*
     gcdMMU_CLEAR_VALUE
@@ -46,7 +46,6 @@ gceMMU_TYPE;
 #   define gcdMMU_CLEAR_VALUE                   0x00000ABC
 #endif
 
-/* VIV: Start GPU address for gcvSURF_VERTEX.  */
 #define gcdVERTEX_START      (128 << 10)
 
 typedef struct _gcsMMU_STLB *gcsMMU_STLB_PTR;
@@ -177,19 +176,19 @@ _Link(
     else
     {
         /* Address page table. */
-        gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+        gctUINT32_PTR map = Mmu->mapLogical;
 
         /* Dispatch on node type. */
-        switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[Index])))
+        switch (gcmENTRY_TYPE(_ReadPageEntry(&map[Index])))
         {
         case gcvMMU_SINGLE:
             /* Set single index. */
-            _WritePageEntry(&pageTable[Index], (Next << 8) | gcvMMU_SINGLE);
+            _WritePageEntry(&map[Index], (Next << 8) | gcvMMU_SINGLE);
             break;
 
         case gcvMMU_FREE:
             /* Set index. */
-            _WritePageEntry(&pageTable[Index + 1], Next);
+            _WritePageEntry(&map[Index + 1], Next);
             break;
 
         default:
@@ -210,18 +209,18 @@ _AddFree(
     IN gctUINT32 Count
     )
 {
-    gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+    gctUINT32_PTR map = Mmu->mapLogical;
 
     if (Count == 1)
     {
         /* Initialize a single page node. */
-        _WritePageEntry(pageTable + Node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
+        _WritePageEntry(map + Node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
     }
     else
     {
         /* Initialize the node. */
-        _WritePageEntry(pageTable + Node + 0, (Count << 8) | gcvMMU_FREE);
-        _WritePageEntry(pageTable + Node + 1, ~0U);
+        _WritePageEntry(map + Node + 0, (Count << 8) | gcvMMU_FREE);
+        _WritePageEntry(map + Node + 1, ~0U);
     }
 
     /* Append the node. */
@@ -233,7 +232,7 @@ _Collect(
     IN gckMMU Mmu
     )
 {
-    gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+    gctUINT32_PTR map = Mmu->mapLogical;
     gceSTATUS status;
     gctUINT32 i, previous, start = 0, count = 0;
 
@@ -244,7 +243,7 @@ _Collect(
     for (i = 0; i < Mmu->pageTableEntries; ++i)
     {
         /* Dispatch based on type of page. */
-        switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[i])))
+        switch (gcmENTRY_TYPE(_ReadPageEntry(&map[i])))
         {
         case gcvMMU_USED:
             /* Used page, so close any open node. */
@@ -277,10 +276,10 @@ _Collect(
             }
 
             /* Advance the count. */
-            count += _ReadPageEntry(&pageTable[i]) >> 8;
+            count += _ReadPageEntry(&map[i]) >> 8;
 
             /* Advance the index into the page table. */
-            i     += (_ReadPageEntry(&pageTable[i]) >> 8) - 1;
+            i     += (_ReadPageEntry(&map[i]) >> 8) - 1;
             break;
 
         default:
@@ -319,6 +318,112 @@ _SetPage(gctUINT32 PageAddress)
            | (1 << 0);
 }
 
+#if gcdPROCESS_ADDRESS_SPACE
+gctUINT32
+_AddressToIndex(
+    IN gckMMU Mmu,
+    IN gctUINT32 Address
+    )
+{
+    gctUINT32 mtlbOffset = (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
+    gctUINT32 stlbOffset = (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
+
+    return (mtlbOffset - Mmu->dynamicMappingStart) * gcdMMU_STLB_4K_ENTRY_NUM + stlbOffset;
+}
+
+gctUINT32
+_MtlbOffset(
+    gctUINT32 Address
+    )
+{
+    return (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
+}
+
+gctUINT32
+_StlbOffset(
+    gctUINT32 Address
+    )
+{
+    return (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
+}
+
+static gceSTATUS
+_AllocateStlb(
+    IN gckOS Os,
+    OUT gcsMMU_STLB_PTR *Stlb
+    )
+{
+    gceSTATUS status;
+    gcsMMU_STLB_PTR stlb;
+    gctPOINTER pointer;
+
+    /* Allocate slave TLB record. */
+    gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsMMU_STLB), &pointer));
+    stlb = pointer;
+
+    stlb->size = gcdMMU_STLB_4K_SIZE;
+
+    /* Allocate slave TLB entries. */
+    gcmkONERROR(gckOS_AllocateContiguous(
+        Os,
+        gcvFALSE,
+        &stlb->size,
+        &stlb->physical,
+        (gctPOINTER)&stlb->logical
+        ));
+
+    gcmkONERROR(gckOS_GetPhysicalAddress(Os, stlb->logical, &stlb->physBase));
+
+#if gcdUSE_MMU_EXCEPTION
+    _FillPageTable(stlb->logical, stlb->size / 4, gcdMMU_STLB_EXCEPTION);
+#else
+    gckOS_ZeroMemory(stlb->logical, stlb->size);
+#endif
+
+    *Stlb = stlb;
+
+    return gcvSTATUS_OK;
+
+OnError:
+    return status;
+}
+
+gceSTATUS
+_SetupProcessAddressSpace(
+    IN gckMMU Mmu
+    )
+{
+    gceSTATUS status;
+    gctINT numEntries = 0;
+    gctUINT32_PTR map;
+
+    numEntries = gcdPROCESS_ADDRESS_SPACE_SIZE
+               /* Address space mapped by one MTLB entry. */
+               / (1 << gcdMMU_MTLB_SHIFT);
+
+    Mmu->dynamicMappingStart = 0;
+
+    Mmu->pageTableSize = numEntries * 4096;
+
+    Mmu->pageTableEntries = Mmu->pageTableSize / gcmSIZEOF(gctUINT32);
+
+    gcmkONERROR(gckOS_Allocate(Mmu->os,
+                               Mmu->pageTableSize,
+                               (void **)&Mmu->mapLogical));
+
+    /* Initilization. */
+    map      = Mmu->mapLogical;
+    _WritePageEntry(map,     (Mmu->pageTableEntries << 8) | gcvMMU_FREE);
+    _WritePageEntry(map + 1, ~0U);
+    Mmu->heapList  = 0;
+    Mmu->freeNodes = gcvFALSE;
+
+    return gcvSTATUS_OK;
+
+OnError:
+    return status;
+}
+#else
 static gceSTATUS
 _FillFlatMapping(
     IN gckMMU Mmu,
@@ -335,6 +440,7 @@ _FillFlatMapping(
     gctUINT32 mEnd = end >> gcdMMU_MTLB_SHIFT;
     gctUINT32 sStart = (start & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
     gctUINT32 sEnd = (end & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
+    gctBOOL ace = gckHARDWARE_IsFeatureAvailable(Mmu->hardware, gcvFEATURE_ACE);
 
     /* Grab the mutex. */
     gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
@@ -348,6 +454,7 @@ _FillFlatMapping(
             gcsMMU_STLB_PTR stlb;
             gctPOINTER pointer = gcvNULL;
             gctUINT32 last = (mStart == mEnd) ? sEnd : (gcdMMU_STLB_64K_ENTRY_NUM - 1);
+            gctUINT32 mtlbEntry;
 
             gcmkONERROR(gckOS_Allocate(Mmu->os, sizeof(struct _gcsMMU_STLB), &pointer));
             stlb = pointer;
@@ -389,15 +496,23 @@ _FillFlatMapping(
                 gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
             }
 
-            _WritePageEntry(Mmu->mtlbLogical + mStart,
-                            stlb->physBase
-                            /* 64KB page size */
-                            | (1 << 2)
-                            /* Ignore exception */
-                            | (0 << 1)
-                            /* Present */
-                            | (1 << 0)
-                            );
+            mtlbEntry = stlb->physBase
+                      /* 64KB page size */
+                      | (1 << 2)
+                      /* Ignore exception */
+                      | (0 << 1)
+                      /* Present */
+                      | (1 << 0);
+
+            if (ace)
+            {
+                mtlbEntry = mtlbEntry
+                          /* Secure */
+                          | (1 << 4);
+            }
+
+            _WritePageEntry(Mmu->mtlbLogical + mStart, mtlbEntry);
+
 #if gcdMMU_TABLE_DUMP
             gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
                 __FUNCTION__, __LINE__,
@@ -587,8 +702,10 @@ _SetupDynamicSpace(
     gctINT i, nodeArraySize = 0;
     gctUINT32 physical;
     gctINT numEntries = 0;
-    gctUINT32_PTR pageTable;
+    gctUINT32_PTR map;
     gctBOOL acquired = gcvFALSE;
+    gctUINT32 mtlbEntry;
+    gctBOOL ace = gckHARDWARE_IsFeatureAvailable(Mmu->hardware, gcvFEATURE_ACE);
 
     /* Find all the dynamic address space. */
     gcmkONERROR(_FindDynamicSpace(Mmu, &nodeArray, &nodeArraySize));
@@ -607,7 +724,11 @@ _SetupDynamicSpace(
 
     Mmu->pageTableSize = numEntries * 4096;
 
-    Mmu->pageTableEntries = Mmu->pageTableSize / gcmSIZEOF(gctUINT32);
+    gcmkSAFECASTSIZET(Mmu->pageTableEntries, Mmu->pageTableSize / gcmSIZEOF(gctUINT32));
+
+    gcmkONERROR(gckOS_Allocate(Mmu->os,
+                               Mmu->pageTableSize,
+                               (void **)&Mmu->mapLogical));
 
     /* Construct Slave TLB. */
     gcmkONERROR(gckOS_AllocateContiguous(Mmu->os,
@@ -628,9 +749,9 @@ _SetupDynamicSpace(
 #endif
 
     /* Initilization. */
-    pageTable      = Mmu->pageTableLogical;
-    _WritePageEntry(pageTable,     (Mmu->pageTableEntries << 8) | gcvMMU_FREE);
-    _WritePageEntry(pageTable + 1, ~0U);
+    map      = Mmu->mapLogical;
+    _WritePageEntry(map,     (Mmu->pageTableEntries << 8) | gcvMMU_FREE);
+    _WritePageEntry(map + 1, ~0U);
     Mmu->heapList  = 0;
     Mmu->freeNodes = gcvFALSE;
 
@@ -647,15 +768,23 @@ _SetupDynamicSpace(
          i < (gctINT)Mmu->dynamicMappingStart + numEntries;
          i++)
     {
-        _WritePageEntry(Mmu->mtlbLogical + i,
-                        physical
-                        /* 4KB page size */
-                        | (0 << 2)
-                        /* Ignore exception */
-                        | (0 << 1)
-                        /* Present */
-                        | (1 << 0)
-                        );
+        mtlbEntry = physical
+                  /* 4KB page size */
+                  | (0 << 2)
+                  /* Ignore exception */
+                  | (0 << 1)
+                  /* Present */
+                  | (1 << 0);
+
+        if (ace)
+        {
+            mtlbEntry = mtlbEntry
+                      /* Secure */
+                      | (1 << 4);
+        }
+
+        _WritePageEntry(Mmu->mtlbLogical + i, mtlbEntry);
+
 #if gcdMMU_TABLE_DUMP
         gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
                 __FUNCTION__, __LINE__,
@@ -671,14 +800,17 @@ _SetupDynamicSpace(
     return gcvSTATUS_OK;
 
 OnError:
-    if (Mmu->pageTableLogical)
+    if (Mmu->mapLogical)
     {
-        /* Free the page table. */
         gcmkVERIFY_OK(
-                gckOS_FreeContiguous(Mmu->os,
-                    Mmu->pageTablePhysical,
-                    (gctPOINTER) Mmu->pageTableLogical,
-                    Mmu->pageTableSize));
+            gckOS_Free(Mmu->os, (gctPOINTER) Mmu->mapLogical));
+
+
+        gcmkVERIFY_OK(
+            gckOS_FreeContiguous(Mmu->os,
+                                 Mmu->pageTablePhysical,
+                                 (gctPOINTER) Mmu->pageTableLogical,
+                                 Mmu->pageTableSize));
     }
 
     if (acquired)
@@ -689,6 +821,7 @@ OnError:
 
     return status;
 }
+#endif
 
 /*******************************************************************************
 **
@@ -720,8 +853,15 @@ _Construct(
     gckHARDWARE hardware;
     gceSTATUS status;
     gckMMU mmu = gcvNULL;
-    gctUINT32_PTR pageTable;
+    gctUINT32_PTR map;
     gctPOINTER pointer = gcvNULL;
+#if gcdPROCESS_ADDRESS_SPACE
+    gctUINT32 i;
+    gctUINT32 physical;
+#endif
+    gctUINT32 physBase;
+    gctUINT32 physSize;
+    gctUINT32 gpuAddress;
 
     gcmkHEADER_ARG("Kernel=0x%x MmuSize=%lu", Kernel, MmuSize);
 
@@ -752,50 +892,44 @@ _Construct(
     mmu->mtlbLogical      = gcvNULL;
     mmu->staticSTLB       = gcvNULL;
     mmu->enabled          = gcvFALSE;
-#ifdef __QNXNTO__
-    mmu->nodeList         = gcvNULL;
-    mmu->nodeMutex        = gcvNULL;
-#endif
+    mmu->mapLogical       = gcvNULL;
 
     /* Create the page table mutex. */
     gcmkONERROR(gckOS_CreateMutex(os, &mmu->pageTableMutex));
 
-#ifdef __QNXNTO__
-    /* Create the node list mutex. */
-    gcmkONERROR(gckOS_CreateMutex(os, &mmu->nodeMutex));
-#endif
-
     if (hardware->mmuVersion == 0)
     {
         mmu->pageTableSize = MmuSize;
 
-        gcmkONERROR(
-            gckOS_AllocateContiguous(os,
-                                     gcvFALSE,
-                                     &mmu->pageTableSize,
-                                     &mmu->pageTablePhysical,
-                                     &pointer));
+        /* Construct address space management table. */
+        gcmkONERROR(gckOS_Allocate(mmu->os,
+                                   mmu->pageTableSize,
+                                   &pointer));
+
+        mmu->mapLogical = pointer;
+
+        /* Construct page table read by GPU. */
+        gcmkONERROR(gckOS_AllocateContiguous(mmu->os,
+                    gcvFALSE,
+                    &mmu->pageTableSize,
+                    &mmu->pageTablePhysical,
+                    (gctPOINTER)&mmu->pageTableLogical));
 
-        mmu->pageTableLogical = pointer;
 
         /* Compute number of entries in page table. */
-        mmu->pageTableEntries = mmu->pageTableSize / sizeof(gctUINT32);
+        gcmkSAFECASTSIZET(mmu->pageTableEntries, mmu->pageTableSize / sizeof(gctUINT32));
 
         /* Mark all pages as free. */
-        pageTable      = mmu->pageTableLogical;
+        map      = mmu->mapLogical;
 
 #if gcdMMU_CLEAR_VALUE
-        _FillPageTable(pageTable, mmu->pageTableEntries, gcdMMU_CLEAR_VALUE);
+        _FillPageTable(mmu->pageTableLogical, mmu->pageTableEntries, gcdMMU_CLEAR_VALUE);
 #endif
 
-        _WritePageEntry(pageTable,     (mmu->pageTableEntries << 8) | gcvMMU_FREE);
-        _WritePageEntry(pageTable + 1, ~0U);
+        _WritePageEntry(map,     (mmu->pageTableEntries << 8) | gcvMMU_FREE);
+        _WritePageEntry(map + 1, ~0U);
         mmu->heapList  = 0;
         mmu->freeNodes = gcvFALSE;
-
-        /* Set page table address. */
-        gcmkONERROR(
-            gckHARDWARE_SetMMU(hardware, (gctPOINTER) mmu->pageTableLogical));
     }
     else
     {
@@ -811,9 +945,55 @@ _Construct(
 
         mmu->mtlbLogical = pointer;
 
+#if gcdPROCESS_ADDRESS_SPACE
+        _FillPageTable(pointer, mmu->mtlbSize / 4, gcdMMU_MTLB_EXCEPTION);
+
+        /* Allocate a array to store stlbs. */
+        gcmkONERROR(gckOS_Allocate(os, mmu->mtlbSize, &mmu->stlbs));
+
+        gckOS_ZeroMemory(mmu->stlbs, mmu->mtlbSize);
+
+        for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+        {
+            gcmkONERROR(gckOS_AtomConstruct(os, &mmu->pageTableDirty[i]));
+        }
+
+        _SetupProcessAddressSpace(mmu);
+
+        /* Map kernel command buffer in MMU. */
+        for (i = 0; i < gcdCOMMAND_QUEUES; i++)
+        {
+            gcmkONERROR(gckOS_GetPhysicalAddress(
+                mmu->os,
+                Kernel->command->queues[i].logical,
+                &physical
+                ));
+
+            gcmkONERROR(gckMMU_FlatMapping(mmu, physical));
+        }
+#else
         /* Invalid all the entries. */
         gcmkONERROR(
             gckOS_ZeroMemory(pointer, mmu->mtlbSize));
+
+        gcmkONERROR(
+            gckOS_QueryOption(mmu->os, "physBase", &physBase));
+
+        gcmkONERROR(
+            gckOS_QueryOption(mmu->os, "physSize", &physSize));
+
+        gcmkONERROR(
+            gckOS_CPUPhysicalToGPUPhysical(mmu->os, physBase, &gpuAddress));
+
+        /* Setup [physBase - physSize) flat mapping. */
+        gcmkONERROR(_FillFlatMapping(
+            mmu,
+            gpuAddress,
+            physSize
+            ));
+
+        gcmkONERROR(_SetupDynamicSpace(mmu));
+#endif
     }
 
     /* Return the gckMMU object pointer. */
@@ -827,15 +1007,17 @@ OnError:
     /* Roll back. */
     if (mmu != gcvNULL)
     {
-        if (mmu->pageTableLogical != gcvNULL)
+        if (mmu->mapLogical != gcvNULL)
         {
-            /* Free the page table. */
+            gcmkVERIFY_OK(
+                gckOS_Free(os, (gctPOINTER) mmu->mapLogical));
+
+
             gcmkVERIFY_OK(
                 gckOS_FreeContiguous(os,
                                      mmu->pageTablePhysical,
                                      (gctPOINTER) mmu->pageTableLogical,
                                      mmu->pageTableSize));
-
         }
 
         if (mmu->mtlbLogical != gcvNULL)
@@ -854,15 +1036,6 @@ OnError:
                 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;
 
@@ -895,24 +1068,14 @@ _Destroy(
     IN gckMMU Mmu
     )
 {
-#ifdef __QNXNTO__
-    gcuVIDMEM_NODE_PTR node, next;
+#if gcdPROCESS_ADDRESS_SPACE
+    gctUINT32 i;
 #endif
-
     gcmkHEADER_ARG("Mmu=0x%x", Mmu);
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
 
-#ifdef __QNXNTO__
-    /* Free all associated virtual memory. */
-    for (node = Mmu->nodeList; node != gcvNULL; node = next)
-    {
-        next = node->Virtual.next;
-        gcmkVERIFY_OK(gckVIDMEM_Free(node));
-    }
-#endif
-
     while (Mmu->staticSTLB != gcvNULL)
     {
         gcsMMU_STLB_PTR pre = Mmu->staticSTLB;
@@ -950,21 +1113,46 @@ _Destroy(
                     Mmu->mtlbSize));
     }
 
-    /* Free the page table. */
-    gcmkVERIFY_OK(
-            gckOS_FreeContiguous(Mmu->os,
-                Mmu->pageTablePhysical,
-                (gctPOINTER) Mmu->pageTableLogical,
-                Mmu->pageTableSize));
+    /* Free address space management table. */
+    if (Mmu->mapLogical != gcvNULL)
+    {
+        gcmkVERIFY_OK(
+            gckOS_Free(Mmu->os, (gctPOINTER) Mmu->mapLogical));
+    }
 
-#ifdef __QNXNTO__
-    /* Delete the node list mutex. */
-    gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->nodeMutex));
-#endif
+    if (Mmu->pageTableLogical != gcvNULL)
+    {
+        /* Free page table. */
+        gcmkVERIFY_OK(
+            gckOS_FreeContiguous(Mmu->os,
+                                 Mmu->pageTablePhysical,
+                                 (gctPOINTER) Mmu->pageTableLogical,
+                                 Mmu->pageTableSize));
+    }
 
     /* Delete the page table mutex. */
     gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->pageTableMutex));
 
+#if gcdPROCESS_ADDRESS_SPACE
+    for (i = 0; i < Mmu->mtlbSize / 4; i++)
+    {
+        struct _gcsMMU_STLB *stlb = ((struct _gcsMMU_STLB **)Mmu->stlbs)[i];
+
+        if (stlb)
+        {
+            gcmkVERIFY_OK(gckOS_FreeContiguous(
+                Mmu->os,
+                stlb->physical,
+                stlb->logical,
+                stlb->size));
+
+            gcmkOS_SAFE_FREE(Mmu->os, stlb);
+        }
+    }
+
+    gcmkOS_SAFE_FREE(Mmu->os, Mmu->stlbs);
+#endif
+
     /* Mark the gckMMU object as unknown. */
     Mmu->object.type = gcvOBJ_UNKNOWN;
 
@@ -993,7 +1181,7 @@ _AdjustIndex(
 {
     gceSTATUS status;
     gctUINT32 index = Index;
-    gctUINT32_PTR map = Mmu->pageTableLogical;
+    gctUINT32_PTR map = Mmu->mapLogical;
 
     gcmkHEADER();
 
@@ -1085,12 +1273,6 @@ gckMMU_Construct(
 
         gcmkONERROR(_Construct(Kernel, MmuSize, &sharedPageTable->mmu));
     }
-    else if (Kernel->hardware->mmuVersion == 0)
-    {
-        /* Set page table address. */
-        gcmkONERROR(
-            gckHARDWARE_SetMMU(Kernel->hardware, (gctPOINTER) sharedPageTable->mmu->pageTableLogical));
-    }
 
     *Mmu = sharedPageTable->mmu;
 
@@ -1166,6 +1348,8 @@ gckMMU_Destroy(
     )
 {
 #if gcdSHARED_PAGETABLE
+    gckOS os = Mmu->os;
+
     sharedPageTable->reference--;
 
     if (sharedPageTable->reference == 0)
@@ -1175,7 +1359,7 @@ gckMMU_Destroy(
             gcmkVERIFY_OK(_Destroy(Mmu));
         }
 
-        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, sharedPageTable));
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, sharedPageTable));
     }
 
     return gcvSTATUS_OK;
@@ -1229,9 +1413,10 @@ _AllocatePages(
     gceSTATUS status;
     gctBOOL mutex = gcvFALSE;
     gctUINT32 index = 0, previous = ~0U, left;
-    gctUINT32_PTR pageTable;
+    gctUINT32_PTR map;
     gctBOOL gotIt;
     gctUINT32 address;
+    gctUINT32 pageCount;
 
     gcmkHEADER_ARG("Mmu=0x%x PageCount=%lu", Mmu, PageCount);
 
@@ -1242,19 +1427,18 @@ _AllocatePages(
 
     if (PageCount > Mmu->pageTableEntries)
     {
-        gcmkPRINT("[galcore]: %s(%d): Run out of free page entry.",
-                  __FUNCTION__, __LINE__);
-
         /* Not enough pages avaiable. */
         gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
     }
 
+    gcmkSAFECASTSIZET(pageCount, PageCount);
+
     /* 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;)
+    for (map = Mmu->mapLogical, gotIt = gcvFALSE; !gotIt;)
     {
         index = Mmu->heapList;
 
@@ -1263,7 +1447,7 @@ _AllocatePages(
             gcmkONERROR(_AdjustIndex(
                 Mmu,
                 index,
-                PageCount,
+                pageCount,
                 gcdVERTEX_START / gcmSIZEOF(gctUINT32),
                 &index
                 ));
@@ -1273,11 +1457,11 @@ _AllocatePages(
         for (; !gotIt && (index < Mmu->pageTableEntries);)
         {
             /* Check the node type. */
-            switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[index])))
+            switch (gcmENTRY_TYPE(_ReadPageEntry(&map[index])))
             {
             case gcvMMU_SINGLE:
                 /* Single odes are valid if we only need 1 page. */
-                if (PageCount == 1)
+                if (pageCount == 1)
                 {
                     gotIt = gcvTRUE;
                 }
@@ -1285,13 +1469,13 @@ _AllocatePages(
                 {
                     /* Move to next node. */
                     previous = index;
-                    index    = _ReadPageEntry(&pageTable[index]) >> 8;
+                    index    = _ReadPageEntry(&map[index]) >> 8;
                 }
                 break;
 
             case gcvMMU_FREE:
                 /* Test if the node has enough space. */
-                if (PageCount <= (_ReadPageEntry(&pageTable[index]) >> 8))
+                if (pageCount <= (_ReadPageEntry(&map[index]) >> 8))
                 {
                     gotIt = gcvTRUE;
                 }
@@ -1299,7 +1483,7 @@ _AllocatePages(
                 {
                     /* Move to next node. */
                     previous = index;
-                    index    = _ReadPageEntry(&pageTable[index + 1]);
+                    index    = _ReadPageEntry(&map[index + 1]);
                 }
                 break;
 
@@ -1319,45 +1503,42 @@ _AllocatePages(
             }
             else
             {
-                gcmkPRINT("[galcore]: %s(%d): Run out of free page entry.",
-                          __FUNCTION__, __LINE__);
-
                 /* Out of resources. */
                 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
             }
         }
     }
 
-    switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[index])))
+    switch (gcmENTRY_TYPE(_ReadPageEntry(&map[index])))
     {
     case gcvMMU_SINGLE:
         /* Unlink single node from free list. */
         gcmkONERROR(
-            _Link(Mmu, previous, _ReadPageEntry(&pageTable[index]) >> 8));
+            _Link(Mmu, previous, _ReadPageEntry(&map[index]) >> 8));
         break;
 
     case gcvMMU_FREE:
         /* Check how many pages will be left. */
-        left = (_ReadPageEntry(&pageTable[index]) >> 8) - PageCount;
+        left = (_ReadPageEntry(&map[index]) >> 8) - pageCount;
         switch (left)
         {
         case 0:
             /* The entire node is consumed, just unlink it. */
             gcmkONERROR(
-                _Link(Mmu, previous, _ReadPageEntry(&pageTable[index + 1])));
+                _Link(Mmu, previous, _ReadPageEntry(&map[index + 1])));
             break;
 
         case 1:
             /* One page will remain.  Convert the node to a single node and
             ** advance the index. */
-            _WritePageEntry(&pageTable[index], (_ReadPageEntry(&pageTable[index + 1]) << 8) | gcvMMU_SINGLE);
+            _WritePageEntry(&map[index], (_ReadPageEntry(&map[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. */
-            _WritePageEntry(&pageTable[index], (left << 8) | gcvMMU_FREE);
+            _WritePageEntry(&map[index], (left << 8) | gcvMMU_FREE);
             index += left;
             break;
         }
@@ -1365,10 +1546,10 @@ _AllocatePages(
     }
 
     /* Mark node as used. */
-    gcmkONERROR(_FillPageTable(&pageTable[index], PageCount, gcvMMU_USED));
+    gcmkONERROR(_FillPageTable(&map[index], pageCount, gcvMMU_USED));
 
     /* Return pointer to page table. */
-    *PageTable = &pageTable[index];
+    *PageTable = &Mmu->pageTableLogical[index];
 
     /* Build virtual address. */
     if (Mmu->hardware->mmuVersion == 0)
@@ -1440,9 +1621,10 @@ _FreePages(
     IN gctSIZE_T PageCount
     )
 {
-    gctUINT32_PTR pageTable;
+    gctUINT32_PTR node;
     gceSTATUS status;
     gctBOOL acquired = gcvFALSE;
+    gctUINT32 pageCount;
 
     gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=%lu",
                    Mmu, PageTable, PageCount);
@@ -1452,8 +1634,10 @@ _FreePages(
     gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
     gcmkVERIFY_ARGUMENT(PageCount > 0);
 
-    /* Convert the pointer. */
-    pageTable = (gctUINT32_PTR) PageTable;
+    gcmkSAFECASTSIZET(pageCount, PageCount);
+
+    /* Get the node by index. */
+    node = Mmu->mapLogical + ((gctUINT32_PTR)PageTable - Mmu->pageTableLogical);
 
     gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
     acquired = gcvTRUE;
@@ -1461,36 +1645,28 @@ _FreePages(
 #if gcdMMU_CLEAR_VALUE
     if (Mmu->hardware->mmuVersion == 0)
     {
-        _FillPageTable(pageTable, PageCount, gcdMMU_CLEAR_VALUE);
+        _FillPageTable(PageTable, pageCount, gcdMMU_CLEAR_VALUE);
     }
 #endif
 
     if (PageCount == 1)
     {
-        /* Single page node. */
-        _WritePageEntry(pageTable,
-                        (~((1U<<8)-1)) | gcvMMU_SINGLE
+       /* Single page node. */
+        _WritePageEntry(node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
 #if gcdUSE_MMU_EXCEPTION
-                        /* Enable exception */
-                        | 1 << 1
+        /* Enable exception */
+        _WritePageEntry(PageTable, (1 << 1));
 #endif
-                        );
     }
     else
     {
         /* Mark the node as free. */
-        _WritePageEntry(pageTable,
-                        (PageCount << 8) | gcvMMU_FREE
-#if gcdUSE_MMU_EXCEPTION
-                        /* Enable exception */
-                        | 1 << 1
-#endif
-                       );
-        _WritePageEntry(pageTable + 1, ~0U);
+        _WritePageEntry(node, (pageCount << 8) | gcvMMU_FREE);
+        _WritePageEntry(node + 1, ~0U);
 
 #if gcdUSE_MMU_EXCEPTION
         /* Enable exception */
-        gcmkVERIFY_OK(_FillPageTable(pageTable + 2, PageCount - 2, 1 << 1));
+        gcmkVERIFY_OK(_FillPageTable(PageTable, pageCount, 1 << 1));
 #endif
     }
 
@@ -1523,7 +1699,7 @@ gckMMU_AllocatePages(
     )
 {
     return gckMMU_AllocatePagesEx(
-                Mmu, PageCount, gcvSURF_UNKNOWN, PageTable, Address);
+                Mmu, PageCount, gcvSURF_TYPE_UNKNOWN, PageTable, Address);
 }
 
 gceSTATUS
@@ -1630,93 +1806,6 @@ gckMMU_FreePages(
 #endif
 }
 
-gceSTATUS
-gckMMU_Enable(
-    IN gckMMU Mmu,
-    IN gctUINT32 PhysBaseAddr,
-    IN gctUINT32 PhysSize
-    )
-{
-    gceSTATUS status;
-#if gcdSHARED_PAGETABLE
-    gckHARDWARE hardware;
-    gctINT i;
-#endif
-
-    gcmkHEADER_ARG("Mmu=0x%x", Mmu);
-
-    /* Verify the arguments. */
-    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
-
-#if gcdSHARED_PAGETABLE
-    if (Mmu->enabled)
-    {
-        gcmkFOOTER_ARG("Status=%d", gcvSTATUS_SKIP);
-        return gcvSTATUS_SKIP;
-    }
-#endif
-
-    if (Mmu->hardware->mmuVersion == 0)
-    {
-        /* Success. */
-        gcmkFOOTER_ARG("Status=%d", gcvSTATUS_SKIP);
-        return gcvSTATUS_SKIP;
-    }
-    else
-    {
-        if (PhysSize != 0)
-        {
-            gcmkONERROR(_FillFlatMapping(
-                Mmu,
-                PhysBaseAddr,
-                PhysSize
-                ));
-        }
-
-        gcmkONERROR(_SetupDynamicSpace(Mmu));
-
-#if gcdSHARED_PAGETABLE
-        for(i = 0; i < gcdMAX_GPU_COUNT; i++)
-        {
-            hardware = sharedPageTable->hardwares[i];
-            if (hardware != gcvNULL)
-            {
-                gcmkONERROR(
-                    gckHARDWARE_SetMMUv2(
-                        hardware,
-                        gcvTRUE,
-                        Mmu->mtlbLogical,
-                        gcvMMU_MODE_4K,
-                        (gctUINT8_PTR)Mmu->mtlbLogical + gcdMMU_MTLB_SIZE,
-                        gcvFALSE
-                        ));
-            }
-        }
-#else
-        gcmkONERROR(
-            gckHARDWARE_SetMMUv2(
-                Mmu->hardware,
-                gcvTRUE,
-                Mmu->mtlbLogical,
-                gcvMMU_MODE_4K,
-                (gctUINT8_PTR)Mmu->mtlbLogical + gcdMMU_MTLB_SIZE,
-                gcvFALSE
-                ));
-#endif
-
-        Mmu->enabled = gcvTRUE;
-
-        /* Success. */
-        gcmkFOOTER_NO();
-        return gcvSTATUS_OK;
-    }
-
-OnError:
-    /* Return the status. */
-    gcmkFOOTER();
-    return status;
-}
-
 gceSTATUS
 gckMMU_SetPage(
     IN gckMMU Mmu,
@@ -1731,7 +1820,6 @@ gckMMU_SetPage(
     gctUINT32 offset = (gctUINT32)PageEntry - (gctUINT32)Mmu->pageTableLogical;
 #endif
 
-    gctUINT32 data;
     gcmkHEADER_ARG("Mmu=0x%x", Mmu);
 
     /* Verify the arguments. */
@@ -1741,15 +1829,13 @@ gckMMU_SetPage(
 
     if (Mmu->hardware->mmuVersion == 0)
     {
-        data = PageAddress;
+        _WritePageEntry(PageEntry, PageAddress);
     }
     else
     {
-        data = _SetPage(PageAddress);
+        _WritePageEntry(PageEntry, _SetPage(PageAddress));
     }
 
-    _WritePageEntry(PageEntry, data);
-
 #if gcdMIRROR_PAGETABLE
     for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
     {
@@ -1771,130 +1857,272 @@ gckMMU_SetPage(
 
     }
 #endif
+
     /* Success. */
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 }
 
-#ifdef __QNXNTO__
+#if gcdPROCESS_ADDRESS_SPACE
 gceSTATUS
-gckMMU_InsertNode(
+gckMMU_GetPageEntry(
     IN gckMMU Mmu,
-    IN gcuVIDMEM_NODE_PTR Node)
+    IN gctUINT32 Address,
+    IN gctUINT32_PTR *PageTable
+    )
 {
     gceSTATUS status;
-    gctBOOL mutex = gcvFALSE;
+    struct _gcsMMU_STLB *stlb;
+    struct _gcsMMU_STLB **stlbs = Mmu->stlbs;
+    gctUINT32 offset = _MtlbOffset(Address);
+    gctUINT32 mtlbEntry;
+    gctBOOL ace = gckHARDWARE_IsFeatureAvailable(Mmu->hardware, gcvFEATURE_ACE);
 
-    gcmkHEADER_ARG("Mmu=0x%x Node=0x%x", Mmu, Node);
+    gcmkHEADER_ARG("Mmu=0x%x", Mmu);
 
+    /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+    gcmkVERIFY_ARGUMENT((Address & 0xFFF) == 0);
 
-    gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
-    mutex = gcvTRUE;
+    stlb = stlbs[offset];
 
-    Node->Virtual.next = Mmu->nodeList;
-    Mmu->nodeList = Node;
+    if (stlb == gcvNULL)
+    {
+        gcmkONERROR(_AllocateStlb(Mmu->os, &stlb));
 
-    gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+        mtlbEntry = stlb->physBase
+                  | gcdMMU_MTLB_4K_PAGE
+                  | gcdMMU_MTLB_PRESENT
+                  ;
 
-    gcmkFOOTER();
+        if (ace)
+        {
+            mtlbEntry = mtlbEntry
+                      /* Secure */
+                      | (1 << 4);
+        }
+
+        /* Insert Slave TLB address to Master TLB entry.*/
+        _WritePageEntry(Mmu->mtlbLogical + offset, mtlbEntry);
+
+        /* Record stlb. */
+        stlbs[offset] = stlb;
+    }
+
+    *PageTable = &stlb->logical[_StlbOffset(Address)];
+
+    /* Success. */
+    gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 
 OnError:
-    if (mutex)
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+_CheckMap(
+    IN gckMMU Mmu
+    )
+{
+    gceSTATUS status;
+    gctUINT32_PTR map = Mmu->mapLogical;
+    gctUINT32 index;
+
+    for (index = Mmu->heapList; index < Mmu->pageTableEntries;)
     {
-        gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+        /* Check the node type. */
+        switch (gcmENTRY_TYPE(_ReadPageEntry(&map[index])))
+        {
+        case gcvMMU_SINGLE:
+            /* Move to next node. */
+            index    = _ReadPageEntry(&map[index]) >> 8;
+            break;
+
+        case gcvMMU_FREE:
+            /* Move to next node. */
+            index    = _ReadPageEntry(&map[index + 1]);
+            break;
+
+        default:
+            gcmkFATAL("MMU table correcupted at index [%u] = %x!", index, map[index]);
+            gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+        }
     }
 
-    gcmkFOOTER();
+    return gcvSTATUS_OK;
+
+OnError:
     return status;
 }
 
 gceSTATUS
-gckMMU_RemoveNode(
+gckMMU_FlatMapping(
     IN gckMMU Mmu,
-    IN gcuVIDMEM_NODE_PTR Node)
+    IN gctUINT32 Physical
+    )
 {
     gceSTATUS status;
-    gctBOOL mutex = gcvFALSE;
-    gcuVIDMEM_NODE_PTR *iter;
+    gctUINT32 index = _AddressToIndex(Mmu, Physical);
+    gctUINT32 i;
+    gctBOOL gotIt = gcvFALSE;
+    gctUINT32_PTR map = Mmu->mapLogical;
+    gctUINT32 previous = ~0U;
+    gctUINT32_PTR pageTable;
 
-    gcmkHEADER_ARG("Mmu=0x%x Node=0x%x", Mmu, Node);
+    gckMMU_GetPageEntry(Mmu, Physical, &pageTable);
 
-    gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+    _WritePageEntry(pageTable, _SetPage(Physical));
 
-    gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
-    mutex = gcvTRUE;
-
-    for (iter = &Mmu->nodeList; *iter; iter = &(*iter)->Virtual.next)
+    if (map)
     {
-        if (*iter == Node)
+        /* Find node which contains index. */
+        for (i = 0; !gotIt && (i < Mmu->pageTableEntries);)
+        {
+            gctUINT32 numPages;
+
+            switch (gcmENTRY_TYPE(_ReadPageEntry(&map[i])))
+            {
+            case gcvMMU_SINGLE:
+                if (i == index)
+                {
+                    gotIt = gcvTRUE;
+                }
+                else
+                {
+                    previous = i;
+                    i = _ReadPageEntry(&map[i]) >> 8;
+                }
+                break;
+
+            case gcvMMU_FREE:
+                numPages = _ReadPageEntry(&map[i]) >> 8;
+                if (index >= i && index < i + numPages)
+                {
+                    gotIt = gcvTRUE;
+                }
+                else
+                {
+                    previous = i;
+                    i = _ReadPageEntry(&map[i + 1]);
+                }
+                break;
+
+            default:
+                gcmkFATAL("MMU table correcupted at index %u!", index);
+                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+            }
+        }
+
+        switch (gcmENTRY_TYPE(_ReadPageEntry(&map[i])))
         {
-            *iter = Node->Virtual.next;
+        case gcvMMU_SINGLE:
+            /* Unlink single node from free list. */
+            gcmkONERROR(
+                _Link(Mmu, previous, _ReadPageEntry(&map[i]) >> 8));
+            break;
+
+        case gcvMMU_FREE:
+            /* Split the node. */
+            {
+                gctUINT32 start;
+                gctUINT32 next = _ReadPageEntry(&map[i+1]);
+                gctUINT32 total = _ReadPageEntry(&map[i]) >> 8;
+                gctUINT32 countLeft = index - i;
+                gctUINT32 countRight = total - countLeft - 1;
+
+                if (countLeft)
+                {
+                    start = i;
+                    _AddFree(Mmu, previous, start, countLeft);
+                    previous = start;
+                }
+
+                if (countRight)
+                {
+                    start = index + 1;
+                    _AddFree(Mmu, previous, start, countRight);
+                    previous = start;
+                }
+
+                _Link(Mmu, previous, 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();
+    /* Roll back. */
     return status;
 }
 
+
+
 gceSTATUS
-gckMMU_FreeHandleMemory(
-    IN gckKERNEL Kernel,
+gckMMU_FreePagesEx(
     IN gckMMU Mmu,
-    IN gctUINT32 Pid
+    IN gctUINT32 Address,
+    IN gctSIZE_T PageCount
     )
 {
+    gctUINT32_PTR node;
     gceSTATUS status;
-    gctBOOL acquired = gcvFALSE;
-    gcuVIDMEM_NODE_PTR curr, next;
 
-    gcmkHEADER_ARG("Kernel=0x%x, Mmu=0x%x Pid=%u", Kernel, Mmu, Pid);
+#if gcdUSE_MMU_EXCEPTION
+    gctUINT32 i;
+    struct _gcsMMU_STLB *stlb;
+    struct _gcsMMU_STLB **stlbs = Mmu->stlbs;
+#endif
+
+    gcmkHEADER_ARG("Mmu=0x%x Address=0x%x PageCount=%lu",
+                   Mmu, Address, PageCount);
 
-    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+    gcmkVERIFY_ARGUMENT(PageCount > 0);
 
-    gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
-    acquired = gcvTRUE;
+    /* Get the node by index. */
+    node = Mmu->mapLogical + _AddressToIndex(Mmu, Address);
 
-    for (curr = Mmu->nodeList; curr != gcvNULL; curr = next)
+    gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+
+    if (PageCount == 1)
     {
-        next = curr->Virtual.next;
+       /* Single page node. */
+        _WritePageEntry(node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
+    }
+    else
+    {
+        /* Mark the node as free. */
+        _WritePageEntry(node, (PageCount << 8) | gcvMMU_FREE);
+        _WritePageEntry(node + 1, ~0U);
+    }
 
-        if (curr->Virtual.processID == Pid)
-        {
-            while (curr->Virtual.unlockPendings[Kernel->core] == 0 && curr->Virtual.lockeds[Kernel->core] > 0)
-            {
-                gcmkONERROR(gckVIDMEM_Unlock(Kernel, curr, gcvSURF_TYPE_UNKNOWN, gcvNULL));
-            }
+    /* We have free nodes. */
+    Mmu->freeNodes = gcvTRUE;
 
-            gcmkVERIFY_OK(gckVIDMEM_Free(curr));
-        }
+#if gcdUSE_MMU_EXCEPTION
+    for (i = 0; i < PageCount; i++)
+    {
+        /* Get */
+        stlb = stlbs[_MtlbOffset(Address)];
+
+        /* Enable exception */
+        stlb->logical[_StlbOffset(Address)] = gcdMMU_STLB_EXCEPTION;
     }
+#endif
 
-    gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
 
-    gcmkFOOTER();
+
+    /* Success. */
+    gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 
 OnError:
-    if (acquired)
-    {
-        gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
-    }
-
     gcmkFOOTER();
     return status;
 }
@@ -1902,42 +2130,53 @@ OnError:
 
 gceSTATUS
 gckMMU_Flush(
-    IN gckMMU Mmu
+    IN gckMMU Mmu,
+    IN gceSURF_TYPE Type
     )
 {
     gckHARDWARE hardware;
-#if gcdSHARED_PAGETABLE
+    gctUINT32 mask;
     gctINT i;
+
+    if (Type == gcvSURF_VERTEX || Type == gcvSURF_INDEX)
+    {
+        mask = gcvPAGE_TABLE_DIRTY_BIT_FE;
+    }
+    else
+    {
+        mask = gcvPAGE_TABLE_DIRTY_BIT_OTHER;
+    }
+
+#if gcdPROCESS_ADDRESS_SPACE
+    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+    {
+        gcmkVERIFY_OK(
+            gckOS_AtomSetMask(Mmu->pageTableDirty[i], mask));
+    }
+#else
+#if gcdSHARED_PAGETABLE
     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
     {
-#if gcdENABLE_VG
-        if (i == gcvCORE_VG)
-        {
-            continue;
-        }
-#endif
         hardware = sharedPageTable->hardwares[i];
         if (hardware)
         {
-            /* Notify cores who use this page table. */
-            gcmkVERIFY_OK(
-                gckOS_AtomSet(hardware->os, hardware->pageTableDirty, 1));
+            gcmkVERIFY_OK(gckOS_AtomSetMask(hardware->pageTableDirty, mask));
         }
     }
 #elif gcdMIRROR_PAGETABLE
-    gctINT i;
-    for (i = 0; i < mirrorPageTable->reference; i++)
+    for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
     {
         hardware = mirrorPageTable->hardwares[i];
 
         /* Notify cores who use this page table. */
         gcmkVERIFY_OK(
-            gckOS_AtomSet(hardware->os, hardware->pageTableDirty, 1));
+            gckOS_AtomSetMask(hardware->pageTableDirty, mask));
     }
 #else
     hardware = Mmu->hardware;
     gcmkVERIFY_OK(
-        gckOS_AtomSet(hardware->os, hardware->pageTableDirty, 1));
+        gckOS_AtomSetMask(hardware->pageTableDirty, mask));
+#endif
 #endif
 
     return gcvSTATUS_OK;
@@ -1949,20 +2188,37 @@ gckMMU_DumpPageTableEntry(
     IN gctUINT32 Address
     )
 {
+#if gcdPROCESS_ADDRESS_SPACE
+    gcsMMU_STLB_PTR *stlbs = Mmu->stlbs;
+    gcsMMU_STLB_PTR stlbDesc = stlbs[_MtlbOffset(Address)];
+#else
     gctUINT32_PTR pageTable;
     gctUINT32 index;
     gctUINT32 mtlb, stlb;
+#endif
 
     gcmkHEADER_ARG("Mmu=0x%08X Address=0x%08X", Mmu, Address);
     gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
 
     gcmkASSERT(Mmu->hardware->mmuVersion > 0);
 
+#if gcdPROCESS_ADDRESS_SPACE
+    if (stlbDesc)
+    {
+        gcmkPRINT("    STLB entry = 0x%08X",
+                  _ReadPageEntry(&stlbDesc->logical[_StlbOffset(Address)]));
+    }
+    else
+    {
+        gcmkPRINT("    MTLB entry is empty.");
+    }
+#else
     mtlb   = (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
-    stlb   = (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
 
-    if (Address >= 0x80000000)
+    if (mtlb >= Mmu->dynamicMappingStart)
     {
+        stlb   = (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
+
         pageTable = Mmu->pageTableLogical;
 
         index = (mtlb - Mmu->dynamicMappingStart)
@@ -1971,6 +2227,28 @@ gckMMU_DumpPageTableEntry(
 
         gcmkPRINT("    Page table entry = 0x%08X", _ReadPageEntry(pageTable + index));
     }
+    else
+    {
+        gcsMMU_STLB_PTR stlbObj = Mmu->staticSTLB;
+        gctUINT32 entry = Mmu->mtlbLogical[mtlb];
+
+        stlb = (Address & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
+
+        entry &= 0xFFFFFFF0;
+
+        while (stlbObj)
+        {
+
+            if (entry == stlbObj->physBase)
+            {
+                gcmkPRINT("    Page table entry = 0x%08X", stlbObj->logical[stlb]);
+                break;
+            }
+
+            stlbObj = stlbObj->next;
+        }
+    }
+#endif
 
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
index 0c20290166a01a41b051aadc0f8f9b2dab9c5845..58c33b1b301d9389262ea19ed25cf1201f1795e5 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -46,7 +46,7 @@
 */
 gceSTATUS gckVGMMU_Construct(
     IN gckVGKERNEL Kernel,
-    IN gctSIZE_T MmuSize,
+    IN gctUINT32 MmuSize,
     OUT gckVGMMU * Mmu
     )
 {
@@ -107,7 +107,7 @@ gceSTATUS gckVGMMU_Construct(
     }
 
     /* Allocate the page table. */
-    mmu->pageTableSize = MmuSize;
+    mmu->pageTableSize = (gctUINT32)MmuSize;
     status = gckOS_AllocateContiguous(os,
                                       gcvFALSE,
                                       &mmu->pageTableSize,
@@ -133,7 +133,7 @@ gceSTATUS gckVGMMU_Construct(
     }
 
     /* Compute number of entries in page table. */
-    mmu->entryCount = mmu->pageTableSize / sizeof(gctUINT32);
+    mmu->entryCount = (gctUINT32)mmu->pageTableSize / sizeof(gctUINT32);
     mmu->entry = 0;
 
     /* Mark the entire page table as available. */
@@ -313,7 +313,7 @@ gceSTATUS gckVGMMU_AllocatePages(
     }
 
     /* Compute the tail for this allocation. */
-    tail = Mmu->entryCount - PageCount;
+    tail = Mmu->entryCount - (gctUINT32)PageCount;
 
     /* Walk all entries until we find enough slots. */
     for (index = Mmu->entry; index <= tail;)
@@ -395,7 +395,7 @@ gceSTATUS gckVGMMU_AllocatePages(
         if (status >= 0)
         {
             /* Update current entry into page table. */
-            Mmu->entry = index + PageCount;
+            Mmu->entry = index + (gctUINT32)PageCount;
 
             /* Return pointer to page table. */
             *PageTable = (gctUINT32 *)  Mmu->pageTableLogical + index;
index df7579da75871ea11dbedd7d876da54af8c916bd..b060310a435bdc23b6032ff709923821f1c22025 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
index 1e764c25710b2b6874149f4f28b12c10ed655e7e..9ea3d53626b40ebde66e83681797d8ba6c000d9d 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security.c
new file mode 100644 (file)
index 0000000..54e5ce3
--- /dev/null
@@ -0,0 +1,239 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2014 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
+
+#if gcdSECURITY
+
+/*
+** Open a security service channel.
+*/
+gceSTATUS
+gckKERNEL_SecurityOpen(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 GPU,
+    OUT gctUINT32 *Channel
+    )
+{
+    gceSTATUS status;
+
+    gcmkONERROR(gckOS_OpenSecurityChannel(Kernel->os, Kernel->core, Channel));
+    gcmkONERROR(gckOS_InitSecurityChannel(*Channel));
+
+    return gcvSTATUS_OK;
+
+OnError:
+    return status;
+}
+
+/*
+** Close a security service channel
+*/
+gceSTATUS
+gckKERNEL_SecurityClose(
+    IN gctUINT32 Channel
+    )
+{
+    return gcvSTATUS_OK;
+}
+
+/*
+** Security service interface.
+*/
+gceSTATUS
+gckKERNEL_SecurityCallService(
+    IN gctUINT32 Channel,
+    IN OUT gcsTA_INTERFACE * Interface
+)
+{
+    gceSTATUS status;
+    gcmkHEADER();
+
+    gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+    gckOS_CallSecurityService(Channel, Interface);
+
+    status = Interface->result;
+
+    gcmkONERROR(status);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityStartCommand(
+    IN gckKERNEL Kernel
+    )
+{
+    gceSTATUS status;
+    gcsTA_INTERFACE iface;
+
+    gcmkHEADER();
+
+    iface.command = KERNEL_START_COMMAND;
+    iface.u.StartCommand.gpu = Kernel->core;
+
+    gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityAllocateSecurityMemory(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Bytes,
+    OUT gctUINT32 * Handle
+    )
+{
+    gceSTATUS status;
+    gcsTA_INTERFACE iface;
+
+    gcmkHEADER();
+
+    iface.command = KERNEL_ALLOCATE_SECRUE_MEMORY;
+    iface.u.AllocateSecurityMemory.bytes = Bytes;
+
+    gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+    *Handle = iface.u.AllocateSecurityMemory.memory_handle;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityExecute(
+    IN gckKERNEL Kernel,
+    IN gctPOINTER Buffer,
+    IN gctUINT32 Bytes
+    )
+{
+    gceSTATUS status;
+    gcsTA_INTERFACE iface;
+
+    gcmkHEADER();
+
+    iface.command = KERNEL_EXECUTE;
+    iface.u.Execute.command_buffer = (gctUINT32 *)Buffer;
+    iface.u.Execute.gpu = Kernel->core;
+    iface.u.Execute.command_buffer_length = Bytes;
+
+#if defined(LINUX)
+    gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os, Buffer,
+            (gctUINT32 *)&iface.u.Execute.command_buffer));
+#endif
+
+    gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+    /* Update queue tail pointer. */
+    gcmkONERROR(gckHARDWARE_UpdateQueueTail(
+        Kernel->hardware, 0, 0
+        ));
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityMapMemory(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 *PhysicalArray,
+    IN gctUINT32 PageCount,
+    OUT gctUINT32 * GPUAddress
+    )
+{
+    gceSTATUS status;
+    gcsTA_INTERFACE iface;
+
+    gcmkHEADER();
+
+    iface.command = KERNEL_MAP_MEMORY;
+
+#if defined(LINUX)
+    gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os, PhysicalArray,
+            (gctUINT32 *)&iface.u.MapMemory.physicals));
+#endif
+
+    iface.u.MapMemory.pageCount = PageCount;
+
+    gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+    *GPUAddress = iface.u.MapMemory.gpuAddress;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityUnmapMemory(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 GPUAddress,
+    IN gctUINT32 PageCount
+    )
+{
+    gceSTATUS status;
+    gcsTA_INTERFACE iface;
+
+    gcmkHEADER();
+
+    iface.command = KERNEL_UNMAP_MEMORY;
+
+    iface.u.UnmapMemory.gpuAddress = GPUAddress;
+    iface.u.UnmapMemory.pageCount  = PageCount;
+
+    gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+#endif
index d7b8e08732522a97846e712081777c708d47067f..eac565cd65f928f20319c1959dedda3d85393f27 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -23,8 +23,6 @@
 
 #if gcdENABLE_VG
 
-#define ENABLE_VG_TRY_VIRTUAL_MEMORY 0
-
 #define _GC_OBJ_ZONE            gcvZONE_VG
 
 /******************************************************************************\
@@ -251,11 +249,11 @@ gceSTATUS gckVGKERNEL_Destroy(
 **          Allocated node.
 */
 gceSTATUS
-gckKERNEL_AllocateLinearMemory(
+gckVGKERNEL_AllocateLinearMemory(
     IN gckKERNEL Kernel,
     IN OUT gcePOOL * Pool,
     IN gctSIZE_T Bytes,
-    IN gctSIZE_T Alignment,
+    IN gctUINT32 Alignment,
     IN gceSURF_TYPE Type,
     OUT gcuVIDMEM_NODE_PTR * Node
     )
@@ -305,13 +303,13 @@ gckKERNEL_AllocateLinearMemory(
 
             if (status == gcvSTATUS_OK)
             {
-                if(*Pool == gcvPOOL_SYSTEM)
-                    Type |= gcvSURF_VG;
                 /* Allocate memory. */
-                status = gckVIDMEM_AllocateLinear(videoMemory,
+                status = gckVIDMEM_AllocateLinear(Kernel,
+                                                  videoMemory,
                                                   Bytes,
                                                   Alignment,
                                                   Type,
+                                                  (*Pool == gcvPOOL_SYSTEM),
                                                   Node);
 
                 if (status == gcvSTATUS_OK)
@@ -335,18 +333,11 @@ gckKERNEL_AllocateLinearMemory(
         else if (pool == gcvPOOL_SYSTEM)
         {
             /* Advance to virtual memory. */
-#if ENABLE_VG_TRY_VIRTUAL_MEMORY
             pool = gcvPOOL_VIRTUAL;
-#else
-            /*VG non-contiguous memory support is not ready yet, disable it temporary*/
-            status = gcvSTATUS_OUT_OF_MEMORY;
-            break;
-#endif
         }
         else
         {
             /* Out of pools. */
-            status = gcvSTATUS_OUT_OF_MEMORY;
             break;
         }
     }
@@ -395,7 +386,6 @@ gceSTATUS gckVGKERNEL_Dispatch(
 {
     gceSTATUS status;
     gcsHAL_INTERFACE * kernelInterface = Interface;
-    gcuVIDMEM_NODE_PTR node;
     gctUINT32 processID;
     gckKERNEL kernel = Kernel;
     gctPOINTER info = gcvNULL;
@@ -443,7 +433,7 @@ gceSTATUS gckVGKERNEL_Dispatch(
     case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
         bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
         /* Allocate non-paged memory. */
-        gcmkERR_BREAK(gckOS_AllocateContiguous(
+        gcmkERR_BREAK(gckOS_AllocateNonPagedMemory(
             Kernel->os,
             gcvTRUE,
             &bytes,
@@ -516,97 +506,28 @@ gceSTATUS gckVGKERNEL_Dispatch(
         break;
 
     case gcvHAL_ALLOCATE_VIDEO_MEMORY:
-        {
-            gctSIZE_T bytes;
-            gctUINT32 bitsPerPixel;
-            gctUINT32 bits;
-
-            /* Align width and height to tiles. */
-            gcmkERR_BREAK(gckVGHARDWARE_AlignToTile(
-                Kernel->vg->hardware,
-                kernelInterface->u.AllocateVideoMemory.type,
-                &kernelInterface->u.AllocateVideoMemory.width,
-                &kernelInterface->u.AllocateVideoMemory.height
-                ));
-
-            /* Convert format into bytes per pixel and bytes per tile. */
-            gcmkERR_BREAK(gckVGHARDWARE_ConvertFormat(
-                Kernel->vg->hardware,
-                kernelInterface->u.AllocateVideoMemory.format,
-                &bitsPerPixel,
-                gcvNULL
-                ));
-
-            /* Compute number of bits for the allocation. */
-            bits
-                = kernelInterface->u.AllocateVideoMemory.width
-                * kernelInterface->u.AllocateVideoMemory.height
-                * kernelInterface->u.AllocateVideoMemory.depth
-                * bitsPerPixel;
-
-            /* Compute number of bytes for the allocation. */
-            bytes = gcmALIGN(bits, 8) / 8;
-
-            /* Allocate memory. */
-            gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
-                Kernel,
-                &kernelInterface->u.AllocateVideoMemory.pool,
-                bytes,
-                64,
-                kernelInterface->u.AllocateVideoMemory.type,
-                &node
-                ));
-
-            kernelInterface->u.AllocateVideoMemory.node = gcmPTR_TO_UINT64(node);
-        }
+        gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED);
         break;
 
     case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
         /* Allocate memory. */
         gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
-            Kernel,
+            Kernel, processID,
             &kernelInterface->u.AllocateLinearVideoMemory.pool,
             kernelInterface->u.AllocateLinearVideoMemory.bytes,
             kernelInterface->u.AllocateLinearVideoMemory.alignment,
             kernelInterface->u.AllocateLinearVideoMemory.type,
-            &node
+            kernelInterface->u.AllocateLinearVideoMemory.flag,
+            &kernelInterface->u.AllocateLinearVideoMemory.node
             ));
 
-        gcmkERR_BREAK(gckKERNEL_AddProcessDB(Kernel,
-           processID, gcvDB_VIDEO_MEMORY,
-           node,
-           gcvNULL,
-           kernelInterface->u.AllocateLinearVideoMemory.bytes
-           ));
-
-        kernelInterface->u.AllocateLinearVideoMemory.node = gcmPTR_TO_UINT64(node);
         break;
 
-    case gcvHAL_FREE_VIDEO_MEMORY:
-        node = gcmUINT64_TO_PTR(Interface->u.FreeVideoMemory.node);
-#ifdef __QNXNTO__
-        /* Unmap the video memory */
-
-        if ((node->VidMem.memory->object.type == gcvOBJ_VIDMEM) &&
-            (node->VidMem.logical != gcvNULL))
-        {
-            gckKERNEL_UnmapVideoMemory(Kernel,
-                                       node->VidMem.logical,
-                                       processID,
-                                       node->VidMem.bytes);
-            node->VidMem.logical = gcvNULL;
-        }
-#endif /* __QNXNTO__ */
-
+    case gcvHAL_RELEASE_VIDEO_MEMORY:
         /* Free video memory. */
-        gcmkERR_BREAK(gckVIDMEM_Free(
-            node
-            ));
-
-        gcmkERR_BREAK(gckKERNEL_RemoveProcessDB(
-            Kernel,
-            processID, gcvDB_VIDEO_MEMORY,
-            node
+        gcmkERR_BREAK(gckKERNEL_ReleaseVideoMemory(
+            Kernel, processID,
+            (gctUINT32)kernelInterface->u.ReleaseVideoMemory.node
             ));
 
         break;
@@ -645,6 +566,9 @@ gceSTATUS gckVGKERNEL_Dispatch(
             ));
 
         kernelInterface->u.MapUserMemory.info = gcmPTR_TO_NAME(info);
+
+        /* Clear temp storage. */
+        info = gcvNULL;
         break;
 
     case gcvHAL_UNMAP_USER_MEMORY:
@@ -657,111 +581,18 @@ gceSTATUS gckVGKERNEL_Dispatch(
             gcmNAME_TO_PTR(kernelInterface->u.UnmapUserMemory.info),
             kernelInterface->u.UnmapUserMemory.address
             ));
+
         gcmRELEASE_NAME(kernelInterface->u.UnmapUserMemory.info);
         break;
-    case gcvHAL_LOCK_VIDEO_MEMORY:
-        node = gcmUINT64_TO_PTR(Interface->u.LockVideoMemory.node);
-
-        /* Lock video memory. */
-        gcmkERR_BREAK(
-            gckVIDMEM_Lock(Kernel,
-                           node,
-                                                  gcvFALSE,
-                           &Interface->u.LockVideoMemory.address));
 
-        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
-        {
-            /* Map video memory address into user space. */
-#ifdef __QNXNTO__
-        if (node->VidMem.logical == gcvNULL)
-        {
-            gcmkONERROR(
-                gckKERNEL_MapVideoMemory(Kernel,
-                                         FromUser,
-                                         Interface->u.LockVideoMemory.address,
-                                         processID,
-                                         node->VidMem.bytes,
-                                         &node->VidMem.logical));
-        }
-
-        Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->VidMem.logical);
-#else
-            gcmkERR_BREAK(
-                gckKERNEL_MapVideoMemoryEx(Kernel,
-                                         gcvCORE_VG,
-                                         FromUser,
-                                         Interface->u.LockVideoMemory.address,
-                                         &logical));
-            Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(logical);
-#endif
-        }
-        else
-        {
-            Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->Virtual.logical);
-
-            /* Success. */
-            status = gcvSTATUS_OK;
-        }
-
-#if gcdSECURE_USER
-        /* Return logical address as physical address. */
-        Interface->u.LockVideoMemory.address =
-            (gctUINT32)(Interface->u.LockVideoMemory.memory);
-#endif
-        gcmkERR_BREAK(
-            gckKERNEL_AddProcessDB(Kernel,
-                                   processID, gcvDB_VIDEO_MEMORY_LOCKED,
-                                   node,
-                                   gcvNULL,
-                                   0));
+    case gcvHAL_LOCK_VIDEO_MEMORY:
+        gcmkONERROR(gckKERNEL_LockVideoMemory(Kernel, gcvCORE_VG, processID, FromUser, Interface));
         break;
 
     case gcvHAL_UNLOCK_VIDEO_MEMORY:
-        /* Unlock video memory. */
-        node = gcmUINT64_TO_PTR(Interface->u.UnlockVideoMemory.node);
-
-#if gcdSECURE_USER
-        /* Save node information before it disappears. */
-        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
-        {
-            logical = gcvNULL;
-            bytes   = 0;
-        }
-        else
-        {
-            logical = node->Virtual.logical;
-            bytes   = node->Virtual.bytes;
-        }
-#endif
-
-        /* Unlock video memory. */
-        gcmkERR_BREAK(
-            gckVIDMEM_Unlock(Kernel,
-                             node,
-                             Interface->u.UnlockVideoMemory.type,
-                             &Interface->u.UnlockVideoMemory.asynchroneous));
-
-#if gcdSECURE_USER
-        /* Flush the translation cache for virtual surfaces. */
-        if (logical != gcvNULL)
-        {
-            gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
-                                                          cache,
-                                                          logical,
-                                                          bytes));
-        }
-#endif
-
-        if (Interface->u.UnlockVideoMemory.asynchroneous == gcvFALSE)
-        {
-            /* There isn't a event to unlock this node, remove record now */
-            gcmkERR_BREAK(
-                    gckKERNEL_RemoveProcessDB(Kernel,
-                        processID, gcvDB_VIDEO_MEMORY_LOCKED,
-                        node));
-        }
-
+        gcmkONERROR(gckKERNEL_UnlockVideoMemory(Kernel, processID, Interface));
         break;
+
     case gcvHAL_USER_SIGNAL:
 #if !USE_NEW_LINUX_SIGNAL
         /* Dispatch depends on the user signal subcommands. */
@@ -783,15 +614,16 @@ gceSTATUS gckVGKERNEL_Dispatch(
             break;
 
         case gcvUSER_SIGNAL_DESTROY:
+            gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+                Kernel,
+                processID, gcvDB_SIGNAL,
+                gcmINT2PTR(Interface->u.UserSignal.id)));
+
             /* Destroy the signal. */
             gcmkERR_BREAK(
                 gckOS_DestroyUserSignal(Kernel->os,
                                         Interface->u.UserSignal.id));
 
-            gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
-                Kernel,
-                processID, gcvDB_SIGNAL,
-                gcmINT2PTR(Interface->u.UserSignal.id)));
             break;
 
         case gcvUSER_SIGNAL_SIGNAL:
@@ -840,6 +672,112 @@ gceSTATUS gckVGKERNEL_Dispatch(
             gckOS_GetBaseAddress(Kernel->os,
                                  &kernelInterface->u.GetBaseAddress.baseAddress));
         break;
+    case gcvHAL_IMPORT_VIDEO_MEMORY:
+        gcmkONERROR(gckVIDMEM_NODE_Import(Kernel,
+                                          Interface->u.ImportVideoMemory.name,
+                                            &Interface->u.ImportVideoMemory.handle));
+        gcmkONERROR(gckKERNEL_AddProcessDB(Kernel,
+                                    processID, gcvDB_VIDEO_MEMORY,
+                                    gcmINT2PTR(Interface->u.ImportVideoMemory.handle),
+                                    gcvNULL,
+                                    0));
+        break;
+
+    case gcvHAL_NAME_VIDEO_MEMORY:
+        gcmkONERROR(gckVIDMEM_NODE_Name(Kernel,
+                                         Interface->u.NameVideoMemory.handle,
+                                         &Interface->u.NameVideoMemory.name));
+        break;
+
+    case gcvHAL_DATABASE:
+        gcmkONERROR(gckKERNEL_QueryDatabase(Kernel, processID, Interface));
+        break;
+    case gcvHAL_SHBUF:
+        {
+            gctSHBUF shBuf;
+            gctPOINTER uData;
+            gctUINT32 bytes;
+
+            switch (Interface->u.ShBuf.command)
+            {
+            case gcvSHBUF_CREATE:
+                bytes = Interface->u.ShBuf.bytes;
+
+                /* Create. */
+                gcmkONERROR(gckKERNEL_CreateShBuffer(Kernel, bytes, &shBuf));
+
+                Interface->u.ShBuf.id = gcmPTR_TO_UINT64(shBuf);
+
+                gcmkVERIFY_OK(
+                    gckKERNEL_AddProcessDB(Kernel,
+                                           processID,
+                                           gcvDB_SHBUF,
+                                           shBuf,
+                                           gcvNULL,
+                                           0));
+                break;
+
+            case gcvSHBUF_DESTROY:
+                shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+
+                /* Check db first to avoid illegal destroy in the process. */
+                gcmkONERROR(
+                    gckKERNEL_RemoveProcessDB(Kernel,
+                                              processID,
+                                              gcvDB_SHBUF,
+                                              shBuf));
+
+                gcmkONERROR(gckKERNEL_DestroyShBuffer(Kernel, shBuf));
+                break;
+
+            case gcvSHBUF_MAP:
+                shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+
+                /* Map for current process access. */
+                gcmkONERROR(gckKERNEL_MapShBuffer(Kernel, shBuf));
+
+                gcmkVERIFY_OK(
+                    gckKERNEL_AddProcessDB(Kernel,
+                                           processID,
+                                           gcvDB_SHBUF,
+                                           shBuf,
+                                           gcvNULL,
+                                           0));
+                break;
+
+            case gcvSHBUF_WRITE:
+                shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+                uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
+                bytes = Interface->u.ShBuf.bytes;
+
+                /* Write. */
+                gcmkONERROR(
+                    gckKERNEL_WriteShBuffer(Kernel, shBuf, uData, bytes));
+                break;
+
+            case gcvSHBUF_READ:
+                shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+                uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
+                bytes = Interface->u.ShBuf.bytes;
+
+                /* Read. */
+                gcmkONERROR(
+                    gckKERNEL_ReadShBuffer(Kernel,
+                                           shBuf,
+                                           uData,
+                                           bytes,
+                                           &bytes));
+
+                /* Return copied size. */
+                Interface->u.ShBuf.bytes = bytes;
+                break;
+
+            default:
+                gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+                break;
+            }
+        }
+        break;
     default:
         /* Invalid command. */
         status = gcvSTATUS_INVALID_ARGUMENT;
index b6c6d7e3bd50ed4c137293de3b1b5b39934eed3d..8bdeb3896f229d37599a80b2f35341193e011fa1 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
index 5699996125cddd55110d1a2e23b013e952d3f637..237b856749066cac244aa691b449c0d9b9eb23e8 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -91,16 +91,8 @@ _Split(
     node->VidMem.pool      = Node->VidMem.pool;
     node->VidMem.physical  = Node->VidMem.physical;
 #ifdef __QNXNTO__
-#if gcdUSE_VIDMEM_PER_PID
-    gcmkASSERT(Node->VidMem.physical != 0);
-    gcmkASSERT(Node->VidMem.logical != gcvNULL);
-    node->VidMem.processID = Node->VidMem.processID;
-    node->VidMem.physical  = Node->VidMem.physical + Bytes;
-    node->VidMem.logical   = Node->VidMem.logical + Bytes;
-#else
     node->VidMem.processID = 0;
     node->VidMem.logical   = gcvNULL;
-#endif
 #endif
 
     /* Insert node behind specified node. */
@@ -150,15 +142,6 @@ _Merge(
 
     /* Save pointer to next node. */
     node = Node->VidMem.next;
-#if gcdUSE_VIDMEM_PER_PID
-    /* Check if the nodes are adjacent physically. */
-    if ( ((Node->VidMem.physical + Node->VidMem.bytes) != node->VidMem.physical) ||
-          ((Node->VidMem.logical + Node->VidMem.bytes) != node->VidMem.logical) )
-    {
-        /* Can't merge. */
-        return gcvSTATUS_OK;
-    }
-#else
 
     /* This is a good time to make sure the heap is not corrupted. */
     if (Node->VidMem.offset + Node->VidMem.bytes != node->VidMem.offset)
@@ -168,7 +151,6 @@ _Merge(
             Node->VidMem.offset + Node->VidMem.bytes == node->VidMem.offset);
         return gcvSTATUS_HEAP_CORRUPTED;
     }
-#endif
 
     /* Adjust byte count. */
     Node->VidMem.bytes += node->VidMem.bytes;
@@ -211,7 +193,7 @@ _Merge(
 gceSTATUS
 gckVIDMEM_ConstructVirtual(
     IN gckKERNEL Kernel,
-    IN gctBOOL Contiguous,
+    IN gctUINT32 Flag,
     IN gctSIZE_T Bytes,
     OUT gcuVIDMEM_NODE_PTR * Node
     )
@@ -222,7 +204,7 @@ gckVIDMEM_ConstructVirtual(
     gctPOINTER pointer = gcvNULL;
     gctINT i;
 
-    gcmkHEADER_ARG("Kernel=0x%x Contiguous=%d Bytes=%lu", Kernel, Contiguous, Bytes);
+    gcmkHEADER_ARG("Kernel=0x%x Flag=%x Bytes=%lu", Kernel, Flag, Bytes);
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
@@ -240,8 +222,11 @@ gckVIDMEM_ConstructVirtual(
 
     /* Initialize gcuVIDMEM_NODE union for virtual memory. */
     node->Virtual.kernel        = Kernel;
-    node->Virtual.contiguous    = Contiguous;
+    node->Virtual.contiguous    = Flag & gcvALLOC_FLAG_CONTIGUOUS;
     node->Virtual.logical       = gcvNULL;
+#if gcdENABLE_VG
+    node->Virtual.kernelVirtual = gcvNULL;
+#endif
 
     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
     {
@@ -250,44 +235,16 @@ gckVIDMEM_ConstructVirtual(
         node->Virtual.lockKernels[i]    = gcvNULL;
     }
 
-    node->Virtual.mutex         = gcvNULL;
-
     gcmkONERROR(gckOS_GetProcessID(&node->Virtual.processID));
 
-#ifdef __QNXNTO__
-    node->Virtual.next          = gcvNULL;
-    node->Virtual.freePending   = gcvFALSE;
-    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
-    {
-        node->Virtual.unlockPendings[i] = gcvFALSE;
-    }
-#endif
-
-    node->Virtual.freed         = gcvFALSE;
-
-    gcmkONERROR(gckOS_ZeroMemory(&node->Virtual.sharedInfo, gcmSIZEOF(gcsVIDMEM_NODE_SHARED_INFO)));
-
-    /* Create the mutex. */
-    gcmkONERROR(
-        gckOS_CreateMutex(os, &node->Virtual.mutex));
-
     /* Allocate the virtual memory. */
     gcmkONERROR(
         gckOS_AllocatePagedMemoryEx(os,
-                                    node->Virtual.contiguous,
+                                    Flag,
                                     node->Virtual.bytes = Bytes,
+                                    &node->Virtual.gid,
                                     &node->Virtual.physical));
 
-#ifdef __QNXNTO__
-    /* Register. */
-#if gcdENABLE_VG
-    if (Kernel->core != gcvCORE_VG)
-#endif
-    {
-        gckMMU_InsertNode(Kernel->mmu, node);
-    }
-#endif
-
     /* Return pointer to the gcuVIDMEM_NODE union. */
     *Node = node;
 
@@ -303,12 +260,6 @@ OnError:
     /* Roll back. */
     if (node != gcvNULL)
     {
-        if (node->Virtual.mutex != gcvNULL)
-        {
-            /* Destroy the mutex. */
-            gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->Virtual.mutex));
-        }
-
         /* Free the structure. */
         gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, node));
     }
@@ -339,7 +290,6 @@ gckVIDMEM_DestroyVirtual(
     )
 {
     gckOS os;
-    gctINT i;
 
     gcmkHEADER_ARG("Node=0x%x", Node);
 
@@ -350,43 +300,6 @@ gckVIDMEM_DestroyVirtual(
     os = Node->Virtual.kernel->os;
     gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
 
-#ifdef __QNXNTO__
-    /* Unregister. */
-#if gcdENABLE_VG
-    if (Node->Virtual.kernel->core != gcvCORE_VG)
-#endif
-    {
-        gcmkVERIFY_OK(
-                gckMMU_RemoveNode(Node->Virtual.kernel->mmu, Node));
-    }
-#endif
-
-    /* Delete the mutex. */
-    gcmkVERIFY_OK(gckOS_DeleteMutex(os, Node->Virtual.mutex));
-
-    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
-    {
-        if (Node->Virtual.pageTables[i] != gcvNULL)
-        {
-#if gcdENABLE_VG
-            if (i == gcvCORE_VG)
-            {
-                /* Free the pages. */
-                gcmkVERIFY_OK(gckVGMMU_FreePages(Node->Virtual.lockKernels[i]->vg->mmu,
-                                               Node->Virtual.pageTables[i],
-                                               Node->Virtual.pageCount));
-            }
-            else
-#endif
-            {
-                /* Free the pages. */
-                gcmkVERIFY_OK(gckMMU_FreePages(Node->Virtual.lockKernels[i]->mmu,
-                                               Node->Virtual.pageTables[i],
-                                               Node->Virtual.pageCount));
-            }
-        }
-    }
-
     /* Delete the gcuVIDMEM_NODE union. */
     gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, Node));
 
@@ -441,6 +354,8 @@ gckVIDMEM_Construct(
     gcuVIDMEM_NODE_PTR node;
     gctINT i, banks = 0;
     gctPOINTER pointer = gcvNULL;
+    gctUINT32 heapBytes;
+    gctUINT32 bankSize;
 
     gcmkHEADER_ARG("Os=0x%x BaseAddress=%08x Bytes=%lu Threshold=%lu "
                    "BankSize=%lu",
@@ -451,6 +366,9 @@ gckVIDMEM_Construct(
     gcmkVERIFY_ARGUMENT(Bytes > 0);
     gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
 
+    gcmkSAFECASTSIZET(heapBytes, Bytes);
+    gcmkSAFECASTSIZET(bankSize, BankSize);
+
     /* Allocate the gckVIDMEM object. */
     gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct _gckVIDMEM), &pointer));
 
@@ -462,35 +380,32 @@ gckVIDMEM_Construct(
 
     /* Set video memory heap information. */
     memory->baseAddress = BaseAddress;
-    memory->bytes       = Bytes;
-    memory->freeBytes   = Bytes;
+    memory->bytes       = heapBytes;
+    memory->freeBytes   = heapBytes;
     memory->threshold   = Threshold;
     memory->mutex       = gcvNULL;
-#if gcdUSE_VIDMEM_PER_PID
-    gcmkONERROR(gckOS_GetProcessID(&memory->pid));
-#endif
 
     BaseAddress = 0;
 
     /* Walk all possible banks. */
     for (i = 0; i < gcmCOUNTOF(memory->sentinel); ++i)
     {
-        gctSIZE_T bytes;
+        gctUINT32 bytes;
 
         if (BankSize == 0)
         {
             /* Use all bytes for the first bank. */
-            bytes = Bytes;
+            bytes = heapBytes;
         }
         else
         {
             /* Compute number of bytes for this bank. */
-            bytes = gcmALIGN(BaseAddress + 1, BankSize) - BaseAddress;
+            bytes = gcmALIGN(BaseAddress + 1, bankSize) - BaseAddress;
 
-            if (bytes > Bytes)
+            if (bytes > heapBytes)
             {
                 /* Make sure we don't exceed the total number of bytes. */
-                bytes = Bytes;
+                bytes = heapBytes;
             }
         }
 
@@ -525,24 +440,13 @@ gckVIDMEM_Construct(
 
         node->VidMem.locked    = 0;
 
-#if gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
-        node->VidMem.kernelVirtual = gcvNULL;
-#endif
-
-        gcmkONERROR(gckOS_ZeroMemory(&node->VidMem.sharedInfo, gcmSIZEOF(gcsVIDMEM_NODE_SHARED_INFO)));
-
 #ifdef __QNXNTO__
-#if gcdUSE_VIDMEM_PER_PID
-        node->VidMem.processID = memory->pid;
-        node->VidMem.physical  = memory->baseAddress + BaseAddress;
-        gcmkONERROR(gckOS_GetLogicalAddressProcess(Os,
-                    node->VidMem.processID,
-                    node->VidMem.physical,
-                    &node->VidMem.logical));
-#else
         node->VidMem.processID = 0;
         node->VidMem.logical   = gcvNULL;
 #endif
+
+#if gcdENABLE_VG
+        node->VidMem.kernelVirtual = gcvNULL;
 #endif
 
         /* Initialize the linked list of nodes. */
@@ -556,7 +460,7 @@ gckVIDMEM_Construct(
 
         /* Adjust address for next bank. */
         BaseAddress += bytes;
-        Bytes       -= bytes;
+        heapBytes       -= bytes;
         banks       ++;
     }
 
@@ -702,89 +606,6 @@ gckVIDMEM_Destroy(
     return gcvSTATUS_OK;
 }
 
-/*******************************************************************************
-**
-**  gckVIDMEM_Allocate
-**
-**  Allocate rectangular memory from the gckVIDMEM object.
-**
-**  INPUT:
-**
-**      gckVIDMEM Memory
-**          Pointer to an gckVIDMEM object.
-**
-**      gctUINT Width
-**          Width of rectangle to allocate.  Make sure the width is properly
-**          aligned.
-**
-**      gctUINT Height
-**          Height of rectangle to allocate.  Make sure the height is properly
-**          aligned.
-**
-**      gctUINT Depth
-**          Depth of rectangle to allocate.  This equals to the number of
-**          rectangles to allocate contiguously (i.e., for cubic maps and volume
-**          textures).
-**
-**      gctUINT BytesPerPixel
-**          Number of bytes per pixel.
-**
-**      gctUINT32 Alignment
-**          Byte alignment for allocation.
-**
-**      gceSURF_TYPE Type
-**          Type of surface to allocate (use by bank optimization).
-**
-**  OUTPUT:
-**
-**      gcuVIDMEM_NODE_PTR * Node
-**          Pointer to a variable that will hold the allocated memory node.
-*/
-gceSTATUS
-gckVIDMEM_Allocate(
-    IN gckVIDMEM Memory,
-    IN gctUINT Width,
-    IN gctUINT Height,
-    IN gctUINT Depth,
-    IN gctUINT BytesPerPixel,
-    IN gctUINT32 Alignment,
-    IN gceSURF_TYPE Type,
-    OUT gcuVIDMEM_NODE_PTR * Node
-    )
-{
-    gctSIZE_T bytes;
-    gceSTATUS status;
-
-    gcmkHEADER_ARG("Memory=0x%x Width=%u Height=%u Depth=%u BytesPerPixel=%u "
-                   "Alignment=%u Type=%d",
-                   Memory, Width, Height, Depth, BytesPerPixel, Alignment,
-                   Type);
-
-    /* Verify the arguments. */
-    gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
-    gcmkVERIFY_ARGUMENT(Width > 0);
-    gcmkVERIFY_ARGUMENT(Height > 0);
-    gcmkVERIFY_ARGUMENT(Depth > 0);
-    gcmkVERIFY_ARGUMENT(BytesPerPixel > 0);
-    gcmkVERIFY_ARGUMENT(Node != gcvNULL);
-
-    /* Compute linear size. */
-    bytes = Width * Height * Depth * BytesPerPixel;
-
-    /* Allocate through linear function. */
-    gcmkONERROR(
-        gckVIDMEM_AllocateLinear(Memory, bytes, Alignment, Type, Node));
-
-    /* Success. */
-    gcmkFOOTER_ARG("*Node=0x%x", *Node);
-    return gcvSTATUS_OK;
-
-OnError:
-    /* Return the status. */
-    gcmkFOOTER();
-    return status;
-}
-
 #if gcdENABLE_BANK_ALIGNMENT
 
 #if !gcdBANK_BIT_START
@@ -820,6 +641,7 @@ OnError:
 */
 static gceSTATUS
 _GetSurfaceBankAlignment(
+    IN gckKERNEL Kernel,
     IN gceSURF_TYPE Type,
     IN gctUINT32 BaseAddress,
     OUT gctUINT32_PTR AlignmentOffset
@@ -857,8 +679,14 @@ _GetSurfaceBankAlignment(
             0 :
             ((1 << (gcdBANK_BIT_END + 1)) + (2 << gcdBANK_BIT_START)) -  (BaseAddress & byteMask);
 
-        /* Add a channel offset at the channel bit. */
-        *AlignmentOffset += (1 << gcdBANK_CHANNEL_BIT);
+        /* Minimum 256 byte alignment needed for fast_msaa. */
+        if ((gcdBANK_CHANNEL_BIT > 7) ||
+            ((gckHARDWARE_IsFeatureAvailable(Kernel->hardware, gcvFEATURE_FAST_MSAA) != gcvSTATUS_TRUE) &&
+             (gckHARDWARE_IsFeatureAvailable(Kernel->hardware, gcvFEATURE_SMALL_MSAA) != gcvSTATUS_TRUE)))
+        {
+            /* Add a channel offset at the channel bit. */
+            *AlignmentOffset += (1 << gcdBANK_CHANNEL_BIT);
+        }
         break;
 
     default:
@@ -874,6 +702,7 @@ _GetSurfaceBankAlignment(
 
 static gcuVIDMEM_NODE_PTR
 _FindNode(
+    IN gckKERNEL Kernel,
     IN gckVIDMEM Memory,
     IN gctINT Bank,
     IN gctSIZE_T Bytes,
@@ -902,7 +731,13 @@ _FindNode(
          node->VidMem.bytes != 0;
          node = node->VidMem.nextFree)
     {
+        if (node->VidMem.bytes < Bytes)
+        {
+            continue;
+        }
+
         gcmkONERROR(_GetSurfaceBankAlignment(
+            Kernel,
             Type,
             node->VidMem.memory->baseAddress + node->VidMem.offset,
             &bankAlignment));
@@ -935,8 +770,13 @@ _FindNode(
          node->VidMem.bytes != 0;
          node = node->VidMem.nextFree)
     {
+        gctUINT offset;
 
-        gctINT modulo = gckMATH_ModuloInt(node->VidMem.offset, *Alignment);
+        gctINT modulo;
+
+        gcmkSAFECASTSIZET(offset, node->VidMem.offset);
+
+        modulo = gckMATH_ModuloInt(offset, *Alignment);
 
         /* Compute number of bytes to skip for alignment. */
         alignment = (*Alignment == 0) ? 0 : (*Alignment - modulo);
@@ -982,6 +822,11 @@ OnError:
 **      gceSURF_TYPE Type
 **          Type of surface to allocate (use by bank optimization).
 **
+**      gctBOOL Specified
+**          If user must use this pool, it should set Specified to gcvTRUE,
+**          otherwise allocator may reserve some memory for other usage, such
+**          as small block size allocation request.
+**
 **  OUTPUT:
 **
 **      gcuVIDMEM_NODE_PTR * Node
@@ -989,10 +834,12 @@ OnError:
 */
 gceSTATUS
 gckVIDMEM_AllocateLinear(
+    IN gckKERNEL Kernel,
     IN gckVIDMEM Memory,
     IN gctSIZE_T Bytes,
     IN gctUINT32 Alignment,
     IN gceSURF_TYPE Type,
+    IN gctBOOL Specified,
     OUT gcuVIDMEM_NODE_PTR * Node
     )
 {
@@ -1001,14 +848,10 @@ gckVIDMEM_AllocateLinear(
     gctUINT32 alignment;
     gctINT bank, i;
     gctBOOL acquired = gcvFALSE;
-#if gcdSMALL_BLOCK_SIZE
-    gctBOOL force_allocate = (Type == gcvSURF_TILE_STATUS) || (Type & gcvSURF_VG);
-#endif
 
     gcmkHEADER_ARG("Memory=0x%x Bytes=%lu Alignment=%u Type=%d",
                    Memory, Bytes, Alignment, Type);
 
-    Type &= ~gcvSURF_VG;
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
     gcmkVERIFY_ARGUMENT(Bytes > 0);
@@ -1019,7 +862,6 @@ gckVIDMEM_AllocateLinear(
     gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
 
     acquired = gcvTRUE;
-#if !gcdUSE_VIDMEM_PER_PID
 
     if (Bytes > Memory->freeBytes)
     {
@@ -1027,11 +869,11 @@ gckVIDMEM_AllocateLinear(
         status = gcvSTATUS_OUT_OF_MEMORY;
         goto OnError;
     }
-#endif
 
 #if gcdSMALL_BLOCK_SIZE
-    if ((!force_allocate) && (Memory->freeBytes < (Memory->bytes/gcdRATIO_FOR_SMALL_MEMORY))
+    if ((Memory->freeBytes < (Memory->bytes/gcdRATIO_FOR_SMALL_MEMORY))
     &&  (Bytes >= gcdSMALL_BLOCK_SIZE)
+    &&  (Specified == gcvFALSE)
     )
     {
         /* The left memory is for small memory.*/
@@ -1045,12 +887,8 @@ gckVIDMEM_AllocateLinear(
     bank      = Memory->mapping[Type];
     alignment = Alignment;
 
-#if gcdUSE_VIDMEM_PER_PID
-    if (Bytes <= Memory->freeBytes)
-    {
-#endif
     /* Find a free node in the default bank. */
-    node = _FindNode(Memory, bank, Bytes, Type, &alignment);
+    node = _FindNode(Kernel, Memory, bank, Bytes, Type, &alignment);
 
     /* Out of memory? */
     if (node == gcvNULL)
@@ -1059,7 +897,7 @@ gckVIDMEM_AllocateLinear(
         for (i = bank - 1; i >= 0; --i)
         {
             /* Find a free node inside the current bank. */
-            node = _FindNode(Memory, i, Bytes, Type, &alignment);
+            node = _FindNode(Kernel, Memory, i, Bytes, Type, &alignment);
             if (node != gcvNULL)
             {
                 break;
@@ -1079,79 +917,19 @@ gckVIDMEM_AllocateLinear(
             }
 
             /* Find a free node inside the current bank. */
-            node = _FindNode(Memory, i, Bytes, Type, &alignment);
+            node = _FindNode(Kernel, Memory, i, Bytes, Type, &alignment);
             if (node != gcvNULL)
             {
                 break;
             }
         }
     }
-#if gcdUSE_VIDMEM_PER_PID
-    }
-#endif
 
     if (node == gcvNULL)
     {
         /* Out of memory. */
-#if gcdUSE_VIDMEM_PER_PID
-        /* Allocate more memory from shared pool. */
-        gctSIZE_T bytes;
-        gctPHYS_ADDR physical_temp;
-        gctUINT32 physical;
-        gctPOINTER logical;
-
-        bytes = gcmALIGN(Bytes, gcdUSE_VIDMEM_PER_PID_SIZE);
-
-        gcmkONERROR(gckOS_AllocateContiguous(Memory->os,
-                gcvTRUE,
-                &bytes,
-                &physical_temp,
-                &logical));
-
-        /* physical address is returned as 0 for user space. workaround. */
-        if (physical_temp == gcvNULL)
-        {
-        gcmkONERROR(gckOS_GetPhysicalAddress(Memory->os, logical, &physical));
-        }
-
-        /* Allocate one gcuVIDMEM_NODE union. */
-        gcmkONERROR(
-            gckOS_Allocate(Memory->os,
-                           gcmSIZEOF(gcuVIDMEM_NODE),
-                           (gctPOINTER *) &node));
-
-        /* Initialize gcuVIDMEM_NODE union. */
-        node->VidMem.memory    = Memory;
-
-        node->VidMem.offset    = 0;
-        node->VidMem.bytes     = bytes;
-        node->VidMem.alignment = 0;
-        node->VidMem.physical  = physical;
-        node->VidMem.pool      = gcvPOOL_UNKNOWN;
-
-        node->VidMem.locked    = 0;
-
-#ifdef __QNXNTO__
-        gcmkONERROR(gckOS_GetProcessID(&node->VidMem.processID));
-        node->VidMem.logical   = logical;
-        gcmkASSERT(logical != gcvNULL);
-#endif
-
-        /* Insert node behind sentinel node. */
-        node->VidMem.next = Memory->sentinel[bank].VidMem.next;
-        node->VidMem.prev = &Memory->sentinel[bank];
-        Memory->sentinel[bank].VidMem.next = node->VidMem.next->VidMem.prev = node;
-
-        /* Insert free node behind sentinel node. */
-        node->VidMem.nextFree = Memory->sentinel[bank].VidMem.nextFree;
-        node->VidMem.prevFree = &Memory->sentinel[bank];
-        Memory->sentinel[bank].VidMem.nextFree = node->VidMem.nextFree->VidMem.prevFree = node;
-
-        Memory->freeBytes += bytes;
-#else
         status = gcvSTATUS_OUT_OF_MEMORY;
         goto OnError;
-#endif
     }
 
     /* Do we have an alignment? */
@@ -1185,20 +963,14 @@ gckVIDMEM_AllocateLinear(
     node->VidMem.alignment = alignment;
     node->VidMem.memory    = Memory;
 #ifdef __QNXNTO__
-#if !gcdUSE_VIDMEM_PER_PID
     node->VidMem.logical   = gcvNULL;
     gcmkONERROR(gckOS_GetProcessID(&node->VidMem.processID));
-#else
-    gcmkASSERT(node->VidMem.logical != gcvNULL);
-#endif
 #endif
 
     /* Adjust the number of free bytes. */
     Memory->freeBytes -= node->VidMem.bytes;
 
-    node->VidMem.freePending = gcvFALSE;
-
-#if gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
+#if gcdENABLE_VG
     node->VidMem.kernelVirtual = gcvNULL;
 #endif
 
@@ -1236,6 +1008,9 @@ OnError:
 **
 **  INPUT:
 **
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
 **      gcuVIDMEM_NODE_PTR Node
 **          Pointer to a gcuVIDMEM_NODE object.
 **
@@ -1245,6 +1020,7 @@ OnError:
 */
 gceSTATUS
 gckVIDMEM_Free(
+    IN gckKERNEL Kernel,
     IN gcuVIDMEM_NODE_PTR Node
     )
 {
@@ -1253,9 +1029,6 @@ gckVIDMEM_Free(
     gckVIDMEM memory = gcvNULL;
     gcuVIDMEM_NODE_PTR node;
     gctBOOL mutexAcquired = gcvFALSE;
-    gckOS os = gcvNULL;
-    gctBOOL acquired = gcvFALSE;
-    gctINT32 i, totalLocked;
 
     gcmkHEADER_ARG("Node=0x%x", Node);
 
@@ -1272,19 +1045,6 @@ gckVIDMEM_Free(
 
     if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
     {
-        if (Node->VidMem.locked > 0)
-        {
-            /* Client still has a lock, defer free op 'till when lock reaches 0. */
-            Node->VidMem.freePending = gcvTRUE;
-
-            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
-                           "Node 0x%x is locked (%d)... deferring free.",
-                           Node, Node->VidMem.locked);
-
-            gcmkFOOTER_NO();
-            return gcvSTATUS_OK;
-        }
-
         /* Extract pointer to gckVIDMEM object owning the node. */
         memory = Node->VidMem.memory;
 
@@ -1295,11 +1055,19 @@ gckVIDMEM_Free(
         mutexAcquired = gcvTRUE;
 
 #ifdef __QNXNTO__
-#if !gcdUSE_VIDMEM_PER_PID
+        /* Unmap the video memory. */
+        if (Node->VidMem.logical != gcvNULL)
+        {
+            gckKERNEL_UnmapVideoMemory(
+                    Kernel,
+                    Node->VidMem.logical,
+                    Node->VidMem.processID,
+                    Node->VidMem.bytes);
+            Node->VidMem.logical = gcvNULL;
+        }
+
         /* Reset. */
         Node->VidMem.processID = 0;
-        Node->VidMem.logical = gcvNULL;
-#endif
 
         /* Don't try to re-free an already freed node. */
         if ((Node->VidMem.nextFree == gcvNULL)
@@ -1307,7 +1075,7 @@ gckVIDMEM_Free(
         )
 #endif
         {
-#if gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
+#if gcdENABLE_VG
             if (Node->VidMem.kernelVirtual)
             {
                 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
@@ -1389,44 +1157,30 @@ gckVIDMEM_Free(
     /* Verify the gckKERNEL object pointer. */
     gcmkVERIFY_OBJECT(kernel, gcvOBJ_KERNEL);
 
-    /* Get the gckOS object pointer. */
-    os = kernel->os;
-    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
-
-    /* Grab the mutex. */
-    gcmkONERROR(
-        gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
-
-    acquired = gcvTRUE;
-
-    for (i = 0, totalLocked = 0; i < gcdMAX_GPU_COUNT; i++)
-    {
-        totalLocked += Node->Virtual.lockeds[i];
-    }
-
-    if (totalLocked > 0)
+#if gcdENABLE_VG
+    if (Node->Virtual.kernelVirtual)
     {
-        gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_VIDMEM,
-                       "gckVIDMEM_Free: Virtual node 0x%x is locked (%d)",
-                       Node, totalLocked);
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                "%s(%d) Unmap %x from kernel space.",
+                __FUNCTION__, __LINE__,
+                Node->Virtual.kernelVirtual);
 
-        /* Set Flag */
-        Node->Virtual.freed = gcvTRUE;
+        gcmkVERIFY_OK(
+            gckOS_UnmapPhysical(kernel->os,
+                                Node->Virtual.kernelVirtual,
+                                Node->Virtual.bytes));
 
-        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+        Node->Virtual.kernelVirtual = gcvNULL;
     }
-    else
-    {
-        /* Free the virtual memory. */
-        gcmkVERIFY_OK(gckOS_FreePagedMemory(kernel->os,
-                                            Node->Virtual.physical,
-                                            Node->Virtual.bytes));
+#endif
 
-        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+    /* Free the virtual memory. */
+    gcmkVERIFY_OK(gckOS_FreePagedMemory(kernel->os,
+                                        Node->Virtual.physical,
+                                        Node->Virtual.bytes));
 
-        /* Destroy the gcuVIDMEM_NODE union. */
-        gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node));
-    }
+    /* Destroy the gcuVIDMEM_NODE union. */
+    gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node));
 
     /* Success. */
     gcmkFOOTER_NO();
@@ -1441,209 +1195,196 @@ OnError:
             ));
     }
 
-    if (acquired)
-    {
-       gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
-    }
-
     /* Return the status. */
     gcmkFOOTER();
     return status;
 }
 
-
-#ifdef __QNXNTO__
+#if !gcdPROCESS_ADDRESS_SPACE
 /*******************************************************************************
 **
-**  gcoVIDMEM_FreeHandleMemory
+** _NeedVirtualMapping
 **
-**  Free all allocated video memory nodes for a handle.
+**  Whether setup GPU page table for video node.
 **
 **  INPUT:
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
 **
-**      gcoVIDMEM Memory
-**          Pointer to an gcoVIDMEM object..
+**      gcuVIDMEM_NODE_PTR Node
+**          Pointer to a gcuVIDMEM_NODE union.
 **
-**  OUTPUT:
+**      gceCORE  Core
+**          Id of current GPU.
 **
-**      Nothing.
+**  OUTPUT:
+**      gctBOOL * NeedMapping
+**          A pointer hold the result whether Node should be mapping.
 */
-gceSTATUS
-gckVIDMEM_FreeHandleMemory(
+static gceSTATUS
+_NeedVirtualMapping(
     IN gckKERNEL Kernel,
-    IN gckVIDMEM Memory,
-    IN gctUINT32 Pid
-    )
+    IN gceCORE  Core,
+    IN gcuVIDMEM_NODE_PTR Node,
+    OUT gctBOOL * NeedMapping
+)
 {
     gceSTATUS status;
-    gctBOOL mutex = gcvFALSE;
-    gcuVIDMEM_NODE_PTR node;
-    gctINT i;
-    gctUINT32 nodeCount = 0, byteCount = 0;
-    gctBOOL again;
-
-    gcmkHEADER_ARG("Kernel=0x%x, Memory=0x%x Pid=0x%u", Kernel, Memory, Pid);
+    gctUINT32 phys;
+    gctUINT32 end;
+    gcePOOL pool;
+    gctUINT32 offset;
+    gctUINT32 baseAddress;
+    gctUINT32 bytes;
 
-    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
-    gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+    gcmkHEADER_ARG("Node=0x%X", Node);
 
-    gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
-    mutex = gcvTRUE;
+    /* Verify the arguments. */
+    gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+    gcmkVERIFY_ARGUMENT(NeedMapping != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Core < gcdMAX_GPU_COUNT);
 
-    /* Walk all sentinels. */
-    for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i)
+    if (Node->Virtual.contiguous)
     {
-        /* Bail out of the heap if it is not used. */
-        if (Memory->sentinel[i].VidMem.next == gcvNULL)
+#if gcdENABLE_VG
+        if (Core == gcvCORE_VG)
         {
-            break;
+            *NeedMapping = gcvFALSE;
         }
-
-        do
+        else
+#endif
         {
-            again = gcvFALSE;
+            /* Convert logical address into a physical address. */
+            gcmkONERROR(gckOS_UserLogicalToPhysical(
+                        Kernel->os, Node->Virtual.logical, &phys
+                        ));
 
-            /* Walk all the nodes until we reach the sentinel. */
-            for (node = Memory->sentinel[i].VidMem.next;
-                 node->VidMem.bytes != 0;
-                 node = node->VidMem.next)
-            {
-                /* Free the node if it was allocated by Handle. */
-                if (node->VidMem.processID == Pid)
-                {
-                    /* Unlock video memory. */
-                    while (node->VidMem.locked > 0)
-                    {
-                        gckVIDMEM_Unlock(Kernel, node, gcvSURF_TYPE_UNKNOWN, gcvNULL);
-                    }
+            gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &baseAddress));
 
-                    nodeCount++;
-                    byteCount += node->VidMem.bytes;
+            gcmkASSERT(phys >= baseAddress);
 
-                    /* Free video memory. */
-                    gcmkVERIFY_OK(gckVIDMEM_Free(node));
+            /* Subtract baseAddress to get a GPU address used for programming. */
+            phys -= baseAddress;
 
-                    /*
-                     * Freeing may cause a merge which will invalidate our iteration.
-                     * Don't be clever, just restart.
-                     */
-                    again = gcvTRUE;
+            /* If part of region is belong to gcvPOOL_VIRTUAL,
+            ** whole region has to be mapped. */
+            gcmkSAFECASTSIZET(bytes, Node->Virtual.bytes);
+            end = phys + bytes - 1;
 
-                    break;
-                }
-#if gcdUSE_VIDMEM_PER_PID
-                else
-                {
-                    gcmkASSERT(node->VidMem.processID == Pid);
-                }
-#endif
-            }
+            gcmkONERROR(gckHARDWARE_SplitMemory(
+                        Kernel->hardware, end, &pool, &offset
+                        ));
+
+            *NeedMapping = (pool == gcvPOOL_VIRTUAL);
         }
-        while (again);
+    }
+    else
+    {
+        *NeedMapping = gcvTRUE;
     }
 
-    gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
-    gcmkFOOTER();
+    gcmkFOOTER_ARG("*NeedMapping=%d", *NeedMapping);
     return gcvSTATUS_OK;
 
 OnError:
-    if (mutex)
-    {
-        gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
-    }
-
     gcmkFOOTER();
     return status;
 }
 #endif
 
-/*******************************************************************************
-**
-** _NeedVirtualMapping
-**
-**  Whether setup GPU page table for video node.
-**
-**  INPUT:
-**      gckKERNEL Kernel
-**          Pointer to an gckKERNEL object.
-**
-**      gcuVIDMEM_NODE_PTR Node
-**          Pointer to a gcuVIDMEM_NODE union.
-**
-**      gceCORE  Core
-**          Id of current GPU.
-**
-**  OUTPUT:
-**      gctBOOL * NeedMapping
-**          A pointer hold the result whether Node should be mapping.
-*/
-static gceSTATUS
-_NeedVirtualMapping(
-    IN gckKERNEL Kernel,
-    IN gceCORE  Core,
-    IN gcuVIDMEM_NODE_PTR Node,
-    OUT gctBOOL * NeedMapping
-)
+#if gcdPROCESS_ADDRESS_SPACE
+gcsGPU_MAP_PTR
+_FindGPUMap(
+    IN gcsGPU_MAP_PTR Head,
+    IN gctINT ProcessID
+    )
 {
-    gceSTATUS status;
-    gctUINT32 phys;
-    gctUINT32 end;
-    gcePOOL pool;
-    gctUINT32 offset;
-    gctUINT32 baseAddress;
-
-    gcmkHEADER_ARG("Node=0x%X", Node);
-
-    /* Verify the arguments. */
-    gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
-    gcmkVERIFY_ARGUMENT(Node != gcvNULL);
-    gcmkVERIFY_ARGUMENT(NeedMapping != gcvNULL);
-    gcmkVERIFY_ARGUMENT(Core < gcdMAX_GPU_COUNT);
+    gcsGPU_MAP_PTR map = Head;
 
-    if (Node->Virtual.contiguous)
+    while (map)
     {
-#if gcdENABLE_VG
-        if (Core == gcvCORE_VG)
+        if (map->pid == ProcessID)
         {
-            *NeedMapping = gcvFALSE;
+            return map;
         }
-        else
-#endif
-        {
-            /* Convert logical address into a physical address. */
-            gcmkONERROR(
-                gckOS_GetPhysicalAddress(Kernel->os, Node->Virtual.logical, &phys));
 
-            gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &baseAddress));
+        map = map->next;
+    }
 
-            gcmkASSERT(phys >= baseAddress);
+    return gcvNULL;
+}
 
-            /* Subtract baseAddress to get a GPU address used for programming. */
-            phys -= baseAddress;
+gcsGPU_MAP_PTR
+_CreateGPUMap(
+    IN gckOS Os,
+    IN gcsGPU_MAP_PTR *Head,
+    IN gcsGPU_MAP_PTR *Tail,
+    IN gctINT ProcessID
+    )
+{
+    gcsGPU_MAP_PTR gpuMap;
+    gctPOINTER pointer = gcvNULL;
 
-            /* If part of region is belong to gcvPOOL_VIRTUAL,
-            ** whole region has to be mapped. */
-            end = phys + Node->Virtual.bytes - 1;
+    gckOS_Allocate(Os, sizeof(gcsGPU_MAP), &pointer);
 
-            gcmkONERROR(gckHARDWARE_SplitMemory(
-                        Kernel->hardware, end, &pool, &offset
-                        ));
+    if (pointer == gcvNULL)
+    {
+        return gcvNULL;
+    }
 
-            *NeedMapping = (pool == gcvPOOL_VIRTUAL);
-        }
+    gpuMap = pointer;
+
+    gckOS_ZeroMemory(pointer, sizeof(gcsGPU_MAP));
+
+    gpuMap->pid = ProcessID;
+
+    if (!*Head)
+    {
+        *Head = *Tail = gpuMap;
     }
     else
     {
-        *NeedMapping = gcvTRUE;
+        gpuMap->prev = *Tail;
+        (*Tail)->next = gpuMap;
+        *Tail = gpuMap;
     }
 
-    gcmkFOOTER_ARG("*NeedMapping=%d", *NeedMapping);
-    return gcvSTATUS_OK;
+    return gpuMap;
+}
 
-OnError:
-    gcmkFOOTER();
-    return status;
+void
+_DestroyGPUMap(
+    IN gckOS Os,
+    IN gcsGPU_MAP_PTR *Head,
+    IN gcsGPU_MAP_PTR *Tail,
+    IN gcsGPU_MAP_PTR gpuMap
+    )
+{
+
+    if (gpuMap == *Head)
+    {
+        if ((*Head = gpuMap->next) == gcvNULL)
+        {
+            *Tail = gcvNULL;
+        }
+    }
+    else
+    {
+        gpuMap->prev->next = gpuMap->next;
+        if (gpuMap == *Tail)
+        {
+            *Tail = gpuMap->prev;
+        }
+        else
+        {
+            gpuMap->next->prev = gpuMap->prev;
+        }
+    }
+
+    gcmkOS_SAFE_FREE(Os, gpuMap);
 }
+#endif
 
 /*******************************************************************************
 **
@@ -1663,55 +1404,76 @@ OnError:
 **
 **      gctUINT32 * Address
 **          Pointer to a variable that will hold the hardware specific address.
+**
+**      gctUINT32 * PhysicalAddress
+**          Pointer to a variable that will hold the bus address of a contiguous
+**          video node.
 */
 gceSTATUS
 gckVIDMEM_Lock(
     IN gckKERNEL Kernel,
-    IN gcuVIDMEM_NODE_PTR Node,
+    IN gckVIDMEM_NODE Node,
     IN gctBOOL Cacheable,
-    OUT gctUINT32 * Address
+    OUT gctUINT32 * Address,
+    OUT gctUINT32 * Gid,
+    OUT gctUINT64 * PhysicalAddress
     )
 {
     gceSTATUS status;
     gctBOOL acquired = gcvFALSE;
     gctBOOL locked = gcvFALSE;
     gckOS os = gcvNULL;
-    gctBOOL needMapping;
+#if !gcdPROCESS_ADDRESS_SPACE
+    gctBOOL needMapping = gcvFALSE;
+#endif
     gctUINT32 baseAddress;
+    gctUINT32 physicalAddress;
+    gcuVIDMEM_NODE_PTR node = Node->node;
 
     gcmkHEADER_ARG("Node=0x%x", Node);
 
     /* Verify the arguments. */
     gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
 
-    if ((Node == gcvNULL)
-    ||  (Node->VidMem.memory == gcvNULL)
+    /* Extract the gckOS object pointer. */
+    os = Kernel->os;
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+    if ((node == gcvNULL)
+    ||  (node->VidMem.memory == gcvNULL)
     )
     {
         /* Invalid object. */
         gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
     }
 
+    /* Grab the mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(os, Node->mutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
     /**************************** Video Memory ********************************/
 
-    if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+    if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
     {
+        gctUINT32 offset;
+
         if (Cacheable == gcvTRUE)
         {
             gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
         }
 
         /* Increment the lock count. */
-        Node->VidMem.locked ++;
+        node->VidMem.locked ++;
 
         /* Return the physical address of the node. */
-#if !gcdUSE_VIDMEM_PER_PID
-        *Address = Node->VidMem.memory->baseAddress
-                 + Node->VidMem.offset
-                 + Node->VidMem.alignment;
-#else
-        *Address = Node->VidMem.physical;
-#endif
+        gcmkSAFECASTSIZET(offset, node->VidMem.offset);
+
+        *Address = node->VidMem.memory->baseAddress
+                 + offset
+                 + node->VidMem.alignment;
+
+        physicalAddress = *Address;
 
         /* Get hardware specific address. */
 #if gcdENABLE_VG
@@ -1727,10 +1489,16 @@ gckVIDMEM_Lock(
             }
         }
 
+        gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(
+            Kernel->os,
+            *Address,
+            Address
+            ));
+
         gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                       "Locked node 0x%x (%d) @ 0x%08X",
-                      Node,
-                      Node->VidMem.locked,
+                      node,
+                      node->VidMem.locked,
                       *Address);
     }
 
@@ -1738,16 +1506,8 @@ gckVIDMEM_Lock(
 
     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;
+        *Gid = node->Virtual.gid;
 
 #if gcdPAGED_MEMORY_CACHEABLE
         /* Force video memory cacheable. */
@@ -1756,36 +1516,29 @@ gckVIDMEM_Lock(
 
         gcmkONERROR(
             gckOS_LockPages(os,
-                            Node->Virtual.physical,
-                            Node->Virtual.bytes,
+                            node->Virtual.physical,
+                            node->Virtual.bytes,
                             Cacheable,
-                            &Node->Virtual.logical,
-                            &Node->Virtual.pageCount));
+                            &node->Virtual.logical,
+                            &node->Virtual.pageCount));
 
-        /* Increment the lock count. */
-        if (Node->Virtual.lockeds[Kernel->core] ++ == 0)
-        {
-            /* Is this node pending for a final unlock? */
-#ifdef __QNXNTO__
-            if (!Node->Virtual.contiguous && Node->Virtual.unlockPendings[Kernel->core])
-            {
-                /* Make sure we have a page table. */
-                gcmkASSERT(Node->Virtual.pageTables[Kernel->core] != gcvNULL);
-
-                /* Remove pending unlock. */
-                Node->Virtual.unlockPendings[Kernel->core] = gcvFALSE;
-            }
-
-            /* First lock - create a page table. */
-            gcmkASSERT(Node->Virtual.pageTables[Kernel->core] == gcvNULL);
+        gcmkONERROR(gckOS_GetPhysicalAddress(
+            os,
+            node->Virtual.logical,
+            &physicalAddress
+            ));
 
-            /* Make sure we mark our node as not flushed. */
-            Node->Virtual.unlockPendings[Kernel->core] = gcvFALSE;
+#if gcdENABLE_VG
+        node->Virtual.physicalAddress = physicalAddress;
 #endif
 
+#if !gcdPROCESS_ADDRESS_SPACE
+        /* Increment the lock count. */
+        if (node->Virtual.lockeds[Kernel->core] ++ == 0)
+        {
             locked = gcvTRUE;
 
-            gcmkONERROR(_NeedVirtualMapping(Kernel, Kernel->core, Node, &needMapping));
+            gcmkONERROR(_NeedVirtualMapping(Kernel, Kernel->core, node, &needMapping));
 
             if (needMapping == gcvFALSE)
             {
@@ -1793,29 +1546,59 @@ gckVIDMEM_Lock(
 #if gcdENABLE_VG
                 if (Kernel->vg != gcvNULL)
                 {
-                    gcmkONERROR(gckVGHARDWARE_ConvertLogical(Kernel->vg->hardware,
-                                Node->Virtual.logical,
-                                &Node->Virtual.addresses[Kernel->core]));
+                    gcmkONERROR(gckVGHARDWARE_ConvertLogical(
+                                Kernel->vg->hardware,
+                                node->Virtual.logical,
+                                gcvTRUE,
+                                &node->Virtual.addresses[Kernel->core]));
                 }
                 else
 #endif
                 {
-                    gcmkONERROR(gckHARDWARE_ConvertLogical(Kernel->hardware,
-                                Node->Virtual.logical,
-                                &Node->Virtual.addresses[Kernel->core]));
+                    gcmkONERROR(gckHARDWARE_ConvertLogical(
+                                Kernel->hardware,
+                                node->Virtual.logical,
+                                gcvTRUE,
+                                &node->Virtual.addresses[Kernel->core]));
                 }
             }
             else
             {
+#if gcdSECURITY
+                gctPHYS_ADDR physicalArrayPhysical;
+                gctPOINTER physicalArrayLogical;
+
+                gcmkONERROR(gckOS_AllocatePageArray(
+                    os,
+                    node->Virtual.physical,
+                    node->Virtual.pageCount,
+                    &physicalArrayLogical,
+                    &physicalArrayPhysical
+                    ));
+
+                gcmkONERROR(gckKERNEL_SecurityMapMemory(
+                    Kernel,
+                    physicalArrayLogical,
+                    node->Virtual.pageCount,
+                    &node->Virtual.addresses[Kernel->core]
+                    ));
+
+                gcmkONERROR(gckOS_FreeNonPagedMemory(
+                    os,
+                    1,
+                    physicalArrayPhysical,
+                    physicalArrayLogical
+                    ));
+#else
 #if gcdENABLE_VG
                 if (Kernel->vg != gcvNULL)
                 {
                     /* Allocate pages inside the MMU. */
                     gcmkONERROR(
                         gckVGMMU_AllocatePages(Kernel->vg->mmu,
-                                             Node->Virtual.pageCount,
-                                             &Node->Virtual.pageTables[Kernel->core],
-                                             &Node->Virtual.addresses[Kernel->core]));
+                                             node->Virtual.pageCount,
+                                             &node->Virtual.pageTables[Kernel->core],
+                                             &node->Virtual.addresses[Kernel->core]));
                 }
                 else
 #endif
@@ -1823,31 +1606,22 @@ gckVIDMEM_Lock(
                     /* Allocate pages inside the MMU. */
                     gcmkONERROR(
                         gckMMU_AllocatePagesEx(Kernel->mmu,
-                                             Node->Virtual.pageCount,
-                                             Node->Virtual.type,
-                                             &Node->Virtual.pageTables[Kernel->core],
-                                             &Node->Virtual.addresses[Kernel->core]));
+                                             node->Virtual.pageCount,
+                                             node->Virtual.type,
+                                             &node->Virtual.pageTables[Kernel->core],
+                                             &node->Virtual.addresses[Kernel->core]));
                 }
 
-                Node->Virtual.lockKernels[Kernel->core] = Kernel;
+                node->Virtual.lockKernels[Kernel->core] = Kernel;
 
                 /* Map the pages. */
-#ifdef __QNXNTO__
-                gcmkONERROR(
-                    gckOS_MapPagesEx(os,
-                                     Kernel->core,
-                                     Node->Virtual.physical,
-                                     Node->Virtual.logical,
-                                     Node->Virtual.pageCount,
-                                     Node->Virtual.pageTables[Kernel->core]));
-#else
                 gcmkONERROR(
                     gckOS_MapPagesEx(os,
                                      Kernel->core,
-                                     Node->Virtual.physical,
-                                     Node->Virtual.pageCount,
-                                     Node->Virtual.pageTables[Kernel->core]));
-#endif
+                                     node->Virtual.physical,
+                                     node->Virtual.pageCount,
+                                     node->Virtual.addresses[Kernel->core],
+                                     node->Virtual.pageTables[Kernel->core]));
 
 #if gcdENABLE_VG
                 if (Kernel->core == gcvCORE_VG)
@@ -1857,22 +1631,26 @@ gckVIDMEM_Lock(
                 else
 #endif
                 {
-                    gcmkONERROR(gckMMU_Flush(Kernel->mmu));
+                    gcmkONERROR(gckMMU_Flush(Kernel->mmu, node->Virtual.type));
                 }
+#endif
             }
             gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                            "Mapped virtual node 0x%x to 0x%08X",
-                           Node,
-                           Node->Virtual.addresses[Kernel->core]);
+                           node,
+                           node->Virtual.addresses[Kernel->core]);
         }
 
         /* Return hardware address. */
-        *Address = Node->Virtual.addresses[Kernel->core];
-
-        /* Release the mutex. */
-        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+        *Address = node->Virtual.addresses[Kernel->core];
+#endif
     }
 
+    /* Release the mutex. */
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
+
+    *PhysicalAddress = (gctUINT64)physicalAddress;
+
     /* Success. */
     gcmkFOOTER_ARG("*Address=%08x", *Address);
     return gcvSTATUS_OK;
@@ -1880,7 +1658,7 @@ gckVIDMEM_Lock(
 OnError:
     if (locked)
     {
-        if (Node->Virtual.pageTables[Kernel->core] != gcvNULL)
+        if (node->Virtual.pageTables[Kernel->core] != gcvNULL)
         {
 #if gcdENABLE_VG
             if (Kernel->vg != gcvNULL)
@@ -1888,8 +1666,8 @@ OnError:
                 /* Free the pages from the MMU. */
                 gcmkVERIFY_OK(
                     gckVGMMU_FreePages(Kernel->vg->mmu,
-                                     Node->Virtual.pageTables[Kernel->core],
-                                     Node->Virtual.pageCount));
+                                     node->Virtual.pageTables[Kernel->core],
+                                     node->Virtual.pageCount));
             }
             else
 #endif
@@ -1897,28 +1675,28 @@ OnError:
                 /* Free the pages from the MMU. */
                 gcmkVERIFY_OK(
                     gckMMU_FreePages(Kernel->mmu,
-                                     Node->Virtual.pageTables[Kernel->core],
-                                     Node->Virtual.pageCount));
+                                     node->Virtual.pageTables[Kernel->core],
+                                     node->Virtual.pageCount));
             }
-            Node->Virtual.pageTables[Kernel->core]  = gcvNULL;
-            Node->Virtual.lockKernels[Kernel->core] = gcvNULL;
+            node->Virtual.pageTables[Kernel->core]  = gcvNULL;
+            node->Virtual.lockKernels[Kernel->core] = gcvNULL;
         }
 
         /* Unlock the pages. */
         gcmkVERIFY_OK(
             gckOS_UnlockPages(os,
-                              Node->Virtual.physical,
-                              Node->Virtual.bytes,
-                              Node->Virtual.logical
+                              node->Virtual.physical,
+                              node->Virtual.bytes,
+                              node->Virtual.logical
                               ));
 
-        Node->Virtual.lockeds[Kernel->core]--;
+        node->Virtual.lockeds[Kernel->core]--;
     }
 
     if (acquired)
     {
         /* Release the mutex. */
-        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
     }
 
     /* Return the status. */
@@ -1957,308 +1735,1073 @@ OnError:
 gceSTATUS
 gckVIDMEM_Unlock(
     IN gckKERNEL Kernel,
-    IN gcuVIDMEM_NODE_PTR Node,
+    IN gckVIDMEM_NODE Node,
     IN gceSURF_TYPE Type,
     IN OUT gctBOOL * Asynchroneous
     )
 {
     gceSTATUS status;
-    gckHARDWARE hardware;
-    gctPOINTER buffer;
-    gctSIZE_T requested, bufferSize;
-    gckCOMMAND command = gcvNULL;
-    gceKERNEL_FLUSH flush;
     gckOS os = gcvNULL;
     gctBOOL acquired = gcvFALSE;
-    gctBOOL commitEntered = gcvFALSE;
-    gctINT32 i, totalLocked;
+    gcuVIDMEM_NODE_PTR node = Node->node;
 
     gcmkHEADER_ARG("Node=0x%x Type=%d *Asynchroneous=%d",
                    Node, Type, gcmOPT_VALUE(Asynchroneous));
 
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+    /* Get the gckOS object pointer. */
+    os = Kernel->os;
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
     /* Verify the arguments. */
-    if ((Node == gcvNULL)
-    ||  (Node->VidMem.memory == gcvNULL)
+    if ((node == gcvNULL)
+    ||  (node->VidMem.memory == gcvNULL)
     )
     {
         /* Invalid object. */
         gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
     }
 
+    /* Grab the mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(os, Node->mutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
     /**************************** Video Memory ********************************/
 
-    if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+    if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
     {
-        if (Node->VidMem.locked <= 0)
+        if (node->VidMem.locked <= 0)
         {
             /* The surface was not locked. */
             status = gcvSTATUS_MEMORY_UNLOCKED;
             goto OnError;
         }
 
-        /* Decrement the lock count. */
-        Node->VidMem.locked --;
-
         if (Asynchroneous != gcvNULL)
         {
-            /* No need for any events. */
-            *Asynchroneous = gcvFALSE;
+            /* Schedule an event to sync with GPU. */
+            *Asynchroneous = gcvTRUE;
+        }
+        else
+        {
+            /* Decrement the lock count. */
+            node->VidMem.locked --;
         }
 
         gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                       "Unlocked node 0x%x (%d)",
-                      Node,
-                      Node->VidMem.locked);
-
-#ifdef __QNXNTO__
-        /* Unmap the video memory */
-        if ((Node->VidMem.locked == 0) && (Node->VidMem.logical != gcvNULL))
-        {
-            if (Kernel->core == gcvCORE_VG)
-            {
-                gckKERNEL_UnmapVideoMemory(Kernel,
-                                           Node->VidMem.logical,
-                                           Node->VidMem.processID,
-                                           Node->VidMem.bytes);
-                Node->VidMem.logical = gcvNULL;
-            }
-        }
-#endif /* __QNXNTO__ */
-
-        if (Node->VidMem.freePending && (Node->VidMem.locked == 0))
-        {
-            /* Client has unlocked node previously attempted to be freed by compositor. Free now. */
-            Node->VidMem.freePending = gcvFALSE;
-            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
-                           "Deferred-freeing Node 0x%x.",
-                           Node);
-            gcmkONERROR(gckVIDMEM_Free(Node));
-        }
+                      node,
+                      node->VidMem.locked);
     }
 
     /*************************** Virtual Memory *******************************/
 
     else
     {
-        /* Verify the gckHARDWARE object pointer. */
-        hardware = Kernel->hardware;
-        gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
-
-        /* Verify the gckCOMMAND object pointer. */
-        command = Kernel->command;
-        gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
-
-        /* Get the gckOS object pointer. */
-        os = Kernel->os;
-        gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
-
-        /* Grab the mutex. */
-        gcmkONERROR(
-            gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
 
-        acquired = gcvTRUE;
 
         if (Asynchroneous == gcvNULL)
         {
-            if (Node->Virtual.lockeds[Kernel->core] == 0)
+#if !gcdPROCESS_ADDRESS_SPACE
+            if (node->Virtual.lockeds[Kernel->core] == 0)
             {
                 status = gcvSTATUS_MEMORY_UNLOCKED;
                 goto OnError;
             }
 
             /* Decrement lock count. */
-            -- Node->Virtual.lockeds[Kernel->core];
+            -- node->Virtual.lockeds[Kernel->core];
 
             /* See if we can unlock the resources. */
-            if (Node->Virtual.lockeds[Kernel->core] == 0)
+            if (node->Virtual.lockeds[Kernel->core] == 0)
             {
+#if gcdSECURITY
+                if (node->Virtual.addresses[Kernel->core] > 0x80000000)
+                {
+                    gcmkONERROR(gckKERNEL_SecurityUnmapMemory(
+                        Kernel,
+                        node->Virtual.addresses[Kernel->core],
+                        node->Virtual.pageCount
+                        ));
+                }
+#else
                 /* Free the page table. */
-                if (Node->Virtual.pageTables[Kernel->core] != gcvNULL)
+                if (node->Virtual.pageTables[Kernel->core] != gcvNULL)
                 {
 #if gcdENABLE_VG
                     if (Kernel->vg != gcvNULL)
                     {
                         gcmkONERROR(
                             gckVGMMU_FreePages(Kernel->vg->mmu,
-                                             Node->Virtual.pageTables[Kernel->core],
-                                             Node->Virtual.pageCount));
+                                             node->Virtual.pageTables[Kernel->core],
+                                             node->Virtual.pageCount));
                     }
                     else
 #endif
                     {
                         gcmkONERROR(
                             gckMMU_FreePages(Kernel->mmu,
-                                             Node->Virtual.pageTables[Kernel->core],
-                                             Node->Virtual.pageCount));
+                                             node->Virtual.pageTables[Kernel->core],
+                                             node->Virtual.pageCount));
                     }
-                    /* Mark page table as freed. */
-                    Node->Virtual.pageTables[Kernel->core] = gcvNULL;
-                    Node->Virtual.lockKernels[Kernel->core] = gcvNULL;
-                }
-
-#ifdef __QNXNTO__
-                /* Mark node as unlocked. */
-                Node->Virtual.unlockPendings[Kernel->core] = gcvFALSE;
-#endif
-            }
-
-            for (i = 0, totalLocked = 0; i < gcdMAX_GPU_COUNT; i++)
-            {
-                totalLocked += Node->Virtual.lockeds[i];
-            }
-
-            if (totalLocked == 0)
-            {
-                /* Owner have already freed this node
-                ** and we are the last one to unlock, do
-                ** real free */
-                if (Node->Virtual.freed)
-                {
-                    /* Free the virtual memory. */
-                    gcmkVERIFY_OK(gckOS_FreePagedMemory(Kernel->os,
-                                                        Node->Virtual.physical,
-                                                        Node->Virtual.bytes));
-
-                    /* Release mutex before node is destroyed */
-                    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
 
-                    acquired = gcvFALSE;
-
-                    /* Destroy the gcuVIDMEM_NODE union. */
-                    gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node));
+                    gcmkONERROR(gckOS_UnmapPages(
+                        Kernel->os,
+                        node->Virtual.pageCount,
+                        node->Virtual.addresses[Kernel->core]
+                        ));
 
-                    /* Node has been destroyed, so we should not touch it any more */
-                    gcmkFOOTER();
-                    return gcvSTATUS_OK;
+                    /* Mark page table as freed. */
+                    node->Virtual.pageTables[Kernel->core] = gcvNULL;
+                    node->Virtual.lockKernels[Kernel->core] = gcvNULL;
                 }
+#endif
             }
 
             gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                            "Unmapped virtual node 0x%x from 0x%08X",
-                           Node, Node->Virtual.addresses[Kernel->core]);
+                           node, node->Virtual.addresses[Kernel->core]);
+#endif
 
         }
 
         else
         {
-            /* If we need to unlock a node from virtual memory we have to be
-            ** very carefull.  If the node is still inside the caches we
-            ** might get a bus error later if the cache line needs to be
-            ** replaced.  So - we have to flush the caches before we do
-            ** anything. */
-
-            /* gckCommand_EnterCommit() can't be called in interrupt handler because
-            ** of a dead lock situation:
-            ** process call Command_Commit(), and acquire Command->mutexQueue in
-            ** gckCOMMAND_EnterCommit(). Then it will wait for a signal which depends
-            ** on interrupt handler to generate, if interrupt handler enter
-            ** gckCommand_EnterCommit(), process will never get the signal. */
-
-            /* So, flush cache when we still in process context, and then ask caller to
-            ** schedule a event. */
-
             gcmkONERROR(
                 gckOS_UnlockPages(os,
-                              Node->Virtual.physical,
-                              Node->Virtual.bytes,
-                              Node->Virtual.logical));
-
-            if (!Node->Virtual.contiguous
-            &&  (Node->Virtual.lockeds[Kernel->core] == 1)
-#if gcdENABLE_VG
-            && (Kernel->vg == gcvNULL)
-#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;
-                }
-                if(hardware)
-                {
-                    gcmkONERROR(
-                        gckHARDWARE_Flush(hardware, flush, gcvNULL, &requested));
+                              node->Virtual.physical,
+                              node->Virtual.bytes,
+                              node->Virtual.logical));
 
-                    if (requested != 0)
-                    {
-                        /* Acquire the command queue. */
-                        gcmkONERROR(gckCOMMAND_EnterCommit(command, gcvFALSE));
-                        commitEntered = gcvTRUE;
+            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+                           "Scheduled unlock for virtual node 0x%x",
+                           node);
 
-                        gcmkONERROR(gckCOMMAND_Reserve(
-                            command, requested, &buffer, &bufferSize
-                            ));
+            /* Schedule the surface to be unlocked. */
+            *Asynchroneous = gcvTRUE;
+        }
+    }
 
-                        gcmkONERROR(gckHARDWARE_Flush(
-                            hardware, flush, buffer, &bufferSize
-                            ));
+    /* Release the mutex. */
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
+    acquired = gcvFALSE;
 
-                        /* Mark node as pending. */
-#ifdef __QNXNTO__
-                        Node->Virtual.unlockPendings[Kernel->core] = gcvTRUE;
-#endif
+    /* Success. */
+    gcmkFOOTER_ARG("*Asynchroneous=%d", gcmOPT_VALUE(Asynchroneous));
+    return gcvSTATUS_OK;
 
-                        gcmkONERROR(gckCOMMAND_Execute(command, requested));
+OnError:
+    if (acquired)
+    {
+        /* Release the mutex. */
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
+    }
 
-                        /* Release the command queue. */
-                        gcmkONERROR(gckCOMMAND_ExitCommit(command, gcvFALSE));
-                        commitEntered = gcvFALSE;
-                    }
-                }
-                else
-                {
-                    gckOS_Print("Hardware already is freed.\n");
-                }
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+gckVIDMEM_Node_Lock(
+    IN gckKERNEL Kernel,
+    IN gckVIDMEM_NODE Node,
+    OUT gctUINT32 *Address
+    )
+{
+    gceSTATUS           status;
+    gckOS               os;
+    gcuVIDMEM_NODE_PTR  node = Node->node;
+    gcsGPU_MAP_PTR      gpuMap;
+    gctPHYS_ADDR        physical = gcvNULL;
+    gctUINT32           phys = gcvINVALID_ADDRESS;
+    gctUINT32           processID;
+    gcsLOCK_INFO_PTR    lockInfo;
+    gctUINT32           pageCount;
+    gckMMU              mmu;
+    gctUINT32           i;
+    gctUINT32_PTR       pageTableEntry;
+    gctUINT32           offset = 0;
+    gctBOOL             acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Node = %x", Node);
+
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+    os = Kernel->os;
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+    gcmkONERROR(gckOS_GetProcessID(&processID));
+
+    gcmkONERROR(gckKERNEL_GetProcessMMU(Kernel, &mmu));
+
+    gcmkONERROR(gckOS_AcquireMutex(os, Node->mapMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Get map information for current process. */
+    gpuMap = _FindGPUMap(Node->mapHead, processID);
+
+    if (gpuMap == gcvNULL)
+    {
+        gpuMap = _CreateGPUMap(os, &Node->mapHead, &Node->mapTail, processID);
+
+        if (gpuMap == gcvNULL)
+        {
+            gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+        }
+    }
+
+    lockInfo = &gpuMap->lockInfo;
+
+    if (lockInfo->lockeds[Kernel->core] ++ == 0)
+    {
+        /* Get necessary information. */
+        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+        {
+            phys = node->VidMem.memory->baseAddress
+                 + node->VidMem.offset
+                 + node->VidMem.alignment;
+
+            /* GPU page table use 4K page. */
+            pageCount = ((phys + node->VidMem.bytes + 4096 - 1) >> 12)
+                      - (phys >> 12);
+
+            offset = phys & 0xFFF;
+        }
+        else
+        {
+            pageCount = node->Virtual.pageCount;
+            physical = node->Virtual.physical;
+        }
+
+        /* Allocate pages inside the MMU. */
+        gcmkONERROR(gckMMU_AllocatePages(
+            mmu,
+            pageCount,
+            &lockInfo->pageTables[Kernel->core],
+            &lockInfo->GPUAddresses[Kernel->core]));
+
+        /* Record MMU from which pages are allocated.  */
+        lockInfo->lockMmus[Kernel->core] = mmu;
+
+        pageTableEntry = lockInfo->pageTables[Kernel->core];
+
+        /* Fill page table entries. */
+        if (phys != gcvINVALID_ADDRESS)
+        {
+            gctUINT32 address = lockInfo->GPUAddresses[Kernel->core];
+            for (i = 0; i < pageCount; i++)
+            {
+                gckMMU_GetPageEntry(mmu, address, &pageTableEntry);
+                gckMMU_SetPage(mmu, phys & 0xFFFFF000, pageTableEntry);
+                phys += 4096;
+                address += 4096;
+                pageTableEntry += 1;
             }
+        }
+        else
+        {
+            gctUINT32 address = lockInfo->GPUAddresses[Kernel->core];
+            gcmkASSERT(physical != gcvNULL);
+            gcmkONERROR(gckOS_MapPagesEx(os,
+                Kernel->core,
+                physical,
+                pageCount,
+                address,
+                pageTableEntry));
+        }
 
-            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
-                           "Scheduled unlock for virtual node 0x%x",
-                           Node);
+        gcmkONERROR(gckMMU_Flush(mmu));
+    }
 
-            /* Schedule the surface to be unlocked. */
-            *Asynchroneous = gcvTRUE;
+    *Address = lockInfo->GPUAddresses[Kernel->core] + offset;
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mapMutex));
+    acquired = gcvFALSE;
+
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mapMutex));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckVIDMEM_NODE_Unlock(
+    IN gckKERNEL Kernel,
+    IN gckVIDMEM_NODE Node,
+    IN gctUINT32 ProcessID
+    )
+{
+    gceSTATUS           status;
+    gcsGPU_MAP_PTR      gpuMap;
+    gcsLOCK_INFO_PTR    lockInfo;
+    gckMMU              mmu;
+    gcuVIDMEM_NODE_PTR  node;
+    gctUINT32           pageCount;
+    gctBOOL             acquired = gcvFALSE;
+
+    gcmkHEADER_ARG("Kernel=0x%08X, Node = %x, ProcessID=%d",
+                   Kernel, Node, ProcessID);
+
+    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+    gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+    gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Node->mapMutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Get map information for current process. */
+    gpuMap = _FindGPUMap(Node->mapHead, ProcessID);
+
+    if (gpuMap == gcvNULL)
+    {
+        /* No mapping for this process. */
+        gcmkONERROR(gcvSTATUS_INVALID_DATA);
+    }
+
+    lockInfo = &gpuMap->lockInfo;
+
+    if (--lockInfo->lockeds[Kernel->core] == 0)
+    {
+        node = Node->node;
+
+        /* Get necessary information. */
+        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+        {
+            gctUINT32 phys = node->VidMem.memory->baseAddress
+                           + node->VidMem.offset
+                           + node->VidMem.alignment;
+
+            /* GPU page table use 4K page. */
+            pageCount = ((phys + node->VidMem.bytes + 4096 - 1) >> 12)
+                      - (phys >> 12);
+        }
+        else
+        {
+            pageCount = node->Virtual.pageCount;
         }
 
-        /* Release the mutex. */
-        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+        /* Get MMU which allocates pages. */
+        mmu = lockInfo->lockMmus[Kernel->core];
+
+        /* Free virtual spaces in page table. */
+        gcmkVERIFY_OK(gckMMU_FreePagesEx(
+            mmu,
+            lockInfo->GPUAddresses[Kernel->core],
+            pageCount
+            ));
 
-        acquired = gcvFALSE;
+        _DestroyGPUMap(Kernel->os, &Node->mapHead, &Node->mapTail, gpuMap);
     }
 
-    /* Success. */
-    gcmkFOOTER_ARG("*Asynchroneous=%d", gcmOPT_VALUE(Asynchroneous));
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Node->mapMutex));
+    acquired = gcvFALSE;
+
+    gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 
 OnError:
-    if (commitEntered)
+    if (acquired)
     {
-        /* Release the command queue mutex. */
-        gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, gcvFALSE));
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Node->mapMutex));
     }
 
+    gcmkFOOTER();
+    return status;
+}
+#endif
+
+/*******************************************************************************
+**
+**  gckVIDMEM_HANDLE_Allocate
+**
+**  Allocate a handle for a gckVIDMEM_NODE object.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gckVIDMEM_NODE Node
+**          Pointer to a gckVIDMEM_NODE object.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Handle
+**          Pointer to a variable receiving a handle represent this
+**          gckVIDMEM_NODE in userspace.
+*/
+static gceSTATUS
+gckVIDMEM_HANDLE_Allocate(
+    IN gckKERNEL Kernel,
+    IN gckVIDMEM_NODE Node,
+    OUT gctUINT32 * Handle
+    )
+{
+    gceSTATUS status;
+    gctUINT32 processID           = 0;
+    gctPOINTER pointer            = gcvNULL;
+    gctPOINTER handleDatabase     = gcvNULL;
+    gctPOINTER mutex              = gcvNULL;
+    gctUINT32 handle              = 0;
+    gckVIDMEM_HANDLE handleObject = gcvNULL;
+    gckOS os                      = Kernel->os;
+
+    gcmkHEADER_ARG("Kernel=0x%X, Node=0x%X", Kernel, Node);
+
+    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+    /* Allocate a gckVIDMEM_HANDLE object. */
+    gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsVIDMEM_HANDLE), &pointer));
+
+    gcmkVERIFY_OK(gckOS_ZeroMemory(pointer, gcmSIZEOF(gcsVIDMEM_HANDLE)));
+
+    handleObject = pointer;
+
+    gcmkONERROR(gckOS_AtomConstruct(os, &handleObject->reference));
+
+    /* Set default reference count to 1. */
+    gckOS_AtomSet(os, handleObject->reference, 1);
+
+    gcmkVERIFY_OK(gckOS_GetProcessID(&processID));
+
+    gcmkONERROR(
+        gckKERNEL_FindHandleDatbase(Kernel,
+                                    processID,
+                                    &handleDatabase,
+                                    &mutex));
+
+    /* Allocate a handle for this object. */
+    gcmkONERROR(
+        gckKERNEL_AllocateIntegerId(handleDatabase, handleObject, &handle));
+
+    handleObject->node = Node;
+    handleObject->handle = handle;
+
+    *Handle = handle;
+
+    gcmkFOOTER_ARG("*Handle=%d", *Handle);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (handleObject != gcvNULL)
+    {
+        if (handleObject->reference != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_AtomDestroy(os, handleObject->reference));
+        }
+
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, handleObject));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+
+static gceSTATUS
+gckVIDMEM_NODE_Reference(
+    IN gckKERNEL Kernel,
+    IN gckVIDMEM_NODE Node
+    )
+{
+    gctINT32 oldValue;
+    gcmkHEADER_ARG("Kernel=0x%X Node=0x%X", Kernel, Node);
+
+    gckOS_AtomIncrement(Kernel->os, Node->reference, &oldValue);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVIDMEM_HANDLE_Reference(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gctUINT32 Handle
+    )
+{
+    gceSTATUS status;
+    gckVIDMEM_HANDLE handleObject = gcvNULL;
+    gctPOINTER database           = gcvNULL;
+    gctPOINTER mutex              = gcvNULL;
+    gctINT32 oldValue             = 0;
+    gctBOOL acquired              = gcvFALSE;
+
+    gcmkHEADER_ARG("Handle=%d PrcoessID=%d", Handle, ProcessID);
+
+    gcmkONERROR(
+        gckKERNEL_FindHandleDatbase(Kernel, ProcessID, &database, &mutex));
+
+    gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Translate handle to gckVIDMEM_HANDLE object. */
+    gcmkONERROR(
+        gckKERNEL_QueryIntegerId(database, Handle, (gctPOINTER *)&handleObject));
+
+    /* Increase the reference count. */
+    gckOS_AtomIncrement(Kernel->os, handleObject->reference, &oldValue);
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+    acquired = gcvFALSE;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
     if (acquired)
     {
-        /* Release the mutex. */
-        gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckVIDMEM_HANDLE_Dereference(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gctUINT32 Handle
+    )
+{
+    gceSTATUS status;
+    gctPOINTER handleDatabase     = gcvNULL;
+    gctPOINTER mutex              = gcvNULL;
+    gctINT32 oldValue             = 0;
+    gckVIDMEM_HANDLE handleObject = gcvNULL;
+    gctBOOL acquired              = gcvFALSE;
+
+    gcmkHEADER_ARG("Handle=%d PrcoessID=%d", Handle, ProcessID);
+
+    gcmkONERROR(
+        gckKERNEL_FindHandleDatbase(Kernel,
+                                    ProcessID,
+                                    &handleDatabase,
+                                    &mutex));
+
+    gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Translate handle to gckVIDMEM_HANDLE. */
+    gcmkONERROR(
+        gckKERNEL_QueryIntegerId(handleDatabase, Handle, (gctPOINTER *)&handleObject));
+
+    gckOS_AtomDecrement(Kernel->os, handleObject->reference, &oldValue);
+
+    if (oldValue == 1)
+    {
+        /* Remove handle from database if this is the last reference. */
+        gcmkVERIFY_OK(gckKERNEL_FreeIntegerId(handleDatabase, Handle));
+    }
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+    acquired = gcvFALSE;
+
+    if (oldValue == 1)
+    {
+        gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, handleObject->reference));
+        gcmkOS_SAFE_FREE(Kernel->os, handleObject);
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckVIDMEM_HANDLE_LookupAndReference(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Handle,
+    OUT gckVIDMEM_NODE * Node
+    )
+{
+    gceSTATUS status;
+    gckVIDMEM_HANDLE handleObject = gcvNULL;
+    gckVIDMEM_NODE node           = gcvNULL;
+    gctPOINTER database           = gcvNULL;
+    gctPOINTER mutex              = gcvNULL;
+    gctUINT32 processID           = 0;
+    gctBOOL acquired              = gcvFALSE;
+
+    gcmkHEADER_ARG("Kernel=0x%X Handle=%d", Kernel, Handle);
+
+    gckOS_GetProcessID(&processID);
+
+    gcmkONERROR(
+        gckKERNEL_FindHandleDatbase(Kernel, processID, &database, &mutex));
+
+    gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Translate handle to gckVIDMEM_HANDLE object. */
+    gcmkONERROR(
+        gckKERNEL_QueryIntegerId(database, Handle, (gctPOINTER *)&handleObject));
+
+    /* Get gckVIDMEM_NODE object. */
+    node = handleObject->node;
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+    acquired = gcvFALSE;
+
+    /* Reference this gckVIDMEM_NODE object. */
+    gcmkVERIFY_OK(gckVIDMEM_NODE_Reference(Kernel, node));
+
+    /* Return result. */
+    *Node = node;
+
+    gcmkFOOTER_ARG("*Node=%d", *Node);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckVIDMEM_HANDLE_Lookup(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN gctUINT32 Handle,
+    OUT gckVIDMEM_NODE * Node
+    )
+{
+    gceSTATUS status;
+    gckVIDMEM_HANDLE handleObject = gcvNULL;
+    gckVIDMEM_NODE node           = gcvNULL;
+    gctPOINTER database           = gcvNULL;
+    gctPOINTER mutex              = gcvNULL;
+    gctBOOL acquired              = gcvFALSE;
+
+    gcmkHEADER_ARG("Kernel=0x%X ProcessID=%d Handle=%d",
+                   Kernel, ProcessID, Handle);
+
+    gcmkONERROR(
+        gckKERNEL_FindHandleDatbase(Kernel, ProcessID, &database, &mutex));
+
+    gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    gcmkONERROR(
+        gckKERNEL_QueryIntegerId(database, Handle, (gctPOINTER *)&handleObject));
+
+    node = handleObject->node;
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+    acquired = gcvFALSE;
+
+    *Node = node;
+
+    gcmkFOOTER_ARG("*Node=%d", *Node);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
     }
 
-    /* Return the status. */
     gcmkFOOTER();
     return status;
 }
+
+/*******************************************************************************
+**
+**  gckVIDMEM_NODE_Allocate
+**
+**  Allocate a gckVIDMEM_NODE object.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gcuVIDMEM_NODE_PTR Node
+**          Pointer to a gcuVIDMEM_NODE union.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Handle
+**          Pointer to a variable receiving a handle represent this
+**          gckVIDMEM_NODE in userspace.
+*/
+gceSTATUS
+gckVIDMEM_NODE_Allocate(
+    IN gckKERNEL Kernel,
+    IN gcuVIDMEM_NODE_PTR VideoNode,
+    IN gceSURF_TYPE Type,
+    IN gcePOOL Pool,
+    IN gctUINT32 * Handle
+    )
+{
+    gceSTATUS status;
+    gckVIDMEM_NODE node = gcvNULL;
+    gctPOINTER pointer  = gcvNULL;
+    gctUINT32 handle    = 0;
+    gckOS os            = Kernel->os;
+
+    gcmkHEADER_ARG("Kernel=0x%X VideoNode=0x%X", Kernel, VideoNode);
+
+    /* Construct a node. */
+    gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsVIDMEM_NODE), &pointer));
+
+    gcmkVERIFY_OK(gckOS_ZeroMemory(pointer, gcmSIZEOF(gcsVIDMEM_NODE)));
+
+    node = pointer;
+
+    node->node = VideoNode;
+    node->type = Type;
+    node->pool = Pool;
+
+#if gcdPROCESS_ADDRESS_SPACE
+    gcmkONERROR(gckOS_CreateMutex(os, &node->mapMutex));
+#endif
+
+    gcmkONERROR(gckOS_AtomConstruct(os, &node->reference));
+
+    gcmkONERROR(gckOS_CreateMutex(os, &node->mutex));
+
+    /* Reference is 1 by default . */
+    gckVIDMEM_NODE_Reference(Kernel, node);
+
+    /* Create a handle to represent this node. */
+    gcmkONERROR(gckVIDMEM_HANDLE_Allocate(Kernel, node, &handle));
+
+    *Handle = handle;
+
+    gcmkFOOTER_ARG("*Handle=%d", *Handle);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (node != gcvNULL)
+    {
+#if gcdPROCESS_ADDRESS_SPACE
+        if (node->mapMutex != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->mapMutex));
+        }
+#endif
+
+        if (node->mutex)
+        {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->mutex));
+        }
+
+        if (node->reference != gcvNULL)
+        {
+            gcmkVERIFY_OK(gckOS_AtomDestroy(os, node->reference));
+        }
+
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, node));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckVIDMEM_NODE_Dereference(
+    IN gckKERNEL Kernel,
+    IN gckVIDMEM_NODE Node
+    )
+{
+    gctINT32 oldValue   = 0;
+    gctPOINTER database = Kernel->db->nameDatabase;
+    gctPOINTER mutex    = Kernel->db->nameDatabaseMutex;
+
+    gcmkHEADER_ARG("Kernel=0x%X Node=0x%X", Kernel, Node);
+
+    gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+
+    gcmkVERIFY_OK(gckOS_AtomDecrement(Kernel->os, Node->reference, &oldValue));
+
+    if (oldValue == 1 && Node->name)
+    {
+        /* Free name if exists. */
+        gcmkVERIFY_OK(gckKERNEL_FreeIntegerId(database, Node->name));
+    }
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+
+    if (oldValue == 1)
+    {
+        /* Free gcuVIDMEM_NODE. */
+        gcmkVERIFY_OK(gckVIDMEM_Free(Kernel, Node->node));
+        gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Node->reference));
+#if gcdPROCESS_ADDRESS_SPACE
+        gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Node->mapMutex));
+#endif
+        gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Node->mutex));
+        gcmkOS_SAFE_FREE(Kernel->os, Node);
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckVIDMEM_NODE_Name
+**
+**  Naming a gckVIDMEM_NODE object.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctUINT32 Handle
+**          Handle to a gckVIDMEM_NODE object.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Name
+**          Pointer to a variable receiving a name which can be pass to another
+**          process.
+*/
+gceSTATUS
+gckVIDMEM_NODE_Name(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Handle,
+    IN gctUINT32 * Name
+    )
+{
+    gceSTATUS status;
+    gckVIDMEM_NODE node = gcvNULL;
+    gctUINT32 name      = 0;
+    gctUINT32 processID = 0;
+    gctPOINTER database = Kernel->db->nameDatabase;
+    gctPOINTER mutex    = Kernel->db->nameDatabaseMutex;
+    gctBOOL acquired    = gcvFALSE;
+    gctBOOL referenced  = gcvFALSE;
+    gcmkHEADER_ARG("Kernel=0x%X Handle=%d", Kernel, Handle);
+
+    gcmkONERROR(gckOS_GetProcessID(&processID));
+
+    gcmkONERROR(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    gcmkONERROR(gckVIDMEM_HANDLE_LookupAndReference(Kernel, Handle, &node));
+    referenced = gcvTRUE;
+
+    if (node->name == 0)
+    {
+        /* Name this node. */
+        gcmkONERROR(gckKERNEL_AllocateIntegerId(database, node, &name));
+        node->name = name;
+    }
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+    acquired = gcvFALSE;
+
+    gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(Kernel, node));
+
+    if(node)
+    {
+        *Name = node->name;
+    }
+
+    gcmkFOOTER_ARG("*Name=%d", *Name);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (referenced)
+    {
+        gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(Kernel, node));
+    }
+
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+
+/*******************************************************************************
+**
+**  gckVIDMEM_NODE_Import
+**
+**  Import a gckVIDMEM_NODE object.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctUINT32 Name
+**          Name of a gckVIDMEM_NODE object.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Handle
+**          Pointer to a variable receiving a handle represent this
+**          gckVIDMEM_NODE in userspace.
+*/
+gceSTATUS
+gckVIDMEM_NODE_Import(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Name,
+    IN gctUINT32 * Handle
+    )
+{
+    gceSTATUS status;
+    gckVIDMEM_NODE node = gcvNULL;
+    gctPOINTER database = Kernel->db->nameDatabase;
+    gctPOINTER mutex    = Kernel->db->nameDatabaseMutex;
+    gctBOOL acquired    = gcvFALSE;
+    gctBOOL referenced  = gcvFALSE;
+
+    gcmkHEADER_ARG("Kernel=0x%X Name=%d", Kernel, Name);
+
+    gcmkONERROR(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+    acquired = gcvTRUE;
+
+    /* Lookup in database to get the node. */
+    gcmkONERROR(gckKERNEL_QueryIntegerId(database, Name, (gctPOINTER *)&node));
+
+    /* Reference the node. */
+    gcmkONERROR(gckVIDMEM_NODE_Reference(Kernel, node));
+    referenced = gcvTRUE;
+
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+    acquired = gcvFALSE;
+
+    /* Allocate a handle for current process. */
+    gcmkONERROR(gckVIDMEM_HANDLE_Allocate(Kernel, node, Handle));
+
+    gcmkFOOTER_ARG("*Handle=%d", *Handle);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (referenced)
+    {
+        gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(Kernel, node));
+    }
+
+    if (acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+
+
+typedef struct _gcsVIDMEM_NODE_FDPRIVATE
+{
+    gcsFDPRIVATE   base;
+    gckKERNEL      kernel;
+    gckVIDMEM_NODE node;
+}
+gcsVIDMEM_NODE_FDPRIVATE;
+
+
+static gctINT
+_ReleaseFdPrivate(
+    gcsFDPRIVATE_PTR FdPrivate
+    )
+{
+    /* Cast private info. */
+    gcsVIDMEM_NODE_FDPRIVATE * private = (gcsVIDMEM_NODE_FDPRIVATE *) FdPrivate;
+
+    gckVIDMEM_NODE_Dereference(private->kernel, private->node);
+    gckOS_Free(private->kernel->os, private);
+
+    return 0;
+}
+
+/*******************************************************************************
+**
+**  gckVIDMEM_NODE_GetFd
+**
+**  Attach a gckVIDMEM_NODE object to a native fd.
+**
+**  INPUT:
+**
+**      gckKERNEL Kernel
+**          Pointer to an gckKERNEL object.
+**
+**      gctUINT32 Handle
+**          Handle to a gckVIDMEM_NODE object.
+**
+**  OUTPUT:
+**
+**      gctUINT32 * Fd
+**          Pointer to a variable receiving a native fd from os.
+*/
+gceSTATUS
+gckVIDMEM_NODE_GetFd(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 Handle,
+    OUT gctINT * Fd
+    )
+{
+    gceSTATUS status;
+    gckVIDMEM_NODE node = gcvNULL;
+    gctBOOL referenced  = gcvFALSE;
+    gcsVIDMEM_NODE_FDPRIVATE * fdPrivate = gcvNULL;
+    gcmkHEADER_ARG("Kernel=0x%X Handle=%d", Kernel, Handle);
+
+    /* Query and reference handle. */
+    gcmkONERROR(gckVIDMEM_HANDLE_LookupAndReference(Kernel, Handle, &node));
+    referenced = gcvTRUE;
+
+    /* Allocate memory for private info. */
+    gcmkONERROR(gckOS_Allocate(
+        Kernel->os,
+        gcmSIZEOF(gcsVIDMEM_NODE_FDPRIVATE),
+        (gctPOINTER *)&fdPrivate
+        ));
+
+    fdPrivate->base.release = _ReleaseFdPrivate;
+    fdPrivate->kernel = Kernel;
+    fdPrivate->node   = node;
+
+    /* Allocated fd owns a reference. */
+    gcmkONERROR(gckOS_GetFd("vidmem", &fdPrivate->base, Fd));
+
+    gcmkFOOTER_ARG("*Fd=%d", *Fd);
+    return gcvSTATUS_OK;
+
+OnError:
+    if (referenced)
+    {
+        gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(Kernel, node));
+    }
+
+    if (fdPrivate)
+    {
+        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, fdPrivate));
+    }
+
+    gcmkFOOTER();
+    return status;
+}
+
index 63d5dad3a75abcfd5e147f9ae5adada6df8b5001..f4b7d9911282948491689d87f477a668affe1096 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 #include "gc_hal_base.h"
 #include "gc_hal_profiler.h"
 #include "gc_hal_driver.h"
-#ifndef VIVANTE_NO_3D
+#if gcdENABLE_3D
 #include "gc_hal_statistics.h"
 #endif
 
+#if gcdSECURITY
+#include "gc_hal_security_interface.h"
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -40,6 +44,13 @@ extern "C" {
 ******************************* Alignment Macros *******************************
 \******************************************************************************/
 
+/* Alignment with a non-power of two value. */
+#define gcmALIGN_NP2(n, align) \
+( \
+    ((n) + (align) - 1) - (((n) + (align) - 1) % (align)) \
+)
+
+/* Alignment with a power of two value. */
 #define gcmALIGN(n, align) \
 ( \
     ((n) + ((align) - 1)) & ~((align) - 1) \
@@ -76,30 +87,11 @@ extern "C" {
 #define gcmRELEASE_NAME(na) \
         gckKERNEL_DeleteName(kernel, gcmALL_TO_UINT32(na))
 
-#ifdef __LP64__
-
 #define gcmALL_TO_UINT32(t) \
 ( \
     (gctUINT32) (gctUINTPTR_T) (t)\
 )
 
-#define gcmPTR_TO_UINT64(p) \
-( \
-    (gctUINT64) (p)\
-)
-
-#define gcmUINT64_TO_PTR(u) \
-( \
-    (gctPOINTER) (u)\
-)
-
-#else /* 32 bit */
-
-#define gcmALL_TO_UINT32(t) \
-( \
-    (gctUINT32) (t)\
-)
-
 #define gcmPTR_TO_UINT64(p) \
 ( \
     (gctUINT64) (gctUINTPTR_T) (p)\
@@ -110,8 +102,6 @@ extern "C" {
     (gctPOINTER) (gctUINTPTR_T) (u)\
 )
 
-#endif
-
 #define gcmUINT64_TO_TYPE(u, t) \
 ( \
     (t) (gctUINTPTR_T) (u)\
@@ -175,6 +165,9 @@ typedef enum _gceOBJECT_TYPE
     gcvOBJ_VERTEX               = gcmCC('V','R','T','X'),
     gcvOBJ_VIDMEM               = gcmCC('V','M','E','M'),
     gcvOBJ_VG                   = gcmCC('V','G',' ',' '),
+    gcvOBJ_BUFOBJ               = gcmCC('B','U','F','O'),
+    gcvOBJ_UNIFORM_BLOCK        = gcmCC('U','B','L','K'),
+    gcvOBJ_CL                   = gcmCC('C','L',' ',' '),
 }
 gceOBJECT_TYPE;
 
@@ -193,11 +186,22 @@ typedef enum _gceCORE
 {
     gcvCORE_MAJOR       = 0x0,
     gcvCORE_2D          = 0x1,
-    gcvCORE_VG          = 0x2
+    gcvCORE_VG          = 0x2,
+#if gcdMULTI_GPU_AFFINITY
+    gcvCORE_OCL         = 0x3,
+#endif
 }
 gceCORE;
 
+#if gcdMULTI_GPU_AFFINITY
+#define gcdMAX_GPU_COUNT               4
+#else
 #define gcdMAX_GPU_COUNT               3
+#endif
+
+#define gcdMAX_SURF_LAYER              4
+
+#define gcdMAX_DRAW_BUFFERS            4
 
 /*******************************************************************************
 **
@@ -356,8 +360,9 @@ gckOS_AllocatePagedMemory(
 gceSTATUS
 gckOS_AllocatePagedMemoryEx(
     IN gckOS Os,
-    IN gctBOOL Contiguous,
+    IN gctUINT32 Flag,
     IN gctSIZE_T Bytes,
+    OUT gctUINT32 * Gid,
     OUT gctPHYS_ADDR * Physical
     );
 
@@ -377,9 +382,6 @@ gceSTATUS
 gckOS_MapPages(
     IN gckOS Os,
     IN gctPHYS_ADDR Physical,
-#ifdef __QNXNTO__
-    IN gctPOINTER Logical,
-#endif
     IN gctSIZE_T PageCount,
     IN gctPOINTER PageTable
     );
@@ -390,13 +392,18 @@ gckOS_MapPagesEx(
     IN gckOS Os,
     IN gceCORE Core,
     IN gctPHYS_ADDR Physical,
-#ifdef __QNXNTO__
-    IN gctPOINTER Logical,
-#endif
     IN gctSIZE_T PageCount,
+    IN gctUINT32 Address,
     IN gctPOINTER PageTable
     );
 
+gceSTATUS
+gckOS_UnmapPages(
+    IN gckOS Os,
+    IN gctSIZE_T PageCount,
+    IN gctUINT32 Address
+    );
+
 /* Unlock pages. */
 gceSTATUS
 gckOS_UnlockPages(
@@ -467,6 +474,14 @@ gckOS_GetPhysicalAddress(
     OUT gctUINT32 * Address
     );
 
+/* Get the physical address of a corresponding user logical address. */
+gceSTATUS
+gckOS_UserLogicalToPhysical(
+    IN gckOS Os,
+    IN gctPOINTER Logical,
+    OUT gctUINT32 * Address
+    );
+
 /* Get the physical address of a corresponding logical address. */
 gceSTATUS
 gckOS_GetPhysicalAddressProcess(
@@ -493,6 +508,14 @@ gckOS_UnmapPhysical(
     IN gctSIZE_T Bytes
     );
 
+/* Get real physical address from descriptor. */
+gceSTATUS
+gckOS_PhysicalToPhysicalAddress(
+    IN gckOS Os,
+    IN gctPOINTER Physical,
+    OUT gctUINT32 * PhysicalAddress
+    );
+
 /* Read data from a hardware register. */
 gceSTATUS
 gckOS_ReadRegister(
@@ -527,6 +550,26 @@ gckOS_WriteRegisterEx(
     IN gctUINT32 Data
     );
 
+#if gcdMULTI_GPU
+gceSTATUS
+gckOS_ReadRegisterByCoreId(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctUINT32 CoreId,
+    IN gctUINT32 Address,
+    OUT gctUINT32 * Data
+    );
+
+gceSTATUS
+gckOS_WriteRegisterByCoreId(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctUINT32 CoreId,
+    IN gctUINT32 Address,
+    IN gctUINT32 Data
+    );
+#endif
+
 /* Write data to a 32-bit memory location. */
 gceSTATUS
 gckOS_WriteMemory(
@@ -621,7 +664,6 @@ gckOS_AtomicExchangePtr(
     OUT gctPOINTER * OldValue
     );
 
-#if gcdSMP
 gceSTATUS
 gckOS_AtomSetMask(
     IN gctPOINTER Atom,
@@ -633,7 +675,6 @@ gckOS_AtomClearMask(
     IN gctPOINTER Atom,
     IN gctUINT32 Mask
     );
-#endif
 
 gceSTATUS
 gckOS_DumpCallStack(
@@ -647,8 +688,6 @@ gckOS_GetProcessNameByPid(
     OUT gctUINT8_PTR String
     );
 
-
-
 /*******************************************************************************
 **
 **  gckOS_AtomConstruct
@@ -945,16 +984,6 @@ gckOS_CopyToUserData(
     IN gctSIZE_T Size
     );
 
-#ifdef __QNXNTO__
-/* Map user physical address. */
-gceSTATUS
-gckOS_MapUserPhysical(
-    IN gckOS Os,
-    IN gctPHYS_ADDR Phys,
-    OUT gctPOINTER * KernelPointer
-    );
-#endif
-
 gceSTATUS
 gckOS_SuspendInterrupt(
     IN gckOS Os
@@ -1056,6 +1085,40 @@ gckOS_GetThreadID(
     OUT gctUINT32_PTR ThreadID
     );
 
+#if gcdSECURITY
+gceSTATUS
+gckOS_OpenSecurityChannel(
+    IN gckOS Os,
+    IN gceCORE Core,
+    OUT gctUINT32 *Channel
+    );
+
+gceSTATUS
+gckOS_CloseSecurityChannel(
+    IN gctUINT32 Channel
+    );
+
+gceSTATUS
+gckOS_CallSecurityService(
+    IN gctUINT32 Channel,
+    IN gcsTA_INTERFACE * Interface
+    );
+
+gceSTATUS
+gckOS_InitSecurityChannel(
+    OUT gctUINT32 Channel
+    );
+
+gceSTATUS
+gckOS_AllocatePageArray(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T PageCount,
+    OUT gctPOINTER * PageArrayLogical,
+    OUT gctPHYS_ADDR * PageArrayPhysical
+    );
+#endif
+
 /******************************************************************************\
 ********************************** Signal Object *********************************
 \******************************************************************************/
@@ -1244,7 +1307,7 @@ gckOS_CacheClean(
     gckOS Os,
     gctUINT32 ProcessID,
     gctPHYS_ADDR Handle,
-    gctPOINTER Physical,
+    gctUINT32 Physical,
     gctPOINTER Logical,
     gctSIZE_T Bytes
     );
@@ -1254,7 +1317,7 @@ gckOS_CacheFlush(
     gckOS Os,
     gctUINT32 ProcessID,
     gctPHYS_ADDR Handle,
-    gctPOINTER Physical,
+    gctUINT32 Physical,
     gctPOINTER Logical,
     gctSIZE_T Bytes
     );
@@ -1264,11 +1327,32 @@ gckOS_CacheInvalidate(
     gckOS Os,
     gctUINT32 ProcessID,
     gctPHYS_ADDR Handle,
-    gctPOINTER Physical,
+    gctUINT32 Physical,
     gctPOINTER Logical,
     gctSIZE_T Bytes
     );
 
+gceSTATUS
+gckOS_CPUPhysicalToGPUPhysical(
+    IN gckOS Os,
+    IN gctUINT32 CPUPhysical,
+    IN gctUINT32_PTR GPUPhysical
+    );
+
+gceSTATUS
+gckOS_GPUPhysicalToCPUPhysical(
+    IN gckOS Os,
+    IN gctUINT32 GPUPhysical,
+    IN gctUINT32_PTR CPUPhysical
+    );
+
+gceSTATUS
+gckOS_QueryOption(
+    IN gckOS Os,
+    IN gctCONST_STRING Option,
+    OUT gctUINT32 * Value
+    );
+
 /******************************************************************************\
 ** Debug Support
 */
@@ -1323,6 +1407,9 @@ typedef enum _gceBROADCAST
 
     /* AXI bus error. */
     gcvBROADCAST_AXI_BUS_ERROR,
+
+    /* Out of memory. */
+    gcvBROADCAST_OUT_OF_MEMORY,
 }
 gceBROADCAST;
 
@@ -1357,9 +1444,9 @@ gckOS_BroadcastCalibrateSpeed(
 **  INPUT:
 **
 **      gckOS Os
-**          Pointer to a gckOS object.ß
+**          Pointer to a gckOS object.
 **
-**      gckCORE Core
+**      gceCORE Core
 **          GPU whose power is set.
 **
 **      gctBOOL Clock
@@ -1571,32 +1658,22 @@ gckVIDMEM_Destroy(
     IN gckVIDMEM Memory
     );
 
-/* Allocate rectangular memory. */
-gceSTATUS
-gckVIDMEM_Allocate(
-    IN gckVIDMEM Memory,
-    IN gctUINT Width,
-    IN gctUINT Height,
-    IN gctUINT Depth,
-    IN gctUINT BytesPerPixel,
-    IN gctUINT32 Alignment,
-    IN gceSURF_TYPE Type,
-    OUT gcuVIDMEM_NODE_PTR * Node
-    );
-
 /* Allocate linear memory. */
 gceSTATUS
 gckVIDMEM_AllocateLinear(
+    IN gckKERNEL Kernel,
     IN gckVIDMEM Memory,
     IN gctSIZE_T Bytes,
     IN gctUINT32 Alignment,
     IN gceSURF_TYPE Type,
+    IN gctBOOL Specified,
     OUT gcuVIDMEM_NODE_PTR * Node
     );
 
 /* Free memory. */
 gceSTATUS
 gckVIDMEM_Free(
+    IN gckKERNEL Kernel,
     IN gcuVIDMEM_NODE_PTR Node
     );
 
@@ -1604,16 +1681,18 @@ gckVIDMEM_Free(
 gceSTATUS
 gckVIDMEM_Lock(
     IN gckKERNEL Kernel,
-    IN gcuVIDMEM_NODE_PTR Node,
+    IN gckVIDMEM_NODE Node,
     IN gctBOOL Cacheable,
-    OUT gctUINT32 * Address
+    OUT gctUINT32 * Address,
+    OUT gctUINT32 * Gid,
+    OUT gctUINT64 * PhysicalAddress
     );
 
 /* Unlock memory. */
 gceSTATUS
 gckVIDMEM_Unlock(
     IN gckKERNEL Kernel,
-    IN gcuVIDMEM_NODE_PTR Node,
+    IN gckVIDMEM_NODE Node,
     IN gceSURF_TYPE Type,
     IN OUT gctBOOL * Asynchroneous
     );
@@ -1622,7 +1701,7 @@ gckVIDMEM_Unlock(
 gceSTATUS
 gckVIDMEM_ConstructVirtual(
     IN gckKERNEL Kernel,
-    IN gctBOOL Contiguous,
+    IN gctUINT32 Flag,
     IN gctSIZE_T Bytes,
     OUT gcuVIDMEM_NODE_PTR * Node
     );
@@ -1654,10 +1733,18 @@ typedef enum _gceKERNEL_FLUSH
     gcvFLUSH_DEPTH              = 0x02,
     gcvFLUSH_TEXTURE            = 0x04,
     gcvFLUSH_2D                 = 0x08,
+#if gcdMULTI_GPU
+    gcvFLUSH_L2                 = 0x10,
+#endif
+    gcvFLUSH_TILE_STATUS        = 0x20,
     gcvFLUSH_ALL                = gcvFLUSH_COLOR
                                 | gcvFLUSH_DEPTH
                                 | gcvFLUSH_TEXTURE
-                                | gcvFLUSH_2D,
+                                | gcvFLUSH_2D
+#if gcdMULTI_GPU
+                                | gcvFLUSH_L2
+#endif
+                                | gcvFLUSH_TILE_STATUS
 }
 gceKERNEL_FLUSH;
 
@@ -1685,6 +1772,14 @@ gckKERNEL_Dispatch(
     IN OUT struct _gcsHAL_INTERFACE * Interface
     );
 
+/* Query Database requirements. */
+gceSTATUS
+    gckKERNEL_QueryDatabase(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN OUT gcsHAL_INTERFACE * Interface
+    );
+
 /* Query the video memory. */
 gceSTATUS
 gckKERNEL_QueryVideoMemory(
@@ -1700,29 +1795,40 @@ gckKERNEL_GetVideoMemoryPool(
     OUT gckVIDMEM * VideoMemory
     );
 
-#if gcdUSE_VIDMEM_PER_PID
 gceSTATUS
-gckKERNEL_GetVideoMemoryPoolPid(
+gckKERNEL_AllocateLinearMemory(
     IN gckKERNEL Kernel,
-    IN gcePOOL Pool,
-    IN gctUINT32 Pid,
-    OUT gckVIDMEM * VideoMemory
+    IN gctUINT32 ProcessID,
+    IN OUT gcePOOL * Pool,
+    IN gctSIZE_T Bytes,
+    IN gctUINT32 Alignment,
+    IN gceSURF_TYPE Type,
+    IN gctUINT32 Flag,
+    OUT gctUINT32 * Node
     );
 
 gceSTATUS
-gckKERNEL_CreateVideoMemoryPoolPid(
+gckKERNEL_ReleaseVideoMemory(
     IN gckKERNEL Kernel,
-    IN gcePOOL Pool,
-    IN gctUINT32 Pid,
-    OUT gckVIDMEM * VideoMemory
+    IN gctUINT32 ProcessID,
+    IN gctUINT32 Handle
     );
 
 gceSTATUS
-gckKERNEL_RemoveVideoMemoryPoolPid(
+gckKERNEL_LockVideoMemory(
     IN gckKERNEL Kernel,
-    IN gckVIDMEM VideoMemory
+    IN gceCORE Core,
+    IN gctUINT32 ProcessID,
+    IN gctBOOL FromUser,
+    IN OUT gcsHAL_INTERFACE * Interface
+    );
+
+gceSTATUS
+gckKERNEL_UnlockVideoMemory(
+    IN gckKERNEL Kernel,
+    IN gctUINT32 ProcessID,
+    IN OUT gcsHAL_INTERFACE * Interface
     );
-#endif
 
 /* Map video memory. */
 gceSTATUS
@@ -1784,6 +1890,9 @@ gckKERNEL_UnmapMemory(
 gceSTATUS
 gckKERNEL_Notify(
     IN gckKERNEL Kernel,
+#if gcdMULTI_GPU
+    IN gctUINT CoreId,
+#endif
     IN gceNOTIFY Notifcation,
     IN gctBOOL Data
     );
@@ -1910,9 +2019,9 @@ gckHARDWARE_BuildVirtualAddress(
 gceSTATUS
 gckHARDWARE_QueryCommandBuffer(
     IN gckHARDWARE Hardware,
-    OUT gctSIZE_T * Alignment,
-    OUT gctSIZE_T * ReservedHead,
-    OUT gctSIZE_T * ReservedTail
+    OUT gctUINT32 * Alignment,
+    OUT gctUINT32 * ReservedHead,
+    OUT gctUINT32 * ReservedTail
     );
 
 /* Add a WAIT/LINK pair in the command queue. */
@@ -1921,20 +2030,16 @@ gckHARDWARE_WaitLink(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
     IN gctUINT32 Offset,
-    IN OUT gctSIZE_T * Bytes,
+    IN OUT gctUINT32 * Bytes,
     OUT gctUINT32 * WaitOffset,
-    OUT gctSIZE_T * WaitBytes
+    OUT gctUINT32 * WaitBytes
     );
 
 /* Kickstart the command processor. */
 gceSTATUS
 gckHARDWARE_Execute(
     IN gckHARDWARE Hardware,
-    IN gctPOINTER Logical,
-#ifdef __QNXNTO__
-    IN gctPOINTER Physical,
-    IN gctBOOL PhysicalAddresses,
-#endif
+    IN gctUINT32 Address,
     IN gctSIZE_T Bytes
     );
 
@@ -1943,23 +2048,24 @@ gceSTATUS
 gckHARDWARE_End(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     );
 
-/* Add a NOP command in the command queue. */
+#if gcdMULTI_GPU
 gceSTATUS
-gckHARDWARE_Nop(
+gckHARDWARE_ChipEnable(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
+    IN gceCORE_3D_MASK ChipEnable,
     IN OUT gctSIZE_T * Bytes
     );
+#endif
 
-/* Add a WAIT command in the command queue. */
+/* Add a NOP command in the command queue. */
 gceSTATUS
-gckHARDWARE_Wait(
+gckHARDWARE_Nop(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
-    IN gctUINT32 Count,
     IN OUT gctSIZE_T * Bytes
     );
 
@@ -1969,7 +2075,7 @@ gckHARDWARE_PipeSelect(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
     IN gcePIPE_SELECT Pipe,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     );
 
 /* Add a LINK command in the command queue. */
@@ -1977,9 +2083,9 @@ gceSTATUS
 gckHARDWARE_Link(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
-    IN gctPOINTER FetchAddress,
-    IN gctSIZE_T FetchSize,
-    IN OUT gctSIZE_T * Bytes
+    IN gctUINT32 FetchAddress,
+    IN gctUINT32 FetchSize,
+    IN OUT gctUINT32 * Bytes
     );
 
 /* Add an EVENT command in the command queue. */
@@ -1989,7 +2095,7 @@ gckHARDWARE_Event(
     IN gctPOINTER Logical,
     IN gctUINT8 Event,
     IN gceKERNEL_WHERE FromWhere,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     );
 
 /* Query the available memory. */
@@ -2013,13 +2119,13 @@ gckHARDWARE_QueryChipIdentity(
     OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
     );
 
-/* Query the shader support. */
+/* Query the shader uniforms support. */
 gceSTATUS
 gckHARDWARE_QueryShaderCaps(
     IN gckHARDWARE Hardware,
     OUT gctUINT * VertexUniforms,
     OUT gctUINT * FragmentUniforms,
-    OUT gctUINT * Varyings
+    OUT gctBOOL * UnifiedUnforms
     );
 
 /* Split a harwdare specific address into API stuff. */
@@ -2044,23 +2150,17 @@ gceSTATUS
 gckHARDWARE_ConvertLogical(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
+    IN gctBOOL InUserSpace,
     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,
+#if gcdMULTI_GPU
+    IN gctUINT CoreId,
+#endif
     IN gctBOOL InterruptValid
     );
 
@@ -2088,6 +2188,20 @@ gckHARDWARE_SetMMUv2(
     IN gctBOOL FromPower
     );
 
+#if gcdPROCESS_ADDRESS_SPACE
+/* Configure mmu configuration. */
+gceSTATUS
+gckHARDWARE_ConfigMMU(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER Logical,
+    IN gctPOINTER MtlbLogical,
+    IN gctUINT32 Offset,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctSIZE_T * WaitLinkOffset,
+    OUT gctSIZE_T * WaitLinkBytes
+    );
+#endif
+
 /* Get idle register. */
 gceSTATUS
 gckHARDWARE_GetIdle(
@@ -2102,7 +2216,7 @@ gckHARDWARE_Flush(
     IN gckHARDWARE Hardware,
     IN gceKERNEL_FLUSH Flush,
     IN gctPOINTER Logical,
-    IN OUT gctSIZE_T * Bytes
+    IN OUT gctUINT32 * Bytes
     );
 
 /* Enable/disable fast clear. */
@@ -2138,6 +2252,12 @@ gckHARDWARE_SetPowerManagement(
     IN gctBOOL PowerManagement
     );
 
+gceSTATUS
+gckHARDWARE_SetPowerManagementLock(
+    IN gckHARDWARE Hardware,
+    IN gctBOOL Lock
+    );
+
 gceSTATUS
 gckHARDWARE_SetGpuProfiler(
     IN gckHARDWARE Hardware,
@@ -2158,6 +2278,12 @@ gckHARDWARE_GetFscaleValue(
     IN gctUINT * MinFscaleValue,
     IN gctUINT * MaxFscaleValue
     );
+
+gceSTATUS
+gckHARDWARE_SetMinFscaleValue(
+    IN gckHARDWARE Hardware,
+    IN gctUINT MinFscaleValue
+    );
 #endif
 
 #if gcdPOWEROFF_TIMEOUT
@@ -2247,6 +2373,21 @@ gckHARDWARE_SetDVFSPeroid(
     IN gctUINT32 Frequency
     );
 
+gceSTATUS
+gckHARDWARE_PrepareFunctions(
+    gckHARDWARE Hardware
+    );
+
+gceSTATUS
+gckHARDWARE_SetMMUStates(
+    IN gckHARDWARE Hardware,
+    IN gctPOINTER MtlbAddress,
+    IN gceMMU_MODE Mode,
+    IN gctPOINTER SafeAddress,
+    IN gctPOINTER Logical,
+    IN OUT gctUINT32 * Bytes
+    );
+
 #if !gcdENABLE_VG
 /******************************************************************************\
 ***************************** gckINTERRUPT Object ******************************
@@ -2302,6 +2443,16 @@ gckEVENT_Destroy(
     );
 
 /* Reserve the next available hardware event. */
+#if gcdMULTI_GPU
+gceSTATUS
+gckEVENT_GetEvent(
+    IN gckEVENT Event,
+    IN gctBOOL Wait,
+    OUT gctUINT8 * EventID,
+    IN gceKERNEL_WHERE Source,
+    IN gceCORE_3D_MASK ChipEnable
+    );
+#else
 gceSTATUS
 gckEVENT_GetEvent(
     IN gckEVENT Event,
@@ -2309,6 +2460,7 @@ gckEVENT_GetEvent(
     OUT gctUINT8 * EventID,
     IN gceKERNEL_WHERE Source
    );
+#endif
 
 /* Add a new event to the list of events. */
 gceSTATUS
@@ -2361,7 +2513,7 @@ gceSTATUS
 gckEVENT_Unlock(
     IN gckEVENT Event,
     IN gceKERNEL_WHERE FromWhere,
-    IN gcuVIDMEM_NODE_PTR Node,
+    IN gctPOINTER Node,
     IN gceSURF_TYPE Type
     );
 
@@ -2371,7 +2523,6 @@ gckEVENT_CommitDone(
     IN gceKERNEL_WHERE FromWhere
     );
 
-#if gcdVIRTUAL_COMMAND_BUFFER
 /* Schedule a FreeVirtualCommandBuffer event. */
 gceSTATUS
 gckEVENT_DestroyVirtualCommandBuffer(
@@ -2381,21 +2532,38 @@ gckEVENT_DestroyVirtualCommandBuffer(
     IN gctPOINTER Logical,
     IN gceKERNEL_WHERE FromWhere
     );
-#endif
 
+#if gcdMULTI_GPU
+gceSTATUS
+gckEVENT_Submit(
+    IN gckEVENT Event,
+    IN gctBOOL Wait,
+    IN gctBOOL FromPower,
+    IN gceCORE_3D_MASK ChipEnable
+    );
+#else
 gceSTATUS
 gckEVENT_Submit(
     IN gckEVENT Event,
     IN gctBOOL Wait,
     IN gctBOOL FromPower
     );
+#endif
 
-/* Commit an event queue. */
+#if gcdMULTI_GPU
+gceSTATUS
+gckEVENT_Commit(
+    IN gckEVENT Event,
+    IN gcsQUEUE_PTR Queue,
+    IN gceCORE_3D_MASK ChipEnable
+    );
+#else
 gceSTATUS
 gckEVENT_Commit(
     IN gckEVENT Event,
     IN gcsQUEUE_PTR Queue
     );
+#endif
 
 /* Schedule a composition event. */
 gceSTATUS
@@ -2415,6 +2583,9 @@ gckEVENT_Notify(
 gceSTATUS
 gckEVENT_Interrupt(
     IN gckEVENT Event,
+#if gcdMULTI_GPU
+    IN gctUINT CoreId,
+#endif
     IN gctUINT32 IDs
     );
 
@@ -2468,8 +2639,20 @@ gckCOMMAND_Stop(
     IN gctBOOL FromRecovery
     );
 
+#if gcdMULTI_GPU
 /* Commit a buffer to the command queue. */
 gceSTATUS
+gckCOMMAND_Commit(
+    IN gckCOMMAND Command,
+    IN gckCONTEXT Context,
+    IN gcoCMDBUF CommandBuffer,
+    IN gcsSTATE_DELTA_PTR StateDelta,
+    IN gcsQUEUE_PTR EventQueue,
+    IN gctUINT32 ProcessID,
+    IN gceCORE_3D_MASK ChipEnable
+    );
+#else
+gceSTATUS
 gckCOMMAND_Commit(
     IN gckCOMMAND Command,
     IN gckCONTEXT Context,
@@ -2478,29 +2661,39 @@ gckCOMMAND_Commit(
     IN gcsQUEUE_PTR EventQueue,
     IN gctUINT32 ProcessID
     );
+#endif
 
 /* Reserve space in the command buffer. */
 gceSTATUS
 gckCOMMAND_Reserve(
     IN gckCOMMAND Command,
-    IN gctSIZE_T RequestedBytes,
+    IN gctUINT32 RequestedBytes,
     OUT gctPOINTER * Buffer,
-    OUT gctSIZE_T * BufferSize
+    OUT gctUINT32 * BufferSize
     );
 
 /* Execute reserved space in the command buffer. */
 gceSTATUS
 gckCOMMAND_Execute(
     IN gckCOMMAND Command,
-    IN gctSIZE_T RequstedBytes
+    IN gctUINT32 RequstedBytes
     );
 
 /* Stall the command queue. */
+#if gcdMULTI_GPU
+gceSTATUS
+gckCOMMAND_Stall(
+    IN gckCOMMAND Command,
+    IN gctBOOL FromPower,
+    IN gceCORE_3D_MASK ChipEnable
+    );
+#else
 gceSTATUS
 gckCOMMAND_Stall(
     IN gckCOMMAND Command,
     IN gctBOOL FromPower
     );
+#endif
 
 /* Attach user process. */
 gceSTATUS
@@ -2518,12 +2711,19 @@ gckCOMMAND_Detach(
     IN gckCONTEXT Context
     );
 
-#if gcdVIRTUAL_COMMAND_BUFFER
+/* Dump command buffer being executed by GPU. */
 gceSTATUS
 gckCOMMAND_DumpExecutingBuffer(
     IN gckCOMMAND Command
     );
-#endif
+
+/* Whether a kernel command buffer address. */
+gceSTATUS
+gckCOMMAND_AddressInKernelCommandBuffer(
+    IN gckCOMMAND Command,
+    IN gctUINT32 Address,
+    OUT gctBOOL *In
+    );
 
 /******************************************************************************\
 ********************************* gckMMU Object ********************************
@@ -2545,14 +2745,6 @@ gckMMU_Destroy(
     IN gckMMU Mmu
     );
 
-/* Enable the MMU. */
-gceSTATUS
-gckMMU_Enable(
-    IN gckMMU Mmu,
-    IN gctUINT32 PhysBaseAddr,
-    IN gctUINT32 PhysSize
-    );
-
 /* Allocate pages inside the MMU. */
 gceSTATUS
 gckMMU_AllocatePages(
@@ -2587,30 +2779,10 @@ gckMMU_SetPage(
    IN gctUINT32 *PageEntry
    );
 
-#ifdef __QNXNTO__
-gceSTATUS
-gckMMU_InsertNode(
-    IN gckMMU Mmu,
-    IN gcuVIDMEM_NODE_PTR Node);
-
-gceSTATUS
-gckMMU_RemoveNode(
-    IN gckMMU Mmu,
-    IN gcuVIDMEM_NODE_PTR Node);
-#endif
-
-#ifdef __QNXNTO__
-gceSTATUS
-gckMMU_FreeHandleMemory(
-    IN gckKERNEL Kernel,
-    IN gckMMU Mmu,
-    IN gctUINT32 Pid
-    );
-#endif
-
 gceSTATUS
 gckMMU_Flush(
-    IN gckMMU Mmu
+    IN gckMMU Mmu,
+    IN gceSURF_TYPE Type
     );
 
 gceSTATUS
@@ -2624,7 +2796,7 @@ gckMMU_DumpPageTableEntry(
 gceSTATUS
 gckHARDWARE_QueryProfileRegisters(
     IN gckHARDWARE Hardware,
-    IN gctBOOL   Clear,
+    IN gctBOOL Reset,
     OUT gcsPROFILER_COUNTERS * Counters
     );
 #endif
@@ -2633,7 +2805,7 @@ gckHARDWARE_QueryProfileRegisters(
 gceSTATUS
 gckHARDWARE_QueryContextProfile(
     IN gckHARDWARE Hardware,
-    IN gctBOOL   Clear,
+    IN gctBOOL Reset,
     IN gckCONTEXT Context,
     OUT gcsPROFILER_COUNTERS * Counters
     );
@@ -2645,6 +2817,13 @@ gckHARDWARE_UpdateContextProfile(
     );
 #endif
 
+#if VIVANTE_PROFILER_NEW
+gceSTATUS
+gckHARDWARE_InitProfiler(
+    IN gckHARDWARE Hardware
+    );
+#endif
+
 gceSTATUS
 gckOS_SignalQueryHardware(
     IN gckOS Os,
@@ -2659,6 +2838,16 @@ gckOS_SignalSetHardware(
     gckHARDWARE Hardware
     );
 
+gceSTATUS
+gckOS_DetectProcessByName(
+    IN gctCONST_POINTER Name
+    );
+
+void
+gckOS_DumpParam(
+    void
+    );
+
 #ifdef __cplusplus
 }
 #endif
index 375a8f5b03d1fc8cad2e7f1e18728ae00d40e842..b798152523af3315e11675c9d31fb236ee8790f1 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 *
 *****************************************************************************/
 
-
 #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
@@ -39,9 +37,12 @@ typedef struct _gckOS *                 gckOS;
 typedef struct _gcoHAL *                gcoHAL;
 typedef struct _gcoOS *                 gcoOS;
 typedef struct _gco2D *                 gco2D;
+typedef struct gcsATOM *                gcsATOM_PTR;
 
-#ifndef VIVANTE_NO_3D
+#if gcdENABLE_3D
 typedef struct _gco3D *                 gco3D;
+typedef struct _gcoCL *                 gcoCL;
+typedef struct _gcsFAST_FLUSH *         gcsFAST_FLUSH_PTR;
 #endif
 
 typedef struct _gcoSURF *               gcoSURF;
@@ -55,29 +56,134 @@ typedef struct _gcsBOUNDARY *           gcsBOUNDARY_PTR;
 typedef struct _gcoDUMP *               gcoDUMP;
 typedef struct _gcoHARDWARE *           gcoHARDWARE;
 typedef union  _gcuVIDMEM_NODE *        gcuVIDMEM_NODE_PTR;
-
-typedef struct gcsATOM *                gcsATOM_PTR;
+typedef struct _gcsVIDMEM_NODE *        gckVIDMEM_NODE;
 
 #if gcdENABLE_VG
 typedef struct _gcoVG *                 gcoVG;
-typedef struct _gcsCOMPLETION_SIGNAL * gcsCOMPLETION_SIGNAL_PTR;
-typedef struct _gcsCONTEXT_MAP *               gcsCONTEXT_MAP_PTR;
+typedef struct _gcsCOMPLETION_SIGNAL *  gcsCOMPLETION_SIGNAL_PTR;
+typedef struct _gcsCONTEXT_MAP *        gcsCONTEXT_MAP_PTR;
 #else
 typedef void *                          gcoVG;
 #endif
 
 #if gcdSYNC
 typedef struct _gcoFENCE *              gcoFENCE;
-typedef struct _gcsSYNC_CONTEXT  *      gcsSYNC_CONTEXT_PTR;
+typedef struct _gcsSYNC_CONTEXT       gcsSYNC_CONTEXT_PTR;
 #endif
 
+#if defined(ANDROID)
 typedef struct _gcoOS_SymbolsList gcoOS_SymbolsList;
+#endif
 
 /******************************************************************************\
 ******************************* Process local storage *************************
 \******************************************************************************/
+
 typedef struct _gcsPLS * gcsPLS_PTR;
 
+#if gcdENABLE_3D
+/******************************************************************************
+**
+** Patch defines which should be moved to dedicate file later
+**
+** !!! ALWAYS ADD new ID in the TAIL, otherwise will break exising TRACE FILE
+*******************************************************************************/
+typedef enum _gcePATCH_ID
+{
+    gcvPATCH_NOTINIT = -1,
+    gcvPATCH_INVALID = 0,
+
+#if gcdDEBUG_OPTION
+    gcvPATCH_DEBUG,
+#endif
+
+    gcvPATCH_GTFES30,
+    gcvPATCH_CTGL11,
+    gcvPATCH_CTGL20,
+    gcvPATCH_GLBM11,
+    gcvPATCH_GLBM21,
+    gcvPATCH_GLBM25,
+    gcvPATCH_GLBM27,
+    gcvPATCH_GLBMGUI,
+    gcvPATCH_GFXBENCH,
+    gcvPATCH_ANTUTU,        /* Antutu 3.x */
+    gcvPATCH_ANTUTU4X,      /* Antutu 4.x */
+    gcvPATCH_QUADRANT,
+    gcvPATCH_GPUBENCH,
+    gcvPATCH_DUOKAN,
+    gcvPATCH_GLOFTSXHM,
+    gcvPATCH_XRUNNER,
+    gcvPATCH_BUSPARKING3D,
+    gcvPATCH_SIEGECRAFT,
+    gcvPATCH_PREMIUM,
+    gcvPATCH_RACEILLEGAL,
+    gcvPATCH_MEGARUN,
+    gcvPATCH_BMGUI,
+    gcvPATCH_NENAMARK,
+    gcvPATCH_NENAMARK2,
+    gcvPATCH_FISHNOODLE,
+    gcvPATCH_MM06,
+    gcvPATCH_MM07,
+    gcvPATCH_BM21,
+    gcvPATCH_SMARTBENCH,
+    gcvPATCH_JPCT,
+    gcvPATCH_NEOCORE,
+    gcvPATCH_RTESTVA,
+    gcvPATCH_NBA2013,
+    gcvPATCH_BARDTALE,
+    gcvPATCH_F18,
+    gcvPATCH_CARPARK,
+    gcvPATCH_CARCHALLENGE,
+    gcvPATCH_HEROESCALL,
+    gcvPATCH_GLOFTF3HM,
+    gcvPATCH_CRAZYRACING,
+    gcvPATCH_FIREFOX,
+    gcvPATCH_CHROME,
+    gcvPATCH_MONOPOLY,
+    gcvPATCH_SNOWCOLD,
+    gcvPATCH_BM3,
+    gcvPATCH_BASEMARKX,
+    gcvPATCH_DEQP,
+    gcvPATCH_SF4,
+    gcePATCH_MGOHEAVEN2,
+    gcePATCH_SILIBILI,
+    gcePATCH_ELEMENTSDEF,
+    gcePATCH_GLOFTKRHM,
+    gcvPATCH_OCLCTS,
+    gcvPATCH_A8HP,
+    gcvPATCH_A8CN,
+    gcvPATCH_WISTONESG,
+    gcvPATCH_SPEEDRACE,
+    gcvPATCH_FSBHAWAIIF,
+    gcvPATCH_AIRNAVY,
+    gcvPATCH_F18NEW,
+    gcvPATCH_CKZOMBIES2,
+    gcvPATCH_EADGKEEPER,
+    gcvPATCH_BASEMARK2V2,
+    gcvPATCH_RIPTIDEGP2,
+    gcvPATCH_OESCTS,
+    gcvPATCH_GANGSTAR,
+    gcvPATCH_WHRKYZIXOVAN,
+    gcvPATCH_NAMESGAS,
+    gcvPATCH_AFTERBURNER,
+    gcvPATCH_UIMARK,
+    gcvPATCH_FM_OES_PLAYER,
+    gcvPATCH_SUMSUNG_BENCH,
+    gcvPATCH_ROCKSTAR_MAXPAYNE,
+    gcvPATCH_TITANPACKING,
+    gcvPATCH_BASEMARKOSIICN,
+    gcvPATCH_FRUITNINJA,
+#if defined(ANDROID)
+    gcePATCH_ANDROID_CTS_MEDIA_PRESENTATIONTIME,
+#endif
+    gcvPATCH_ANDROID_COMPOSITOR,
+    gcvPATCH_CTS_TEXTUREVIEW,
+    gcvPATCH_WATER2_CHUKONG,
+
+    gcvPATCH_COUNT
+} gcePATCH_ID;
+#endif /* gcdENABLE_3D */
+
 typedef void (* gctPLS_DESTRUCTOR) (
     gcsPLS_PTR
     );
@@ -108,29 +214,86 @@ typedef struct _gcsPLS
     gctPOINTER                  eglSurfaceInfo;
     gceSURF_FORMAT              eglConfigFormat;
 
+    /* PLS reference count */
+    gcsATOM_PTR                 reference;
+
     /* PorcessID of the constrcutor process */
     gctUINT32                   processID;
-#if gcdFORCE_GAL_LOAD_TWICE
+
     /* ThreadID of the constrcutor process. */
     gctSIZE_T                   threadID;
     /* Flag for calling module destructor. */
     gctBOOL                     exiting;
-#endif
 
-    /* Reference count for destructor. */
-    gcsATOM_PTR                 reference;
-    gctBOOL                     bKFS;
-#if gcdUSE_NPOT_PATCH
     gctBOOL                     bNeedSupportNP2Texture;
-#endif
 
-    /* Destructor for eglDisplayInfo. */
     gctPLS_DESTRUCTOR           destructor;
+    /* Mutex to guard PLS access. currently it's for EGL.
+    ** We can use this mutex for every PLS access.
+    */
+    gctPOINTER                  accessLock;
+#if gcdENABLE_3D
+    /* Global patchID to overwrite the detection */
+    gcePATCH_ID                 patchID;
+#endif
 }
 gcsPLS;
 
 extern gcsPLS gcPLS;
 
+#if gcdENABLE_3D
+#define gcPLS_INITIALIZER \
+{ \
+    gcvNULL,         /* gcoOS object.      */ \
+    gcvNULL,         /* gcoHAL object.     */ \
+    0,               /* internalSize       */ \
+    gcvNULL,         /* internalPhysical   */ \
+    gcvNULL,         /* internalLogical    */ \
+    0,               /* externalSize       */ \
+    gcvNULL,         /* externalPhysical   */ \
+    gcvNULL,         /* externalLogical    */ \
+    0,               /* contiguousSize     */ \
+    gcvNULL,         /* contiguousPhysical */ \
+    gcvNULL,         /* contiguousLogical  */ \
+    gcvNULL,         /* eglDisplayInfo     */ \
+    gcvNULL,         /* eglSurfaceInfo     */ \
+    gcvSURF_A8R8G8B8,/* eglConfigFormat    */ \
+    gcvNULL,         /* reference          */ \
+    0,               /* processID          */ \
+    0,               /* threadID           */ \
+    gcvFALSE,        /* exiting            */ \
+    gcvFALSE,        /* Special flag for NP2 texture. */ \
+    gcvNULL,         /* destructor        */ \
+    gcvNULL,         /* accessLock        */ \
+    gcvPATCH_NOTINIT,/* global patchID    */ \
+}
+#else
+#define gcPLS_INITIALIZER \
+{ \
+    gcvNULL,         /* gcoOS object.      */ \
+    gcvNULL,         /* gcoHAL object.     */ \
+    0,               /* internalSize       */ \
+    gcvNULL,         /* internalPhysical   */ \
+    gcvNULL,         /* internalLogical    */ \
+    0,               /* externalSize       */ \
+    gcvNULL,         /* externalPhysical   */ \
+    gcvNULL,         /* externalLogical    */ \
+    0,               /* contiguousSize     */ \
+    gcvNULL,         /* contiguousPhysical */ \
+    gcvNULL,         /* contiguousLogical  */ \
+    gcvNULL,         /* eglDisplayInfo     */ \
+    gcvNULL,         /* eglSurfaceInfo     */ \
+    gcvSURF_A8R8G8B8,/* eglConfigFormat    */ \
+    gcvNULL,         /* reference          */ \
+    0,               /* processID          */ \
+    0,               /* threadID           */ \
+    gcvFALSE,        /* exiting            */ \
+    gcvFALSE,        /* Special flag for NP2 texture. */ \
+    gcvNULL,         /* destructor        */ \
+    gcvNULL,         /* accessLock        */ \
+}
+#endif
+
 /******************************************************************************\
 ******************************* Thread local storage *************************
 \******************************************************************************/
@@ -144,30 +307,39 @@ typedef void (* gctTLS_DESTRUCTOR) (
 typedef struct _gcsTLS
 {
     gceHARDWARE_TYPE            currentType;
-    gcoHARDWARE                 hardware;
+
+    /* Current 3D hardwre of this thread */
+    gcoHARDWARE                 currentHardware;
+
+    /* Default 3D hardware of this thread */
+    gcoHARDWARE                 defaultHardware;
+
     /* Only for separated 3D and 2D */
     gcoHARDWARE                 hardware2D;
 #if gcdENABLE_VG
     gcoVGHARDWARE               vg;
     gcoVG                       engineVG;
 #endif /* gcdENABLE_VG */
+#if gcdENABLE_3D
+    gco3D                       engine3D;
+#endif
+#if gcdENABLE_2D
+    gco2D                       engine2D;
+#endif
+
+    /*thread data */
     gctPOINTER                  context;
+    /* ES(including es1 and es2) client driver context which is current state */
+    gctPOINTER                  esClientCtx;
     gctTLS_DESTRUCTOR           destructor;
-    gctBOOL                     ProcessExiting;
 
-#ifndef VIVANTE_NO_3D
-       gco3D                                           engine3D;
-#endif
-#if gcdSYNC
-    gctBOOL                     fenceEnable;
-#endif
-       gco2D                                           engine2D;
     gctBOOL                     copied;
 
-#if gcdFORCE_GAL_LOAD_TWICE
     /* libGAL.so handle */
     gctHANDLE                   handle;
-#endif
+
+    /* If true, do not releas 2d engine and hardware in hal layer */
+    gctBOOL                     release2DUpper;
 }
 gcsTLS;
 
@@ -197,14 +369,12 @@ typedef enum _gcePOOL
     gcvPOOL_VIRTUAL,
     gcvPOOL_USER,
     gcvPOOL_CONTIGUOUS,
-    gcvPOOL_DEFAULT_FORCE_CONTIGUOUS,
-    gcvPOOL_DEFAULT_FORCE_CONTIGUOUS_CACHEABLE,
 
     gcvPOOL_NUMBER_OF_POOLS
 }
 gcePOOL;
 
-#ifndef VIVANTE_NO_3D
+#if gcdENABLE_3D
 /* Blending functions. */
 typedef enum _gceBLEND_FUNCTION
 {
@@ -237,16 +407,6 @@ typedef enum _gceBLEND_MODE
 }
 gceBLEND_MODE;
 
-/* API flags. */
-typedef enum _gceAPI
-{
-    gcvAPI_D3D                  = 0x1,
-    gcvAPI_OPENGL               = 0x2,
-    gcvAPI_OPENVG               = 0x3,
-    gcvAPI_OPENCL               = 0x4,
-}
-gceAPI;
-
 /* Depth modes. */
 typedef enum _gceDEPTH_MODE
 {
@@ -255,7 +415,23 @@ typedef enum _gceDEPTH_MODE
     gcvDEPTH_W,
 }
 gceDEPTH_MODE;
-#endif /* VIVANTE_NO_3D */
+#endif /* gcdENABLE_3D */
+
+#if (gcdENABLE_3D || gcdENABLE_VG)
+/* API flags. */
+typedef enum _gceAPI
+{
+    gcvAPI_D3D = 1,
+    gcvAPI_OPENGL_ES11,
+    gcvAPI_OPENGL_ES20,
+    gcvAPI_OPENGL_ES30,
+    gcvAPI_OPENGL,
+    gcvAPI_OPENVG,
+    gcvAPI_OPENCL,
+}
+gceAPI;
+#endif
+
 
 typedef enum _gceWHERE
 {
@@ -279,8 +455,6 @@ typedef enum _gceSignalHandlerType
 }
 gceSignalHandlerType;
 
-
-#if gcdENABLE_VG
 /* gcsHAL_Limits*/
 typedef struct _gcsHAL_LIMITS
 {
@@ -291,13 +465,12 @@ typedef struct _gcsHAL_LIMITS
     gctUINT32       *chipFeatures;
 
     /* target caps */
-       gctUINT32         maxWidth;
-       gctUINT32         maxHeight;
-       gctUINT32         multiTargetCount;
-       gctUINT32         maxSamples;
+    gctUINT32         maxWidth;
+    gctUINT32         maxHeight;
+    gctUINT32         multiTargetCount;
+    gctUINT32         maxSamples;
 
 }gcsHAL_LIMITS;
-#endif
 
 /******************************************************************************\
 *********** Generic Memory Allocation Optimization Using Containers ************
@@ -367,7 +540,7 @@ gcsCONTAINER_FreeAll(
 
 /* Construct a new gcoHAL object. */
 gceSTATUS
-gcoHAL_Construct(
+gcoHAL_ConstructEx(
     IN gctPOINTER Context,
     IN gcoOS Os,
     OUT gcoHAL * Hal
@@ -375,16 +548,77 @@ gcoHAL_Construct(
 
 /* Destroy an gcoHAL object. */
 gceSTATUS
+gcoHAL_DestroyEx(
+    IN gcoHAL Hal
+    );
+
+/* Empty function for compatibility. */
+gceSTATUS
+gcoHAL_Construct(
+    IN gctPOINTER Context,
+    IN gcoOS Os,
+    OUT gcoHAL * Hal
+    );
+
+/* Empty function for compatibility. */
+gceSTATUS
 gcoHAL_Destroy(
     IN gcoHAL Hal
     );
 
+/* Get HAL options */
+gceSTATUS
+gcoHAL_GetOption(
+     IN gcoHAL Hal,
+     IN gceOPTION Option
+     );
+
+gceSTATUS
+gcoHAL_FrameInfoOps(
+    IN gcoHAL Hal,
+    IN gceFRAMEINFO FrameInfo,
+    IN gceFRAMEINFO_OP Op,
+    IN OUT gctUINT * Val
+    );
+
+
+gceSTATUS
+gcoHAL_GetHardware(
+    IN gcoHAL Hal,
+    OUT gcoHARDWARE* Hw
+    );
+
+#if gcdENABLE_2D
 /* Get pointer to gco2D object. */
 gceSTATUS
 gcoHAL_Get2DEngine(
     IN gcoHAL Hal,
     OUT gco2D * Engine
     );
+#endif
+
+#if gcdENABLE_3D
+gceSTATUS
+gcoHAL_GetSpecialHintData(
+    IN gcoHAL Hal,
+    OUT gctINT * Hint
+    );
+/*
+** Deprecated(Don't use it), keep it here for external library(libgcu.so)
+*/
+gceSTATUS
+gcoHAL_Get3DEngine(
+    IN gcoHAL Hal,
+    OUT gco3D * Engine
+    );
+#endif /* gcdEANBLE_3D */
+
+
+gceSTATUS
+gcoHAL_GetProductName(
+    IN gcoHAL Hal,
+    OUT gctSTRING *ProductName
+    );
 
 gceSTATUS
 gcoHAL_SetFscaleValue(
@@ -403,44 +637,39 @@ gcoHAL_SetBltNP2Texture(
     gctBOOL enable
     );
 
-#ifndef VIVANTE_NO_3D
-/* Get pointer to gco3D object. */
 gceSTATUS
-gcoHAL_Get3DEngine(
-    IN gcoHAL Hal,
-    OUT gco3D * Engine
+gcoHAL_NameVideoMemory(
+    IN gctUINT32 Handle,
+    OUT gctUINT32 * Name
     );
 
 gceSTATUS
-gcoHAL_Query3DEngine(
-    IN gcoHAL Hal,
-    OUT gco3D * Engine
+gcoHAL_ImportVideoMemory(
+    IN gctUINT32 Name,
+    OUT gctUINT32 * Handle
     );
 
 gceSTATUS
-gcoHAL_Set3DEngine(
-    IN gcoHAL Hal,
-    IN gco3D Engine
+gcoHAL_GetVideoMemoryFd(
+    IN gctUINT32 Handle,
+    OUT gctINT * Fd
     );
 
+/* Verify whether the specified feature is available in hardware. */
 gceSTATUS
-gcoHAL_Get3DHardware(
+gcoHAL_IsFeatureAvailable(
     IN gcoHAL Hal,
-    OUT gcoHARDWARE * Hardware
+    IN gceFEATURE Feature
     );
 
 gceSTATUS
-gcoHAL_Set3DHardware(
+gcoHAL_IsSwwaNeeded(
     IN gcoHAL Hal,
-    IN gcoHARDWARE Hardware
+    IN gceSWWA Swwa
     );
 
-
-#endif /* VIVANTE_NO_3D */
-
-/* Verify whether the specified feature is available in hardware. */
 gceSTATUS
-gcoHAL_IsFeatureAvailable(
+gcoHAL_IsFeatureAvailable1(
     IN gcoHAL Hal,
     IN gceFEATURE Feature
     );
@@ -462,6 +691,13 @@ gceSTATUS gcoHAL_QueryChipMinorFeatures(
     OUT gctUINT32* ChipMinorFeatures
     );
 
+gctINT32
+gcoOS_EndRecordAllocation(void);
+void
+gcoOS_RecordAllocation(void);
+void
+gcoOS_AddRecordAllocation(gctSIZE_T Size);
+
 /* Query the amount of video memory. */
 gceSTATUS
 gcoHAL_QueryVideoMemory(
@@ -501,6 +737,36 @@ gcoHAL_ScheduleUnmapMemory(
     IN gctPOINTER Logical
     );
 
+/* Allocate video memory. */
+gceSTATUS
+gcoOS_AllocateVideoMemory(
+    IN gcoOS Os,
+    IN gctBOOL InUserSpace,
+    IN gctBOOL InCacheable,
+    IN OUT gctSIZE_T * Bytes,
+    OUT gctUINT32 * Physical,
+    OUT gctPOINTER * Logical,
+    OUT gctPOINTER * Handle
+    );
+
+/* Free video memory. */
+gceSTATUS
+gcoOS_FreeVideoMemory(
+    IN gcoOS Os,
+    IN gctPOINTER Handle
+    );
+
+/* Lock video memory. */
+gceSTATUS
+gcoOS_LockVideoMemory(
+    IN gcoOS Os,
+    IN gctPOINTER Handle,
+    IN gctBOOL InUserSpace,
+    IN gctBOOL InCacheable,
+    OUT gctUINT32 * Physical,
+    OUT gctPOINTER * Logical
+    );
+
 /* Map user memory. */
 gceSTATUS
 gcoHAL_MapUserMemory(
@@ -537,6 +803,14 @@ gcoHAL_Commit(
     IN gctBOOL Stall
     );
 
+#if gcdENABLE_3D
+/* Sencd fence command. */
+gceSTATUS
+gcoHAL_SendFence(
+    IN gcoHAL Hal
+    );
+#endif /* gcdENABLE_3D */
+
 /* Query the tile capabilities. */
 gceSTATUS
 gcoHAL_QueryTiled(
@@ -591,19 +865,33 @@ gcoHAL_GetDump(
     OUT gcoDUMP * Dump
     );
 
-/* Call the kernel HAL layer. */
+#if gcdENABLE_3D
 gceSTATUS
-gcoHAL_Call(
-    IN gcoHAL Hal,
-    IN OUT gcsHAL_INTERFACE_PTR Interface
+gcoHAL_SetPatchID(
+    IN  gcoHAL Hal,
+    IN  gcePATCH_ID PatchID
     );
 
+/* Get Patch ID based on process name */
 gceSTATUS
 gcoHAL_GetPatchID(
     IN  gcoHAL Hal,
     OUT gcePATCH_ID * PatchID
     );
 
+gceSTATUS
+gcoHAL_SetGlobalPatchID(
+    IN  gcoHAL Hal,
+    IN  gcePATCH_ID PatchID
+    );
+#endif /* gcdENABLE_3D */
+/* Call the kernel HAL layer. */
+gceSTATUS
+gcoHAL_Call(
+    IN gcoHAL Hal,
+    IN OUT gcsHAL_INTERFACE_PTR Interface
+    );
+
 /* Schedule an event. */
 gceSTATUS
 gcoHAL_ScheduleEvent(
@@ -660,18 +948,19 @@ gcoHAL_QueryChipCount(
     );
 
 gceSTATUS
-gcoHAL_QuerySeparated3D2D(
-    IN gcoHAL Hal
+gcoHAL_Query3DCoreCount(
+    IN gcoHAL       Hal,
+    OUT gctUINT32  *Count
     );
 
 gceSTATUS
-gcoHAL_QuerySpecialHint(
-    IN gceSPECIAL_HINT Hint
+gcoHAL_QuerySeparated2D(
+    IN gcoHAL Hal
     );
 
 gceSTATUS
-gcoHAL_SetSpecialHintData(
-    IN gcoHARDWARE Hardware
+gcoHAL_Is3DAvailable(
+    IN gcoHAL Hal
     );
 
 /* Get pointer to gcoVG object. */
@@ -681,23 +970,91 @@ gcoHAL_GetVGEngine(
     OUT gcoVG * Engine
     );
 
-#if gcdENABLE_VG
 gceSTATUS
 gcoHAL_QueryChipLimits(
     IN gcoHAL           Hal,
     IN gctINT32         Chip,
+    IN gctINT32         Mask,
     OUT gcsHAL_LIMITS   *Limits);
 
 gceSTATUS
 gcoHAL_QueryChipFeature(
     IN gcoHAL       Hal,
     IN gctINT32     Chip,
+    IN gctINT32     Mask,
     IN gceFEATURE   Feature);
 
+/*----------------------------------------------------------------------------*/
+/*----- Shared Buffer --------------------------------------------------------*/
+
+/* Create shared buffer. */
+gceSTATUS
+gcoHAL_CreateShBuffer(
+    IN gctUINT32 Size,
+    OUT gctSHBUF * ShBuf
+    );
+
+/* Destroy shared buffer. */
+gceSTATUS
+gcoHAL_DestroyShBuffer(
+    IN gctSHBUF ShBuf
+    );
+
+/* Map shared buffer to current process. */
+gceSTATUS
+gcoHAL_MapShBuffer(
+    IN gctSHBUF ShBuf
+    );
+
+/* Write user data to shared buffer. */
+gceSTATUS
+gcoHAL_WriteShBuffer(
+    IN gctSHBUF ShBuf,
+    IN gctCONST_POINTER Data,
+    IN gctUINT32 ByteCount
+    );
+
+/* Read user data from shared buffer. */
+gceSTATUS
+gcoHAL_ReadShBuffer(
+    IN gctSHBUF ShBuf,
+    IN gctPOINTER Data,
+    IN gctUINT32 BytesCount,
+    OUT gctUINT32 * BytesRead
+    );
+
+/* Config power management to be enabled or disabled. */
+gceSTATUS
+gcoHAL_ConfigPowerManagement(
+    IN gctBOOL Enable
+    );
+
+#if gcdENABLE_3D || gcdENABLE_VG
+/* Query the target capabilities. */
+gceSTATUS
+gcoHAL_QueryTargetCaps(
+    IN gcoHAL Hal,
+    OUT gctUINT * MaxWidth,
+    OUT gctUINT * MaxHeight,
+    OUT gctUINT * MultiTargetCount,
+    OUT gctUINT * MaxSamples
+    );
 #endif
+
 /******************************************************************************\
 ********************************** gcoOS Object *********************************
 \******************************************************************************/
+/* Lock PLS access */
+gceSTATUS
+gcoOS_LockPLS(
+    void
+    );
+
+/* Unlock PLS access */
+gceSTATUS
+gcoOS_UnLockPLS(
+    void
+    );
 
 /* Get PLS value for given key */
 gctPOINTER
@@ -724,17 +1081,17 @@ gcoOS_GetTLS(
 /* Destroy the objects associated with the current thread. */
 void
 gcoOS_FreeThreadData(
-    IN gctBOOL ProcessExiting
+    void
     );
 
-/* Construct a new gcoOS object. */
+/* Empty function for compatibility. */
 gceSTATUS
 gcoOS_Construct(
     IN gctPOINTER Context,
     OUT gcoOS * Os
     );
 
-/* Destroy an gcoOS object. */
+/* Empty function for compatibility. */
 gceSTATUS
 gcoOS_Destroy(
     IN gcoOS Os
@@ -770,6 +1127,21 @@ gcoOS_Free(
     IN gctPOINTER Memory
     );
 
+/* Allocate memory. */
+gceSTATUS
+gcoOS_AllocateSharedMemory(
+    IN gcoOS Os,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Memory
+    );
+
+/* Free memory. */
+gceSTATUS
+gcoOS_FreeSharedMemory(
+    IN gcoOS Os,
+    IN gctPOINTER Memory
+    );
+
 /* Allocate memory. */
 gceSTATUS
 gcoOS_AllocateMemory(
@@ -804,33 +1176,6 @@ gcoOS_FreeContiguous(
     IN gctSIZE_T Bytes
     );
 
-/* Allocate video memory. */
-gceSTATUS
-gcoOS_AllocateVideoMemory(
-    IN gcoOS Os,
-    IN gctBOOL InUserSpace,
-    IN gctBOOL InCacheable,
-    IN OUT gctSIZE_T * Bytes,
-    OUT gctUINT32 * Physical,
-    OUT gctPOINTER * Logical,
-    OUT gctPOINTER * Handle
-    );
-
-/* Free video memory. */
-gceSTATUS
-gcoOS_FreeVideoMemory(
-    IN gcoOS Os,
-    IN gctPOINTER Handle
-    );
-
-gceSTATUS
-gcoSURF_GetBankOffsetBytes(
-    IN gcoSURF Surfce,
-    IN gceSURF_TYPE Type,
-    IN gctUINT32 Stride,
-    IN gctUINT32_PTR Bytes
-    );
-
 /* Map user memory. */
 gceSTATUS
 gcoOS_MapUserMemory(
@@ -893,12 +1238,16 @@ gcoOS_FreeNonPagedMemory(
     );
 
 #define gcmOS_SAFE_FREE(os, mem) \
-       gcoOS_Free(os, mem); \
-       mem = gcvNULL
+    gcoOS_Free(os, mem); \
+    mem = gcvNULL
+
+#define gcmOS_SAFE_FREE_SHARED_MEMORY(os, mem) \
+    gcoOS_FreeSharedMemory(os, mem); \
+    mem = gcvNULL
 
 #define gcmkOS_SAFE_FREE(os, mem) \
     gckOS_Free(os, mem); \
-       mem = gcvNULL
+    mem = gcvNULL
 
 typedef enum _gceFILE_MODE
 {
@@ -1039,7 +1388,7 @@ gcoOS_SetEnv(
 gceSTATUS
 gcoOS_GetCwd(
     IN gcoOS Os,
-       IN gctINT SizeInBytes,
+    IN gctINT SizeInBytes,
     OUT gctSTRING Buffer
     );
 
@@ -1146,18 +1495,17 @@ gcoOS_StrToFloat(
     );
 
 /* Convert hex string to integer. */
-gceSTATUS
-gcoOS_HexStrToInt(
-       IN gctCONST_STRING String,
-       OUT gctINT * Int
-       );
+gceSTATUS gcoOS_HexStrToInt(
+    IN gctCONST_STRING String,
+    OUT gctINT * Int
+    );
 
 /* Convert hex string to float. */
 gceSTATUS
 gcoOS_HexStrToFloat(
-       IN gctCONST_STRING String,
-       OUT gctFLOAT * Float
-       );
+    IN gctCONST_STRING String,
+    OUT gctFLOAT * Float
+    );
 
 /* Convert string to integer. */
 gceSTATUS
@@ -1233,11 +1581,6 @@ gcoOS_SetProfileSetting(
         );
 #endif
 
-gctBOOL
-gcoOS_IsNeededSupportNP2Texture(
-    IN gctCHAR* ProcName
-    );
-
 /* Query the video memory. */
 gceSTATUS
 gcoOS_QueryVideoMemory(
@@ -1292,6 +1635,22 @@ gcoOS_AtomDestroy(
     IN gcsATOM_PTR Atom
     );
 
+/* Get the 32-bit value protected by an atom. */
+gceSTATUS
+gcoOS_AtomGet(
+    IN gcoOS Os,
+    IN gcsATOM_PTR Atom,
+    OUT gctINT32_PTR Value
+    );
+
+/* Set the 32-bit value protected by an atom. */
+gceSTATUS
+gcoOS_AtomSet(
+    IN gcoOS Os,
+    IN gcsATOM_PTR Atom,
+    IN gctINT32 Value
+    );
+
 /* Increment an atom. */
 gceSTATUS
 gcoOS_AtomIncrement(
@@ -1523,7 +1882,7 @@ gcoOS_ReadRegister(
 gceSTATUS
 gcoOS_CacheClean(
     IN gcoOS Os,
-    IN gctUINT64 Node,
+    IN gctUINT32 Node,
     IN gctPOINTER Logical,
     IN gctSIZE_T Bytes
     );
@@ -1531,7 +1890,7 @@ gcoOS_CacheClean(
 gceSTATUS
 gcoOS_CacheFlush(
     IN gcoOS Os,
-    IN gctUINT64 Node,
+    IN gctUINT32 Node,
     IN gctPOINTER Logical,
     IN gctSIZE_T Bytes
     );
@@ -1539,7 +1898,7 @@ gcoOS_CacheFlush(
 gceSTATUS
 gcoOS_CacheInvalidate(
     IN gcoOS Os,
-    IN gctUINT64 Node,
+    IN gctUINT32 Node,
     IN gctPOINTER Logical,
     IN gctSIZE_T Bytes
     );
@@ -1550,6 +1909,11 @@ gcoOS_MemoryBarrier(
     IN gctPOINTER Logical
     );
 
+gceSTATUS
+gcoOS_CPUPhysicalToGPUPhysical(
+    IN gctUINT32 CPUPhysical,
+    OUT gctUINT32_PTR GPUPhysical
+    );
 
 /*----------------------------------------------------------------------------*/
 /*----- Profile --------------------------------------------------------------*/
@@ -1608,7 +1972,7 @@ gcoOS_QueryProfileTickRate(
 #   define gcmPROFILE_QUERY(start, ticks)   do { } while (gcvFALSE)
 #   define gcmPROFILE_ONLY(x)               do { } while (gcvFALSE)
 #   define gcmPROFILE_ELSE(x)               x
-#   define gcmPROFILE_DECLARE_ONLY(x)       do { } while (gcvFALSE) 
+#   define gcmPROFILE_DECLARE_ONLY(x)       do { } while (gcvFALSE)
 #   define gcmPROFILE_DECLARE_ELSE(x)       x
 #endif
 
@@ -1653,6 +2017,41 @@ gcoMATH_UInt8AsFloat16(
     IN gctUINT8 X
     );
 
+gctUINT32
+gcoMATH_Float16ToFloat(
+    IN gctUINT16 In
+    );
+
+gctUINT16
+gcoMATH_FloatToFloat16(
+    IN gctUINT32 In
+    );
+
+gctUINT32
+gcoMATH_Float11ToFloat(
+    IN gctUINT32 In
+    );
+
+gctUINT16
+gcoMATH_FloatToFloat11(
+    IN gctUINT32 In
+    );
+
+gctUINT32
+gcoMATH_Float10ToFloat(
+    IN gctUINT32 In
+    );
+
+gctUINT16
+gcoMATH_FloatToFloat10(
+    IN gctUINT32 In
+    );
+
+gctUINT32
+gcoMATH_Float14ToFloat(
+    IN gctUINT16 In
+    );
+
 /******************************************************************************\
 **************************** Coordinate Structures *****************************
 \******************************************************************************/
@@ -1702,7 +2101,6 @@ typedef union _gcsPIXEL
 
 } gcsPIXEL;
 
-
 /******************************************************************************\
 ********************************* gcoSURF Object ********************************
 \******************************************************************************/
@@ -1719,9 +2117,28 @@ typedef enum _gceFORMAT_CLASS
     gcvFORMAT_CLASS_LUMINANCE,
     gcvFORMAT_CLASS_BUMP,
     gcvFORMAT_CLASS_DEPTH,
+    gcvFORMAT_CLASS_ASTC,
+    gcvFORMAT_CLASS_OTHER
 }
 gceFORMAT_CLASS;
 
+/* Color format data type */
+typedef enum _gceFORMAT_DATATYPE
+{
+    gcvFORMAT_DATATYPE_UNSIGNED_NORMALIZED,
+    gcvFORMAT_DATATYPE_SIGNED_NORMALIZED,
+    gcvFORMAT_DATATYPE_UNSIGNED_INTEGER,
+    gcvFORMAT_DATATYPE_SIGNED_INTEGER,
+    gcvFORMAT_DATATYPE_FLOAT16,
+    gcvFORMAT_DATATYPE_FLOAT32,
+    gcvFORMAT_DATATYPE_FLOAT_E5B9G9R9,
+    gcvFORMAT_DATATYPE_FLOAT_B10G11R11F,
+    gcvFORMAT_DATATYPE_INDEX,
+    gcvFORMAT_DATATYPE_SRGB,
+    gcvFORMAT_DATATYPE_FLOAT32_UINT,
+}
+gceFORMAT_DATATYPE;
+
 /* Special enums for width field in gcsFORMAT_COMPONENT. */
 typedef enum _gceCOMPONENT_CONTROL
 {
@@ -1794,34 +2211,74 @@ typedef struct _gcsFORMAT_CLASS_TYPE_DEPTH
 }
 gcsFORMAT_CLASS_TYPE_DEPTH;
 
+typedef union _gcuPIXEL_FORMAT_CLASS
+{
+    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;
+}
+gcuPIXEL_FORMAT_CLASS;
+
 /* Format parameters. */
 typedef struct _gcsSURF_FORMAT_INFO
 {
+    /* Name of the format */
+    gctCONST_STRING             formatName;
+
     /* Format code and class. */
     gceSURF_FORMAT              format;
     gceFORMAT_CLASS             fmtClass;
 
+    /* Format data type */
+    gceFORMAT_DATATYPE          fmtDataType;
+
     /* The size of one pixel in bits. */
     gctUINT8                    bitsPerPixel;
 
-    /* Component swizzle. */
-    gceSURF_SWIZZLE             swizzle;
+    /* Pixel block dimensions. */
+    gctUINT                     blockWidth;
+    gctUINT                     blockHeight;
+
+    /* Pixel block size in bits. */
+    gctUINT                     blockSize;
+
+    /* Some formats are larger than what the GPU can support.      */
+    /* These formats are read in the number of layers specified.   */
+    gctUINT8                    layers;
+
+    /* The format is faked and software will interpret it differently
+    ** with HW. Most of them can't be blendable(PE) or filterable(TX).
+    */
+    gctBOOL                     fakedFormat;
 
     /* 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;
+    gctBOOL                     interleaved;
+
+    /* sRGB format. */
+    gctBOOL                     sRGB;
 
     /* 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;
+    gcuPIXEL_FORMAT_CLASS       u;
+
+    /* Format components. */
+    gcuPIXEL_FORMAT_CLASS       uOdd;
+
+    /* Render format. */
+    gceSURF_FORMAT              closestRenderFormat;
+    /*gctCLOSEST_FORMAT           dynamicClosestRenderFormat;*/
+    gctUINT                     renderFormat;
+    const gceTEXTURE_SWIZZLE  * pixelSwizzle;
+
+    /* Texture format. */
+    gceSURF_FORMAT              closestTXFormat;
+    gctUINT                     txFormat;
+    const gceTEXTURE_SWIZZLE  * txSwizzle;
+    gctBOOL                     txIntFilter;
 }
 gcsSURF_FORMAT_INFO;
 
@@ -1835,16 +2292,6 @@ typedef struct _gcsSURF_FRAMEBUFFER
 }
 gcsSURF_FRAMEBUFFER;
 
-typedef struct _gcsVIDMEM_NODE_SHARED_INFO
-{
-    gctBOOL                     tileStatusDisabled;
-    gcsPOINT                    SrcOrigin;
-    gcsPOINT                    DestOrigin;
-    gcsSIZE                     RectSize;
-    gctUINT32                   clearValue;
-}
-gcsVIDMEM_NODE_SHARED_INFO;
-
 /* Generic pixel component descriptors. */
 extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XXX8;
 extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XX8X;
@@ -1887,13 +2334,23 @@ gcoSURF_MapUserSurface(
     IN gctUINT32 Physical
     );
 
+/* Wrapp surface with known logical/GPU address */
+gceSTATUS
+gcoSURF_WrapSurface(
+    IN gcoSURF Surface,
+    IN gctUINT Alignment,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Physical
+    );
+
+
 /* Query vid mem node info. */
 gceSTATUS
 gcoSURF_QueryVidMemNode(
     IN gcoSURF Surface,
-    OUT gctUINT64 * Node,
+    OUT gctUINT32 * Node,
     OUT gcePOOL * Pool,
-    OUT gctUINT_PTR Bytes
+    OUT gctSIZE_T_PTR Bytes
     );
 
 /* Set the color type of the surface. */
@@ -1910,23 +2367,26 @@ gcoSURF_GetColorType(
     OUT gceSURF_COLOR_TYPE *ColorType
     );
 
-/* Set the surface ration angle. */
+/* Set the color space of the surface. */
 gceSTATUS
-gcoSURF_SetRotation(
+gcoSURF_SetColorSpace(
     IN gcoSURF Surface,
-    IN gceSURF_ROTATION Rotation
+    IN gceSURF_COLOR_SPACE ColorSpace
     );
 
+/* Get the color space of the surface. */
 gceSTATUS
-gcoSURF_SetPreRotation(
+gcoSURF_GetColorSpace(
     IN gcoSURF Surface,
-    IN gceSURF_ROTATION Rotation
+    OUT gceSURF_COLOR_SPACE *ColorSpace
     );
 
+
+/* Set the surface ration angle. */
 gceSTATUS
-gcoSURF_GetPreRotation(
+gcoSURF_SetRotation(
     IN gcoSURF Surface,
-    IN gceSURF_ROTATION *Rotation
+    IN gceSURF_ROTATION Rotation
     );
 
 gceSTATUS
@@ -1934,25 +2394,38 @@ gcoSURF_IsValid(
     IN gcoSURF Surface
     );
 
-#ifndef VIVANTE_NO_3D
+#if gcdENABLE_3D
 /* Verify and return the state of the tile status mechanism. */
 gceSTATUS
 gcoSURF_IsTileStatusSupported(
     IN gcoSURF Surface
     );
 
-/* Process tile status for the specified surface. */
+/* Verify if surface has tile status enabled. */
+gceSTATUS
+gcoSURF_IsTileStatusEnabled(
+    IN gcoSURF Surface
+    );
+
+/* Verify if surface is compressed. */
 gceSTATUS
-gcoSURF_SetTileStatus(
+gcoSURF_IsCompressed(
     IN gcoSURF Surface
     );
 
-/* Enable tile status for the specified surface. */
+/* Enable tile status for the specified surface on zero slot. */
 gceSTATUS
 gcoSURF_EnableTileStatus(
     IN gcoSURF Surface
     );
 
+/* Enable tile status for the specified surface on specified slot. */
+gceSTATUS
+gcoSURF_EnableTileStatusEx(
+    IN gcoSURF Surface,
+    IN gctUINT RtIndex
+    );
+
 /* Disable tile status for the specified surface. */
 gceSTATUS
 gcoSURF_DisableTileStatus(
@@ -1960,15 +2433,13 @@ gcoSURF_DisableTileStatus(
     IN gctBOOL Decompress
     );
 
+/* Flush tile status cache for the specified surface. */
 gceSTATUS
-gcoSURF_AlignResolveRect(
-    IN gcoSURF Surf,
-    IN gcsPOINT_PTR RectOrigin,
-    IN gcsPOINT_PTR RectSize,
-    OUT gcsPOINT_PTR AlignedOrigin,
-    OUT gcsPOINT_PTR AlignedSize
+gcoSURF_FlushTileStatus(
+    IN gcoSURF Surface,
+    IN gctBOOL Decompress
     );
-#endif /* VIVANTE_NO_3D */
+#endif /* gcdENABLE_3D */
 
 /* Get surface size. */
 gceSTATUS
@@ -1998,11 +2469,34 @@ gcoSURF_GetAlignment(
     OUT gctUINT * YAlignment
     );
 
+gceSTATUS
+gcoSURF_AlignResolveRect(
+    IN gcoSURF Surf,
+    IN gcsPOINT_PTR RectOrigin,
+    IN gcsPOINT_PTR RectSize,
+    OUT gcsPOINT_PTR AlignedOrigin,
+    OUT gcsPOINT_PTR AlignedSize
+    );
+
 /* Get surface type and format. */
 gceSTATUS
 gcoSURF_GetFormat(
     IN gcoSURF Surface,
-    OUT gceSURF_TYPE * Type,
+    OUT OPTIONAL gceSURF_TYPE * Type,
+    OUT OPTIONAL gceSURF_FORMAT * Format
+    );
+
+/* Get surface information */
+gceSTATUS
+gcoSURF_GetFormatInfo(
+    IN gcoSURF Surface,
+    OUT gcsSURF_FORMAT_INFO_PTR * formatInfo
+    );
+
+/* Get Surface pack format */
+gceSTATUS
+gcoSURF_GetPackedFormat(
+    IN gcoSURF Surface,
     OUT gceSURF_FORMAT * Format
     );
 
@@ -2013,6 +2507,20 @@ gcoSURF_GetTiling(
     OUT gceTILING * Tiling
     );
 
+/* Get flip bitmap offset bytes. */
+gceSTATUS
+gcoSURF_GetFlipBitmapOffset(
+    IN gcoSURF Surface,
+    OUT gctUINT_PTR FlipBitmapOffset
+    );
+
+/* Get bottom buffer offset bytes. */
+gceSTATUS
+gcoSURF_GetBottomBufferOffset(
+    IN gcoSURF Surface,
+    OUT gctUINT_PTR BottomBufferOffset
+    );
+
 /* Lock the surface. */
 gceSTATUS
 gcoSURF_Lock(
@@ -2028,7 +2536,16 @@ gcoSURF_Unlock(
     IN gctPOINTER Memory
     );
 
-/* Return pixel format parameters. */
+/*. Query surface flags.*/
+gceSTATUS
+gcoSURF_QueryFlags(
+    IN gcoSURF Surface,
+    IN gceSURF_FLAG Flag
+    );
+
+/* Return pixel format parameters; Info is required to be a pointer to an
+ * array of at least two items because some formats have up to two records
+ * of description. */
 gceSTATUS
 gcoSURF_QueryFormat(
     IN gceSURF_FORMAT Format,
@@ -2054,9 +2571,6 @@ gcoSURF_FillFromTile(
     IN gcoSURF Surface
     );
 
-/* Check if surface needs a filler. */
-gceSTATUS gcoSURF_NeedFiller(IN gcoSURF Surface);
-
 /* Fill surface with a value. */
 gceSTATUS
 gcoSURF_Fill(
@@ -2085,6 +2599,14 @@ gcoSURF_ConstructWrapper(
     OUT gcoSURF * Surface
     );
 
+/* Set surface flags.*/
+gceSTATUS
+gcoSURF_SetFlags(
+    IN gcoSURF Surface,
+    IN gceSURF_FLAG Flag,
+    IN gctBOOL Value
+    );
+
 /* Set the underlying buffer for the surface wrapper. */
 gceSTATUS
 gcoSURF_SetBuffer(
@@ -2157,13 +2679,7 @@ gcoSURF_QueryOrientation(
 gceSTATUS
 gcoSURF_SetOffset(
     IN gcoSURF Surface,
-    IN gctUINT Offset
-    );
-
-gceSTATUS
-gcoSURF_GetOffset(
-    IN gcoSURF Surface,
-    OUT gctUINT *Offset
+    IN gctSIZE_T Offset
     );
 
 gceSTATUS
@@ -2174,6 +2690,30 @@ gcoSURF_NODE_Cache(
     IN gceCACHEOPERATION Operation
     );
 
+/* Lock and unlock surface node */
+gceSTATUS
+gcoSURF_LockNode(
+    IN gcsSURF_NODE_PTR Node,
+    OUT gctUINT32 * Address,
+    OUT gctPOINTER * Memory
+    );
+
+gceSTATUS
+gcoSURF_UnLockNode(
+    IN gcsSURF_NODE_PTR Node,
+    IN gceSURF_TYPE Type
+    );
+
+/* Perform CPU cache operation on surface node */
+gceSTATUS
+gcoSURF_NODE_CPUCacheOperation(
+    IN gcsSURF_NODE_PTR Node,
+    IN gceSURF_TYPE Type,
+    IN gctSIZE_T Offset,
+    IN gctSIZE_T Length,
+    IN gceCACHEOPERATION Operation
+    );
+
 /* Perform CPU cache operation on surface */
 gceSTATUS
 gcoSURF_CPUCacheOperation(
@@ -2183,14 +2723,85 @@ gcoSURF_CPUCacheOperation(
 
 
 gceSTATUS
-gcoSURF_SetLinearResolveAddress(
+gcoSURF_Swap(
+    IN gcoSURF Surface1,
+    IN gcoSURF Surface2
+    );
+
+gceSTATUS
+gcoSURF_ResetSurWH(
     IN gcoSURF Surface,
-    IN gctUINT32 Address,
-    IN gctPOINTER Memory
+    IN gctUINT oriw,
+    IN gctUINT orih,
+    IN gctUINT alignw,
+    IN gctUINT alignh,
+    IN gceSURF_FORMAT fmt
+);
+
+/* Update surface timestamp. */
+gceSTATUS
+gcoSURF_UpdateTimeStamp(
+    IN gcoSURF Surface
     );
 
-    gceSTATUS
-    gcoSURF_Swap(IN gcoSURF Surface1, IN gcoSURF Surface2);
+/* Query surface current timestamp. */
+gceSTATUS
+gcoSURF_QueryTimeStamp(
+    IN gcoSURF Surface,
+    OUT gctUINT64 * TimeStamp
+    );
+
+/*
+ * Allocate shared buffer for this surface, so that
+ * surface states can be shared across processes.
+ */
+gceSTATUS
+gcoSURF_AllocShBuffer(
+    IN gcoSURF Surface,
+    OUT gctSHBUF * ShBuf
+    );
+
+/* Bind shared buffer to this surface */
+gceSTATUS
+gcoSURF_BindShBuffer(
+    IN gcoSURF Surface,
+    IN gctSHBUF ShBuf
+    );
+
+/* Push surface shared states to shared buffer. */
+gceSTATUS
+gcoSURF_PushSharedInfo(
+    IN gcoSURF Surface
+    );
+
+/* Pop shared states from shared buffer. */
+gceSTATUS
+gcoSURF_PopSharedInfo(
+    IN gcoSURF Surface
+    );
+
+#if (gcdENABLE_3D || gcdENABLE_VG)
+/* Copy surface. */
+gceSTATUS
+gcoSURF_Copy(
+    IN gcoSURF Surface,
+    IN gcoSURF Source
+    );
+
+/* 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
+    );
+#endif
 
 /******************************************************************************\
 ********************************* gcoDUMP Object ********************************
@@ -2455,7 +3066,16 @@ gcoOS_SetDebugFile(
 gctFILE
 gcoOS_ReplaceDebugFile(
     IN gctFILE fp
-       );
+    );
+
+void
+gcoOS_SysTraceBegin(
+    IN gctCONST_STRING FuncName
+    );
+
+void
+gcoOS_SysTraceEnd(
+    IN void);
 
 /*******************************************************************************
 **
@@ -2484,7 +3104,7 @@ gcoOS_DebugFatal(
 #if gcmIS_DEBUG(gcdDEBUG_FATAL)
 #   define gcmFATAL             gcoOS_DebugFatal
 #   define gcmkFATAL            gckOS_DebugFatal
-#elif gcdHAS_ELLIPSES
+#elif gcdHAS_ELLIPSIS
 #   define gcmFATAL(...)
 #   define gcmkFATAL(...)
 #else
@@ -2546,7 +3166,7 @@ gcoOS_DebugTrace(
 #   define gcmTRACE             gcoOS_DebugTrace
 #   define gcmkTRACE            gckOS_DebugTrace
 #   define gcmkTRACE_N          gckOS_DebugTraceN
-#elif gcdHAS_ELLIPSES
+#elif gcdHAS_ELLIPSIS
 #   define gcmTRACE(...)
 #   define gcmkTRACE(...)
 #   define gcmkTRACE_N(...)
@@ -2615,6 +3235,9 @@ gcoOS_DebugTrace(
 #define gcvZONE_IMAGE           (1 << 19)
 #define gcvZONE_UTILITY         (1 << 20)
 #define gcvZONE_PARAMETERS      (1 << 21)
+#define gcvZONE_BUFOBJ          (1 << 22)
+#define gcvZONE_SHADER          (1 << 23)
+#define gcvZONE_STREAM_OUT      (1 << 24)
 
 /* API definitions. */
 #define gcvZONE_API_HAL         (1 << 28)
@@ -2624,9 +3247,9 @@ gcoOS_DebugTrace(
 #define gcvZONE_API_VG11        (5 << 28)
 #define gcvZONE_API_GL          (6 << 28)
 #define gcvZONE_API_DFB         (7 << 28)
-#define gcvZONE_API_GDI         (8 << 28)
-#define gcvZONE_API_D3D         (9 << 28)
-#define gcvZONE_API_ES30        (10 << 28)
+#define gcvZONE_API_GDI         ((gctUINT32)8 << 28)
+#define gcvZONE_API_D3D         ((gctUINT32)9 << 28)
+#define gcvZONE_API_ES30        ((gctUINT32)10 << 28)
 
 
 #define gcmZONE_GET_API(zone)   ((zone) >> 28)
@@ -2685,7 +3308,7 @@ gcoOS_DebugTraceZone(
 #   define gcmTRACE_ZONE            gcoOS_DebugTraceZone
 #   define gcmkTRACE_ZONE           gckOS_DebugTraceZone
 #   define gcmkTRACE_ZONE_N         gckOS_DebugTraceZoneN
-#elif gcdHAS_ELLIPSES
+#elif gcdHAS_ELLIPSIS
 #   define gcmTRACE_ZONE(...)
 #   define gcmkTRACE_ZONE(...)
 #   define gcmkTRACE_ZONE_N(...)
@@ -2748,28 +3371,20 @@ gcoOS_DebugTraceZone(
 **      ...         Optional arguments for text.
 */
 #if gcmIS_DEBUG(gcdDEBUG_STACK)
-    void
-    gcoOS_StackPush(
-        IN gctCONST_STRING Function,
-        IN gctINT Line,
-        IN gctCONST_STRING Text,
-        ...
-        );
-    void
-    gcoOS_StackPop(
-        IN gctCONST_STRING Function
-        );
-    void
-    gcoOS_StackDump(
-        void
-        );
+    void gcoOS_StackPush(IN gctINT8_PTR Identity, IN gctCONST_STRING Function, IN gctINT Line, IN gctCONST_STRING Text, ...);
+    void gcoOS_StackPop(IN gctINT8_PTR Identity, IN gctCONST_STRING Function);
+    void gcoOS_StackDump(void);
+    void gcoOS_StackRemove(IN gctHANDLE Thread);
+
 #   define gcmSTACK_PUSH            gcoOS_StackPush
 #   define gcmSTACK_POP             gcoOS_StackPop
 #   define gcmSTACK_DUMP            gcoOS_StackDump
-#elif gcdHAS_ELLIPSES
+#   define gcmSTACK_REMOVE          gcoOS_StackRemove
+#elif gcdHAS_ELLIPSIS
 #   define gcmSTACK_PUSH(...)       do { } while (0)
-#   define gcmSTACK_POP(Function)   do { } while (0)
+#   define gcmSTACK_POP(...)        do { } while (0)
 #   define gcmSTACK_DUMP()          do { } while (0)
+#   define gcmSTACK_REMOVE(...)     do { } while (0)
 #else
     gcmINLINE static void
     __dummy_stack_push(
@@ -2780,8 +3395,62 @@ gcoOS_DebugTraceZone(
     {
     }
 #   define gcmSTACK_PUSH            __dummy_stack_push
-#   define gcmSTACK_POP(Function)   do { } while (0)
+#   define gcmSTACK_POP(a,b)        do { } while (0)
 #   define gcmSTACK_DUMP()          do { } while (0)
+#   define gcmSTACK_REMOVE(a)       do { } while (0)
+#endif
+
+/******************************************************************************\
+******************************** Binary Trace **********************************
+\******************************************************************************/
+typedef struct _gcsBINARY_TRACE_MESSAGE * gcsBINARY_TRACE_MESSAGE_PTR;
+typedef struct _gcsBINARY_TRACE_MESSAGE
+{
+    gctUINT32   signature;
+    gctUINT32   pid;
+    gctUINT32   tid;
+    gctUINT32   line;
+    gctUINT32   numArguments;
+    gctUINT8    payload;
+}
+gcsBINARY_TRACE_MESSAGE;
+
+#define gcdBINARY_TRACE_MESSAGE_SIZE 240
+
+#if gcdBINARY_TRACE
+    void
+    gcoOS_BinaryTrace(
+        IN gctCONST_STRING Function,
+        IN gctINT Line,
+        IN gctCONST_STRING Text OPTIONAL,
+        ...
+        );
+
+    void
+    gckOS_BinaryTrace(
+        IN gctCONST_STRING Function,
+        IN gctINT Line,
+        IN gctCONST_STRING Text OPTIONAL,
+        ...
+        );
+
+#   define gcmBINARY_TRACE          gcoOS_BinaryTrace
+#   define gcmkBINARY_TRACE         gckOS_BinaryTrace
+#elif gcdHAS_ELLIPSIS
+#   define gcmBINARY_TRACE(Function, Line, Text, ...)
+#   define gcmkBINARY_TRACE(Function, Line, Text, ...)
+#else
+    gcmINLINE static void
+    __dummy_binary_trace(
+        IN gctCONST_STRING Function,
+        IN gctINT Line,
+        IN gctCONST_STRING Text,
+        )
+    {
+    }
+
+#   define gcmBINARY_TRACE          __dummy_binary_trace
+#   define gcmkBINARY_TRACE         __dummy_binary_trace
 #endif
 
 /******************************************************************************\
@@ -2790,6 +3459,9 @@ gcoOS_DebugTraceZone(
 
 #define gcdHEADER_LEVEL             gcvLEVEL_VERBOSE
 
+#ifndef gcdEMPTY_HEADER_FOOTER
+#define gcdEMPTY_HEADER_FOOTER 0
+#endif
 
 #if gcdENABLE_PROFILING
 void
@@ -2799,33 +3471,40 @@ gcoOS_ProfileDB(
     );
 
 #define gcmHEADER() \
+    gctINT8 __user__ = 1; \
     static gctBOOL __profile__initialized__ = gcvFALSE; \
-    gcmSTACK_PUSH(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+    gcmSTACK_PUSH(&__user__, __FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
     gcoOS_ProfileDB(__FUNCTION__, &__profile__initialized__)
 #define gcmHEADER_ARG(...) \
+    gctINT8 __user__ = 1; \
     static gctBOOL __profile__initialized__ = gcvFALSE; \
-    gcmSTACK_PUSH(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
+    gcmSTACK_PUSH(&__user__, __FUNCTION__, __LINE__, Text, __VA_ARGS__); \
     gcoOS_ProfileDB(__FUNCTION__, &__profile__initialized__)
 #define gcmFOOTER() \
-    gcmSTACK_POP(__FUNCTION__); \
+    gcmSTACK_POP(&__user__, __FUNCTION__); \
     gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
 #define gcmFOOTER_NO() \
-    gcmSTACK_POP(__FUNCTION__); \
+    gcmSTACK_POP(&__user__, __FUNCTION__); \
     gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
 #define gcmFOOTER_ARG(...) \
-    gcmSTACK_POP(__FUNCTION__); \
+    gcmSTACK_POP(&__user__, __FUNCTION__); \
     gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
 #define gcmFOOTER_KILL() \
-    gcmSTACK_POP(__FUNCTION__); \
+    gcmSTACK_POP(&__user__, __FUNCTION__); \
     gcoOS_ProfileDB(gcvNULL, gcvNULL)
 
 #else /* gcdENABLE_PROFILING */
 
-#if gcdHAS_ELLIPSES
+#ifdef gcdFSL_REL_BUILD
+#define gcmHEADER()
+#elif gcdEMPTY_HEADER_FOOTER
+#   define gcmHEADER()
+#elif gcdHAS_ELLIPSIS
 #define gcmHEADER() \
     gctINT8 __user__ = 1; \
     gctINT8_PTR __user_ptr__ = &__user__; \
-    gcmSTACK_PUSH(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+    gcmSTACK_PUSH(__user_ptr__, __FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+    gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
     gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
                   "++%s(%d)", __FUNCTION__, __LINE__)
 #else
@@ -2836,13 +3515,20 @@ gcoOS_ProfileDB(
 #   define gcmHEADER                   __dummy_header
 #endif
 
-#if gcdHAS_ELLIPSES
+#ifdef gcdFSL_REL_BUILD
+#define gcmHEADER_ARG(Text, ...)
+#elif gcdHAS_ELLIPSIS
+#if gcdEMPTY_HEADER_FOOTER
+#   define gcmHEADER_ARG(Text, ...)
+#else
 #   define gcmHEADER_ARG(Text, ...) \
         gctINT8 __user__ = 1; \
         gctINT8_PTR __user_ptr__ = &__user__; \
-        gcmSTACK_PUSH(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
+        gcmSTACK_PUSH(__user_ptr__, __FUNCTION__, __LINE__, Text, __VA_ARGS__); \
+        gcmBINARY_TRACE(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
         gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
                       "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
+#endif
 #else
     gcmINLINE static void
     __dummy_header_arg(
@@ -2854,18 +3540,18 @@ gcoOS_ProfileDB(
 #   define gcmHEADER_ARG                __dummy_header_arg
 #endif
 
-#if gcdHAS_ELLIPSES
+#ifdef gcdFSL_REL_BUILD
+#   define gcmFOOTER()
+#elif gcdEMPTY_HEADER_FOOTER
+#   define gcmFOOTER()
+#elif gcdHAS_ELLIPSIS
 #   define gcmFOOTER() \
-    gcmSTACK_POP(__FUNCTION__); \
-    gcmPROFILE_ONLY(gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
-                                  "--%s(%d) [%llu,%llu]: status=%d(%s)", \
-                                  __FUNCTION__, __LINE__, \
-                                  __ticks__, __total__, \
-                                  status, gcoOS_DebugStatus2Name(status))); \
-    gcmPROFILE_ELSE(gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
-                                  "--%s(%d): status=%d(%s)", \
-                                  __FUNCTION__, __LINE__, \
-                                  status, gcoOS_DebugStatus2Name(status))); \
+    gcmSTACK_POP(__user_ptr__, __FUNCTION__); \
+    gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+    gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+                  "--%s(%d): status=%d(%s)", \
+                  __FUNCTION__, __LINE__, \
+                  status, gcoOS_DebugStatus2Name(status)); \
     *__user_ptr__ -= 1
 #else
     gcmINLINE static void
@@ -2875,9 +3561,14 @@ gcoOS_ProfileDB(
 #   define gcmFOOTER                    __dummy_footer
 #endif
 
-#if gcdHAS_ELLIPSES
+#ifdef gcdFSL_REL_BUILD
+#define gcmFOOTER_NO()
+#elif gcdEMPTY_HEADER_FOOTER
+#   define gcmFOOTER_NO()
+#elif gcdHAS_ELLIPSIS
 #define gcmFOOTER_NO() \
-    gcmSTACK_POP(__FUNCTION__); \
+    gcmSTACK_POP(__user_ptr__, __FUNCTION__); \
+    gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
     gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
                   "--%s(%d)", __FUNCTION__, __LINE__); \
     *__user_ptr__ -= 1
@@ -2889,9 +3580,14 @@ gcoOS_ProfileDB(
 #   define gcmFOOTER_NO                 __dummy_footer_no
 #endif
 
-#if gcdHAS_ELLIPSES
+#ifdef gcdFSL_REL_BUILD
+#define gcmFOOTER_KILL()
+#elif gcdEMPTY_HEADER_FOOTER
+#   define gcmFOOTER_KILL()
+#elif gcdHAS_ELLIPSIS
 #define gcmFOOTER_KILL() \
-    gcmSTACK_POP(__FUNCTION__); \
+    gcmSTACK_POP(__user_ptr__, __FUNCTION__); \
+    gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
     gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
                   "--%s(%d)", __FUNCTION__, __LINE__); \
     *__user_ptr__ -= 1
@@ -2903,12 +3599,19 @@ gcoOS_ProfileDB(
 #   define gcmFOOTER_KILL               __dummy_footer_kill
 #endif
 
-#if gcdHAS_ELLIPSES
+#ifdef gcdFSL_REL_BUILD
+#   define gcmFOOTER_ARG(Text, ...)
+#elif gcdHAS_ELLIPSIS
+#if gcdEMPTY_HEADER_FOOTER
+#   define gcmFOOTER_ARG(Text, ...)
+#else
 #   define gcmFOOTER_ARG(Text, ...) \
-        gcmSTACK_POP(__FUNCTION__); \
+        gcmSTACK_POP(__user_ptr__, __FUNCTION__); \
+        gcmBINARY_TRACE(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
         gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
                       "--%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__); \
         *__user_ptr__ -= 1
+#endif
 #else
     gcmINLINE static void
     __dummy_footer_arg(
@@ -2922,10 +3625,13 @@ gcoOS_ProfileDB(
 
 #endif /* gcdENABLE_PROFILING */
 
-#if gcdHAS_ELLIPSES
+#ifdef gcdFSL_REL_BUILD
+#define gcmkHEADER()
+#elif gcdHAS_ELLIPSIS
 #define gcmkHEADER() \
     gctINT8 __kernel__ = 1; \
     gctINT8_PTR __kernel_ptr__ = &__kernel__; \
+    gcmkBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
     gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
                    "++%s(%d)", __FUNCTION__, __LINE__)
 #else
@@ -2936,10 +3642,13 @@ gcoOS_ProfileDB(
 #   define gcmkHEADER                  __dummy_kheader
 #endif
 
-#if gcdHAS_ELLIPSES
+#ifdef gcdFSL_REL_BUILD
+#   define gcmkHEADER_ARG(Text, ...)
+#elif gcdHAS_ELLIPSIS
 #   define gcmkHEADER_ARG(Text, ...) \
         gctINT8 __kernel__ = 1; \
         gctINT8_PTR __kernel_ptr__ = &__kernel__; \
+        gcmkBINARY_TRACE(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
         gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
                        "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
 #else
@@ -2953,8 +3662,11 @@ gcoOS_ProfileDB(
 #   define gcmkHEADER_ARG               __dummy_kheader_arg
 #endif
 
-#if gcdHAS_ELLIPSES
+#ifdef gcdFSL_REL_BUILD
+#define gcmkFOOTER()
+#elif gcdHAS_ELLIPSIS
 #define gcmkFOOTER() \
+    gcmkBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, status); \
     gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
                    "--%s(%d): status=%d(%s)", \
                    __FUNCTION__, __LINE__, status, gckOS_DebugStatus2Name(status)); \
@@ -2967,8 +3679,11 @@ gcoOS_ProfileDB(
 #   define gcmkFOOTER                   __dummy_kfooter
 #endif
 
-#if gcdHAS_ELLIPSES
+#ifdef gcdFSL_REL_BUILD
+#define gcmkFOOTER_NO()
+#elif gcdHAS_ELLIPSIS
 #define gcmkFOOTER_NO() \
+    gcmkBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
     gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
                    "--%s(%d)", __FUNCTION__, __LINE__); \
     *__kernel_ptr__ -= 1
@@ -2980,8 +3695,11 @@ gcoOS_ProfileDB(
 #   define gcmkFOOTER_NO                __dummy_kfooter_no
 #endif
 
-#if gcdHAS_ELLIPSES
+#ifdef gcdFSL_REL_BUILD
+#   define gcmkFOOTER_ARG(Text, ...)
+#elif gcdHAS_ELLIPSIS
 #   define gcmkFOOTER_ARG(Text, ...) \
+        gcmkBINARY_TRACE(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
         gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
                        "--%s(%d): " Text, \
                        __FUNCTION__, __LINE__, __VA_ARGS__); \
@@ -3104,7 +3822,7 @@ gckOS_DebugFlush(
         void
     );
 #   define gcmDUMP_FRAMERATE        gcfDumpFrameRate
-#elif gcdHAS_ELLIPSES
+#elif gcdHAS_ELLIPSIS
 #   define gcmDUMP_FRAMERATE(...)
 #else
     gcmINLINE static void
@@ -3137,7 +3855,7 @@ gckOS_DebugFlush(
         ...
         );
 #  define gcmDUMP               gcfDump
-#elif gcdHAS_ELLIPSES
+#elif gcdHAS_ELLIPSIS
 #  define gcmDUMP(...)
 #else
     gcmINLINE static void
@@ -3178,7 +3896,7 @@ gckOS_DebugFlush(
         IN gctSIZE_T Bytes
         );
 #  define gcmDUMP_DATA          gcfDumpData
-#elif gcdHAS_ELLIPSES
+#elif gcdHAS_ELLIPSIS
 #  define gcmDUMP_DATA(...)
 #else
     gcmINLINE static void
@@ -3228,7 +3946,7 @@ gcfDumpBuffer(
     IN gctSIZE_T Bytes
     );
 #   define gcmDUMP_BUFFER       gcfDumpBuffer
-#elif gcdHAS_ELLIPSES
+#elif gcdHAS_ELLIPSIS
 #   define gcmDUMP_BUFFER(...)
 #else
     gcmINLINE static void
@@ -3260,7 +3978,7 @@ gcfDumpBuffer(
 gceSTATUS gcfDumpApi(IN gctCONST_STRING String, ...);
 #if gcdDUMP_API
 #   define gcmDUMP_API           gcfDumpApi
-#elif gcdHAS_ELLIPSES
+#elif gcdHAS_ELLIPSIS
 #   define gcmDUMP_API(...)
 #else
     gcmINLINE static void
@@ -3287,7 +4005,7 @@ gceSTATUS gcfDumpApi(IN gctCONST_STRING String, ...);
 gceSTATUS gcfDumpArray(IN gctCONST_POINTER Data, IN gctUINT32 Size);
 #if gcdDUMP_API
 #   define gcmDUMP_API_ARRAY        gcfDumpArray
-#elif gcdHAS_ELLIPSES
+#elif gcdHAS_ELLIPSIS
 #   define gcmDUMP_API_ARRAY(...)
 #else
     gcmINLINE static void
@@ -3314,7 +4032,7 @@ gceSTATUS gcfDumpArray(IN gctCONST_POINTER Data, IN gctUINT32 Size);
 gceSTATUS gcfDumpArrayToken(IN gctCONST_POINTER Data, IN gctUINT32 Termination);
 #if gcdDUMP_API
 #   define gcmDUMP_API_ARRAY_TOKEN  gcfDumpArrayToken
-#elif gcdHAS_ELLIPSES
+#elif gcdHAS_ELLIPSIS
 #   define gcmDUMP_API_ARRAY_TOKEN(...)
 #else
     gcmINLINE static void
@@ -3341,7 +4059,7 @@ gceSTATUS gcfDumpArrayToken(IN gctCONST_POINTER Data, IN gctUINT32 Termination);
 gceSTATUS gcfDumpApiData(IN gctCONST_POINTER Data, IN gctSIZE_T Size);
 #if gcdDUMP_API
 #   define gcmDUMP_API_DATA         gcfDumpApiData
-#elif gcdHAS_ELLIPSES
+#elif gcdHAS_ELLIPSIS
 #   define gcmDUMP_API_DATA(...)
 #else
     gcmINLINE static void
@@ -3354,6 +4072,115 @@ gceSTATUS gcfDumpApiData(IN gctCONST_POINTER Data, IN gctSIZE_T Size);
 #   define gcmDUMP_API_DATA         __dummy_dump_api_data
 #endif
 
+/*******************************************************************************
+** gcmDUMP_2D_COMMAND
+**
+**      Print the 2D command buffer.
+**
+**  ARGUMENTS:
+**
+**      gctUINT32_PTR       Pointer to the command buffer.
+**      gctUINT32           Command buffer size.
+*/
+gceSTATUS gcfDump2DCommand(IN gctUINT32_PTR Command, IN gctUINT32 Size);
+#if gcdDUMP_2D
+#   define gcmDUMP_2D_COMMAND       gcfDump2DCommand
+#elif gcdHAS_ELLIPSIS
+#   define gcmDUMP_2D_COMMAND(...)
+#else
+    gcmINLINE static void
+    __dummy_dump_2d_command(
+        IN gctUINT32_PTR Command,
+        IN gctUINT32 Size
+        )
+    {
+    }
+#   define gcmDUMP_2D_COMMAND       __dummy_dump_2d_command
+#endif
+
+/*******************************************************************************
+** gcmDUMP_2D_SURFACE
+**
+**      Print the 2D surface memory.
+**
+**  ARGUMENTS:
+**
+**      gctBOOL             Src.
+**      gctUINT32           Address.
+*/
+gceSTATUS gcfDump2DSurface(IN gctBOOL Src, IN gctUINT32 Address);
+#if gcdDUMP_2D
+#   define gcmDUMP_2D_SURFACE       gcfDump2DSurface
+#elif gcdHAS_ELLIPSIS
+#   define gcmDUMP_2D_SURFACE(...)
+#else
+    gcmINLINE static void
+    __dummy_dump_2d_surface(
+        IN gctBOOL Src,
+        IN gctUINT32 Address
+        )
+    {
+    }
+#   define gcmDUMP_2D_SURFACE       __dummy_dump_2d_surface
+#endif
+
+/*******************************************************************************
+** gcmDUMP_ADD_MEMORY_INFO
+**
+**      Record the memory info.
+**
+**  ARGUMENTS:
+**
+**      gctUINT32           Address.
+**      gctSIZE_T           Size.
+*/
+gceSTATUS gcfAddMemoryInfo(IN gctUINT32 GPUAddress, IN gctPOINTER Logical, IN gctUINT32 Physical, IN gctUINT32 Size);
+#if gcdDUMP_2D
+#   define gcmDUMP_ADD_MEMORY_INFO  gcfAddMemoryInfo
+#elif gcdHAS_ELLIPSIS
+#   define gcmDUMP_ADD_MEMORY_INFO(...)
+#else
+    gcmINLINE static void
+    __dummy_dump_add_memory_info(
+        IN gctUINT32 GPUAddress,
+        IN gctPOINTER Logical,
+        IN gctUINT32 Physical,
+        IN gctUINT32 Size
+        )
+    {
+    }
+#   define gcmDUMP_ADD_MEMORY_INFO  __dummy_dump_add_memory_info
+#endif
+
+/*******************************************************************************
+** gcmDUMP_DEL_MEMORY_INFO
+**
+**      Record the memory info.
+**
+**  ARGUMENTS:
+**
+**      gctUINT32           Address.
+*/
+gceSTATUS gcfDelMemoryInfo(IN gctUINT32 Address);
+#if gcdDUMP_2D
+#   define gcmDUMP_DEL_MEMORY_INFO  gcfDelMemoryInfo
+#elif gcdHAS_ELLIPSIS
+#   define gcmDUMP_DEL_MEMORY_INFO(...)
+#else
+    gcmINLINE static void
+    __dummy_dump_del_memory_info(
+        IN gctUINT32 Address
+        )
+    {
+    }
+#   define gcmDUMP_DEL_MEMORY_INFO  __dummy_dump_del_memory_info
+#endif
+
+#if gcdDUMP_2D
+extern gctPOINTER dumpMemInfoListMutex;
+extern gctBOOL    dump2DFlag;
+#endif
+
 /*******************************************************************************
 **
 **  gcmTRACE_RELEASE
@@ -3667,6 +4494,46 @@ gckOS_DebugStatus2Name(
 #define gcmONERROR(func)            _gcmONERROR(gcm, func)
 #define gcmkONERROR(func)           _gcmkONERROR(gcmk, func)
 
+/*******************************************************************************
+**
+**  gcmkSAFECASTSIZET
+**
+**      Check wether value of a gctSIZE_T varible beyond the capability
+**      of 32bits GPU hardware.
+**
+**  ASSUMPTIONS:
+**
+**
+**
+**  ARGUMENTS:
+**
+**      x   A gctUINT32 variable
+**      y   A gctSIZE_T variable
+*/
+#define gcmkSAFECASTSIZET(x, y) \
+    do \
+    { \
+        gctUINT32 tmp = (gctUINT32)(y); \
+        if (gcmSIZEOF(gctSIZE_T) > gcmSIZEOF(gctUINT32)) \
+        { \
+            gcmkASSERT(tmp <= gcvMAXUINT32); \
+            } \
+        (x) = tmp; \
+    } \
+    while (gcvFALSE)
+
+#define gcmSAFECASTSIZET(x, y) \
+    do \
+    { \
+        gctUINT32 tmp = (gctUINT32)(y); \
+        if (gcmSIZEOF(gctSIZE_T) > gcmSIZEOF(gctUINT32)) \
+        { \
+            gcmASSERT(tmp <= gcvMAXUINT32); \
+            } \
+        (x) = tmp; \
+    } \
+    while (gcvFALSE)
+
 /*******************************************************************************
 **
 **  gcmVERIFY_LOCK
@@ -3865,13 +4732,17 @@ gcGetUserDebugOption(
     void
     );
 
+#if defined(ANDROID)
 struct _gcoOS_SymbolsList
 {
+#if gcdENABLE_3D
     gcePATCH_ID patchId;
+#endif
     const char * symList[10];
 };
+#endif
 
-#if gcdHAS_ELLIPSES
+#if gcdHAS_ELLIPSIS
 #define gcmUSER_DEBUG_MSG(level, ...) \
     do \
     { \
@@ -3889,6 +4760,759 @@ struct _gcoOS_SymbolsList
 #define gcmUSER_DEBUG_WARNING_MSG
 #endif
 
+/*******************************************************************************
+**
+**  A set of macros to aid state loading.
+**
+**  ARGUMENTS:
+**
+**      CommandBuffer   Pointer to a gcoCMDBUF object.
+**      StateDelta      Pointer to a gcsSTATE_DELTA state delta structure.
+**      Memory          Destination memory pointer of gctUINT32_PTR type.
+**      PartOfContext   Whether or not the state is a part of the context.
+**      FixedPoint      Whether or not the state is of the fixed point format.
+**      Count           Number of consecutive states to be loaded.
+**      Address         State address.
+**      Data            Data to be set to the state.
+*/
+
+/*----------------------------------------------------------------------------*/
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+
+#   define gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count) \
+        CommandBuffer->lastLoadStatePtr     = gcmPTR_TO_UINT64(Memory); \
+        CommandBuffer->lastLoadStateAddress = Address; \
+        CommandBuffer->lastLoadStateCount   = Count
+
+#   define gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address) \
+        gcmASSERT( \
+            (gctUINT) (Memory  - gcmUINT64_TO_TYPE(CommandBuffer->lastLoadStatePtr, gctUINT32_PTR) - 1) \
+            == \
+            (gctUINT) (Address - CommandBuffer->lastLoadStateAddress) \
+            ); \
+        \
+        gcmASSERT(CommandBuffer->lastLoadStateCount > 0); \
+        \
+        CommandBuffer->lastLoadStateCount -= 1
+
+#   define gcmVERIFYLOADSTATEDONE(CommandBuffer) \
+        gcmASSERT(CommandBuffer->lastLoadStateCount == 0);
+
+#   define gcmDEFINELOADSTATEBASE() \
+        gctUINT32_PTR LoadStateBase;
+
+#   define gcmSETLOADSTATEBASE(CommandBuffer, OutSide) \
+        if (OutSide) \
+        {\
+            LoadStateBase = (gctUINT32_PTR)*OutSide; \
+        }\
+        else\
+        {\
+            LoadStateBase = (gctUINT_PTR)CommandBuffer->buffer;\
+        }
+
+
+#   define gcmVERIFYLOADSTATEALIGNED(CommandBuffer, Memory) \
+        gcmASSERT(((Memory - LoadStateBase) & 1) == 0);
+
+#   define gcmUNSETLOADSTATEBASE() \
+        LoadStateBase = LoadStateBase;
+
+#else
+
+#   define gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count)
+#   define gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address)
+#   define gcmVERIFYLOADSTATEDONE(CommandBuffer)
+
+#   define gcmDEFINELOADSTATEBASE()
+#   define gcmSETLOADSTATEBASE(CommandBuffer, OutSide)
+#   define gcmVERIFYLOADSTATEALIGNED(CommandBuffer, Memory)
+#   define gcmUNSETLOADSTATEBASE()
+
+#endif
+
+#if gcdSECURE_USER
+
+#   define gcmDEFINESECUREUSER() \
+        gctUINT         __secure_user_offset__; \
+        gctUINT32_PTR   __secure_user_hintArray__;
+
+#   define gcmBEGINSECUREUSER() \
+        __secure_user_offset__ = reserve->lastOffset; \
+        \
+        __secure_user_hintArray__ = gcmUINT64_TO_PTR(reserve->hintArrayTail)
+
+#   define gcmENDSECUREUSER() \
+        reserve->hintArrayTail = gcmPTR_TO_UINT64(__secure_user_hintArray__)
+
+#   define gcmSKIPSECUREUSER() \
+        __secure_user_offset__ += gcmSIZEOF(gctUINT32)
+
+#   define gcmUPDATESECUREUSER() \
+        *__secure_user_hintArray__ = __secure_user_offset__; \
+        \
+        __secure_user_offset__    += gcmSIZEOF(gctUINT32); \
+        __secure_user_hintArray__ += 1
+
+#else
+
+#   define gcmDEFINESECUREUSER()
+#   define gcmBEGINSECUREUSER()
+#   define gcmENDSECUREUSER()
+#   define gcmSKIPSECUREUSER()
+#   define gcmUPDATESECUREUSER()
+
+#endif
+
+/*----------------------------------------------------------------------------*/
+
+#if gcdDUMP
+#   define gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, Data) \
+        if (FixedPoint) \
+        { \
+            gcmDUMP(gcvNULL, "#[state.x 0x%04X 0x%08X]", \
+                Address, Data \
+                ); \
+        } \
+        else \
+        { \
+            gcmDUMP(gcvNULL, "#[state 0x%04X 0x%08X]", \
+                Address, Data \
+                ); \
+        }
+#else
+#   define gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, Data)
+#endif
+
+#define gcmDEFINESTATEBUFFER(CommandBuffer, StateDelta, Memory, ReserveSize) \
+    gcmDEFINESECUREUSER() \
+    gctSIZE_T ReserveSize; \
+    gcoCMDBUF CommandBuffer; \
+    gctUINT32_PTR Memory; \
+    gcsSTATE_DELTA_PTR StateDelta
+
+#define gcmBEGINSTATEBUFFER(Hardware, CommandBuffer, StateDelta, Memory, ReserveSize) \
+{ \
+    gcmONERROR(gcoBUFFER_Reserve( \
+        Hardware->buffer, ReserveSize, gcvTRUE, gcvCOMMAND_3D, &CommandBuffer \
+        )); \
+    \
+    Memory = (gctUINT32_PTR) gcmUINT64_TO_PTR(CommandBuffer->lastReserve); \
+    \
+    StateDelta = Hardware->delta; \
+    \
+    gcmBEGINSECUREUSER(); \
+}
+
+#define gcmENDSTATEBUFFER(Hardware, CommandBuffer, Memory, ReserveSize) \
+{ \
+    gcmENDSECUREUSER(); \
+    \
+    gcmASSERT( \
+        gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT8_PTR) + ReserveSize \
+        == \
+         (gctUINT8_PTR) Memory \
+        ); \
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, Count) \
+{ \
+    gcmASSERT(((Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT32_PTR)) & 1) == 0); \
+    gcmASSERT((gctUINT32)Count <= 1024); \
+    \
+    gcmVERIFYLOADSTATEDONE(CommandBuffer); \
+    \
+    gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count); \
+    \
+    *Memory++ \
+        = gcmSETFIELDVALUE(0, AQ_COMMAND_LOAD_STATE_COMMAND, OPCODE,  LOAD_STATE) \
+        | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, FLOAT,   FixedPoint) \
+        | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, COUNT,   Count) \
+        | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, ADDRESS, Address); \
+    \
+    gcmSKIPSECUREUSER(); \
+}
+
+#define gcmENDSTATEBATCH(CommandBuffer, Memory) \
+{ \
+    gcmVERIFYLOADSTATEDONE(CommandBuffer); \
+    \
+    gcmASSERT(((Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT32_PTR)) & 1) == 0); \
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmSETSTATEDATA(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                        Address, Data) \
+{ \
+    gctUINT32 __temp_data32__; \
+    \
+    gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
+    \
+    gcmSAFECASTSIZET(__temp_data32__, Data); \
+    \
+    *Memory++ = __temp_data32__; \
+    \
+    gcoHARDWARE_UpdateDelta( \
+        StateDelta, Address, 0, __temp_data32__ \
+        ); \
+    \
+    gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+    \
+    gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETSTATEDATAWITHMASK(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                        Address, Mask, Data) \
+{ \
+    gctUINT32 __temp_data32__; \
+    \
+    gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
+    \
+    __temp_data32__ = Data; \
+    \
+    *Memory++ = __temp_data32__; \
+    \
+    gcoHARDWARE_UpdateDelta( \
+        StateDelta, Address, Mask, __temp_data32__ \
+        ); \
+    \
+    gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+    \
+    gcmUPDATESECUREUSER(); \
+}
+
+
+#define gcmSETCTRLSTATE(StateDelta, CommandBuffer, Memory, Address, Data) \
+{ \
+    gctUINT32 __temp_data32__; \
+    \
+    gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
+    \
+    __temp_data32__ = Data; \
+    \
+    *Memory++ = __temp_data32__; \
+    \
+    gcmDUMPSTATEDATA(StateDelta, gcvFALSE, Address, __temp_data32__); \
+    \
+    gcmSKIPSECUREUSER(); \
+}
+
+#define gcmSETFILLER(CommandBuffer, Memory) \
+{ \
+    gcmVERIFYLOADSTATEDONE(CommandBuffer); \
+    \
+    Memory += 1; \
+    \
+    gcmSKIPSECUREUSER(); \
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmSETSINGLESTATE(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                          Address, Data) \
+{ \
+    gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
+    gcmSETSTATEDATA(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                    Address, Data); \
+    gcmENDSTATEBATCH(CommandBuffer, Memory); \
+}
+
+#define gcmSETSINGLESTATEWITHMASK(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                          Address, Mask, Data) \
+{ \
+    gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
+    gcmSETSTATEDATAWITHMASK(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                    Address, Mask, Data); \
+    gcmENDSTATEBATCH(CommandBuffer, Memory); \
+}
+
+
+#define gcmSETSINGLECTRLSTATE(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                              Address, Data) \
+{ \
+    gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
+    gcmSETCTRLSTATE(StateDelta, CommandBuffer, Memory, Address, Data); \
+    gcmENDSTATEBATCH(CommandBuffer, Memory); \
+}
+
+
+
+#define gcmSETSEMASTALLPIPE(StateDelta, CommandBuffer, Memory, Data) \
+{ \
+    gcmSETSINGLESTATE(StateDelta, CommandBuffer, Memory, gcvFALSE, AQSemaphoreRegAddrs, Data); \
+    \
+    *Memory++ = gcmSETFIELDVALUE(0, STALL_COMMAND, OPCODE, STALL); \
+    \
+    *Memory++ = Data; \
+    \
+    gcmDUMP(gcvNULL, "#[stall 0x%08X 0x%08X]", \
+        gcmSETFIELDVALUE(0, AQ_SEMAPHORE, SOURCE, FRONT_END), \
+        gcmSETFIELDVALUE(0, AQ_SEMAPHORE, DESTINATION, PIXEL_ENGINE)); \
+    \
+    gcmSKIPSECUREUSER(); \
+}
+
+/*******************************************************************************
+**
+**  gcmSETSTARTDECOMMAND
+**
+**      Form a START_DE command.
+**
+**  ARGUMENTS:
+**
+**      Memory          Destination memory pointer of gctUINT32_PTR type.
+**      Count           Number of the rectangles.
+*/
+
+#define gcmSETSTARTDECOMMAND(Memory, Count) \
+{ \
+    *Memory++ \
+        = gcmSETFIELDVALUE(0, AQ_COMMAND_START_DE_COMMAND, OPCODE,     START_DE) \
+        | gcmSETFIELD     (0, AQ_COMMAND_START_DE_COMMAND, COUNT,      Count) \
+        | gcmSETFIELD     (0, AQ_COMMAND_START_DE_COMMAND, DATA_COUNT, 0); \
+    \
+    *Memory++ = 0xDEADDEED; \
+}
+
+/*****************************************
+** Temp command buffer macro
+*/
+#define gcmDEFINESTATEBUFFER_NEW(CommandBuffer, StateDelta, Memory) \
+    gcmDEFINESECUREUSER() \
+    gcmDEFINELOADSTATEBASE() \
+    gcsTEMPCMDBUF CommandBuffer = gcvNULL; \
+    gctUINT32_PTR Memory; \
+    gcsSTATE_DELTA_PTR StateDelta
+
+
+#define gcmBEGINSTATEBUFFER_NEW(Hardware, CommandBuffer, StateDelta, Memory, OutSide) \
+{ \
+    if (OutSide) \
+    {\
+        Memory = (gctUINT32_PTR)*OutSide; \
+    }\
+    else \
+    {\
+        gcmONERROR(gcoBUFFER_StartTEMPCMDBUF( \
+            Hardware->buffer, &CommandBuffer \
+            ));\
+        \
+        Memory = (gctUINT32_PTR)(CommandBuffer->buffer); \
+        \
+    }\
+    StateDelta = Hardware->delta; \
+    \
+    gcmBEGINSECUREUSER(); \
+    gcmSETLOADSTATEBASE(CommandBuffer,OutSide);\
+}
+
+#define gcmENDSTATEBUFFER_NEW(Hardware, CommandBuffer, Memory, OutSide) \
+{ \
+    gcmENDSECUREUSER(); \
+    \
+    if (OutSide) \
+    {\
+        *OutSide = Memory; \
+    }\
+    else \
+    {\
+        CommandBuffer->currentByteSize = (gctUINT32)((gctUINT8_PTR)Memory -  \
+                                         (gctUINT8_PTR)CommandBuffer->buffer); \
+        \
+        gcmONERROR(gcoBUFFER_EndTEMPCMDBUF(Hardware->buffer));\
+    }\
+    gcmUNSETLOADSTATEBASE()\
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, Count) \
+{ \
+    gcmVERIFYLOADSTATEALIGNED(CommandBuffer,Memory);\
+    gcmASSERT((gctUINT32)Count <= 1024); \
+    \
+    *Memory++ \
+        = gcmSETFIELDVALUE(0, AQ_COMMAND_LOAD_STATE_COMMAND, OPCODE,  LOAD_STATE) \
+        | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, FLOAT,   FixedPoint) \
+        | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, COUNT,   Count) \
+        | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, ADDRESS, Address); \
+    \
+    gcmSKIPSECUREUSER(); \
+}
+
+#define gcmENDSTATEBATCH_NEW(CommandBuffer, Memory) \
+    gcmVERIFYLOADSTATEALIGNED(CommandBuffer,Memory);
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmSETSTATEDATA_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                        Address, Data) \
+{ \
+    gctUINT32 __temp_data32__; \
+    \
+    __temp_data32__ = Data; \
+    \
+    *Memory++ = __temp_data32__; \
+    \
+    gcoHARDWARE_UpdateDelta( \
+        StateDelta, Address, 0, __temp_data32__ \
+        ); \
+    \
+    gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+    \
+    gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETSTATEDATAWITHMASK_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                                Address, Mask, Data) \
+{ \
+    gctUINT32 __temp_data32__; \
+    \
+    __temp_data32__ = Data; \
+    \
+    *Memory++ = __temp_data32__; \
+    \
+    gcoHARDWARE_UpdateDelta( \
+        StateDelta, Address, Mask, __temp_data32__ \
+        ); \
+    \
+    gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+    \
+    gcmUPDATESECUREUSER(); \
+}
+
+
+#define gcmSETCTRLSTATE_NEW(StateDelta, CommandBuffer, Memory, Address, Data) \
+{ \
+    gctUINT32 __temp_data32__; \
+    \
+    __temp_data32__ = Data; \
+    \
+    *Memory++ = __temp_data32__; \
+    \
+    gcmDUMPSTATEDATA(StateDelta, gcvFALSE, Address, __temp_data32__); \
+    \
+    gcmSKIPSECUREUSER(); \
+}
+
+#define gcmSETFILLER_NEW(CommandBuffer, Memory) \
+{ \
+    Memory += 1; \
+    \
+    gcmSKIPSECUREUSER(); \
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmSETSINGLESTATE_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                              Address, Data) \
+{ \
+    gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
+    gcmSETSTATEDATA_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                    Address, Data); \
+    gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
+}
+
+#define gcmSETSINGLESTATEWITHMASK_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                                      Address, Mask, Data) \
+{ \
+    gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
+    gcmSETSTATEDATAWITHMASK_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                    Address, Mask, Data); \
+    gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
+}
+
+
+#define gcmSETSINGLECTRLSTATE_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                              Address, Data) \
+{ \
+    gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
+    gcmSETCTRLSTATE_NEW(StateDelta, CommandBuffer, Memory, Address, Data); \
+    gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
+}
+
+
+
+#define gcmSETSEMASTALLPIPE_NEW(StateDelta, CommandBuffer, Memory, Data) \
+{ \
+    gcmSETSINGLESTATE_NEW(StateDelta, CommandBuffer, Memory, gcvFALSE, AQSemaphoreRegAddrs, Data); \
+    \
+    *Memory++ = gcmSETFIELDVALUE(0, STALL_COMMAND, OPCODE, STALL); \
+    \
+    *Memory++ = Data; \
+    \
+    gcmDUMP(gcvNULL, "#[stall 0x%08X 0x%08X]", \
+        gcmSETFIELDVALUE(0, AQ_SEMAPHORE, SOURCE, FRONT_END), \
+        gcmSETFIELDVALUE(0, AQ_SEMAPHORE, DESTINATION, PIXEL_ENGINE)); \
+    \
+    gcmSKIPSECUREUSER(); \
+}
+
+#define gcmSETSTARTDECOMMAND_NEW(CommandBuffer, Memory, Count) \
+{ \
+    *Memory++ \
+        = gcmSETFIELDVALUE(0, AQ_COMMAND_START_DE_COMMAND, OPCODE,     START_DE) \
+        | gcmSETFIELD     (0, AQ_COMMAND_START_DE_COMMAND, COUNT,      Count) \
+        | gcmSETFIELD     (0, AQ_COMMAND_START_DE_COMMAND, DATA_COUNT, 0); \
+    \
+    *Memory++ = 0xDEADDEED; \
+    \
+}
+
+#define gcmSETSTATEDATA_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                        Address, Data) \
+{ \
+    gctUINT32 __temp_data32__; \
+    \
+    __temp_data32__ = Data; \
+    \
+    *Memory++ = __temp_data32__; \
+    \
+    gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+    \
+    gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETSTATEDATAWITHMASK_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                                Address, Mask, Data) \
+{ \
+    gctUINT32 __temp_data32__; \
+    \
+    __temp_data32__ = Data; \
+    \
+    *Memory++ = __temp_data32__; \
+    \
+    gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+    \
+    gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETSINGLESTATE_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                              Address, Data) \
+{ \
+    gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
+    gcmSETSTATEDATA_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                    Address, Data); \
+    gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
+}
+
+#define gcmSETSINGLESTATEWITHMASK_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                                      Address, Mask, Data) \
+{ \
+    gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
+    gcmSETSTATEDATAWITHMASK_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                    Address, Mask, Data); \
+    gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
+}
+
+#define gcmSETSTATEDATA_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                        Address, Data) \
+{ \
+    gctUINT32 __temp_data32__; \
+    \
+    gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
+    \
+    gcmSAFECASTSIZET(__temp_data32__, Data); \
+    \
+    *Memory++ = __temp_data32__; \
+    \
+    gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+    \
+    gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETSTATEDATAWITHMASK_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                        Address, Mask, Data) \
+{ \
+    gctUINT32 __temp_data32__; \
+    \
+    gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
+    \
+    __temp_data32__ = Data; \
+    \
+    *Memory++ = __temp_data32__; \
+    \
+    gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+    \
+    gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETSINGLESTATE_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                          Address, Data) \
+{ \
+    gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
+    gcmSETSTATEDATA_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                    Address, Data); \
+    gcmENDSTATEBATCH(CommandBuffer, Memory); \
+}
+
+#define gcmSETSINGLESTATEWITHMASK_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                          Address, Mask, Data) \
+{ \
+    gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
+    gcmSETSTATEDATAWITHMASK_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+                    Address, Mask, Data); \
+    gcmENDSTATEBATCH(CommandBuffer, Memory); \
+}
+
+#define gcmDEFINESTATEBUFFER_NEW_FAST(CommandBuffer, Memory) \
+    gcmDEFINESECUREUSER() \
+    gcmDEFINELOADSTATEBASE() \
+    gcsTEMPCMDBUF CommandBuffer = gcvNULL; \
+    gctUINT32_PTR Memory;
+
+#define gcmDEFINESTATEBUFFER_FAST(CommandBuffer, Memory, ReserveSize) \
+    gcmDEFINESECUREUSER() \
+    gctSIZE_T ReserveSize; \
+    gcoCMDBUF CommandBuffer; \
+    gctUINT32_PTR Memory;
+
+#define gcmBEGINSTATEBUFFER_FAST(Hardware, CommandBuffer, Memory, ReserveSize) \
+{ \
+    gcmONERROR(gcoBUFFER_Reserve( \
+        Hardware->buffer, ReserveSize, gcvTRUE, &CommandBuffer \
+        )); \
+    \
+    Memory = (gctUINT32_PTR) gcmUINT64_TO_PTR(CommandBuffer->lastReserve); \
+    \
+    gcmBEGINSECUREUSER(); \
+}
+
+#define gcmBEGINSTATEBUFFER_NEW_FAST(Hardware, CommandBuffer, Memory, OutSide) \
+{ \
+    if (OutSide) \
+    {\
+        Memory = (gctUINT32_PTR)*OutSide; \
+    }\
+    else \
+    {\
+        gcmONERROR(gcoBUFFER_StartTEMPCMDBUF( \
+            Hardware->buffer, &CommandBuffer \
+            ));\
+        \
+        Memory = (gctUINT32_PTR)(CommandBuffer->buffer); \
+        \
+    }\
+    \
+    gcmBEGINSECUREUSER(); \
+    gcmSETLOADSTATEBASE(CommandBuffer,OutSide);\
+}
+/*******************************************************************************
+**
+**  gcmCONFIGUREUNIFORMS
+**
+**      Configure uniforms according to chip and numConstants.
+*/
+#if !gcdENABLE_UNIFIED_CONSTANT
+#define gcmCONFIGUREUNIFORMS(ChipModel, ChipRevision, NumConstants, \
+             UnifiedConst, VsConstBase, PsConstBase, VsConstMax, PsConstMax, ConstMax) \
+{ \
+    if (ChipModel == gcv2000 && ChipRevision == 0x5118) \
+    { \
+        UnifiedConst = gcvFALSE; \
+        VsConstBase  = AQVertexShaderConstRegAddrs; \
+        PsConstBase  = AQPixelShaderConstRegAddrs; \
+        VsConstMax   = 256; \
+        PsConstMax   = 64; \
+        ConstMax     = 320; \
+    } \
+    else if (NumConstants == 320) \
+    { \
+        UnifiedConst = gcvFALSE; \
+        VsConstBase  = AQVertexShaderConstRegAddrs; \
+        PsConstBase  = AQPixelShaderConstRegAddrs; \
+        VsConstMax   = 256; \
+        PsConstMax   = 64; \
+        ConstMax     = 320; \
+    } \
+    /* All GC1000 series chips can only support 64 uniforms for ps on non-unified const mode. */ \
+    else if (NumConstants > 256 && ChipModel == gcv1000) \
+    { \
+        UnifiedConst = gcvFALSE; \
+        VsConstBase  = AQVertexShaderConstRegAddrs; \
+        PsConstBase  = AQPixelShaderConstRegAddrs; \
+        VsConstMax   = 256; \
+        PsConstMax   = 64; \
+        ConstMax     = 320; \
+    } \
+    else if (NumConstants > 256) \
+    { \
+        UnifiedConst = gcvFALSE; \
+        VsConstBase  = AQVertexShaderConstRegAddrs; \
+        PsConstBase  = AQPixelShaderConstRegAddrs; \
+        VsConstMax   = 256; \
+        PsConstMax   = 256; \
+        ConstMax     = 512; \
+    } \
+    else if (NumConstants == 256) \
+    { \
+        UnifiedConst = gcvFALSE; \
+        VsConstBase  = AQVertexShaderConstRegAddrs; \
+        PsConstBase  = AQPixelShaderConstRegAddrs; \
+        VsConstMax   = 256; \
+        PsConstMax   = 256; \
+        ConstMax     = 512; \
+    } \
+    else \
+    { \
+        UnifiedConst = gcvFALSE; \
+        VsConstBase  = AQVertexShaderConstRegAddrs; \
+        PsConstBase  = AQPixelShaderConstRegAddrs; \
+        VsConstMax   = 168; \
+        PsConstMax   = 64; \
+        ConstMax     = 232; \
+    } \
+}
+#else
+#define gcmCONFIGUREUNIFORMS(ChipModel, ChipRevision, NumConstants, \
+             UnifiedConst, VsConstBase, PsConstBase, VsConstMax, PsConstMax, ConstMax) \
+{ \
+    if (NumConstants > 256) \
+    { \
+        UnifiedConst = gcvTRUE; \
+        VsConstBase  = gcregSHUniformsRegAddrs; \
+        PsConstBase  = gcregSHUniformsRegAddrs; \
+        ConstMax     = NumConstants; \
+        VsConstMax   = 256; \
+        PsConstMax   = ConstMax - VsConstMax; \
+    } \
+    else if (NumConstants == 256) \
+    { \
+        if (ChipModel == gcv2000 && ChipRevision == 0x5118) \
+        { \
+            UnifiedConst = gcvFALSE; \
+            VsConstBase  = AQVertexShaderConstRegAddrs; \
+            PsConstBase  = AQPixelShaderConstRegAddrs; \
+            VsConstMax   = 256; \
+            PsConstMax   = 64; \
+            ConstMax     = 320; \
+        } \
+        else \
+        { \
+            UnifiedConst = gcvFALSE; \
+            VsConstBase  = AQVertexShaderConstRegAddrs; \
+            PsConstBase  = AQPixelShaderConstRegAddrs; \
+            VsConstMax   = 256; \
+            PsConstMax   = 256; \
+            ConstMax     = 512; \
+        } \
+    } \
+    else \
+    { \
+        UnifiedConst = gcvFALSE; \
+        VsConstBase  = AQVertexShaderConstRegAddrs; \
+        PsConstBase  = AQPixelShaderConstRegAddrs; \
+        VsConstMax   = 168; \
+        PsConstMax   = 64; \
+        ConstMax     = 232; \
+    } \
+}
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h
deleted file mode 100644 (file)
index f841370..0000000
+++ /dev/null
@@ -1,4298 +0,0 @@
-/****************************************************************************
-*
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
-*
-*    This program is free software; you can redistribute it and/or modify
-*    it under the terms of the GNU General Public License as published by
-*    the Free Software Foundation; either version 2 of the license, or
-*    (at your option) any later version.
-*
-*    This program is distributed in the hope that it will be useful,
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-*    GNU General Public License for more details.
-*
-*    You should have received a copy of the GNU General Public License
-*    along with this program; if not write to the Free Software
-*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*
-*****************************************************************************/
-
-/*
-**     Include file the defines the front- and back-end compilers, as well as the
-**     objects they use.
-*/
-
-#ifndef __gc_hal_compiler_h_
-#define __gc_hal_compiler_h_
-
-#ifndef VIVANTE_NO_3D
-#include "gc_hal_types.h"
-#include "gc_hal_engine.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef GC_ENABLE_LOADTIME_OPT
-#define GC_ENABLE_LOADTIME_OPT           1
-#endif
-
-#define TEMP_OPT_CONSTANT_TEXLD_COORD    0
-
-#define TEMP_SHADER_PATCH                1
-
-#define TEMP_INLINE_ALL_EXPANSION            1
-/******************************* IR VERSION ******************/
-#define gcdSL_IR_VERSION gcmCC('\0','\0','\0','\1')
-
-/******************************************************************************\
-|******************************* SHADER LANGUAGE ******************************|
-\******************************************************************************/
-
-    /* allocator/deallocator function pointer */
-typedef gceSTATUS (*gctAllocatorFunc)(
-    IN gctSIZE_T Bytes,
-    OUT gctPOINTER * Memory
-    );
-
-typedef gceSTATUS (*gctDeallocatorFunc)(
-    IN gctPOINTER Memory
-    );
-
-typedef gctBOOL (*compareFunc) (
-     IN void *    data,
-     IN void *    key
-     );
-
-typedef struct _gcsListNode gcsListNode;
-struct _gcsListNode
-{
-    gcsListNode *       next;
-    void *              data;
-};
-
-typedef struct _gcsAllocator
-{
-    gctAllocatorFunc    allocate;
-    gctDeallocatorFunc  deallocate;
-} gcsAllocator;
-
-/* simple map structure */
-typedef struct _SimpleMap SimpleMap;
-struct _SimpleMap
-{
-    gctUINT32     key;
-    gctUINT32     val;
-    SimpleMap    *next;
-    gcsAllocator *allocator;
-
-};
-
-/* SimpleMap Operations */
-/* return -1 if not found, otherwise return the mapped value */
-gctUINT32
-gcSimpleMap_Find(
-     IN SimpleMap *Map,
-     IN gctUINT32    Key
-     );
-
-gceSTATUS
-gcSimpleMap_Destory(
-     IN SimpleMap *    Map,
-     IN gcsAllocator * Allocator
-     );
-
-/* Add a pair <Key, Val> to the Map head, the user should be aware that the
- * map pointer is always changed when adding a new node :
- *
- *   gcSimpleMap_AddNode(&theMap, key, val, allocator);
- *
- */
-gceSTATUS
-gcSimpleMap_AddNode(
-     IN SimpleMap **   Map,
-     IN gctUINT32      Key,
-     IN gctUINT32      Val,
-     IN gcsAllocator * Allocator
-     );
-
-/* gcsList data structure and related operations */
-typedef struct _gcsList
-{
-    gcsListNode  *head;
-    gcsListNode  *tail;
-    gctINT        count;
-    gcsAllocator *allocator;
-} gcsList;
-
-/* List operations */
-void
-gcList_Init(
-    IN gcsList *list,
-    IN gcsAllocator *allocator
-    );
-
-gceSTATUS
-gcList_CreateNode(
-    IN void *             Data,
-    IN gctAllocatorFunc   Allocator,
-    OUT gcsListNode **    ListNode
-    );
-
-gceSTATUS
-gcList_Clean(
-    IN gcsList *          List,
-    IN gctBOOL            FreeData
-    );
-
-gcsListNode *
-gcList_FindNode(
-    IN gcsList *      List,
-    IN void *         Key,
-    IN compareFunc    compare
-    );
-
-gceSTATUS
-gcList_AddNode(
-    IN gcsList *          List,
-    IN void *             Data
-    );
-
-gceSTATUS
-gcList_RemoveNode(
-    IN gcsList *          List,
-    IN gcsListNode *      Node
-    );
-
-/*  link list structure for code list */
-typedef gcsList gcsCodeList;
-typedef gcsCodeList * gctCodeList;
-typedef gcsListNode gcsCodeListNode;
-
-/* Possible shader language opcodes. */
-typedef enum _gcSL_OPCODE
-{
-       gcSL_NOP,                                                       /* 0x00 */
-       gcSL_MOV,                                                       /* 0x01 */
-       gcSL_SAT,                                                       /* 0x02 */
-       gcSL_DP3,                                                       /* 0x03 */
-       gcSL_DP4,                                                       /* 0x04 */
-       gcSL_ABS,                                                       /* 0x05 */
-       gcSL_JMP,                                                       /* 0x06 */
-       gcSL_ADD,                                                       /* 0x07 */
-       gcSL_MUL,                                                       /* 0x08 */
-       gcSL_RCP,                                                       /* 0x09 */
-       gcSL_SUB,                                                       /* 0x0A */
-       gcSL_KILL,                                                      /* 0x0B */
-       gcSL_TEXLD,                                                     /* 0x0C */
-       gcSL_CALL,                                                      /* 0x0D */
-       gcSL_RET,                                                       /* 0x0E */
-       gcSL_NORM,                                                      /* 0x0F */
-       gcSL_MAX,                                                       /* 0x10 */
-       gcSL_MIN,                                                       /* 0x11 */
-       gcSL_POW,                                                       /* 0x12 */
-       gcSL_RSQ,                                                       /* 0x13 */
-       gcSL_LOG,                                                       /* 0x14 */
-       gcSL_FRAC,                                                      /* 0x15 */
-       gcSL_FLOOR,                                                     /* 0x16 */
-       gcSL_CEIL,                                                      /* 0x17 */
-       gcSL_CROSS,                                                     /* 0x18 */
-       gcSL_TEXLDP,                                            /* 0x19 */
-       gcSL_TEXBIAS,                                           /* 0x1A */
-       gcSL_TEXGRAD,                                           /* 0x1B */
-       gcSL_TEXLOD,                                            /* 0x1C */
-       gcSL_SIN,                                                       /* 0x1D */
-       gcSL_COS,                                                       /* 0x1E */
-       gcSL_TAN,                                                       /* 0x1F */
-       gcSL_EXP,                                                       /* 0x20 */
-       gcSL_SIGN,                                                      /* 0x21 */
-       gcSL_STEP,                                                      /* 0x22 */
-       gcSL_SQRT,                                                      /* 0x23 */
-       gcSL_ACOS,                                                      /* 0x24 */
-       gcSL_ASIN,                                                      /* 0x25 */
-       gcSL_ATAN,                                                      /* 0x26 */
-       gcSL_SET,                                                       /* 0x27 */
-       gcSL_DSX,                                                       /* 0x28 */
-       gcSL_DSY,                                                       /* 0x29 */
-       gcSL_FWIDTH,                                            /* 0x2A */
-       gcSL_DIV,                                               /* 0x2B */
-       gcSL_MOD,                                               /* 0x2C */
-       gcSL_AND_BITWISE,                                       /* 0x2D */
-       gcSL_OR_BITWISE,                                        /* 0x2E */
-       gcSL_XOR_BITWISE,                                       /* 0x2F */
-       gcSL_NOT_BITWISE,                                       /* 0x30 */
-       gcSL_LSHIFT,                                            /* 0x31 */
-       gcSL_RSHIFT,                                            /* 0x32 */
-       gcSL_ROTATE,                                            /* 0x33 */
-       gcSL_BITSEL,                                            /* 0x34 */
-       gcSL_LEADZERO,                                          /* 0x35 */
-       gcSL_LOAD,                                                      /* 0x36 */
-       gcSL_STORE,                                                     /* 0x37 */
-       gcSL_BARRIER,                                           /* 0x38 */
-       gcSL_STORE1,                                            /* 0x39 */
-       gcSL_ATOMADD,                                           /* 0x3A */
-       gcSL_ATOMSUB,                                           /* 0x3B */
-       gcSL_ATOMXCHG,                                          /* 0x3C */
-       gcSL_ATOMCMPXCHG,                                       /* 0x3D */
-       gcSL_ATOMMIN,                                           /* 0x3E */
-       gcSL_ATOMMAX,                                           /* 0x3F */
-       gcSL_ATOMOR,                                            /* 0x40 */
-       gcSL_ATOMAND,                                           /* 0x41 */
-       gcSL_ATOMXOR,                                           /* 0x42 */
-       /*gcSL_UNUSED,                                           0x43 */
-       /*gcSL_UNUSED,                                           0x44 */
-       /*gcSL_UNUSED,                                           0x45 */
-       /*gcSL_UNUSED,                                           0x46 */
-       /*gcSL_UNUSED,                                           0x47 */
-       /*gcSL_UNUSED,                                           0x48 */
-       /*gcSL_UNUSED,                                           0x49 */
-       /*gcSL_UNUSED,                                           0x4A */
-       /*gcSL_UNUSED,                                           0x4B */
-       /*gcSL_UNUSED,                                           0x4C */
-       /*gcSL_UNUSED,                                           0x4D */
-       /*gcSL_UNUSED,                                           0x4E */
-       /*gcSL_UNUSED,                                           0x4F */
-       /*gcSL_UNUSED,                                           0x50 */
-       /*gcSL_UNUSED,                                           0x51 */
-       /*gcSL_UNUSED,                                           0x52 */
-       gcSL_ADDLO = 0x53,                                      /* 0x53 */  /* Float only. */
-       gcSL_MULLO,                                                     /* 0x54 */  /* Float only. */
-       gcSL_CONV,                                                      /* 0x55 */
-       gcSL_GETEXP,                                            /* 0x56 */
-       gcSL_GETMANT,                                           /* 0x57 */
-       gcSL_MULHI,                                                     /* 0x58 */  /* Integer only. */
-       gcSL_CMP,                                                       /* 0x59 */
-       gcSL_I2F,                                                       /* 0x5A */
-       gcSL_F2I,                                                       /* 0x5B */
-       gcSL_ADDSAT,                                            /* 0x5C */  /* Integer only. */
-       gcSL_SUBSAT,                                            /* 0x5D */  /* Integer only. */
-       gcSL_MULSAT,                                            /* 0x5E */  /* Integer only. */
-       gcSL_DP2,                                                       /* 0x5F */
-       gcSL_MAXOPCODE
-}
-gcSL_OPCODE;
-
-typedef enum _gcSL_FORMAT
-{
-       gcSL_FLOAT = 0,                                         /* 0 */
-       gcSL_INTEGER = 1,                                   /* 1 */
-       gcSL_INT32 = 1,                                     /* 1 */
-       gcSL_BOOLEAN = 2,                                       /* 2 */
-       gcSL_UINT32 = 3,                                        /* 3 */
-       gcSL_INT8,                                                  /* 4 */
-       gcSL_UINT8,                                                 /* 5 */
-       gcSL_INT16,                                                 /* 6 */
-       gcSL_UINT16,                                            /* 7 */
-       gcSL_INT64,                                                 /* 8 */     /* Reserved for future enhancement. */
-       gcSL_UINT64,                                            /* 9 */     /* Reserved for future enhancement. */
-       gcSL_INT128,                                        /* 10 */    /* Reserved for future enhancement. */
-       gcSL_UINT128,                                           /* 11 */    /* Reserved for future enhancement. */
-       gcSL_FLOAT16,                                       /* 12 */
-       gcSL_FLOAT64,                                           /* 13 */    /* Reserved for future enhancement. */
-       gcSL_FLOAT128,                                          /* 14 */    /* Reserved for future enhancement. */
-}
-gcSL_FORMAT;
-
-/* Destination write enable bits. */
-typedef enum _gcSL_ENABLE
-{
-    gcSL_ENABLE_NONE                    = 0x0,     /* none is enabled, error/uninitialized state */
-       gcSL_ENABLE_X                                           = 0x1,
-       gcSL_ENABLE_Y                                           = 0x2,
-       gcSL_ENABLE_Z                                           = 0x4,
-       gcSL_ENABLE_W                                           = 0x8,
-       /* Combinations. */
-       gcSL_ENABLE_XY                                          = gcSL_ENABLE_X | gcSL_ENABLE_Y,
-       gcSL_ENABLE_XYZ                                         = gcSL_ENABLE_X | gcSL_ENABLE_Y | gcSL_ENABLE_Z,
-       gcSL_ENABLE_XYZW                                        = gcSL_ENABLE_X | gcSL_ENABLE_Y | gcSL_ENABLE_Z | gcSL_ENABLE_W,
-       gcSL_ENABLE_XYW                                         = gcSL_ENABLE_X | gcSL_ENABLE_Y | gcSL_ENABLE_W,
-       gcSL_ENABLE_XZ                                          = gcSL_ENABLE_X | gcSL_ENABLE_Z,
-       gcSL_ENABLE_XZW                                         = gcSL_ENABLE_X | gcSL_ENABLE_Z | gcSL_ENABLE_W,
-       gcSL_ENABLE_XW                                          = gcSL_ENABLE_X | gcSL_ENABLE_W,
-       gcSL_ENABLE_YZ                                          = gcSL_ENABLE_Y | gcSL_ENABLE_Z,
-       gcSL_ENABLE_YZW                                         = gcSL_ENABLE_Y | gcSL_ENABLE_Z | gcSL_ENABLE_W,
-       gcSL_ENABLE_YW                                          = gcSL_ENABLE_Y | gcSL_ENABLE_W,
-       gcSL_ENABLE_ZW                                          = gcSL_ENABLE_Z | gcSL_ENABLE_W,
-}
-gcSL_ENABLE;
-
-/* Possible indices. */
-typedef enum _gcSL_INDEXED
-{
-       gcSL_NOT_INDEXED,                                       /* 0 */
-       gcSL_INDEXED_X,                                         /* 1 */
-       gcSL_INDEXED_Y,                                         /* 2 */
-       gcSL_INDEXED_Z,                                         /* 3 */
-       gcSL_INDEXED_W,                                         /* 4 */
-}
-gcSL_INDEXED;
-
-/* Opcode conditions. */
-typedef enum _gcSL_CONDITION
-{
-       gcSL_ALWAYS,                                            /* 0x0 */
-       gcSL_NOT_EQUAL,                                         /* 0x1 */
-       gcSL_LESS_OR_EQUAL,                                     /* 0x2 */
-       gcSL_LESS,                                                      /* 0x3 */
-       gcSL_EQUAL,                                                     /* 0x4 */
-       gcSL_GREATER,                                           /* 0x5 */
-       gcSL_GREATER_OR_EQUAL,                          /* 0x6 */
-       gcSL_AND,                                                       /* 0x7 */
-       gcSL_OR,                                                        /* 0x8 */
-       gcSL_XOR,                                                       /* 0x9 */
-    gcSL_NOT_ZERO,                      /* 0xA */
-}
-gcSL_CONDITION;
-
-/* Possible source operand types. */
-typedef enum _gcSL_TYPE
-{
-       gcSL_NONE,                                                      /* 0x0 */
-       gcSL_TEMP,                                                      /* 0x1 */
-       gcSL_ATTRIBUTE,                                         /* 0x2 */
-       gcSL_UNIFORM,                                           /* 0x3 */
-       gcSL_SAMPLER,                                           /* 0x4 */
-       gcSL_CONSTANT,                                          /* 0x5 */
-       gcSL_OUTPUT,                                            /* 0x6 */
-       gcSL_PHYSICAL,                                          /* 0x7 */
-}
-gcSL_TYPE;
-
-/* Swizzle generator macro. */
-#define gcmSWIZZLE(Component1, Component2, Component3, Component4) \
-( \
-       (gcSL_SWIZZLE_ ## Component1 << 0) | \
-       (gcSL_SWIZZLE_ ## Component2 << 2) | \
-       (gcSL_SWIZZLE_ ## Component3 << 4) | \
-       (gcSL_SWIZZLE_ ## Component4 << 6)   \
-)
-
-#define gcmExtractSwizzle(Swizzle, Index) \
-    ((gcSL_SWIZZLE) ((((Swizzle) >> (Index * 2)) & 0x3)))
-
-#define gcmComposeSwizzle(SwizzleX, SwizzleY, SwizzleZ, SwizzleW) \
-( \
-       ((SwizzleX) << 0) | \
-       ((SwizzleY) << 2) | \
-       ((SwizzleZ) << 4) | \
-       ((SwizzleW) << 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_YYZZ = gcmSWIZZLE(Y, Y, Z, Z),
-       gcSL_SWIZZLE_YYWW = gcmSWIZZLE(Y, Y, W, W),
-       gcSL_SWIZZLE_ZZZW = gcmSWIZZLE(Z, Z, Z, W),
-       gcSL_SWIZZLE_XZZW = gcmSWIZZLE(X, Z, Z, W),
-       gcSL_SWIZZLE_YYZW = gcmSWIZZLE(Y, Y, Z, W),
-
-    gcSL_SWIZZLE_INVALID = 0x7FFFFFFF
-}
-gcSL_SWIZZLE;
-
-typedef enum _gcSL_COMPONENT
-{
-       gcSL_COMPONENT_X,               /* 0x0 */
-       gcSL_COMPONENT_Y,               /* 0x1 */
-       gcSL_COMPONENT_Z,               /* 0x2 */
-       gcSL_COMPONENT_W,               /* 0x3 */
-    gcSL_COMPONENT_COUNT            /* 0x4 */
-} gcSL_COMPONENT;
-
-#define gcmIsComponentEnabled(Enable, Component) (((Enable) & (1 << (Component))) != 0)
-
-/******************************************************************************\
-|*********************************** SHADERS **********************************|
-\******************************************************************************/
-
-/* Shader types. */
-typedef enum _gcSHADER_KIND {
-    gcSHADER_TYPE_UNKNOWN = 0,
-    gcSHADER_TYPE_VERTEX,
-    gcSHADER_TYPE_FRAGMENT,
-    gcSHADER_TYPE_CL,
-    gcSHADER_TYPE_PRECOMPILED,
-    gcSHADER_KIND_COUNT
-} gcSHADER_KIND;
-
-typedef enum _gcGL_DRIVER_VERSION {
-    gcGL_DRIVER_ES11,    /* OpenGL ES 1.1 */
-    gcGL_DRIVER_ES20,    /* OpenGL ES 2.0 */
-    gcGL_DRIVER_ES30     /* OpenGL ES 3.0 */
-} gcGL_DRIVER_VERSION;
-
-/* gcSHADER objects. */
-typedef struct _gcSHADER *              gcSHADER;
-typedef struct _gcATTRIBUTE *                  gcATTRIBUTE;
-typedef struct _gcUNIFORM *             gcUNIFORM;
-typedef struct _gcOUTPUT *              gcOUTPUT;
-typedef struct _gcsFUNCTION *                  gcFUNCTION;
-typedef struct _gcsKERNEL_FUNCTION *   gcKERNEL_FUNCTION;
-typedef struct _gcsHINT *               gcsHINT_PTR;
-typedef struct _gcSHADER_PROFILER *     gcSHADER_PROFILER;
-typedef struct _gcVARIABLE *                   gcVARIABLE;
-
-struct _gcsHINT
-{
-    /* Numbr of data transfers for Vertex Shader output. */
-    gctUINT32   vsOutputCount;
-
-    /* Flag whether the VS has point size or not. */
-    gctBOOL     vsHasPointSize;
-
-#if gcdUSE_WCLIP_PATCH
-    /* Flag whether the VS gl_position.z depends on gl_position.w
-       it's a hint for wclipping */
-    gctBOOL     vsPositionZDependsOnW;
-#endif
-
-    gctBOOL     clipW;
-
-    /* Flag whether or not the shader has a KILL instruction. */
-    gctBOOL     hasKill;
-
-    /* Element count. */
-    gctUINT32   elementCount;
-
-    /* Component count. */
-    gctUINT32   componentCount;
-
-    /* Number of data transfers for Fragment Shader input. */
-    gctUINT32   fsInputCount;
-
-    /* Maximum number of temporary registers used in FS. */
-    gctUINT32   fsMaxTemp;
-
-       /* Maximum number of temporary registers used in VS. */
-       gctUINT32   vsMaxTemp;
-
-    /* Balance minimum. */
-    gctUINT32   balanceMin;
-
-    /* Balance maximum. */
-    gctUINT32   balanceMax;
-
-    /* Auto-shift balancing. */
-    gctBOOL     autoShift;
-
-    /* Flag whether the PS outputs the depth value or not. */
-    gctBOOL     psHasFragDepthOut;
-
-       /* Flag whether the ThreadWalker is in PS. */
-       gctBOOL         threadWalkerInPS;
-
-    /* HW reg number for position of VS */
-    gctUINT32   hwRegNoOfSIVPos;
-
-#if gcdALPHA_KILL_IN_SHADER
-    /* States to set when alpha kill is enabled. */
-    gctUINT32   killStateAddress;
-    gctUINT32   alphaKillStateValue;
-    gctUINT32   colorKillStateValue;
-
-    /* Shader instructiuon. */
-    gctUINT32   killInstructionAddress;
-    gctUINT32   alphaKillInstruction[3];
-    gctUINT32   colorKillInstruction[3];
-#endif
-
-#if TEMP_SHADER_PATCH
-       gctUINT32       pachedShaderIdentifier;
-#endif
-};
-
-#if TEMP_SHADER_PATCH
-#define INVALID_SHADER_IDENTIFIER 0xFFFFFFFF
-#endif
-
-/* gcSHADER_TYPE enumeration. */
-typedef enum _gcSHADER_TYPE
-{
-    gcSHADER_FLOAT_X1   = 0,        /* 0x00 */
-    gcSHADER_FLOAT_X2,                         /* 0x01 */
-       gcSHADER_FLOAT_X3,                              /* 0x02 */
-       gcSHADER_FLOAT_X4,                              /* 0x03 */
-       gcSHADER_FLOAT_2X2,                             /* 0x04 */
-       gcSHADER_FLOAT_3X3,                             /* 0x05 */
-       gcSHADER_FLOAT_4X4,                             /* 0x06 */
-       gcSHADER_BOOLEAN_X1,                    /* 0x07 */
-       gcSHADER_BOOLEAN_X2,                    /* 0x08 */
-       gcSHADER_BOOLEAN_X3,                    /* 0x09 */
-       gcSHADER_BOOLEAN_X4,                    /* 0x0A */
-       gcSHADER_INTEGER_X1,                    /* 0x0B */
-       gcSHADER_INTEGER_X2,                    /* 0x0C */
-       gcSHADER_INTEGER_X3,                    /* 0x0D */
-       gcSHADER_INTEGER_X4,                    /* 0x0E */
-       gcSHADER_SAMPLER_1D,                    /* 0x0F */
-       gcSHADER_SAMPLER_2D,                    /* 0x10 */
-       gcSHADER_SAMPLER_3D,                    /* 0x11 */
-       gcSHADER_SAMPLER_CUBIC,                 /* 0x12 */
-       gcSHADER_FIXED_X1,                              /* 0x13 */
-       gcSHADER_FIXED_X2,                              /* 0x14 */
-       gcSHADER_FIXED_X3,                              /* 0x15 */
-       gcSHADER_FIXED_X4,                              /* 0x16 */
-       gcSHADER_IMAGE_2D,                              /* 0x17 */  /* For OCL. */
-       gcSHADER_IMAGE_3D,                              /* 0x18 */  /* For OCL. */
-       gcSHADER_SAMPLER,                               /* 0x19 */  /* For OCL. */
-       gcSHADER_FLOAT_2X3,                             /* 0x1A */
-       gcSHADER_FLOAT_2X4,                             /* 0x1B */
-       gcSHADER_FLOAT_3X2,                             /* 0x1C */
-       gcSHADER_FLOAT_3X4,                             /* 0x1D */
-       gcSHADER_FLOAT_4X2,                             /* 0x1E */
-       gcSHADER_FLOAT_4X3,                             /* 0x1F */
-       gcSHADER_ISAMPLER_2D,                   /* 0x20 */
-       gcSHADER_ISAMPLER_3D,                   /* 0x21 */
-       gcSHADER_ISAMPLER_CUBIC,                /* 0x22 */
-       gcSHADER_USAMPLER_2D,                   /* 0x23 */
-       gcSHADER_USAMPLER_3D,                   /* 0x24 */
-       gcSHADER_USAMPLER_CUBIC,                /* 0x25 */
-       gcSHADER_SAMPLER_EXTERNAL_OES,          /* 0x26 */
-
-       gcSHADER_UINT_X1,                       /* 0x27 */
-       gcSHADER_UINT_X2,                       /* 0x28 */
-       gcSHADER_UINT_X3,                       /* 0x29 */
-       gcSHADER_UINT_X4,                       /* 0x2A */
-
-    gcSHADER_UNKONWN_TYPE,      /* do not add type after this */
-    gcSHADER_TYPE_COUNT         /* must to change gcvShaderTypeInfo at the
-                                 * same time if you add any new type! */}
-gcSHADER_TYPE;
-
-typedef enum _gcSHADER_TYPE_KIND
-{
-    gceTK_UNKOWN,
-    gceTK_FLOAT,
-    gceTK_INT,
-    gceTK_UINT,
-    gceTK_BOOL,
-    gceTK_FIXED,
-    gceTK_SAMPLER,
-    gceTK_IMAGE,
-    gceTK_OTHER
-} gcSHADER_TYPE_KIND;
-
-typedef struct _gcSHADER_TYPEINFO
-{
-    gcSHADER_TYPE      type;              /* e.g. gcSHADER_FLOAT_2X4 */
-    gctINT             components;        /* e.g. 4 components       */
-    gctINT             rows;              /* e.g. 2 rows             */
-    gcSHADER_TYPE      componentType;     /* e.g. gcSHADER_FLOAT_X4  */
-    gcSHADER_TYPE_KIND kind;              /* e.g. gceTK_FLOAT */
-    gctCONST_STRING    name;              /* e.g. "FLOAT_2X4" */
-} gcSHADER_TYPEINFO;
-
-extern gcSHADER_TYPEINFO gcvShaderTypeInfo[];
-
-#define gcmType_Comonents(Type)    (gcvShaderTypeInfo[Type].components)
-#define gcmType_Rows(Type)         (gcvShaderTypeInfo[Type].rows)
-#define gcmType_ComonentType(Type) (gcvShaderTypeInfo[Type].componentType)
-#define gcmType_Kind(Type)         (gcvShaderTypeInfo[Type].kind)
-#define gcmType_Name(Type)         (gcvShaderTypeInfo[Type].name)
-
-#define gcmType_isMatrix(type) (gcmType_Rows(type) > 1)
-
-typedef enum _gcSHADER_VAR_CATEGORY
-{
-    gcSHADER_VAR_CATEGORY_NORMAL  =  0, /* primitive type and its array */
-    gcSHADER_VAR_CATEGORY_STRUCT  =  1  /* structure */
-}
-gcSHADER_VAR_CATEGORY;
-
-typedef enum _gceTYPE_QUALIFIER
-{
-    gcvTYPE_QUALIFIER_NONE         = 0x0, /* unqualified */
-    gcvTYPE_QUALIFIER_VOLATILE     = 0x1, /* volatile */
-}gceTYPE_QUALIFIER;
-
-typedef gctUINT16  gctTYPE_QUALIFIER;
-
-#if GC_ENABLE_LOADTIME_OPT
-typedef struct _gcSHADER_TYPE_INFO
-{
-    gcSHADER_TYPE    type;        /* eg. gcSHADER_FLOAT_2X3 is the type */
-    gctCONST_STRING  name;        /* the name of the type: "gcSHADER_FLOAT_2X3" */
-    gcSHADER_TYPE    baseType;    /* its base type is gcSHADER_FLOAT_2 */
-    gctINT           components;  /* it has 2 components */
-    gctINT           rows;        /* and 3 rows */
-    gctINT           size;        /* the size in byte */
-} gcSHADER_TYPE_INFO;
-
-extern gcSHADER_TYPE_INFO shader_type_info[];
-
-enum gceLTCDumpOption {
-    gceLTC_DUMP_UNIFORM      = 0x0001,
-    gceLTC_DUMP_EVALUATION   = 0x0002,
-    gceLTC_DUMP_EXPESSION    = 0x0004,
-    gceLTC_DUMP_COLLECTING   = 0x0008,
-};
-
-gctBOOL gcDumpOption(gctINT Opt);
-
-#endif /* GC_ENABLE_LOADTIME_OPT */
-
-#define IS_MATRIX_TYPE(type) \
-    (((type >= gcSHADER_FLOAT_2X2) && (type <= gcSHADER_FLOAT_4X4)) || \
-     ((type >= gcSHADER_FLOAT_2X3) && (type <= gcSHADER_FLOAT_4X3)))
-
-/* gcSHADER_PRECISION enumeration. */
-typedef enum _gcSHADER_PRECISION
-{
-       gcSHADER_PRECISION_DEFAULT,                             /* 0x00 */
-       gcSHADER_PRECISION_HIGH,                                /* 0x01 */
-       gcSHADER_PRECISION_MEDIUM,                              /* 0x02 */
-       gcSHADER_PRECISION_LOW,                             /* 0x03 */
-}
-gcSHADER_PRECISION;
-
-/* Shader flags. */
-typedef enum _gceSHADER_FLAGS
-{
-    gcvSHADER_NO_OPTIMIZATION           = 0x00,
-       gcvSHADER_DEAD_CODE                                     = 0x01,
-       gcvSHADER_RESOURCE_USAGE                        = 0x02,
-       gcvSHADER_OPTIMIZER                                     = 0x04,
-       gcvSHADER_USE_GL_Z                                      = 0x08,
-    /*
-        The GC family of GPU cores model GC860 and under require the Z
-        to be from 0 <= z <= w.
-        However, OpenGL specifies the Z to be from -w <= z <= w.  So we
-        have to a conversion here:
-
-            z = (z + w) / 2.
-
-        So here we append two instructions to the vertex shader.
-    */
-       gcvSHADER_USE_GL_POSITION                       = 0x10,
-       gcvSHADER_USE_GL_FACE                           = 0x20,
-       gcvSHADER_USE_GL_POINT_COORD            = 0x40,
-       gcvSHADER_LOADTIME_OPTIMIZER            = 0x80,
-#if gcdALPHA_KILL_IN_SHADER
-    gcvSHADER_USE_ALPHA_KILL            = 0x100,
-#endif
-
-#if gcdPRE_ROTATION && (ANDROID_SDK_VERSION >= 14)
-    gcvSHADER_VS_PRE_ROTATION           = 0x200,
-#endif
-
-#if TEMP_INLINE_ALL_EXPANSION
-    gcvSHADER_INLINE_ALL_EXPANSION      = 0x400,
-#endif
-}
-gceSHADER_FLAGS;
-
-gceSTATUS
-gcSHADER_CheckClipW(
-    IN gctCONST_STRING VertexSource,
-    IN gctCONST_STRING FragmentSource,
-    OUT gctBOOL * clipW);
-
-/*******************************************************************************
-**  gcSHADER_GetUniformVectorCount
-**
-**  Get the number of vectors used by uniforms for this shader.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**  OUTPUT:
-**
-**      gctSIZE_T * Count
-**          Pointer to a variable receiving the number of vectors.
-*/
-gceSTATUS
-gcSHADER_GetUniformVectorCount(
-    IN gcSHADER Shader,
-    OUT gctSIZE_T * Count
-    );
-
-/*******************************************************************************
-**                                                     gcOptimizer Data Structures
-*******************************************************************************/
-typedef enum _gceSHADER_OPTIMIZATION
-{
-    /*  No optimization. */
-       gcvOPTIMIZATION_NONE,
-
-    /*  Flow graph construction. */
-       gcvOPTIMIZATION_CONSTRUCTION                = 1 << 0,
-
-    /*  Dead code elimination. */
-       gcvOPTIMIZATION_DEAD_CODE                   = 1 << 1,
-
-    /*  Redundant move instruction elimination. */
-       gcvOPTIMIZATION_REDUNDANT_MOVE              = 1 << 2,
-
-    /*  Inline expansion. */
-       gcvOPTIMIZATION_INLINE_EXPANSION            = 1 << 3,
-
-    /*  Constant propagation. */
-       gcvOPTIMIZATION_CONSTANT_PROPAGATION        = 1 << 4,
-
-    /*  Redundant bounds/checking elimination. */
-       gcvOPTIMIZATION_REDUNDANT_CHECKING          = 1 << 5,
-
-    /*  Loop invariant movement. */
-       gcvOPTIMIZATION_LOOP_INVARIANT              = 1 << 6,
-
-    /*  Induction variable removal. */
-       gcvOPTIMIZATION_INDUCTION_VARIABLE          = 1 << 7,
-
-    /*  Common subexpression elimination. */
-       gcvOPTIMIZATION_COMMON_SUBEXPRESSION        = 1 << 8,
-
-    /*  Control flow/banch optimization. */
-       gcvOPTIMIZATION_CONTROL_FLOW                = 1 << 9,
-
-    /*  Vector component operation merge. */
-       gcvOPTIMIZATION_VECTOR_INSTRUCTION_MERGE    = 1 << 10,
-
-    /*  Algebra simplificaton. */
-       gcvOPTIMIZATION_ALGEBRAIC_SIMPLIFICATION    = 1 << 11,
-
-    /*  Pattern matching and replacing. */
-       gcvOPTIMIZATION_PATTERN_MATCHING            = 1 << 12,
-
-    /*  Interprocedural constant propagation. */
-       gcvOPTIMIZATION_IP_CONSTANT_PROPAGATION     = 1 << 13,
-
-    /*  Interprecedural register optimization. */
-       gcvOPTIMIZATION_IP_REGISTRATION             = 1 << 14,
-
-    /*  Optimization option number. */
-       gcvOPTIMIZATION_OPTION_NUMBER               = 1 << 15,
-
-       /*  Loadtime constant. */
-    gcvOPTIMIZATION_LOADTIME_CONSTANT           = 1 << 16,
-
-    /*  MAD instruction optimization. */
-       gcvOPTIMIZATION_MAD_INSTRUCTION             = 1 << 17,
-
-    /*  Special optimization for LOAD SW workaround. */
-       gcvOPTIMIZATION_LOAD_SW_WORKAROUND          = 1 << 18,
-
-    /* move code into conditional block if possile */
-       gcvOPTIMIZATION_CONDITIONALIZE              = 1 << 19,
-
-    /* expriemental: power optimization mode
-        1. add extra dummy texld to tune performance
-        2. insert NOP after high power instrucitons
-        3. split high power vec3/vec4 instruciton to vec2/vec1 operation
-        4. ...
-     */
-       gcvOPTIMIZATION_POWER_OPTIMIZATION           = 1 << 20,
-
-    /* optimize varying packing */
-    gcvOPTIMIZATION_VARYINGPACKING              = 1 << 22,
-
-#if TEMP_INLINE_ALL_EXPANSION
-       gcvOPTIMIZATION_INLINE_ALL_EXPANSION        = 1 << 23,
-#endif
-
-    /*  Full optimization. */
-    /*  Note that gcvOPTIMIZATION_LOAD_SW_WORKAROUND is off. */
-       gcvOPTIMIZATION_FULL                        = 0x7FFFFFFF &
-                                                  ~gcvOPTIMIZATION_LOAD_SW_WORKAROUND &
-                                                  ~gcvOPTIMIZATION_INLINE_ALL_EXPANSION &
-                                                  ~gcvOPTIMIZATION_POWER_OPTIMIZATION,
-
-       /* Optimization Unit Test flag. */
-    gcvOPTIMIZATION_UNIT_TEST                   = 1 << 31
-}
-gceSHADER_OPTIMIZATION;
-
-typedef enum _gceOPTIMIZATION_VaryingPaking
-{
-    gcvOPTIMIZATION_VARYINGPACKING_NONE = 0,
-    gcvOPTIMIZATION_VARYINGPACKING_NOSPLIT,
-    gcvOPTIMIZATION_VARYINGPACKING_SPLIT
-} gceOPTIMIZATION_VaryingPaking;
-
-typedef struct _gcOPTIMIZER_OPTION
-{
-    gceSHADER_OPTIMIZATION     optFlags;
-
-    /* debug & dump options:
-
-         VC_OPTION=-DUMP:SRC:OPT|:OPTV|:CG|:CGV:|ALL|ALLV
-
-         SRC:  dump shader source code
-         OPT:  dump incoming and final IR
-         OPTV: dump result IR in each optimization phase
-         CG:   dump generated machine code
-         CGV:  dump BE tree and optimization detail
-
-         ALL = SRC|OPT|CG
-         ALLV = SRC|OPT|OPTV|CG|CGV
-     */
-    gctBOOL     dumpShaderSource;      /* dump shader source code */
-    gctBOOL     dumpOptimizer;         /* dump incoming and final IR */
-    gctBOOL     dumpOptimizerVerbose;  /* dump result IR in each optimization phase */
-    gctBOOL     dumpBEGenertedCode;    /* dump generated machine code */
-    gctBOOL     dumpBEVerbose;         /* dump BE tree and optimization detail */
-    gctBOOL     dumpBEFinalIR;         /* dump BE final IR */
-
-    /* Code generation */
-
-    /* Varying Packing:
-
-          VC_OPTION=-PACKVARYING:[0-2]|:T[-]m[,n]|:LshaderIdx,min,max
-
-          0: turn off varying packing
-          1: pack varyings, donot split any varying
-          2: pack varyings, may split to make fully packed output
-
-          Tm:    only packing shader pair which vertex shader id is m
-          Tm,n:  only packing shader pair which vertex shader id
-                   is in range of [m, n]
-          T-m:   do not packing shader pair which vertex shader id is m
-          T-m,n: do not packing shader pair which vertex shader id
-                   is in range of [m, n]
-
-          LshaderIdx,min,max : set  load balance (min, max) for shaderIdx
-                               if shaderIdx is -1, all shaders are impacted
-                               newMin = origMin * (min/100.);
-                               newMax = origMax * (max/100.);
-     */
-    gceOPTIMIZATION_VaryingPaking    packVarying;
-    gctINT                           _triageStart;
-    gctINT                           _triageEnd;
-    gctINT                           _loadBalanceShaderIdx;
-    gctINT                           _loadBalanceMin;
-    gctINT                           _loadBalanceMax;
-
-    /* Do not generate immdeiate
-
-          VC_OPTION=-NOIMM
-
-       Force generate immediate even the machine model don't support it,
-       for testing purpose only
-
-          VC_OPTION=-FORCEIMM
-     */
-    gctBOOL     noImmediate;
-    gctBOOL     forceImmediate;
-
-    /* Power reduction mode options */
-    gctBOOL   needPowerOptimization;
-
-    /* Patch TEXLD instruction by adding dummy texld
-       (can be used to tune GPU power usage):
-         for every TEXLD we seen, add n dummy TEXLD
-
-        it can be enabled by environment variable:
-
-          VC_OPTION=-PATCH_TEXLD:M:N
-
-        (for each M texld, add N dummy texld)
-     */
-    gctINT      patchEveryTEXLDs;
-    gctINT      patchDummyTEXLDs;
-
-    /* Insert NOP after high power consumption instructions
-
-         VC_OPTION="-INSERTNOP:MUL:MULLO:DP3:DP4:SEENTEXLD"
-     */
-    gctBOOL     insertNOP;
-    gctBOOL     insertNOPAfterMUL;
-    gctBOOL     insertNOPAfterMULLO;
-    gctBOOL     insertNOPAfterDP3;
-    gctBOOL     insertNOPAfterDP4;
-    gctBOOL     insertNOPOnlyWhenTexldSeen;
-
-    /* split MAD to MUL and ADD:
-
-         VC_OPTION=-SPLITMAD
-     */
-    gctBOOL     splitMAD;
-
-    /* Convert vect3/vec4 operations to multiple vec2/vec1 operations
-
-         VC_OPTION=-SPLITVEC:MUL:MULLO:DP3:DP4
-     */
-    gctBOOL     splitVec;
-    gctBOOL     splitVec4MUL;
-    gctBOOL     splitVec4MULLO;
-    gctBOOL     splitVec4DP3;
-    gctBOOL     splitVec4DP4;
-
-    /* turn/off features:
-
-          VC_OPTION=-F:n,[0|1]
-          Note: n must be decimal number
-     */
-    gctUINT     featureBits;
-
-    /* inline level (default 2 at O1):
-
-          VC_OPTION=-INLINELEVEL:[0-3]
-             0:  no inline
-             1:  only inline the function only called once or small function
-             2:  inline functions be called less than 5 times or medium size function
-             3:  inline everything possible
-     */
-    gctUINT     inlineLevel;
-} gcOPTIMIZER_OPTION;
-
-extern gcOPTIMIZER_OPTION theOptimizerOption;
-#define gcmGetOptimizerOption() gcGetOptimizerOption()
-
-#define gcmOPT_DUMP_SHADER_SRC()         \
-             (gcmGetOptimizerOption()->dumpShaderSource != 0)
-#define gcmOPT_DUMP_OPTIMIZER()          \
-             (gcmGetOptimizerOption()->dumpOptimizer != 0 || \
-              gcmOPT_DUMP_OPTIMIZER_VERBOSE() )
-#define gcmOPT_DUMP_OPTIMIZER_VERBOSE()  \
-             (gcmGetOptimizerOption()->dumpOptimizerVerbose != 0)
-#define gcmOPT_DUMP_CODEGEN()            \
-             (gcmGetOptimizerOption()->dumpBEGenertedCode != 0 || \
-              gcmOPT_DUMP_CODEGEN_VERBOSE() )
-#define gcmOPT_DUMP_CODEGEN_VERBOSE()    \
-             (gcmGetOptimizerOption()->dumpBEVerbose != 0)
-#define gcmOPT_DUMP_FINAL_IR()    \
-             (gcmGetOptimizerOption()->dumpBEFinalIR != 0)
-
-#define gcmOPT_SET_DUMP_SHADER_SRC(v)   \
-             gcmGetOptimizerOption()->dumpShaderSource = (v)
-
-#define gcmOPT_PATCH_TEXLD()  (gcmGetOptimizerOption()->patchDummyTEXLDs != 0)
-#define gcmOPT_INSERT_NOP()   (gcmGetOptimizerOption()->insertNOP == gcvTRUE)
-#define gcmOPT_SPLITMAD()     (gcmGetOptimizerOption()->splitMAD == gcvTRUE)
-#define gcmOPT_SPLITVEC()     (gcmGetOptimizerOption()->splitVec == gcvTRUE)
-
-#define gcmOPT_NOIMMEDIATE()  (gcmGetOptimizerOption()->noImmediate == gcvTRUE)
-#define gcmOPT_FORCEIMMEDIATE()  (gcmGetOptimizerOption()->forceImmediate == gcvTRUE)
-
-#define gcmOPT_PACKVARYING()     (gcmGetOptimizerOption()->packVarying)
-#define gcmOPT_PACKVARYING_triageStart()   (gcmGetOptimizerOption()->_triageStart)
-#define gcmOPT_PACKVARYING_triageEnd()     (gcmGetOptimizerOption()->_triageEnd)
-
-#define gcmOPT_INLINELEVEL()     (gcmGetOptimizerOption()->inlineLevel)
-
-/* Setters */
-#define gcmOPT_SetPatchTexld(m,n) (gcmGetOptimizerOption()->patchEveryTEXLDs = (m),\
-                                   gcmGetOptimizerOption()->patchDummyTEXLDs = (n))
-#define gcmOPT_SetSplitVecMUL() (gcmGetOptimizerOption()->splitVec = gcvTRUE, \
-                                 gcmGetOptimizerOption()->splitVec4MUL = gcvTRUE)
-#define gcmOPT_SetSplitVecMULLO() (gcmGetOptimizerOption()->splitVec = gcvTRUE, \
-                                  gcmGetOptimizerOption()->splitVec4MULLO = gcvTRUE)
-#define gcmOPT_SetSplitVecDP3() (gcmGetOptimizerOption()->splitVec = gcvTRUE, \
-                                 gcmGetOptimizerOption()->splitVec4DP3 = gcvTRUE)
-#define gcmOPT_SetSplitVecDP4() (gcmGetOptimizerOption()->splitVec = gcvTRUE, \
-                                 gcmGetOptimizerOption()->splitVec4DP4 = gcvTRUE)
-
-#define gcmOPT_SetPackVarying(v)     (gcmGetOptimizerOption()->packVarying = v)
-
-#define FB_LIVERANGE_FIX1     0x0001
-
-
-#define PredefinedDummySamplerId       8
-
-/* Function argument qualifier */
-typedef enum _gceINPUT_OUTPUT
-{
-       gcvFUNCTION_INPUT,
-       gcvFUNCTION_OUTPUT,
-       gcvFUNCTION_INOUT
-}
-gceINPUT_OUTPUT;
-
-/* Kernel function property flags. */
-typedef enum _gcePROPERTY_FLAGS
-{
-       gcvPROPERTY_REQD_WORK_GRP_SIZE  = 0x01
-}
-gceKERNEL_FUNCTION_PROPERTY_FLAGS;
-
-/* Uniform flags. */
-typedef enum _gceUNIFORM_FLAGS
-{
-       gcvUNIFORM_KERNEL_ARG                   = 0x01,
-       gcvUNIFORM_KERNEL_ARG_LOCAL             = 0x02,
-       gcvUNIFORM_KERNEL_ARG_SAMPLER           = 0x04,
-       gcvUNIFORM_LOCAL_ADDRESS_SPACE          = 0x08,
-       gcvUNIFORM_PRIVATE_ADDRESS_SPACE        = 0x10,
-       gcvUNIFORM_CONSTANT_ADDRESS_SPACE       = 0x20,
-       gcvUNIFORM_GLOBAL_SIZE                  = 0x40,
-       gcvUNIFORM_LOCAL_SIZE                   = 0x80,
-       gcvUNIFORM_NUM_GROUPS                   = 0x100,
-       gcvUNIFORM_GLOBAL_OFFSET                = 0x200,
-       gcvUNIFORM_WORK_DIM                     = 0x400,
-       gcvUNIFORM_KERNEL_ARG_CONSTANT          = 0x800,
-       gcvUNIFORM_KERNEL_ARG_LOCAL_MEM_SIZE    = 0x1000,
-       gcvUNIFORM_KERNEL_ARG_PRIVATE           = 0x2000,
-       gcvUNIFORM_LOADTIME_CONSTANT            = 0x4000,
-    gcvUNIFORM_IS_ARRAY                 = 0x8000,
-}
-gceUNIFORM_FLAGS;
-
-#define gcdUNIFORM_KERNEL_ARG_MASK  (gcvUNIFORM_KERNEL_ARG         | \
-                                     gcvUNIFORM_KERNEL_ARG_LOCAL   | \
-                                                                        gcvUNIFORM_KERNEL_ARG_SAMPLER | \
-                                                                        gcvUNIFORM_KERNEL_ARG_PRIVATE | \
-                                                                        gcvUNIFORM_KERNEL_ARG_CONSTANT)
-
-typedef enum _gceVARIABLE_UPDATE_FLAGS
-{
-    gcvVARIABLE_UPDATE_NOUPDATE = 0,
-    gcvVARIABLE_UPDATE_TEMPREG,
-    gcvVARIABLE_UPDATE_TYPE_QUALIFIER,
-}gceVARIABLE_UPDATE_FLAGS;
-
-typedef struct _gcMACHINE_INST
-{
-    gctUINT        state0;
-    gctUINT        state1;
-    gctUINT        state2;
-    gctUINT        state3;
-}gcMACHINE_INST, *gcMACHINE_INST_PTR;
-
-typedef struct _gcMACHINECODE
-{
-    gcMACHINE_INST_PTR   pCode;          /* machine code  */
-    gctUINT              instCount;      /* 128-bit count */
-    gctUINT              maxConstRegNo;
-    gctUINT              maxTempRegNo;
-    gctUINT              endPCOfMainRoutine;
-}gcMACHINECODE, *gcMACHINECODE_PTR;
-
-typedef enum NP2_ADDRESS_MODE
-{
-    NP2_ADDRESS_MODE_CLAMP  = 0,
-    NP2_ADDRESS_MODE_REPEAT = 1,
-    NP2_ADDRESS_MODE_MIRROR = 2
-}NP2_ADDRESS_MODE;
-
-typedef struct _gcNPOT_PATCH_PARAM
-{
-    gctINT               samplerSlot;
-    NP2_ADDRESS_MODE     addressMode[3];
-    gctINT               texDimension;    /* 2 or 3 */
-}gcNPOT_PATCH_PARAM, *gcNPOT_PATCH_PARAM_PTR;
-
-typedef struct _gcZBIAS_PATCH_PARAM
-{
-    /* Driver uses this to program uniform that designating zbias */
-    gctINT               uniformAddr;
-    gctINT               channel;
-}gcZBIAS_PATCH_PARAM, *gcZBIAS_PATCH_PARAM_PTR;
-
-void
-gcGetOptionFromEnv(
-    IN OUT gcOPTIMIZER_OPTION * Option
-    );
-
-void
-gcSetOptimizerOption(
-    IN gceSHADER_FLAGS Flags
-    );
-
-gcOPTIMIZER_OPTION *
-gcGetOptimizerOption();
-
-/*******************************************************************************
-**  gcSHADER_SetCompilerVersion
-**
-**  Set the compiler version of a gcSHADER object.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to gcSHADER object
-**
-**      gctINT *Version
-**          Pointer to a two word version
-*/
-gceSTATUS
-gcSHADER_SetCompilerVersion(
-    IN gcSHADER Shader,
-    IN gctUINT32 *Version
-    );
-
-/*******************************************************************************
-**  gcSHADER_GetCompilerVersion
-**
-**  Get the compiler version of a gcSHADER object.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**  OUTPUT:
-**
-**      gctUINT32_PTR *CompilerVersion.
-**          Pointer to holder of returned compilerVersion pointer
-*/
-gceSTATUS
-gcSHADER_GetCompilerVersion(
-    IN gcSHADER Shader,
-    OUT gctUINT32_PTR *CompilerVersion
-    );
-
-/*******************************************************************************
-**  gcSHADER_GetType
-**
-**  Get the gcSHADER object's type.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**  OUTPUT:
-**
-**      gctINT *Type.
-**          Pointer to return shader type.
-*/
-gceSTATUS
-gcSHADER_GetType(
-    IN gcSHADER Shader,
-    OUT gctINT *Type
-    );
-
-gctUINT
-gcSHADER_NextId();
-/*******************************************************************************
-**                             gcSHADER_Construct
-********************************************************************************
-**
-**     Construct a new gcSHADER object.
-**
-**     INPUT:
-**
-**             gcoOS Hal
-**                     Pointer to an gcoHAL object.
-**
-**             gctINT ShaderType
-**                     Type of gcSHADER object to cerate.  'ShaderType' can be one of the
-**                     following:
-**
-**                             gcSHADER_TYPE_VERTEX    Vertex shader.
-**                             gcSHADER_TYPE_FRAGMENT  Fragment shader.
-**
-**     OUTPUT:
-**
-**             gcSHADER * Shader
-**                     Pointer to a variable receiving the gcSHADER object pointer.
-*/
-gceSTATUS
-gcSHADER_Construct(
-       IN gcoHAL Hal,
-       IN gctINT ShaderType,
-       OUT gcSHADER * Shader
-       );
-
-/*******************************************************************************
-**                              gcSHADER_Destroy
-********************************************************************************
-**
-**     Destroy a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_Destroy(
-       IN gcSHADER Shader
-       );
-
-/*******************************************************************************
-**                              gcSHADER_Copy
-********************************************************************************
-**
-**     Copy a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**      gcSHADER Source
-**          Pointer to a gcSHADER object that will be copied.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_Copy(
-       IN gcSHADER Shader,
-       IN gcSHADER Source
-       );
-
-/*******************************************************************************
-**  gcSHADER_LoadHeader
-**
-**  Load a gcSHADER object from a binary buffer.  The binary buffer is layed out
-**  as follows:
-**      // Six word header
-**      // Signature, must be 'S','H','D','R'.
-**      gctINT8             signature[4];
-**      gctUINT32           binFileVersion;
-**      gctUINT32           compilerVersion[2];
-**      gctUINT32           gcSLVersion;
-**      gctUINT32           binarySize;
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**          Shader type will be returned if type in shader object is not gcSHADER_TYPE_PRECOMPILED
-**
-**      gctPOINTER Buffer
-**          Pointer to a binary buffer containing the shader data to load.
-**
-**      gctSIZE_T BufferSize
-**          Number of bytes inside the binary buffer pointed to by 'Buffer'.
-**
-**  OUTPUT:
-**      nothing
-**
-*/
-gceSTATUS
-gcSHADER_LoadHeader(
-    IN gcSHADER Shader,
-    IN gctPOINTER Buffer,
-    IN gctSIZE_T BufferSize,
-    OUT gctUINT32 * ShaderVersion
-    );
-
-/*******************************************************************************
-**  gcSHADER_LoadKernel
-**
-**  Load a kernel function given by name into gcSHADER object
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gctSTRING KernelName
-**          Pointer to a kernel function name
-**
-**  OUTPUT:
-**      nothing
-**
-*/
-gceSTATUS
-gcSHADER_LoadKernel(
-    IN gcSHADER Shader,
-    IN gctSTRING KernelName
-    );
-
-/*******************************************************************************
-**                                gcSHADER_Load
-********************************************************************************
-**
-**     Load a gcSHADER object from a binary buffer.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctPOINTER Buffer
-**                     Pointer to a binary buffer containg the shader data to load.
-**
-**             gctSIZE_T BufferSize
-**                     Number of bytes inside the binary buffer pointed to by 'Buffer'.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_Load(
-       IN gcSHADER Shader,
-       IN gctPOINTER Buffer,
-       IN gctSIZE_T BufferSize
-       );
-
-/*******************************************************************************
-**                                gcSHADER_Save
-********************************************************************************
-**
-**     Save a gcSHADER object to a binary buffer.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctPOINTER Buffer
-**                     Pointer to a binary buffer to be used as storage for the gcSHADER
-**                     object.  If 'Buffer' is gcvNULL, the gcSHADER object will not be saved,
-**                     but the number of bytes required to hold the binary output for the
-**                     gcSHADER object will be returned.
-**
-**             gctSIZE_T * BufferSize
-**                     Pointer to a variable holding the number of bytes allocated in
-**                     'Buffer'.  Only valid if 'Buffer' is not gcvNULL.
-**
-**     OUTPUT:
-**
-**             gctSIZE_T * BufferSize
-**                     Pointer to a variable receiving the number of bytes required to hold
-**                     the binary form of the gcSHADER object.
-*/
-gceSTATUS
-gcSHADER_Save(
-       IN gcSHADER Shader,
-       IN gctPOINTER Buffer,
-       IN OUT gctSIZE_T * BufferSize
-       );
-
-/*******************************************************************************
-**                                gcSHADER_LoadEx
-********************************************************************************
-**
-**     Load a gcSHADER object from a binary buffer.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctPOINTER Buffer
-**                     Pointer to a binary buffer containg the shader data to load.
-**
-**             gctSIZE_T BufferSize
-**                     Number of bytes inside the binary buffer pointed to by 'Buffer'.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_LoadEx(
-       IN gcSHADER Shader,
-       IN gctPOINTER Buffer,
-       IN gctSIZE_T BufferSize
-       );
-
-/*******************************************************************************
-**                                gcSHADER_SaveEx
-********************************************************************************
-**
-**     Save a gcSHADER object to a binary buffer.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctPOINTER Buffer
-**                     Pointer to a binary buffer to be used as storage for the gcSHADER
-**                     object.  If 'Buffer' is gcvNULL, the gcSHADER object will not be saved,
-**                     but the number of bytes required to hold the binary output for the
-**                     gcSHADER object will be returned.
-**
-**             gctSIZE_T * BufferSize
-**                     Pointer to a variable holding the number of bytes allocated in
-**                     'Buffer'.  Only valid if 'Buffer' is not gcvNULL.
-**
-**     OUTPUT:
-**
-**             gctSIZE_T * BufferSize
-**                     Pointer to a variable receiving the number of bytes required to hold
-**                     the binary form of the gcSHADER object.
-*/
-gceSTATUS
-gcSHADER_SaveEx(
-       IN gcSHADER Shader,
-       IN gctPOINTER Buffer,
-       IN OUT gctSIZE_T * BufferSize
-       );
-
-/*******************************************************************************
-**  gcSHADER_ReallocateAttributes
-**
-**  Reallocate an array of pointers to gcATTRIBUTE objects.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gctSIZE_T Count
-**          Array count to reallocate.  'Count' must be at least 1.
-*/
-gceSTATUS
-gcSHADER_ReallocateAttributes(
-    IN gcSHADER Shader,
-    IN gctSIZE_T Count
-    );
-
-/*******************************************************************************
-**                                                       gcSHADER_AddAttribute
-********************************************************************************
-**
-**     Add an attribute to a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctCONST_STRING Name
-**                     Name of the attribute to add.
-**
-**             gcSHADER_TYPE Type
-**                     Type of the attribute to add.
-**
-**             gctSIZE_T Length
-**                     Array length of the attribute to add.  'Length' must be at least 1.
-**
-**             gctBOOL IsTexture
-**                     gcvTRUE if the attribute is used as a texture coordinate, gcvFALSE if not.
-**
-**     OUTPUT:
-**
-**             gcATTRIBUTE * Attribute
-**                     Pointer to a variable receiving the gcATTRIBUTE object pointer.
-*/
-gceSTATUS
-gcSHADER_AddAttribute(
-       IN gcSHADER Shader,
-       IN gctCONST_STRING Name,
-       IN gcSHADER_TYPE Type,
-       IN gctSIZE_T Length,
-       IN gctBOOL IsTexture,
-       OUT gcATTRIBUTE * Attribute
-       );
-
-/*******************************************************************************
-**                         gcSHADER_GetAttributeCount
-********************************************************************************
-**
-**     Get the number of attributes for this shader.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**     OUTPUT:
-**
-**             gctSIZE_T * Count
-**                     Pointer to a variable receiving the number of attributes.
-*/
-gceSTATUS
-gcSHADER_GetAttributeCount(
-       IN gcSHADER Shader,
-       OUT gctSIZE_T * Count
-       );
-
-/*******************************************************************************
-**                            gcSHADER_GetAttribute
-********************************************************************************
-**
-**     Get the gcATTRIBUTE object poniter for an indexed attribute for this shader.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctUINT Index
-**                     Index of the attribute to retrieve.
-**
-**     OUTPUT:
-**
-**             gcATTRIBUTE * Attribute
-**                     Pointer to a variable receiving the gcATTRIBUTE object pointer.
-*/
-gceSTATUS
-gcSHADER_GetAttribute(
-       IN gcSHADER Shader,
-       IN gctUINT Index,
-       OUT gcATTRIBUTE * Attribute
-       );
-
-/*******************************************************************************
-**  gcSHADER_ReallocateUniforms
-**
-**  Reallocate an array of pointers to gcUNIFORM objects.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gctSIZE_T Count
-**          Array count to reallocate.  'Count' must be at least 1.
-*/
-gceSTATUS
-gcSHADER_ReallocateUniforms(
-    IN gcSHADER Shader,
-    IN gctSIZE_T Count
-    );
-
-/*******************************************************************************
-**                                                        gcSHADER_AddUniform
-********************************************************************************
-**
-**     Add an uniform to a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctCONST_STRING Name
-**                     Name of the uniform to add.
-**
-**             gcSHADER_TYPE Type
-**                     Type of the uniform to add.
-**
-**             gctSIZE_T Length
-**                     Array length of the uniform to add.  'Length' must be at least 1.
-**
-**     OUTPUT:
-**
-**             gcUNIFORM * Uniform
-**                     Pointer to a variable receiving the gcUNIFORM object pointer.
-*/
-gceSTATUS
-gcSHADER_AddUniform(
-       IN gcSHADER Shader,
-       IN gctCONST_STRING Name,
-       IN gcSHADER_TYPE Type,
-       IN gctSIZE_T Length,
-       OUT gcUNIFORM * Uniform
-       );
-
-/*******************************************************************************
-**                                                        gcSHADER_AddPreRotationUniform
-********************************************************************************
-**
-**     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.
-**
-**             gctINT col
-**                     Which uniform.
-**
-**     OUTPUT:
-**
-**             gcUNIFORM * Uniform
-**                     Pointer to a variable receiving the gcUNIFORM object pointer.
-*/
-gceSTATUS
-gcSHADER_AddPreRotationUniform(
-       IN gcSHADER Shader,
-       IN gctCONST_STRING Name,
-       IN gcSHADER_TYPE Type,
-       IN gctSIZE_T Length,
-    IN gctINT col,
-       OUT gcUNIFORM * Uniform
-       );
-
-/*******************************************************************************
-**                                                        gcSHADER_AddUniformEx
-********************************************************************************
-**
-**     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.
-**
-**      gcSHADER_PRECISION precision
-**          Precision 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_AddUniformEx(
-       IN gcSHADER Shader,
-       IN gctCONST_STRING Name,
-       IN gcSHADER_TYPE Type,
-    IN gcSHADER_PRECISION precision,
-       IN gctSIZE_T Length,
-       OUT gcUNIFORM * Uniform
-       );
-
-/*******************************************************************************
-**                                                        gcSHADER_AddUniformEx1
-********************************************************************************
-**
-**     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.
-**
-**      gcSHADER_PRECISION precision
-**          Precision of the uniform to add.
-**
-**             gctSIZE_T Length
-**                     Array length of the uniform to add.  'Length' must be at least 1.
-**
-**      gcSHADER_VAR_CATEGORY varCategory
-**          Variable category, normal or struct.
-**
-**      gctUINT16 numStructureElement
-**          If struct, its element number.
-**
-**      gctINT16 parent
-**          If struct, parent index in gcSHADER.variables.
-**
-**      gctINT16 prevSibling
-**          If struct, previous sibling index in gcSHADER.variables.
-**
-**     OUTPUT:
-**
-**             gcUNIFORM * Uniform
-**                     Pointer to a variable receiving the gcUNIFORM object pointer.
-**
-**      gctINT16* ThisUniformIndex
-**          Returned value about uniform index in gcSHADER.
-*/
-gceSTATUS
-gcSHADER_AddUniformEx1(
-       IN gcSHADER Shader,
-       IN gctCONST_STRING Name,
-       IN gcSHADER_TYPE Type,
-    IN gcSHADER_PRECISION precision,
-       IN gctSIZE_T Length,
-    IN gctINT    IsArray,
-    IN gcSHADER_VAR_CATEGORY varCategory,
-    IN gctUINT16 numStructureElement,
-    IN gctINT16 parent,
-    IN gctINT16 prevSibling,
-    OUT gctINT16* ThisUniformIndex,
-       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_GetPreRotationUniform
-********************************************************************************
-**
-**     Get the preRotate Uniform.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**     OUTPUT:
-**
-**             gcUNIFORM ** pUniform
-**                     Pointer to a preRotation uniforms array.
-*/
-gceSTATUS
-gcSHADER_GetPreRotationUniform(
-       IN gcSHADER Shader,
-       OUT gcUNIFORM ** pUniform
-       );
-
-/*******************************************************************************
-**                             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_GetUniformIndexingRange
-********************************************************************************
-**
-**     Get the gcUNIFORM object pointer for an indexed uniform for this shader.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctINT uniformIndex
-**                     Index of the start uniform.
-**
-**             gctINT offset
-**                     Offset to indexing.
-**
-**     OUTPUT:
-**
-**             gctINT * LastUniformIndex
-**                     Pointer to index of last uniform in indexing range.
-**
-**             gctINT * OffsetUniformIndex
-**                     Pointer to index of uniform that indexing at offset.
-**
-**             gctINT * DeviationInOffsetUniform
-**                     Pointer to offset in uniform picked up.
-*/
-gceSTATUS
-gcSHADER_GetUniformIndexingRange(
-       IN gcSHADER Shader,
-       IN gctINT uniformIndex,
-    IN gctINT offset,
-       OUT gctINT * LastUniformIndex,
-    OUT gctINT * OffsetUniformIndex,
-    OUT gctINT * DeviationInOffsetUniform
-       );
-
-/*******************************************************************************
-**  gcSHADER_GetKernelFucntion
-**
-**  Get the gcKERNEL_FUNCTION object pointer for an indexed kernel function for this shader.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gctUINT Index
-**          Index of kernel function to retreive the name for.
-**
-**  OUTPUT:
-**
-**      gcKERNEL_FUNCTION * KernelFunction
-**          Pointer to a variable receiving the gcKERNEL_FUNCTION object pointer.
-*/
-gceSTATUS
-gcSHADER_GetKernelFunction(
-    IN gcSHADER Shader,
-    IN gctUINT Index,
-    OUT gcKERNEL_FUNCTION * KernelFunction
-    );
-
-gceSTATUS
-gcSHADER_GetKernelFunctionByName(
-       IN gcSHADER Shader,
-    IN gctSTRING KernelName,
-    OUT gcKERNEL_FUNCTION * KernelFunction
-    );
-/*******************************************************************************
-**  gcSHADER_GetKernelFunctionCount
-**
-**  Get the number of kernel functions for this shader.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**  OUTPUT:
-**
-**      gctSIZE_T * Count
-**          Pointer to a variable receiving the number of kernel functions.
-*/
-gceSTATUS
-gcSHADER_GetKernelFunctionCount(
-    IN gcSHADER Shader,
-    OUT gctSIZE_T * Count
-    );
-
-/*******************************************************************************
-**  gcSHADER_ReallocateOutputs
-**
-**  Reallocate an array of pointers to gcOUTPUT objects.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gctSIZE_T Count
-**          Array count to reallocate.  'Count' must be at least 1.
-*/
-gceSTATUS
-gcSHADER_ReallocateOutputs(
-    IN gcSHADER Shader,
-    IN gctSIZE_T Count
-    );
-
-/*******************************************************************************
-**                                                        gcSHADER_AddOutput
-********************************************************************************
-**
-**     Add an output to a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctCONST_STRING Name
-**                     Name of the output to add.
-**
-**             gcSHADER_TYPE Type
-**                     Type of the output to add.
-**
-**             gctSIZE_T Length
-**                     Array length of the output to add.  'Length' must be at least 1.
-**
-**             gctUINT16 TempRegister
-**                     Temporary register index that holds the output value.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddOutput(
-       IN gcSHADER Shader,
-       IN gctCONST_STRING Name,
-       IN gcSHADER_TYPE Type,
-       IN gctSIZE_T Length,
-       IN gctUINT16 TempRegister
-       );
-
-gceSTATUS
-gcSHADER_AddOutputIndexed(
-       IN gcSHADER Shader,
-       IN gctCONST_STRING Name,
-       IN gctSIZE_T Index,
-       IN gctUINT16 TempIndex
-       );
-
-/*******************************************************************************
-**                                                      gcSHADER_GetOutputCount
-********************************************************************************
-**
-**     Get the number of outputs for this shader.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**     OUTPUT:
-**
-**             gctSIZE_T * Count
-**                     Pointer to a variable receiving the number of outputs.
-*/
-gceSTATUS
-gcSHADER_GetOutputCount(
-       IN gcSHADER Shader,
-       OUT gctSIZE_T * Count
-       );
-
-/*******************************************************************************
-**                                                        gcSHADER_GetOutput
-********************************************************************************
-**
-**     Get the gcOUTPUT object pointer for an indexed output for this shader.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctUINT Index
-**                     Index of output to retrieve.
-**
-**     OUTPUT:
-**
-**             gcOUTPUT * Output
-**                     Pointer to a variable receiving the gcOUTPUT object pointer.
-*/
-gceSTATUS
-gcSHADER_GetOutput(
-       IN gcSHADER Shader,
-       IN gctUINT Index,
-       OUT gcOUTPUT * Output
-       );
-
-
-/*******************************************************************************
-**                                                        gcSHADER_GetOutputByName
-********************************************************************************
-**
-**     Get the gcOUTPUT object pointer for this shader by output name.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctSTRING name
-**                     Name of output to retrieve.
-**
-**      gctSIZE_T nameLength
-**          Length of name to retrieve
-**
-**     OUTPUT:
-**
-**             gcOUTPUT * Output
-**                     Pointer to a variable receiving the gcOUTPUT object pointer.
-*/
-gceSTATUS
-gcSHADER_GetOutputByName(
-       IN gcSHADER Shader,
-       IN gctSTRING name,
-    IN gctSIZE_T nameLength,
-       OUT gcOUTPUT * Output
-       );
-
-/*******************************************************************************
-**  gcSHADER_ReallocateVariables
-**
-**  Reallocate an array of pointers to gcVARIABLE objects.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gctSIZE_T Count
-**          Array count to reallocate.  'Count' must be at least 1.
-*/
-gceSTATUS
-gcSHADER_ReallocateVariables(
-    IN gcSHADER Shader,
-    IN gctSIZE_T Count
-    );
-
-/*******************************************************************************
-**                                                        gcSHADER_AddVariable
-********************************************************************************
-**
-**     Add a variable to a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctCONST_STRING Name
-**                     Name of the variable to add.
-**
-**             gcSHADER_TYPE Type
-**                     Type of the variable to add.
-**
-**             gctSIZE_T Length
-**                     Array length of the variable to add.  'Length' must be at least 1.
-**
-**             gctUINT16 TempRegister
-**                     Temporary register index that holds the variable value.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddVariable(
-       IN gcSHADER Shader,
-       IN gctCONST_STRING Name,
-       IN gcSHADER_TYPE Type,
-       IN gctSIZE_T Length,
-       IN gctUINT16 TempRegister
-       );
-
-
-/*******************************************************************************
-**  gcSHADER_AddVariableEx
-********************************************************************************
-**
-**  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.
-**
-**      gcSHADER_VAR_CATEGORY varCategory
-**          Variable category, normal or struct.
-**
-**      gctUINT16 numStructureElement
-**          If struct, its element number.
-**
-**      gctINT16 parent
-**          If struct, parent index in gcSHADER.variables.
-**
-**      gctINT16 prevSibling
-**          If struct, previous sibling index in gcSHADER.variables.
-**
-**  OUTPUT:
-**
-**      gctINT16* ThisVarIndex
-**          Returned value about variable index in gcSHADER.
-*/
-gceSTATUS
-gcSHADER_AddVariableEx(
-    IN gcSHADER Shader,
-    IN gctCONST_STRING Name,
-    IN gcSHADER_TYPE Type,
-    IN gctSIZE_T Length,
-    IN gctUINT16 TempRegister,
-    IN gcSHADER_VAR_CATEGORY varCategory,
-    IN gctUINT16 numStructureElement,
-    IN gctINT16 parent,
-    IN gctINT16 prevSibling,
-    OUT gctINT16* ThisVarIndex
-    );
-
-/*******************************************************************************
-**  gcSHADER_UpdateVariable
-********************************************************************************
-**
-**  Update a variable to a gcSHADER object.
-**
-**  INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctUINT Index
-**                     Index of variable to retrieve.
-**
-**             gceVARIABLE_UPDATE_FLAGS flag
-**                     Flag which property of variable will be updated.
-**
-**      gctUINT newValue
-**          New value to update.
-**
-**  OUTPUT:
-**
-**      Nothing.
-*/
-gceSTATUS
-gcSHADER_UpdateVariable(
-    IN gcSHADER Shader,
-    IN gctUINT Index,
-    IN gceVARIABLE_UPDATE_FLAGS flag,
-    IN gctUINT newValue
-    );
-
-/*******************************************************************************
-**                                                      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_GetVariableIndexingRange
-********************************************************************************
-**
-**     Get the gcVARIABLE indexing range.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gcVARIABLE variable
-**                     Start variable.
-**
-**             gctBOOL whole
-**                     Indicate whether maximum indexing range is queried
-**
-**     OUTPUT:
-**
-**             gctUINT *Start
-**                     Pointer to range start (temp register index).
-**
-**             gctUINT *End
-**                     Pointer to range end (temp register index).
-*/
-gceSTATUS
-gcSHADER_GetVariableIndexingRange(
-       IN gcSHADER Shader,
-    IN gcVARIABLE variable,
-    IN gctBOOL whole,
-    OUT gctUINT *Start,
-    OUT gctUINT *End
-       );
-
-/*******************************************************************************
-**                                                        gcSHADER_AddOpcode
-********************************************************************************
-**
-**     Add an opcode to a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gcSL_OPCODE Opcode
-**                     Opcode to add.
-**
-**             gctUINT16 TempRegister
-**                     Temporary register index that acts as the target of the opcode.
-**
-**             gctUINT8 Enable
-**                     Write enable bits for the temporary register that acts as the target
-**                     of the opcode.
-**
-**             gcSL_FORMAT Format
-**                     Format of the temporary register.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddOpcode(
-       IN gcSHADER Shader,
-       IN gcSL_OPCODE Opcode,
-       IN gctUINT16 TempRegister,
-       IN gctUINT8 Enable,
-       IN gcSL_FORMAT Format
-       );
-
-gceSTATUS
-gcSHADER_AddOpcode2(
-       IN gcSHADER Shader,
-       IN gcSL_OPCODE Opcode,
-       IN gcSL_CONDITION Condition,
-       IN gctUINT16 TempRegister,
-       IN gctUINT8 Enable,
-       IN gcSL_FORMAT Format
-       );
-
-/*******************************************************************************
-**                                                     gcSHADER_AddOpcodeIndexed
-********************************************************************************
-**
-**     Add an opcode to a gcSHADER object that writes to an dynamically indexed
-**     target.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gcSL_OPCODE Opcode
-**                     Opcode to add.
-**
-**             gctUINT16 TempRegister
-**                     Temporary register index that acts as the target of the opcode.
-**
-**             gctUINT8 Enable
-**                     Write enable bits  for the temporary register that acts as the
-**                     target of the opcode.
-**
-**             gcSL_INDEXED Mode
-**                     Location of the dynamic index inside the temporary register.  Valid
-**                     values can be:
-**
-**                             gcSL_INDEXED_X - Use x component of the temporary register.
-**                             gcSL_INDEXED_Y - Use y component of the temporary register.
-**                             gcSL_INDEXED_Z - Use z component of the temporary register.
-**                             gcSL_INDEXED_W - Use w component of the temporary register.
-**
-**             gctUINT16 IndexRegister
-**                     Temporary register index that holds the dynamic index.
-**
-**             gcSL_FORMAT Format
-**                     Format of the temporary register.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddOpcodeIndexed(
-       IN gcSHADER Shader,
-       IN gcSL_OPCODE Opcode,
-       IN gctUINT16 TempRegister,
-       IN gctUINT8 Enable,
-       IN gcSL_INDEXED Mode,
-       IN gctUINT16 IndexRegister,
-       IN gcSL_FORMAT Format
-       );
-
-/*******************************************************************************
-**  gcSHADER_AddOpcodeConditionIndexed
-**
-**  Add an opcode to a gcSHADER object that writes to an dynamically indexed
-**  target.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gcSL_OPCODE Opcode
-**          Opcode to add.
-**
-**      gcSL_CONDITION Condition
-**          Condition to check.
-**
-**      gctUINT16 TempRegister
-**          Temporary register index that acts as the target of the opcode.
-**
-**      gctUINT8 Enable
-**          Write enable bits  for the temporary register that acts as the
-**          target of the opcode.
-**
-**      gcSL_INDEXED Indexed
-**          Location of the dynamic index inside the temporary register.  Valid
-**          values can be:
-**
-**              gcSL_INDEXED_X - Use x component of the temporary register.
-**              gcSL_INDEXED_Y - Use y component of the temporary register.
-**              gcSL_INDEXED_Z - Use z component of the temporary register.
-**              gcSL_INDEXED_W - Use w component of the temporary register.
-**
-**      gctUINT16 IndexRegister
-**          Temporary register index that holds the dynamic index.
-**
-**  OUTPUT:
-**
-**      Nothing.
-*/
-gceSTATUS
-gcSHADER_AddOpcodeConditionIndexed(
-    IN gcSHADER Shader,
-    IN gcSL_OPCODE Opcode,
-    IN gcSL_CONDITION Condition,
-    IN gctUINT16 TempRegister,
-    IN gctUINT8 Enable,
-    IN gcSL_INDEXED Indexed,
-    IN gctUINT16 IndexRegister,
-    IN gcSL_FORMAT Format
-    );
-
-/*******************************************************************************
-**                                               gcSHADER_AddOpcodeConditional
-********************************************************************************
-**
-**     Add an conditional opcode to a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gcSL_OPCODE Opcode
-**                     Opcode to add.
-**
-**             gcSL_CONDITION Condition
-**                     Condition that needs to evaluate to gcvTRUE in order for the opcode to
-**                     execute.
-**
-**             gctUINT Label
-**                     Target label if 'Condition' evaluates to gcvTRUE.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddOpcodeConditional(
-       IN gcSHADER Shader,
-       IN gcSL_OPCODE Opcode,
-       IN gcSL_CONDITION Condition,
-       IN gctUINT Label
-       );
-
-/*******************************************************************************
-**  gcSHADER_AddOpcodeConditionalFormatted
-**
-**  Add an conditional jump or call opcode to a gcSHADER object.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gcSL_OPCODE Opcode
-**          Opcode to add.
-**
-**      gcSL_CONDITION Condition
-**          Condition that needs to evaluate to gcvTRUE in order for the opcode to
-**          execute.
-**
-**      gcSL_FORMAT Format
-**          Format of conditional operands
-**
-**      gctUINT Label
-**          Target label if 'Condition' evaluates to gcvTRUE.
-**
-**  OUTPUT:
-**
-**      Nothing.
-*/
-gceSTATUS
-gcSHADER_AddOpcodeConditionalFormatted(
-    IN gcSHADER Shader,
-    IN gcSL_OPCODE Opcode,
-    IN gcSL_CONDITION Condition,
-    IN gcSL_FORMAT Format,
-    IN gctUINT Label
-    );
-
-/*******************************************************************************
-**  gcSHADER_AddOpcodeConditionalFormattedEnable
-**
-**  Add an conditional jump or call opcode to a gcSHADER object.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gcSL_OPCODE Opcode
-**          Opcode to add.
-**
-**      gcSL_CONDITION Condition
-**          Condition that needs to evaluate to gcvTRUE in order for the opcode to
-**          execute.
-**
-**      gcSL_FORMAT Format
-**          Format of conditional operands
-**
-**      gctUINT8 Enable
-**          Write enable value for the target of the opcode.
-**
-**      gctUINT Label
-**          Target label if 'Condition' evaluates to gcvTRUE.
-**
-**  OUTPUT:
-**
-**      Nothing.
-*/
-gceSTATUS
-gcSHADER_AddOpcodeConditionalFormattedEnable(
-    IN gcSHADER Shader,
-    IN gcSL_OPCODE Opcode,
-    IN gcSL_CONDITION Condition,
-    IN gcSL_FORMAT Format,
-    IN gctUINT8 Enable,
-    IN gctUINT Label
-    );
-
-/*******************************************************************************
-**                                                             gcSHADER_AddLabel
-********************************************************************************
-**
-**     Define a label at the current instruction of a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctUINT Label
-**                     Label to define.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddLabel(
-       IN gcSHADER Shader,
-       IN gctUINT Label
-       );
-
-/*******************************************************************************
-**                                                        gcSHADER_AddSource
-********************************************************************************
-**
-**     Add a source operand to a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gcSL_TYPE Type
-**                     Type of the source operand.
-**
-**             gctUINT16 SourceIndex
-**                     Index of the source operand.
-**
-**             gctUINT8 Swizzle
-**                     x, y, z, and w swizzle values packed into one 8-bit value.
-**
-**             gcSL_FORMAT Format
-**                     Format of the source operand.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddSource(
-       IN gcSHADER Shader,
-       IN gcSL_TYPE Type,
-       IN gctUINT16 SourceIndex,
-       IN gctUINT8 Swizzle,
-       IN gcSL_FORMAT Format
-       );
-
-/*******************************************************************************
-**                                                     gcSHADER_AddSourceIndexed
-********************************************************************************
-**
-**     Add a dynamically indexed source operand to a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gcSL_TYPE Type
-**                     Type of the source operand.
-**
-**             gctUINT16 SourceIndex
-**                     Index of the source operand.
-**
-**             gctUINT8 Swizzle
-**                     x, y, z, and w swizzle values packed into one 8-bit value.
-**
-**             gcSL_INDEXED Mode
-**                     Addressing mode for the index.
-**
-**             gctUINT16 IndexRegister
-**                     Temporary register index that holds the dynamic index.
-**
-**             gcSL_FORMAT Format
-**                     Format of the source operand.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddSourceIndexed(
-       IN gcSHADER Shader,
-       IN gcSL_TYPE Type,
-       IN gctUINT16 SourceIndex,
-       IN gctUINT8 Swizzle,
-       IN gcSL_INDEXED Mode,
-       IN gctUINT16 IndexRegister,
-       IN gcSL_FORMAT Format
-       );
-
-/*******************************************************************************
-**                                                gcSHADER_AddSourceAttribute
-********************************************************************************
-**
-**     Add an attribute as a source operand to a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gcATTRIBUTE Attribute
-**                     Pointer to a gcATTRIBUTE object.
-**
-**             gctUINT8 Swizzle
-**                     x, y, z, and w swizzle values packed into one 8-bit value.
-**
-**             gctINT Index
-**                     Static index into the attribute in case the attribute is a matrix
-**                     or array.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddSourceAttribute(
-       IN gcSHADER Shader,
-       IN gcATTRIBUTE Attribute,
-       IN gctUINT8 Swizzle,
-       IN gctINT Index
-       );
-
-/*******************************************************************************
-**                                                gcSHADER_AddSourceAttributeIndexed
-********************************************************************************
-**
-**     Add an indexed attribute as a source operand to a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gcATTRIBUTE Attribute
-**                     Pointer to a gcATTRIBUTE object.
-**
-**             gctUINT8 Swizzle
-**                     x, y, z, and w swizzle values packed into one 8-bit value.
-**
-**             gctINT Index
-**                     Static index into the attribute in case the attribute is a matrix
-**                     or array.
-**
-**             gcSL_INDEXED Mode
-**                     Addressing mode of the dynamic index.
-**
-**             gctUINT16 IndexRegister
-**                     Temporary register index that holds the dynamic index.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddSourceAttributeIndexed(
-       IN gcSHADER Shader,
-       IN gcATTRIBUTE Attribute,
-       IN gctUINT8 Swizzle,
-       IN gctINT Index,
-       IN gcSL_INDEXED Mode,
-       IN gctUINT16 IndexRegister
-       );
-
-/*******************************************************************************
-**                                                     gcSHADER_AddSourceUniform
-********************************************************************************
-**
-**     Add a uniform as a source operand to a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gcUNIFORM Uniform
-**                     Pointer to a gcUNIFORM object.
-**
-**             gctUINT8 Swizzle
-**                     x, y, z, and w swizzle values packed into one 8-bit value.
-**
-**             gctINT Index
-**                     Static index into the uniform in case the uniform is a matrix or
-**                     array.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddSourceUniform(
-       IN gcSHADER Shader,
-       IN gcUNIFORM Uniform,
-       IN gctUINT8 Swizzle,
-       IN gctINT Index
-       );
-
-/*******************************************************************************
-**                                             gcSHADER_AddSourceUniformIndexed
-********************************************************************************
-**
-**     Add an indexed uniform as a source operand to a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gcUNIFORM Uniform
-**                     Pointer to a gcUNIFORM object.
-**
-**             gctUINT8 Swizzle
-**                     x, y, z, and w swizzle values packed into one 8-bit value.
-**
-**             gctINT Index
-**                     Static index into the uniform in case the uniform is a matrix or
-**                     array.
-**
-**             gcSL_INDEXED Mode
-**                     Addressing mode of the dynamic index.
-**
-**             gctUINT16 IndexRegister
-**                     Temporary register index that holds the dynamic index.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddSourceUniformIndexed(
-       IN gcSHADER Shader,
-       IN gcUNIFORM Uniform,
-       IN gctUINT8 Swizzle,
-       IN gctINT Index,
-       IN gcSL_INDEXED Mode,
-       IN gctUINT16 IndexRegister
-       );
-
-gceSTATUS
-gcSHADER_AddSourceSamplerIndexed(
-       IN gcSHADER Shader,
-       IN gctUINT8 Swizzle,
-       IN gcSL_INDEXED Mode,
-       IN gctUINT16 IndexRegister
-       );
-
-gceSTATUS
-gcSHADER_AddSourceAttributeFormatted(
-    IN gcSHADER Shader,
-    IN gcATTRIBUTE Attribute,
-    IN gctUINT8 Swizzle,
-    IN gctINT Index,
-    IN gcSL_FORMAT Format
-    );
-
-gceSTATUS
-gcSHADER_AddSourceAttributeIndexedFormatted(
-    IN gcSHADER Shader,
-    IN gcATTRIBUTE Attribute,
-    IN gctUINT8 Swizzle,
-    IN gctINT Index,
-    IN gcSL_INDEXED Mode,
-    IN gctUINT16 IndexRegister,
-    IN gcSL_FORMAT Format
-    );
-
-gceSTATUS
-gcSHADER_AddSourceUniformFormatted(
-    IN gcSHADER Shader,
-    IN gcUNIFORM Uniform,
-    IN gctUINT8 Swizzle,
-    IN gctINT Index,
-    IN gcSL_FORMAT Format
-    );
-
-gceSTATUS
-gcSHADER_AddSourceUniformIndexedFormatted(
-    IN gcSHADER Shader,
-    IN gcUNIFORM Uniform,
-    IN gctUINT8 Swizzle,
-    IN gctINT Index,
-    IN gcSL_INDEXED Mode,
-    IN gctUINT16 IndexRegister,
-    IN gcSL_FORMAT Format
-    );
-
-gceSTATUS
-gcSHADER_AddSourceSamplerIndexedFormatted(
-    IN gcSHADER Shader,
-    IN gctUINT8 Swizzle,
-    IN gcSL_INDEXED Mode,
-    IN gctUINT16 IndexRegister,
-    IN gcSL_FORMAT Format
-    );
-
-/*******************************************************************************
-**                                                gcSHADER_AddSourceConstant
-********************************************************************************
-**
-**     Add a constant floating point value as a source operand to a gcSHADER
-**     object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctFLOAT Constant
-**                     Floating point constant.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddSourceConstant(
-       IN gcSHADER Shader,
-       IN gctFLOAT Constant
-       );
-
-/*******************************************************************************
-**                                        gcSHADER_AddSourceConstantFormatted
-********************************************************************************
-**
-**     Add a constant value as a source operand to a gcSHADER
-**     object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             void * Constant
-**                     Pointer to constant.
-**
-**             gcSL_FORMAT Format
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_AddSourceConstantFormatted(
-       IN gcSHADER Shader,
-       IN void *Constant,
-       IN gcSL_FORMAT Format
-       );
-
-/*******************************************************************************
-**                                                               gcSHADER_Pack
-********************************************************************************
-**
-**     Pack a dynamically created gcSHADER object by trimming the allocated arrays
-**     and resolving all the labeling.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_Pack(
-       IN gcSHADER Shader
-       );
-
-/*******************************************************************************
-**                                                             gcSHADER_SetOptimizationOption
-********************************************************************************
-**
-**     Set optimization option of a gcSHADER object.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object.
-**
-**             gctUINT OptimizationOption
-**                     Optimization option.  Can be one of the following:
-**
-**                             0                                               - No optimization.
-**                             1                                               - Full optimization.
-**                             Other value                             - For optimizer testing.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcSHADER_SetOptimizationOption(
-       IN gcSHADER Shader,
-       IN gctUINT OptimizationOption
-       );
-
-/*******************************************************************************
-**  gcSHADER_ReallocateFunctions
-**
-**  Reallocate an array of pointers to gcFUNCTION objects.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gctSIZE_T Count
-**          Array count to reallocate.  'Count' must be at least 1.
-*/
-gceSTATUS
-gcSHADER_ReallocateFunctions(
-    IN gcSHADER Shader,
-    IN gctSIZE_T Count
-    );
-
-gceSTATUS
-gcSHADER_AddFunction(
-       IN gcSHADER Shader,
-       IN gctCONST_STRING Name,
-       OUT gcFUNCTION * Function
-       );
-
-gceSTATUS
-gcSHADER_ReallocateKernelFunctions(
-    IN gcSHADER Shader,
-    IN gctSIZE_T Count
-    );
-
-gceSTATUS
-gcSHADER_AddKernelFunction(
-       IN gcSHADER Shader,
-       IN gctCONST_STRING Name,
-       OUT gcKERNEL_FUNCTION * KernelFunction
-       );
-
-gceSTATUS
-gcSHADER_BeginFunction(
-       IN gcSHADER Shader,
-       IN gcFUNCTION Function
-       );
-
-gceSTATUS
-gcSHADER_EndFunction(
-       IN gcSHADER Shader,
-       IN gcFUNCTION Function
-       );
-
-gceSTATUS
-gcSHADER_BeginKernelFunction(
-       IN gcSHADER Shader,
-       IN gcKERNEL_FUNCTION KernelFunction
-       );
-
-gceSTATUS
-gcSHADER_EndKernelFunction(
-       IN gcSHADER Shader,
-       IN gcKERNEL_FUNCTION KernelFunction,
-       IN gctSIZE_T LocalMemorySize
-       );
-
-gceSTATUS
-gcSHADER_SetMaxKernelFunctionArgs(
-    IN gcSHADER Shader,
-    IN gctUINT32 MaxKernelFunctionArgs
-    );
-
-/*******************************************************************************
-**  gcSHADER_SetConstantMemorySize
-**
-**  Set the constant memory address space size of a gcSHADER object.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gctSIZE_T ConstantMemorySize
-**          Constant memory size in bytes
-**
-**      gctCHAR *ConstantMemoryBuffer
-**          Constant memory buffer
-*/
-gceSTATUS
-gcSHADER_SetConstantMemorySize(
-    IN gcSHADER Shader,
-    IN gctSIZE_T ConstantMemorySize,
-    IN gctCHAR * ConstantMemoryBuffer
-    );
-
-/*******************************************************************************
-**  gcSHADER_GetConstantMemorySize
-**
-**  Set the constant memory address space size of a gcSHADER object.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**  OUTPUT:
-**
-**      gctSIZE_T * ConstantMemorySize
-**          Pointer to a variable receiving constant memory size in bytes
-**
-**      gctCHAR **ConstantMemoryBuffer.
-**          Pointer to a variable for returned shader constant memory buffer.
-*/
-gceSTATUS
-gcSHADER_GetConstantMemorySize(
-    IN gcSHADER Shader,
-    OUT gctSIZE_T * ConstantMemorySize,
-    OUT gctCHAR ** ConstantMemoryBuffer
-    );
-
-/*******************************************************************************
-**  gcSHADER_SetPrivateMemorySize
-**
-**  Set the private memory address space size of a gcSHADER object.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gctSIZE_T PrivateMemorySize
-**          Private memory size in bytes
-*/
-gceSTATUS
-gcSHADER_SetPrivateMemorySize(
-    IN gcSHADER Shader,
-    IN gctSIZE_T PrivateMemorySize
-    );
-
-/*******************************************************************************
-**  gcSHADER_GetPrivateMemorySize
-**
-**  Set the private memory address space size of a gcSHADER object.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**  OUTPUT:
-**
-**      gctSIZE_T * PrivateMemorySize
-**          Pointer to a variable receiving private memory size in bytes
-*/
-gceSTATUS
-gcSHADER_GetPrivateMemorySize(
-    IN gcSHADER Shader,
-    OUT gctSIZE_T * PrivateMemorySize
-    );
-
-/*******************************************************************************
-**  gcSHADER_SetLocalMemorySize
-**
-**  Set the local memory address space size of a gcSHADER object.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**      gctSIZE_T LocalMemorySize
-**          Local memory size in bytes
-*/
-gceSTATUS
-gcSHADER_SetLocalMemorySize(
-    IN gcSHADER Shader,
-    IN gctSIZE_T LocalMemorySize
-    );
-
-/*******************************************************************************
-**  gcSHADER_GetLocalMemorySize
-**
-**  Set the local memory address space size of a gcSHADER object.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-**  OUTPUT:
-**
-**      gctSIZE_T * LocalMemorySize
-**          Pointer to a variable receiving lcoal memory size in bytes
-*/
-gceSTATUS
-gcSHADER_GetLocalMemorySize(
-    IN gcSHADER Shader,
-    OUT gctSIZE_T * LocalMemorySize
-    );
-
-
-/*******************************************************************************
-**  gcSHADER_CheckValidity
-**
-**  Check validity for a gcSHADER object.
-**
-**  INPUT:
-**
-**      gcSHADER Shader
-**          Pointer to a gcSHADER object.
-**
-*/
-gceSTATUS
-gcSHADER_CheckValidity(
-    IN gcSHADER Shader
-    );
-
-#if gcdUSE_WCLIP_PATCH
-gceSTATUS
-gcATTRIBUTE_IsPosition(
-        IN gcATTRIBUTE Attribute,
-        OUT gctBOOL * IsPosition
-        );
-#endif
-
-/*******************************************************************************
-**                             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_GetTypeEx
-********************************************************************************
-**
-**     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.
-**
-**             gcSHADER_PRECISION * Precision
-**                     Pointer to a variable receiving the precision of the uniform.  'Precision' 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_GetTypeEx(
-       IN gcUNIFORM Uniform,
-       OUT gcSHADER_TYPE * Type,
-    OUT gcSHADER_PRECISION * Precision,
-       OUT gctSIZE_T * ArrayLength
-       );
-
-/*******************************************************************************
-**                              gcUNIFORM_GetFlags
-********************************************************************************
-**
-**     Get the flags of a gcUNIFORM object.
-**
-**     INPUT:
-**
-**             gcUNIFORM Uniform
-**                     Pointer to a gcUNIFORM object.
-**
-**     OUTPUT:
-**
-**             gceUNIFORM_FLAGS * Flags
-**                     Pointer to a variable receiving the flags of the uniform.
-**
-*/
-gceSTATUS
-gcUNIFORM_GetFlags(
-       IN gcUNIFORM Uniform,
-       OUT gceUNIFORM_FLAGS * Flags
-       );
-
-/*******************************************************************************
-**                              gcUNIFORM_SetFlags
-********************************************************************************
-**
-**     Set the flags of a gcUNIFORM object.
-**
-**     INPUT:
-**
-**             gcUNIFORM Uniform
-**                     Pointer to a gcUNIFORM object.
-**
-**             gceUNIFORM_FLAGS Flags
-**                     Flags of the uniform to be set.
-**
-**     OUTPUT:
-**                     Nothing.
-**
-*/
-gceSTATUS
-gcUNIFORM_SetFlags(
-       IN gcUNIFORM Uniform,
-       IN gceUNIFORM_FLAGS Flags
-       );
-
-/*******************************************************************************
-**                              gcUNIFORM_GetName
-********************************************************************************
-**
-**     Get the name of a gcUNIFORM object.
-**
-**     INPUT:
-**
-**             gcUNIFORM Uniform
-**                     Pointer to a gcUNIFORM object.
-**
-**     OUTPUT:
-**
-**             gctSIZE_T * Length
-**                     Pointer to a variable receiving the length of the uniform name.
-**                     'Length' can be gcvNULL, in which case no length will be returned.
-**
-**             gctCONST_STRING * Name
-**                     Pointer to a variable receiving the pointer to the uniform name.
-**                     'Name' can be gcvNULL, in which case no name will be returned.
-*/
-gceSTATUS
-gcUNIFORM_GetName(
-       IN gcUNIFORM Uniform,
-       OUT gctSIZE_T * Length,
-       OUT gctCONST_STRING * Name
-       );
-
-/*******************************************************************************
-**                              gcUNIFORM_GetSampler
-********************************************************************************
-**
-**     Get the physical sampler number for a sampler gcUNIFORM object.
-**
-**     INPUT:
-**
-**             gcUNIFORM Uniform
-**                     Pointer to a gcUNIFORM object.
-**
-**     OUTPUT:
-**
-**             gctUINT32 * Sampler
-**                     Pointer to a variable receiving the physical sampler.
-*/
-gceSTATUS
-gcUNIFORM_GetSampler(
-       IN gcUNIFORM Uniform,
-       OUT gctUINT32 * Sampler
-       );
-
-/*******************************************************************************
-**  gcUNIFORM_GetFormat
-**
-**  Get the type and array length of a gcUNIFORM object.
-**
-**  INPUT:
-**
-**      gcUNIFORM Uniform
-**          Pointer to a gcUNIFORM object.
-**
-**  OUTPUT:
-**
-**      gcSL_FORMAT * Format
-**          Pointer to a variable receiving the format of element of the uniform.
-**          'Type' can be gcvNULL, in which case no type will be returned.
-**
-**      gctBOOL * IsPointer
-**          Pointer to a variable receiving the state wheter the uniform is a pointer.
-**          'IsPointer' can be gcvNULL, in which case no array length will be returned.
-*/
-gceSTATUS
-gcUNIFORM_GetFormat(
-    IN gcUNIFORM Uniform,
-    OUT gcSL_FORMAT * Format,
-    OUT gctBOOL * IsPointer
-    );
-
-/*******************************************************************************
-**  gcUNIFORM_SetFormat
-**
-**  Set the format and isPointer of a uniform.
-**
-**  INPUT:
-**
-**      gcUNIFORM Uniform
-**          Pointer to a gcUNIFORM object.
-**
-**      gcSL_FORMAT Format
-**          Format of element of the uniform shaderType.
-**
-**      gctBOOL IsPointer
-**          Wheter the uniform is a pointer.
-**
-**  OUTPUT:
-**
-**      Nothing.
-*/
-gceSTATUS
-gcUNIFORM_SetFormat(
-    IN gcUNIFORM Uniform,
-    IN gcSL_FORMAT Format,
-    IN gctBOOL IsPointer
-    );
-
-/*******************************************************************************
-**                                                        gcUNIFORM_SetValue
-********************************************************************************
-**
-**     Set the value of a uniform in integer.
-**
-**     INPUT:
-**
-**             gcUNIFORM Uniform
-**                     Pointer to a gcUNIFORM object.
-**
-**             gctSIZE_T Count
-**                     Number of entries to program if the uniform has been declared as an
-**                     array.
-**
-**             const gctINT * Value
-**                     Pointer to a buffer holding the integer values for the uniform.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcUNIFORM_SetValue(
-       IN gcUNIFORM Uniform,
-       IN gctSIZE_T Count,
-       IN const gctINT * Value
-       );
-
-/*******************************************************************************
-**                                                        gcUNIFORM_SetValueX
-********************************************************************************
-**
-**     Set the value of a uniform in fixed point.
-**
-**     INPUT:
-**
-**             gcUNIFORM Uniform
-**                     Pointer to a gcUNIFORM object.
-**
-**             gctSIZE_T Count
-**                     Number of entries to program if the uniform has been declared as an
-**                     array.
-**
-**             const gctFIXED_POINT * Value
-**                     Pointer to a buffer holding the fixed point values for the uniform.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcUNIFORM_SetValueX(
-       IN gcUNIFORM Uniform,
-       IN gctSIZE_T Count,
-       IN gctFIXED_POINT * Value
-       );
-
-/*******************************************************************************
-**                                                        gcUNIFORM_SetValueF
-********************************************************************************
-**
-**     Set the value of a uniform in floating point.
-**
-**     INPUT:
-**
-**             gcUNIFORM Uniform
-**                     Pointer to a gcUNIFORM object.
-**
-**             gctSIZE_T Count
-**                     Number of entries to program if the uniform has been declared as an
-**                     array.
-**
-**             const gctFLOAT * Value
-**                     Pointer to a buffer holding the floating point values for the
-**                     uniform.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gceSTATUS
-gcUNIFORM_SetValueF(
-       IN gcUNIFORM Uniform,
-       IN gctSIZE_T Count,
-       IN const gctFLOAT * Value
-       );
-
-/*******************************************************************************
-**  gcUNIFORM_ProgramF
-**
-**  Set the value of a uniform in floating point.
-**
-**  INPUT:
-**
-**      gctUINT32 Address
-**          Address of Uniform.
-**
-**      gctSIZE_T Row/Col
-**
-**      const gctFLOAT * Value
-**          Pointer to a buffer holding the floating point values for the
-**          uniform.
-**
-**  OUTPUT:
-**
-**      Nothing.
-*/
-gceSTATUS
-gcUNIFORM_ProgramF(
-    IN gctUINT32 Address,
-    IN gctSIZE_T Row,
-    IN gctSIZE_T Col,
-    IN const gctFLOAT * Value
-    );
-
-/*******************************************************************************
-**                                              gcUNIFORM_GetModelViewProjMatrix
-********************************************************************************
-**
-**     Get the value of uniform modelViewProjMatrix ID if present.
-**
-**     INPUT:
-**
-**             gcUNIFORM Uniform
-**                     Pointer to a gcUNIFORM object.
-**
-**     OUTPUT:
-**
-**             Nothing.
-*/
-gctUINT
-gcUNIFORM_GetModelViewProjMatrix(
-    IN gcUNIFORM Uniform
-    );
-
-/*******************************************************************************
-**                                                             gcOUTPUT_GetType
-********************************************************************************
-**
-**     Get the type and array length of a gcOUTPUT object.
-**
-**     INPUT:
-**
-**             gcOUTPUT Output
-**                     Pointer to a gcOUTPUT object.
-**
-**     OUTPUT:
-**
-**             gcSHADER_TYPE * Type
-**                     Pointer to a variable receiving the type of the output.  'Type' can
-**                     be gcvNULL, in which case no type will be returned.
-**
-**             gctSIZE_T * ArrayLength
-**                     Pointer to a variable receiving the length of the array if the
-**                     output was declared as an array.  If the output was not declared
-**                     as an array, the array length will be 1.  'ArrayLength' can be gcvNULL,
-**                     in which case no array length will be returned.
-*/
-gceSTATUS
-gcOUTPUT_GetType(
-       IN gcOUTPUT Output,
-       OUT gcSHADER_TYPE * Type,
-       OUT gctSIZE_T * ArrayLength
-       );
-
-/*******************************************************************************
-**                                                        gcOUTPUT_GetIndex
-********************************************************************************
-**
-**     Get the index of a gcOUTPUT object.
-**
-**     INPUT:
-**
-**             gcOUTPUT Output
-**                     Pointer to a gcOUTPUT object.
-**
-**     OUTPUT:
-**
-**             gctUINT * Index
-**                     Pointer to a variable receiving the temporary register index of the
-**                     output.  'Index' can be gcvNULL,. in which case no index will be
-**                     returned.
-*/
-gceSTATUS
-gcOUTPUT_GetIndex(
-       IN gcOUTPUT Output,
-       OUT gctUINT * Index
-       );
-
-/*******************************************************************************
-**                                                             gcOUTPUT_GetName
-********************************************************************************
-**
-**     Get the name of a gcOUTPUT object.
-**
-**     INPUT:
-**
-**             gcOUTPUT Output
-**                     Pointer to a gcOUTPUT object.
-**
-**     OUTPUT:
-**
-**             gctSIZE_T * Length
-**                     Pointer to a variable receiving the length of the output name.
-**                     'Length' can be gcvNULL, in which case no length will be returned.
-**
-**             gctCONST_STRING * Name
-**                     Pointer to a variable receiving the pointer to the output name.
-**                     'Name' can be gcvNULL, in which case no name will be returned.
-*/
-gceSTATUS
-gcOUTPUT_GetName(
-       IN gcOUTPUT Output,
-       OUT gctSIZE_T * Length,
-       OUT gctCONST_STRING * Name
-       );
-
-/*******************************************************************************
-*********************************************************** F U N C T I O N S **
-*******************************************************************************/
-
-/*******************************************************************************
-**  gcFUNCTION_ReallocateArguments
-**
-**  Reallocate an array of gcsFUNCTION_ARGUMENT objects.
-**
-**  INPUT:
-**
-**      gcFUNCTION Function
-**          Pointer to a gcFUNCTION object.
-**
-**      gctSIZE_T Count
-**          Array count to reallocate.  'Count' must be at least 1.
-*/
-gceSTATUS
-gcFUNCTION_ReallocateArguments(
-    IN gcFUNCTION Function,
-    IN gctSIZE_T Count
-    );
-
-gceSTATUS
-gcFUNCTION_AddArgument(
-       IN gcFUNCTION Function,
-       IN gctUINT16 TempIndex,
-       IN gctUINT8 Enable,
-       IN gctUINT8 Qualifier
-       );
-
-gceSTATUS
-gcFUNCTION_GetArgument(
-       IN gcFUNCTION Function,
-       IN gctUINT16 Index,
-       OUT gctUINT16_PTR Temp,
-       OUT gctUINT8_PTR Enable,
-       OUT gctUINT8_PTR Swizzle
-       );
-
-gceSTATUS
-gcFUNCTION_GetLabel(
-       IN gcFUNCTION Function,
-       OUT gctUINT_PTR Label
-       );
-
-/*******************************************************************************
-************************* K E R N E L    P R O P E R T Y    F U N C T I O N S **
-*******************************************************************************/
-/*******************************************************************************/
-gceSTATUS
-gcKERNEL_FUNCTION_AddKernelFunctionProperties(
-           IN gcKERNEL_FUNCTION KernelFunction,
-               IN gctINT propertyType,
-               IN gctSIZE_T propertySize,
-               IN gctINT * values
-               );
-
-gceSTATUS
-gcKERNEL_FUNCTION_GetPropertyCount(
-    IN gcKERNEL_FUNCTION KernelFunction,
-    OUT gctSIZE_T * Count
-    );
-
-gceSTATUS
-gcKERNEL_FUNCTION_GetProperty(
-    IN gcKERNEL_FUNCTION KernelFunction,
-    IN gctUINT Index,
-       OUT gctSIZE_T * propertySize,
-       OUT gctINT * propertyType,
-       OUT gctINT * propertyValues
-    );
-
-
-/*******************************************************************************
-*******************************I M A G E   S A M P L E R    F U N C T I O N S **
-*******************************************************************************/
-/*******************************************************************************
-**  gcKERNEL_FUNCTION_ReallocateImageSamplers
-**
-**  Reallocate an array of pointers to image sampler pair.
-**
-**  INPUT:
-**
-**      gcKERNEL_FUNCTION KernelFunction
-**          Pointer to a gcKERNEL_FUNCTION object.
-**
-**      gctSIZE_T Count
-**          Array count to reallocate.  'Count' must be at least 1.
-*/
-gceSTATUS
-gcKERNEL_FUNCTION_ReallocateImageSamplers(
-    IN gcKERNEL_FUNCTION KernelFunction,
-    IN gctSIZE_T Count
-    );
-
-gceSTATUS
-gcKERNEL_FUNCTION_AddImageSampler(
-    IN gcKERNEL_FUNCTION KernelFunction,
-    IN gctUINT8 ImageNum,
-    IN gctBOOL IsConstantSamplerType,
-    IN gctUINT32 SamplerType
-    );
-
-gceSTATUS
-gcKERNEL_FUNCTION_GetImageSamplerCount(
-    IN gcKERNEL_FUNCTION KernelFunction,
-    OUT gctSIZE_T * Count
-    );
-
-gceSTATUS
-gcKERNEL_FUNCTION_GetImageSampler(
-    IN gcKERNEL_FUNCTION KernelFunction,
-    IN gctUINT Index,
-    OUT gctUINT8 *ImageNum,
-    OUT gctBOOL *IsConstantSamplerType,
-    OUT gctUINT32 *SamplerType
-    );
-
-/*******************************************************************************
-*********************************************K E R N E L    F U N C T I O N S **
-*******************************************************************************/
-
-/*******************************************************************************
-**  gcKERNEL_FUNCTION_ReallocateArguments
-**
-**  Reallocate an array of gcsFUNCTION_ARGUMENT objects.
-**
-**  INPUT:
-**
-**      gcKERNEL_FUNCTION Function
-**          Pointer to a gcKERNEL_FUNCTION object.
-**
-**      gctSIZE_T Count
-**          Array count to reallocate.  'Count' must be at least 1.
-*/
-gceSTATUS
-gcKERNEL_FUNCTION_ReallocateArguments(
-    IN gcKERNEL_FUNCTION Function,
-    IN gctSIZE_T Count
-    );
-
-gceSTATUS
-gcKERNEL_FUNCTION_AddArgument(
-       IN gcKERNEL_FUNCTION Function,
-       IN gctUINT16 TempIndex,
-       IN gctUINT8 Enable,
-       IN gctUINT8 Qualifier
-       );
-
-gceSTATUS
-gcKERNEL_FUNCTION_GetArgument(
-       IN gcKERNEL_FUNCTION Function,
-       IN gctUINT16 Index,
-       OUT gctUINT16_PTR Temp,
-       OUT gctUINT8_PTR Enable,
-       OUT gctUINT8_PTR Swizzle
-       );
-
-gceSTATUS
-gcKERNEL_FUNCTION_GetLabel(
-       IN gcKERNEL_FUNCTION Function,
-       OUT gctUINT_PTR Label
-       );
-
-gceSTATUS
-gcKERNEL_FUNCTION_GetName(
-    IN gcKERNEL_FUNCTION KernelFunction,
-    OUT gctSIZE_T * Length,
-    OUT gctCONST_STRING * Name
-    );
-
-gceSTATUS
-gcKERNEL_FUNCTION_ReallocateUniformArguments(
-    IN gcKERNEL_FUNCTION KernelFunction,
-    IN gctSIZE_T Count
-    );
-
-gceSTATUS
-gcKERNEL_FUNCTION_AddUniformArgument(
-    IN gcKERNEL_FUNCTION KernelFunction,
-    IN gctCONST_STRING Name,
-    IN gcSHADER_TYPE Type,
-    IN gctSIZE_T Length,
-    OUT gcUNIFORM * UniformArgument
-    );
-
-gceSTATUS
-gcKERNEL_FUNCTION_GetUniformArgumentCount(
-    IN gcKERNEL_FUNCTION KernelFunction,
-    OUT gctSIZE_T * Count
-    );
-
-gceSTATUS
-gcKERNEL_FUNCTION_GetUniformArgument(
-    IN gcKERNEL_FUNCTION KernelFunction,
-    IN gctUINT Index,
-    OUT gcUNIFORM * UniformArgument
-    );
-
-gceSTATUS
-gcKERNEL_FUNCTION_SetCodeEnd(
-    IN gcKERNEL_FUNCTION KernelFunction
-    );
-
-/*******************************************************************************
-**                              gcCompileShader
-********************************************************************************
-**
-**     Compile a shader.
-**
-**     INPUT:
-**
-**             gcoOS Hal
-**                     Pointer to an gcoHAL object.
-**
-**             gctINT ShaderType
-**                     Shader type to compile.  Can be one of the following values:
-**
-**                             gcSHADER_TYPE_VERTEX
-**                                     Compile a vertex shader.
-**
-**                             gcSHADER_TYPE_FRAGMENT
-**                                     Compile a fragment shader.
-**
-**             gctSIZE_T SourceSize
-**                     Size of the source buffer in bytes.
-**
-**             gctCONST_STRING Source
-**                     Pointer to the buffer containing the shader source code.
-**
-**     OUTPUT:
-**
-**             gcSHADER * Binary
-**                     Pointer to a variable receiving the pointer to a gcSHADER object
-**                     containg the compiled shader code.
-**
-**             gctSTRING * Log
-**                     Pointer to a variable receiving a string pointer containging the
-**                     compile log.
-*/
-gceSTATUS
-gcCompileShader(
-       IN gcoHAL Hal,
-       IN gctINT ShaderType,
-       IN gctSIZE_T SourceSize,
-       IN gctCONST_STRING Source,
-       OUT gcSHADER * Binary,
-       OUT gctSTRING * Log
-       );
-
-/*******************************************************************************
-**                              gcOptimizeShader
-********************************************************************************
-**
-**     Optimize a shader.
-**
-**     INPUT:
-**
-**             gcSHADER Shader
-**                     Pointer to a gcSHADER object holding information about the compiled
-**                     shader.
-**
-**             gctFILE LogFile
-**                     Pointer to an open FILE object.
-*/
-gceSTATUS
-gcOptimizeShader(
-       IN gcSHADER Shader,
-       IN gctFILE LogFile
-       );
-
-/*******************************************************************************
-**                                gcLinkShaders
-********************************************************************************
-**
-**     Link two shaders and generate a harwdare specific state buffer by compiling
-**     the compiler generated code through the resource allocator and code
-**     generator.
-**
-**     INPUT:
-**
-**             gcSHADER VertexShader
-**                     Pointer to a gcSHADER object holding information about the compiled
-**                     vertex shader.
-**
-**             gcSHADER FragmentShader
-**                     Pointer to a gcSHADER object holding information about the compiled
-**                     fragment shader.
-**
-**             gceSHADER_FLAGS Flags
-**                     Compiler flags.  Can be any of the following:
-**
-**                             gcvSHADER_DEAD_CODE       - Dead code elimination.
-**                             gcvSHADER_RESOURCE_USAGE  - Resource usage optimizaion.
-**                             gcvSHADER_OPTIMIZER       - Full optimization.
-**                             gcvSHADER_USE_GL_Z        - Use OpenGL ES Z coordinate.
-**                             gcvSHADER_USE_GL_POSITION - Use OpenGL ES gl_Position.
-**                             gcvSHADER_USE_GL_FACE     - Use OpenGL ES gl_FaceForward.
-**
-**     OUTPUT:
-**
-**             gctSIZE_T * StateBufferSize
-**                     Pointer to a variable receicing the number of bytes in the buffer
-**                     returned in 'StateBuffer'.
-**
-**             gctPOINTER * StateBuffer
-**                     Pointer to a variable receiving a buffer pointer that contains the
-**                     states required to download the shaders into the hardware.
-**
-**             gcsHINT_PTR * Hints
-**                     Pointer to a variable receiving a gcsHINT structure pointer that
-**                     contains information required when loading the shader states.
-*/
-gceSTATUS
-gcLinkShaders(
-       IN gcSHADER VertexShader,
-       IN gcSHADER FragmentShader,
-       IN gceSHADER_FLAGS Flags,
-       OUT gctSIZE_T * StateBufferSize,
-       OUT gctPOINTER * StateBuffer,
-       OUT gcsHINT_PTR * Hints,
-    OUT gcMACHINECODE_PTR *ppVsMachineCode,
-    OUT gcMACHINECODE_PTR *ppFsMachineCode
-       );
-
-/*******************************************************************************
-**                                gcLoadShaders
-********************************************************************************
-**
-**     Load a pre-compiled and pre-linked shader program into the hardware.
-**
-**     INPUT:
-**
-**             gcoHAL Hal
-**                     Pointer to a gcoHAL object.
-**
-**             gctSIZE_T StateBufferSize
-**                     The number of bytes in the 'StateBuffer'.
-**
-**             gctPOINTER StateBuffer
-**                     Pointer to the states that make up the shader program.
-**
-**             gcsHINT_PTR Hints
-**                     Pointer to a gcsHINT structure that contains information required
-**                     when loading the shader states.
-*/
-gceSTATUS
-gcLoadShaders(
-       IN gcoHAL Hal,
-       IN gctSIZE_T StateBufferSize,
-       IN gctPOINTER StateBuffer,
-       IN gcsHINT_PTR Hints
-       );
-
-gceSTATUS
-gcRecompileShaders(
-    IN gcoHAL Hal,
-    IN gcMACHINECODE_PTR pVsMachineCode,
-    IN gcMACHINECODE_PTR pPsMachineCode,
-    /*Recompile variables*/
-    IN OUT gctPOINTER *ppRecompileStateBuffer,
-    IN OUT gctSIZE_T *pRecompileStateBufferSize,
-    IN OUT gcsHINT_PTR *ppRecompileHints,
-    /* natvie state*/
-    IN gctPOINTER pNativeStateBuffer,
-    IN gctSIZE_T nativeStateBufferSize,
-    IN gcsHINT_PTR pNativeHints,
-    /* npt info */
-    IN gctUINT32 Samplers,
-    IN gctUINT32 *SamplerWrapS,
-    IN gctUINT32 *SamplerWrapT
-    );
-
-gceSTATUS
-gcRecompileDepthBias(
-    IN gcoHAL Hal,
-    IN gcMACHINECODE_PTR pVsMachineCode,
-    /*Recompile variables*/
-    IN OUT gctPOINTER *ppRecompileStateBuffer,
-    IN OUT gctSIZE_T *pRecompileStateBufferSize,
-    IN OUT gcsHINT_PTR *ppRecompileHints,
-    /* natvie state*/
-    IN gctPOINTER pNativeStateBuffer,
-    IN gctSIZE_T nativeStateBufferSize,
-    IN gcsHINT_PTR pNativeHints,
-       OUT gctINT * uniformAddr,
-       OUT gctINT * uniformChannel
-    );
-
-/*******************************************************************************
-**                                gcSaveProgram
-********************************************************************************
-**
-**     Save pre-compiled shaders and pre-linked programs to a binary file.
-**
-**     INPUT:
-**
-**             gcSHADER VertexShader
-**                     Pointer to vertex shader object.
-**
-**             gcSHADER FragmentShader
-**                     Pointer to fragment shader object.
-**
-**             gctSIZE_T ProgramBufferSize
-**                     Number of bytes in 'ProgramBuffer'.
-**
-**             gctPOINTER ProgramBuffer
-**                     Pointer to buffer containing the program states.
-**
-**             gcsHINT_PTR Hints
-**                     Pointer to HINTS structure for program states.
-**
-**     OUTPUT:
-**
-**             gctPOINTER * Binary
-**                     Pointer to a variable receiving the binary data to be saved.
-**
-**             gctSIZE_T * BinarySize
-**                     Pointer to a variable receiving the number of bytes inside 'Binary'.
-*/
-gceSTATUS
-gcSaveProgram(
-       IN gcSHADER VertexShader,
-       IN gcSHADER FragmentShader,
-       IN gctSIZE_T ProgramBufferSize,
-       IN gctPOINTER ProgramBuffer,
-       IN gcsHINT_PTR Hints,
-       OUT gctPOINTER * Binary,
-       OUT gctSIZE_T * BinarySize
-       );
-
-/*******************************************************************************
-**                                gcLoadProgram
-********************************************************************************
-**
-**     Load pre-compiled shaders and pre-linked programs from a binary file.
-**
-**     INPUT:
-**
-**             gctPOINTER Binary
-**                     Pointer to the binary data loaded.
-**
-**             gctSIZE_T BinarySize
-**                     Number of bytes in 'Binary'.
-**
-**     OUTPUT:
-**
-**             gcSHADER VertexShader
-**                     Pointer to a vertex shader object.
-**
-**             gcSHADER FragmentShader
-**                     Pointer to a fragment shader object.
-**
-**             gctSIZE_T * ProgramBufferSize
-**                     Pointer to a variable receicing the number of bytes in the buffer
-**                     returned in 'ProgramBuffer'.
-**
-**             gctPOINTER * ProgramBuffer
-**                     Pointer to a variable receiving a buffer pointer that contains the
-**                     states required to download the shaders into the hardware.
-**
-**             gcsHINT_PTR * Hints
-**                     Pointer to a variable receiving a gcsHINT structure pointer that
-**                     contains information required when loading the shader states.
-*/
-gceSTATUS
-gcLoadProgram(
-       IN gctPOINTER Binary,
-       IN gctSIZE_T BinarySize,
-       OUT gcSHADER VertexShader,
-       OUT gcSHADER FragmentShader,
-       OUT gctSIZE_T * ProgramBufferSize,
-       OUT gctPOINTER * ProgramBuffer,
-       OUT gcsHINT_PTR * Hints
-       );
-
-/*******************************************************************************
-**                              gcCompileKernel
-********************************************************************************
-**
-**     Compile a OpenCL kernel shader.
-**
-**     INPUT:
-**
-**             gcoOS Hal
-**                     Pointer to an gcoHAL object.
-**
-**             gctSIZE_T SourceSize
-**                     Size of the source buffer in bytes.
-**
-**             gctCONST_STRING Source
-**                     Pointer to the buffer containing the shader source code.
-**
-**     OUTPUT:
-**
-**             gcSHADER * Binary
-**                     Pointer to a variable receiving the pointer to a gcSHADER object
-**                     containg the compiled shader code.
-**
-**             gctSTRING * Log
-**                     Pointer to a variable receiving a string pointer containging the
-**                     compile log.
-*/
-gceSTATUS
-gcCompileKernel(
-       IN gcoHAL Hal,
-       IN gctSIZE_T SourceSize,
-       IN gctCONST_STRING Source,
-       IN gctCONST_STRING Options,
-       OUT gcSHADER * Binary,
-       OUT gctSTRING * Log
-       );
-
-/*******************************************************************************
-**                                gcLinkKernel
-********************************************************************************
-**
-**     Link OpenCL kernel and generate a harwdare specific state buffer by compiling
-**     the compiler generated code through the resource allocator and code
-**     generator.
-**
-**     INPUT:
-**
-**             gcSHADER Kernel
-**                     Pointer to a gcSHADER object holding information about the compiled
-**                     OpenCL kernel.
-**
-**             gceSHADER_FLAGS Flags
-**                     Compiler flags.  Can be any of the following:
-**
-**                             gcvSHADER_DEAD_CODE       - Dead code elimination.
-**                             gcvSHADER_RESOURCE_USAGE  - Resource usage optimizaion.
-**                             gcvSHADER_OPTIMIZER       - Full optimization.
-**                             gcvSHADER_USE_GL_Z        - Use OpenGL ES Z coordinate.
-**                             gcvSHADER_USE_GL_POSITION - Use OpenGL ES gl_Position.
-**                             gcvSHADER_USE_GL_FACE     - Use OpenGL ES gl_FaceForward.
-**
-**     OUTPUT:
-**
-**             gctSIZE_T * StateBufferSize
-**                     Pointer to a variable receiving the number of bytes in the buffer
-**                     returned in 'StateBuffer'.
-**
-**             gctPOINTER * StateBuffer
-**                     Pointer to a variable receiving a buffer pointer that contains the
-**                     states required to download the shaders into the hardware.
-**
-**             gcsHINT_PTR * Hints
-**                     Pointer to a variable receiving a gcsHINT structure pointer that
-**                     contains information required when loading the shader states.
-*/
-gceSTATUS
-gcLinkKernel(
-       IN gcSHADER Kernel,
-       IN gceSHADER_FLAGS Flags,
-       OUT gctSIZE_T * StateBufferSize,
-       OUT gctPOINTER * StateBuffer,
-       OUT gcsHINT_PTR * Hints
-       );
-
-/*******************************************************************************
-**                                gcLoadKernel
-********************************************************************************
-**
-**  Load a pre-compiled and pre-linked kernel program into the hardware.
-**
-**  INPUT:
-**
-**      gctSIZE_T StateBufferSize
-**          The number of bytes in the 'StateBuffer'.
-**
-**      gctPOINTER StateBuffer
-**          Pointer to the states that make up the shader program.
-**
-**      gcsHINT_PTR Hints
-**          Pointer to a gcsHINT structure that contains information required
-**          when loading the shader states.
-*/
-gceSTATUS
-gcLoadKernel(
-    IN gctSIZE_T StateBufferSize,
-    IN gctPOINTER StateBuffer,
-    IN gcsHINT_PTR Hints
-    );
-
-gceSTATUS
-gcInvokeThreadWalker(
-    IN gcsTHREAD_WALKER_INFO_PTR Info
-    );
-
-void
-gcTYPE_GetTypeInfo(
-    IN gcSHADER_TYPE      Type,
-    OUT gctINT *          Components,
-    OUT gctINT *          Rows,
-    OUT gctCONST_STRING * Name
-    );
-
-gctBOOL
-gcOPT_doVaryingPackingForShader(
-       IN gcSHADER Shader
-    );
-
-gceSTATUS
-gcSHADER_PatchNPOTForMachineCode(
-    IN     gcSHADER_KIND          shaderType,
-    IN     gcMACHINECODE_PTR      pMachineCode,
-    IN     gcNPOT_PATCH_PARAM_PTR pPatchParam,
-    IN     gctUINT                countOfPatchParam,
-    IN     gctUINT                hwSupportedInstCount,
-    OUT    gctPOINTER*            ppCmdBuffer,
-    OUT    gctUINT32*             pByteSizeOfCmdBuffer,
-    IN OUT gcsHINT_PTR            pHints /* User needs copy original hints to this one, then passed this one in */
-    );
-
-gceSTATUS
-gcSHADER_PatchZBiasForMachineCodeVS(
-    IN     gcMACHINECODE_PTR       pMachineCode,
-    IN OUT gcZBIAS_PATCH_PARAM_PTR pPatchParam,
-    IN     gctUINT                 hwSupportedInstCount,
-    OUT    gctPOINTER*             ppCmdBuffer,
-    OUT    gctUINT32*              pByteSizeOfCmdBuffer,
-    IN OUT gcsHINT_PTR             pHints /* User needs copy original hints to this one, then passed this one in */
-    );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* VIVANTE_NO_3D */
-#endif /* __gc_hal_compiler_h_ */
index ea86349dcf97f1f5014c1d75cda5541fa4611168..345b4eaca17b7f5181f25ca9b291a96e149dc865 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -18,7 +18,6 @@
 *
 *****************************************************************************/
 
-
 #ifndef __gc_hal_driver_h_
 #define __gc_hal_driver_h_
 
@@ -42,6 +41,7 @@ extern "C" {
 #define IOCTL_GCHAL_KERNEL_INTERFACE    30001
 #define IOCTL_GCHAL_TERMINATE           30002
 
+#undef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
 /******************************************************************************\
 ********************************* Command Codes ********************************
 \******************************************************************************/
@@ -61,7 +61,7 @@ typedef enum _gceHAL_COMMAND_CODES
     /* Video memory allocation. */
     gcvHAL_ALLOCATE_VIDEO_MEMORY,           /* Enforced alignment. */
     gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY,    /* No alignment. */
-    gcvHAL_FREE_VIDEO_MEMORY,
+    gcvHAL_RELEASE_VIDEO_MEMORY,
 
     /* Physical-to-logical mapping. */
     gcvHAL_MAP_MEMORY,
@@ -145,9 +145,6 @@ typedef enum _gceHAL_COMMAND_CODES
     /* Frame database. */
     gcvHAL_GET_FRAME_INFO,
 
-    /* Shared info for each process */
-    gcvHAL_GET_SHARED_INFO,
-    gcvHAL_SET_SHARED_INFO,
     gcvHAL_QUERY_COMMAND_BUFFER,
 
     gcvHAL_COMMIT_DONE,
@@ -164,17 +161,33 @@ typedef enum _gceHAL_COMMAND_CODES
     gcvHAL_SET_FSCALE_VALUE,
     gcvHAL_GET_FSCALE_VALUE,
 
+    gcvHAL_NAME_VIDEO_MEMORY,
+    gcvHAL_IMPORT_VIDEO_MEMORY,
+
     /* Reset time stamp. */
     gcvHAL_QUERY_RESET_TIME_STAMP,
 
+    /* Multi-GPU read/write. */
+    gcvHAL_READ_REGISTER_EX,
+    gcvHAL_WRITE_REGISTER_EX,
+
     /* Sync point operations. */
     gcvHAL_SYNC_POINT,
 
     /* Create native fence and return its fd. */
     gcvHAL_CREATE_NATIVE_FENCE,
 
-    /* Video memory database */
-    gcvHAL_VIDMEM_DATABASE,
+    /* Destory MMU. */
+    gcvHAL_DESTROY_MMU,
+
+    /* Shared buffer. */
+    gcvHAL_SHBUF,
+
+    /* Config power management. */
+    gcvHAL_CONFIG_POWER_MANAGEMENT,
+
+    /* Connect a video node to an OS native fd. */
+    gcvHAL_GET_VIDEO_MEMORY_FD,
 }
 gceHAL_COMMAND_CODES;
 
@@ -222,6 +235,9 @@ typedef struct _gcsHAL_QUERY_CHIP_IDENTITY
     /* Supported minor feature 4 fields. */
     gctUINT32                   chipMinorFeatures4;
 
+    /* Supported minor feature 5 fields. */
+    gctUINT32                   chipMinorFeatures5;
+
     /* Number of streams supported. */
     gctUINT32                   streamCount;
 
@@ -257,6 +273,17 @@ typedef struct _gcsHAL_QUERY_CHIP_IDENTITY
 
     /* Supertile layout style in hardware */
     gctUINT32                   superTileMode;
+
+#if gcdMULTI_GPU
+    /* Number of 3D GPUs */
+    gctUINT32                   gpuCoreCount;
+#endif
+
+    /* Special control bits for 2D chip. */
+    gctUINT32                   chip2DControl;
+
+    /* Product ID */
+    gctUINT32                   productID;
 }
 gcsHAL_QUERY_CHIP_IDENTITY;
 
@@ -384,11 +411,14 @@ typedef struct _gcsHAL_INTERFACE
             /* Type of allocation. */
             IN gceSURF_TYPE             type;
 
+            /* Flag of allocation. */
+            IN gctUINT32                flag;
+
             /* Memory pool to allocate from. */
             IN OUT gcePOOL              pool;
 
-            /* Allocated video memory in gcuVIDMEM_NODE. */
-            OUT gctUINT64               node;
+            /* Allocated video memory. */
+            OUT gctUINT32               node;
         }
         AllocateLinearVideoMemory;
 
@@ -413,58 +443,64 @@ typedef struct _gcsHAL_INTERFACE
             /* Memory pool to allocate from. */
             IN OUT gcePOOL              pool;
 
-            /* Allocated video memory in gcuVIDMEM_NODE. */
-            OUT gctUINT64               node;
+            /* Allocated video memory. */
+            OUT gctUINT32               node;
         }
         AllocateVideoMemory;
 
-        /* gcvHAL_FREE_VIDEO_MEMORY */
-        struct _gcsHAL_FREE_VIDEO_MEMORY
+        /* gcvHAL_RELEASE_VIDEO_MEMORY */
+        struct _gcsHAL_RELEASE_VIDEO_MEMORY
         {
-            /* Allocated video memory in gcuVIDMEM_NODE. */
-            IN gctUINT64        node;
+            /* Allocated video memory. */
+            IN gctUINT32                node;
 
 #ifdef __QNXNTO__
 /* TODO: This is part of the unlock - why is it here? */
             /* Mapped logical address to unmap in user space. */
-            OUT gctUINT64       memory;
+            OUT gctUINT64               memory;
 
             /* Number of bytes to allocated. */
-            OUT gctUINT64       bytes;
+            OUT gctUINT64               bytes;
 #endif
         }
-        FreeVideoMemory;
+        ReleaseVideoMemory;
 
         /* gcvHAL_LOCK_VIDEO_MEMORY */
         struct _gcsHAL_LOCK_VIDEO_MEMORY
         {
-            /* Allocated video memory gcuVIDMEM_NODE gcuVIDMEM_NODE. */
-            IN gctUINT64            node;
+            /* Allocated video memory. */
+            IN gctUINT32                node;
 
             /* Cache configuration. */
             /* Only gcvPOOL_CONTIGUOUS and gcvPOOL_VIRUTAL
             ** can be configured */
-            IN gctBOOL              cacheable;
+            IN gctBOOL                  cacheable;
 
             /* Hardware specific address. */
-            OUT gctUINT32           address;
+            OUT gctUINT32               address;
 
             /* Mapped logical address. */
-            OUT gctUINT64           memory;
+            OUT gctUINT64               memory;
+
+            /* Customer priviate handle*/
+            OUT gctUINT32               gid;
+
+            /* Bus address of a contiguous video node. */
+            OUT gctUINT64               physicalAddress;
         }
         LockVideoMemory;
 
         /* gcvHAL_UNLOCK_VIDEO_MEMORY */
         struct _gcsHAL_UNLOCK_VIDEO_MEMORY
         {
-            /* Allocated video memory in gcuVIDMEM_NODE. */
-            IN gctUINT64            node;
+            /* Allocated video memory. */
+            IN gctUINT64                node;
 
             /* Type of surface. */
-            IN gceSURF_TYPE         type;
+            IN gceSURF_TYPE             type;
 
             /* Flag to unlock surface asynchroneously. */
-            IN OUT gctBOOL          asynchroneous;
+            IN OUT gctBOOL              asynchroneous;
         }
         UnlockVideoMemory;
 
@@ -528,7 +564,13 @@ typedef struct _gcsHAL_INTERFACE
         struct _gcsHAL_EVENT_COMMIT
         {
             /* Event queue in gcsQUEUE. */
-            IN gctUINT64             queue;
+            IN gctUINT64            queue;
+
+#if gcdMULTI_GPU
+            IN gceCORE_3D_MASK     chipEnable;
+
+            IN gceMULTI_GPU_MODE    gpuMode;
+#endif
         }
         Event;
 
@@ -546,6 +588,12 @@ typedef struct _gcsHAL_INTERFACE
 
             /* Event queue in gcsQUEUE. */
             IN gctUINT64            queue;
+
+#if gcdMULTI_GPU
+            IN gceCORE_3D_MASK      chipEnable;
+
+            IN gceMULTI_GPU_MODE    gpuMode;
+#endif
         }
         Commit;
 
@@ -696,15 +744,40 @@ typedef struct _gcsHAL_INTERFACE
         }
         WriteRegisterData;
 
+#if gcdMULTI_GPU
+        /* gcvHAL_READ_REGISTER_EX */
+        struct _gcsHAL_READ_REGISTER_EX
+        {
+            /* Logical address of memory to write data to. */
+            IN gctUINT32            address;
+
+            IN gctUINT32            coreSelect;
+
+            /* Data read. */
+            OUT gctUINT32           data[gcdMULTI_GPU];
+        }
+        ReadRegisterDataEx;
+
+        /* gcvHAL_WRITE_REGISTER_EX */
+        struct _gcsHAL_WRITE_REGISTER_EX
+        {
+            /* Logical address of memory to write data to. */
+            IN gctUINT32            address;
+
+            IN gctUINT32            coreSelect;
+
+            /* Data read. */
+            IN gctUINT32            data[gcdMULTI_GPU];
+        }
+        WriteRegisterDataEx;
+#endif
+
 #if VIVANTE_PROFILER
         /* gcvHAL_GET_PROFILE_SETTING */
         struct _gcsHAL_GET_PROFILE_SETTING
         {
             /* Enable profiling */
             OUT gctBOOL             enable;
-
-            /* The profile file name */
-            OUT gctCHAR             fileName[gcdMAX_PROFILE_FILE_NAME];
         }
         GetProfileSetting;
 
@@ -713,9 +786,6 @@ typedef struct _gcsHAL_INTERFACE
         {
             /* Enable profiling */
             IN gctBOOL              enable;
-
-            /* The profile file name */
-            IN gctCHAR              fileName[gcdMAX_PROFILE_FILE_NAME];
         }
         SetProfileSetting;
 
@@ -736,6 +806,7 @@ typedef struct _gcsHAL_INTERFACE
             /* Context buffer object gckCONTEXT. Just a name. */
             IN gctUINT32                context;
 #endif
+
             /* Data read. */
             OUT gcsPROFILER_COUNTERS    counters;
         }
@@ -749,6 +820,7 @@ typedef struct _gcsHAL_INTERFACE
         }
         RegisterProfileData2D;
 #endif
+
         /* Power management. */
         /* gcvHAL_SET_POWER_MANAGEMENT_STATE */
         struct _gcsHAL_SET_POWER_MANAGEMENT
@@ -809,12 +881,10 @@ typedef struct _gcsHAL_INTERFACE
         struct _gcsHAL_CACHE
         {
             IN gceCACHEOPERATION        operation;
-            /* gctHANDLE */
             IN gctUINT64                process;
             IN gctUINT64                logical;
             IN gctUINT64                bytes;
-            /* gcuVIDMEM_NODE_PTR */
-            IN gctUINT64                node;
+            IN gctUINT32                node;
         }
         Cache;
 
@@ -847,25 +917,11 @@ typedef struct _gcsHAL_INTERFACE
             OUT gcuDATABASE_INFO        nonPaged;
             OUT gcuDATABASE_INFO        contiguous;
             OUT gcuDATABASE_INFO        gpuIdle;
-        }
-        Database;
 
-        /* gcvHAL_VIDMEM_DATABASE */
-        struct _gcsHAL_VIDMEM_DATABASE
-        {
-            /* Set to gcvTRUE if you want to query a particular process ID.
-            ** Set to gcvFALSE to query the last detached process. */
-            IN gctBOOL                  validProcessID;
-
-            /* Process ID to query. */
-            IN gctUINT32                processID;
-
-            /* Information. */
-            OUT gcuDATABASE_INFO        vidMemResv;
-            OUT gcuDATABASE_INFO        vidMemCont;
-            OUT gcuDATABASE_INFO        vidMemVirt;
+            /* Detail information about video memory. */
+            OUT gcuDATABASE_INFO        vidMemPool[3];
         }
-        VidMemDatabase;
+        Database;
 
         /* gcvHAL_VERSION */
         struct _gcsHAL_VERSION
@@ -898,11 +954,23 @@ typedef struct _gcsHAL_INTERFACE
         /* gcvHAL_ATTACH */
         struct _gcsHAL_ATTACH
         {
-            /* Context buffer object gckCONTEXT. Just a name. */
+            /* Handle of context buffer object. */
             OUT gctUINT32               context;
 
             /* Number of states in the buffer. */
             OUT gctUINT64               stateCount;
+
+            /* Map context buffer to user or not. */
+            IN gctBOOL                  map;
+
+            /* Physical of context buffer. */
+            OUT gctUINT32               physicals[2];
+
+            /* Physical of context buffer. */
+            OUT gctUINT64               logicals[2];
+
+            /* Bytes of context buffer. */
+            OUT gctUINT32               bytes;
         }
         Attach;
 
@@ -933,61 +1001,32 @@ typedef struct _gcsHAL_INTERFACE
         SetTimeOut;
 
 #if gcdENABLE_VG
-               /* gcvHAL_COMMIT */
-               struct _gcsHAL_VGCOMMIT
-               {
-                       /* Context buffer in gcsVGCONTEXT. */
-                       IN gctUINT64                    context;
-
-                       /* Command queue in gcsVGCMDQUEUE. */
-                       IN gctUINT64                    queue;
-
-                       /* Number of entries in the queue. */
-                       IN gctUINT                      entryCount;
-
-                       /* Task table in gcsTASK_MASTER_TABLE. */
-                       IN gctUINT64                    taskTable;
-               }
-               VGCommit;
-
-               /* gcvHAL_QUERY_COMMAND_BUFFER */
-               struct _gcsHAL_QUERY_COMMAND_BUFFER
-               {
-                       /* Command buffer attributes. */
-                       OUT gcsCOMMAND_BUFFER_INFO      information;
-               }
-               QueryCommandBuffer;
-
-#endif
-
-        struct _gcsHAL_GET_SHARED_INFO
+        /* gcvHAL_COMMIT */
+        struct _gcsHAL_VGCOMMIT
         {
-            /* Process id. */
-            IN gctUINT32            pid;
+            /* Context buffer. gcsVGCONTEXT_PTR */
+            IN gctUINT64                context;
 
-            /* Data id. */
-            IN gctUINT32            dataId;
+            /* Command queue. gcsVGCMDQUEUE_PTR */
+            IN gctUINT64                queue;
 
-            /* Data size. */
-            IN gctSIZE_T            bytes;
+            /* Number of entries in the queue. */
+            IN gctUINT                  entryCount;
 
-            /* Pointer to save the shared data. */
-            OUT gctPOINTER          data;
+            /* Task table. gcsTASK_MASTER_TABLE_PTR */
+            IN gctUINT64                taskTable;
         }
-        GetSharedInfo;
+        VGCommit;
 
-        struct _gcsHAL_SET_SHARED_INFO
+        /* gcvHAL_QUERY_COMMAND_BUFFER */
+        struct _gcsHAL_QUERY_COMMAND_BUFFER
         {
-            /* Data id. */
-            IN gctUINT32            dataId;
-
-            /* Data to be shared. */
-            IN gctPOINTER           data;
-
-            /* Data size. */
-            IN gctSIZE_T            bytes;
+            /* Command buffer attributes. */
+            OUT gcsCOMMAND_BUFFER_INFO    information;
         }
-        SetSharedInfo;
+        QueryCommandBuffer;
+
+#endif
 
         struct _gcsHAL_SET_FSCALE_VALUE
         {
@@ -1003,6 +1042,20 @@ typedef struct _gcsHAL_INTERFACE
         }
         GetFscaleValue;
 
+        struct _gcsHAL_NAME_VIDEO_MEMORY
+        {
+            IN gctUINT32            handle;
+            OUT gctUINT32           name;
+        }
+        NameVideoMemory;
+
+        struct _gcsHAL_IMPORT_VIDEO_MEMORY
+        {
+            IN gctUINT32            name;
+            OUT gctUINT32           handle;
+        }
+        ImportVideoMemory;
+
         struct _gcsHAL_QUERY_RESET_TIME_STAMP
         {
             OUT gctUINT64           timeStamp;
@@ -1035,6 +1088,41 @@ typedef struct _gcsHAL_INTERFACE
 
         }
         CreateNativeFence;
+
+        struct _gcsHAL_DESTROY_MMU
+        {
+            /* Mmu object. */
+            IN gctUINT64                mmu;
+        }
+        DestroyMmu;
+
+        struct _gcsHAL_SHBUF
+        {
+            gceSHBUF_COMMAND_CODES      command;
+
+            /* Shared buffer. */
+            IN OUT gctUINT64            id;
+
+            /* User data to be shared. */
+            IN gctUINT64                data;
+
+            /* Data size. */
+            IN OUT gctUINT32            bytes;
+        }
+        ShBuf;
+
+        struct _gcsHAL_CONFIG_POWER_MANAGEMENT
+        {
+            IN gctBOOL                  enable;
+        }
+        ConfigPowerManagement;
+
+        struct _gcsHAL_GET_VIDEO_MEMORY_FD
+        {
+            IN gctUINT32            handle;
+            OUT gctINT              fd;
+        }
+        GetVideoMemoryFd;
     }
     u;
 }
index b54752f8be6e6d11b4420c0c0f74d3483ce45648..d4e4b3eb67c7af5b760e8000dc60bda5218d3623 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -56,37 +56,37 @@ typedef struct _gcsCOMMAND_BUFFER_INFO
 
     /* Alignment and mask for the buffer address. */
     gctUINT                     addressMask;
-    gctSIZE_T                   addressAlignment;
+    gctUINT32                    addressAlignment;
 
     /* Alignment for each command. */
-    gctSIZE_T                   commandAlignment;
+    gctUINT32                   commandAlignment;
 
     /* Number of bytes required by the STATE command. */
-    gctSIZE_T                   stateCommandSize;
+    gctUINT32                   stateCommandSize;
 
     /* Number of bytes required by the RESTART command. */
-    gctSIZE_T                   restartCommandSize;
+    gctUINT32                   restartCommandSize;
 
     /* Number of bytes required by the FETCH command. */
-    gctSIZE_T                   fetchCommandSize;
+    gctUINT32                   fetchCommandSize;
 
     /* Number of bytes required by the CALL command. */
-    gctSIZE_T                   callCommandSize;
+    gctUINT32                   callCommandSize;
 
     /* Number of bytes required by the RETURN command. */
-    gctSIZE_T                   returnCommandSize;
+    gctUINT32                   returnCommandSize;
 
     /* Number of bytes required by the EVENT command. */
-    gctSIZE_T                   eventCommandSize;
+    gctUINT32                   eventCommandSize;
 
     /* Number of bytes required by the END command. */
-    gctSIZE_T                   endCommandSize;
+    gctUINT32                   endCommandSize;
 
     /* Number of bytes reserved at the tail of a static command buffer. */
-    gctSIZE_T                   staticTailSize;
+    gctUINT32                   staticTailSize;
 
     /* Number of bytes reserved at the tail of a dynamic command buffer. */
-    gctSIZE_T                   dynamicTailSize;
+    gctUINT32                   dynamicTailSize;
 }
 gcsCOMMAND_BUFFER_INFO;
 
@@ -221,7 +221,7 @@ typedef struct _gcsTASK_FREE_VIDEO_MEMORY
     IN gceTASK                  id;
 
     /* Allocated video memory. */
-    IN gctUINT64                node;
+    IN gctUINT32                node;
 }
 gcsTASK_FREE_VIDEO_MEMORY;
 
index ffd45e8f677b910e9eadcac52819ef6bdddc989f..3f5dfac53012067e996b2e097c743efe923c1273 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -27,56 +27,57 @@ extern "C" {
 #endif
 
 /*
-**     FILE LAYOUT:
+**    FILE LAYOUT:
 **
-**             gcsDUMP_FILE structure
+**        gcsDUMP_FILE structure
 **
-**             gcsDUMP_DATA frame
-**                     gcsDUMP_DATA or gcDUMP_DATA_SIZE records rendingring the frame
-**                     gctUINT8 data[length]
+**        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')
+#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 */
+    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',' '),
+    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',' '),
+    gcvTAG_BUFOBJ                   = gcmCC('b','u','f','o'),
 }
 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. */
+    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. */
+    gceDUMP_TAG             type;        /* Type of record. */
+    gctSIZE_T             length;        /* Number of bytes of data. */
+    gctUINT32             address;    /* Address for the data. */
 }
 gcsDUMP_DATA;
 
index c4347e1e0bbc1dbf9bb49b873153a00604c275a8..1f35873601d23454102069b3555a5062817e4600 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -18,6 +18,7 @@
 *
 *****************************************************************************/
 
+
 #ifndef __gc_hal_eglplatform_h_
 #define __gc_hal_eglplatform_h_
 
@@ -51,22 +52,30 @@ typedef struct _DFBPixmap *  HALNativePixmapType;
 #elif defined(LINUX) && defined(EGL_API_FB) && !defined(__APPLE__)
 
 #if defined(EGL_API_WL)
+
+#if defined(__GNUC__)
+#   define inline            __inline__  /* GNU keyword. */
+#endif
+
 /* Wayland platform. */
-#include "wayland-server.h"
 #include <wayland-egl.h>
 
-#define WL_EGL_NUM_BACKBUFFERS 2
+#define WL_EGL_NUM_BACKBUFFERS 3
 
 typedef struct _gcsWL_VIV_BUFFER
 {
-   struct wl_buffer wl_buffer;
+   struct wl_resource *wl_buffer;
    gcoSURF surface;
+   gctINT32 width, height;
 } gcsWL_VIV_BUFFER;
 
 typedef struct _gcsWL_EGL_DISPLAY
 {
    struct wl_display* wl_display;
    struct wl_viv* wl_viv;
+   struct wl_registry *registry;
+   struct wl_event_queue    *wl_queue;
+   gctINT swapInterval;
 } gcsWL_EGL_DISPLAY;
 
 typedef struct _gcsWL_EGL_BUFFER_INFO
@@ -79,6 +88,9 @@ typedef struct _gcsWL_EGL_BUFFER_INFO
    gcePOOL pool;
    gctUINT bytes;
    gcoSURF surface;
+   gcoSURF attached_surface;
+   gctINT32 invalidate;
+   gctBOOL locked;
 } gcsWL_EGL_BUFFER_INFO;
 
 typedef struct _gcsWL_EGL_BUFFER
@@ -89,19 +101,24 @@ typedef struct _gcsWL_EGL_BUFFER
 
 typedef struct _gcsWL_EGL_WINDOW_INFO
 {
+   gctINT32 dx;
+   gctINT32 dy;
    gctUINT width;
    gctUINT height;
+   gctINT32 attached_width;
+   gctINT32 attached_height;
    gceSURF_FORMAT format;
    gctUINT bpp;
 } gcsWL_EGL_WINDOW_INFO;
 
 struct wl_egl_window
 {
+   gcsWL_EGL_DISPLAY* display;
    gcsWL_EGL_BUFFER backbuffers[WL_EGL_NUM_BACKBUFFERS];
    gcsWL_EGL_WINDOW_INFO info;
    gctUINT current;
    struct wl_surface* surface;
-   struct wl_callback* pending;
+   struct wl_callback* frame_callback;
 };
 
 typedef void*   HALNativeDisplayType;
@@ -278,6 +295,12 @@ gcoOS_SetSwapInterval(
     IN gctINT Interval
 );
 
+gceSTATUS
+gcoOS_SetSwapIntervalEx(
+    IN HALNativeDisplayType Display,
+    IN gctINT Interval,
+    IN gctPOINTER localDisplay);
+
 gceSTATUS
 gcoOS_GetSwapInterval(
     IN HALNativeDisplayType Display,
@@ -609,8 +632,41 @@ gcoOS_SwapBuffers(
     OUT gctUINT *Width,
     OUT gctUINT *Height
     );
+
+#ifdef EGL_API_DRI
+gceSTATUS
+gcoOS_ResizeWindow(
+    IN gctPOINTER localDisplay,
+    IN HALNativeWindowType Drawable,
+    IN gctUINT Width,
+    IN gctUINT Height)
+    ;
+
+#ifdef USE_FREESCALE_EGL_ACCEL
+gceSTATUS
+gcoOS_SwapBuffersGeneric_Async(
+    IN gctPOINTER localDisplay,
+    IN HALNativeWindowType Drawable,
+    IN gcoSURF RenderTarget,
+    IN gcoSURF ResolveTarget,
+    IN gctPOINTER ResolveBits,
+    OUT gctUINT *Width,
+    OUT gctUINT *Height,
+    IN void * resolveRect
+    );
+
+gceSTATUS
+gcoOS_DrawSurface(
+    IN gctPOINTER localDisplay,
+    IN HALNativeWindowType Drawable
+    );
+#endif
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* __gc_hal_eglplatform_h_ */
+
index 4f5c3cea4c2cc0346731b5fa1b2c678a8c76c1d6..10da3af527de2024b4d6d1a2683552c6931b76f9 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -32,20 +32,20 @@ extern "C" {
 
 typedef enum _halEventType
 {
-       /* Keyboard event. */
+    /* Keyboard event. */
     HAL_KEYBOARD,
 
-       /* Mouse move event. */
+    /* Mouse move event. */
     HAL_POINTER,
 
-       /* Mouse button event. */
+    /* Mouse button event. */
     HAL_BUTTON,
 
-       /* Application close event. */
-       HAL_CLOSE,
+    /* Application close event. */
+    HAL_CLOSE,
 
-       /* Application window has been updated. */
-       HAL_WINDOW_UPDATE
+    /* Application window has been updated. */
+    HAL_WINDOW_UPDATE
 }
 halEventType;
 
@@ -171,10 +171,10 @@ halKeys;
 /* Structure that defined keyboard mapping. */
 typedef struct _halKeyMap
 {
-       /* Normal key. */
+    /* Normal key. */
     halKeys normal;
 
-       /* Extended key. */
+    /* Extended key. */
     halKeys extended;
 }
 halKeyMap;
@@ -182,50 +182,50 @@ halKeyMap;
 /* Event structure. */
 typedef struct _halEvent
 {
-       /* Event type. */
+    /* Event type. */
     halEventType type;
 
-       /* Event data union. */
+    /* Event data union. */
     union _halEventData
     {
-               /* Event data for keyboard. */
+        /* Event data for keyboard. */
         struct _halKeyboard
         {
-                       /* Scancode. */
-            halKeys    scancode;
+            /* Scancode. */
+            halKeys scancode;
 
-                       /* ASCII characte of the key pressed. */
-            char       key;
+            /* ASCII characte of the key pressed. */
+            char    key;
 
-                       /* Flag whether the key was pressed (1) or released (0). */
-            char       pressed;
+            /* Flag whether the key was pressed (1) or released (0). */
+            char    pressed;
         }
         keyboard;
 
-               /* Event data for pointer. */
+        /* Event data for pointer. */
         struct _halPointer
         {
-                       /* Current pointer coordinate. */
-            int                x;
-            int                y;
+            /* Current pointer coordinate. */
+            int     x;
+            int     y;
         }
         pointer;
 
-               /* Event data for mouse buttons. */
+        /* Event data for mouse buttons. */
         struct _halButton
         {
-                       /* Left button state. */
-            int                left;
+            /* Left button state. */
+            int     left;
 
-                       /* Middle button state. */
-            int                middle;
+            /* Middle button state. */
+            int     middle;
 
-                       /* Right button state. */
-            int                right;
+            /* Right button state. */
+            int     right;
 
-                       /* Current pointer coordinate. */
-                       int             x;
-                       int             y;
+            /* Current pointer coordinate. */
+            int     x;
+            int     y;
         }
         button;
     }
index 3fb2fe4c2709ad75c9185198f975e35465704257..700f7eb6d76a9171f418f0a2b938904023b02cac 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 #ifndef __gc_hal_engine_h_
 #define __gc_hal_engine_h_
 
-#ifndef VIVANTE_NO_3D
 #include "gc_hal_types.h"
 #include "gc_hal_enum.h"
 
+#if gcdENABLE_3D
 #if gcdENABLE_VG
 #include "gc_hal_engine_vg.h"
 #endif
@@ -44,160 +44,40 @@ typedef struct _gcoTEXTURE *            gcoTEXTURE;
 typedef struct _gcoINDEX *              gcoINDEX;
 typedef struct _gcsVERTEX_ATTRIBUTES *  gcsVERTEX_ATTRIBUTES_PTR;
 typedef struct _gcoVERTEXARRAY *        gcoVERTEXARRAY;
+typedef struct _gcoBUFOBJ *             gcoBUFOBJ;
 
 #define gcdATTRIBUTE_COUNT              16
 
-/******************************************************************************\
-********************************* Enumerations *********************************
-\******************************************************************************/
-
-/* Shading format. */
-typedef enum _gceSHADING
-{
-    gcvSHADING_SMOOTH,
-    gcvSHADING_FLAT_D3D,
-    gcvSHADING_FLAT_OPENGL,
-}
-gceSHADING;
-
-/* Culling modes. */
-typedef enum _gceCULL
-{
-    gcvCULL_NONE,
-    gcvCULL_CCW,
-    gcvCULL_CW,
-}
-gceCULL;
-
-/* Fill modes. */
-typedef enum _gceFILL
-{
-    gcvFILL_POINT,
-    gcvFILL_WIRE_FRAME,
-    gcvFILL_SOLID,
-}
-gceFILL;
-
-/* Compare modes. */
-typedef enum _gceCOMPARE
-{
-    gcvCOMPARE_NEVER,
-    gcvCOMPARE_NOT_EQUAL,
-    gcvCOMPARE_LESS,
-    gcvCOMPARE_LESS_OR_EQUAL,
-    gcvCOMPARE_EQUAL,
-    gcvCOMPARE_GREATER,
-    gcvCOMPARE_GREATER_OR_EQUAL,
-    gcvCOMPARE_ALWAYS,
-    gcvCOMPARE_INVALID = -1
-}
-gceCOMPARE;
-
-/* Stencil modes. */
-typedef enum _gceSTENCIL_MODE
-{
-    gcvSTENCIL_NONE,
-    gcvSTENCIL_SINGLE_SIDED,
-    gcvSTENCIL_DOUBLE_SIDED,
-}
-gceSTENCIL_MODE;
-
-/* Stencil operations. */
-typedef enum _gceSTENCIL_OPERATION
-{
-    gcvSTENCIL_KEEP,
-    gcvSTENCIL_REPLACE,
-    gcvSTENCIL_ZERO,
-    gcvSTENCIL_INVERT,
-    gcvSTENCIL_INCREMENT,
-    gcvSTENCIL_DECREMENT,
-    gcvSTENCIL_INCREMENT_SATURATE,
-    gcvSTENCIL_DECREMENT_SATURATE,
-    gcvSTENCIL_OPERATION_INVALID = -1
-}
-gceSTENCIL_OPERATION;
-
-/* Stencil selection. */
-typedef enum _gceSTENCIL_WHERE
-{
-    gcvSTENCIL_FRONT,
-    gcvSTENCIL_BACK,
-}
-gceSTENCIL_WHERE;
-
-/* Texture addressing selection. */
-typedef enum _gceTEXTURE_WHICH
+typedef enum _gcePROGRAM_STAGE
 {
-    gcvTEXTURE_S,
-    gcvTEXTURE_T,
-    gcvTEXTURE_R,
+    gcvPROGRAM_STAGE_VERTEX   = 0x0,
+    gcvPROGRAM_STAGE_TES      = 0x1,
+    gcvPROGRAM_STAGE_TCS      = 0x2,
+    gcvPROGRAM_STAGE_GEOMETRY = 0x3,
+    gcvPROGRAM_STAGE_FRAGMENT = 0x4,
+    gcvPROGRAM_STAGE_COMPUTE  = 0x5,
+    gcvPROGRAM_STAGE_OPENCL   = 0x6,
+    gcvPROGRAM_STAGE_LAST
 }
-gceTEXTURE_WHICH;
+gcePROGRAM_STAGE;
 
-/* Texture addressing modes. */
-typedef enum _gceTEXTURE_ADDRESSING
+typedef enum _gcePROGRAM_STAGE_BIT
 {
-    gcvTEXTURE_WRAP,
-    gcvTEXTURE_CLAMP,
-    gcvTEXTURE_BORDER,
-    gcvTEXTURE_MIRROR,
-    gcvTEXTURE_MIRROR_ONCE,
+    gcvPROGRAM_STAGE_VERTEX_BIT   = 1 << gcvPROGRAM_STAGE_VERTEX,
+    gcvPROGRAM_STAGE_TES_BIT      = 1 << gcvPROGRAM_STAGE_TES,
+    gcvPROGRAM_STAGE_TCS_BIT      = 1 << gcvPROGRAM_STAGE_TCS,
+    gcvPROGRAM_STAGE_GEOMETRY_BIT = 1 << gcvPROGRAM_STAGE_GEOMETRY,
+    gcvPROGRAM_STAGE_FRAGMENT_BIT = 1 << gcvPROGRAM_STAGE_FRAGMENT,
+    gcvPROGRAM_STAGE_COMPUTE_BIT  = 1 << gcvPROGRAM_STAGE_COMPUTE,
+    gcvPROGRAM_STAGE_OPENCL_BIT   = 1 << gcvPROGRAM_STAGE_OPENCL,
 }
-gceTEXTURE_ADDRESSING;
+gcePROGRAM_STAGE_BIT;
 
-/* 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,
-    gcvPRIMITIVE_RECTANGLE,
-}
-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,
@@ -206,6 +86,31 @@ gcoHAL_QueryShaderCaps(
     OUT gctUINT * Varyings
     );
 
+gceSTATUS
+gcoHAL_QueryShaderCapsEx(
+                         IN gcoHAL Hal,
+                         OUT gctUINT * ShaderCoreCount,
+                         OUT gctUINT * ThreadCount,
+                         OUT gctUINT * VertexInstructionCount,
+                         OUT gctUINT * FragmentInstructionCount
+                         );
+
+gceSTATUS
+gcoHAL_QuerySamplerBase(
+                        IN  gcoHAL Hal,
+                        OUT gctUINT32 * VertexCount,
+                        OUT gctINT_PTR VertexBase,
+                        OUT gctUINT32 * FragmentCount,
+                        OUT gctINT_PTR FragmentBase
+                        );
+
+gceSTATUS
+gcoHAL_QueryUniformBase(
+                                           IN  gcoHAL Hal,
+                                           OUT gctUINT32 * VertexBase,
+                                           OUT gctUINT32 * FragmentBase
+                                           );
+
 gceSTATUS
 gcoHAL_QueryTextureCaps(
     IN gcoHAL Hal,
@@ -239,46 +144,198 @@ gcoHAL_QueryStreamCaps(
 
 /*----------------------------------------------------------------------------*/
 /*--------------------------------- gcoSURF 3D --------------------------------*/
+typedef enum _gceBLIT_FLAG
+{
+    gcvBLIT_FLAG_SKIP_DEPTH_WRITE   = 0x1,
+    gcvBLIT_FLAG_SKIP_STENCIL_WRITE = 0x2,
+} gceBLIT_FLAG;
 
-/* Copy surface. */
-gceSTATUS
-gcoSURF_Copy(
-    IN gcoSURF Surface,
-    IN gcoSURF Source
-    );
+typedef struct _gcsSURF_BLIT_ARGS
+{
+    gcoSURF     srcSurface;
+    gctINT      srcX, srcY, srcZ;
+    gctINT      srcWidth, srcHeight, srcDepth;
+    gcoSURF     dstSurface;
+    gctINT      dstX, dstY, dstZ;
+    gctINT      dstWidth, dstHeight, dstDepth;
+    gctBOOL     xReverse;
+    gctBOOL     yReverse;
+    gctBOOL     scissorTest;
+    gcsRECT     scissor;
+    gctUINT     flags;
+}
+gcsSURF_BLIT_ARGS;
+
+
+
+
+/* Clear flags. */
+typedef enum _gceCLEAR
+{
+    gcvCLEAR_COLOR              = 0x1,
+    gcvCLEAR_DEPTH              = 0x2,
+    gcvCLEAR_STENCIL            = 0x4,
+    gcvCLEAR_HZ                 = 0x8,
+    gcvCLEAR_HAS_VAA            = 0x10,
+    gcvCLEAR_WITH_GPU_ONLY      = 0x100,
+    gcvCLEAR_WITH_CPU_ONLY      = 0x200,
+}
+gceCLEAR;
+
+typedef struct _gcsSURF_CLEAR_ARGS
+{
+    /*
+    ** Color to fill the color portion of the framebuffer when clear
+    ** is called.
+    */
+    struct {
+    gcuVALUE r;
+    gcuVALUE g;
+    gcuVALUE b;
+    gcuVALUE a;
+    /*
+    ** Color has multiple value type so we must specify it.
+    */
+    gceVALUE_TYPE valueType;
+    } color;
+
+    gcuVALUE depth;
+
+    gctUINT  stencil;
+
+
+
+    /*
+    ** stencil bit-wise mask
+    */
+    gctUINT8 stencilMask;
+    /*
+    ** Depth Write Mask
+    */
+    gctBOOL depthMask;
+    /*
+    ** 4-bit channel Mask: ABGR:MSB->LSB
+    */
+    gctUINT8 colorMask;
+    /*
+    ** If ClearRect is NULL, it means full clear
+    */
+    gcsRECT_PTR clearRect;
+    /*
+    ** clear flags
+    */
+    gceCLEAR  flags;
+
+    /*
+    ** Offset in surface to cube/array/3D
+    */
+    gctUINT32 offset;
+
+} gcsSURF_CLEAR_ARGS;
+
+
+typedef gcsSURF_CLEAR_ARGS* gcsSURF_CLEAR_ARGS_PTR;
+
+typedef struct _gscSURF_BLITDRAW_BLIT
+{
+    gcoSURF  srcSurface;
+    gcoSURF  dstSurface;
+    gcsRECT  srcRect;
+    gcsRECT  dstRect;
+    gceTEXTURE_FILTER  filterMode;
+    gctBOOL  xReverse;
+    gctBOOL  yReverse;
+    gctBOOL  scissorEnabled;
+    gcsRECT  scissor;
+}gscSURF_BLITDRAW_BLIT;
+
+
+typedef enum _gceBLITDRAW_TYPE
+{
+    gcvBLITDRAW_CLEAR = 0,
+    gcvBLITDRAW_BLIT  = 1,
+
+    /* last number, not a real type */
+    gcvBLITDRAW_NUM_TYPE
+ }
+gceBLITDRAW_TYPE;
+
+
+typedef struct _gscSURF_BLITDRAW_ARGS
+{
+    /* always the fist member */
+    gceHAL_ARG_VERSION version;
+
+    union _gcsSURF_BLITDRAW_ARGS_UNION
+    {
+       struct _gscSURF_BLITDRAW_ARG_v1
+       {
+            /* Whether it's clear or blit operation, can be extended. */
+            gceBLITDRAW_TYPE type;
+
+            union _gscSURF_BLITDRAW_UNION
+            {
+                gscSURF_BLITDRAW_BLIT blit;
+
+                struct _gscSURF_BLITDRAW_CLEAR
+                {
+                    gcsSURF_CLEAR_ARGS clearArgs;
+                    gcoSURF rtSurface;
+                    gcoSURF dsSurface;
+                } clear;
+            } u;
+       } v1;
+    } uArgs;
+}
+gcsSURF_BLITDRAW_ARGS;
+
+
+typedef struct _gcsSURF_RESOLVE_ARGS
+{
+    gceHAL_ARG_VERSION version;
+    union _gcsSURF_RESOLVE_ARGS_UNION
+    {
+        struct _gcsSURF_RESOLVE_ARG_v1
+        {
+            gctBOOL yInverted;
+        }v1;
+    } uArgs;
+}
+gcsSURF_RESOLVE_ARGS;
 
-/* Clear surface. */
+
+/* CPU Blit with format (including linear <-> tile) conversion*/
 gceSTATUS
-gcoSURF_Clear(
-    IN gcoSURF Surface,
-    IN gctUINT Flags
+gcoSURF_BlitCPU(
+    gcsSURF_BLIT_ARGS* args
     );
 
-/* Set number of samples for a gcoSURF object. */
+
 gceSTATUS
-gcoSURF_SetSamples(
-    IN gcoSURF Surface,
-    IN gctUINT Samples
+gcoSURF_BlitDraw(
+    IN gcsSURF_BLITDRAW_ARGS *args
     );
+#endif  /* gcdENABLE_3D */
+
 
-/* Get the number of samples per pixel. */
+
+#if gcdENABLE_3D
+/* Clear surface function. */
 gceSTATUS
-gcoSURF_GetSamples(
+gcoSURF_Clear(
     IN gcoSURF Surface,
-    OUT gctUINT_PTR Samples
+    IN gcsSURF_CLEAR_ARGS_PTR  clearArg
     );
 
-/* Clear rectangular surface. */
+/* Preserve pixels from source. */
 gceSTATUS
-gcoSURF_ClearRect(
-    IN gcoSURF Surface,
-    IN gctINT Left,
-    IN gctINT Top,
-    IN gctINT Right,
-    IN gctINT Bottom,
-    IN gctUINT Flags
+gcoSURF_Preserve(
+    IN gcoSURF Source,
+    IN gcoSURF Dest,
+    IN gcsRECT_PTR MaskRect
     );
 
+
 /* TO BE REMOVED */
     gceSTATUS
     depr_gcoSURF_Resolve(
@@ -324,7 +381,16 @@ gcoSURF_Resolve(
     );
 
 gceSTATUS
-gcoSURF_IsHWResolveable(
+gcoSURF_ResolveEx(
+    IN gcoSURF SrcSurface,
+    IN gcoSURF DestSurface,
+    IN gcsSURF_RESOLVE_ARGS *args
+    );
+
+
+/* Resolve rectangular area of a surface. */
+gceSTATUS
+gcoSURF_ResolveRect(
     IN gcoSURF SrcSurface,
     IN gcoSURF DestSurface,
     IN gcsPOINT_PTR SrcOrigin,
@@ -334,7 +400,27 @@ gcoSURF_IsHWResolveable(
 
 /* Resolve rectangular area of a surface. */
 gceSTATUS
-gcoSURF_ResolveRect(
+gcoSURF_ResolveRectEx(
+    IN gcoSURF SrcSurface,
+    IN gcoSURF DestSurface,
+    IN gcsPOINT_PTR SrcOrigin,
+    IN gcsPOINT_PTR DestOrigin,
+    IN gcsPOINT_PTR RectSize,
+    IN gcsSURF_RESOLVE_ARGS *args
+    );
+
+
+gceSTATUS
+gcoSURF_GetResolveAlignment(
+    IN gcoSURF Surface,
+    OUT gctUINT *originX,
+    OUT gctUINT *originY,
+    OUT gctUINT *sizeX,
+    OUT gctUINT *sizeY
+    );
+
+gceSTATUS
+gcoSURF_IsHWResolveable(
     IN gcoSURF SrcSurface,
     IN gcoSURF DestSurface,
     IN gcsPOINT_PTR SrcOrigin,
@@ -359,11 +445,26 @@ gcoSURF_IsFormatRenderableAsRT(
     IN gcoSURF Surface
     );
 
-#if gcdSYNC
 gceSTATUS
 gcoSURF_GetFence(
     IN gcoSURF Surface
     );
+
+gceSTATUS
+gcoBUFOBJ_GetFence(
+    IN gcoBUFOBJ bufObj
+    );
+
+gceSTATUS
+gcoBUFOBJ_WaitFence(
+    IN gcoBUFOBJ bufObj
+    );
+
+gceSTATUS
+gcoBUFOBJ_IsFenceEnabled(
+    IN gcoBUFOBJ bufObj
+    );
+
 gceSTATUS
 gcoSURF_WaitFence(
     IN gcoSURF Surface
@@ -388,7 +489,30 @@ gceSTATUS
 gcoINDEX_WaitFence(
     IN gcoINDEX index
     );
-#endif
+
+gceSTATUS
+gcoSURF_3DBlitClearRect(
+    IN gcoSURF Surface,
+    IN gcsSURF_CLEAR_ARGS_PTR ClearArgs
+    );
+
+
+gceSTATUS
+gcoSURF_3DBlitBltRect(
+    IN gcoSURF SrcSurf,
+    IN gcoSURF DestSurf,
+    IN gcsPOINT_PTR SrcOrigin,
+    IN gcsPOINT_PTR DestOrigin,
+    IN gcsPOINT_PTR RectSize
+    );
+
+gceSTATUS
+gcoSURF_3DBlitCopy(
+    IN gctUINT32 SrcAddress,
+    IN gctUINT32 DestAddress,
+    IN gctUINT32 Bytes
+    );
+
 
 /******************************************************************************\
 ******************************** gcoINDEX Object *******************************
@@ -463,7 +587,7 @@ gcoINDEX_Upload(
 gceSTATUS
 gcoINDEX_UploadOffset(
     IN gcoINDEX Index,
-    IN gctUINT32 Offset,
+    IN gctSIZE_T Offset,
     IN gctCONST_POINTER Buffer,
     IN gctSIZE_T Bytes
     );
@@ -512,28 +636,10 @@ gcoINDEX_SetDynamic(
     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
 {
@@ -562,6 +668,13 @@ gco3D_SetAPI(
     IN gceAPI ApiType
     );
 
+/* Get 3D API type. */
+gceSTATUS
+gco3D_GetAPI(
+    IN gco3D Engine,
+    OUT gceAPI * ApiType
+    );
+
 /* Set render target. */
 gceSTATUS
 gco3D_SetTarget(
@@ -576,6 +689,36 @@ gco3D_UnsetTarget(
     IN gcoSURF Surface
     );
 
+gceSTATUS
+gco3D_SetTargetEx(
+    IN gco3D Engine,
+    IN gctUINT32 TargetIndex,
+    IN gcoSURF Surface,
+    IN gctUINT32 LayerIndex
+    );
+
+gceSTATUS
+gco3D_UnsetTargetEx(
+    IN gco3D Engine,
+    IN gctUINT32 TargetIndex,
+    IN gcoSURF Surface
+    );
+
+gceSTATUS
+gco3D_SetTargetOffsetEx(
+    IN gco3D Engine,
+    IN gctUINT32 TargetIndex,
+    IN gctSIZE_T Offset
+    );
+
+
+gceSTATUS
+gco3D_SetPSOutputMapping(
+    IN gco3D Engine,
+    IN gctINT32 * psOutputMapping
+    );
+
+
 /* Set depth buffer. */
 gceSTATUS
 gco3D_SetDepth(
@@ -583,6 +726,12 @@ gco3D_SetDepth(
     IN gcoSURF Surface
     );
 
+gceSTATUS
+gco3D_SetDepthBufferOffset(
+    IN gco3D Engine,
+    IN gctSIZE_T Offset
+    );
+
 /* Unset depth buffer. */
 gceSTATUS
 gco3D_UnsetDepth(
@@ -661,45 +810,6 @@ gco3D_SetClearStencil(
     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(
@@ -879,13 +989,22 @@ gco3D_SetEarlyDepth(
     IN gctBOOL Enable
     );
 
-/* Enable or disable all early depth operations. */
+/* Deprecated: Enable or disable all early depth operations. */
 gceSTATUS
 gco3D_SetAllEarlyDepthModes(
     IN gco3D Engine,
     IN gctBOOL Disable
     );
 
+/* Enable or disable all early depth operations. */
+gceSTATUS
+gco3D_SetAllEarlyDepthModesEx(
+    IN gco3D Engine,
+    IN gctBOOL Disable,
+    IN gctBOOL DisableModify,
+    IN gctBOOL DisablePassZ
+    );
+
 /* Switch dynamic early mode */
 gceSTATUS
 gco3D_SwitchDynamicEarlyDepthMode(
@@ -912,7 +1031,7 @@ typedef struct _gcsSTENCIL_INFO
     gceSTENCIL_MODE         mode;
 
     gctUINT8                maskFront;
-       gctUINT8                maskBack;
+    gctUINT8                maskBack;
     gctUINT8                writeMaskFront;
     gctUINT8                writeMaskBack;
 
@@ -1099,10 +1218,22 @@ gceSTATUS
 gco3D_DrawPrimitives(
     IN gco3D Engine,
     IN gcePRIMITIVE Type,
-    IN gctINT StartVertex,
+    IN gctSIZE_T StartVertex,
     IN gctSIZE_T PrimitiveCount
     );
 
+gceSTATUS
+gco3D_DrawInstancedPrimitives(
+    IN gco3D Engine,
+    IN gcePRIMITIVE Type,
+    IN gctBOOL DrawIndex,
+    IN gctSIZE_T StartVertex,
+    IN gctSIZE_T StartIndex,
+    IN gctSIZE_T PrimitiveCount,
+    IN gctSIZE_T VertexCount,
+    IN gctSIZE_T InstanceCount
+    );
+
 gceSTATUS
 gco3D_DrawPrimitivesCount(
     IN gco3D Engine,
@@ -1127,8 +1258,8 @@ gceSTATUS
 gco3D_DrawIndexedPrimitives(
     IN gco3D Engine,
     IN gcePRIMITIVE Type,
-    IN gctINT BaseVertex,
-    IN gctINT StartIndex,
+    IN gctSIZE_T BaseVertex,
+    IN gctSIZE_T StartIndex,
     IN gctSIZE_T PrimitiveCount
     );
 
@@ -1142,6 +1273,13 @@ gco3D_DrawIndexedPrimitivesOffset(
     IN gctSIZE_T PrimitiveCount
     );
 
+/* Draw a element from pattern */
+gceSTATUS
+gco3D_DrawPattern(
+    IN gco3D Engine,
+    IN gcsFAST_FLUSH_PTR FastFlushInfo
+    );
+
 /* Enable or disable anti-aliasing. */
 gceSTATUS
 gco3D_SetAntiAlias(
@@ -1166,6 +1304,12 @@ gco3D_Semaphore(
     IN gceWHERE To,
     IN gceHOW How);
 
+/* Explicitly flush shader L1 cache */
+gceSTATUS
+gco3D_FlushSHL1Cache(
+    IN gco3D Engine
+    );
+
 /* Set the subpixels center. */
 gceSTATUS
 gco3D_SetCentroids(
@@ -1180,6 +1324,48 @@ gco3D_SetLogicOp(
     IN gctUINT8 Rop
     );
 
+gceSTATUS
+gco3D_SetOQ(
+    IN gco3D Engine,
+    INOUT gctPOINTER * Result,
+    IN gctBOOL Enable
+    );
+
+gceSTATUS
+gco3D_GetOQ(
+    IN gco3D Engine,
+    IN gctPOINTER Result,
+    OUT gctINT64 * Logical
+    );
+
+gceSTATUS
+gco3D_DeleteOQ(
+    IN gco3D Engine,
+    INOUT gctPOINTER Result
+    );
+
+gceSTATUS
+gco3D_SetColorOutCount(
+    IN gco3D Engine,
+    IN gctUINT32 ColorOutCount
+    );
+
+gceSTATUS
+gco3D_Set3DEngine(
+    IN gco3D Engine
+    );
+
+gceSTATUS
+gco3D_UnSet3DEngine(
+    IN gco3D Engine
+    );
+
+gceSTATUS
+gco3D_Get3DEngine(
+    OUT gco3D * Engine
+    );
+
+
 /* OCL thread walker information. */
 typedef struct _gcsTHREAD_WALKER_INFO * gcsTHREAD_WALKER_INFO_PTR;
 typedef struct _gcsTHREAD_WALKER_INFO
@@ -1219,11 +1405,18 @@ gco3D_InvokeThreadWalker(
     IN gcsTHREAD_WALKER_INFO_PTR Info
     );
 
-/* Set w clip and w plane limit value. */
 gceSTATUS
-gco3D_SetWClipEnable(
-       IN gco3D Engine,
-       IN gctBOOL Enable
+gco3D_GetClosestRenderFormat(
+    IN gco3D Engine,
+    IN gceSURF_FORMAT InFormat,
+    OUT gceSURF_FORMAT* OutFormat
+    );
+
+/* Set w clip and w plane limit value. */
+gceSTATUS
+gco3D_SetWClipEnable(
+    IN gco3D Engine,
+    IN gctBOOL Enable
     );
 
 gceSTATUS
@@ -1234,23 +1427,67 @@ gco3D_GetWClipEnable(
 
 gceSTATUS
 gco3D_SetWPlaneLimitF(
-       IN gco3D Engine,
-       IN gctFLOAT Value
+    IN gco3D Engine,
+    IN gctFLOAT Value
     );
 
 gceSTATUS
 gco3D_SetWPlaneLimitX(
-       IN gco3D Engine,
-       IN gctFIXED_POINT Value
+    IN gco3D Engine,
+    IN gctFIXED_POINT Value
     );
 
-
 gceSTATUS
 gco3D_SetWPlaneLimit(
         IN gco3D Engine,
         IN gctFLOAT Value
         );
 
+gceSTATUS
+gco3D_PrimitiveRestart(
+    IN gco3D Engine,
+    IN gctBOOL PrimitiveRestart);
+
+#if gcdSTREAM_OUT_BUFFER
+
+gceSTATUS
+gco3D_QueryStreamOut(
+    IN gco3D Engine,
+    IN gctUINT32 OriginalIndexAddress,
+    IN gctUINT32 OriginalIndexOffset,
+    IN gctUINT32 OriginalIndexCount,
+    OUT gctBOOL_PTR Found
+    );
+
+gceSTATUS
+gco3D_StartStreamOut(
+    IN gco3D Engine,
+    IN gctINT StreamOutStatus,
+    IN gctUINT32 IndexAddress,
+    IN gctUINT32 IndexOffset,
+    IN gctUINT32 IndexCount
+    );
+
+gceSTATUS
+gco3D_StopStreamOut(
+    IN gco3D Engine
+    );
+
+gceSTATUS
+gco3D_ReplayStreamOut(
+    IN gco3D Engine,
+    IN gctUINT32 IndexAddress,
+    IN gctUINT32 IndexOffset,
+    IN gctUINT32 IndexCount
+    );
+
+gceSTATUS
+gco3D_EndStreamOut(
+    IN gco3D Engine
+    );
+
+#endif
+
 /*----------------------------------------------------------------------------*/
 /*-------------------------- gco3D Fragment Processor ------------------------*/
 
@@ -1379,12 +1616,6 @@ gco3D_SetAlphaTextureFunction(
     IN gctINT Scale
     );
 
-/* Invoke OCL thread walker. */
-gceSTATUS
-gcoHARDWARE_InvokeThreadWalker(
-    IN gcsTHREAD_WALKER_INFO_PTR Info
-    );
-
 /******************************************************************************\
 ******************************* gcoTEXTURE Object *******************************
 \******************************************************************************/
@@ -1402,16 +1633,6 @@ typedef enum _gceTEXTURE_FACE
 }
 gceTEXTURE_FACE;
 
-#if gcdFORCE_MIPMAP
-typedef enum
-{
-    gcvForceMipDisabled  = 0,
-    gcvForceMipEnable    = 1,
-    gcvForceMipGenerated = 2,
-    gcvForceMipNever     = 3,
-}gceFORCE_MIPMAP;
-#endif
-
 typedef struct _gcsTEXTURE
 {
     /* Addressing modes. */
@@ -1419,23 +1640,30 @@ typedef struct _gcsTEXTURE
     gceTEXTURE_ADDRESSING       t;
     gceTEXTURE_ADDRESSING       r;
 
+    gceTEXTURE_SWIZZLE          swizzle[gcvTEXTURE_COMPONENT_NUM];
+
     /* Border color. */
-    gctUINT8                    border[4];
+    gctUINT8                    border[gcvTEXTURE_COMPONENT_NUM];
 
     /* Filters. */
     gceTEXTURE_FILTER           minFilter;
     gceTEXTURE_FILTER           magFilter;
     gceTEXTURE_FILTER           mipFilter;
     gctUINT                     anisoFilter;
-    gctBOOL                     forceTopLevel;
-    gctBOOL                     autoMipmap;
-#if gcdFORCE_MIPMAP
-    gceFORCE_MIPMAP             forceMipmap;
-#endif
+
     /* Level of detail. */
-    gctFIXED_POINT              lodBias;
-    gctFIXED_POINT              lodMin;
-    gctFIXED_POINT              lodMax;
+    gctFLOAT                    lodBias;
+    gctFLOAT                    lodMin;
+    gctFLOAT                    lodMax;
+
+    /* base/max level */
+    gctINT32                    baseLevel;
+    gctINT32                    maxLevel;
+
+    /* depth texture comparison */
+    gceTEXTURE_COMPARE_MODE     compareMode;
+    gceCOMPARE                  compareFunc;
+
 }
 gcsTEXTURE, * gcsTEXTURE_PTR;
 
@@ -1446,6 +1674,15 @@ gcoTEXTURE_Construct(
     OUT gcoTEXTURE * Texture
     );
 
+/* Construct a new gcoTEXTURE object with type information. */
+gceSTATUS
+gcoTEXTURE_ConstructEx(
+    IN gcoHAL Hal,
+    IN gceTEXTURE_TYPE Type,
+    OUT gcoTEXTURE * Texture
+    );
+
+
 /* Construct a new sized gcoTEXTURE object. */
 gceSTATUS
 gcoTEXTURE_ConstructSized(
@@ -1465,61 +1702,41 @@ gceSTATUS
 gcoTEXTURE_Destroy(
     IN gcoTEXTURE Texture
     );
-#if gcdFORCE_MIPMAP
-gceSTATUS
-gcoTEXTURE_DestroyForceMipmap(
-    IN gcoTEXTURE Texture
-    );
-
-gceSTATUS
-gcoTEXTURE_GetMipLevels(
-    IN gcoTEXTURE Texture,
-    OUT gctINT * levels
-    );
-#endif
-/* Replace a mipmap in gcoTEXTURE object. */
-gceSTATUS
-gcoTEXTURE_ReplaceMipMap(
-    IN gcoTEXTURE Texture,
-    IN gctUINT Level,
-    IN gctUINT Width,
-    IN gctUINT Height,
-    IN gctINT imageFormat,
-    IN gceSURF_FORMAT Format,
-    IN gctUINT Depth,
-    IN gctUINT Faces,
-    IN gcePOOL Pool
-    );
 
 /* Upload data to an gcoTEXTURE object. */
 gceSTATUS
 gcoTEXTURE_Upload(
     IN gcoTEXTURE Texture,
+    IN gctINT MipMap,
     IN gceTEXTURE_FACE Face,
-    IN gctUINT Width,
-    IN gctUINT Height,
+    IN gctSIZE_T Width,
+    IN gctSIZE_T Height,
     IN gctUINT Slice,
     IN gctCONST_POINTER Memory,
-    IN gctINT Stride,
-    IN gceSURF_FORMAT Format
+    IN gctSIZE_T Stride,
+    IN gceSURF_FORMAT Format,
+    IN gceSURF_COLOR_SPACE SrcColorSpace
     );
 
 /* Upload data to an gcoTEXTURE object. */
 gceSTATUS
 gcoTEXTURE_UploadSub(
     IN gcoTEXTURE Texture,
-    IN gctUINT MipMap,
+    IN gctINT MipMap,
     IN gceTEXTURE_FACE Face,
-    IN gctUINT X,
-    IN gctUINT Y,
-    IN gctUINT Width,
-    IN gctUINT Height,
+    IN gctSIZE_T X,
+    IN gctSIZE_T Y,
+    IN gctSIZE_T Width,
+    IN gctSIZE_T Height,
     IN gctUINT Slice,
     IN gctCONST_POINTER Memory,
-    IN gctINT Stride,
-    IN gceSURF_FORMAT Format
+    IN gctSIZE_T Stride,
+    IN gceSURF_FORMAT Format,
+    IN gceSURF_COLOR_SPACE SrcColorSpace,
+    IN gctUINT32 PhysicalAddress
     );
 
+
 /* Upload YUV data to an gcoTEXTURE object. */
 gceSTATUS
 gcoTEXTURE_UploadYUV(
@@ -1537,9 +1754,10 @@ gcoTEXTURE_UploadYUV(
 gceSTATUS
 gcoTEXTURE_UploadCompressed(
     IN gcoTEXTURE Texture,
+    IN gctINT MipMap,
     IN gceTEXTURE_FACE Face,
-    IN gctUINT Width,
-    IN gctUINT Height,
+    IN gctSIZE_T Width,
+    IN gctSIZE_T Height,
     IN gctUINT Slice,
     IN gctCONST_POINTER Memory,
     IN gctSIZE_T Bytes
@@ -1549,25 +1767,17 @@ gcoTEXTURE_UploadCompressed(
 gceSTATUS
 gcoTEXTURE_UploadCompressedSub(
     IN gcoTEXTURE Texture,
-    IN gctUINT MipMap,
+    IN gctINT MipMap,
     IN gceTEXTURE_FACE Face,
-    IN gctUINT XOffset,
-    IN gctUINT YOffset,
-    IN gctUINT Width,
-    IN gctUINT Height,
+    IN gctSIZE_T XOffset,
+    IN gctSIZE_T YOffset,
+    IN gctSIZE_T Width,
+    IN gctSIZE_T Height,
     IN gctUINT Slice,
     IN gctCONST_POINTER Memory,
     IN gctSIZE_T Size
     );
 
-/* GetImageFormat of texture. */
-gceSTATUS
-gcoTEXTURE_GetImageFormat(
-    IN gcoTEXTURE Texture,
-    IN gctUINT MipMap,
-    OUT gctINT *  ImageFormat
-    );
-
 /* Get gcoSURF object for a mipmap level. */
 gceSTATUS
 gcoTEXTURE_GetMipMap(
@@ -1583,41 +1793,59 @@ gcoTEXTURE_GetMipMapFace(
     IN gctUINT MipMap,
     IN gceTEXTURE_FACE Face,
     OUT gcoSURF * Surface,
-    OUT gctUINT32_PTR Offset
+    OUT gctSIZE_T_PTR Offset
+    );
+
+gceSTATUS
+gcoTEXTURE_GetMipMapSlice(
+    IN gcoTEXTURE Texture,
+    IN gctUINT MipMap,
+    IN gctUINT Slice,
+    OUT gcoSURF * Surface,
+    OUT gctSIZE_T_PTR Offset
     );
 
 gceSTATUS
 gcoTEXTURE_AddMipMap(
     IN gcoTEXTURE Texture,
     IN gctINT Level,
-    IN gctINT imageFormat,
+    IN gctINT InternalFormat,
     IN gceSURF_FORMAT Format,
-    IN gctUINT Width,
-    IN gctUINT Height,
-    IN gctUINT Depth,
+    IN gctSIZE_T Width,
+    IN gctSIZE_T Height,
+    IN gctSIZE_T Depth,
     IN gctUINT Faces,
     IN gcePOOL Pool,
     OUT gcoSURF * Surface
     );
 
 gceSTATUS
-gcoTEXTURE_AddMipMapFromClient(
+gcoTEXTURE_AddMipMapWithFlag(
     IN gcoTEXTURE Texture,
-    IN gctINT     Level,
-    IN gcoSURF    Surface
+    IN gctINT Level,
+    IN gctINT InternalFormat,
+    IN gceSURF_FORMAT Format,
+    IN gctSIZE_T Width,
+    IN gctSIZE_T Height,
+    IN gctSIZE_T Depth,
+    IN gctUINT Faces,
+    IN gcePOOL Pool,
+    IN gctBOOL Protected,
+    OUT gcoSURF * Surface
     );
 
 gceSTATUS
-gcoTEXTURE_AddMipMapFromSurface(
+gcoTEXTURE_AddMipMapFromClient(
     IN gcoTEXTURE Texture,
     IN gctINT     Level,
     IN gcoSURF    Surface
     );
 
 gceSTATUS
-gcoTEXTURE_SetMaxLevel(
+gcoTEXTURE_AddMipMapFromSurface(
     IN gcoTEXTURE Texture,
-    IN gctUINT Levels
+    IN gctINT     Level,
+    IN gcoSURF    Surface
     );
 
 gceSTATUS
@@ -1637,6 +1865,11 @@ gcoTEXTURE_Flush(
     IN gcoTEXTURE Texture
     );
 
+gceSTATUS
+gcoTEXTURE_FlushVS(
+    IN gcoTEXTURE Texture
+    );
+
 gceSTATUS
 gcoTEXTURE_QueryCaps(
     IN  gcoHAL    Hal,
@@ -1650,19 +1883,33 @@ gcoTEXTURE_QueryCaps(
     );
 
 gceSTATUS
-gcoTEXTURE_GetTiling(
-    IN gcoTEXTURE Texture,
-    IN gctINT preferLevel,
-       OUT gceTILING * Tiling
+gcoTEXTURE_GetClosestFormat(
+    IN gcoHAL Hal,
+    IN gceSURF_FORMAT InFormat,
+    OUT gceSURF_FORMAT* OutFormat
     );
 
 gceSTATUS
-gcoTEXTURE_GetClosestFormat(
+gcoTEXTURE_GetClosestFormatEx(
     IN gcoHAL Hal,
     IN gceSURF_FORMAT InFormat,
+    IN gceTEXTURE_TYPE TextureType,
     OUT gceSURF_FORMAT* OutFormat
     );
 
+gceSTATUS
+gcoTEXTURE_GetFormatInfo(
+    IN gcoTEXTURE Texture,
+    IN gctINT preferLevel,
+    OUT gcsSURF_FORMAT_INFO_PTR * TxFormatInfo
+    );
+
+gceSTATUS
+gcoTEXTURE_GetTextureFormatName(
+    IN gcsSURF_FORMAT_INFO_PTR TxFormatInfo,
+    OUT gctCONST_STRING * TxName
+    );
+
 gceSTATUS
 gcoTEXTURE_RenderIntoMipMap(
     IN gcoTEXTURE Texture,
@@ -1670,13 +1917,14 @@ gcoTEXTURE_RenderIntoMipMap(
     );
 
 gceSTATUS
-gcoTEXTURE_IsRenderable(
+gcoTEXTURE_RenderIntoMipMap2(
     IN gcoTEXTURE Texture,
-    IN gctUINT Level
+    IN gctINT Level,
+    IN gctBOOL Sync
     );
 
 gceSTATUS
-gcoTEXTURE_IsRenderableEx(
+gcoTEXTURE_IsRenderable(
     IN gcoTEXTURE Texture,
     IN gctUINT Level
     );
@@ -1684,6 +1932,8 @@ gcoTEXTURE_IsRenderableEx(
 gceSTATUS
 gcoTEXTURE_IsComplete(
     IN gcoTEXTURE Texture,
+    IN gcsTEXTURE_PTR Info,
+    IN gctINT BaseLevel,
     IN gctINT MaxLevel
     );
 
@@ -1695,6 +1945,28 @@ gcoTEXTURE_BindTexture(
     IN gcsTEXTURE_PTR Info
     );
 
+gceSTATUS
+gcoTEXTURE_BindTextureEx(
+    IN gcoTEXTURE Texture,
+    IN gctINT Target,
+    IN gctINT Sampler,
+    IN gcsTEXTURE_PTR Info,
+    IN gctINT textureLayer
+    );
+
+gceSTATUS
+gcoTEXTURE_InitParams(
+    IN gcoHAL Hal,
+    IN gcsTEXTURE_PTR TexParams
+    );
+
+gceSTATUS
+gcoTEXTURE_SetDepthTextureFlag(
+    IN gcoTEXTURE Texture,
+    IN gctBOOL  unsized
+    );
+
+
 /******************************************************************************\
 ******************************* gcoSTREAM Object ******************************
 \******************************************************************************/
@@ -1712,9 +1984,26 @@ typedef enum _gceVERTEX_FORMAT
     gcvVERTEX_FLOAT,
     gcvVERTEX_UNSIGNED_INT_10_10_10_2,
     gcvVERTEX_INT_10_10_10_2,
+    gcvVERTEX_UNSIGNED_INT_2_10_10_10_REV,
+    gcvVERTEX_INT_2_10_10_10_REV,
+    /* integer format */
+    gcvVERTEX_INT8,
+    gcvVERTEX_INT16,
+    gcvVERTEX_INT32,
 }
 gceVERTEX_FORMAT;
 
+/* What the SW converting scheme to create temp attrib */
+typedef enum _gceATTRIB_SCHEME
+{
+    gcvATTRIB_SCHEME_KEEP = 0,
+    gcvATTRIB_SCHEME_2_10_10_10_REV_TO_FLOAT,
+    gcvATTRIB_SCHEME_BYTE_TO_INT,
+    gcvATTRIB_SCHEME_SHORT_TO_INT,
+    gcvATTRIB_SCHEME_UBYTE_TO_UINT,
+    gcvATTRIB_SCHEME_USHORT_TO_UINT,
+} gceATTRIB_SCHEME;
+
 gceSTATUS
 gcoSTREAM_Construct(
     IN gcoHAL Hal,
@@ -1730,7 +2019,7 @@ gceSTATUS
 gcoSTREAM_Upload(
     IN gcoSTREAM Stream,
     IN gctCONST_POINTER Buffer,
-    IN gctUINT32 Offset,
+    IN gctSIZE_T Offset,
     IN gctSIZE_T Bytes,
     IN gctBOOL Dynamic
     );
@@ -1741,6 +2030,18 @@ gcoSTREAM_SetStride(
     IN gctUINT32 Stride
     );
 
+gceSTATUS
+gcoSTREAM_Size(
+    IN gcoSTREAM Stream,
+    OUT gctSIZE_T *Size
+    );
+
+gceSTATUS
+gcoSTREAM_Node(
+    IN gcoSTREAM Stream,
+    OUT gcsSURF_NODE_PTR * Node
+    );
+
 gceSTATUS
 gcoSTREAM_Lock(
     IN gcoSTREAM Stream,
@@ -1799,6 +2100,14 @@ gcoSTREAM_CPUCacheOperation(
     IN gceCACHEOPERATION Operation
     );
 
+gceSTATUS
+gcoSTREAM_CPUCacheOperation_Range(
+    IN gcoSTREAM Stream,
+    IN gctSIZE_T Offset,
+    IN gctSIZE_T Length,
+    IN gceCACHEOPERATION Operation
+    );
+
 /******************************************************************************\
 ******************************** gcoVERTEX Object ******************************
 \******************************************************************************/
@@ -1857,6 +2166,61 @@ gcoVERTEX_Bind(
 /*******************************************************************************
 ***** gcoVERTEXARRAY Object ***************************************************/
 
+typedef struct _gcsATTRIBUTE
+{
+    /* Enabled. */
+    gctBOOL             enable;
+
+    /* Number of components. */
+    gctINT              size;
+
+    /* Attribute format. */
+    gceVERTEX_FORMAT    format;
+
+    /* Flag whether the attribute is normalized or not. */
+    gctBOOL             normalized;
+
+    /* Stride of the component. */
+    gctSIZE_T           stride;
+
+    /* Divisor of the attribute */
+    gctUINT             divisor;
+
+    /* Pointer to the attribute data. */
+    gctCONST_POINTER    pointer;
+
+    /* Stream object owning the attribute data. */
+    gcoBUFOBJ           stream;
+
+    /* Generic values for attribute. */
+    gctFLOAT            genericValue[4];
+
+    /* Generic size for attribute. */
+    gctINT              genericSize;
+
+    /* Vertex shader linkage. */
+    gctUINT             linkage;
+
+#if gcdUSE_WCLIP_PATCH
+    /* Does it hold positions? */
+    gctBOOL             isPosition;
+#endif
+
+    /* Index to vertex array */
+    gctINT              arrayIdx;
+
+    gceATTRIB_SCHEME    convertScheme;
+
+    /* Pointer to the temporary buffer to be freed */
+    gcoBUFOBJ           tempStream;
+
+    /* Pointer to the temporary memory to be freed */
+    gctCONST_POINTER    tempMemory;
+}
+gcsATTRIBUTE,
+* gcsATTRIBUTE_PTR;
+
+
 typedef struct _gcsVERTEXARRAY
 {
     /* Enabled. */
@@ -1874,6 +2238,9 @@ typedef struct _gcsVERTEXARRAY
     /* Stride of the component. */
     gctUINT             stride;
 
+    /* Divisor of the attribute */
+    gctUINT             divisor;
+
     /* Pointer to the attribute data. */
     gctCONST_POINTER    pointer;
 
@@ -1889,9 +2256,7 @@ typedef struct _gcsVERTEXARRAY
     /* Vertex shader linkage. */
     gctUINT             linkage;
 
-#if gcdUSE_WCLIP_PATCH
     gctBOOL             isPosition;
-#endif
 }
 gcsVERTEXARRAY,
 * gcsVERTEXARRAY_PTR;
@@ -1908,12 +2273,14 @@ gcoVERTEXARRAY_Destroy(
     );
 
 gceSTATUS
-gcoVERTEXARRAY_Bind(
+gcoVERTEXARRAY_Bind_Ex(
     IN gcoVERTEXARRAY Vertex,
     IN gctUINT32 EnableBits,
     IN gcsVERTEXARRAY_PTR VertexArray,
     IN gctUINT First,
     IN gctSIZE_T Count,
+    IN gctBOOL DrawArraysInstanced,
+    IN gctSIZE_T InstanceCount,
     IN gceINDEX_TYPE IndexType,
     IN gcoINDEX IndexObject,
     IN gctPOINTER IndexMemory,
@@ -1927,16 +2294,49 @@ gcoVERTEXARRAY_Bind(
 #endif
     );
 
-gctUINT
-gcoVERTEXARRAY_GetMaxStream(
-    IN gcoVERTEXARRAY Vertex
-);
+gceSTATUS
+gcoVERTEXARRAY_Bind_Ex2(
+    IN gcoVERTEXARRAY Vertex,
+    IN gctUINT32 EnableBits,
+    IN gcsATTRIBUTE_PTR VertexArray,
+    IN gctSIZE_T First,
+    IN gctSIZE_T Count,
+    IN gctBOOL DrawArraysInstanced,
+    IN gctSIZE_T InstanceCount,
+    IN gceINDEX_TYPE IndexType,
+    IN gcoBUFOBJ IndexObject,
+    IN gctPOINTER IndexMemory,
+    IN OUT gcePRIMITIVE * PrimitiveType,
+#if gcdUSE_WCLIP_PATCH
+    IN OUT gctSIZE_T * PrimitiveCount,
+    IN OUT gctFLOAT * wLimitRms,
+    IN OUT gctBOOL * wLimitDirty,
+#else
+    IN OUT gctUINT * PrimitiveCount,
+#endif
+    IN gctINT VertexInstanceIdLinkage
+    );
 
 gceSTATUS
-gcoVERTEXARRAY_SetMaxStream(
+gcoVERTEXARRAY_Bind(
     IN gcoVERTEXARRAY Vertex,
-    gctUINT maxStreams
-);
+    IN gctUINT32 EnableBits,
+    IN gcsVERTEXARRAY_PTR VertexArray,
+    IN gctUINT First,
+    IN gctSIZE_T Count,
+    IN gceINDEX_TYPE IndexType,
+    IN gcoINDEX IndexObject,
+    IN gctPOINTER IndexMemory,
+    IN OUT gcePRIMITIVE * PrimitiveType,
+#if gcdUSE_WCLIP_PATCH
+    IN OUT gctUINT * PrimitiveCount,
+    IN OUT gctFLOAT * wLimitRms,
+    IN OUT gctBOOL * wLimitDirty
+#else
+    IN OUT gctUINT * PrimitiveCount
+#endif
+    );
+
 /*******************************************************************************
 ***** Composition *************************************************************/
 
@@ -1985,21 +2385,24 @@ gcsCOMPOSITION;
 
 gceSTATUS
 gco3D_ProbeComposition(
-    gctBOOL ResetIfEmpty
+    IN gcoHARDWARE Hardware,
+    IN gctBOOL ResetIfEmpty
     );
 
 gceSTATUS
 gco3D_CompositionBegin(
-    void
+    IN gcoHARDWARE Hardware
     );
 
 gceSTATUS
 gco3D_ComposeLayer(
+    IN gcoHARDWARE Hardware,
     IN gcsCOMPOSITION_PTR Layer
     );
 
 gceSTATUS
 gco3D_CompositionSignals(
+    IN gcoHARDWARE Hardware,
     IN gctHANDLE Process,
     IN gctSIGNAL Signal1,
     IN gctSIGNAL Signal2
@@ -2007,6 +2410,7 @@ gco3D_CompositionSignals(
 
 gceSTATUS
 gco3D_CompositionEnd(
+    IN gcoHARDWARE Hardware,
     IN gcoSURF Target,
     IN gctBOOL Synchronous
     );
@@ -2022,32 +2426,162 @@ gcoHAL_DumpFrameDB(
     gctCONST_STRING Filename OPTIONAL
     );
 
+/******************************************************************************
+**********************gcoBUFOBJ object*****************************************
+*******************************************************************************/
+typedef enum _gceBUFOBJ_TYPE
+{
+    gcvBUFOBJ_TYPE_ARRAY_BUFFER = 1,
+    gcvBUFOBJ_TYPE_ELEMENT_ARRAY_BUFFER  = 2,
+    gcvBUFOBJ_TYPE_GENERIC_BUFFER = 100
+
+} gceBUFOBJ_TYPE;
+
+typedef enum _gceBUFOBJ_USAGE
+{
+    gcvBUFOBJ_USAGE_STREAM_DRAW = 1,
+    gcvBUFOBJ_USAGE_STREAM_READ,
+    gcvBUFOBJ_USAGE_STREAM_COPY,
+    gcvBUFOBJ_USAGE_STATIC_DRAW,
+    gcvBUFOBJ_USAGE_STATIC_READ,
+    gcvBUFOBJ_USAGE_STATIC_COPY,
+    gcvBUFOBJ_USAGE_DYNAMIC_DRAW,
+    gcvBUFOBJ_USAGE_DYNAMIC_READ,
+    gcvBUFOBJ_USAGE_DYNAMIC_COPY,
+
+} gceBUFOBJ_USAGE;
+
+/* Construct a new gcoBUFOBJ object. */
+gceSTATUS
+gcoBUFOBJ_Construct(
+    IN gcoHAL Hal,
+    IN gceBUFOBJ_TYPE Type,
+    OUT gcoBUFOBJ * BufObj
+    );
+
+/* Destroy a gcoBUFOBJ object. */
+gceSTATUS
+gcoBUFOBJ_Destroy(
+    IN gcoBUFOBJ BufObj
+    );
+
+/* Lock pbo in memory. */
+gceSTATUS
+gcoBUFOBJ_Lock(
+    IN gcoBUFOBJ BufObj,
+    OUT gctUINT32 * Address,
+    OUT gctPOINTER * Memory
+    );
+
+/* Lock pbo in memory. */
+gceSTATUS
+gcoBUFOBJ_FastLock(
+    IN gcoBUFOBJ BufObj,
+    OUT gctUINT32 * Address,
+    OUT gctPOINTER * Memory
+    );
+
+/* Unlock pbo that was previously locked with gcoBUFOBJ_Lock. */
 gceSTATUS
-gcoHAL_GetSharedInfo(
-    IN gctUINT32 Pid,
-    IN gctUINT32 DataId,
+gcoBUFOBJ_Unlock(
+    IN gcoBUFOBJ BufObj
+    );
+
+/* Free existing pbo buffer. */
+gceSTATUS
+gcoBUFOBJ_Free(
+    IN gcoBUFOBJ BufObj
+    );
+
+/* Upload data into an pbo buffer. */
+gceSTATUS
+gcoBUFOBJ_Upload(
+    IN gcoBUFOBJ BufObj,
+    IN gctCONST_POINTER Buffer,
+    IN gctSIZE_T Offset,
     IN gctSIZE_T Bytes,
-    OUT gctPOINTER Data
+    IN gceBUFOBJ_USAGE Usage
     );
 
+/* Bind an index object to the hardware. */
 gceSTATUS
-gcoHAL_SetSharedInfo(
-    IN gctUINT32 DataId,
-    IN gctPOINTER Data,
-    IN gctSIZE_T Bytes
+gcoBUFOBJ_IndexBind (
+    IN gcoBUFOBJ Index,
+    IN gceINDEX_TYPE Type,
+    IN gctUINT32 Offset,
+    IN gctSIZE_T Count
     );
 
-#if VIVANTE_PROFILER_CONTEXT
+/* Find min and max index for the index buffer */
 gceSTATUS
-gcoHARDWARE_GetContext(
-    IN gcoHARDWARE Hardware,
-    OUT gctUINT32 * Context
+gcoBUFOBJ_IndexGetRange(
+    IN gcoBUFOBJ Index,
+    IN gceINDEX_TYPE Type,
+    IN gctUINT32 Offset,
+    IN gctUINT32 Count,
+    OUT gctUINT32 * MinimumIndex,
+    OUT gctUINT32 * MaximumIndex
+    );
+
+/*  Sets a buffer object as dirty */
+gceSTATUS
+gcoBUFOBJ_SetDirty(
+    IN gcoBUFOBJ BufObj
+    );
+
+/* Creates a new buffer if needed */
+gceSTATUS
+gcoBUFOBJ_AlignIndexBufferWhenNeeded(
+    IN gcoBUFOBJ BufObj,
+    IN gctSIZE_T Offset,
+    OUT gcoBUFOBJ * AlignedBufObj
+    );
+
+/* Cache operations on whole range */
+gceSTATUS
+gcoBUFOBJ_CPUCacheOperation(
+    IN gcoBUFOBJ BufObj,
+    IN gceCACHEOPERATION Operation
+    );
+
+/* Cache operations on a specified range */
+gceSTATUS
+gcoBUFOBJ_CPUCacheOperation_Range(
+    IN gcoBUFOBJ BufObj,
+    IN gctSIZE_T Offset,
+    IN gctSIZE_T Length,
+    IN gceCACHEOPERATION Operation
+    );
+
+/* Return size of the bufobj */
+gceSTATUS
+gcoBUFOBJ_GetSize(
+    IN gcoBUFOBJ BufObj,
+    OUT gctSIZE_T_PTR Size
+    );
+
+/* Return memory node of the bufobj */
+gceSTATUS
+gcoBUFOBJ_GetNode(
+    IN gcoBUFOBJ BufObj,
+    OUT gcsSURF_NODE_PTR * Node
+    );
+
+/* Handle GPU cache operations */
+gceSTATUS
+gcoBUFOBJ_GPUCacheOperation(
+    gcoBUFOBJ BufObj
+    );
+
+/* Dump buffer. */
+void
+gcoBUFOBJ_Dump(
+    IN gcoBUFOBJ BufObj
     );
-#endif
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* VIVANTE_NO_3D */
+#endif /* gcdENABLE_3D */
 #endif /* __gc_hal_engine_h_ */
index 4bb6772549ff3823a7738b1c09470e6685e785cc..7e98d054c34199f25d6617d84c9ef2e8f8cffb45 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -465,6 +465,12 @@ gcsPATH_DATA;
 gceSTATUS
 gcoHAL_QueryPathStorage(
     IN gcoHAL Hal,
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     OUT gcsPATH_BUFFER_INFO_PTR Information
     );
 
@@ -472,6 +478,12 @@ gcoHAL_QueryPathStorage(
 gceSTATUS
 gcoHAL_AssociateCompletion(
     IN gcoHAL Hal,
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcsPATH_DATA_PTR PathData
     );
 
@@ -479,6 +491,12 @@ gcoHAL_AssociateCompletion(
 gceSTATUS
 gcoHAL_DeassociateCompletion(
     IN gcoHAL Hal,
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcsPATH_DATA_PTR PathData
     );
 
@@ -486,6 +504,12 @@ gcoHAL_DeassociateCompletion(
 gceSTATUS
 gcoHAL_CheckCompletion(
     IN gcoHAL Hal,
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcsPATH_DATA_PTR PathData
     );
 
@@ -493,6 +517,12 @@ gcoHAL_CheckCompletion(
 gceSTATUS
 gcoHAL_WaitCompletion(
     IN gcoHAL Hal,
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcsPATH_DATA_PTR PathData
     );
 
@@ -500,12 +530,25 @@ gcoHAL_WaitCompletion(
 gceSTATUS
 gcoHAL_Flush(
     IN gcoHAL Hal
+#if GC355_PROFILER
+    ,
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth
+#endif
     );
 
 /* Split a harwdare address into pool and offset. */
 gceSTATUS
 gcoHAL_SplitAddress(
     IN gcoHAL Hal,
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctUINT32 Address,
     OUT gcePOOL * Pool,
     OUT gctUINT32 * Offset
@@ -515,6 +558,12 @@ gcoHAL_SplitAddress(
 gceSTATUS
 gcoHAL_CombineAddress(
     IN gcoHAL Hal,
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcePOOL Pool,
     IN gctUINT32 Offset,
     OUT gctUINT32 * Address
@@ -524,30 +573,54 @@ gcoHAL_CombineAddress(
 gceSTATUS
 gcoHAL_ScheduleVideoMemory(
     IN gcoHAL Hal,
-    IN gctUINT64 Node
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
+    IN gctUINT32 Node
     );
 
 /* Free linear video memory allocated with gcoHAL_AllocateLinearVideoMemory. */
 gceSTATUS
 gcoHAL_FreeVideoMemory(
     IN gcoHAL Hal,
-    IN gctUINT64 Node
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
+    IN gctUINT32 Node
     );
 
 /* Query command buffer attributes. */
 gceSTATUS
 gcoHAL_QueryCommandBuffer(
     IN gcoHAL Hal,
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     OUT gcsCOMMAND_BUFFER_INFO_PTR Information
     );
 /* Allocate and lock linear video memory. */
 gceSTATUS
 gcoHAL_AllocateLinearVideoMemory(
     IN gcoHAL Hal,
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctUINT Size,
     IN gctUINT Alignment,
     IN gcePOOL Pool,
-    OUT gctUINT64 * Node,
+    OUT gctUINT32 * Node,
     OUT gctUINT32 * Address,
     OUT gctPOINTER * Memory
     );
@@ -556,6 +629,12 @@ gcoHAL_AllocateLinearVideoMemory(
 gceSTATUS
 gcoHAL_GetAlignedSurfaceSize(
     IN gcoHAL Hal,
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gceSURF_TYPE Type,
     IN OUT gctUINT32_PTR Width,
     IN OUT gctUINT32_PTR Height
@@ -564,9 +643,15 @@ gcoHAL_GetAlignedSurfaceSize(
 gceSTATUS
 gcoHAL_ReserveTask(
     IN gcoHAL Hal,
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gceBLOCK Block,
     IN gctUINT TaskCount,
-    IN gctSIZE_T Bytes,
+    IN gctUINT32 Bytes,
     OUT gctPOINTER * Memory
     );
 /******************************************************************************\
@@ -577,23 +662,69 @@ gcoHAL_ReserveTask(
 **
 **  The gcoVG object abstracts the VG hardware pipe.
 */
+#if GC355_PROFILER
+void
+gcoVG_ProfilerEnableDisable(
+    IN gcoVG Vg,
+    IN gctUINT enableGetAPITimes,
+    IN gctFILE apiTimeFile
+    );
+
+void
+gcoVG_ProfilerTreeDepth(
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth
+    );
+
+void
+gcoVG_ProfilerSetStates(
+    IN gcoVG Vg,
+    IN gctUINT treeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth
+    );
+#endif
 
 gctBOOL
 gcoVG_IsMaskSupported(
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gceSURF_FORMAT Format
     );
 
 gctBOOL
 gcoVG_IsTargetSupported(
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gceSURF_FORMAT Format
     );
 
 gctBOOL
 gcoVG_IsImageSupported(
+#if GC355_PROFILER
+    IN gcoVG Vg,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gceSURF_FORMAT Format
     );
 
 gctUINT8 gcoVG_PackColorComponent(
+#if GC355_PROFILER
+    gcoVG Vg,
+    gctUINT TreeDepth,
+    gctUINT saveLayerTreeDepth,
+    gctUINT varTreeDepth,
+#endif
     gctFLOAT Value
     );
 
@@ -606,64 +737,121 @@ gcoVG_Construct(
 gceSTATUS
 gcoVG_Destroy(
     IN gcoVG Vg
+#if GC355_PROFILER
+    ,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth
+#endif
     );
 
 gceSTATUS
 gcoVG_SetTarget(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcoSURF Target
     );
 
 gceSTATUS
 gcoVG_UnsetTarget(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcoSURF Surface
     );
 
 gceSTATUS
 gcoVG_SetUserToSurface(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctFLOAT UserToSurface[9]
     );
 
 gceSTATUS
 gcoVG_SetSurfaceToImage(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctFLOAT SurfaceToImage[9]
     );
 
 gceSTATUS
 gcoVG_EnableMask(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctBOOL Enable
     );
 
 gceSTATUS
 gcoVG_SetMask(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcoSURF Mask
     );
 
 gceSTATUS
 gcoVG_UnsetMask(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcoSURF Surface
     );
 
 gceSTATUS
 gcoVG_FlushMask(
     IN gcoVG Vg
+#if GC355_PROFILER
+    ,
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth
+#endif
     );
 
 gceSTATUS
 gcoVG_EnableScissor(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctBOOL Enable
     );
 
 gceSTATUS
 gcoVG_SetScissor(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctSIZE_T RectangleCount,
     IN gcsVG_RECT_PTR Rectangles
     );
@@ -671,18 +859,33 @@ gcoVG_SetScissor(
 gceSTATUS
 gcoVG_EnableColorTransform(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctBOOL Enable
     );
 
 gceSTATUS
 gcoVG_SetColorTransform(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctFLOAT ColorTransform[8]
     );
 
 gceSTATUS
 gcoVG_SetTileFillColor(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctFLOAT Red,
     IN gctFLOAT Green,
     IN gctFLOAT Blue,
@@ -692,6 +895,11 @@ gcoVG_SetTileFillColor(
 gceSTATUS
 gcoVG_SetSolidPaint(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctUINT8 Red,
     IN gctUINT8 Green,
     IN gctUINT8 Blue,
@@ -701,6 +909,11 @@ gcoVG_SetSolidPaint(
 gceSTATUS
 gcoVG_SetLinearPaint(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctFLOAT Constant,
     IN gctFLOAT StepX,
     IN gctFLOAT StepY
@@ -709,6 +922,11 @@ gcoVG_SetLinearPaint(
 gceSTATUS
 gcoVG_SetRadialPaint(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctFLOAT LinConstant,
     IN gctFLOAT LinStepX,
     IN gctFLOAT LinStepY,
@@ -723,6 +941,11 @@ gcoVG_SetRadialPaint(
 gceSTATUS
 gcoVG_SetPatternPaint(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctFLOAT UConstant,
     IN gctFLOAT UStepX,
     IN gctFLOAT UStepY,
@@ -735,6 +958,11 @@ gcoVG_SetPatternPaint(
 gceSTATUS
 gcoVG_SetColorRamp(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcoSURF ColorRamp,
     IN gceTILE_MODE ColorRampSpreadMode
     );
@@ -742,6 +970,13 @@ gcoVG_SetColorRamp(
 gceSTATUS
 gcoVG_SetPattern(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
+    IN gctINT32 width,
+    IN gctINT32 height,
     IN gcoSURF Pattern,
     IN gceTILE_MODE TileMode,
     IN gceIMAGE_FILTER Filter
@@ -750,24 +985,44 @@ gcoVG_SetPattern(
 gceSTATUS
 gcoVG_SetImageMode(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gceVG_IMAGE Mode
     );
 
 gceSTATUS
 gcoVG_SetBlendMode(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gceVG_BLEND Mode
     );
 
 gceSTATUS
 gcoVG_SetRenderingQuality(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gceRENDER_QUALITY Quality
     );
 
 gceSTATUS
 gcoVG_SetFillRule(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gceFILL_RULE FillRule
     );
 
@@ -780,6 +1035,11 @@ gcoVG_FinalizePath(
 gceSTATUS
 gcoVG_Clear(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctINT X,
     IN gctINT Y,
     IN gctINT Width,
@@ -789,15 +1049,30 @@ gcoVG_Clear(
 gceSTATUS
 gcoVG_DrawPath(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcsPATH_DATA_PTR PathData,
     IN gctFLOAT Scale,
     IN gctFLOAT Bias,
+#if gcdMOVG
+    IN gctUINT32 Width,
+    IN gctUINT32 Height,
+    IN gctFLOAT *Bounds,
+#endif
     IN gctBOOL SoftwareTesselation
     );
 
 gceSTATUS
 gcoVG_DrawImage(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcoSURF Source,
     IN gcsPOINT_PTR SourceOrigin,
     IN gcsPOINT_PTR TargetOrigin,
@@ -808,22 +1083,38 @@ gcoVG_DrawImage(
     IN gctINT TargetY,
     IN gctINT Width,
     IN gctINT Height,
-    IN gctBOOL Mask
+    IN gctBOOL Mask,
+    IN gctBOOL isDrawImage
     );
 
 gceSTATUS
 gcoVG_TesselateImage(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcoSURF Image,
     IN gcsVG_RECT_PTR Rectangle,
     IN gceIMAGE_FILTER Filter,
     IN gctBOOL Mask,
+#if gcdMOVG
+    IN gctBOOL SoftwareTesselation,
+    IN gceVG_BLEND BlendMode
+#else
     IN gctBOOL SoftwareTesselation
+#endif
     );
 
 gceSTATUS
 gcoVG_Blit(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcoSURF Source,
     IN gcoSURF Target,
     IN gcsVG_RECT_PTR SrcRect,
@@ -835,6 +1126,11 @@ gcoVG_Blit(
 gceSTATUS
 gcoVG_ColorMatrix(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcoSURF Source,
     IN gcoSURF Target,
     IN const gctFLOAT * Matrix,
@@ -850,6 +1146,11 @@ gcoVG_ColorMatrix(
 gceSTATUS
 gcoVG_SeparableConvolve(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcoSURF Source,
     IN gcoSURF Target,
     IN gctINT KernelWidth,
@@ -875,6 +1176,11 @@ gcoVG_SeparableConvolve(
 gceSTATUS
 gcoVG_GaussianBlur(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gcoSURF Source,
     IN gcoSURF Target,
     IN gctFLOAT StdDeviationX,
@@ -894,6 +1200,11 @@ gcoVG_GaussianBlur(
 gceSTATUS
 gcoVG_EnableDither(
     IN gcoVG Vg,
+#if GC355_PROFILER
+    IN gctUINT TreeDepth,
+    IN gctUINT saveLayerTreeDepth,
+    IN gctUINT varTreeDepth,
+#endif
     IN gctBOOL Enable
     );
 
index 1d19882217defca120bdc2058f5edbb4dbc39baf..d20f00774b98710c3bce0d549b728ec948d914a0 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -29,15 +29,19 @@ extern "C" {
 /* Chip models. */
 typedef enum _gceCHIPMODEL
 {
+    gcv200  = 0x0200,
     gcv300  = 0x0300,
     gcv320  = 0x0320,
+    gcv328  = 0x0328,
     gcv350  = 0x0350,
     gcv355  = 0x0355,
     gcv400  = 0x0400,
     gcv410  = 0x0410,
     gcv420  = 0x0420,
+    gcv428  = 0x0428,
     gcv450  = 0x0450,
     gcv500  = 0x0500,
+    gcv520  = 0x0520,
     gcv530  = 0x0530,
     gcv600  = 0x0600,
     gcv700  = 0x0700,
@@ -45,9 +49,16 @@ typedef enum _gceCHIPMODEL
     gcv860  = 0x0860,
     gcv880  = 0x0880,
     gcv1000 = 0x1000,
+    gcv1500 = 0x1500,
     gcv2000 = 0x2000,
     gcv2100 = 0x2100,
+    gcv2200 = 0x2200,
+    gcv2500 = 0x2500,
+    gcv3000 = 0x3000,
     gcv4000 = 0x4000,
+    gcv5000 = 0x5000,
+    gcv5200 = 0x5200,
+    gcv6400 = 0x6400,
 }
 gceCHIPMODEL;
 
@@ -74,7 +85,7 @@ typedef enum _gceFEATURE
     gcvFEATURE_YUY2_AVERAGING,
     gcvFEATURE_FLIP_Y,
     gcvFEATURE_EARLY_Z,
-    gcvFEATURE_Z_COMPRESSION,
+    gcvFEATURE_COMPRESSION,
     gcvFEATURE_MSAA,
     gcvFEATURE_SPECIAL_ANTI_ALIASING,
     gcvFEATURE_SPECIAL_MSAA_LOD,
@@ -100,9 +111,11 @@ typedef enum _gceFEATURE
     gcvFEATURE_VG_DOUBLE_BUFFER,
     gcvFEATURE_MC20,
     gcvFEATURE_SUPER_TILED,
+    gcvFEATURE_FAST_CLEAR_FLUSH,
     gcvFEATURE_2D_FILTERBLIT_PLUS_ALPHABLEND,
     gcvFEATURE_2D_DITHER,
     gcvFEATURE_2D_A8_TARGET,
+    gcvFEATURE_2D_A8_NO_ALPHA,
     gcvFEATURE_2D_FILTERBLIT_FULLROTATION,
     gcvFEATURE_2D_BITBLIT_FULLROTATION,
     gcvFEATURE_WIDE_LINE,
@@ -125,51 +138,198 @@ typedef enum _gceFEATURE
     gcvFEATURE_TEXTURE_10_10_10_2,
     gcvFEATURE_TEXTURE_ANISOTROPIC_FILTERING,
     gcvFEATURE_TEXTURE_FLOAT_HALF_FLOAT,
-       gcvFEATURE_2D_ROTATION_STALL_FIX,
+    gcvFEATURE_2D_ROTATION_STALL_FIX,
     gcvFEATURE_2D_MULTI_SOURCE_BLT_EX,
-       gcvFEATURE_BUG_FIXES10,
+    gcvFEATURE_BUG_FIXES10,
     gcvFEATURE_2D_MINOR_TILING,
     /* Supertiled compressed textures are supported. */
     gcvFEATURE_TEX_COMPRRESSION_SUPERTILED,
     gcvFEATURE_FAST_MSAA,
     gcvFEATURE_BUG_FIXED_INDEXED_TRIANGLE_STRIP,
-    gcvFEATURE_TEXTURE_TILED_READ,
+    gcvFEATURE_TEXTURE_TILE_STATUS_READ,
     gcvFEATURE_DEPTH_BIAS_FIX,
     gcvFEATURE_RECT_PRIMITIVE,
-       gcvFEATURE_BUG_FIXES11,
-       gcvFEATURE_SUPERTILED_TEXTURE,
+    gcvFEATURE_BUG_FIXES11,
+    gcvFEATURE_SUPERTILED_TEXTURE,
     gcvFEATURE_2D_NO_COLORBRUSH_INDEX8,
     gcvFEATURE_RS_YUV_TARGET,
     gcvFEATURE_2D_FC_SOURCE,
-       gcvFEATURE_PE_DITHER_FIX,
+    gcvFEATURE_2D_CC_NOAA_SOURCE,
+    gcvFEATURE_PE_DITHER_FIX,
     gcvFEATURE_2D_YUV_SEPARATE_STRIDE,
     gcvFEATURE_FRUSTUM_CLIP_FIX,
+    gcvFEATURE_TEXTURE_SWIZZLE,
+    gcvFEATURE_PRIMITIVE_RESTART,
     gcvFEATURE_TEXTURE_LINEAR,
     gcvFEATURE_TEXTURE_YUV_ASSEMBLER,
+    gcvFEATURE_LINEAR_RENDER_TARGET,
+    gcvFEATURE_SHADER_HAS_ATOMIC,
     gcvFEATURE_SHADER_HAS_INSTRUCTION_CACHE,
+    gcvFEATURE_SHADER_ENHANCEMENTS2,
+    gcvFEATURE_BUG_FIXES7,
+    gcvFEATURE_SHADER_HAS_RTNE,
+    gcvFEATURE_SHADER_HAS_EXTRA_INSTRUCTIONS2,
+    gcvFEATURE_SHADER_ENHANCEMENTS3,
     gcvFEATURE_DYNAMIC_FREQUENCY_SCALING,
-    gcvFEATURE_BUGFIX15,
+    gcvFEATURE_SINGLE_BUFFER,
+    gcvFEATURE_OCCLUSION_QUERY,
     gcvFEATURE_2D_GAMMA,
     gcvFEATURE_2D_COLOR_SPACE_CONVERSION,
     gcvFEATURE_2D_SUPER_TILE_VERSION,
+    gcvFEATURE_HALTI0,
+    gcvFEATURE_HALTI1,
+    gcvFEATURE_HALTI2,
     gcvFEATURE_2D_MIRROR_EXTENSION,
+    gcvFEATURE_TEXTURE_ASTC,
     gcvFEATURE_2D_SUPER_TILE_V1,
     gcvFEATURE_2D_SUPER_TILE_V2,
     gcvFEATURE_2D_SUPER_TILE_V3,
     gcvFEATURE_2D_MULTI_SOURCE_BLT_EX2,
-    gcvFEATURE_ELEMENT_INDEX_UINT,
+    gcvFEATURE_NEW_RA,
+    gcvFEATURE_BUG_FIXED_IMPLICIT_PRIMITIVE_RESTART,
+    gcvFEATURE_PE_MULTI_RT_BLEND_ENABLE_CONTROL,
+    gcvFEATURE_SMALL_MSAA, /* An upgraded version of Fast MSAA */
+    gcvFEATURE_VERTEX_INST_ID_AS_ATTRIBUTE,
+    gcvFEATURE_DUAL_16,
+    gcvFEATURE_BRANCH_ON_IMMEDIATE_REG,
     gcvFEATURE_2D_COMPRESSION,
+    gcvFEATURE_TPC_COMPRESSION,
     gcvFEATURE_2D_OPF_YUV_OUTPUT,
+    gcvFEATURE_2D_FILTERBLIT_A8_ALPHA,
     gcvFEATURE_2D_MULTI_SRC_BLT_TO_UNIFIED_DST_RECT,
+    gcvFEATURE_V2_COMPRESSION_Z16_FIX,
+
+    gcvFEATURE_VERTEX_INST_ID_AS_INTEGER,
     gcvFEATURE_2D_YUV_MODE,
-    gcvFEATURE_DECOMPRESS_Z16,
-       gcvFEATURE_LINEAR_RENDER_TARGET,
-    gcvFEATURE_BUG_FIXES8,
-    gcvFEATURE_HALTI2,
+    gcvFEATURE_ACE,
+    gcvFEATURE_COLOR_COMPRESSION,
+
+    gcvFEATURE_32BPP_COMPONENT_TEXTURE_CHANNEL_SWIZZLE,
+    gcvFEATURE_64BPP_HW_CLEAR_SUPPORT,
+    gcvFEATURE_TX_LERP_PRECISION_FIX,
+    gcvFEATURE_COMPRESSION_V2,
     gcvFEATURE_MMU,
+    gcvFEATURE_COMPRESSION_V3,
+    gcvFEATURE_TX_DECOMPRESSOR,
+    gcvFEATURE_MRT_TILE_STATUS_BUFFER,
+    gcvFEATURE_COMPRESSION_V1,
+    gcvFEATURE_V1_COMPRESSION_Z16_DECOMPRESS_FIX,
+    gcvFEATURE_RTT,
+    gcvFEATURE_GENERICS,
+    gcvFEATURE_2D_ONE_PASS_FILTER,
+    gcvFEATURE_2D_ONE_PASS_FILTER_TAP,
+    gcvFEATURE_2D_POST_FLIP,
+    gcvFEATURE_2D_PIXEL_ALIGNMENT,
+    gcvFEATURE_CORRECT_AUTO_DISABLE_COUNT,
+    gcvFEATURE_CORRECT_AUTO_DISABLE_COUNT_WIDTH,
+
+    gcvFEATURE_HALTI3,
+    gcvFEATURE_EEZ,
+    gcvFEATURE_INTEGER_PIPE_FIX,
+    gcvFEATURE_PSOUTPUT_MAPPING,
+    gcvFEATURE_8K_RT_FIX,
+    gcvFEATURE_TX_TILE_STATUS_MAPPING,
+    gcvFEATURE_SRGB_RT_SUPPORT,
+    gcvFEATURE_UNIFORM_APERTURE,
+    gcvFEATURE_TEXTURE_16K,
+    gcvFEATURE_PA_FARZCLIPPING_FIX,
+    gcvFEATURE_PE_DITHER_COLORMASK_FIX,
+    gcvFEATURE_ZSCALE_FIX,
+
+    gcvFEATURE_MULTI_PIXELPIPES,
+    gcvFEATURE_PIPE_CL,
+
+    gcvFEATURE_BUG_FIXES18,
+
+    gcvFEATURE_UNIFIED_SAMPLERS,
+    gcvFEATURE_CL_PS_WALKER,
+    gcvFEATURE_NEW_HZ,
+
+    gcvFEATURE_TX_FRAC_PRECISION_6BIT,
+    gcvFEATURE_SH_INSTRUCTION_PREFETCH,
+    gcvFEATURE_PROBE,
+
+    gcvFEATURE_BUG_FIXES8,
+    gcvFEATURE_2D_ALL_QUAD,
+
+    gcvFEATURE_SINGLE_PIPE_HALTI1,
+
+    gcvFEATURE_BLOCK_SIZE_16x16,
+
+    gcvFEATURE_NO_USER_CSC,
+    gcvFEATURE_ANDROID_ONLY,
+    gcvFEATURE_HAS_PRODUCTID,
+
+    gcvFEATURE_V2_MSAA_COMP_FIX,
+
+    gcvFEATURE_S8_ONLY_RENDERING,
+
+    gcvFEATURE_SEPARATE_SRC_DST,
+
+    gcvFEATURE_FE_START_VERTEX_SUPPORT,
+    gcvFEATURE_RS_DEPTHSTENCIL_NATIVE_SUPPORT,
+
+    /* Insert features above this comment only. */
+    gcvFEATURE_COUNT                /* Not a feature. */
 }
 gceFEATURE;
 
+/* Chip SWWA. */
+typedef enum _gceSWWA
+{
+    gcvSWWA_601 = 0,
+    gcvSWWA_706,
+    gcvSWWA_1163,
+    gcvSWWA_1165,
+    /* Insert SWWA above this comment only. */
+    gcvSWWA_COUNT                   /* Not a SWWA. */
+}
+gceSWWA;
+
+
+/* Option Set*/
+typedef enum _gceOPITON
+{
+    /* HW setting we take PREFER */
+    gcvOPTION_PREFER_MULTIPIPE_RS = 0,
+    gcvOPTION_PREFER_ZCONVERT_BYPASS =1,
+
+
+    gcvOPTION_HW_NULL = 50,
+    gcvOPTION_PRINT_OPTION = 51,
+
+    gcvOPTION_FBO_PREFER_MEM = 80,
+
+    /* Insert option above this comment only */
+    gcvOPTION_COUNT                     /* Not a OPTION*/
+}
+gceOPTION;
+
+typedef enum _gceFRAMEINFO
+{
+    gcvFRAMEINFO_FRAME_NUM       = 0,
+    gcvFRAMEINFO_DRAW_NUM        = 1,
+    gcvFRAMEINFO_DRAW_DUAL16_NUM = 2,
+    gcvFRAMEINFO_DRAW_FL32_NUM   = 3,
+
+
+    gcvFRAMEINFO_COUNT,
+}
+gceFRAMEINFO;
+
+typedef enum _gceFRAMEINFO_OP
+{
+    gcvFRAMEINFO_OP_INC       = 0,
+    gcvFRAMEINFO_OP_DEC       = 1,
+    gcvFRAMEINFO_OP_ZERO      = 2,
+    gcvFRAMEINFO_OP_GET       = 3,
+
+
+    gcvFRAMEINFO_OP_COUNT,
+}
+gceFRAMEINFO_OP;
+
+
 /* Chip Power Status. */
 typedef enum _gceCHIPPOWERSTATE
 {
@@ -209,7 +369,7 @@ typedef enum _gceSURF_TYPE
     gcvSURF_DEPTH,
     gcvSURF_BITMAP,
     gcvSURF_TILE_STATUS,
-       gcvSURF_IMAGE,
+    gcvSURF_IMAGE,
     gcvSURF_MASK,
     gcvSURF_SCISSOR,
     gcvSURF_HIERARCHICAL_DEPTH,
@@ -220,15 +380,28 @@ typedef enum _gceSURF_TYPE
     gcvSURF_NO_VIDMEM      = 0x200, /* Used to allocate surfaces with no underlying vidmem node.
                                        In Android, vidmem node is allocated by another process. */
     gcvSURF_CACHEABLE      = 0x400, /* Used to allocate a cacheable surface */
+
     gcvSURF_FLIP           = 0x800, /* The Resolve Target the will been flip resolve from RT */
+
     gcvSURF_TILE_STATUS_DIRTY  = 0x1000, /* Init tile status to all dirty */
 
     gcvSURF_LINEAR             = 0x2000,
-    gcvSURF_VG                     = 0x4000,
+
+    gcvSURF_CREATE_AS_TEXTURE  = 0x4000,  /* create it as a texture */
+
+    gcvSURF_PROTECTED_CONTENT  = 0x8000,  /* create it as content protected */
+
+    /* Create it as no compression, valid on when it has tile status. */
+    gcvSURF_NO_COMPRESSION     = 0x40000,
+
+    gcvSURF_CONTIGUOUS         = 0x20000,      /*create it as contiguous */
 
     gcvSURF_TEXTURE_LINEAR               = gcvSURF_TEXTURE
                                          | gcvSURF_LINEAR,
 
+    gcvSURF_RENDER_TARGET_LINEAR         = gcvSURF_RENDER_TARGET
+                                         | gcvSURF_LINEAR,
+
     gcvSURF_RENDER_TARGET_NO_TILE_STATUS = gcvSURF_RENDER_TARGET
                                          | gcvSURF_NO_TILE_STATUS,
 
@@ -268,6 +441,14 @@ typedef enum _gceSURF_USAGE
 }
 gceSURF_USAGE;
 
+typedef enum _gceSURF_COLOR_SPACE
+{
+    gcvSURF_COLOR_SPACE_UNKNOWN,
+    gcvSURF_COLOR_SPACE_LINEAR,
+    gcvSURF_COLOR_SPACE_NONLINEAR,
+}
+gceSURF_COLOR_SPACE;
+
 typedef enum _gceSURF_COLOR_TYPE
 {
     gcvSURF_COLOR_UNKNOWN = 0,
@@ -286,18 +467,35 @@ typedef enum _gceSURF_ROTATION
     gcvSURF_FLIP_X,
     gcvSURF_FLIP_Y,
 
-       gcvSURF_POST_FLIP_X = 0x40000000,
+    gcvSURF_POST_FLIP_X = 0x40000000,
     gcvSURF_POST_FLIP_Y = 0x80000000,
 }
 gceSURF_ROTATION;
 
+/* Surface flag */
+typedef enum _gceSURF_FLAG
+{
+    /* None flag */
+    gcvSURF_FLAG_NONE                = 0x0,
+    /* content is preserved after swap */
+    gcvSURF_FLAG_CONTENT_PRESERVED   = 0x1,
+    /* content is updated after swap*/
+    gcvSURF_FLAG_CONTENT_UPDATED     = 0x2,
+    /* content is y inverted */
+    gcvSURF_FLAG_CONTENT_YINVERTED   = 0x4,
+    /* content is protected */
+    gcvSURF_FLAG_CONTENT_PROTECTED   = 0x8,
+    /* surface is contiguous. */
+    gcvSURF_FLAG_CONTIGUOUS          = (1 << 4),
+}
+gceSURF_FLAG;
+
 typedef enum _gceMIPMAP_IMAGE_FORMAT
 {
     gcvUNKNOWN_MIPMAP_IMAGE_FORMAT  = -2
 }
 gceMIPMAP_IMAGE_FORMAT;
 
-
 /* Surface formats. */
 typedef enum _gceSURF_FORMAT
 {
@@ -336,6 +534,10 @@ typedef enum _gceSURF_FORMAT
     gcvSURF_R8G8B8X8,
     gcvSURF_R5G5B5X1,
     gcvSURF_R4G4B4X4,
+    gcvSURF_X16R16G16B16_2_A8R8G8B8,
+    gcvSURF_A16R16G16B16_2_A8R8G8B8,
+    gcvSURF_A32R32G32B32_2_G32R32F,
+    gcvSURF_A32R32G32B32_4_A8R8G8B8,
 
     /* BGR formats. */
     gcvSURF_A4B4G4R4            = 300,
@@ -360,6 +562,10 @@ typedef enum _gceSURF_FORMAT
     gcvSURF_B4G4R4X4,
     gcvSURF_B5G5R5X1,
     gcvSURF_X2B10G10R10,
+    gcvSURF_B8G8R8_SNORM,
+    gcvSURF_X8B8G8R8_SNORM,
+    gcvSURF_A8B8G8R8_SNORM,
+    gcvSURF_A8B12G12R12_2_A8R8G8B8,
 
     /* Compressed formats. */
     gcvSURF_DXT1                = 400,
@@ -397,6 +603,12 @@ typedef enum _gceSURF_FORMAT
     gcvSURF_D24S8,
     gcvSURF_D32,
     gcvSURF_D24X8,
+    gcvSURF_D32F,
+    gcvSURF_S8D32F,
+    gcvSURF_S8D32F_1_G32R32F,
+    gcvSURF_S8D32F_2_A8R8G8B8,
+    gcvSURF_D24S8_1_A8R8G8B8,
+    gcvSURF_S8,
 
     /* Alpha formats. */
     gcvSURF_A4                  = 700,
@@ -448,6 +660,11 @@ typedef enum _gceSURF_FORMAT
     gcvSURF_X32G32R32,
     gcvSURF_A32R32,
     gcvSURF_RG16,
+    gcvSURF_R8_SNORM,
+    gcvSURF_G8R8_SNORM,
+
+    gcvSURF_R8_1_X8R8G8B8,
+    gcvSURF_G8R8_1_X8R8G8B8,
 
     /* Floating point formats. */
     gcvSURF_R16F                = 1200,
@@ -472,10 +689,159 @@ typedef enum _gceSURF_FORMAT
     gcvSURF_L32F,
     gcvSURF_A32L32F,
     gcvSURF_A32R32F,
-
+    gcvSURF_E5B9G9R9,
+    gcvSURF_B10G11R11F,
+
+    gcvSURF_X16B16G16R16F_2_A8R8G8B8,
+    gcvSURF_A16B16G16R16F_2_A8R8G8B8,
+    gcvSURF_G32R32F_2_A8R8G8B8,
+    gcvSURF_X32B32G32R32F_2_G32R32F,
+    gcvSURF_A32B32G32R32F_2_G32R32F,
+    gcvSURF_X32B32G32R32F_4_A8R8G8B8,
+    gcvSURF_A32B32G32R32F_4_A8R8G8B8,
+
+    gcvSURF_R16F_1_A4R4G4B4,
+    gcvSURF_G16R16F_1_A8R8G8B8,
+    gcvSURF_B16G16R16F_2_A8R8G8B8,
+
+    gcvSURF_R32F_1_A8R8G8B8,
+    gcvSURF_B32G32R32F_3_A8R8G8B8,
+
+    gcvSURF_B10G11R11F_1_A8R8G8B8,
+
+
+    /* sRGB format. */
+    gcvSURF_SBGR8               = 1400,
+    gcvSURF_A8_SBGR8,
+    gcvSURF_X8_SBGR8,
+
+    /* Integer formats. */
+    gcvSURF_R8I                 = 1500,
+    gcvSURF_R8UI,
+    gcvSURF_R16I,
+    gcvSURF_R16UI,
+    gcvSURF_R32I,
+    gcvSURF_R32UI,
+    gcvSURF_X8R8I,
+    gcvSURF_G8R8I,
+    gcvSURF_X8R8UI,
+    gcvSURF_G8R8UI,
+    gcvSURF_X16R16I,
+    gcvSURF_G16R16I,
+    gcvSURF_X16R16UI,
+    gcvSURF_G16R16UI,
+    gcvSURF_X32R32I,
+    gcvSURF_G32R32I,
+    gcvSURF_X32R32UI,
+    gcvSURF_G32R32UI,
+    gcvSURF_X8G8R8I,
+    gcvSURF_B8G8R8I,
+    gcvSURF_X8G8R8UI,
+    gcvSURF_B8G8R8UI,
+    gcvSURF_X16G16R16I,
+    gcvSURF_B16G16R16I,
+    gcvSURF_X16G16R16UI,
+    gcvSURF_B16G16R16UI,
+    gcvSURF_X32G32R32I,
+    gcvSURF_B32G32R32I,
+    gcvSURF_X32G32R32UI,
+    gcvSURF_B32G32R32UI,
+    gcvSURF_X8B8G8R8I,
+    gcvSURF_A8B8G8R8I,
+    gcvSURF_X8B8G8R8UI,
+    gcvSURF_A8B8G8R8UI,
+    gcvSURF_X16B16G16R16I,
+    gcvSURF_A16B16G16R16I,
+    gcvSURF_X16B16G16R16UI,
+    gcvSURF_A16B16G16R16UI,
+    gcvSURF_X32B32G32R32I,
+    gcvSURF_A32B32G32R32I,
+    gcvSURF_X32B32G32R32UI,
+    gcvSURF_A32B32G32R32UI,
+    gcvSURF_A2B10G10R10UI,
+    gcvSURF_G32R32I_2_A8R8G8B8,
+    gcvSURF_G32R32UI_2_A8R8G8B8,
+    gcvSURF_X16B16G16R16I_2_A8R8G8B8,
+    gcvSURF_A16B16G16R16I_2_A8R8G8B8,
+    gcvSURF_X16B16G16R16UI_2_A8R8G8B8,
+    gcvSURF_A16B16G16R16UI_2_A8R8G8B8,
+    gcvSURF_X32B32G32R32I_2_G32R32I,
+    gcvSURF_A32B32G32R32I_2_G32R32I,
+    gcvSURF_X32B32G32R32I_3_A8R8G8B8,
+    gcvSURF_A32B32G32R32I_4_A8R8G8B8,
+    gcvSURF_X32B32G32R32UI_2_G32R32UI,
+    gcvSURF_A32B32G32R32UI_2_G32R32UI,
+    gcvSURF_X32B32G32R32UI_3_A8R8G8B8,
+    gcvSURF_A32B32G32R32UI_4_A8R8G8B8,
+    gcvSURF_A2B10G10R10UI_1_A8R8G8B8,
+    gcvSURF_A8B8G8R8I_1_A8R8G8B8,
+    gcvSURF_A8B8G8R8UI_1_A8R8G8B8,
+    gcvSURF_R8I_1_A4R4G4B4,
+    gcvSURF_R8UI_1_A4R4G4B4,
+    gcvSURF_R16I_1_A4R4G4B4,
+    gcvSURF_R16UI_1_A4R4G4B4,
+    gcvSURF_R32I_1_A8R8G8B8,
+    gcvSURF_R32UI_1_A8R8G8B8,
+    gcvSURF_X8R8I_1_A4R4G4B4,
+    gcvSURF_X8R8UI_1_A4R4G4B4,
+    gcvSURF_G8R8I_1_A4R4G4B4,
+    gcvSURF_G8R8UI_1_A4R4G4B4,
+    gcvSURF_X16R16I_1_A4R4G4B4,
+    gcvSURF_X16R16UI_1_A4R4G4B4,
+    gcvSURF_G16R16I_1_A8R8G8B8,
+    gcvSURF_G16R16UI_1_A8R8G8B8,
+    gcvSURF_X32R32I_1_A8R8G8B8,
+    gcvSURF_X32R32UI_1_A8R8G8B8,
+    gcvSURF_X8G8R8I_1_A4R4G4B4,
+    gcvSURF_X8G8R8UI_1_A4R4G4B4,
+    gcvSURF_B8G8R8I_1_A8R8G8B8,
+    gcvSURF_B8G8R8UI_1_A8R8G8B8,
+    gcvSURF_B16G16R16I_2_A8R8G8B8,
+    gcvSURF_B16G16R16UI_2_A8R8G8B8,
+    gcvSURF_B32G32R32I_3_A8R8G8B8,
+    gcvSURF_B32G32R32UI_3_A8R8G8B8,
+
+    /* ASTC formats. */
+    gcvSURF_ASTC4x4             = 1600,
+    gcvSURF_ASTC5x4,
+    gcvSURF_ASTC5x5,
+    gcvSURF_ASTC6x5,
+    gcvSURF_ASTC6x6,
+    gcvSURF_ASTC8x5,
+    gcvSURF_ASTC8x6,
+    gcvSURF_ASTC8x8,
+    gcvSURF_ASTC10x5,
+    gcvSURF_ASTC10x6,
+    gcvSURF_ASTC10x8,
+    gcvSURF_ASTC10x10,
+    gcvSURF_ASTC12x10,
+    gcvSURF_ASTC12x12,
+    gcvSURF_ASTC4x4_SRGB,
+    gcvSURF_ASTC5x4_SRGB,
+    gcvSURF_ASTC5x5_SRGB,
+    gcvSURF_ASTC6x5_SRGB,
+    gcvSURF_ASTC6x6_SRGB,
+    gcvSURF_ASTC8x5_SRGB,
+    gcvSURF_ASTC8x6_SRGB,
+    gcvSURF_ASTC8x8_SRGB,
+    gcvSURF_ASTC10x5_SRGB,
+    gcvSURF_ASTC10x6_SRGB,
+    gcvSURF_ASTC10x8_SRGB,
+    gcvSURF_ASTC10x10_SRGB,
+    gcvSURF_ASTC12x10_SRGB,
+    gcvSURF_ASTC12x12_SRGB,
+
+    gcvSURF_FORMAT_COUNT
 }
 gceSURF_FORMAT;
 
+/* Format modifiers. */
+typedef enum _gceSURF_FORMAT_MODE
+{
+    gcvSURF_FORMAT_OCL = 0x80000000
+}
+gceSURF_FORMAT_MODE;
+
 /* Pixel swizzle modes. */
 typedef enum _gceSURF_SWIZZLE
 {
@@ -505,11 +871,10 @@ typedef enum _gceSURF_ALIGNMENT
     gcvSURF_SIXTEEN,
     gcvSURF_SUPER_TILED,
     gcvSURF_SPLIT_TILED,
-    gcvSURF_SPLIT_SUPER_TILED,
+    gcvSURF_SPLIT_SUPER_TILED
 }
 gceSURF_ALIGNMENT;
 
-
 /* Surface Addressing. */
 typedef enum _gceSURF_ADDRESSING
 {
@@ -667,6 +1032,7 @@ typedef enum _gce2D_COMMAND
     gcv2D_HOR_FILTER,
     gcv2D_VER_FILTER,
     gcv2D_MULTI_SOURCE_BLT,
+    gcv2D_FILTER_BLT,
 }
 gce2D_COMMAND;
 
@@ -677,6 +1043,7 @@ typedef enum _gce2D_TILE_STATUS_CONFIG
     gcv2D_TSC_COMPRESSED    = 0x00000002,
     gcv2D_TSC_DOWN_SAMPLER  = 0x00000004,
     gcv2D_TSC_2D_COMPRESSED = 0x00000008,
+    gcv2D_TSC_TPC_COMPRESSED = 0x00000010,
 }
 gce2D_TILE_STATUS_CONFIG;
 
@@ -704,6 +1071,8 @@ typedef enum _gce2D_STATE
     gcv2D_STATE_EN_GAMMA,
     gcv2D_STATE_DE_GAMMA,
     gcv2D_STATE_MULTI_SRC_BLIT_UNIFIED_DST_RECT,
+    gcv2D_STATE_PROFILE_ENABLE,
+    gcv2D_STATE_XRGB_ENABLE,
 
     gcv2D_STATE_ARRAY_EN_GAMMA                   = 0x10001,
     gcv2D_STATE_ARRAY_DE_GAMMA,
@@ -712,7 +1081,30 @@ typedef enum _gce2D_STATE
 }
 gce2D_STATE;
 
-#ifndef VIVANTE_NO_3D
+typedef enum _gce2D_STATE_PROFILE
+{
+    gcv2D_STATE_PROFILE_NONE    = 0x0,
+    gcv2D_STATE_PROFILE_COMMAND = 0x1,
+    gcv2D_STATE_PROFILE_SURFACE = 0x2,
+    gcv2D_STATE_PROFILE_ALL     = 0xFFFF,
+}
+gce2D_STATE_PROFILE;
+
+/* Texture object types */
+typedef enum _gceTEXTURE_TYPE
+{
+    gcvTEXTURE_UNKNOWN = 0,
+    gcvTEXTURE_1D,
+    gcvTEXTURE_2D,
+    gcvTEXTURE_3D,
+    gcvTEXTURE_CUBEMAP,
+    gcvTEXTURE_1D_ARRAY,
+    gcvTEXTURE_2D_ARRAY,
+    gcvTEXTURE_EXTERNAL
+}
+gceTEXTURE_TYPE;
+
+#if gcdENABLE_3D
 /* Texture functions. */
 typedef enum _gceTEXTURE_FUNCTION
 {
@@ -746,7 +1138,7 @@ typedef enum _gceTEXTURE_CHANNEL
     gcvFROM_ONE_MINUS_ALPHA
 }
 gceTEXTURE_CHANNEL;
-#endif /* VIVANTE_NO_3D */
+#endif /* gcdENABLE_3D */
 
 /* Filter types. */
 typedef enum _gceFILTER_TYPE
@@ -777,12 +1169,22 @@ gceENDIAN_HINT;
 /* Tiling modes. */
 typedef enum _gceTILING
 {
-    gcvLINEAR = 0,
-    gcvTILED,
-    gcvSUPERTILED,
-    gcvMULTI_TILED,
-    gcvMULTI_SUPERTILED,
-    gcvMINORTILED,
+    gcvINVALIDTILED = 0x0,        /* Invalid tiling */
+    /* Tiling basic modes enum'ed in power of 2. */
+    gcvLINEAR      = 0x1,         /* No    tiling. */
+    gcvTILED       = 0x2,         /* 4x4   tiling. */
+    gcvSUPERTILED  = 0x4,         /* 64x64 tiling. */
+    gcvMINORTILED  = 0x8,         /* 2x2   tiling. */
+
+    /* Tiling special layouts. */
+    gcvTILING_SPLIT_BUFFER = 0x100,
+
+    /* Tiling combination layouts. */
+    gcvMULTI_TILED      = gcvTILED
+                        | gcvTILING_SPLIT_BUFFER,
+
+    gcvMULTI_SUPERTILED = gcvSUPERTILED
+                        | gcvTILING_SPLIT_BUFFER,
 }
 gceTILING;
 
@@ -822,7 +1224,9 @@ typedef enum _gceHARDWARE_TYPE
     gcvHARDWARE_3D      = 0x01,
     gcvHARDWARE_2D      = 0x02,
     gcvHARDWARE_VG      = 0x04,
-
+#if gcdMULTI_GPU_AFFINITY
+    gcvHARDWARE_OCL     = 0x05,
+#endif
     gcvHARDWARE_3D2D    = gcvHARDWARE_3D | gcvHARDWARE_2D
 }
 gceHARDWARE_TYPE;
@@ -856,6 +1260,17 @@ typedef enum _gceSYNC_POINT_COMMAND_CODES
 }
 gceSYNC_POINT_COMMAND_CODES;
 
+/* Shared buffer command codes. */
+typedef enum _gceSHBUF_COMMAND_CODES
+{
+    gcvSHBUF_CREATE,
+    gcvSHBUF_DESTROY,
+    gcvSHBUF_MAP,
+    gcvSHBUF_WRITE,
+    gcvSHBUF_READ,
+}
+gceSHBUF_COMMAND_CODES;
+
 /* Event locations. */
 typedef enum _gceKERNEL_WHERE
 {
@@ -871,18 +1286,18 @@ gceKERNEL_WHERE;
 /* Hardware blocks. */
 typedef enum _gceBLOCK
 {
-       gcvBLOCK_COMMAND,
-       gcvBLOCK_TESSELLATOR,
-       gcvBLOCK_TESSELLATOR2,
-       gcvBLOCK_TESSELLATOR3,
-       gcvBLOCK_RASTER,
-       gcvBLOCK_VG,
-       gcvBLOCK_VG2,
-       gcvBLOCK_VG3,
-       gcvBLOCK_PIXEL,
-
-       /* Number of defined blocks. */
-       gcvBLOCK_COUNT
+    gcvBLOCK_COMMAND,
+    gcvBLOCK_TESSELLATOR,
+    gcvBLOCK_TESSELLATOR2,
+    gcvBLOCK_TESSELLATOR3,
+    gcvBLOCK_RASTER,
+    gcvBLOCK_VG,
+    gcvBLOCK_VG2,
+    gcvBLOCK_VG3,
+    gcvBLOCK_PIXEL,
+
+    /* Number of defined blocks. */
+    gcvBLOCK_COUNT
 }
 gceBLOCK;
 #endif
@@ -895,43 +1310,271 @@ typedef enum _gceDEBUG_MESSAGE_TYPE
 }
 gceDEBUG_MESSAGE_TYPE;
 
-typedef enum _gceSPECIAL_HINT
+/* Shading format. */
+typedef enum _gceSHADING
 {
-    gceSPECIAL_HINT0,
-    gceSPECIAL_HINT1,
-    gceSPECIAL_HINT2,
-    gceSPECIAL_HINT3,
-    /* For disable dynamic stream/index */
-    gceSPECIAL_HINT4
+    gcvSHADING_SMOOTH,
+    gcvSHADING_FLAT_D3D,
+    gcvSHADING_FLAT_OPENGL,
 }
-gceSPECIAL_HINT;
+gceSHADING;
 
-typedef enum _gceMACHINECODE
+/* Culling modes. */
+typedef enum _gceCULL
 {
-    gcvMACHINECODE_HOVERJET0       = 0x0,
-    gcvMACHINECODE_HOVERJET1      ,
+    gcvCULL_NONE,
+    gcvCULL_CCW,
+    gcvCULL_CW,
+}
+gceCULL;
 
-    gcvMACHINECODE_TAIJI0         ,
-    gcvMACHINECODE_TAIJI1         ,
-    gcvMACHINECODE_TAIJI2         ,
+/* Fill modes. */
+typedef enum _gceFILL
+{
+    gcvFILL_POINT,
+    gcvFILL_WIRE_FRAME,
+    gcvFILL_SOLID,
+}
+gceFILL;
 
-    gcvMACHINECODE_ANTUTU0        ,
+/* Compare modes. */
+typedef enum _gceCOMPARE
+{
+    gcvCOMPARE_INVALID = 0,
+    gcvCOMPARE_NEVER,
+    gcvCOMPARE_NOT_EQUAL,
+    gcvCOMPARE_LESS,
+    gcvCOMPARE_LESS_OR_EQUAL,
+    gcvCOMPARE_EQUAL,
+    gcvCOMPARE_GREATER,
+    gcvCOMPARE_GREATER_OR_EQUAL,
+    gcvCOMPARE_ALWAYS,
+}
+gceCOMPARE;
 
-    gcvMACHINECODE_GLB27_RELEASE_0,
-    gcvMACHINECODE_GLB27_RELEASE_1,
+/* Stencil modes. */
+typedef enum _gceSTENCIL_MODE
+{
+    gcvSTENCIL_NONE,
+    gcvSTENCIL_SINGLE_SIDED,
+    gcvSTENCIL_DOUBLE_SIDED,
+}
+gceSTENCIL_MODE;
+
+/* Stencil operations. */
+typedef enum _gceSTENCIL_OPERATION
+{
+    gcvSTENCIL_KEEP,
+    gcvSTENCIL_REPLACE,
+    gcvSTENCIL_ZERO,
+    gcvSTENCIL_INVERT,
+    gcvSTENCIL_INCREMENT,
+    gcvSTENCIL_DECREMENT,
+    gcvSTENCIL_INCREMENT_SATURATE,
+    gcvSTENCIL_DECREMENT_SATURATE,
+    gcvSTENCIL_OPERATION_INVALID = -1
+}
+gceSTENCIL_OPERATION;
+
+/* Stencil selection. */
+typedef enum _gceSTENCIL_WHERE
+{
+    gcvSTENCIL_FRONT,
+    gcvSTENCIL_BACK,
+}
+gceSTENCIL_WHERE;
+
+/* Texture addressing selection. */
+typedef enum _gceTEXTURE_WHICH
+{
+    gcvTEXTURE_S,
+    gcvTEXTURE_T,
+    gcvTEXTURE_R,
+}
+gceTEXTURE_WHICH;
+
+/* Texture addressing modes. */
+typedef enum _gceTEXTURE_ADDRESSING
+{
+    gcvTEXTURE_INVALID    = 0,
+    gcvTEXTURE_CLAMP,
+    gcvTEXTURE_WRAP,
+    gcvTEXTURE_MIRROR,
+    gcvTEXTURE_BORDER,
+    gcvTEXTURE_MIRROR_ONCE,
+}
+gceTEXTURE_ADDRESSING;
+
+/* Texture filters. */
+typedef enum _gceTEXTURE_FILTER
+{
+    gcvTEXTURE_NONE,
+    gcvTEXTURE_POINT,
+    gcvTEXTURE_LINEAR,
+    gcvTEXTURE_ANISOTROPIC,
+}
+gceTEXTURE_FILTER;
+
+typedef enum _gceTEXTURE_COMPONENT
+{
+    gcvTEXTURE_COMPONENT_R,
+    gcvTEXTURE_COMPONENT_G,
+    gcvTEXTURE_COMPONENT_B,
+    gcvTEXTURE_COMPONENT_A,
+
+    gcvTEXTURE_COMPONENT_NUM,
+} gceTEXTURE_COMPONENT;
+
+/* Texture swizzle modes. */
+typedef enum _gceTEXTURE_SWIZZLE
+{
+    gcvTEXTURE_SWIZZLE_R = 0,
+    gcvTEXTURE_SWIZZLE_G,
+    gcvTEXTURE_SWIZZLE_B,
+    gcvTEXTURE_SWIZZLE_A,
+    gcvTEXTURE_SWIZZLE_0,
+    gcvTEXTURE_SWIZZLE_1,
+
+    gcvTEXTURE_SWIZZLE_INVALID,
+} gceTEXTURE_SWIZZLE;
+
+typedef enum _gceTEXTURE_COMPARE_MODE
+{
+    gcvTEXTURE_COMPARE_MODE_INVALID  = 0,
+    gcvTEXTURE_COMPARE_MODE_NONE,
+    gcvTEXTURE_COMPARE_MODE_REF,
+} gceTEXTURE_COMPARE_MODE;
 
-    gcvMACHINECODE_WAVESCAPE0     ,
-    gcvMACHINECODE_WAVESCAPE1     ,
+/* Pixel output swizzle modes. */
+typedef enum _gcePIXEL_SWIZZLE
+{
+    gcvPIXEL_SWIZZLE_R = gcvTEXTURE_SWIZZLE_R,
+    gcvPIXEL_SWIZZLE_G = gcvTEXTURE_SWIZZLE_G,
+    gcvPIXEL_SWIZZLE_B = gcvTEXTURE_SWIZZLE_B,
+    gcvPIXEL_SWIZZLE_A = gcvTEXTURE_SWIZZLE_A,
+
+    gcvPIXEL_SWIZZLE_INVALID,
+} gcePIXEL_SWIZZLE;
+
+/* 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,
+    gcvPRIMITIVE_RECTANGLE,
+}
+gcePRIMITIVE;
+
+/* Index types. */
+typedef enum _gceINDEX_TYPE
+{
+    gcvINDEX_8,
+    gcvINDEX_16,
+    gcvINDEX_32,
+}
+gceINDEX_TYPE;
+
+/* Multi GPU rendering modes. */
+typedef enum _gceMULTI_GPU_RENDERING_MODE
+{
+    gcvMULTI_GPU_RENDERING_MODE_OFF,
+    gcvMULTI_GPU_RENDERING_MODE_SPLIT_WIDTH,
+    gcvMULTI_GPU_RENDERING_MODE_SPLIT_HEIGHT,
+    gcvMULTI_GPU_RENDERING_MODE_INTERLEAVED_64x64,
+    gcvMULTI_GPU_RENDERING_MODE_INTERLEAVED_128x64,
+    gcvMULTI_GPU_RENDERING_MODE_INTERLEAVED_128x128
+}
+gceMULTI_GPU_RENDERING_MODE;
+
+typedef enum _gceCORE_3D_MASK
+{
+    gcvCORE_3D_0_MASK   = (1 << 0),
+    gcvCORE_3D_1_MASK   = (1 << 1),
+
+    gcvCORE_3D_ALL_MASK = (0xFFFF)
+}
+gceCORE_3D_MASK;
+
+typedef enum _gceCORE_3D_ID
+{
+    gcvCORE_3D_0_ID       = 0,
+    gcvCORE_3D_1_ID       = 1,
 
-    gcvMACHINECODE_NENAMARKV2_4_0 ,
-    gcvMACHINECODE_NENAMARKV2_4_1 ,
+    gcvCORE_3D_ID_INVALID = ~0UL
+}
+gceCORE_3D_ID;
+
+typedef enum _gceMULTI_GPU_MODE
+{
+    gcvMULTI_GPU_MODE_COMBINED    = 0,
+    gcvMULTI_GPU_MODE_INDEPENDENT = 1
+}
+gceMULTI_GPU_MODE;
+
+typedef enum _gceMACHINECODE
+{
+    gcvMACHINECODE_ANTUTU0 = 0x0,
+
+    gcvMACHINECODE_GLB27_RELEASE_0,
 
     gcvMACHINECODE_GLB25_RELEASE_0,
     gcvMACHINECODE_GLB25_RELEASE_1,
     gcvMACHINECODE_GLB25_RELEASE_2,
+
+    /* keep it as the last enum */
+    gcvMACHINECODE_COUNT
 }
 gceMACHINECODE;
 
+typedef enum _gceUNIFORMCVT
+{
+    gcvUNIFORMCVT_NONE = 0,
+    gcvUNIFORMCVT_TO_BOOL,
+    gcvUNIFORMCVT_TO_FLOAT,
+} gceUNIFORMCVT;
+
+typedef enum _gceHAL_ARG_VERSION
+{
+    gcvHAL_ARG_VERSION_V1 = 0x0,
+}
+gceHAL_ARG_VERSION;
+
+
+/*
+* Bit of a requirment is 1 means requirement is a must, 0 means requirement can
+* be ignored.
+*/
+#define gcvALLOC_FLAG_CONTIGUOUS_BIT        0
+#define gcvALLOC_FLAG_CACHEABLE_BIT         1
+#define gcvALLOC_FLAG_SECURITY_BIT          2
+#define gcvALLOC_FLAG_NON_CONTIGUOUS_BIT    3
+#define gcvALLOC_FLAG_MEMLIMIT_BIT    4
+
+/* No special needs. */
+#define gcvALLOC_FLAG_NONE              (0)
+/* Physical contiguous. */
+#define gcvALLOC_FLAG_CONTIGUOUS        (1 << gcvALLOC_FLAG_CONTIGUOUS_BIT)
+/* Can be remapped as cacheable. */
+#define gcvALLOC_FLAG_CACHEABLE         (1 << gcvALLOC_FLAG_CACHEABLE_BIT)
+/* Secure buffer. */
+#define gcvALLOC_FLAG_SECURITY          (1 << gcvALLOC_FLAG_SECURITY_BIT)
+/* Physical non contiguous. */
+#define gcvALLOC_FLAG_NON_CONTIGUOUS    (1 << gcvALLOC_FLAG_NON_CONTIGUOUS_BIT)
+#define gcvALLOC_FLAG_MEMLIMIT    (1 << gcvALLOC_FLAG_MEMLIMIT_BIT)
+
+/* GL_VIV internal usage */
+#ifndef GL_MAP_BUFFER_OBJ_VIV
+#define GL_MAP_BUFFER_OBJ_VIV       0x10000
+#endif
+
+/* Command buffer usage. */
+#define gcvCOMMAND_2D   (1 << 0)
+#define gcvCOMMAND_3D   (1 << 1)
 
 /******************************************************************************\
 ****************************** Object Declarations *****************************
@@ -939,6 +1582,7 @@ gceMACHINECODE;
 
 typedef struct _gckCONTEXT          * gckCONTEXT;
 typedef struct _gcoCMDBUF           * gcoCMDBUF;
+
 typedef struct _gcsSTATE_DELTA      * gcsSTATE_DELTA_PTR;
 typedef struct _gcsQUEUE            * gcsQUEUE_PTR;
 typedef struct _gcoQUEUE            * gcoQUEUE;
@@ -946,15 +1590,15 @@ typedef struct _gcsHAL_INTERFACE    * gcsHAL_INTERFACE_PTR;
 typedef struct _gcs2D_PROFILE       * gcs2D_PROFILE_PTR;
 
 #if gcdENABLE_VG
-typedef struct _gcoVGHARDWARE *                        gcoVGHARDWARE;
+typedef struct _gcoVGHARDWARE *            gcoVGHARDWARE;
 typedef struct _gcoVGBUFFER *           gcoVGBUFFER;
 typedef struct _gckVGHARDWARE *         gckVGHARDWARE;
-typedef struct _gcsVGCONTEXT *                 gcsVGCONTEXT_PTR;
-typedef struct _gcsVGCONTEXT_MAP *             gcsVGCONTEXT_MAP_PTR;
-typedef struct _gcsVGCMDQUEUE *                        gcsVGCMDQUEUE_PTR;
-typedef struct _gcsTASK_MASTER_TABLE * gcsTASK_MASTER_TABLE_PTR;
-typedef struct _gckVGKERNEL *                  gckVGKERNEL;
-typedef void *                                         gctTHREAD;
+typedef struct _gcsVGCONTEXT *            gcsVGCONTEXT_PTR;
+typedef struct _gcsVGCONTEXT_MAP *        gcsVGCONTEXT_MAP_PTR;
+typedef struct _gcsVGCMDQUEUE *            gcsVGCMDQUEUE_PTR;
+typedef struct _gcsTASK_MASTER_TABLE *    gcsTASK_MASTER_TABLE_PTR;
+typedef struct _gckVGKERNEL *            gckVGKERNEL;
+typedef void *                            gctTHREAD;
 #endif
 
 #ifdef __cplusplus
index 0608e437f54d83b274f5c709a2ee8c616b488a57..84283421f1dd706a970c49b0c9dda34ce8c5485e 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -22,7 +22,6 @@
 #ifndef __gc_hal_kernel_buffer_h_
 #define __gc_hal_kernel_buffer_h_
 
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -91,12 +90,38 @@ typedef struct _gcsSTATE_DELTA
 }
 gcsSTATE_DELTA;
 
+/* Command buffer patch record. */
+struct _gcsPATCH
+{
+    /* Pointer within the buffer. */
+    gctUINT32_PTR               pointer;
+
+    /* 32-bit data to write at the specified offset. */
+    gctUINT32                   data;
+};
+
+/* List of patches for the command buffer. */
+struct _gcsPATCH_LIST
+{
+    /* Array of patch records. */
+    struct _gcsPATCH            patch[1024];
+
+    /* Number of patches in the array. */
+    gctUINT                     count;
+
+    /* Next item in the list. */
+    struct _gcsPATCH_LIST       *next;
+};
+
 /* Command buffer object. */
 struct _gcoCMDBUF
 {
     /* The object. */
     gcsOBJECT                   object;
 
+    /* Commit count. */
+    gctUINT                     count;
+
     /* Command buffer entry and exit pipes. */
     gcePIPE_SELECT              entryPipe;
     gcePIPE_SELECT              exitPipe;
@@ -114,20 +139,20 @@ struct _gcoCMDBUF
     gctUINT64                   logical;
 
     /* Number of bytes in command buffer. */
-    gctUINT                     bytes;
+    gctUINT32                   bytes;
 
     /* Start offset into the command buffer. */
-    gctUINT                     startOffset;
+    gctUINT32                   startOffset;
 
     /* Current offset into the command buffer. */
-    gctUINT                     offset;
+    gctUINT32                   offset;
 
     /* Number of free bytes in command buffer. */
-    gctUINT                     free;
+    gctUINT32                   free;
 
     /* Location of the last reserved area. */
     gctUINT64                   lastReserve;
-    gctUINT                     lastOffset;
+    gctUINT32                   lastOffset;
 
 #if gcdSECURE_USER
     /* Hint array for the current command buffer. */
@@ -142,6 +167,17 @@ struct _gcoCMDBUF
     gctUINT32                   lastLoadStateAddress;
     gctUINT32                   lastLoadStateCount;
 #endif
+
+    /* Completion signal. */
+    gctSIGNAL                   signal;
+
+    /* List of patches. */
+    struct _gcsPATCH_LIST       *patchHead;
+    struct _gcsPATCH_LIST       *patchTail;
+
+    /* Link to the siblings. */
+    gcoCMDBUF                   prev;
+    gcoCMDBUF                   next;
 };
 
 typedef struct _gcsQUEUE
@@ -164,20 +200,24 @@ struct _gcoQUEUE
     gcsQUEUE_PTR                head;
     gcsQUEUE_PTR                tail;
 
-#ifdef __QNXNTO__
-    /* Buffer for records. */
-    gcsQUEUE_PTR                records;
-    gctUINT32                   freeBytes;
-    gctUINT32                   offset;
-#else
+    /* chunks of the records. */
+    gctPOINTER                  chunks;
+
     /* List of free records. */
     gcsQUEUE_PTR                freeList;
-#endif
+
     #define gcdIN_QUEUE_RECORD_LIMIT 16
     /* Number of records currently in queue */
     gctUINT32                   recordCount;
 };
 
+struct _gcsTEMPCMDBUF
+{
+    gctUINT32 currentByteSize;
+    gctPOINTER buffer;
+    gctBOOL  inUse;
+};
+
 #ifdef __cplusplus
 }
 #endif
index 9e32878cd76d7803fcb2aaaa0f4a85ed264c72fa..df35019bce2a5d4d99744c180d92bc8c6e4356eb 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 
 
 /*
-**     Include file for the local memory management.
+**    Include file for the local memory management.
 */
 
 #ifndef __gc_hal_mem_h_
 #define __gc_hal_mem_h_
-#ifndef VIVANTE_NO_3D
+#if (gcdENABLE_3D || gcdENABLE_VG)
 
 #ifdef __cplusplus
 extern "C" {
@@ -34,100 +34,100 @@ extern "C" {
 /*******************************************************************************
 **  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);
+    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.
+**    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
 /*
@@ -135,161 +135,161 @@ extern "C" {
 
     This define enables the local memory management to improve performance.
 */
-#define USE_LOCAL_MEMORY_POOL          1
+#define USE_LOCAL_MEMORY_POOL        1
 #endif
 
 /*******************************************************************************
-**                                                     Memory Pool Data Structures
+**                            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;
+    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;
+    typedef gcoOS    gcsMEM_FS_MEM_POOL;
+    typedef gcoOS    gcsMEM_VS_MEM_POOL;
+    typedef gcoOS    gcsMEM_AFS_MEM_POOL;
 #endif
 
 /*******************************************************************************
-**                                                     Memory Pool Macros
+**                            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 \
-       ) \
+    gcsMEM_FS_MEM_POOL        MemPool, \
+    Type **                    Pointer \
+    ) \
 { \
-       return(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+    return(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
 } \
  \
 gceSTATUS \
 Prefix##_CAllocate##TypeName( \
-       gcsMEM_FS_MEM_POOL              MemPool, \
-       Type **                                 Pointer \
-       ) \
+    gcsMEM_FS_MEM_POOL        MemPool, \
+    Type **                    Pointer \
+    ) \
 { \
-       gceSTATUS                               status; \
+    gceSTATUS                status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
-       gcmERR_RETURN(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
-       gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
+    gcmERR_RETURN(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+    gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
     gcmFOOTER(); \
-       return gcvSTATUS_OK; \
+    return gcvSTATUS_OK; \
 } \
  \
 gceSTATUS \
 Prefix##_Free##TypeName( \
-       gcsMEM_FS_MEM_POOL              MemPool, \
-       Type *                                  Pointer \
-       ) \
+    gcsMEM_FS_MEM_POOL        MemPool, \
+    Type *                    Pointer \
+    ) \
 { \
-    gceSTATUS                          status; \
+    gceSTATUS                status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
     status = gcfMEM_FSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
     gcmFOOTER(); \
-       return status; \
+    return status; \
 } \
  \
 gceSTATUS \
 Prefix##_Free##TypeName##List( \
-       gcsMEM_FS_MEM_POOL              MemPool, \
-       Type *                                  FirstPointer, \
-       Type *                                  LastPointer \
-       ) \
+    gcsMEM_FS_MEM_POOL        MemPool, \
+    Type *                    FirstPointer, \
+    Type *                    LastPointer \
+    ) \
 { \
     gceSTATUS               status; \
     gcmHEADER_ARG("MemPool=0x%x FirstPointer=0x%x LastPointer=0x%x", MemPool, FirstPointer, LastPointer); \
     status = gcfMEM_FSMemPoolFreeAList(MemPool, (gctPOINTER) FirstPointer, (gctPOINTER) LastPointer); \
     gcmFOOTER(); \
-       return status; \
+    return status; \
 }
 
 #define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
 gceSTATUS \
 Prefix##_Allocate##TypeName( \
-       gcsMEM_FS_MEM_POOL              MemPool, \
-       Type **                                 Pointer, \
-       gctUINT                                 Size \
-       ) \
+    gcsMEM_FS_MEM_POOL        MemPool, \
+    Type **                    Pointer, \
+    gctUINT                    Size \
+    ) \
 { \
     gceSTATUS               status;\
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
     status = gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer); \
     gcmFOOTER(); \
-       return status; \
+    return status; \
 } \
  \
 gceSTATUS \
  Prefix##_CAllocate##TypeName( \
-       gcsMEM_FS_MEM_POOL              MemPool, \
-       Type **                                 Pointer, \
-       gctUINT                                 Size \
-       ) \
+    gcsMEM_FS_MEM_POOL        MemPool, \
+    Type **                    Pointer, \
+    gctUINT                    Size \
+    ) \
 { \
-       gceSTATUS                               status; \
+    gceSTATUS                status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
-       gcmERR_RETURN(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
-       gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, size); \
+    gcmERR_RETURN(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
+    gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, size); \
     gcmFOOTER(); \
-       return gcvSTATUS_OK; \
+    return gcvSTATUS_OK; \
 } \
  \
 gceSTATUS \
 Prefix##_Free##TypeName( \
-       gcsMEM_FS_MEM_POOL              MemPool, \
-       Type *                                  Pointer \
-       ) \
+    gcsMEM_FS_MEM_POOL        MemPool, \
+    Type *                    Pointer \
+    ) \
 { \
     gceSTATUS               status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pinter); \
     status = gcfMEM_VSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
     gcmFOOTER(); \
-       return status; \
+    return status; \
 }
 
 #define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
 gceSTATUS \
 Prefix##_Allocate##TypeName( \
-       gcsMEM_AFS_MEM_POOL             MemPool, \
-       Type **                                 Pointer, \
-       gctUINT                                 Count \
-       ) \
+    gcsMEM_AFS_MEM_POOL        MemPool, \
+    Type **                    Pointer, \
+    gctUINT                    Count \
+    ) \
 { \
     gceSTATUS               status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
     status = gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer); \
     gcmFOOTER(); \
-       return status; \
+    return status; \
 } \
  \
 gceSTATUS \
 Prefix##_CAllocate##TypeName( \
-       gcsMEM_AFS_MEM_POOL             MemPool, \
-       Type **                                 Pointer, \
-       gctUINT                                 Count \
-       ) \
+    gcsMEM_AFS_MEM_POOL        MemPool, \
+    Type **                    Pointer, \
+    gctUINT                    Count \
+    ) \
 { \
-       gceSTATUS                               status; \
+    gceSTATUS                status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
-       gcmERR_RETURN(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
-       gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
+    gcmERR_RETURN(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
+    gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
     gcmFOOTER(); \
-       return gcvSTATUS_OK; \
+    return gcvSTATUS_OK; \
 } \
  \
 gceSTATUS \
 Prefix##_Free##TypeName( \
-       gcsMEM_AFS_MEM_POOL             MemPool, \
-       Type *                                  Pointer \
-       ) \
+    gcsMEM_AFS_MEM_POOL        MemPool, \
+    Type *                    Pointer \
+    ) \
 { \
     gceSTATUS               status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
     status = gcfMEM_AFSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
     gcmFOOTER(); \
-       return status; \
+    return status; \
 }
 
 #else
@@ -297,234 +297,234 @@ Prefix##_Free##TypeName( \
 #define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
 gceSTATUS \
 Prefix##_Allocate##TypeName( \
-       gcsMEM_FS_MEM_POOL              MemPool, \
-       Type **                                 Pointer \
-       ) \
+    gcsMEM_FS_MEM_POOL        MemPool, \
+    Type **                    Pointer \
+    ) \
 { \
     gceSTATUS               status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
     status = gcoOS_Allocate(MemPool, \
-                                                       gcmSIZEOF(Type), \
-                                                       (gctPOINTER *) Pointer); \
+                            gcmSIZEOF(Type), \
+                            (gctPOINTER *) Pointer); \
     gcmFOOTER(); \
-       return status; \
+    return status; \
 } \
  \
 gceSTATUS \
 Prefix##_CAllocate##TypeName( \
-       gcsMEM_FS_MEM_POOL              MemPool, \
-       Type **                                 Pointer \
-       ) \
+    gcsMEM_FS_MEM_POOL        MemPool, \
+    Type **                    Pointer \
+    ) \
 { \
-       gceSTATUS                               status; \
+    gceSTATUS                status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
-       gcmERR_RETURN(gcoOS_Allocate(MemPool, \
-                                                       gcmSIZEOF(Type), \
-                                                       (gctPOINTER *) Pointer)); \
-       gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
+    gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+                            gcmSIZEOF(Type), \
+                            (gctPOINTER *) Pointer)); \
+    gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
     gcmFOOTER(); \
-       return gcvSTATUS_OK; \
+    return gcvSTATUS_OK; \
 } \
  \
 gceSTATUS \
 Prefix##_Free##TypeName( \
-       gcsMEM_FS_MEM_POOL              MemPool, \
-       Type *                                  Pointer \
-       ) \
+    gcsMEM_FS_MEM_POOL        MemPool, \
+    Type *                    Pointer \
+    ) \
 { \
-    gceSTATUS                          status; \
+    gceSTATUS                status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
     status = gcmOS_SAFE_FREE(MemPool, Pointer); \
     gcmFOOTER(); \
-       return status; \
+    return status; \
 }
 
 #define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
 gceSTATUS \
 Prefix##_Allocate##TypeName( \
-       gcsMEM_VS_MEM_POOL              MemPool, \
-       Type **                                 Pointer, \
-       gctUINT                                 Size \
-       ) \
+    gcsMEM_VS_MEM_POOL        MemPool, \
+    Type **                    Pointer, \
+    gctUINT                    Size \
+    ) \
 { \
-    gceSTATUS                          status; \
+    gceSTATUS                status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
     status = gcoOS_Allocate(MemPool, \
-                                                       Size, \
-                                                       (gctPOINTER *) Pointer); \
+                            Size, \
+                            (gctPOINTER *) Pointer); \
     gcmFOOTER(); \
-       return status; \
+    return status; \
 } \
  \
 gceSTATUS \
 Prefix##_CAllocate##TypeName( \
-       gcsMEM_VS_MEM_POOL              MemPool, \
-       Type **                                 Pointer, \
-       gctUINT                                 Size \
-       ) \
+    gcsMEM_VS_MEM_POOL        MemPool, \
+    Type **                    Pointer, \
+    gctUINT                    Size \
+    ) \
 { \
-       gceSTATUS                               status; \
+    gceSTATUS                status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
-       gcmERR_RETURN(gcoOS_Allocate(MemPool, \
-                                                       Size, \
-                                                       (gctPOINTER *) Pointer)); \
-       gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Size); \
+    gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+                            Size, \
+                            (gctPOINTER *) Pointer)); \
+    gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Size); \
     gcmFOOTER(); \
-       return gcvSTATUS_OK; \
+    return gcvSTATUS_OK; \
 } \
  \
 gceSTATUS \
 Prefix##_Free##TypeName( \
-       gcsMEM_VS_MEM_POOL              MemPool, \
-       Type *                                  Pointer \
-       ) \
+    gcsMEM_VS_MEM_POOL        MemPool, \
+    Type *                    Pointer \
+    ) \
 { \
-    gceSTATUS                          status; \
+    gceSTATUS                status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
     status = gcmOS_SAFE_FREE(MemPool, Pointer); \
     gcmFOOTER(); \
-       return status; \
+    return status; \
 }
 
 #define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
 gceSTATUS \
 Prefix##_Allocate##TypeName( \
-       gcsMEM_AFS_MEM_POOL             MemPool, \
-       Type **                                 Pointer, \
-       gctUINT                                 Count \
-       ) \
+    gcsMEM_AFS_MEM_POOL        MemPool, \
+    Type **                    Pointer, \
+    gctUINT                    Count \
+    ) \
 { \
-    gceSTATUS                          status; \
+    gceSTATUS                status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
     status = gcoOS_Allocate(MemPool, \
-                                                       Count * gcmSIZEOF(Type), \
-                                                       (gctPOINTER *) Pointer); \
+                            Count * gcmSIZEOF(Type), \
+                            (gctPOINTER *) Pointer); \
     gcmFOOTER(); \
-       return status; \
+    return status; \
 } \
  \
 gceSTATUS \
 Prefix##_CAllocate##TypeName( \
-       gcsMEM_AFS_MEM_POOL             MemPool, \
-       Type **                                 Pointer, \
-       gctUINT                                 Count \
-       ) \
+    gcsMEM_AFS_MEM_POOL        MemPool, \
+    Type **                    Pointer, \
+    gctUINT                    Count \
+    ) \
 { \
-       gceSTATUS                               status; \
+    gceSTATUS                status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
-       gcmERR_RETURN(gcoOS_Allocate(MemPool, \
-                                                       Count * gcmSIZEOF(Type), \
-                                                       (gctPOINTER *) Pointer)); \
-       gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
+    gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+                            Count * gcmSIZEOF(Type), \
+                            (gctPOINTER *) Pointer)); \
+    gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
     gcmFOOTER(); \
-       return gcvSTATUS_OK; \
+    return gcvSTATUS_OK; \
 } \
  \
 gceSTATUS \
 Prefix##_Free##TypeName( \
-       gcsMEM_AFS_MEM_POOL             MemPool, \
-       Type *                                  Pointer \
-       ) \
+    gcsMEM_AFS_MEM_POOL        MemPool, \
+    Type *                    Pointer \
+    ) \
 { \
-    gceSTATUS                          status; \
+    gceSTATUS                status; \
     gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
     status = gcmOS_SAFE_FREE(MemPool, Pointer); \
     gcmFOOTER(); \
-       return status; \
+    return status; \
 }
 #endif
 
 /*******************************************************************************
-**                                                     Memory Pool Data Functions
+**                            Memory Pool Data Functions
 *******************************************************************************/
 gceSTATUS
 gcfMEM_InitFSMemPool(
-       IN gcsMEM_FS_MEM_POOL * MemPool,
-       IN gcoOS                                OS,
-       IN gctUINT                              NodeCount,
-       IN gctUINT                              NodeSize
-       );
+    IN gcsMEM_FS_MEM_POOL * MemPool,
+    IN gcoOS                OS,
+    IN gctUINT                NodeCount,
+    IN gctUINT                NodeSize
+    );
 
 gceSTATUS
 gcfMEM_FreeFSMemPool(
-       IN gcsMEM_FS_MEM_POOL * MemPool
-       );
+    IN gcsMEM_FS_MEM_POOL * MemPool
+    );
 
 gceSTATUS
 gcfMEM_FSMemPoolGetANode(
-       IN gcsMEM_FS_MEM_POOL   MemPool,
-       OUT gctPOINTER *                Node
-       );
+    IN gcsMEM_FS_MEM_POOL    MemPool,
+    OUT gctPOINTER *        Node
+    );
 
 gceSTATUS
 gcfMEM_FSMemPoolFreeANode(
-       IN gcsMEM_FS_MEM_POOL   MemPool,
-       IN gctPOINTER                   Node
-       );
+    IN gcsMEM_FS_MEM_POOL    MemPool,
+    IN gctPOINTER            Node
+    );
 
 gceSTATUS
 gcfMEM_FSMemPoolFreeAList(
-       IN gcsMEM_FS_MEM_POOL   MemPool,
-       IN gctPOINTER                   FirstNode,
-       IN gctPOINTER                   LastNode
-       );
+    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
-       );
+    IN gcsMEM_VS_MEM_POOL * MemPool,
+    IN gcoOS                OS,
+    IN gctUINT                BlockSize,
+    IN gctBOOL                RecycleFreeNode
+    );
 
 gceSTATUS
 gcfMEM_FreeVSMemPool(
-       IN gcsMEM_VS_MEM_POOL * MemPool
-       );
+    IN gcsMEM_VS_MEM_POOL * MemPool
+    );
 
 gceSTATUS
 gcfMEM_VSMemPoolGetANode(
-       IN gcsMEM_VS_MEM_POOL   MemPool,
-       IN gctUINT                              Size,
-       IN gctUINT                              Alignment,
-       OUT gctPOINTER *                Node
-       );
+    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
-       );
+    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
-       );
+    IN gcsMEM_AFS_MEM_POOL *MemPool,
+    IN gcoOS                OS,
+    IN gctUINT                NodeCount,
+    IN gctUINT                NodeSize
+    );
 
 gceSTATUS
 gcfMEM_FreeAFSMemPool(
-       IN gcsMEM_AFS_MEM_POOL *MemPool
-       );
+    IN gcsMEM_AFS_MEM_POOL *MemPool
+    );
 
 gceSTATUS
 gcfMEM_AFSMemPoolGetANode(
-       IN gcsMEM_AFS_MEM_POOL  MemPool,
-       IN gctUINT                              Count,
-       OUT gctPOINTER *                Node
-       );
+    IN gcsMEM_AFS_MEM_POOL    MemPool,
+    IN gctUINT                Count,
+    OUT gctPOINTER *        Node
+    );
 
 gceSTATUS
 gcfMEM_AFSMemPoolFreeANode(
-       IN gcsMEM_AFS_MEM_POOL  MemPool,
-       IN gctPOINTER                   Node
-       );
+    IN gcsMEM_AFS_MEM_POOL    MemPool,
+    IN gctPOINTER            Node
+    );
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* VIVANTE_NO_3D */
+#endif /* (gcdENABLE_3D || gcdENABLE_VG) */
 #endif /* __gc_hal_mem_h_ */
index 420437f514bcefaa0c0d6ce28f5622afd30994b8..b93015d32f923ee337738d89829f9fbe3ef0dee4 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 *
 *****************************************************************************/
 
-
 #ifndef __gc_hal_options_h_
 #define __gc_hal_options_h_
 
+/*
+    gcdSECURITY
+
+*/
+#ifndef gcdSECURITY
+#   define gcdSECURITY                          0
+#endif
+
 /*
     gcdPRINT_VERSION
 
 #   define VIVANTE_PROFILER                     1
 #endif
 
-#ifndef VIVANTE_PROFILER_PERDRAW
-#   define  VIVANTE_PROFILER_PERDRAW    0
-#endif
-
 /*
     VIVANTE_PROFILER_CONTEXT
 
-        This define enables the profiler according to each hw context.
+        This define enables the profiler according each context.
 */
 #ifndef VIVANTE_PROFILER_CONTEXT
 #   define VIVANTE_PROFILER_CONTEXT             1
 #endif
 
+#ifndef VIVANTE_PROFILER_PERDRAW
+#   define VIVANTE_PROFILER_PERDRAW             0
+#endif
+
+#ifndef VIVANTE_PROFILER_NEW
+#   define VIVANTE_PROFILER_NEW                 0
+#endif
+
+#ifndef VIVANTE_PROFILER_PM
+#   define VIVANTE_PROFILER_PM                  1
+#endif
 /*
     gcdUSE_VG
 
 #   define USE_SW_FB                            0
 #endif
 
-/*
-    USE_SUPER_SAMPLING
-
-        This define enables super-sampling support.
-*/
-#define USE_SUPER_SAMPLING                      0
-
 /*
     PROFILE_HAL_COUNTERS
 
 #   define gcdDUMP_API                          0
 #endif
 
+
+
+/*
+    gcdDEBUG_OPTION
+        When set to 1, the debug options are enabled. We must set other MACRO to enable
+        sub case.
+*/
+#ifndef gcdDEBUG_OPTION
+#   define gcdDEBUG_OPTION                      0
+
+#if gcdDEBUG_OPTION
+/*
+    gcdDEBUG_OPTION_KEY
+        The process name of debug application.
+*/
+#ifndef gcdDEBUG_OPTION_KEY
+#          define gcdDEBUG_OPTION_KEY                           "process"
+#       endif
+/*
+    gcdDEBUG_OPTION_NO_GL_DRAWS
+        When set to 1, all glDrawArrays and glDrawElements will be skip.
+*/
+#ifndef gcdDEBUG_OPTION_NO_GL_DRAWS
+#           define gcdDEBUG_OPTION_NO_GL_DRAWS                  0
+#       endif
+/*
+    gcdDEBUG_OPTION_NO_DRAW_PRIMITIVES
+        When set to 1, all DrawPrimitives will be skip.
+*/
+#ifndef gcdDEBUG_OPTION_NO_DRAW_PRIMITIVES
+#           define gcdDEBUG_OPTION_NO_DRAW_PRIMITIVES           0
+#       endif
+/*
+    gcdDEBUG_OPTION_SKIP_SWAP
+        When set to 1, just one out of gcdDEBUG_OPTION_SKIP_FRAMES(such as 1/10) eglSwapBuffers will be resolve,
+        others skip.
+*/
+#ifndef gcdDEBUG_OPTION_SKIP_SWAP
+#           define gcdDEBUG_OPTION_SKIP_SWAP                    0
+#           define gcdDEBUG_OPTION_SKIP_FRAMES                  10
+#       endif
+/*
+    gcdDEBUG_OPTION_FORCE_16BIT_RENDER_TARGET
+        When set to 1, the format of render target will force to RGB565.
+*/
+#ifndef gcdDEBUG_OPTION_FORCE_16BIT_RENDER_TARGET
+#           define gcdDEBUG_OPTION_FORCE_16BIT_RENDER_TARGET    0
+#       endif
+/*
+    gcdDEBUG_OPTION_NONE_TEXTURE
+        When set to 1, the type of texture will be set to AQ_TEXTURE_SAMPLE_MODE_TYPE_NONE.
+*/
+#ifndef gcdDEBUG_OPTION_NONE_TEXTURE
+#           define gcdDEBUG_OPTION_NONE_TEXTURE                 0
+#       endif
+/*
+    gcdDEBUG_OPTION_NONE_DEPTH
+        When set to 1, the depth format of surface will be set to gcvSURF_UNKNOWN.
+*/
+#ifndef gcdDEBUG_OPTION_NONE_DEPTH
+#           define gcdDEBUG_OPTION_NONE_DEPTH                   0
+#       endif
+
+#   endif
+#endif
+
+/*
+    gcdDUMP_SWAP_PER_DRAW
+
+        When set to 1, dump swap command for every single draw to make simulation comparison happy.
+        Only valid for ES3 driver for now.
+*/
+#ifndef gcdDUMP_SWAP_PER_DRAW
+#   define gcdDUMP_SWAP_PER_DRAW                0
+#endif
+
 /*
     gcdDUMP_FRAMERATE
         When set to a value other than zero, averaqe frame rate will be dumped.
         in the average. Frame count starts from 1.
 */
 #ifndef gcdDUMP_FRAMERATE
-#   define gcdDUMP_FRAMERATE                                   0
-#endif
-
-/*
-    gcdVIRTUAL_COMMAND_BUFFER
-        When set to 1, user command buffer and context buffer will be allocated
-        from gcvPOOL_VIRTUAL.
-*/
-#ifndef gcdVIRTUAL_COMMAND_BUFFER
-#   define gcdVIRTUAL_COMMAND_BUFFER            0
+#   define gcdDUMP_FRAMERATE                    0
 #endif
 
 /*
 #   define gcdDUMP_COMMAND                      0
 #endif
 
+/*
+    gcdDUMP_2D
+
+        When set to non-zero, it will dump the 2D command and surface.
+*/
+#ifndef gcdDUMP_2D
+#   define gcdDUMP_2D                           0
+#endif
+
 /*
     gcdDUMP_FRAME_TGA
 
     will be done into frame.tga. Frame count starts from 1.
  */
 #ifndef gcdDUMP_FRAME_TGA
-#define gcdDUMP_FRAME_TGA                       0
+#   define gcdDUMP_FRAME_TGA                    0
 #endif
 /*
     gcdNULL_DRIVER
     Set to 3 for bypassing the drivers.
 */
 #ifndef gcdNULL_DRIVER
-#   define gcdNULL_DRIVER                       0
+#   define gcdNULL_DRIVER  0
 #endif
 
 /*
 #   define gcdREGISTER_ACCESS_FROM_USER         1
 #endif
 
-/*
-    gcdUSER_HEAP_ALLOCATOR
-
-        Set to 1 to enable user mode heap allocator for fast memory allocation
-        and destroying. Otherwise, memory allocation/destroying in user mode
-        will be directly managed by system. Only for linux for now.
-*/
-#ifndef gcdUSER_HEAP_ALLOCATOR
-#   define gcdUSER_HEAP_ALLOCATOR               1
-#endif
-
 /*
     gcdHEAP_SIZE
 
 #endif
 
 /*
-    gcdPOWER_SUSNPEND_WHEN_IDLE
+    gcdPOWER_SUSPEND_WHEN_IDLE
 
         Set to 1 to make GPU enter gcvPOWER_SUSPEND when idle detected,
         otherwise GPU will enter gcvPOWER_IDLE.
 */
-#ifndef gcdPOWER_SUSNPEND_WHEN_IDLE
-#   define gcdPOWER_SUSNPEND_WHEN_IDLE          1
+#ifndef gcdPOWER_SUSPEND_WHEN_IDLE
+#   define gcdPOWER_SUSPEND_WHEN_IDLE          1
 #endif
 
-/*
-    gcdFPGA_BUILD
-
-        This define enables work arounds for FPGA images.
-*/
 #ifndef gcdFPGA_BUILD
-#   define gcdFPGA_BUILD                        0
+#   define gcdFPGA_BUILD                       0
 #endif
 
 /*
 #ifndef gcdGPU_TIMEOUT
 #if gcdFPGA_BUILD
 #       define gcdGPU_TIMEOUT                   0
+#       define gcdGPU_2D_TIMEOUT                0
 #   else
 #       define gcdGPU_TIMEOUT                   20000
+#       define gcdGPU_2D_TIMEOUT                4000
 #   endif
 #endif
 
 #   define gcdCMD_NO_2D_CONTEXT                 1
 #endif
 
+/*
+    gcdENABLE_BUFFER_ALIGNMENT
+
+    When enabled, video memory is allocated  with atleast 16KB aligment
+    between multiple sub-buffers.
+*/
+#ifndef gcdENABLE_BUFFER_ALIGNMENT
+#   define gcdENABLE_BUFFER_ALIGNMENT             1
+#endif
+
 /*
     gcdENABLE_BANK_ALIGNMENT
 
     When enabled, video memory is allocated bank aligned. The vendor can modify
-    _GetSurfaceBankAlignment() and gcoSURF_GetBankOffsetBytes() to define how
+    _GetSurfaceBankAlignment() and _GetBankOffsetBytes() to define how
     different types of allocations are bank and channel aligned.
     When disabled (default), no bank alignment is done.
 */
 #endif
 
 /*
-    gcdENABLE_VG
-            enable the 2D openVG
-*/
-
-#ifndef gcdENABLE_VG
-#   define gcdENABLE_VG                         0
-#endif
-
-/*
-    gcdDYNAMIC_MAP_RESERVED_MEMORY
-
-        When gcvPOOL_SYSTEM is constructed from RESERVED memory,
-        driver can map the whole reserved memory to kernel space
-        at the beginning, or just map a piece of memory when need
-        to access.
-
-        Notice:
-        -  It's only for the 2D openVG. For other cores, there is
-           _NO_ need to map reserved memory to kernel.
-        -  It's meaningless when memory is allocated by
-           gckOS_AllocateContiguous, in that case, memory is always
-           mapped by system when allocated.
+    gcdDISABLE_CORES_2D3D
+            disable the 2D3D cores for 2D openVG
 */
-#ifndef gcdDYNAMIC_MAP_RESERVED_MEMORY
-#   define gcdDYNAMIC_MAP_RESERVED_MEMORY      1
+#ifndef gcdDISABLE_CORES_2D3D
+#   define gcdDISABLE_CORES_2D3D                0
 #endif
 
 /*
         This option is only for those SOC which can't enable
         writecombine without enabling cacheable.
 */
-
 #ifndef gcdPAGED_MEMORY_CACHEABLE
 #   define gcdPAGED_MEMORY_CACHEABLE            0
 #endif
 
         When non-zero, non paged memory will be cacheable.
 */
-
 #ifndef gcdNONPAGED_MEMORY_CACHEABLE
 #   define gcdNONPAGED_MEMORY_CACHEABLE         0
 #endif
         gcdNONPAGED_MEMORY_BUFFERABLE and gcdNONPAGED_MEMORY_CACHEABLE
         can't be set 1 at same time
 */
-
 #ifndef gcdNONPAGED_MEMORY_BUFFERABLE
 #   define gcdNONPAGED_MEMORY_BUFFERABLE        1
 #endif
     gcdENABLE_INFINITE_SPEED_HW
             enable the Infinte HW , this is for 2D openVG
 */
-
 #ifndef gcdENABLE_INFINITE_SPEED_HW
 #   define gcdENABLE_INFINITE_SPEED_HW          0
 #endif
 
 /*
-    gcdENABLE_TS_DOUBLE_BUFFER
-            enable the TS double buffer, this is for 2D openVG
-*/
+    gcdMULTI_GPU
 
-#ifndef gcdENABLE_TS_DOUBLE_BUFFER
-#   define gcdENABLE_TS_DOUBLE_BUFFER           1
+    Enable/disable multi-GPU support.
+    0      : Disable multi-GPU support
+    1      : Enable one of the 3D cores
+    [2..X] : Number of 3D GPU Cores
+*/
+#ifndef gcdMULTI_GPU
+#   define gcdMULTI_GPU                         0
 #endif
 
 /*
-    gcd6000_SUPPORT
+    gcdMULTI_GPU_AFFINITY
 
-    Temporary define to enable/disable 6000 support.
- */
-#ifndef gcd6000_SUPPORT
-#   define gcd6000_SUPPORT                      0
+    Enable/disable the binding of a context to one GPU
+*/
+#ifndef gcdMULTI_GPU_AFFINITY
+#   define gcdMULTI_GPU_AFFINITY                0
 #endif
 
 /*
         idle state, and gcdPOWEROFF_TIMEOUT is also the default
         timeout in milliseconds.
  */
-
 #ifndef gcdPOWEROFF_TIMEOUT
 #   define gcdPOWEROFF_TIMEOUT                  300
 #endif
 
-/*
-    gcdUSE_VIDMEM_PER_PID
-*/
-#ifndef gcdUSE_VIDMEM_PER_PID
-#   define gcdUSE_VIDMEM_PER_PID                0
-#endif
-
 /*
     QNX_SINGLE_THREADED_DEBUGGING
 */
 #   define QNX_SINGLE_THREADED_DEBUGGING        0
 #endif
 
-/*
-    gcdENABLE_RECOVERY
-
-        This define enables the recovery code.
-*/
-#ifndef gcdENABLE_RECOVERY
-#   define gcdENABLE_RECOVERY                   1
-#endif
-
 /*
     gcdRENDER_THREADS
 
 
 */
 #ifndef gcdSMP
+#ifdef __APPLE__
+#   define gcdSMP                               1
+#else
 #   define gcdSMP                               0
 #endif
-
-/*
-    gcdSUPPORT_SWAP_RECTANGLE
-
-        Support swap with a specific rectangle.
-
-        Set the rectangle with eglSetSwapRectangleANDROID api.
-*/
-#ifndef gcdSUPPORT_SWAP_RECTANGLE
-#   define gcdSUPPORT_SWAP_RECTANGLE            0
-#endif
-
-/*
-    gcdGPU_LINEAR_BUFFER_ENABLED
-
-        Use linear buffer for GPU apps so HWC can do 2D composition.
-*/
-#ifndef gcdGPU_LINEAR_BUFFER_ENABLED
-#   define gcdGPU_LINEAR_BUFFER_ENABLED         1
-#endif
-
-/*
-    gcdENABLE_RENDER_INTO_WINDOW
-
-        Enable Render-Into-Window (ie, No-Resolve) feature on android.
-        NOTE that even if enabled, it still depends on hardware feature and
-        android application behavior. When hardware feature or application
-        behavior can not support render into window mode, it will fail back
-        to normal mode.
-        When Render-Into-Window is finally used, window back buffer of android
-        applications will be allocated matching render target tiling format.
-        Otherwise buffer tiling is decided by the above option
-        'gcdGPU_LINEAR_BUFFER_ENABLED'.
-*/
-#ifndef gcdENABLE_RENDER_INTO_WINDOW
-#   define gcdENABLE_RENDER_INTO_WINDOW         1
 #endif
 
 /*
         Use shared resolve buffer for all app buffers.
 */
 #ifndef gcdSHARED_RESOLVE_BUFFER_ENABLED
-#   define gcdSHARED_RESOLVE_BUFFER_ENABLED         0
+#   define gcdSHARED_RESOLVE_BUFFER_ENABLED     0
 #endif
 
 /*
      gcdUSE_TRIANGLE_STRIP_PATCH
  */
 #ifndef gcdUSE_TRIANGLE_STRIP_PATCH
-#   define gcdUSE_TRIANGLE_STRIP_PATCH            1
+#   define gcdUSE_TRIANGLE_STRIP_PATCH          1
 #endif
 
 /*
 #   define gcdENABLE_OUTER_CACHE_PATCH          0
 #endif
 
-#ifndef gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST
-#   ifdef ANDROID
-#      define  gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST    1
-#   else
-#      define  gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST    0
-#   endif
-#endif
+/*
+    gcdPROCESS_ADDRESS_SPACE
 
-#ifndef gcdENABLE_PE_DITHER_FIX
-#   define gcdENABLE_PE_DITHER_FIX              1
+        When non-zero, every process which attaches to galcore has its own GPU
+        address space, size of which is gcdPROCESS_ADDRESS_SPACE_SIZE.
+*/
+#ifndef gcdPROCESS_ADDRESS_SPACE
+#   define gcdPROCESS_ADDRESS_SPACE             0
+#   define gcdPROCESS_ADDRESS_SPACE_SIZE        0x80000000
 #endif
 
+/*
+    gcdSHARED_PAGETABLE
+
+        When non-zero, multiple GPUs in one chip with same MMU use
+        one shared pagetable. So that when accessing same surface,
+        they can use same GPU virtual address.
+*/
 #ifndef gcdSHARED_PAGETABLE
-#   define gcdSHARED_PAGETABLE                  1
+#   define gcdSHARED_PAGETABLE                  !gcdPROCESS_ADDRESS_SPACE
 #endif
+
 #ifndef gcdUSE_PVR
-#   define gcdUSE_PVR                                  1
+#   define gcdUSE_PVR                           1
 #endif
 
 /*
         For Linux, it's the size of a page. If this requeset fallbacks
         to gcvPOOL_CONTIGUOUS or gcvPOOL_VIRTUAL, memory will be wasted
         because they allocate a page at least.
- */
+*/
 #ifndef gcdSMALL_BLOCK_SIZE
 #   define gcdSMALL_BLOCK_SIZE                  4096
 #   define gcdRATIO_FOR_SMALL_MEMORY            32
     gcdCONTIGUOUS_SIZE_LIMIT
         When non-zero, size of video node from gcvPOOL_CONTIGUOUS is
         limited by gcdCONTIGUOUS_SIZE_LIMIT.
- */
+*/
 #ifndef gcdCONTIGUOUS_SIZE_LIMIT
 #   define gcdCONTIGUOUS_SIZE_LIMIT             0
 #endif
 
-#ifndef gcdDISALBE_EARLY_EARLY_Z
-#   define gcdDISALBE_EARLY_EARLY_Z             1
-#endif
-
-#ifndef gcdSHADER_SRC_BY_MACHINECODE
-#   define gcdSHADER_SRC_BY_MACHINECODE         1
-#endif
-
 /*
     gcdLINK_QUEUE_SIZE
 
         is be used to debug.
 */
 #ifndef gcdLINK_QUEUE_SIZE
-#   define gcdLINK_QUEUE_SIZE                  0
+#   define gcdLINK_QUEUE_SIZE                   5
 #endif
 
 /*  gcdALPHA_KILL_IN_SHADER
- *
*  Enable alpha kill inside the shader. This will be set automatically by the
*  HAL if certain states match a criteria.
- */
+
       Enable alpha kill inside the shader. This will be set automatically by the
       HAL if certain states match a criteria.
+*/
 #ifndef gcdALPHA_KILL_IN_SHADER
 #   define gcdALPHA_KILL_IN_SHADER              1
 #endif
 
-/*  gcdHIGH_PRECISION_DELAY_ENABLE
- *
- *  Enable high precision schedule delay with 1ms unit. otherwise schedule delay up to 10ms.
- *  Browser app performance will have obvious drop without this enablement
+
+
+/*
+    gcdDVFS
+
+        When non-zero, software will make use of dynamic voltage and
+        frequency feature.
  */
-#ifndef gcdHIGH_PRECISION_DELAY_ENABLE
-#   define gcdHIGH_PRECISION_DELAY_ENABLE        1
+#ifndef gcdDVFS
+#   define gcdDVFS                              0
+#   define gcdDVFS_ANAYLSE_WINDOW               4
+#   define gcdDVFS_POLLING_TIME                 (gcdDVFS_ANAYLSE_WINDOW * 4)
 #endif
 
-#ifndef gcdUSE_WCLIP_PATCH
-#   define gcdUSE_WCLIP_PATCH                   1
+#ifndef gcdSYNC
+#   define gcdSYNC                              1
 #endif
 
-#ifndef gcdHZ_L2_DISALBE
-#   define gcdHZ_L2_DISALBE                     1
+#ifndef gcdSHADER_SRC_BY_MACHINECODE
+#   define gcdSHADER_SRC_BY_MACHINECODE         1
 #endif
 
-#ifndef gcdBUGFIX15_DISABLE
-#   define gcdBUGFIX15_DISABLE                  1
+#ifndef gcdGLB27_SHADER_REPLACE_OPTIMIZATION
+#    define gcdGLB27_SHADER_REPLACE_OPTIMIZATION 1
 #endif
 
-#ifndef gcdDISABLE_HZ_FAST_CLEAR
-#   define gcdDISABLE_HZ_FAST_CLEAR             1
+/*
+    gcdSTREAM_OUT_BUFFER
+
+        Enable suppport for the secondary stream out buffer.
+*/
+#ifndef gcdSTREAM_OUT_BUFFER
+#   define gcdSTREAM_OUT_BUFFER                 0
+#   define gcdSTREAM_OUT_NAIVE_SYNC             0
 #endif
 
-#ifndef gcdUSE_NPOT_PATCH
-#define gcdUSE_NPOT_PATCH                       1
+/*
+    gcdUSE_HARDWARE_CONFIGURATION_TABLES
+
+        Enable the use of hardware configuration tables,
+        instead of query hardware and determine the features.
+*/
+#ifndef gcdUSE_HARDWARE_CONFIGURATION_TABLES
+#   define gcdUSE_HARDWARE_CONFIGURATION_TABLES 0
 #endif
 
-#ifndef gcdSYNC
-#   define gcdSYNC                              1
+/*
+    gcdSUPPORT_SWAP_RECTANGLE
+
+        Support swap with a specific rectangle.
+
+        Set the rectangle with eglSetSwapRectangleVIV api.
+        Android only.
+*/
+#ifndef gcdSUPPORT_SWAP_RECTANGLE
+#   define gcdSUPPORT_SWAP_RECTANGLE            1
 #endif
 
-#ifndef gcdENABLE_SPECIAL_HINT3
-#   define gcdENABLE_SPECIAL_HINT3               1
+/*
+    gcdGPU_LINEAR_BUFFER_ENABLED
+
+        Use linear buffer for GPU apps so HWC can do 2D composition.
+        Android only.
+*/
+#ifndef gcdGPU_LINEAR_BUFFER_ENABLED
+#   define gcdGPU_LINEAR_BUFFER_ENABLED         1
 #endif
 
-#if defined(ANDROID)
-#ifndef gcdPRE_ROTATION
-#   define gcdPRE_ROTATION                      1
+/*
+    gcdENABLE_RENDER_INTO_WINDOW
+
+        Enable Render-Into-Window (ie, No-Resolve) feature on android.
+        NOTE that even if enabled, it still depends on hardware feature and
+        android application behavior. When hardware feature or application
+        behavior can not support render into window mode, it will fail back
+        to normal mode.
+        When Render-Into-Window is finally used, window back buffer of android
+        applications will be allocated matching render target tiling format.
+        Otherwise buffer tiling is decided by the above option
+        'gcdGPU_LINEAR_BUFFER_ENABLED'.
+        Android only for now.
+*/
+#ifndef gcdENABLE_RENDER_INTO_WINDOW
+#   define gcdENABLE_RENDER_INTO_WINDOW         1
 #endif
+
+/*
+    gcdENABLE_RENDER_INTO_WINDOW_WITH_FC
+
+        Enable Direct-rendering (ie, No-Resolve) with tile status.
+        This is expremental and in development stage.
+        This will dynamically check if color compression is available.
+*/
+#ifndef gcdENABLE_RENDER_INTO_WINDOW_WITH_FC
+#   define gcdENABLE_RENDER_INTO_WINDOW_WITH_FC 1
 #endif
 
 /*
-    gcdDVFS
+    gcdENABLE_BLIT_BUFFER_PRESERVE
 
-        When non-zero, software will make use of dynamic voltage and
-        frequency feature.
- */
-#ifndef gcdDVFS
-#   define gcdDVFS                               0
-#   define gcdDVFS_ANAYLSE_WINDOW                4
-#   define gcdDVFS_POLLING_TIME                  (gcdDVFS_ANAYLSE_WINDOW * 4)
+        Render-Into-Window (ie, No-Resolve) does not include preserved swap
+        behavior.  This feature can enable buffer preserve in No-Resolve mode.
+        When enabled, previous buffer (may be part of ) will be resolve-blitted
+        to current buffer.
+*/
+#ifndef gcdENABLE_BLIT_BUFFER_PRESERVE
+#   define gcdENABLE_BLIT_BUFFER_PRESERVE       1
 #endif
 
 /*
              'acquireFenceFd' for framebuffer target for DC
  */
 #ifndef gcdANDROID_NATIVE_FENCE_SYNC
-#   define gcdANDROID_NATIVE_FENCE_SYNC        0
+#   define gcdANDROID_NATIVE_FENCE_SYNC         0
+#endif
+
+/*
+    gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC
+
+        Enable implicit android native buffer sync.
+
+        For non-HW_RENDER buffer, CPU (or other hardware) and GPU can access
+        the buffer at the same time. This is to add implicit synchronization
+        between CPU (or the hardware) and GPU.
+
+        Eventually, please do not use implicit native buffer sync, but use
+        "fence sync" or "android native fence sync" instead in libgui, which
+        can be enabled in frameworks/native/libs/gui/Android.mk. This kind
+        of synchronization should be done by app but not driver itself.
+
+        Please disable this option when either "fence sync" or
+        "android native fence sync" is enabled.
+ */
+#ifndef gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC
+#   define gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC   1
+#endif
+
+/*
+ * Implicit native buffer sync is not needed when ANDROID_native_fence_sync
+ * is available.
+ */
+#if gcdANDROID_NATIVE_FENCE_SYNC
+#   undef  gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC
+#   define gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC   0
+#endif
+
+/*
+    gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST
+
+        Enable source surface address adjust when composition on android.
+        Android only.
+*/
+#ifndef gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST
+#   define  gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST      1
+#endif
+
+/*
+    gcdUSE_WCLIP_PATCH
+
+        Enable wclipping patch.
+*/
+#ifndef gcdUSE_WCLIP_PATCH
+#   define gcdUSE_WCLIP_PATCH                   1
+#endif
+
+#ifndef gcdUSE_NPOT_PATCH
+#   define gcdUSE_NPOT_PATCH                    1
+#endif
+
+/*
+    gcd3DBLIT
+
+        TODO: Should be replaced by feature bit if available.
+*/
+#ifndef gcd3DBLIT
+#   define gcd3DBLIT                            0
+#endif
+
+/*
+    gcdINTERNAL_COMMENT
+
+        Wrap internal comment, content wrapped by it and the macor itself
+        will be removed in release driver.
+*/
+#ifndef gcdINTERNAL_COMMENT
+#   define gcdINTERNAL_COMMENT                  1
 #endif
 
+/*
+    gcdRTT_DISABLE_FC
+
+        Disable RTT FC support. For test only.
+*/
+#ifndef gcdRTT_DISABLE_FC
+#   define gcdRTT_DISABLE_FC                    0
+#endif
+
+/*
+    gcdFORCE_MIPMAP
+
+        Force generate mipmap for texture.
+*/
 #ifndef gcdFORCE_MIPMAP
-#   define gcdFORCE_MIPMAP                     0
+#   define gcdFORCE_MIPMAP                      0
+#endif
+
+/*
+    gcdFORCE_BILINEAR
+
+        Force bilinear for mipfilter.
+*/
+#ifndef gcdFORCE_BILINEAR
+#   define gcdFORCE_BILINEAR                    1
 #endif
 
 /*
-    gcdFORCE_GAL_LOAD_TWICE
+    gcdBINARY_TRACE
+
+        When non-zero, binary trace will be generated.
+
+        When gcdBINARY_TRACE_FILE_SIZE is non-zero, binary trace buffer will
+        be written to a file which size is limited to
+        gcdBINARY_TRACE_FILE_SIZE.
+*/
+#ifndef gcdBINARY_TRACE
+#   define gcdBINARY_TRACE                       0
+#   define gcdBINARY_TRACE_FILE_SIZE             0
+#endif
+
+#ifndef gcdMOVG
+#   define gcdMOVG                              0
+#if gcdMOVG
+#       define GC355_PROFILER                   1
+#   endif
+#       define gcdENABLE_TS_DOUBLE_BUFFER       1
+#else
+#if gcdMOVG
+#       define GC355_PROFILER                   1
+#       define gcdENABLE_TS_DOUBLE_BUFFER       0
+#else
+#       define gcdENABLE_TS_DOUBLE_BUFFER       1
+#endif
+#endif
 
-        When non-zero, each thread except the main one will load libGAL.so twice to avoid potential segmetantion fault when app using dlopen/dlclose.
-        If threads exit arbitrarily, libGAL.so may not unload until the process quit.
+/*  gcdINTERRUPT_STATISTIC
+ *
+ *  Monitor the event send to GPU and interrupt issued by GPU.
  */
-#ifndef gcdFORCE_GAL_LOAD_TWICE
-#   define gcdFORCE_GAL_LOAD_TWICE             0
+
+#ifndef gcdINTERRUPT_STATISTIC
+#if defined(LINUX)
+#   define gcdINTERRUPT_STATISTIC               1
+#else
+#   define gcdINTERRUPT_STATISTIC               0
+#endif
+#endif
+
+/*
+    gcdYINVERTED_RENDERING
+        When it's not zero, we will rendering display buffer
+        with top-bottom direction. All other offscreen rendering
+        will be bottom-top, which follow OpenGL ES spec.
+*/
+#ifndef gcdYINVERTED_RENDERING
+#   define gcdYINVERTED_RENDERING 1
+#endif
+
+#if gcdYINVERTED_RENDERING
+/* disable unaligned linear composition adjust in Y-inverted rendering mode. */
+#   undef  gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST
+#   define gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST 0
+#endif
+
+/*
+    gcdFENCE_WAIT_LOOP_COUNT
+        Wait fence, loop count.
+*/
+#ifndef gcdFENCE_WAIT_LOOP_COUNT
+#   define gcdFENCE_WAIT_LOOP_COUNT 100
+#endif
+
+/*
+    gcdHAL_3D_DRAWBLIT
+        When it's not zero, we will enable HAL 3D drawblit
+        to replace client 3dblit.
+*/
+#ifndef gcdHAL_3D_DRAWBLIT
+#   define gcdHAL_3D_DRAWBLIT 1
+#endif
+
+/*
+    gcdPARTIAL_FAST_CLEAR
+        When it's not zero, partial fast clear is enabled.
+        Depends on gcdHAL_3D_DRAWBLIT, if gcdHAL_3D_DRAWBLIT is not enabled,
+        only available when scissor box is completely aligned.
+        Expremental, under test.
+*/
+#ifndef gcdPARTIAL_FAST_CLEAR
+#   define gcdPARTIAL_FAST_CLEAR                1
+#endif
+
+/*
+    gcdREMOVE_SURF_ORIENTATION
+        When it's not zero, we will remove surface orientation function.
+        It wil become to a parameter of resolve function.
+*/
+#ifndef gcdREMOVE_SURF_ORIENTATION
+#   define gcdREMOVE_SURF_ORIENTATION 0
+#endif
+
+/*
+    gcdPATTERN_FAST_PATH
+         For pattern match
+*/
+#ifndef gcdPATTERN_FAST_PATH
+#   define gcdPATTERN_FAST_PATH       1
+#endif
+
+/*
+    gcdUSE_INPUT_DEVICE
+         disable input devices usage under fb mode to support fb+vdk multi-process
+*/
+#ifndef gcdUSE_INPUT_DEVICE
+#   define gcdUSE_INPUT_DEVICE        1
+#endif
+
+
+/*
+    gcdFRAMEINFO_STATISTIC
+        When enable, collect frame information.
+*/
+#ifndef gcdFRAMEINFO_STATISTIC
+
+#if (defined(DBG) && DBG) || defined(DEBUG) || defined(_DEBUG) || gcdDUMP
+#   define gcdFRAMEINFO_STATISTIC      1
+#else
+#   define gcdFRAMEINFO_STATISTIC      0
+#endif
+
+#endif
+
+/*
+    gcdPACKED_OUTPUT_ADDRESS
+        When it's not zero, ps output is already packed after linked
+*/
+#ifndef gcdPACKED_OUTPUT_ADDRESS
+#   define gcdPACKED_OUTPUT_ADDRESS             1
+#endif
+
+/*
+    gcdENABLE_THIRD_PARTY_OPERATION
+        Enable third party operation like tpc or not.
+*/
+#ifndef gcdENABLE_THIRD_PARTY_OPERATION
+#   define gcdENABLE_THIRD_PARTY_OPERATION      1
+#endif
+
+
+/*
+    Core configurations. By default enable all cores.
+*/
+#ifndef gcdENABLE_3D
+#   define gcdENABLE_3D                         1
+#endif
+
+#ifndef gcdENABLE_2D
+#   define gcdENABLE_2D                         1
+#endif
+
+#ifndef gcdENABLE_VG
+#   define gcdENABLE_VG                         0
+#endif
+
+#ifndef gcdGC355_MEM_PRINT
+#   define gcdGC355_MEM_PRINT                      0
+#else
+#if (!((gcdENABLE_3D == 0) && (gcdENABLE_2D == 0) && (gcdENABLE_VG == 1)))
+#      undef gcdGC355_MEM_PRINT
+#      define gcdGC355_MEM_PRINT                   0
+#   endif
+#endif
+
+#ifndef gcdENABLE_UNIFIED_CONSTANT
+#   define gcdENABLE_UNIFIED_CONSTANT           1
+#endif
+
+/*
+    gcdRECORD_COMMAND
+*/
+#ifndef gcdRECORD_COMMAND
+#   define gcdRECORD_COMMAND                    0
 #endif
 
 #endif /* __gc_hal_options_h_ */
index aed73aa82c34276d043db3facaf60f3dc9974861..d2abf9a5c685c22660b0f913a34dd7506906c86a 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 #ifndef __gc_hal_profiler_h_
 #define __gc_hal_profiler_h_
 
+#if VIVANTE_PROFILER_NEW
+#include "gc_hal_engine.h"
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -35,6 +39,9 @@ extern "C" {
 #define GLTEXTURE_OBJECT 30
 #define GLTEXTURE_OBJECT_BYTES 31
 
+#define GLBUFOBJ_OBJECT 40
+#define GLBUFOBJ_OBJECT_BYTES 41
+
 #if VIVANTE_PROFILER
 #define gcmPROFILE_GC(Enum, Value)  gcoPROFILER_Count(gcvNULL, Enum, Value)
 #else
@@ -52,12 +59,12 @@ extern "C" {
 #define    ES11_LINECOUNT          (ES11_POINTCOUNT        + 1)
 #define    ES11_TRIANGLECOUNT      (ES11_LINECOUNT         + 1)
 
-#define    ES20_CALLS              159
-#define    ES20_DRAWCALLS          (ES20_CALLS             + 1)
-#define    ES20_STATECHANGECALLS   (ES20_DRAWCALLS         + 1)
-#define    ES20_POINTCOUNT         (ES20_STATECHANGECALLS  + 1)
-#define    ES20_LINECOUNT          (ES20_POINTCOUNT        + 1)
-#define    ES20_TRIANGLECOUNT      (ES20_LINECOUNT         + 1)
+#define    ES30_CALLS              159
+#define    ES30_DRAWCALLS          (ES30_CALLS             + 1)
+#define    ES30_STATECHANGECALLS   (ES30_DRAWCALLS         + 1)
+#define    ES30_POINTCOUNT         (ES30_STATECHANGECALLS  + 1)
+#define    ES30_LINECOUNT          (ES30_POINTCOUNT        + 1)
+#define    ES30_TRIANGLECOUNT      (ES30_LINECOUNT         + 1)
 
 #define    VG11_CALLS              88
 #define    VG11_DRAWCALLS          (VG11_CALLS              + 1)
@@ -164,7 +171,7 @@ extern "C" {
 #define VPG_TIME        0x030000
 #define VPG_MEM         0x040000
 #define VPG_ES11        0x050000
-#define VPG_ES20        0x060000
+#define VPG_ES30        0x060000
 #define VPG_VG11        0x070000
 #define VPG_HAL         0x080000
 #define VPG_HW          0x090000
@@ -182,10 +189,11 @@ extern "C" {
 #define VPG_PVS         0x150000
 #define VPG_PPS         0x160000
 #define VPG_ES11_TIME   0x170000
-#define VPG_ES20_TIME   0x180000
+#define VPG_ES30_TIME   0x180000
 #define VPG_FRAME       0x190000
 #define VPG_ES11_DRAW   0x200000
-#define VPG_ES20_DRAW   0x210000
+#define VPG_ES30_DRAW   0x210000
+#define VPG_VG11_TIME   0x220000
 #define VPG_END         0xff0000
 
 /* Info. */
@@ -214,13 +222,13 @@ extern "C" {
 #define    VPC_ES11LINECOUNT        (VPG_ES11 +    ES11_LINECOUNT)
 #define    VPC_ES11TRIANGLECOUNT    (VPG_ES11 +    ES11_TRIANGLECOUNT)
 
-/* OpenGL ES20 Statistics Counter IDs. */
-#define    VPC_ES20CALLS            (VPG_ES20 +    ES20_CALLS)
-#define    VPC_ES20DRAWCALLS        (VPG_ES20 +    ES20_DRAWCALLS)
-#define    VPC_ES20STATECHANGECALLS (VPG_ES20 +    ES20_STATECHANGECALLS)
-#define    VPC_ES20POINTCOUNT       (VPG_ES20 +    ES20_POINTCOUNT)
-#define    VPC_ES20LINECOUNT        (VPG_ES20 +    ES20_LINECOUNT)
-#define    VPC_ES20TRIANGLECOUNT    (VPG_ES20 +    ES20_TRIANGLECOUNT)
+/* OpenGL ES30 Statistics Counter IDs. */
+#define    VPC_ES30CALLS            (VPG_ES30 +    ES30_CALLS)
+#define    VPC_ES30DRAWCALLS        (VPG_ES30 +    ES30_DRAWCALLS)
+#define    VPC_ES30STATECHANGECALLS (VPG_ES30 +    ES30_STATECHANGECALLS)
+#define    VPC_ES30POINTCOUNT       (VPG_ES30 +    ES30_POINTCOUNT)
+#define    VPC_ES30LINECOUNT        (VPG_ES30 +    ES30_LINECOUNT)
+#define    VPC_ES30TRIANGLECOUNT    (VPG_ES30 +    ES30_TRIANGLECOUNT)
 
 /* OpenVG Statistics Counter IDs. */
 #define    VPC_VG11CALLS            (VPG_VG11 +    VG11_CALLS)
@@ -329,11 +337,8 @@ extern "C" {
 
 #define VPC_PROGRAMHANDLE           (VPG_PROG + 1)
 
-#define VPG_ES20_DRAW_NO  (VPG_ES20_DRAW + 1)
-#define VPG_ES11_DRAW_NO  (VPG_ES11_DRAW + 1)
-
-#define VPG_FRAME_USEVBO (VPG_FRAME + 1)
-
+#define VPC_ES30_DRAW_NO            (VPG_ES30_DRAW + 1)
+#define VPC_ES11_DRAW_NO            (VPG_ES11_DRAW + 1)
 #endif
 
 
@@ -416,6 +421,10 @@ typedef struct _gcsPROFILER_COUNTERS
 }
 gcsPROFILER_COUNTERS;
 
+#if VIVANTE_PROFILER_NEW
+#define NumOfDrawBuf 64
+#endif
+
 /* HAL profile information. */
 typedef struct _gcsPROFILER
 {
@@ -424,6 +433,7 @@ typedef struct _gcsPROFILER
     gctBOOL         enableHW;
     gctBOOL         enableSH;
     gctBOOL         isSyncMode;
+    gctBOOL         disableOutputCounter;
 
     gctBOOL         useSocket;
     gctINT          sockFd;
@@ -476,8 +486,10 @@ typedef struct _gcsPROFILER
     gctUINT32       prevPSTexInstCount;
     gctUINT32       prevPSPixelCount;
 
-    char*           psSource;
-    char*           vsSource;
+#if VIVANTE_PROFILER_NEW
+    gcoBUFOBJ       newCounterBuf[NumOfDrawBuf];
+    gctUINT32       curBufId;
+#endif
 
 }
 gcsPROFILER;
@@ -507,7 +519,8 @@ struct _gcsSHADER_PROFILER
 /* Initialize the gcsProfiler. */
 gceSTATUS
 gcoPROFILER_Initialize(
-    IN gcoHAL Hal
+    IN gcoHAL Hal,
+    IN gctBOOL Enable
     );
 
 /* Destroy the gcProfiler. */
@@ -546,21 +559,9 @@ gcoPROFILER_EndDraw(
 /* Increase profile counter Enum by Value. */
 gceSTATUS
 gcoPROFILER_Count(
-       IN gcoHAL Hal,
-       IN gctUINT32 Enum,
-       IN gctINT Value
-       );
-
-gceSTATUS
-gcoPROFILER_ShaderSourceFS(
-    IN gcoHAL Hal,
-    IN char* source
-    );
-
-gceSTATUS
-gcoPROFILER_ShaderSourceVS(
     IN gcoHAL Hal,
-    IN char* source
+    IN gctUINT32 Enum,
+    IN gctINT Value
     );
 
 /* Profile input vertex shader. */
index 6e4d830ee74b6a75bfb67906b767f78c468dc88a..035b76e0927922af3cb5dce4e2d9ce8e66517f8b 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -33,8 +33,8 @@ extern "C" {
 ****************************** Object Declarations *****************************
 \******************************************************************************/
 
-typedef struct _gcoBRUSH *                             gcoBRUSH;
-typedef struct _gcoBRUSH_CACHE *               gcoBRUSH_CACHE;
+typedef struct _gcoBRUSH *                gcoBRUSH;
+typedef struct _gcoBRUSH_CACHE *          gcoBRUSH_CACHE;
 
 /******************************************************************************\
 ******************************** gcoBRUSH Object *******************************
@@ -43,44 +43,44 @@ typedef struct _gcoBRUSH_CACHE *            gcoBRUSH_CACHE;
 /* Create a new solid color gcoBRUSH object. */
 gceSTATUS
 gcoBRUSH_ConstructSingleColor(
-       IN gcoHAL Hal,
-       IN gctUINT32 ColorConvert,
-       IN gctUINT32 Color,
-       IN gctUINT64 Mask,
-       gcoBRUSH * Brush
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    IN gcoBRUSH Brush
+    );
 
 /******************************************************************************\
 ******************************** gcoSURF Object *******************************
@@ -89,138 +89,151 @@ gcoBRUSH_Destroy(
 /* Set cipping rectangle. */
 gceSTATUS
 gcoSURF_SetClipping(
-       IN gcoSURF Surface
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    IN gcoSURF Surface,
+    IN gctPOINTER Memory,
+    IN gctINT X,
+    IN gctINT Y,
+    IN gceSURF_FORMAT Format,
+    IN gctPOINTER PixelValue
+    );
 
 gceSTATUS
 gcoSURF_SetDither(
     IN gcoSURF Surface,
     IN gctBOOL Dither
     );
+
+gceSTATUS
+gcoSURF_Set2DSource(
+    gcoSURF Surface,
+    gceSURF_ROTATION Rotation
+    );
+
+gceSTATUS
+gcoSURF_Set2DTarget(
+    gcoSURF Surface,
+    gceSURF_ROTATION Rotation
+    );
+
 /******************************************************************************\
 ********************************** gco2D Object *********************************
 \******************************************************************************/
@@ -228,40 +241,40 @@ gcoSURF_SetDither(
 /* Construct a new gco2D object. */
 gceSTATUS
 gco2D_Construct(
-       IN gcoHAL Hal,
-       OUT gco2D * Hardware
-       );
+    IN gcoHAL Hal,
+    OUT gco2D * Hardware
+    );
 
 /* Destroy an gco2D object. */
 gceSTATUS
 gco2D_Destroy(
-       IN gco2D Hardware
-       );
+    IN gco2D Hardware
+    );
 
 /* Sets the maximum number of brushes in the brush cache. */
 gceSTATUS
 gco2D_SetBrushLimit(
-       IN gco2D Hardware,
-       IN gctUINT MaxCount
-       );
+    IN gco2D Hardware,
+    IN gctUINT MaxCount
+    );
 
 /* Flush the brush. */
 gceSTATUS
 gco2D_FlushBrush(
-       IN gco2D Engine,
-       IN gcoBRUSH Brush,
-       IN gceSURF_FORMAT Format
-       );
+    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
-       );
+    IN gco2D Engine,
+    IN gceSURF_FORMAT Format,
+    IN gctUINT32 ColorConvert,
+    IN gctUINT32 Color,
+    IN gctUINT64 Mask
+    );
 
 gceSTATUS
 gco2D_LoadMonochromeBrush(
@@ -288,57 +301,57 @@ gco2D_LoadColorBrush(
 /* 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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    IN gco2D Engine,
+    IN gctUINT32 Address,
+    IN gctUINT32 Stride,
+    IN gceSURF_FORMAT Format,
+    IN gceSURF_ROTATION Rotation,
+    IN gctUINT32 SurfaceWidth,
+    IN gctUINT32 SurfaceHeight,
+    IN gctBOOL CoordRelative
+    );
 
 gceSTATUS
 gco2D_SetColorSourceN(
@@ -355,62 +368,62 @@ gco2D_SetColorSourceN(
 /* 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
-       );
+    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
-       );
+    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
-       );
+    IN gco2D Engine,
+    IN gcsRECT_PTR SrcRect
+    );
 
 /* Set clipping rectangle. */
 gceSTATUS
 gco2D_SetClipping(
-       IN gco2D Engine,
-       IN gcsRECT_PTR Rect
-       );
+    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
-       );
+    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
-       );
+    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
@@ -423,101 +436,101 @@ gco2D_CalcStretchFactor(
 
 gceSTATUS
 gco2D_SetStretchFactors(
-       IN gco2D Engine,
-       IN gctUINT32 HorFactor,
-       IN gctUINT32 VerFactor
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    IN gco2D Engine,
+    IN gctUINT32 RectCount,
+    IN gcsRECT_PTR Rect,
+    IN gctUINT8 FgRop,
+    IN gctUINT8 BgRop,
+    IN gceSURF_FORMAT DestFormat
+    );
 
 gceSTATUS
 gco2D_Blend(
@@ -533,40 +546,40 @@ gco2D_Blend(
 /* 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
-       );
+    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
-       );
+    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
-       );
+    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
+    );
 
 gceSTATUS
 gco2D_MonoBlitEx(
@@ -588,87 +601,87 @@ gco2D_MonoBlitEx(
 /* Set kernel size. */
 gceSTATUS
 gco2D_SetKernelSize(
-       IN gco2D Engine,
-       IN gctUINT8 HorKernelSize,
-       IN gctUINT8 VerKernelSize
-       );
+    IN gco2D Engine,
+    IN gctUINT8 HorKernelSize,
+    IN gctUINT8 VerKernelSize
+    );
 
 /* Set filter type. */
 gceSTATUS
 gco2D_SetFilterType(
-       IN gco2D Engine,
-       IN gceFILTER_TYPE FilterType
-       );
+    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
-       );
+    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
-       );
+    IN gco2D Engine,
+    IN gctBOOL HorPass,
+    IN gctBOOL VerPass
+    );
 
 /* Frees the temporary buffer allocated by filter blit operation. */
 gceSTATUS
 gco2D_FreeFilterBuffer(
-       IN gco2D Engine
-       );
+    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
-       );
+    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
-       );
+    IN gco2D Engine,
+    IN gctUINT32 SrcAddress,
+    IN gctUINT SrcStride,
+    IN gctUINT32 SrcUAddress,
+    IN gctUINT SrcUStride,
+    IN gctUINT32 SrcVAddress,
+    IN gctUINT SrcVStride,
+    IN gceSURF_FORMAT SrcFormat,
+    IN gceSURF_ROTATION SrcRotation,
+    IN gctUINT32 SrcSurfaceWidth,
+    IN gctUINT32 SrcSurfaceHeight,
+    IN gcsRECT_PTR SrcRect,
+    IN gctUINT32 DestAddress,
+    IN gctUINT DestStride,
+    IN gceSURF_FORMAT DestFormat,
+    IN gceSURF_ROTATION DestRotation,
+    IN gctUINT32 DestSurfaceWidth,
+    IN gctUINT32 DestSurfaceHeight,
+    IN gcsRECT_PTR DestRect,
+    IN gcsRECT_PTR DestSubRect
+    );
 
 gceSTATUS
 gco2D_FilterBlitEx2(
@@ -699,94 +712,94 @@ gco2D_FilterBlitEx2(
 /* 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
-       );
+    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
-       );
+    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
-       );
+    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
-       );
+    IN gco2D Engine
+    );
 
 /* Retrieve the maximum number of 32-bit data chunks for a single DE command. */
 gctUINT32
 gco2D_GetMaximumDataCount(
-       void
-       );
+    void
+    );
 
 /* Retrieve the maximum number of rectangles, that can be passed in a single DE command. */
 gctUINT32
 gco2D_GetMaximumRectCount(
-       void
-       );
+    void
+    );
 
 /* Returns the pixel alignment of the surface. */
 gceSTATUS
 gco2D_GetPixelAlignment(
-       gceSURF_FORMAT Format,
-       gcsPOINT_PTR Alignment
-       );
+    gceSURF_FORMAT Format,
+    gcsPOINT_PTR Alignment
+    );
 
 /* Retrieve monochrome stream pack size. */
 gceSTATUS
 gco2D_GetPackSize(
-       IN gceSURF_MONOPACK StreamPack,
-       OUT gctUINT32 * PackWidth,
-       OUT gctUINT32 * PackHeight
-       );
+    IN gceSURF_MONOPACK StreamPack,
+    OUT gctUINT32 * PackWidth,
+    OUT gctUINT32 * PackHeight
+    );
 
 /* Flush the 2D pipeline. */
 gceSTATUS
 gco2D_Flush(
-       IN gco2D Engine
-       );
+    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
-       );
+    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
-       );
+    IN gco2D Engine,
+    IN gctBOOL HorizontalMirror,
+    IN gctBOOL VerticalMirror
+    );
 
 /*
  * Set the transparency for source, destination and pattern.
@@ -799,82 +812,82 @@ gco2D_SetTransparencyAdvancedEx(
     IN gce2D_TRANSPARENCY DstTransparency,
     IN gce2D_TRANSPARENCY PatTransparency,
     IN gctBOOL EnableDFBColorKeyMode
-       );
+    );
 
 /* Set the transparency for source, destination and pattern. */
 gceSTATUS
 gco2D_SetTransparencyAdvanced(
-       IN gco2D Engine,
-       IN gce2D_TRANSPARENCY SrcTransparency,
-       IN gce2D_TRANSPARENCY DstTransparency,
-       IN gce2D_TRANSPARENCY PatTransparency
-       );
+    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
-       );
+    IN gco2D Engine,
+    IN gctUINT32 ColorKey
+    );
 
 /* Set the source color key range. */
 gceSTATUS
 gco2D_SetSourceColorKeyRangeAdvanced(
-       IN gco2D Engine,
-       IN gctUINT32 ColorKeyLow,
-       IN gctUINT32 ColorKeyHigh
-       );
+    IN gco2D Engine,
+    IN gctUINT32 ColorKeyLow,
+    IN gctUINT32 ColorKeyHigh
+    );
 
 /* Set the target color key. */
 gceSTATUS
 gco2D_SetTargetColorKeyAdvanced(
-       IN gco2D Engine,
-       IN gctUINT32 ColorKey
-       );
+    IN gco2D Engine,
+    IN gctUINT32 ColorKey
+    );
 
 /* Set the target color key range. */
 gceSTATUS
 gco2D_SetTargetColorKeyRangeAdvanced(
-       IN gco2D Engine,
-       IN gctUINT32 ColorKeyLow,
-       IN gctUINT32 ColorKeyHigh
-       );
+    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
-       );
+    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
-       );
+    IN gco2D Engine,
+    IN gctUINT32 Color32
+    );
 
 /* Setup the target global color value in ARGB8 format. */
 gceSTATUS gco2D_SetTargetGlobalColorAdvanced(
-       IN gco2D Engine,
-       IN gctUINT32 Color32
-       );
+    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
-       );
+    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
-       );
+    IN gco2D Engine,
+    IN gctUINT32 Cycles
+    );
 
 #if VIVANTE_PROFILER
 /* Read the profile registers available in the 2D engine and sets them in the profile.
@@ -882,17 +895,17 @@ gco2D_SetAutoFlushCycles(
 */
 gceSTATUS
 gco2D_ProfileEngine(
-       IN gco2D Engine,
-       OPTIONAL gcs2D_PROFILE_PTR Profile
-       );
+    IN gco2D Engine,
+    OPTIONAL gcs2D_PROFILE_PTR Profile
+    );
 #endif
 
 /* Enable or disable 2D dithering. */
 gceSTATUS
 gco2D_EnableDither(
-       IN gco2D Engine,
-       IN gctBOOL Enable
-       );
+    IN gco2D Engine,
+    IN gctBOOL Enable
+    );
 
 gceSTATUS
 gco2D_SetGenericSource(
@@ -1003,6 +1016,21 @@ gco2D_SetTargetRect(
     IN gcsRECT_PTR Rect
     );
 
+gceSTATUS
+gco2D_Set2DEngine(
+    IN gco2D Engine
+    );
+
+gceSTATUS
+gco2D_UnSet2DEngine(
+    IN gco2D Engine
+    );
+
+gceSTATUS
+gco2D_Get2DEngine(
+    OUT gco2D * Engine
+    );
+
 #ifdef __cplusplus
 }
 #endif
index 6c10fbf78a323214dd2641cf87b11bda410412fd..745a1044c0d2d595d5314fd6a22d6ad9dfc94b63 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -49,8 +49,9 @@
 #define gckOS_FreeContiguous            gcmHAL2D(gckOS_FreeContiguous)
 #define gckOS_GetPageSize               gcmHAL2D(gckOS_GetPageSize)
 #define gckOS_GetPhysicalAddress        gcmHAL2D(gckOS_GetPhysicalAddress)
-#define gckOS_GetPhysicalAddressProcess     gcmHAL2D(gckOS_GetPhysicalAddressProcess)
-#define gckOS_MapPhysical                   gcmHAL2D(gckOS_MapPhysical)
+#define gckOS_UserLogicalToPhysical     gcmHAL2D(gckOS_UserLogicalToPhysical)
+#define gckOS_GetPhysicalAddressProcess gcmHAL2D(gckOS_GetPhysicalAddressProcess)
+#define gckOS_MapPhysical               gcmHAL2D(gckOS_MapPhysical)
 #define gckOS_UnmapPhysical             gcmHAL2D(gckOS_UnmapPhysical)
 #define gckOS_ReadRegister              gcmHAL2D(gckOS_ReadRegister)
 #define gckOS_WriteRegister             gcmHAL2D(gckOS_WriteRegister)
@@ -77,7 +78,6 @@
 #define gckOS_QueryNeedCopy             gcmHAL2D(gckOS_QueryNeedCopy)
 #define gckOS_CopyFromUserData          gcmHAL2D(gckOS_CopyFromUserData)
 #define gckOS_CopyToUserData            gcmHAL2D(gckOS_CopyToUserData)
-#define gckOS_MapUserPhysical           gcmHAL2D(gckOS_MapUserPhysical)
 #define gckOS_SuspendInterrupt          gcmHAL2D(gckOS_SuspendInterrupt)
 #define gckOS_ResumeInterrupt           gcmHAL2D(gckOS_ResumeInterrupt)
 #define gckOS_GetBaseAddress            gcmHAL2D(gckOS_GetBaseAddress)
 #define gckHARDWARE_Execute             gcmHAL2D(gckHARDWARE_Execute)
 #define gckHARDWARE_End                 gcmHAL2D(gckHARDWARE_End)
 #define gckHARDWARE_Nop                 gcmHAL2D(gckHARDWARE_Nop)
-#define gckHARDWARE_Wait                gcmHAL2D(gckHARDWARE_Wait)
 #define gckHARDWARE_PipeSelect          gcmHAL2D(gckHARDWARE_PipeSelect)
 #define gckHARDWARE_Link                gcmHAL2D(gckHARDWARE_Link)
 #define gckHARDWARE_Event               gcmHAL2D(gckHARDWARE_Event)
 #define gckHARDWARE_AlignToTile         gcmHAL2D(gckHARDWARE_AlignToTile)
 #define gckHARDWARE_UpdateQueueTail     gcmHAL2D(gckHARDWARE_UpdateQueueTail)
 #define gckHARDWARE_ConvertLogical      gcmHAL2D(gckHARDWARE_ConvertLogical)
-#define gckHARDWARE_ConvertPhysical     gcmHAL2D(gckHARDWARE_ConvertPhysical)
 #define gckHARDWARE_Interrupt           gcmHAL2D(gckHARDWARE_Interrupt)
 #define gckHARDWARE_SetMMU              gcmHAL2D(gckHARDWARE_SetMMU)
 #define gckHARDWARE_FlushMMU            gcmHAL2D(gckHARDWARE_FlushMMU)
 #define gckMMU_Destroy                  gcmHAL2D(gckMMU_Destroy)
 #define gckMMU_AllocatePages            gcmHAL2D(gckMMU_AllocatePages)
 #define gckMMU_FreePages                gcmHAL2D(gckMMU_FreePages)
-#define gckMMU_InsertNode               gcmHAL2D(gckMMU_InsertNode)
-#define gckMMU_RemoveNode               gcmHAL2D(gckMMU_RemoveNode)
-#define gckMMU_FreeHandleMemory         gcmHAL2D(gckMMU_FreeHandleMemory)
 #define gckMMU_Test                     gcmHAL2D(gckMMU_Test)
 #define gckHARDWARE_QueryProfileRegisters     gcmHAL2D(gckHARDWARE_QueryProfileRegisters)
 
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_security_interface.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_security_interface.h
new file mode 100644 (file)
index 0000000..cb86d76
--- /dev/null
@@ -0,0 +1,137 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2014 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_SECURITY_INTERFACE_H_
+#define _GC_HAL_SECURITY_INTERFACE_H_
+/*!
+ @brief Command codes between kernel module and TrustZone
+ @discussion
+ Critical services must be done in TrustZone to avoid sensitive content leak. Most of kernel module is kept in non-Secure os to minimize
+ code in TrustZone.
+ */
+typedef enum kernel_packet_command {
+    KERNEL_START_COMMAND,
+    KERNEL_SUBMIT,
+    KERNEL_MAP_MEMORY,                    /* */
+    KERNEL_UNMAP_MEMORY,
+    KERNEL_ALLOCATE_SECRUE_MEMORY,        /*! Security memory management. */
+    KERNEL_FREE_SECURE_MEMORY,
+    KERNEL_EXECUTE,                       /* Execute a command buffer. */
+} kernel_packet_command_t;
+
+/*!
+ @brief gckCOMMAND Object requests TrustZone to start FE.
+ @discussion
+ DMA enabled register can only be written in TrustZone to avoid GPU from jumping to a hacked code.
+ Kernel module need use these command to ask TrustZone start command parser.
+ */
+struct kernel_start_command {
+    kernel_packet_command_t command;      /*! The command (always needs to be the first entry in a structure). */
+    gctUINT8       gpu;                    /*! Which GPU. */
+};
+
+/*!
+ @brief gckCOMMAND Object requests TrustZone to submit command buffer.
+ @discussion
+ Code in trustzone will check content of command buffer after copying command buffer to TrustZone.
+ */
+struct kernel_submit {
+    kernel_packet_command_t command;      /*! The command (always needs to be the first entry in a structure). */
+    gctUINT8       gpu;                    /*! Which GPU. */
+    gctUINT8       kernel_command;         /*! Whether it is a kernel command. */
+    gctUINT32      command_buffer_handle;  /*! Handle to command buffer. */
+    gctUINT32      offset;                  /* Offset in command buffer. */
+    gctUINT32 *    command_buffer;         /*! Content of command buffer need to be submit. */
+    gctUINT32      command_buffer_length;  /*! Length of command buffer. */
+};
+
+
+/*!
+ @brief gckVIDMEM Object requests TrustZone to allocate security memory.
+ @discussion
+ Allocate a buffer from security GPU memory.
+ */
+struct kernel_allocate_security_memory {
+    kernel_packet_command_t command;      /*! The command (always needs to be the first entry in a structure). */
+    gctUINT32      bytes;                  /*! Requested bytes. */
+    gctUINT32      memory_handle;          /*! Handle of allocated memory. */
+};
+
+/*!
+ @brief gckVIDMEM Object requests TrustZone to allocate security memory.
+ @discussion
+ Free a video memory buffer from security GPU memory.
+ */
+struct kernel_free_security_memory {
+    kernel_packet_command_t command;      /*! The command (always needs to be the first entry in a structure). */
+    gctUINT32      memory_handle;          /*! Handle of allocated memory. */
+};
+
+struct kernel_execute {
+    kernel_packet_command_t command;      /*! The command (always needs to be the first entry in a structure). */
+    gctUINT8       gpu;                    /*! Which GPU. */
+    gctUINT8       kernel_command;         /*! Whether it is a kernel command. */
+    gctUINT32 *    command_buffer;         /*! Content of command buffer need to be submit. */
+    gctUINT32      command_buffer_length;  /*! Length of command buffer. */
+};
+
+typedef struct kernel_map_scatter_gather {
+    gctUINT32      bytes;
+    gctUINT32      physical;
+    struct kernel_map_scatter_gather *next;
+}
+kernel_map_scatter_gather_t;
+
+struct kernel_map_memory {
+    kernel_packet_command_t command;
+    kernel_map_scatter_gather_t *scatter;
+    gctUINT32       *physicals;
+    gctUINT32       pageCount;
+    gctUINT32       gpuAddress;
+};
+
+struct kernel_unmap_memory {
+    gctUINT32       gpuAddress;
+    gctUINT32       pageCount;
+};
+
+typedef struct _gcsTA_INTERFACE {
+    kernel_packet_command_t command;
+    union {
+        struct kernel_submit                   Submit;
+        struct kernel_start_command            StartCommand;
+        struct kernel_allocate_security_memory AllocateSecurityMemory;
+        struct kernel_execute                  Execute;
+        struct kernel_map_memory               MapMemory;
+        struct kernel_unmap_memory             UnmapMemory;
+    } u;
+    gceSTATUS result;
+} gcsTA_INTERFACE;
+
+enum {
+    gcvTA_COMMAND_INIT,
+    gcvTA_COMMAND_DISPATCH,
+
+    gcvTA_CALLBACK_ALLOC_SECURE_MEM,
+    gcvTA_CALLBACK_FREE_SECURE_MEM,
+};
+
+#endif
index 82336e89b418f18421790dc4cab50c265cc00de3..07b8e725f29aacddb936cb10e4cbaad9b74b5f30 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -30,6 +30,7 @@
 */
 #define VIV_STAT_FRAME_BUFFER_SIZE              30
 
+
 /*
     Total number of frames sampled for a mode. This means
 
@@ -64,14 +65,6 @@ typedef struct _gcsSTATISTICS_EARLYZ
 gcsSTATISTICS_EARLYZ;
 
 
-/* Defines the statistical data keys monitored by the statistics module */
-typedef enum _gceSTATISTICS_Call
-{
-       gcvSTAT_ES11_GLDRAWELEMENTS      =   1,
-}
-gceSTATISTICS_Call;
-
-
 /* HAL statistics information. */
 typedef struct _gcsSTATISTICS
 {
@@ -79,8 +72,6 @@ typedef struct _gcsSTATISTICS
     gctUINT64                   previousFrameTime;
     gctUINT                     frame;
     gcsSTATISTICS_EARLYZ        earlyZ;
-       gctUINT                                         ES11_drawElementsCount;
-       gctBOOL                                         applyRTestVAFix;
 }
 gcsSTATISTICS;
 
@@ -104,12 +95,5 @@ gcfSTATISTICS_DisableDynamicEarlyZ (
     IN gctBOOL Disabled
     );
 
-/* Checks whether or not glDrawArray function call will be discarded */
-gctBOOL
-gcfSTATISTICS_DiscardCall(
-       gceSTATISTICS_Call Function
-       );
-
-
 #endif /*__gc_hal_statistics_h_ */
 
index b44652944c922e72844534077f91b5d23ffd742d..51a686cb72570aecbfa56d7552f292433c3d785a 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 #include "gc_hal_version.h"
 #include "gc_hal_options.h"
 
+#if !defined(VIV_KMD)
+#if defined(__KERNEL__)
+#include "linux/version.h"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    typedef unsigned long uintptr_t;
+#   endif
+#   include "linux/types.h"
+#elif defined(UNDER_CE)
+#include <crtdefs.h>
+#elif defined(_MSC_VER) && (_MSC_VER <= 1500)
+#include <crtdefs.h>
+#include "vadefs.h"
+#elif defined(__QNXNTO__)
+#define _QNX_SOURCE
+#include <stdint.h>
+#include <stddef.h>
+#else
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#endif
+#endif
+
 #ifdef _WIN32
 #pragma warning(disable:4127)   /* Conditional expression is constant (do { }
                                 ** while(0)). */
@@ -33,6 +56,8 @@
 #pragma warning(disable:4131)   /* Uses old-style declarator (for Bison and
                                 ** Flex generated files). */
 #pragma warning(disable:4206)   /* Translation unit is empty. */
+#pragma warning(disable:4214)   /* Nonstandard extension used :
+                                ** bit field types other than int. */
 #endif
 
 #ifdef __cplusplus
@@ -44,26 +69,27 @@ extern "C" {
 */
 
 #if defined(__GNUC__)
-#   define gcdHAS_ELLIPSES      1       /* GCC always has it. */
+#   define gcdHAS_ELLIPSIS      1       /* GCC always has it. */
 #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-#   define gcdHAS_ELLIPSES      1       /* C99 has it. */
+#   define gcdHAS_ELLIPSIS      1       /* C99 has it. */
 #elif defined(_MSC_VER) && (_MSC_VER >= 1500)
-#   define gcdHAS_ELLIPSES      1       /* MSVC 2007+ has it. */
+#   define gcdHAS_ELLIPSIS      1       /* MSVC 2007+ has it. */
 #elif defined(UNDER_CE)
 #if UNDER_CE >= 600
-#       define gcdHAS_ELLIPSES  1
+#       define gcdHAS_ELLIPSIS  1
 #   else
-#       define gcdHAS_ELLIPSES  0
+#       define gcdHAS_ELLIPSIS  0
 #   endif
 #else
-#   error "gcdHAS_ELLIPSES: Platform could not be determined"
+#   error "gcdHAS_ELLIPSIS: Platform could not be determined"
 #endif
 
 /******************************************************************************\
 ************************************ Keyword ***********************************
 \******************************************************************************/
-
-#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
+#if defined(ANDROID) && defined(__BIONIC_FORTIFY)
+#   define gcmINLINE            __inline__ __attribute__ ((always_inline)) __attribute__ ((gnu_inline)) __attribute__ ((artificial))
+#elif ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__APPLE__))
 #   define gcmINLINE            inline      /* C99 keyword. */
 #elif defined(__GNUC__)
 #   define gcmINLINE            __inline__  /* GNU keyword. */
@@ -128,7 +154,6 @@ typedef int                     gctBOOL;
 typedef gctBOOL *               gctBOOL_PTR;
 
 typedef int                     gctINT;
-typedef long                    gctLONG;
 typedef signed char             gctINT8;
 typedef signed short            gctINT16;
 typedef signed int              gctINT32;
@@ -145,7 +170,7 @@ typedef unsigned char           gctUINT8;
 typedef unsigned short          gctUINT16;
 typedef unsigned int            gctUINT32;
 typedef unsigned long long      gctUINT64;
-typedef unsigned long           gctUINTPTR_T;
+typedef uintptr_t               gctUINTPTR_T;
 
 typedef gctUINT *               gctUINT_PTR;
 typedef gctUINT8 *              gctUINT8_PTR;
@@ -153,8 +178,9 @@ typedef gctUINT16 *             gctUINT16_PTR;
 typedef gctUINT32 *             gctUINT32_PTR;
 typedef gctUINT64 *             gctUINT64_PTR;
 
-typedef unsigned long           gctSIZE_T;
+typedef size_t                  gctSIZE_T;
 typedef gctSIZE_T *             gctSIZE_T_PTR;
+typedef gctUINT32               gctTRACE;
 
 #ifdef __cplusplus
 #   define gcvNULL              0
@@ -162,6 +188,24 @@ typedef gctSIZE_T *             gctSIZE_T_PTR;
 #   define gcvNULL              ((void *) 0)
 #endif
 
+#define gcvMAXINT8              0x7f
+#define gcvMININT8              0x80
+#define gcvMAXINT16             0x7fff
+#define gcvMININT16             0x8000
+#define gcvMAXINT32             0x7fffffff
+#define gcvMININT32             0x80000000
+#define gcvMAXINT64             0x7fffffffffffffff
+#define gcvMININT64             0x8000000000000000
+#define gcvMAXUINT8             0xff
+#define gcvMINUINT8             0x0
+#define gcvMAXUINT16            0xffff
+#define gcvMINUINT16            0x8000
+#define gcvMAXUINT32            0xffffffff
+#define gcvMINUINT32            0x80000000
+#define gcvMAXUINT64            0xffffffffffffffff
+#define gcvMINUINT64            0x8000000000000000
+#define gcvMAXUINTPTR_T         (~(gctUINTPTR_T)0)
+
 typedef float                   gctFLOAT;
 typedef signed int              gctFIXED_POINT;
 typedef float *                 gctFLOAT_PTR;
@@ -173,8 +217,9 @@ typedef void *                  gctSIGNAL;
 typedef void *                  gctWINDOW;
 typedef void *                  gctIMAGE;
 typedef void *                  gctSYNC_POINT;
+typedef void *                  gctSHBUF;
 
-typedef void *                                 gctSEMAPHORE;
+typedef void *                  gctSEMAPHORE;
 
 typedef void *                  gctPOINTER;
 typedef const void *            gctCONST_POINTER;
@@ -204,6 +249,90 @@ gcuFLOAT_UINT32;
 #define gcvNEGONE_X             ((gctFIXED_POINT) 0xFFFF0000)
 #define gcvTWO_X                ((gctFIXED_POINT) 0x00020000)
 
+
+
+#define gcmFIXEDCLAMP_NEG1_TO_1(_x) \
+    (((_x) < gcvNEGONE_X) \
+        ? gcvNEGONE_X \
+        : (((_x) > gcvONE_X) \
+            ? gcvONE_X \
+            : (_x)))
+
+#define gcmFLOATCLAMP_NEG1_TO_1(_f) \
+    (((_f) < -1.0f) \
+        ? -1.0f \
+        : (((_f) > 1.0f) \
+            ? 1.0f \
+            : (_f)))
+
+
+#define gcmFIXEDCLAMP_0_TO_1(_x) \
+    (((_x) < 0) \
+        ? 0 \
+        : (((_x) > gcvONE_X) \
+            ? gcvONE_X \
+            : (_x)))
+
+#define gcmFLOATCLAMP_0_TO_1(_f) \
+    (((_f) < 0.0f) \
+        ? 0.0f \
+        : (((_f) > 1.0f) \
+            ? 1.0f \
+            : (_f)))
+
+
+/******************************************************************************\
+******************************* Multicast Values *******************************
+\******************************************************************************/
+
+/* Value types. */
+typedef enum _gceVALUE_TYPE
+{
+    gcvVALUE_UINT = 0x0,
+    gcvVALUE_FIXED,
+    gcvVALUE_FLOAT,
+    gcvVALUE_INT,
+
+    /*
+    ** The value need be unsigned denormalized. clamp (0.0-1.0) should be done first.
+    */
+    gcvVALUE_FLAG_UNSIGNED_DENORM = 0x00010000,
+
+    /*
+    ** The value need be signed denormalized. clamp (-1.0-1.0) should be done first.
+    */
+    gcvVALUE_FLAG_SIGNED_DENORM   = 0x00020000,
+
+    /*
+    ** The value need to gammar
+    */
+    gcvVALUE_FLAG_GAMMAR          = 0x00040000,
+
+    /*
+    ** The value need to convert from float to float16
+    */
+    gcvVALUE_FLAG_FLOAT_TO_FLOAT16 = 0x0080000,
+
+    /*
+    ** Mask for flag field.
+    */
+    gcvVALUE_FLAG_MASK            = 0xFFFF0000,
+}
+gceVALUE_TYPE;
+
+/* Value unions. */
+typedef union _gcuVALUE
+{
+    gctUINT                     uintValue;
+    gctFIXED_POINT              fixedValue;
+    gctFLOAT                    floatValue;
+    gctINT                      intValue;
+}
+gcuVALUE;
+
+
+
+
 /* Stringizing macro. */
 #define gcmSTRING(Value)        #Value
 
@@ -256,6 +385,7 @@ gcs2D_PROFILE;
 
 #define IN
 #define OUT
+#define INOUT
 #define OPTIONAL
 
 /******************************************************************************\
@@ -283,11 +413,9 @@ typedef enum _gceSTATUS
     gcvSTATUS_INVALID_CONFIG        =   15,
     gcvSTATUS_CHANGED               =   16,
     gcvSTATUS_NOT_SUPPORT_DITHER    =   17,
-       gcvSTATUS_EXECUTED                              =       18,
+    gcvSTATUS_EXECUTED              =   18,
     gcvSTATUS_TERMINATE             =   19,
 
-    gcvSTATUS_CONVERT_TO_SINGLE_STREAM    =   20,
-
     gcvSTATUS_INVALID_ARGUMENT      =   -1,
     gcvSTATUS_INVALID_OBJECT        =   -2,
     gcvSTATUS_OUT_OF_MEMORY         =   -3,
@@ -318,20 +446,37 @@ typedef enum _gceSTATUS
     gcvSTATUS_NOT_MULTI_PIPE_ALIGNED =   -28,
 
     /* 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,
-    gcvSTATUS_UNIFORM_TYPE_MISMATCH =   -1009,
+    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,
+    gcvSTATUS_UNIFORM_MISMATCH                  =   -1009,
+    gcvSTATUS_UNSAT_LIB_SYMBOL                  =   -1010,
+    gcvSTATUS_TOO_MANY_SHADERS                  =   -1011,
+    gcvSTATUS_LINK_INVALID_SHADERS              =   -1012,
+    gcvSTATUS_CS_NO_WORKGROUP_SIZE              =   -1013,
+    gcvSTATUS_LINK_LIB_ERROR                    =   -1014,
+    gcvSTATUS_SHADER_VERSION_MISMATCH           =   -1015,
+    gcvSTATUS_TOO_MANY_INSTRUCTION              =   -1016,
+    gcvSTATUS_SSBO_MISMATCH                     =   -1017,
+    gcvSTATUS_TOO_MANY_OUTPUT                   =   -1018,
+    gcvSTATUS_TOO_MANY_INPUT                    =   -1019,
+    gcvSTATUS_NOT_SUPPORT_CL                    =   -1020,
+    gcvSTATUS_NOT_SUPPORT_INTEGER               =   -1021,
+    gcvSTATUS_UNIFORM_TYPE_MISMATCH             =   -1022,
+    gcvSTATUS_TOO_MANY_SAMPLER                  =   -1023,
 
     /* Compiler errors. */
-    gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR = -2000,
-    gcvSTATUS_COMPILER_FE_PARSER_ERROR = -2001,
+    gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR    =   -2000,
+    gcvSTATUS_COMPILER_FE_PARSER_ERROR          =   -2001,
+
+    /* Recompilation Errors */
+    gcvSTATUS_RECOMPILER_CONVERT_UNIMPLEMENTED  =   -3000,
 }
 gceSTATUS;
 
@@ -567,254 +712,6 @@ gceSTATUS;
     ((Address & (~0U << Name ## _LSB)) == (Name ## _Address >> 2)) \
 )
 
-/*******************************************************************************
-**
-**  A set of macros to aid state loading.
-**
-**  ARGUMENTS:
-**
-**      CommandBuffer   Pointer to a gcoCMDBUF object.
-**      StateDelta      Pointer to a gcsSTATE_DELTA state delta structure.
-**      Memory          Destination memory pointer of gctUINT32_PTR type.
-**      PartOfContext   Whether or not the state is a part of the context.
-**      FixedPoint      Whether or not the state is of the fixed point format.
-**      Count           Number of consecutive states to be loaded.
-**      Address         State address.
-**      Data            Data to be set to the state.
-*/
-
-/*----------------------------------------------------------------------------*/
-
-#if gcmIS_DEBUG(gcdDEBUG_CODE)
-
-#   define gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count) \
-        CommandBuffer->lastLoadStatePtr     = gcmPTR_TO_UINT64(Memory); \
-        CommandBuffer->lastLoadStateAddress = Address; \
-        CommandBuffer->lastLoadStateCount   = Count
-
-#   define gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address) \
-        gcmASSERT( \
-            (gctUINT) (Memory  - gcmUINT64_TO_TYPE(CommandBuffer->lastLoadStatePtr, gctUINT32_PTR) - 1) \
-            == \
-            (gctUINT) (Address - CommandBuffer->lastLoadStateAddress) \
-            ); \
-        \
-        gcmASSERT(CommandBuffer->lastLoadStateCount > 0); \
-        \
-        CommandBuffer->lastLoadStateCount -= 1
-
-#   define gcmVERIFYLOADSTATEDONE(CommandBuffer) \
-        gcmASSERT(CommandBuffer->lastLoadStateCount == 0)
-
-#else
-
-#   define gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count)
-#   define gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address)
-#   define gcmVERIFYLOADSTATEDONE(CommandBuffer)
-
-#endif
-
-#if gcdSECURE_USER
-
-#   define gcmDEFINESECUREUSER() \
-        gctUINT         __secure_user_offset__; \
-        gctUINT32_PTR   __secure_user_hintArray__;
-
-#   define gcmBEGINSECUREUSER() \
-        __secure_user_offset__ = reserve->lastOffset; \
-        \
-        __secure_user_hintArray__ = gcmUINT64_TO_PTR(reserve->hintArrayTail)
-
-#   define gcmENDSECUREUSER() \
-        reserve->hintArrayTail = gcmPTR_TO_UINT64(__secure_user_hintArray__)
-
-#   define gcmSKIPSECUREUSER() \
-        __secure_user_offset__ += gcmSIZEOF(gctUINT32)
-
-#   define gcmUPDATESECUREUSER() \
-        *__secure_user_hintArray__ = __secure_user_offset__; \
-        \
-        __secure_user_offset__    += gcmSIZEOF(gctUINT32); \
-        __secure_user_hintArray__ += 1
-
-#else
-
-#   define gcmDEFINESECUREUSER()
-#   define gcmBEGINSECUREUSER()
-#   define gcmENDSECUREUSER()
-#   define gcmSKIPSECUREUSER()
-#   define gcmUPDATESECUREUSER()
-
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-#if gcdDUMP
-#   define gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, Data) \
-        if (FixedPoint) \
-        { \
-            gcmDUMP(gcvNULL, "@[state.x 0x%04X 0x%08X]", \
-                Address, Data \
-                ); \
-        } \
-        else \
-        { \
-            gcmDUMP(gcvNULL, "@[state 0x%04X 0x%08X]", \
-                Address, Data \
-                ); \
-        }
-#else
-#   define gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, Data)
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-#define gcmDEFINESTATEBUFFER(CommandBuffer, StateDelta, Memory, ReserveSize) \
-    gcmDEFINESECUREUSER() \
-    gctSIZE_T ReserveSize; \
-    gcoCMDBUF CommandBuffer; \
-    gctUINT32_PTR Memory; \
-    gcsSTATE_DELTA_PTR StateDelta
-
-#define gcmBEGINSTATEBUFFER(Hardware, CommandBuffer, StateDelta, Memory, ReserveSize) \
-{ \
-    gcmONERROR(gcoBUFFER_Reserve( \
-        Hardware->buffer, ReserveSize, gcvTRUE, &CommandBuffer \
-        )); \
-    \
-    Memory =  gcmUINT64_TO_PTR(CommandBuffer->lastReserve); \
-    \
-    StateDelta = Hardware->delta; \
-    \
-    gcmBEGINSECUREUSER(); \
-}
-
-#define gcmENDSTATEBUFFER(CommandBuffer, Memory, ReserveSize) \
-{ \
-    gcmENDSECUREUSER(); \
-    \
-    gcmASSERT( \
-        gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT8_PTR) + ReserveSize \
-        == \
-         (gctUINT8_PTR) Memory \
-        ); \
-}
-
-/*----------------------------------------------------------------------------*/
-
-#define gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, Count) \
-{ \
-    gcmASSERT(((Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT32_PTR)) & 1) == 0); \
-    gcmASSERT((gctUINT32)Count <= 1024); \
-    \
-    gcmVERIFYLOADSTATEDONE(CommandBuffer); \
-    \
-    gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count); \
-    \
-    *Memory++ \
-        = gcmSETFIELDVALUE(0, AQ_COMMAND_LOAD_STATE_COMMAND, OPCODE,  LOAD_STATE) \
-        | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, FLOAT,   FixedPoint) \
-        | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, COUNT,   Count) \
-        | gcmSETFIELD     (0, AQ_COMMAND_LOAD_STATE_COMMAND, ADDRESS, Address); \
-    \
-    gcmSKIPSECUREUSER(); \
-}
-
-#define gcmENDSTATEBATCH(CommandBuffer, Memory) \
-{ \
-    gcmVERIFYLOADSTATEDONE(CommandBuffer); \
-    \
-    gcmASSERT(((Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT32_PTR)) & 1) == 0); \
-}
-
-/*----------------------------------------------------------------------------*/
-
-#define gcmSETSTATEDATA(StateDelta, CommandBuffer, Memory, FixedPoint, \
-                        Address, Data) \
-{ \
-    gctUINT32 __temp_data32__; \
-    \
-    gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
-    \
-    __temp_data32__ = Data; \
-    \
-    *Memory++ = __temp_data32__; \
-    \
-    gcoHARDWARE_UpdateDelta( \
-        StateDelta, FixedPoint, Address, 0, __temp_data32__ \
-        ); \
-    \
-    gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
-    \
-    gcmUPDATESECUREUSER(); \
-}
-
-#define gcmSETCTRLSTATE(StateDelta, CommandBuffer, Memory, Address, Data) \
-{ \
-    gctUINT32 __temp_data32__; \
-    \
-    gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
-    \
-    __temp_data32__ = Data; \
-    \
-    *Memory++ = __temp_data32__; \
-    \
-    gcmDUMPSTATEDATA(StateDelta, gcvFALSE, Address, __temp_data32__); \
-    \
-    gcmSKIPSECUREUSER(); \
-}
-
-#define gcmSETFILLER(CommandBuffer, Memory) \
-{ \
-    gcmVERIFYLOADSTATEDONE(CommandBuffer); \
-    \
-    Memory += 1; \
-    \
-    gcmSKIPSECUREUSER(); \
-}
-
-/*----------------------------------------------------------------------------*/
-
-#define gcmSETSINGLESTATE(StateDelta, CommandBuffer, Memory, FixedPoint, \
-                          Address, Data) \
-{ \
-    gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
-    gcmSETSTATEDATA(StateDelta, CommandBuffer, Memory, FixedPoint, \
-                    Address, Data); \
-    gcmENDSTATEBATCH(CommandBuffer, Memory); \
-}
-
-#define gcmSETSINGLECTRLSTATE(StateDelta, CommandBuffer, Memory, FixedPoint, \
-                              Address, Data) \
-{ \
-    gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
-    gcmSETCTRLSTATE(StateDelta, CommandBuffer, Memory, Address, Data); \
-    gcmENDSTATEBATCH(CommandBuffer, Memory); \
-}
-
-
-/*******************************************************************************
-**
-**  gcmSETSTARTDECOMMAND
-**
-**      Form a START_DE command.
-**
-**  ARGUMENTS:
-**
-**      Memory          Destination memory pointer of gctUINT32_PTR type.
-**      Count           Number of the rectangles.
-*/
-
-#define gcmSETSTARTDECOMMAND(Memory, Count) \
-{ \
-    *Memory++ \
-        = gcmSETFIELDVALUE(0, AQ_COMMAND_START_DE_COMMAND, OPCODE,     START_DE) \
-        | gcmSETFIELD     (0, AQ_COMMAND_START_DE_COMMAND, COUNT,      Count) \
-        | gcmSETFIELD     (0, AQ_COMMAND_START_DE_COMMAND, DATA_COUNT, 0); \
-    \
-    *Memory++ = 0xDEADDEED; \
-}
-
 /******************************************************************************\
 ******************************** Ceiling Macro ********************************
 \******************************************************************************/
@@ -831,6 +728,10 @@ gceSTATUS;
 #define gcmABS(x)               (((x) < 0)    ? -(x) :  (x))
 #define gcmNEG(x)               (((x) < 0)    ?  (x) : -(x))
 
+/******************************************************************************\
+******************************** Bit Macro ********************************
+\******************************************************************************/
+#define gcmBITSET(x, y)         ((x) & (y))
 /*******************************************************************************
 **
 **  gcmPTR2INT
@@ -841,17 +742,15 @@ gceSTATUS;
 **
 **      p       Pointer value.
 */
-#if defined(_WIN32) || (defined(__LP64__) && __LP64__)
-#   define gcmPTR2INT(p) \
-    ( \
-        (gctUINT32) (gctUINT64) (p) \
-    )
-#else
-#   define gcmPTR2INT(p) \
-    ( \
-        (gctUINT32) (p) \
-    )
-#endif
+#define gcmPTR2INT(p) \
+( \
+    (gctUINTPTR_T) (p) \
+)
+
+#define gcmPTR2INT32(p) \
+( \
+    (gctUINT32)(gctUINTPTR_T) (p) \
+)
 
 /*******************************************************************************
 **
@@ -863,17 +762,11 @@ gceSTATUS;
 **
 **      v       Integer value.
 */
-#ifdef __LP64__
-#   define gcmINT2PTR(i) \
-    ( \
-        (gctPOINTER) (gctINT64) (i) \
-    )
-#else
-#   define gcmINT2PTR(i) \
-    ( \
-        (gctPOINTER) (i) \
-    )
-#endif
+
+#define gcmINT2PTR(i) \
+( \
+    (gctPOINTER) (gctUINTPTR_T)(i) \
+)
 
 /*******************************************************************************
 **
@@ -888,9 +781,15 @@ gceSTATUS;
 */
 #define gcmOFFSETOF(s, field) \
 ( \
-    gcmPTR2INT(& (((struct s *) 0)->field)) \
+    gcmPTR2INT32(& (((struct s *) 0)->field)) \
 )
 
+/*******************************************************************************
+**
+** gcmSWAB32
+**
+**      Return a value with all bytes in the 32 bit argument swapped.
+*/
 #define gcmSWAB32(x) ((gctUINT32)( \
         (((gctUINT32)(x) & (gctUINT32)0x000000FFUL) << 24) | \
         (((gctUINT32)(x) & (gctUINT32)0x0000FF00UL) << 8)  | \
@@ -943,19 +842,12 @@ typedef struct _gcsHAL_FRAME_INFO
     OUT gctUINT                 readRequests[8];
     OUT gctUINT                 writeRequests[8];
 
-    /* FE counters. */
-    OUT gctUINT                 drawCount;
-    OUT gctUINT                 vertexOutCount;
-    OUT gctUINT                 vertexMissCount;
-
     /* 3D counters. */
     OUT gctUINT                 vertexCount;
     OUT gctUINT                 primitiveCount;
     OUT gctUINT                 rejectedPrimitives;
     OUT gctUINT                 culledPrimitives;
     OUT gctUINT                 clippedPrimitives;
-    OUT gctUINT                 droppedPrimitives;
-    OUT gctUINT                 frustumClippedPrimitives;
     OUT gctUINT                 outPrimitives;
     OUT gctUINT                 inPrimitives;
     OUT gctUINT                 culledQuadCount;
@@ -973,94 +865,25 @@ typedef struct _gcsHAL_FRAME_INFO
     OUT gctUINT                 shaderCycles;
     OUT gctUINT                 vsInstructionCount;
     OUT gctUINT                 vsTextureCount;
-    OUT gctUINT                 vsBranchCount;
-    OUT gctUINT                 vsVertices;
     OUT gctUINT                 psInstructionCount;
     OUT gctUINT                 psTextureCount;
-    OUT gctUINT                 psBranchCount;
-    OUT gctUINT                 psPixels;
 
     /* Texture counters. */
     OUT gctUINT                 bilinearRequests;
     OUT gctUINT                 trilinearRequests;
-    OUT gctUINT                 txBytes8[2];
+    OUT gctUINT                 txBytes8;
     OUT gctUINT                 txHitCount;
     OUT gctUINT                 txMissCount;
 }
 gcsHAL_FRAME_INFO;
 
-typedef enum _gcePATCH_ID
-{
-    gcePATCH_UNKNOWN = 0xFFFFFFFF,
-
-    /* Benchmark list*/
-    gcePATCH_GLB11 = 0x0,
-    gcePATCH_GLB21,
-    gcePATCH_GLB25,
-    gcePATCH_GLB27,
-
-    gcePATCH_BM21,
-    gcePATCH_MM,
-    gcePATCH_MM06,
-    gcePATCH_MM07,
-    gcePATCH_QUADRANT,
-    gcePATCH_ANTUTU,
-    gcePATCH_SMARTBENCH,
-    gcePATCH_JPCT,
-    gcePATCH_NENAMARK,
-    gcePATCH_NENAMARK2,
-    gcePATCH_NEOCORE,
-    gcePATCH_GLB,
-    gcePATCH_GB,
-    gcePATCH_RTESTVA,
-    gcePATCH_BMX,
-    gcePATCH_BMGUI,
-
-    /* Game list */
-    gcePATCH_NBA2013,
-    gcePATCH_BARDTALE,
-    gcePATCH_BUSPARKING3D,
-    gcePATCH_FISHBOODLE,
-    gcePATCH_SUBWAYSURFER,
-    gcePATCH_HIGHWAYDRIVER,
-    gcePATCH_PREMIUM,
-    gcePATCH_RACEILLEGAL,
-    gcePATCH_BLABLA,
-    gcePATCH_MEGARUN,
-    gcePATCH_GALAXYONFIRE2,
-    gcePATCH_GLOFTR3HM,
-    gcePATCH_GLOFTSXHM,
-    gcePATCH_GLOFTF3HM,
-    gcePATCH_GLOFTGANG,
-    gcePATCH_XRUNNER,
-    gcePATCH_WP,
-    gcePATCH_DEVIL,
-    gcePATCH_HOLYARCH,
-    gcePATCH_MUSE,
-    gcePATCH_SG,
-    gcePATCH_SIEGECRAFT,
-    gcePATCH_CARCHALLENGE,
-    gcePATCH_HEROESCALL,
-    gcePATCH_MONOPOLY,
-    gcePATCH_CTGL20,
-    gcePATCH_FIREFOX,
-    gcePATCH_CHORME,
-    gcePATCH_DUOKANTV,
-    gcePATCH_TESTAPP,
-    gcePATCH_GOOGLEEARTH,
-
-    /* Count enum*/
-    gcePATCH_COUNT,
-}
-gcePATCH_ID;
-
 #if gcdLINK_QUEUE_SIZE
 typedef struct _gckLINKDATA * gckLINKDATA;
 struct _gckLINKDATA
 {
     gctUINT32                   start;
     gctUINT32                   end;
-    gctINT                      pid;
+    gctUINT32                   pid;
 };
 
 typedef struct _gckLINKQUEUE * gckLINKQUEUE;
@@ -1073,6 +896,35 @@ struct _gckLINKQUEUE
 };
 #endif
 
+#define gcdENTRY_QUEUE_SIZE 256
+typedef struct _gckENTRYDATA * gckENTRYDATA;
+struct _gckENTRYDATA
+{
+    gctUINT32                   physical;
+    gctUINT32                   bytes;
+};
+
+typedef struct _gckENTRYQUEUE * gckENTRYQUEUE;
+struct _gckENTRYQUEUE
+{
+    struct _gckENTRYDATA        data[gcdENTRY_QUEUE_SIZE];
+    gctUINT32                   rear;
+    gctUINT32                   front;
+    gctUINT32                   count;
+};
+
+typedef enum _gceTRACEMODE
+{
+    gcvTRACEMODE_NONE     = 0,
+    gcvTRACEMODE_FULL     = 1,
+    gcvTRACEMODE_LOGGER   = 2,
+    gcvTRACEMODE_PRE      = 3,
+    gcvTRACEMODE_POST     = 4,
+    gcvTRACEMODE_SYSTRACE = 5,
+
+} gceTRACEMODE;
+
+
 #ifdef __cplusplus
 }
 #endif
index 2eab66604642a015dab53eb613c857dce6ba8375..4f95350184f78ccfa00f2006b8726b01c78b76b5 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 #ifndef __gc_hal_version_h_
 #define __gc_hal_version_h_
 
-#define gcvVERSION_MAJOR        4
+#define gcvVERSION_MAJOR        5
 
-#define gcvVERSION_MINOR        6
+#define gcvVERSION_MINOR        0
 
-#define gcvVERSION_PATCH        9
+#define gcvVERSION_PATCH        11
 
-#define gcvVERSION_BUILD     9754
+#define gcvVERSION_BUILD     25762
+
+#define gcvVERSION_STRING    "5.0.11.p4.25762"
 
 #define gcvVERSION_DATE      __DATE__
 
index 2a910e8ee36dba596f6feccc73621b412cc17380..09e8b9647423d7daf5251471a142b2457c6157ce 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -346,11 +346,11 @@ gckVGKERNEL_Destroy(
 
 /* Allocate linear video memory. */
 gceSTATUS
-gckKERNEL_AllocateLinearMemory(
+gckVGKERNEL_AllocateLinearMemory(
     IN gckKERNEL Kernel,
     IN OUT gcePOOL * Pool,
     IN gctSIZE_T Bytes,
-    IN gctSIZE_T Alignment,
+    IN gctUINT32 Alignment,
     IN gceSURF_TYPE Type,
     OUT gcuVIDMEM_NODE_PTR * Node
     );
@@ -379,21 +379,6 @@ gckKERNEL_QueryCommandBuffer(
     OUT gcsCOMMAND_BUFFER_INFO_PTR Information
     );
 
-#if gcdDYNAMIC_MAP_RESERVED_MEMORY
-gceSTATUS
-gckOS_MapReservedMemoryToKernel(
-    IN gckOS Os,
-    IN gctUINT32 Physical,
-    IN gctINT Bytes,
-    IN OUT gctPOINTER *Virtual
-    );
-
-gceSTATUS
-gckOS_UnmapReservedMemoryFromKernel(
-    IN gctPOINTER Virtual
-    );
-#endif
-
 /******************************************************************************\
 ******************************* gckVGHARDWARE Object ******************************
 \******************************************************************************/
@@ -433,7 +418,7 @@ gceSTATUS
 gckVGHARDWARE_Execute(
     IN gckVGHARDWARE Hardware,
     IN gctUINT32 Address,
-    IN gctSIZE_T Count
+    IN gctUINT32 Count
     );
 
 /* Query the available memory. */
@@ -493,6 +478,7 @@ gceSTATUS
 gckVGHARDWARE_ConvertLogical(
     IN gckVGHARDWARE Hardware,
     IN gctPOINTER Logical,
+    IN gctBOOL InUserSpace,
     OUT gctUINT32 * Address
     );
 
@@ -579,7 +565,7 @@ gckVGHARDWARE_QueryIdle(
 \******************************************************************************/
 
 /* Vacant command buffer marker. */
-#define gcvVACANT_BUFFER        ((gcsCOMPLETION_SIGNAL_PTR) (1))
+#define gcvVACANT_BUFFER        ((gcsCOMPLETION_SIGNAL_PTR) ((gctSIZE_T)1))
 
 /* Command buffer header. */
 typedef struct _gcsCMDBUFFER * gcsCMDBUFFER_PTR;
@@ -591,7 +577,7 @@ typedef struct _gcsCMDBUFFER
     /* The user sets this to the node of the container buffer whitin which
        this particular command buffer resides. The kernel sets this to the
        node of the internally allocated buffer. */
-    gctUINT64                   node;
+    gcuVIDMEM_NODE_PTR          node;
 
     /* Command buffer hardware address. */
     gctUINT32                   address;
@@ -601,7 +587,7 @@ typedef struct _gcsCMDBUFFER
 
     /* Size of the area allocated for the data portion of this particular
        command buffer (headers and tail reserves are excluded). */
-    gctSIZE_T                   size;
+    gctUINT32                   size;
 
     /* Offset into the buffer [0..size]; reflects exactly how much data has
        been put into the command buffer. */
@@ -609,7 +595,7 @@ typedef struct _gcsCMDBUFFER
 
     /* The number of command units in the buffer for the hardware to
        execute. */
-    gctSIZE_T                   dataCount;
+    gctUINT32                   dataCount;
 
     /* MANAGED BY : user HAL (gcoBUFFER object).
        USED BY    : user HAL (gcoBUFFER object).
@@ -664,16 +650,13 @@ typedef struct _gcsVGCONTEXT
     gctUINT32                   currentPipe;
 
     /* State map/mod buffer. */
-    gctSIZE_T                   mapFirst;
-    gctSIZE_T                   mapLast;
-#ifdef __QNXNTO__
-    gctSIZE_T                   mapContainerSize;
-#endif
-    gcsVGCONTEXT_MAP_PTR            mapContainer;
-    gcsVGCONTEXT_MAP_PTR            mapPrev;
-    gcsVGCONTEXT_MAP_PTR            mapCurr;
-    gcsVGCONTEXT_MAP_PTR            firstPrevMap;
-    gcsVGCONTEXT_MAP_PTR            firstCurrMap;
+    gctUINT32                   mapFirst;
+    gctUINT32                   mapLast;
+    gcsVGCONTEXT_MAP_PTR        mapContainer;
+    gcsVGCONTEXT_MAP_PTR        mapPrev;
+    gcsVGCONTEXT_MAP_PTR        mapCurr;
+    gcsVGCONTEXT_MAP_PTR        firstPrevMap;
+    gcsVGCONTEXT_MAP_PTR        firstCurrMap;
 
     /* Main context buffer. */
     gcsCMDBUFFER_PTR            header;
@@ -863,7 +846,7 @@ typedef struct _gckVGMMU *          gckVGMMU;
 gceSTATUS
 gckVGMMU_Construct(
     IN gckVGKERNEL Kernel,
-    IN gctSIZE_T MmuSize,
+    IN gctUINT32 MmuSize,
     OUT gckVGMMU * Mmu
     );
 
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h
new file mode 100644 (file)
index 0000000..fa2190f
--- /dev/null
@@ -0,0 +1,34 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2014 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.
+*
+*****************************************************************************/
+
+
+extern gceSTATUS
+_DefaultAlloctorInit(
+    IN gckOS Os,
+    OUT gckALLOCATOR * Allocator
+    );
+
+gcsALLOCATOR_DESC allocatorArray[] =
+{
+    /* Default allocator. */
+    gcmkDEFINE_ALLOCATOR_DESC("default", _DefaultAlloctorInit),
+};
+
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_array.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_array.h
new file mode 100644 (file)
index 0000000..acdd929
--- /dev/null
@@ -0,0 +1,45 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2014 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.
+*
+*****************************************************************************/
+
+
+extern gceSTATUS
+_DefaultAlloctorInit(
+    IN gckOS Os,
+    OUT gckALLOCATOR * Allocator
+    );
+
+#if LINUX_CMA_FSL
+gceSTATUS
+_CMAFSLAlloctorInit(
+    IN gckOS Os,
+    OUT gckALLOCATOR * Allocator
+    );
+#endif
+
+gcsALLOCATOR_DESC allocatorArray[] =
+{
+#if LINUX_CMA_FSL
+    gcmkDEFINE_ALLOCATOR_DESC("cmafsl", _CMAFSLAlloctorInit),
+#endif
+    /* Default allocator. */
+    gcmkDEFINE_ALLOCATOR_DESC("default", _DefaultAlloctorInit),
+};
+
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c
new file mode 100644 (file)
index 0000000..e419558
--- /dev/null
@@ -0,0 +1,412 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2014 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 "gc_hal_kernel_allocator.h"
+
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mman.h>
+#include <asm/atomic.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#define _GC_OBJ_ZONE    gcvZONE_OS
+
+typedef struct _gcsCMA_PRIV * gcsCMA_PRIV_PTR;
+typedef struct _gcsCMA_PRIV {
+    gctUINT32 cmasize;
+}
+gcsCMA_PRIV;
+
+struct mdl_cma_priv {
+    gctPOINTER kvaddr;
+    dma_addr_t physical;
+};
+
+int gc_cma_usage_show(struct seq_file* m, void* data)
+{
+    gcsINFO_NODE *node = m->private;
+    gckALLOCATOR Allocator = node->device;
+    gcsCMA_PRIV_PTR priv = Allocator->privateData;
+
+    seq_printf(m, "cma:  %u bytes\n", priv->cmasize);
+
+    return 0;
+}
+
+static gcsINFO InfoList[] =
+{
+    {"cmausage", gc_cma_usage_show},
+};
+
+static void
+_DefaultAllocatorDebugfsInit(
+    IN gckALLOCATOR Allocator,
+    IN gckDEBUGFS_DIR Root
+    )
+{
+    gcmkVERIFY_OK(
+        gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "cma"));
+
+    gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
+        &Allocator->debugfsDir,
+        InfoList,
+        gcmCOUNTOF(InfoList),
+        Allocator
+        ));
+}
+
+static void
+_DefaultAllocatorDebugfsCleanup(
+    IN gckALLOCATOR Allocator
+    )
+{
+    gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
+        &Allocator->debugfsDir,
+        InfoList,
+        gcmCOUNTOF(InfoList)
+        ));
+
+    gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
+}
+
+static gceSTATUS
+_CMAFSLAlloc(
+    IN gckALLOCATOR Allocator,
+    INOUT PLINUX_MDL Mdl,
+    IN gctSIZE_T NumPages,
+    IN gctUINT32 Flags
+    )
+{
+    gceSTATUS status;
+    gcsCMA_PRIV_PTR priv = (gcsCMA_PRIV_PTR)Allocator->privateData;
+
+    struct mdl_cma_priv *mdl_priv=gcvNULL;
+    gckOS os = Allocator->os;
+
+    gcmkHEADER_ARG("Mdl=%p NumPages=%d", Mdl, NumPages);
+
+    gcmkONERROR(gckOS_Allocate(os, sizeof(struct mdl_cma_priv), (gctPOINTER *)&mdl_priv));
+    mdl_priv->kvaddr = gcvNULL;
+
+    mdl_priv->kvaddr = dma_alloc_writecombine(gcvNULL,
+            NumPages * PAGE_SIZE,
+            &mdl_priv->physical,
+            GFP_KERNEL | gcdNOWARN);
+
+    if (mdl_priv->kvaddr == gcvNULL)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    Mdl->priv = mdl_priv;
+    priv->cmasize += NumPages * PAGE_SIZE;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    if(mdl_priv)
+        gckOS_Free(os, mdl_priv);
+    gcmkFOOTER();
+    return status;
+}
+
+static void
+_CMAFSLFree(
+    IN gckALLOCATOR Allocator,
+    IN OUT PLINUX_MDL Mdl
+    )
+{
+    gckOS os = Allocator->os;
+    struct mdl_cma_priv *mdl_priv=(struct mdl_cma_priv *)Mdl->priv;
+    gcsCMA_PRIV_PTR priv = (gcsCMA_PRIV_PTR)Allocator->privateData;
+    dma_free_writecombine(gcvNULL,
+            Mdl->numPages * PAGE_SIZE,
+            mdl_priv->kvaddr,
+            mdl_priv->physical);
+     gckOS_Free(os, mdl_priv);
+    priv->cmasize -= Mdl->numPages * PAGE_SIZE;
+}
+
+gctINT
+_CMAFSLMapUser(
+    gckALLOCATOR Allocator,
+    PLINUX_MDL Mdl,
+    PLINUX_MDL_MAP MdlMap,
+    gctBOOL Cacheable
+    )
+{
+
+    PLINUX_MDL      mdl = Mdl;
+    PLINUX_MDL_MAP  mdlMap = MdlMap;
+    struct mdl_cma_priv *mdl_priv=(struct mdl_cma_priv *)Mdl->priv;
+
+    gcmkHEADER_ARG("Allocator=%p Mdl=%p MdlMap=%p gctBOOL=%d", Allocator, Mdl, MdlMap, Cacheable);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+    mdlMap->vmaAddr = (gctSTRING)vm_mmap(gcvNULL,
+                    0L,
+                    mdl->numPages * PAGE_SIZE,
+                    PROT_READ | PROT_WRITE,
+                    MAP_SHARED,
+                    0);
+#else
+    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);
+
+    up_write(&current->mm->mmap_sem);
+#endif
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_INFO, gcvZONE_OS,
+        "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
+        __FUNCTION__, __LINE__,
+        (gctUINT32)(gctUINTPTR_T)mdlMap->vmaAddr,
+        (gctUINT32)(gctUINTPTR_T)mdl
+        );
+
+    if (IS_ERR(mdlMap->vmaAddr))
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS,
+            "%s(%d): do_mmap_pgoff error",
+            __FUNCTION__, __LINE__
+            );
+
+        mdlMap->vmaAddr = gcvNULL;
+
+        gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    down_write(&current->mm->mmap_sem);
+
+    mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+    if (mdlMap->vma == gcvNULL)
+    {
+        up_write(&current->mm->mmap_sem);
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS,
+            "%s(%d): find_vma error",
+            __FUNCTION__, __LINE__
+            );
+
+        mdlMap->vmaAddr = gcvNULL;
+
+        gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+        return gcvSTATUS_OUT_OF_RESOURCES;
+    }
+
+    /* Now map all the vmalloc pages to this user address. */
+    if (mdl->contiguous)
+    {
+        /* map kernel memory to user space.. */
+        if (dma_mmap_writecombine(gcvNULL,
+                mdlMap->vma,
+                mdl_priv->kvaddr,
+                mdl_priv->physical,
+                mdl->numPages * PAGE_SIZE) < 0)
+        {
+            up_write(&current->mm->mmap_sem);
+
+            gcmkTRACE_ZONE(
+                gcvLEVEL_WARNING, gcvZONE_OS,
+                "%s(%d): dma_mmap_attrs error",
+                __FUNCTION__, __LINE__
+                );
+
+             mdlMap->vmaAddr = gcvNULL;
+
+            gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+            return gcvSTATUS_OUT_OF_MEMORY;
+        }
+    }
+    else
+    {
+        gckOS_Print("incorrect mdl:conti%d\n",mdl->contiguous);
+    }
+
+    up_write(&current->mm->mmap_sem);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+void
+_CMAUnmapUser(
+    IN gckALLOCATOR Allocator,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Size
+    )
+{
+    if (unlikely(current->mm == gcvNULL))
+    {
+        /* Do nothing if process is exiting. */
+        return;
+    }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
+    if (vm_munmap((unsigned long)Logical, Size) < 0)
+    {
+        gcmkTRACE_ZONE(
+                gcvLEVEL_WARNING, gcvZONE_OS,
+                "%s(%d): vm_munmap failed",
+                __FUNCTION__, __LINE__
+                );
+    }
+#else
+    down_write(&current->mm->mmap_sem);
+    if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
+    {
+        gcmkTRACE_ZONE(
+                gcvLEVEL_WARNING, gcvZONE_OS,
+                "%s(%d): do_munmap failed",
+                __FUNCTION__, __LINE__
+                );
+    }
+    up_write(&current->mm->mmap_sem);
+#endif
+}
+
+gceSTATUS
+_CMAMapKernel(
+    IN gckALLOCATOR Allocator,
+    IN PLINUX_MDL Mdl,
+    OUT gctPOINTER *Logical
+    )
+{
+    struct mdl_cma_priv *mdl_priv=(struct mdl_cma_priv *)Mdl->priv;
+    *Logical =mdl_priv->kvaddr;
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_CMAUnmapKernel(
+    IN gckALLOCATOR Allocator,
+    IN PLINUX_MDL Mdl,
+    IN gctPOINTER Logical
+    )
+{
+    return gcvSTATUS_OK;
+}
+
+extern gceSTATUS
+_DefaultLogicalToPhysical(
+    IN gckALLOCATOR Allocator,
+    IN PLINUX_MDL Mdl,
+    IN gctPOINTER Logical,
+    IN gctUINT32 ProcessID,
+    OUT gctUINT32_PTR Physical
+    );
+
+extern gceSTATUS
+_DefaultCache(
+    IN gckALLOCATOR Allocator,
+    IN PLINUX_MDL Mdl,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Physical,
+    IN gctUINT32 Bytes,
+    IN gceCACHEOPERATION Operation
+    );
+
+gceSTATUS
+_CMAPhysical(
+    IN gckALLOCATOR Allocator,
+    IN PLINUX_MDL Mdl,
+    IN gctUINT32 Offset,
+    OUT gctUINT32_PTR Physical
+    )
+{
+    struct mdl_cma_priv *mdl_priv=(struct mdl_cma_priv *)Mdl->priv;
+     gcmkASSERT(!Offset);
+    *Physical = mdl_priv->physical;
+
+    return gcvSTATUS_OK;
+}
+
+
+extern void
+_DefaultAllocatorDestructor(
+    IN void* PrivateData
+    );
+
+/* Default allocator operations. */
+gcsALLOCATOR_OPERATIONS CMAFSLAllocatorOperations = {
+    .Alloc              = _CMAFSLAlloc,
+    .Free               = _CMAFSLFree,
+    .MapUser            = _CMAFSLMapUser,
+    .UnmapUser          = _CMAUnmapUser,
+    .MapKernel          = _CMAMapKernel,
+    .UnmapKernel        = _CMAUnmapKernel,
+    .LogicalToPhysical  = _DefaultLogicalToPhysical,
+    .Cache              = _DefaultCache,
+    .Physical           = _CMAPhysical,
+};
+
+/* Default allocator entry. */
+gceSTATUS
+_CMAFSLAlloctorInit(
+    IN gckOS Os,
+    OUT gckALLOCATOR * Allocator
+    )
+{
+    gceSTATUS status;
+    gckALLOCATOR allocator;
+    gcsCMA_PRIV_PTR priv = gcvNULL;
+
+    gcmkONERROR(
+        gckALLOCATOR_Construct(Os, &CMAFSLAllocatorOperations, &allocator));
+
+    priv = kzalloc(gcmSIZEOF(gcsCMA_PRIV), GFP_KERNEL | gcdNOWARN);
+
+    if (!priv)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    /* Register private data. */
+    allocator->privateData = priv;
+    allocator->privateDataDestructor = _DefaultAllocatorDestructor;
+
+    allocator->debugfsInit = _DefaultAllocatorDebugfsInit;
+    allocator->debugfsCleanup = _DefaultAllocatorDebugfsCleanup;
+
+    allocator->capability = gcvALLOC_FLAG_CONTIGUOUS;
+
+    *Allocator = allocator;
+
+    return gcvSTATUS_OK;
+
+OnError:
+    return status;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c
new file mode 100644 (file)
index 0000000..193b5d9
--- /dev/null
@@ -0,0 +1,938 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2014 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 "gc_hal_kernel_allocator.h"
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mman.h>
+#include <asm/atomic.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#include "gc_hal_kernel_allocator_array.h"
+#include "gc_hal_kernel_platform.h"
+
+#define _GC_OBJ_ZONE    gcvZONE_OS
+
+typedef struct _gcsDEFAULT_PRIV * gcsDEFAULT_PRIV_PTR;
+typedef struct _gcsDEFAULT_PRIV {
+    gctUINT32 low;
+    gctUINT32 high;
+}
+gcsDEFAULT_PRIV;
+
+/******************************************************************************\
+************************** Default Allocator Debugfs ***************************
+\******************************************************************************/
+
+int gc_usage_show(struct seq_file* m, void* data)
+{
+    gcsINFO_NODE *node = m->private;
+    gckALLOCATOR Allocator = node->device;
+    gcsDEFAULT_PRIV_PTR priv = Allocator->privateData;
+
+    seq_printf(m, "low:  %u bytes\n", priv->low);
+    seq_printf(m, "high: %u bytes\n", priv->high);
+
+    return 0;
+}
+
+static gcsINFO InfoList[] =
+{
+    {"lowHighUsage", gc_usage_show},
+};
+
+static void
+_DefaultAllocatorDebugfsInit(
+    IN gckALLOCATOR Allocator,
+    IN gckDEBUGFS_DIR Root
+    )
+{
+    gcmkVERIFY_OK(
+        gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "default"));
+
+    gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
+        &Allocator->debugfsDir,
+        InfoList,
+        gcmCOUNTOF(InfoList),
+        Allocator
+        ));
+}
+
+static void
+_DefaultAllocatorDebugfsCleanup(
+    IN gckALLOCATOR Allocator
+    )
+{
+    gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
+        &Allocator->debugfsDir,
+        InfoList,
+        gcmCOUNTOF(InfoList)
+        ));
+
+    gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
+}
+
+
+static void
+_NonContiguousFree(
+    IN struct page ** Pages,
+    IN gctUINT32 NumPages
+    )
+{
+    gctINT i;
+
+    gcmkHEADER_ARG("Pages=0x%X, NumPages=%d", Pages, NumPages);
+
+    gcmkASSERT(Pages != gcvNULL);
+
+    for (i = 0; i < NumPages; i++)
+    {
+        __free_page(Pages[i]);
+    }
+
+    if (is_vmalloc_addr(Pages))
+    {
+        vfree(Pages);
+    }
+    else
+    {
+        kfree(Pages);
+    }
+
+    gcmkFOOTER_NO();
+}
+
+static struct page **
+_NonContiguousAlloc(
+    IN gctUINT32 NumPages
+    )
+{
+    struct page ** pages;
+    struct page *p;
+    gctINT i, size;
+
+    gcmkHEADER_ARG("NumPages=%lu", NumPages);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+    if (NumPages > totalram_pages)
+#else
+    if (NumPages > num_physpages)
+#endif
+    {
+        gcmkFOOTER_NO();
+        return gcvNULL;
+    }
+
+    size = NumPages * sizeof(struct page *);
+
+    pages = kmalloc(size, GFP_KERNEL | gcdNOWARN);
+
+    if (!pages)
+    {
+        pages = vmalloc(size);
+
+        if (!pages)
+        {
+            gcmkFOOTER_NO();
+            return gcvNULL;
+        }
+    }
+
+    for (i = 0; i < NumPages; i++)
+    {
+        p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
+
+        if (!p)
+        {
+            _NonContiguousFree(pages, i);
+            gcmkFOOTER_NO();
+            return gcvNULL;
+        }
+
+        pages[i] = p;
+    }
+
+    gcmkFOOTER_ARG("pages=0x%X", pages);
+    return pages;
+}
+
+gctSTRING
+_CreateKernelVirtualMapping(
+    IN PLINUX_MDL Mdl
+    )
+{
+    gctSTRING addr = 0;
+    gctINT numPages = Mdl->numPages;
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+    if (Mdl->contiguous)
+    {
+        addr = page_address(Mdl->u.contiguousPages);
+    }
+    else
+    {
+        addr = vmap(Mdl->u.nonContiguousPages,
+                    numPages,
+                    0,
+                    PAGE_KERNEL);
+
+        /* Trigger a page fault. */
+        memset(addr, 0, numPages * PAGE_SIZE);
+    }
+#else
+    struct page ** pages;
+    gctBOOL free = gcvFALSE;
+    gctINT i;
+
+    if (Mdl->contiguous)
+    {
+        pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
+
+        if (!pages)
+        {
+            return gcvNULL;
+        }
+
+        for (i = 0; i < numPages; i++)
+        {
+            pages[i] = nth_page(Mdl->u.contiguousPages, i);
+        }
+
+        free = gcvTRUE;
+    }
+    else
+    {
+        pages = Mdl->u.nonContiguousPages;
+    }
+
+    /* ioremap() can't work on system memory since 2.6.38. */
+    addr = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
+
+    if (free)
+    {
+        kfree(pages);
+    }
+
+#endif
+
+    return addr;
+}
+
+void
+_DestoryKernelVirtualMapping(
+    IN gctSTRING Addr
+    )
+{
+#if !gcdNONPAGED_MEMORY_CACHEABLE
+    vunmap(Addr);
+#endif
+}
+
+void
+_UnmapUserLogical(
+    IN gctPOINTER Logical,
+    IN gctUINT32  Size
+)
+{
+    if (unlikely(current->mm == gcvNULL))
+    {
+        /* Do nothing if process is exiting. */
+        return;
+    }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+    if (vm_munmap((unsigned long)Logical, Size) < 0)
+    {
+        gcmkTRACE_ZONE(
+                gcvLEVEL_WARNING, gcvZONE_OS,
+                "%s(%d): vm_munmap failed",
+                __FUNCTION__, __LINE__
+                );
+    }
+#else
+    down_write(&current->mm->mmap_sem);
+    if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
+    {
+        gcmkTRACE_ZONE(
+                gcvLEVEL_WARNING, gcvZONE_OS,
+                "%s(%d): do_munmap failed",
+                __FUNCTION__, __LINE__
+                );
+    }
+    up_write(&current->mm->mmap_sem);
+#endif
+}
+
+/***************************************************************************\
+************************ Default Allocator **********************************
+\***************************************************************************/
+#define C_MAX_PAGENUM  (50*1024)
+static gceSTATUS
+_DefaultAlloc(
+    IN gckALLOCATOR Allocator,
+    INOUT PLINUX_MDL Mdl,
+    IN gctSIZE_T NumPages,
+    IN gctUINT32 Flags
+    )
+{
+    gceSTATUS status;
+    gctUINT32 order;
+    gctSIZE_T bytes;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+    gctPOINTER addr = gcvNULL;
+#endif
+    gctUINT32 numPages;
+    gctUINT i = 0;
+    gctBOOL contiguous = Flags & gcvALLOC_FLAG_CONTIGUOUS;
+    struct sysinfo temsysinfo;
+    gcsDEFAULT_PRIV_PTR priv = (gcsDEFAULT_PRIV_PTR)Allocator->privateData;
+
+    gcmkHEADER_ARG("Mdl=%p NumPages=%d", Mdl, NumPages);
+
+    numPages = NumPages;
+    bytes = NumPages * PAGE_SIZE;
+    order = get_order(bytes);
+
+    si_meminfo(&temsysinfo);
+
+    if (Flags & gcvALLOC_FLAG_MEMLIMIT)
+    {
+        if ( (temsysinfo.freeram < NumPages) || ((temsysinfo.freeram-NumPages) < C_MAX_PAGENUM) )
+        {
+            gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+        }
+    }
+
+    if (contiguous)
+    {
+        if (order >= MAX_ORDER)
+        {
+            gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+        }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+        addr =
+            alloc_pages_exact(bytes, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY);
+
+        Mdl->u.contiguousPages = addr
+                               ? virt_to_page(addr)
+                               : gcvNULL;
+
+        Mdl->exact = gcvTRUE;
+#else
+        Mdl->u.contiguousPages =
+            alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, order);
+#endif
+
+        if (Mdl->u.contiguousPages == gcvNULL)
+        {
+            Mdl->u.contiguousPages =
+                alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, order);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+            Mdl->exact = gcvFALSE;
+#endif
+        }
+    }
+    else
+    {
+        Mdl->u.nonContiguousPages = _NonContiguousAlloc(numPages);
+    }
+
+    if (Mdl->u.contiguousPages == gcvNULL && Mdl->u.nonContiguousPages == gcvNULL)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    for (i = 0; i < numPages; i++)
+    {
+        struct page *page;
+
+        if (contiguous)
+        {
+            page = nth_page(Mdl->u.contiguousPages, i);
+        }
+        else
+        {
+            page = _NonContiguousToPage(Mdl->u.nonContiguousPages, i);
+        }
+
+        SetPageReserved(page);
+
+        if (!PageHighMem(page) && page_to_phys(page))
+        {
+            gcmkVERIFY_OK(
+                gckOS_CacheFlush(Allocator->os, _GetProcessID(), gcvNULL,
+                                 page_to_phys(page),
+                                 page_address(page),
+                                 PAGE_SIZE));
+
+            priv->low += PAGE_SIZE;
+        }
+        else
+        {
+            flush_dcache_page(page);
+
+#if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE) && gcdENABLE_OUTER_CACHE_PATCH
+            if (page_to_phys(page))
+            {
+                _HandleOuterCache(
+                    Allocator->os,
+                    page_to_phys(page),
+                    gcvNULL,
+                    PAGE_SIZE,
+                    gcvCACHE_FLUSH
+                    );
+            }
+#endif
+
+            priv->high += PAGE_SIZE;
+        }
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+static void
+_DefaultFree(
+    IN gckALLOCATOR Allocator,
+    IN OUT PLINUX_MDL Mdl
+    )
+{
+    gctINT i;
+    struct page * page;
+    gcsDEFAULT_PRIV_PTR priv = (gcsDEFAULT_PRIV_PTR)Allocator->privateData;
+
+    for (i = 0; i < Mdl->numPages; i++)
+    {
+        if (Mdl->contiguous)
+        {
+            page = nth_page(Mdl->u.contiguousPages, i);
+        }
+        else
+        {
+            page = _NonContiguousToPage(Mdl->u.nonContiguousPages, i);
+        }
+
+        ClearPageReserved(page);
+
+        if (PageHighMem(page))
+        {
+            priv->high -= PAGE_SIZE;
+        }
+        else
+        {
+            priv->low -= PAGE_SIZE;
+        }
+    }
+
+    if (Mdl->contiguous)
+    {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+        if (Mdl->exact == gcvTRUE)
+        {
+            free_pages_exact(page_address(Mdl->u.contiguousPages), Mdl->numPages * PAGE_SIZE);
+        }
+        else
+#endif
+        {
+            __free_pages(Mdl->u.contiguousPages, get_order(Mdl->numPages * PAGE_SIZE));
+        }
+    }
+    else
+    {
+        _NonContiguousFree(Mdl->u.nonContiguousPages, Mdl->numPages);
+    }
+}
+
+gctINT
+_DefaultMapUser(
+    gckALLOCATOR Allocator,
+    PLINUX_MDL Mdl,
+    PLINUX_MDL_MAP MdlMap,
+    gctBOOL Cacheable
+    )
+{
+
+    gctSTRING       addr;
+    unsigned long   start;
+    unsigned long   pfn;
+    gctINT i;
+    gckOS           os = Allocator->os;
+    gcsPLATFORM *   platform = os->device->platform;
+
+    PLINUX_MDL      mdl = Mdl;
+    PLINUX_MDL_MAP  mdlMap = MdlMap;
+
+    gcmkHEADER_ARG("Allocator=%p Mdl=%p MdlMap=%p gctBOOL=%d", Allocator, Mdl, MdlMap, Cacheable);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+    mdlMap->vmaAddr = (gctSTRING)vm_mmap(gcvNULL,
+                    0L,
+                    mdl->numPages * PAGE_SIZE,
+                    PROT_READ | PROT_WRITE,
+                    MAP_SHARED,
+                    0);
+#else
+    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);
+
+    up_write(&current->mm->mmap_sem);
+#endif
+
+    gcmkTRACE_ZONE(
+        gcvLEVEL_INFO, gcvZONE_OS,
+        "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
+        __FUNCTION__, __LINE__,
+        (gctUINT32)(gctUINTPTR_T)mdlMap->vmaAddr,
+        (gctUINT32)(gctUINTPTR_T)mdl
+        );
+
+    if (IS_ERR(mdlMap->vmaAddr))
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS,
+            "%s(%d): do_mmap_pgoff error",
+            __FUNCTION__, __LINE__
+            );
+
+        mdlMap->vmaAddr = gcvNULL;
+
+        gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    down_write(&current->mm->mmap_sem);
+
+    mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+    if (mdlMap->vma == gcvNULL)
+    {
+        up_write(&current->mm->mmap_sem);
+
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS,
+            "%s(%d): find_vma error",
+            __FUNCTION__, __LINE__
+            );
+
+        mdlMap->vmaAddr = gcvNULL;
+
+        gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+        return gcvSTATUS_OUT_OF_RESOURCES;
+    }
+
+    mdlMap->vma->vm_flags |= gcdVM_FLAGS;
+
+    if (Cacheable == gcvFALSE)
+    {
+        /* Make this mapping non-cached. */
+        mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
+    }
+
+    if (platform && platform->ops->adjustProt)
+    {
+        platform->ops->adjustProt(mdlMap->vma);
+    }
+
+    addr = mdl->addr;
+
+    /* Now map all the vmalloc pages to this user address. */
+    if (mdl->contiguous)
+    {
+        /* map kernel memory to user space.. */
+        if (remap_pfn_range(mdlMap->vma,
+                            mdlMap->vma->vm_start,
+                            page_to_pfn(mdl->u.contiguousPages),
+                            mdlMap->vma->vm_end - mdlMap->vma->vm_start,
+                            mdlMap->vma->vm_page_prot) < 0)
+        {
+            up_write(&current->mm->mmap_sem);
+
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO, gcvZONE_OS,
+                "%s(%d): unable to mmap ret",
+                __FUNCTION__, __LINE__
+                );
+
+            mdlMap->vmaAddr = gcvNULL;
+
+            gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+            return gcvSTATUS_OUT_OF_MEMORY;
+        }
+    }
+    else
+    {
+        start = mdlMap->vma->vm_start;
+
+        for (i = 0; i < mdl->numPages; i++)
+        {
+            pfn = _NonContiguousToPfn(mdl->u.nonContiguousPages, i);
+
+            if (remap_pfn_range(mdlMap->vma,
+                                start,
+                                pfn,
+                                PAGE_SIZE,
+                                mdlMap->vma->vm_page_prot) < 0)
+            {
+                up_write(&current->mm->mmap_sem);
+
+                mdlMap->vmaAddr = gcvNULL;
+
+                gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+                return gcvSTATUS_OUT_OF_MEMORY;
+            }
+
+            start += PAGE_SIZE;
+            addr += PAGE_SIZE;
+        }
+    }
+
+    up_write(&current->mm->mmap_sem);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+void
+_DefaultUnmapUser(
+    IN gckALLOCATOR Allocator,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Size
+    )
+{
+    _UnmapUserLogical(Logical, Size);
+}
+
+gceSTATUS
+_DefaultMapKernel(
+    IN gckALLOCATOR Allocator,
+    IN PLINUX_MDL Mdl,
+    OUT gctPOINTER *Logical
+    )
+{
+    *Logical = _CreateKernelVirtualMapping(Mdl);
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_DefaultUnmapKernel(
+    IN gckALLOCATOR Allocator,
+    IN PLINUX_MDL Mdl,
+    IN gctPOINTER Logical
+    )
+{
+    _DestoryKernelVirtualMapping(Logical);
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_DefaultLogicalToPhysical(
+    IN gckALLOCATOR Allocator,
+    IN PLINUX_MDL Mdl,
+    IN gctPOINTER Logical,
+    IN gctUINT32 ProcessID,
+    OUT gctUINT32_PTR Physical
+    )
+{
+    return _ConvertLogical2Physical(
+                Allocator->os, Logical, ProcessID, Mdl, Physical);
+}
+
+gceSTATUS
+_DefaultCache(
+    IN gckALLOCATOR Allocator,
+    IN PLINUX_MDL Mdl,
+    IN gctPOINTER Logical,
+    IN gctUINT32 Physical,
+    IN gctUINT32 Bytes,
+    IN gceCACHEOPERATION Operation
+    )
+{
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_DefaultPhysical(
+    IN gckALLOCATOR Allocator,
+    IN PLINUX_MDL Mdl,
+    IN gctUINT32 Offset,
+    OUT gctUINT32_PTR Physical
+    )
+{
+    gcmkASSERT(Mdl->pagedMem && !Mdl->contiguous);
+    *Physical = _NonContiguousToPhys(Mdl->u.nonContiguousPages, Offset);
+
+    return gcvSTATUS_OK;
+}
+
+void
+_DefaultAllocatorDestructor(
+    IN void* PrivateData
+    )
+{
+    kfree(PrivateData);
+}
+
+/* Default allocator operations. */
+gcsALLOCATOR_OPERATIONS DefaultAllocatorOperations = {
+    .Alloc              = _DefaultAlloc,
+    .Free               = _DefaultFree,
+    .MapUser            = _DefaultMapUser,
+    .UnmapUser          = _DefaultUnmapUser,
+    .MapKernel          = _DefaultMapKernel,
+    .UnmapKernel        = _DefaultUnmapKernel,
+    .LogicalToPhysical  = _DefaultLogicalToPhysical,
+    .Cache              = _DefaultCache,
+    .Physical           = _DefaultPhysical,
+};
+
+/* Default allocator entry. */
+gceSTATUS
+_DefaultAlloctorInit(
+    IN gckOS Os,
+    OUT gckALLOCATOR * Allocator
+    )
+{
+    gceSTATUS status;
+    gckALLOCATOR allocator;
+    gcsDEFAULT_PRIV_PTR priv = gcvNULL;
+
+    gcmkONERROR(
+        gckALLOCATOR_Construct(Os, &DefaultAllocatorOperations, &allocator));
+
+    priv = kzalloc(gcmSIZEOF(gcsDEFAULT_PRIV), GFP_KERNEL | gcdNOWARN);
+
+    if (!priv)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    /* Register private data. */
+    allocator->privateData = priv;
+    allocator->privateDataDestructor = _DefaultAllocatorDestructor;
+
+    allocator->debugfsInit = _DefaultAllocatorDebugfsInit;
+    allocator->debugfsCleanup = _DefaultAllocatorDebugfsCleanup;
+
+    *Allocator = allocator;
+
+    return gcvSTATUS_OK;
+
+OnError:
+    return status;
+}
+
+/***************************************************************************\
+************************ Allocator helper ***********************************
+\***************************************************************************/
+
+gceSTATUS
+gckALLOCATOR_Construct(
+    IN gckOS Os,
+    IN gcsALLOCATOR_OPERATIONS * Operations,
+    OUT gckALLOCATOR * Allocator
+    )
+{
+    gceSTATUS status;
+    gckALLOCATOR allocator;
+
+    gcmkHEADER_ARG("Os=%p, Operations=%p, Allocator=%p",
+                   Os, Operations, Allocator);
+
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Allocator != gcvNULL);
+    gcmkVERIFY_ARGUMENT
+        (  Operations
+        && Operations->Alloc
+        && Operations->Free
+        && Operations->MapUser
+        && Operations->UnmapUser
+        && Operations->MapKernel
+        && Operations->UnmapKernel
+        && Operations->LogicalToPhysical
+        && Operations->Cache
+        && Operations->Physical
+        );
+
+    gcmkONERROR(
+        gckOS_Allocate(Os, gcmSIZEOF(gcsALLOCATOR), (gctPOINTER *)&allocator));
+
+    gckOS_ZeroMemory(allocator, gcmSIZEOF(gcsALLOCATOR));
+
+    /* Record os. */
+    allocator->os = Os;
+
+    /* Set operations. */
+    allocator->ops = Operations;
+
+    allocator->capability = gcvALLOC_FLAG_CONTIGUOUS
+                          | gcvALLOC_FLAG_NON_CONTIGUOUS
+                          | gcvALLOC_FLAG_CACHEABLE
+                          | gcvALLOC_FLAG_MEMLIMIT;
+                          ;
+
+    *Allocator = allocator;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+/******************************************************************************\
+******************************** Debugfs Support *******************************
+\******************************************************************************/
+
+static gceSTATUS
+_AllocatorDebugfsInit(
+    IN gckOS Os
+    )
+{
+    gceSTATUS status;
+    gckGALDEVICE device = Os->device;
+
+    gckDEBUGFS_DIR dir = &Os->allocatorDebugfsDir;
+
+    gcmkONERROR(gckDEBUGFS_DIR_Init(dir, device->debugfsDir.root, "allocators"));
+
+    return gcvSTATUS_OK;
+
+OnError:
+    return status;
+}
+
+static void
+_AllocatorDebugfsCleanup(
+    IN gckOS Os
+    )
+{
+    gckDEBUGFS_DIR dir = &Os->allocatorDebugfsDir;
+
+    gckDEBUGFS_DIR_Deinit(dir);
+}
+
+/***************************************************************************\
+************************ Allocator management *******************************
+\***************************************************************************/
+
+gceSTATUS
+gckOS_ImportAllocators(
+    gckOS Os
+    )
+{
+    gceSTATUS status;
+    gctUINT i;
+    gckALLOCATOR allocator;
+
+    _AllocatorDebugfsInit(Os);
+
+    INIT_LIST_HEAD(&Os->allocatorList);
+
+    for (i = 0; i < gcmCOUNTOF(allocatorArray); i++)
+    {
+        if (allocatorArray[i].construct)
+        {
+            /* Construct allocator. */
+            status = allocatorArray[i].construct(Os, &allocator);
+
+            if (gcmIS_ERROR(status))
+            {
+                gcmkPRINT("["DEVICE_NAME"]: Can't construct allocator(%s)",
+                          allocatorArray[i].name);
+
+                continue;
+            }
+
+            allocator->name = allocatorArray[i].name;
+
+            if (allocator->debugfsInit)
+            {
+                /* Init allocator's debugfs. */
+                allocator->debugfsInit(allocator, &Os->allocatorDebugfsDir);
+            }
+
+            list_add_tail(&allocator->head, &Os->allocatorList);
+        }
+    }
+
+#if gcdDEBUG
+    list_for_each_entry(allocator, &Os->allocatorList, head)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_WARNING, gcvZONE_OS,
+            "%s(%d) Allocator: %s",
+            __FUNCTION__, __LINE__,
+            allocator->name
+            );
+    }
+#endif
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_FreeAllocators(
+    gckOS Os
+    )
+{
+    gckALLOCATOR allocator;
+    gckALLOCATOR temp;
+
+    list_for_each_entry_safe(allocator, temp, &Os->allocatorList, head)
+    {
+        list_del(&allocator->head);
+
+        if (allocator->debugfsCleanup)
+        {
+            /* Clean up allocator's debugfs. */
+            allocator->debugfsCleanup(allocator);
+        }
+
+        /* Free private data. */
+        if (allocator->privateDataDestructor && allocator->privateData)
+        {
+            allocator->privateDataDestructor(allocator->privateData);
+        }
+
+        gckOS_Free(Os, allocator);
+    }
+
+    _AllocatorDebugfsCleanup(Os);
+
+    return gcvSTATUS_OK;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h
new file mode 100644 (file)
index 0000000..f36e1b0
--- /dev/null
@@ -0,0 +1,400 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2014 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_allocator_h_
+#define __gc_hal_kernel_allocator_h_
+
+#include "gc_hal_kernel_linux.h"
+
+typedef struct _gcsALLOCATOR * gckALLOCATOR;
+
+typedef struct _gcsALLOCATOR_OPERATIONS
+{
+    /**************************************************************************
+    **
+    ** Alloc
+    **
+    ** Allocte memory, request size is page aligned.
+    **
+    ** INPUT:
+    **
+    **    gckALLOCATOR Allocator
+    **        Pointer to an gckALLOCATOER object.
+    **
+    **    PLINUX_Mdl
+    **        Pointer to Mdl whichs stores information
+    **        about allocated memory.
+    **
+    **    gctSIZE_T NumPages
+    **        Number of pages need to allocate.
+    **
+    **    gctUINT32 Flag
+    **        Allocation option.
+    **
+    ** OUTPUT:
+    **
+    **      Nothing.
+    **
+    */
+    gceSTATUS
+    (*Alloc)(
+        IN gckALLOCATOR Allocator,
+        IN PLINUX_MDL Mdl,
+        IN gctSIZE_T NumPages,
+        IN gctUINT32 Flag
+        );
+
+    /**************************************************************************
+    **
+    ** Free
+    **
+    ** Free memory.
+    **
+    ** INPUT:
+    **
+    **     gckALLOCATOR Allocator
+    **          Pointer to an gckALLOCATOER object.
+    **
+    **     PLINUX_MDL Mdl
+    **          Mdl which stores information.
+    **
+    ** OUTPUT:
+    **
+    **      Nothing.
+    **
+    */
+    void
+    (*Free)(
+        IN gckALLOCATOR Allocator,
+        IN PLINUX_MDL Mdl
+        );
+
+    /**************************************************************************
+    **
+    ** MapUser
+    **
+    ** Map memory to user space.
+    **
+    ** INPUT:
+    **      gckALLOCATOR Allocator
+    **          Pointer to an gckALLOCATOER object.
+    **
+    **      PLINUX_MDL Mdl
+    **          Pointer to a Mdl.
+    **
+    **      PLINUX_MDL_MAP MdlMap
+    **          Pointer to a MdlMap, mapped address is stored
+    **          in MdlMap->vmaAddr
+    **
+    **      gctBOOL Cacheable
+    **          Whether this mapping is cacheable.
+    **
+    ** OUTPUT:
+    **
+    **      Nothing.
+    **
+    */
+    gctINT
+    (*MapUser)(
+        IN gckALLOCATOR Allocator,
+        IN PLINUX_MDL Mdl,
+        IN PLINUX_MDL_MAP MdlMap,
+        IN gctBOOL Cacheable
+        );
+
+    /**************************************************************************
+    **
+    ** UnmapUser
+    **
+    ** Unmap address from user address space.
+    **
+    ** INPUT:
+    **      gckALLOCATOR Allocator
+    **          Pointer to an gckALLOCATOER object.
+    **
+    **      gctPOINTER Logical
+    **          Address to be unmap
+    **
+    **      gctUINT32 Size
+    **          Size of address space
+    **
+    ** OUTPUT:
+    **
+    **      Nothing.
+    **
+    */
+    void
+    (*UnmapUser)(
+        IN gckALLOCATOR Allocator,
+        IN gctPOINTER Logical,
+        IN gctUINT32 Size
+        );
+
+    /**************************************************************************
+    **
+    ** MapKernel
+    **
+    ** Map memory to kernel space.
+    **
+    ** INPUT:
+    **      gckALLOCATOR Allocator
+    **          Pointer to an gckALLOCATOER object.
+    **
+    **      PLINUX_MDL Mdl
+    **          Pointer to a Mdl object.
+    **
+    ** OUTPUT:
+    **      gctPOINTER * Logical
+    **          Mapped kernel address.
+    */
+    gceSTATUS
+    (*MapKernel)(
+        IN gckALLOCATOR Allocator,
+        IN PLINUX_MDL Mdl,
+        OUT gctPOINTER *Logical
+        );
+
+    /**************************************************************************
+    **
+    ** UnmapKernel
+    **
+    ** Unmap memory from kernel space.
+    **
+    ** INPUT:
+    **      gckALLOCATOR Allocator
+    **          Pointer to an gckALLOCATOER object.
+    **
+    **      PLINUX_MDL Mdl
+    **          Pointer to a Mdl object.
+    **
+    **      gctPOINTER Logical
+    **          Mapped kernel address.
+    **
+    ** OUTPUT:
+    **
+    **      Nothing.
+    **
+    */
+    gceSTATUS
+    (*UnmapKernel)(
+        IN gckALLOCATOR Allocator,
+        IN PLINUX_MDL Mdl,
+        IN gctPOINTER Logical
+        );
+
+    /**************************************************************************
+    **
+    ** LogicalToPhysical
+    **
+    ** Get physical address from logical address, logical
+    ** address could be user virtual address or kernel
+    ** virtual address.
+    **
+    ** INPUT:
+    **      gckALLOCATOR Allocator
+    **          Pointer to an gckALLOCATOER object.
+    **
+    **      PLINUX_MDL Mdl
+    **          Pointer to a Mdl object.
+    **
+    **      gctPOINTER Logical
+    **          Mapped kernel address.
+    **
+    **      gctUINT32 ProcessID
+    **          pid of current process.
+    ** OUTPUT:
+    **
+    **      gctUINT32_PTR Physical
+    **          Physical address.
+    **
+    */
+    gceSTATUS
+    (*LogicalToPhysical)(
+        IN gckALLOCATOR Allocator,
+        IN PLINUX_MDL Mdl,
+        IN gctPOINTER Logical,
+        IN gctUINT32 ProcessID,
+        OUT gctUINT32_PTR Physical
+        );
+
+    /**************************************************************************
+    **
+    ** Cache
+    **
+    ** Maintain cache coherency.
+    **
+    ** INPUT:
+    **      gckALLOCATOR Allocator
+    **          Pointer to an gckALLOCATOER object.
+    **
+    **      PLINUX_MDL Mdl
+    **          Pointer to a Mdl object.
+    **
+    **      gctPOINTER Logical
+    **          Logical address, could be user address or kernel address
+    **
+    **      gctUINT32_PTR Physical
+    **          Physical address.
+    **
+    **      gctUINT32 Bytes
+    **          Size of memory region.
+    **
+    **      gceCACHEOPERATION Opertaion
+    **          Cache operation.
+    **
+    ** OUTPUT:
+    **
+    **      Nothing.
+    **
+    */
+    gceSTATUS (*Cache)(
+        IN gckALLOCATOR Allocator,
+        IN PLINUX_MDL Mdl,
+        IN gctPOINTER Logical,
+        IN gctUINT32 Physical,
+        IN gctUINT32 Bytes,
+        IN gceCACHEOPERATION Operation
+        );
+
+    /**************************************************************************
+    **
+    ** Physical
+    **
+    ** Get physical address from a offset in memory region.
+    **
+    ** INPUT:
+    **      gckALLOCATOR Allocator
+    **          Pointer to an gckALLOCATOER object.
+    **
+    **      PLINUX_MDL Mdl
+    **          Pointer to a Mdl object.
+    **
+    **      gctUINT32 Offset
+    **          Offset in this memory region.
+    **
+    ** OUTPUT:
+    **      gctUINT32_PTR Physical
+    **          Physical address.
+    **
+    */
+    gceSTATUS (*Physical)(
+        IN gckALLOCATOR Allocator,
+        IN PLINUX_MDL Mdl,
+        IN gctUINT32 Offset,
+        OUT gctUINT32_PTR Physical
+        );
+}
+gcsALLOCATOR_OPERATIONS;
+
+typedef struct _gcsALLOCATOR
+{
+    /* Pointer to gckOS Object. */
+    gckOS                     os;
+
+    /* Name. */
+    gctSTRING                 name;
+
+    /* Operations. */
+    gcsALLOCATOR_OPERATIONS*  ops;
+
+    /* Capability of this allocator. */
+    gctUINT32                 capability;
+
+    struct list_head          head;
+
+    /* Debugfs entry of this allocator. */
+    gcsDEBUGFS_DIR            debugfsDir;
+
+    /* Init allocator debugfs. */
+    void                      (*debugfsInit)(gckALLOCATOR, gckDEBUGFS_DIR);
+
+    /* Cleanup allocator debugfs. */
+    void                      (*debugfsCleanup)(gckALLOCATOR);
+
+    /* Private data used by customer allocator. */
+    void *                    privateData;
+
+    /* Private data destructor. */
+    void                      (*privateDataDestructor)(void *);
+}
+gcsALLOCATOR;
+
+typedef struct _gcsALLOCATOR_DESC
+{
+    /* Name of a allocator. */
+    char *                    name;
+
+    /* Entry function to construct a allocator. */
+    gceSTATUS                 (*construct)(gckOS, gckALLOCATOR *);
+}
+gcsALLOCATOR_DESC;
+
+/*
+* Helpers
+*/
+
+/* Fill a gcsALLOCATOR_DESC structure. */
+#define gcmkDEFINE_ALLOCATOR_DESC(Name, Construct) \
+    { \
+        .name      = Name, \
+        .construct = Construct, \
+    }
+
+/* Construct a allocator. */
+gceSTATUS
+gckALLOCATOR_Construct(
+    IN gckOS Os,
+    IN gcsALLOCATOR_OPERATIONS * Operations,
+    OUT gckALLOCATOR * Allocator
+    );
+
+/*
+    How to implement customer allocator
+
+    Build in customer alloctor
+
+        It is recommanded that customer allocator is implmented in independent
+        source file(s) which is specified by CUSOMTER_ALLOCATOR_OBJS in Kbuld.
+
+    Register gcsALLOCATOR
+
+        For each customer specified allocator, a desciption entry must be added
+        to allocatorArray defined in gc_hal_kernel_allocator_array.h.
+
+        An entry in allocatorArray is a gcsALLOCATOR_DESC structure which describes
+        name and constructor of a gckALLOCATOR object.
+
+
+    Implement gcsALLOCATOR_DESC.init()
+
+        In gcsALLOCATOR_DESC.init(), gckALLOCATOR_Construct should be called
+        to create a gckALLOCATOR object, customer specified private data can
+        be put in gcsALLOCATOR.privateData.
+
+
+    Implement gcsALLOCATOR_OPERATIONS
+
+        When call gckALLOCATOR_Construct to create a gckALLOCATOR object, a
+        gcsALLOCATOR_OPERATIONS structure must be provided whose all members
+        implemented.
+
+*/
+#endif
index 339dff462780de861cac5a34dc08a023e0bedbed..ef341d2625f2e8e05c754daf98128cf2fa1db164 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -43,14 +43,18 @@ typedef va_list gctARGUMENTS;
 #define gcmkARGUMENTS_END(Arguments) \
     va_end(Arguments)
 
+#define gcmkARGUMENTS_ARG(Arguments, Type) \
+    va_arg(Arguments, Type)
+
 #define gcmkDECLARE_LOCK(__spinLock__) \
-    static DEFINE_SPINLOCK(__spinLock__);
+    static DEFINE_SPINLOCK(__spinLock__); \
+    unsigned long __spinLock__##flags = 0;
 
 #define gcmkLOCKSECTION(__spinLock__) \
-    spin_lock(&__spinLock__)
+    spin_lock_irqsave(&__spinLock__, __spinLock__##flags)
 
 #define gcmkUNLOCKSECTION(__spinLock__) \
-    spin_unlock(&__spinLock__)
+    spin_unlock_irqrestore(&__spinLock__, __spinLock__##flags)
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
 #   define gcmkGETPROCESSID() \
@@ -69,10 +73,11 @@ typedef va_list gctARGUMENTS;
 #endif
 
 #define gcmkOUTPUT_STRING(String) \
-   if(gckDebugFileSystemIsEnabled()) \
-       gckDebugFileSystemPrint(String);\
-   else\
-       printk(String); \
+    if(gckDEBUGFS_IsEnabled()) {\
+        while(-ERESTARTSYS == gckDEBUGFS_Print(String));\
+    }else{\
+        printk(String); \
+    }\
     touch_softlockup_watchdog()
 
 
@@ -86,11 +91,17 @@ typedef va_list gctARGUMENTS;
     snprintf(Destination, Size, Message, Value1, Value2, Value3)
 
 #define gcmkVSPRINTF(Destination, Size, Message, Arguments) \
-    vsnprintf(Destination, Size, Message, *(va_list *) &Arguments)
+    vsnprintf(Destination, Size, Message, *((va_list*)Arguments))
 
 #define gcmkSTRCAT(Destination, Size, String) \
     strncat(Destination, String, Size)
 
+#define gcmkMEMCPY(Destination, Source, Size) \
+    memcpy(Destination, Source, Size)
+
+#define gcmkSTRLEN(String) \
+    strlen(String)
+
 /* If not zero, forces data alignment in the variable argument list
    by its individual size. */
 #define gcdALIGNBYSIZE      1
index 6bdc5a6256098d584b3a6f21185ec346eaf2b122..35b125f28e9239487e8ebb61d84c9460c15197b1 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -41,7 +41,9 @@
 #include <linux/poll.h>
 #include <asm/uaccess.h>
 #include <linux/completion.h>
+#include <linux/seq_file.h>
 #include "gc_hal_kernel_linux.h"
+#include "gc_hal_kernel.h"
 
 /*
    Prequsite:
         2.a)If the debugfs is not mounted, you must do "mount -t debugfs none /sys/kernel/debug"
 
    3) To read what is being printed in the debugfs file system:
-        Ex : cat /sys/kernel/debug/gpu/galcore_trace
+        Ex : cat /sys/kernel/debug/gc/galcore_trace
 
    4)To write into the debug file system from user side :
-        Ex: echo "hello" > cat /sys/kernel/debug/gpu/galcore_trace
+        Ex: echo "hello" > cat /sys/kernel/debug/gc/galcore_trace
 
-   5)To write into debugfs from kernel side, Use the function called gckDebugFileSystemPrint
+   5)To write into debugfs from kernel side, Use the function called gckDEBUGFS_Print
 
+   How to Get Video Memory Usage:
+   1) Select a process whose video memory usage can be dump, no need to reset it until <pid> is needed to be change.
+        echo <pid>  > /sys/kernel/debug/gc/vidmem
+
+   2) Get video memory usage.
+        cat /sys/kernel/debug/gc/vidmem
 
    USECASE Kernel Dump:
 
 /**/
 typedef va_list gctDBGARGS ;
 #define gcmkARGS_START(argument, pointer)   va_start(argument, pointer)
-#define gcmkARGS_END(argument)                       va_end(argument)
+#define gcmkARGS_END(argument)                        va_end(argument)
 
-#define gcmkDBGFSPRINT(ArgumentSize, Message) \
+#define gcmkDEBUGFS_PRINT(ArgumentSize, Message) \
   { \
-         gctDBGARGS __arguments__; \
-         gcmkARGS_START(__arguments__, Message); \
-         _DebugFSPrint(ArgumentSize, Message, __arguments__);\
-         gcmkARGS_END(__arguments__); \
+      gctDBGARGS __arguments__; \
+      gcmkARGS_START(__arguments__, Message); \
+      _debugfs_res = _DebugFSPrint(ArgumentSize, Message, &__arguments__);\
+      gcmkARGS_END(__arguments__); \
   }
 
-/*Debug File System Node Struct*/
-struct _gcsDebugFileSystemNode
+/* Debug File System Node Struct. */
+struct _gcsDEBUGFS_Node
 {
     /*wait queues for read and write operations*/
 #if defined(DECLARE_WAIT_QUEUE_HEAD)
@@ -108,6 +116,7 @@ struct _gcsDebugFileSystemNode
 #endif
     struct dentry *parent ; /*parent directory*/
     struct dentry *filen ; /*filename*/
+    struct dentry *vidmem;
     struct semaphore sem ; /* mutual exclusion semaphore */
     char *data ; /* The circular buffer data */
     int size ; /* Size of the buffer pointed to by 'data' */
@@ -115,8 +124,8 @@ struct _gcsDebugFileSystemNode
     int read_point ; /* Offset in circ. buffer of oldest data */
     int write_point ; /* Offset in circ. buffer of newest data */
     int offset ; /* Byte number of read_point in the stream */
-    struct _gcsDebugFileSystemNode *next ;
-} ;
+    struct _gcsDEBUGFS_Node *next ;
+};
 
 /* amount of data in the queue */
 #define gcmkNODE_QLEN(node) ( (node)->write_point >= (node)->read_point ? \
@@ -135,22 +144,131 @@ struct _gcsDebugFileSystemNode
 #define gcmkMIN(x, y) ((x) < (y) ? (x) : y)
 
 /*Debug File System Struct*/
-typedef struct _gcsDebugFileSystem
+typedef struct _gcsDEBUGFS_
 {
-    gcsDebugFileSystemNode* linkedlist ;
-    gcsDebugFileSystemNode* currentNode ;
+    gcsDEBUGFS_Node* linkedlist ;
+    gcsDEBUGFS_Node* currentNode ;
     int isInited ;
-} gcsDebugFileSystem ;
-
+} gcsDEBUGFS_ ;
 
 /*debug file system*/
-static gcsDebugFileSystem gc_dbgfs ;
+static gcsDEBUGFS_ gc_dbgfs ;
+
+static int gc_debugfs_open(struct inode *inode, struct file *file)
+{
+    gcsINFO_NODE *node = inode->i_private;
+
+    return single_open(file, node->info->show, node);
+}
+
+static const struct file_operations gc_debugfs_operations = {
+    .owner = THIS_MODULE,
+    .open = gc_debugfs_open,
+    .read = seq_read,
+    .llseek = seq_lseek,
+    .release = single_release,
+};
+
+gceSTATUS
+gckDEBUGFS_DIR_Init(
+    IN gckDEBUGFS_DIR Dir,
+    IN struct dentry *root,
+    IN gctCONST_STRING Name
+    )
+{
+    Dir->root = debugfs_create_dir(Name, root);
+
+    if (!Dir->root)
+    {
+        return gcvSTATUS_NOT_SUPPORTED;
+    }
+
+    INIT_LIST_HEAD(&Dir->nodeList);
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckDEBUGFS_DIR_CreateFiles(
+    IN gckDEBUGFS_DIR Dir,
+    IN gcsINFO * List,
+    IN int count,
+    IN gctPOINTER Data
+    )
+{
+    int i;
+    gcsINFO_NODE * node;
+    gceSTATUS status;
+
+    for (i = 0; i < count; i++)
+    {
+        /* Create a node. */
+        node = (gcsINFO_NODE *)kzalloc(sizeof(gcsINFO_NODE), GFP_KERNEL);
+
+        node->info   = &List[i];
+        node->device = Data;
 
+        /* Bind to a file. TODO: clean up when fail. */
+        node->entry = debugfs_create_file(
+            List[i].name, S_IRUGO|S_IWUSR, Dir->root, node, &gc_debugfs_operations);
 
+        if (!node->entry)
+        {
+            gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+        }
+
+        list_add(&(node->head), &(Dir->nodeList));
+    }
+
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(Dir, List, count));
+    return status;
+}
+
+gceSTATUS
+gckDEBUGFS_DIR_RemoveFiles(
+    IN gckDEBUGFS_DIR Dir,
+    IN gcsINFO * List,
+    IN int count
+    )
+{
+    int i;
+    gcsINFO_NODE * node;
+    gcsINFO_NODE * temp;
+
+    for (i = 0; i < count; i++)
+    {
+        list_for_each_entry_safe(node, temp, &Dir->nodeList, head)
+        {
+            if (node->info == &List[i])
+            {
+                debugfs_remove(node->entry);
+                list_del(&node->head);
+                kfree(node);
+            }
+        }
+    }
+
+    return gcvSTATUS_OK;
+}
+
+void
+gckDEBUGFS_DIR_Deinit(
+    IN gckDEBUGFS_DIR Dir
+    )
+{
+    if (Dir->root != NULL)
+    {
+        debugfs_remove(Dir->root);
+        Dir->root = NULL;
+    }
+}
 
 /*******************************************************************************
  **
- **            READ & WRITE FUNCTIONS (START)
+ **        READ & WRITE FUNCTIONS (START)
  **
  *******************************************************************************/
 
@@ -158,15 +276,15 @@ static gcsDebugFileSystem gc_dbgfs ;
  **
  **  _ReadFromNode
  **
- **    1) reading bytes out of a circular buffer with wraparound.
- **    2)returns caddr_t, pointer to data read, which the caller must free.
- **    3) length is (a pointer to) the number of bytes to be read, which will be set by this function to
- **        be the number of bytes actually returned
+ **    1) reading bytes out of a circular buffer with wraparound.
+ **    2)returns caddr_t, pointer to data read, which the caller must free.
+ **    3) length is (a pointer to) the number of bytes to be read, which will be set by this function to
+ **        be the number of bytes actually returned
  **
  *******************************************************************************/
 static caddr_t
 _ReadFromNode (
-                gcsDebugFileSystemNode* Node ,
+                gcsDEBUGFS_Node* Node ,
                 size_t *Length ,
                 loff_t *Offset
                 )
@@ -228,7 +346,7 @@ _ReadFromNode (
  *********************************************************************************/
 static void
 _WriteToNode (
-               gcsDebugFileSystemNode* Node ,
+               gcsDEBUGFS_Node* Node ,
                caddr_t Buf ,
                int Length
                )
@@ -243,7 +361,7 @@ _WriteToNode (
 
         /* in case of overflow, figure out where the new buffer will
          * begin.  we start by figuring out where the current buffer ENDS:
-         * node->parent->offset +  gcmkNODE_QLEN.      we then advance the end-offset
+         * node->parent->offset +  gcmkNODE_QLEN.    we then advance the end-offset
          * by the Length of the current write, and work backwards to
          * figure out what the oldest unoverwritten data will be (i.e.,
          * size of the buffer). */
@@ -271,10 +389,9 @@ _WriteToNode (
     }
 }
 
-
 /*******************************************************************************
  **
- **            PRINTING UTILITY (START)
+ **         PRINTING UTILITY (START)
  **
  *******************************************************************************/
 
@@ -309,7 +426,7 @@ _GetArgumentSize (
  *******************************************************************************/
 static ssize_t
 _AppendString (
-                IN gcsDebugFileSystemNode* Node ,
+                IN gcsDEBUGFS_Node* Node ,
                 IN gctCONST_STRING String ,
                 IN int Length
                 )
@@ -341,18 +458,28 @@ _AppendString (
  **
  **
  *******************************************************************************/
-static void
+static ssize_t
 _DebugFSPrint (
                 IN unsigned int ArgumentSize ,
                 IN const char* Message ,
-                IN gctDBGARGS Arguments
+                IN gctDBGARGS Arguments
 
                 )
 {
     char buffer[MAX_LINE_SIZE] ;
     int len ;
-    down ( gcmkNODE_SEM ( gc_dbgfs.currentNode ) ) ;
-    len = vsnprintf ( buffer , sizeof (buffer ) , Message , *( va_list * ) & Arguments ) ;
+    ssize_t res=0;
+
+   if(in_interrupt())
+    {
+        return - ERESTARTSYS ;
+    }
+
+    if(down_interruptible( gcmkNODE_SEM ( gc_dbgfs.currentNode ) ) )
+    {
+         return - ERESTARTSYS ;
+    }
+    len = vsnprintf ( buffer , sizeof (buffer ) , Message , *( va_list * ) Arguments ) ;
     buffer[len] = '\0' ;
 
     /* Add end-of-line if missing. */
@@ -361,9 +488,10 @@ _DebugFSPrint (
         buffer[len ++] = '\n' ;
         buffer[len] = '\0' ;
     }
-    _AppendString ( gc_dbgfs.currentNode , buffer , len ) ;
+    res = _AppendString ( gc_dbgfs.currentNode , buffer , len ) ;
     up ( gcmkNODE_SEM ( gc_dbgfs.currentNode ) ) ;
     wake_up_interruptible ( gcmkNODE_READQ ( gc_dbgfs.currentNode ) ) ; /* blocked in read*/
+    return res;
 }
 
 /*******************************************************************************
@@ -375,15 +503,15 @@ _DebugFSPrint (
 /*******************************************************************************
  **
  **  find the vivlog structure associated with an inode.
- **    returns a       pointer to the structure if found, NULL if not found
+ **      returns a    pointer to the structure if found, NULL if not found
  **
  *******************************************************************************/
-static gcsDebugFileSystemNode*
+static gcsDEBUGFS_Node*
 _GetNodeInfo (
                IN struct inode *Inode
                )
 {
-    gcsDebugFileSystemNode* node ;
+    gcsDEBUGFS_Node* node ;
 
     if ( Inode == NULL )
         return NULL ;
@@ -410,7 +538,7 @@ _DebugFSRead (
 {
     int retval ;
     caddr_t data_to_return ;
-    gcsDebugFileSystemNode* node ;
+    gcsDEBUGFS_Node* node ;
     /* get the metadata about this emlog */
     if ( ( node = _GetNodeInfo ( file->f_dentry->d_inode ) ) == NULL )
     {
@@ -477,7 +605,7 @@ _DebugFSWrite (
 {
     caddr_t message = NULL ;
     int n ;
-    gcsDebugFileSystemNode*node ;
+    gcsDEBUGFS_Node*node ;
 
     /* get the metadata about this log */
     if ( ( node = _GetNodeInfo ( file->f_dentry->d_inode ) ) == NULL )
@@ -502,6 +630,7 @@ _DebugFSWrite (
         return - ENOMEM ;
     }
 
+
     /* copy into our temp buffer */
     if ( copy_from_user ( message , buffer , n ) > 0 )
     {
@@ -524,6 +653,230 @@ _DebugFSWrite (
     return n ;
 }
 
+int dumpProcess = 0;
+
+void
+_PrintCounter(
+    struct seq_file *file,
+    gcsDATABASE_COUNTERS * counter,
+    gctCONST_STRING Name
+    )
+{
+    seq_printf(file,"Counter: %s\n", Name);
+
+    seq_printf(file,"%-9s%10s","", "All");
+
+    seq_printf(file, "\n");
+
+    seq_printf(file,"%-9s","Current");
+
+    seq_printf(file,"%10lld", counter->bytes);
+
+    seq_printf(file, "\n");
+
+    seq_printf(file,"%-9s","Maximum");
+
+    seq_printf(file,"%10lld", counter->maxBytes);
+
+    seq_printf(file, "\n");
+
+    seq_printf(file,"%-9s","Total");
+
+    seq_printf(file,"%10lld", counter->totalBytes);
+
+    seq_printf(file, "\n");
+}
+
+void
+_ShowCounters(
+    struct seq_file *file,
+    gcsDATABASE_PTR database
+    )
+{
+    gctUINT i = 0;
+    gcsDATABASE_COUNTERS * counter;
+    gcsDATABASE_COUNTERS * nonPaged;
+
+    static gctCONST_STRING surfaceTypes[] = {
+        "UNKNOWN",
+        "Index",
+        "Vertex",
+        "Texture",
+        "RT",
+        "Depth",
+        "Bitmap",
+        "TS",
+        "Image",
+        "Mask",
+        "Scissor",
+        "HZDepth",
+    };
+
+    /* Get pointer to counters. */
+    counter = &database->vidMem;
+
+    nonPaged = &database->nonPaged;
+
+    seq_printf(file,"Counter: vidMem (for each surface type)\n");
+
+    seq_printf(file,"%-9s%10s","", "All");
+
+    for (i = 1; i < gcvSURF_NUM_TYPES; i++)
+    {
+        counter = &database->vidMemType[i];
+
+        seq_printf(file, "%10s",surfaceTypes[i]);
+    }
+
+    seq_printf(file, "\n");
+
+    seq_printf(file,"%-9s","Current");
+
+    seq_printf(file,"%10lld", database->vidMem.bytes);
+
+    for (i = 1; i < gcvSURF_NUM_TYPES; i++)
+    {
+        counter = &database->vidMemType[i];
+
+        seq_printf(file,"%10lld", counter->bytes);
+    }
+
+    seq_printf(file, "\n");
+
+    seq_printf(file,"%-9s","Maximum");
+
+    seq_printf(file,"%10lld", database->vidMem.maxBytes);
+
+    for (i = 1; i < gcvSURF_NUM_TYPES; i++)
+    {
+        counter = &database->vidMemType[i];
+
+        seq_printf(file,"%10lld", counter->maxBytes);
+    }
+
+    seq_printf(file, "\n");
+
+    seq_printf(file,"%-9s","Total");
+
+    seq_printf(file,"%10lld", database->vidMem.totalBytes);
+
+    for (i = 1; i < gcvSURF_NUM_TYPES; i++)
+    {
+        counter = &database->vidMemType[i];
+
+        seq_printf(file,"%10lld", counter->totalBytes);
+    }
+
+    seq_printf(file, "\n");
+
+    seq_printf(file,"Counter: vidMem (for each pool)\n");
+
+    seq_printf(file,"%-9s%10s","", "All");
+
+    for (i = 1; i < gcvPOOL_NUMBER_OF_POOLS; i++)
+    {
+        seq_printf(file, "%10d", i);
+    }
+
+    seq_printf(file, "\n");
+
+    seq_printf(file,"%-9s","Current");
+
+    seq_printf(file,"%10lld", database->vidMem.bytes);
+
+    for (i = 1; i < gcvPOOL_NUMBER_OF_POOLS; i++)
+    {
+        counter = &database->vidMemPool[i];
+
+        seq_printf(file,"%10lld", counter->bytes);
+    }
+
+    seq_printf(file, "\n");
+
+    seq_printf(file,"%-9s","Maximum");
+
+    seq_printf(file,"%10lld", database->vidMem.maxBytes);
+
+    for (i = 1; i < gcvPOOL_NUMBER_OF_POOLS; i++)
+    {
+        counter = &database->vidMemPool[i];
+
+        seq_printf(file,"%10lld", counter->maxBytes);
+    }
+
+    seq_printf(file, "\n");
+
+    seq_printf(file,"%-9s","Total");
+
+    seq_printf(file,"%10lld", database->vidMem.totalBytes);
+
+    for (i = 1; i < gcvPOOL_NUMBER_OF_POOLS; i++)
+    {
+        counter = &database->vidMemPool[i];
+
+        seq_printf(file,"%10lld", counter->totalBytes);
+    }
+
+    seq_printf(file, "\n");
+
+    /* Print nonPaged. */
+    _PrintCounter(file, &database->nonPaged, "nonPaged");
+    _PrintCounter(file, &database->contiguous, "contiguous");
+    _PrintCounter(file, &database->mapUserMemory, "mapUserMemory");
+    _PrintCounter(file, &database->mapMemory, "mapMemory");
+}
+
+gckKERNEL
+_GetValidKernel(
+    gckGALDEVICE Device
+);
+static int vidmem_show(struct seq_file *file, void *unused)
+{
+    gceSTATUS status;
+    gcsDATABASE_PTR database;
+    gckGALDEVICE device = file->private;
+
+    gckKERNEL kernel = _GetValidKernel(device);
+    if(kernel == gcvNULL)
+    {
+        return 0;
+    }
+
+    /* Find the database. */
+    gcmkONERROR(
+        gckKERNEL_FindDatabase(kernel, dumpProcess, gcvFALSE, &database));
+
+    seq_printf(file, "VidMem Usage (Process %d):\n", dumpProcess);
+
+    _ShowCounters(file, database);
+
+    return 0;
+
+OnError:
+    return 0;
+}
+
+static int
+vidmem_open(
+    struct inode *inode,
+    struct file *file
+    )
+{
+    return single_open(file, vidmem_show, inode->i_private);
+}
+
+static ssize_t
+vidmem_write(
+    struct file *file,
+    const char __user *buf,
+    size_t count,
+    loff_t *pos
+    )
+{
+    dumpProcess = simple_strtol(buf, NULL, 0);
+    return count;
+}
+
 /*******************************************************************************
  **
  ** File Operations Table
@@ -535,6 +888,14 @@ static const struct file_operations debugfs_operations = {
                                                           .write = _DebugFSWrite ,
 } ;
 
+static const struct file_operations vidmem_operations = {
+    .owner = THIS_MODULE ,
+    .open = vidmem_open,
+    .read = seq_read,
+    .write = vidmem_write,
+    .llseek = seq_lseek,
+} ;
+
 /*******************************************************************************
  **
  **                             INTERFACE FUNCTIONS (START)
@@ -543,7 +904,7 @@ static const struct file_operations debugfs_operations = {
 
 /*******************************************************************************
  **
- **  gckDebugFileSystemIsEnabled
+ **  gckDEBUGFS_IsEnabled
  **
  **
  **  INPUT:
@@ -554,13 +915,13 @@ static const struct file_operations debugfs_operations = {
 
 
 gctINT
-gckDebugFileSystemIsEnabled ( void )
+gckDEBUGFS_IsEnabled ( void )
 {
     return gc_dbgfs.isInited ;
 }
 /*******************************************************************************
  **
- **  gckDebugFileSystemInitialize
+ **  gckDEBUGFS_Initialize
  **
  **
  **  INPUT:
@@ -570,7 +931,7 @@ gckDebugFileSystemIsEnabled ( void )
  *******************************************************************************/
 
 gctINT
-gckDebugFileSystemInitialize ( void )
+gckDEBUGFS_Initialize ( void )
 {
     if ( ! gc_dbgfs.isInited )
     {
@@ -582,7 +943,7 @@ gckDebugFileSystemInitialize ( void )
 }
 /*******************************************************************************
  **
- **  gckDebugFileSystemTerminate
+ **  gckDEBUGFS_Terminate
  **
  **
  **  INPUT:
@@ -592,17 +953,17 @@ gckDebugFileSystemInitialize ( void )
  *******************************************************************************/
 
 gctINT
-gckDebugFileSystemTerminate ( void )
+gckDEBUGFS_Terminate ( void )
 {
-    gcsDebugFileSystemNode * next = gcvNULL ;
-    gcsDebugFileSystemNode * temp = gcvNULL ;
+    gcsDEBUGFS_Node * next = gcvNULL ;
+    gcsDEBUGFS_Node * temp = gcvNULL ;
     if ( gc_dbgfs.isInited )
     {
         temp = gc_dbgfs.linkedlist ;
         while ( temp != gcvNULL )
         {
             next = temp->next ;
-            gckDebugFileSystemFreeNode ( temp ) ;
+            gckDEBUGFS_FreeNode ( temp ) ;
             kfree ( temp ) ;
             temp = next ;
         }
@@ -614,33 +975,34 @@ gckDebugFileSystemTerminate ( void )
 
 /*******************************************************************************
  **
- **  gckDebugFileSystemCreateNode
+ **  gckDEBUGFS_CreateNode
  **
  **
  **  INPUT:
  **
  **  OUTPUT:
  **
- **     gckDebugFileSystemFreeNode * Device
- **              Pointer to a variable receiving the gcsDebugFileSystemNode object pointer on
- **              success.
+ **     gckDEBUGFS_FreeNode * Device
+ **          Pointer to a variable receiving the gcsDEBUGFS_Node object pointer on
+ **          success.
  *********************************************************************************/
 
 gctINT
-gckDebugFileSystemCreateNode (
-                               IN gctINT SizeInKB ,
-                               IN gctCONST_STRING ParentName ,
-                               IN gctCONST_STRING NodeName ,
-                               OUT gcsDebugFileSystemNode **Node
-                               )
+gckDEBUGFS_CreateNode (
+    IN gctPOINTER Device,
+    IN gctINT SizeInKB ,
+    IN struct dentry * Root ,
+    IN gctCONST_STRING NodeName ,
+    OUT gcsDEBUGFS_Node **Node
+    )
 {
-    gcsDebugFileSystemNode*node ;
+    gcsDEBUGFS_Node*node ;
     /* allocate space for our metadata and initialize it */
-    if ( ( node = kmalloc ( sizeof (gcsDebugFileSystemNode ) , GFP_KERNEL ) ) == NULL )
+    if ( ( node = kmalloc ( sizeof (gcsDEBUGFS_Node ) , GFP_KERNEL ) ) == NULL )
         goto struct_malloc_failed ;
 
     /*Zero it out*/
-    memset ( node , 0 , sizeof (gcsDebugFileSystemNode ) ) ;
+    memset ( node , 0 , sizeof (gcsDEBUGFS_Node ) ) ;
 
     /*Init the sync primitives*/
 #if defined(DECLARE_WAIT_QUEUE_HEAD)
@@ -657,28 +1019,34 @@ gckDebugFileSystemCreateNode (
     sema_init ( gcmkNODE_SEM ( node ) , 1 ) ;
     /*End the sync primitives*/
 
-
-    /* figure out how much of a buffer this should be and allocate the buffer */
-    node->size = 1024 * SizeInKB ;
-    if ( ( node->data = ( char * ) vmalloc ( sizeof (char ) * node->size ) ) == NULL )
-        goto data_malloc_failed ;
-
     /*creating the debug file system*/
-    node->parent = debugfs_create_dir ( ParentName , NULL ) ;
+    node->parent = Root;
 
-    /*creating the file*/
-    node->filen = debugfs_create_file ( NodeName , S_IRUGO | S_IWUSR , node->parent , NULL ,
-                                        &debugfs_operations ) ;
+    if (SizeInKB)
+    {
+        /* figure out how much of a buffer this should be and allocate the buffer */
+        node->size = 1024 * SizeInKB ;
+        if ( ( node->data = ( char * ) vmalloc ( sizeof (char ) * node->size ) ) == NULL )
+            goto data_malloc_failed ;
+
+        /*creating the file*/
+        node->filen = debugfs_create_file(NodeName, S_IRUGO|S_IWUSR, node->parent, NULL,
+                                          &debugfs_operations);
+    }
+
+    node->vidmem
+        = debugfs_create_file("vidmem", S_IRUGO|S_IWUSR, node->parent, Device, &vidmem_operations);
 
     /* add it to our linked list */
     node->next = gc_dbgfs.linkedlist ;
     gc_dbgfs.linkedlist = node ;
 
+
     /* pass the struct back */
     *Node = node ;
     return 0 ;
 
-    vfree ( node->data ) ;
+
 data_malloc_failed:
     kfree ( node ) ;
 struct_malloc_failed:
@@ -687,7 +1055,7 @@ struct_malloc_failed:
 
 /*******************************************************************************
  **
- **  gckDebugFileSystemFreeNode
+ **  gckDEBUGFS_FreeNode
  **
  **
  **  INPUT:
@@ -696,12 +1064,12 @@ struct_malloc_failed:
  **
  *******************************************************************************/
 void
-gckDebugFileSystemFreeNode (
-                             IN gcsDebugFileSystemNode * Node
+gckDEBUGFS_FreeNode (
+                             IN gcsDEBUGFS_Node * Node
                              )
 {
 
-    gcsDebugFileSystemNode **ptr ;
+    gcsDEBUGFS_Node **ptr ;
 
     if ( Node == NULL )
     {
@@ -714,13 +1082,14 @@ gckDebugFileSystemFreeNode (
     vfree ( Node->data ) ;
 
     /*Close Debug fs*/
-    if ( Node->filen )
+    if (Node->vidmem)
     {
-        debugfs_remove ( Node->filen ) ;
+        debugfs_remove(Node->vidmem);
     }
-    if ( Node->parent )
+
+    if ( Node->filen )
     {
-        debugfs_remove ( Node->parent ) ;
+        debugfs_remove ( Node->filen ) ;
     }
 
     /* now delete the node from the linked list */
@@ -741,7 +1110,7 @@ gckDebugFileSystemFreeNode (
 
 /*******************************************************************************
  **
- **   gckDebugFileSystemSetCurrentNode
+ **   gckDEBUGFS_SetCurrentNode
  **
  **
  **  INPUT:
@@ -750,8 +1119,8 @@ gckDebugFileSystemFreeNode (
  **
  *******************************************************************************/
 void
-gckDebugFileSystemSetCurrentNode (
-                                   IN gcsDebugFileSystemNode * Node
+gckDEBUGFS_SetCurrentNode (
+                                   IN gcsDEBUGFS_Node * Node
                                    )
 {
     gc_dbgfs.currentNode = Node ;
@@ -759,7 +1128,7 @@ gckDebugFileSystemSetCurrentNode (
 
 /*******************************************************************************
  **
- **   gckDebugFileSystemGetCurrentNode
+ **   gckDEBUGFS_GetCurrentNode
  **
  **
  **  INPUT:
@@ -768,8 +1137,8 @@ gckDebugFileSystemSetCurrentNode (
  **
  *******************************************************************************/
 void
-gckDebugFileSystemGetCurrentNode (
-                                   OUT gcsDebugFileSystemNode ** Node
+gckDEBUGFS_GetCurrentNode (
+                                   OUT gcsDEBUGFS_Node ** Node
                                    )
 {
     *Node = gc_dbgfs.currentNode ;
@@ -777,7 +1146,7 @@ gckDebugFileSystemGetCurrentNode (
 
 /*******************************************************************************
  **
- **   gckDebugFileSystemPrint
+ **   gckDEBUGFS_Print
  **
  **
  **  INPUT:
@@ -785,11 +1154,13 @@ gckDebugFileSystemGetCurrentNode (
  **  OUTPUT:
  **
  *******************************************************************************/
-void
-gckDebugFileSystemPrint (
+ssize_t
+gckDEBUGFS_Print (
                           IN gctCONST_STRING Message ,
                           ...
                           )
 {
-    gcmkDBGFSPRINT ( _GetArgumentSize ( Message ) , Message ) ;
+    ssize_t _debugfs_res;
+    gcmkDEBUGFS_PRINT ( _GetArgumentSize ( Message ) , Message ) ;
+    return _debugfs_res;
 }
index 78d819918988e25eb05f98ad09a306c1b6d1ace5..9d17e879410d991433666601afdc9d6316c21328 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 #ifndef __gc_hal_kernel_debugfs_h_
 #define __gc_hal_kernel_debugfs_h_
 
- #define MAX_LINE_SIZE 768          /* Max bytes for a line of debug info */
-
-
- typedef struct _gcsDebugFileSystemNode gcsDebugFileSystemNode ;
-
+ #define MAX_LINE_SIZE 768           /* Max bytes for a line of debug info */
+
+
+ typedef struct _gcsDEBUGFS_Node gcsDEBUGFS_Node;
+
+typedef struct _gcsDEBUGFS_DIR *gckDEBUGFS_DIR;
+typedef struct _gcsDEBUGFS_DIR
+{
+    struct dentry *     root;
+    struct list_head    nodeList;
+}
+gcsDEBUGFS_DIR;
+
+typedef struct _gcsINFO
+{
+    const char *        name;
+    int                 (*show)(struct seq_file*, void*);
+}
+gcsINFO;
+
+typedef struct _gcsINFO_NODE
+{
+    gcsINFO *          info;
+    gctPOINTER         device;
+    struct dentry *    entry;
+    struct list_head   head;
+}
+gcsINFO_NODE;
+
+gceSTATUS
+gckDEBUGFS_DIR_Init(
+    IN gckDEBUGFS_DIR Dir,
+    IN struct dentry *root,
+    IN gctCONST_STRING Name
+    );
+
+gceSTATUS
+gckDEBUGFS_DIR_CreateFiles(
+    IN gckDEBUGFS_DIR Dir,
+    IN gcsINFO * List,
+    IN int count,
+    IN gctPOINTER Data
+    );
+
+gceSTATUS
+gckDEBUGFS_DIR_RemoveFiles(
+    IN gckDEBUGFS_DIR Dir,
+    IN gcsINFO * List,
+    IN int count
+    );
+
+void
+gckDEBUGFS_DIR_Deinit(
+    IN gckDEBUGFS_DIR Dir
+    );
 
 /*******************************************************************************
  **
  **
  *******************************************************************************/
 
-gctINT    gckDebugFileSystemIsEnabled(void);
+gctINT gckDEBUGFS_IsEnabled(void);
 
-gctINT   gckDebugFileSystemInitialize(void);
+gctINT gckDEBUGFS_Initialize(void);
 
-gctINT   gckDebugFileSystemTerminate(void);
+gctINT gckDEBUGFS_Terminate(void);
 
 
 /*******************************************************************************
@@ -49,35 +99,36 @@ gctINT   gckDebugFileSystemTerminate(void);
  **
  *******************************************************************************/
 
-gctINT gckDebugFileSystemCreateNode(
-                       IN gctINT SizeInKB,
-                        IN gctCONST_STRING  ParentName ,
-                        IN gctCONST_STRING  NodeName,
-                        OUT gcsDebugFileSystemNode  **Node
-                        );
-
+gctINT
+gckDEBUGFS_CreateNode(
+    IN gctPOINTER Device,
+    IN gctINT SizeInKB,
+    IN struct dentry * Root,
+    IN gctCONST_STRING NodeName,
+    OUT gcsDEBUGFS_Node **Node
+    );
 
-void gckDebugFileSystemFreeNode(
-                       IN gcsDebugFileSystemNode  * Node
-                       );
+void gckDEBUGFS_FreeNode(
+            IN gcsDEBUGFS_Node  * Node
+            );
 
 
 
-void gckDebugFileSystemSetCurrentNode(
-                       IN gcsDebugFileSystemNode  * Node
-                       );
+void gckDEBUGFS_SetCurrentNode(
+            IN gcsDEBUGFS_Node  * Node
+            );
 
 
 
-void gckDebugFileSystemGetCurrentNode(
-                       OUT gcsDebugFileSystemNode  ** Node
-                       );
+void gckDEBUGFS_GetCurrentNode(
+            OUT gcsDEBUGFS_Node  ** Node
+            );
 
 
-void gckDebugFileSystemPrint(
-                       IN gctCONST_STRING  Message,
-                       ...
-                        );
+ssize_t gckDEBUGFS_Print(
+                IN gctCONST_STRING  Message,
+                ...
+                );
 
 #endif
 
index bff85a0e9bf4baee008135ff7d041cfbf27d0e67..ccec82f282bc27e7494f4bc0b894aa476bc0227a 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 #include "gc_hal_kernel_linux.h"
 #include <linux/pagemap.h>
 #include <linux/seq_file.h>
-#include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/slab.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-#include <mach/hardware.h>
-#endif
-#include <linux/pm_runtime.h>
 
 #define _GC_OBJ_ZONE    gcvZONE_DEVICE
 
-#define DEBUG_FILE                     "galcore_trace"
-#define PARENT_FILE            "gpu"
+#define DEBUG_FILE          "galcore_trace"
+#define PARENT_FILE         "gpu"
 
 
 #ifdef FLAREON
     static struct dove_gpio_irq_handler gc500_handle;
 #endif
 
-#define gcmIS_CORE_PRESENT(Device, Core) (Device->irqLines[Core] > 0)
+gckKERNEL
+_GetValidKernel(
+    gckGALDEVICE Device
+    )
+{
+    if (Device->kernels[gcvCORE_MAJOR])
+    {
+        return Device->kernels[gcvCORE_MAJOR];
+    }
+    else
+    if (Device->kernels[gcvCORE_2D])
+    {
+        return Device->kernels[gcvCORE_2D];
+    }
+    else
+    if (Device->kernels[gcvCORE_VG])
+    {
+        return Device->kernels[gcvCORE_VG];
+    }
+    else
+    {
+        return gcvNULL;
+    }
+}
+
+/******************************************************************************\
+******************************** Debugfs Support *******************************
+\******************************************************************************/
+
+/******************************************************************************\
+***************************** DEBUG SHOW FUNCTIONS *****************************
+\******************************************************************************/
+
+int gc_info_show(struct seq_file* m, void* data)
+{
+    gcsINFO_NODE *node = m->private;
+    gckGALDEVICE device = node->device;
+    int i = 0;
+    gceCHIPMODEL chipModel;
+    gctUINT32 chipRevision;
+
+    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+    {
+        if (device->irqLines[i] != -1)
+        {
+#if gcdENABLE_VG
+            if (i == gcvCORE_VG)
+            {
+                chipModel = device->kernels[i]->vg->hardware->chipModel;
+                chipRevision = device->kernels[i]->vg->hardware->chipRevision;
+            }
+            else
+#endif
+            {
+                chipModel = device->kernels[i]->hardware->identity.chipModel;
+                chipRevision = device->kernels[i]->hardware->identity.chipRevision;
+            }
+
+            seq_printf(m, "gpu      : %d\n", i);
+            seq_printf(m, "model    : %4x\n", chipModel);
+            seq_printf(m, "revision : %4x\n", chipRevision);
+            seq_printf(m, "\n");
+        }
+    }
+
+    return 0;
+}
+
+int gc_clients_show(struct seq_file* m, void* data)
+{
+    gcsINFO_NODE *node = m->private;
+    gckGALDEVICE device = node->device;
+
+    gckKERNEL kernel = _GetValidKernel(device);
+
+    gcsDATABASE_PTR database;
+    gctINT i, pid;
+    gctUINT8 name[24];
+
+    seq_printf(m, "%-8s%s\n", "PID", "NAME");
+    seq_printf(m, "------------------------\n");
+
+    /* Acquire the database mutex. */
+    gcmkVERIFY_OK(
+        gckOS_AcquireMutex(kernel->os, kernel->db->dbMutex, gcvINFINITE));
+
+    /* Walk the databases. */
+    for (i = 0; i < gcmCOUNTOF(kernel->db->db); ++i)
+    {
+        for (database = kernel->db->db[i];
+             database != gcvNULL;
+             database = database->next)
+        {
+            pid = database->processID;
+
+            gcmkVERIFY_OK(gckOS_ZeroMemory(name, gcmSIZEOF(name)));
+
+            gcmkVERIFY_OK(gckOS_GetProcessNameByPid(pid, gcmSIZEOF(name), name));
+
+            seq_printf(m, "%-8d%s\n", pid, name);
+        }
+    }
+
+    /* Release the database mutex. */
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(kernel->os, kernel->db->dbMutex));
+
+    /* Success. */
+    return 0;
+}
+
+static void
+_CounterAdd(
+    gcsDATABASE_COUNTERS * Dest,
+    gcsDATABASE_COUNTERS * Src
+    )
+{
+    Dest->bytes += Src->bytes;
+    Dest->maxBytes += Src->maxBytes;
+    Dest->totalBytes += Src->totalBytes;
+}
+
+static void
+_CounterPrint(
+    gcsDATABASE_COUNTERS * Counter,
+    gctCONST_STRING Name,
+    struct seq_file* m
+    )
+{
+    seq_printf(m, "    %s:\n", Name);
+    seq_printf(m, "        Used  : %10llu B\n", Counter->bytes);
+}
+
+int gc_meminfo_show(struct seq_file* m, void* data)
+{
+    gcsINFO_NODE *node = m->private;
+    gckGALDEVICE device = node->device;
+    gckKERNEL kernel = _GetValidKernel(device);
+    gckVIDMEM memory;
+    gceSTATUS status;
+    gcsDATABASE_PTR database;
+    gctUINT32 i;
+
+    gctUINT32 free = 0, used = 0, total = 0;
+
+    gcsDATABASE_COUNTERS contiguousCounter = {0, 0, 0};
+    gcsDATABASE_COUNTERS virtualCounter = {0, 0, 0};
+    gcsDATABASE_COUNTERS nonPagedCounter = {0, 0, 0};
+
+    status = gckKERNEL_GetVideoMemoryPool(kernel, gcvPOOL_SYSTEM, &memory);
+
+    if (gcmIS_SUCCESS(status))
+    {
+        gcmkVERIFY_OK(
+            gckOS_AcquireMutex(memory->os, memory->mutex, gcvINFINITE));
+
+        free  = memory->freeBytes;
+        used  = memory->bytes - memory->freeBytes;
+        total = memory->bytes;
+
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex));
+    }
+
+    seq_printf(m, "VIDEO MEMORY:\n");
+    seq_printf(m, "    gcvPOOL_SYSTEM:\n");
+    seq_printf(m, "        Free  : %10u B\n", free);
+    seq_printf(m, "        Used  : %10u B\n", used);
+    seq_printf(m, "        Total : %10u B\n", total);
+
+    /* Acquire the database mutex. */
+    gcmkVERIFY_OK(
+        gckOS_AcquireMutex(kernel->os, kernel->db->dbMutex, gcvINFINITE));
+
+    /* Walk the databases. */
+    for (i = 0; i < gcmCOUNTOF(kernel->db->db); ++i)
+    {
+        for (database = kernel->db->db[i];
+             database != gcvNULL;
+             database = database->next)
+        {
+            gcsDATABASE_COUNTERS * counter = &database->vidMemPool[gcvPOOL_CONTIGUOUS];
+            _CounterAdd(&contiguousCounter, counter);
+
+            counter = &database->vidMemPool[gcvPOOL_VIRTUAL];
+            _CounterAdd(&virtualCounter, counter);
+
+
+            counter = &database->nonPaged;
+            _CounterAdd(&nonPagedCounter, counter);
+        }
+    }
+
+    /* Release the database mutex. */
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(kernel->os, kernel->db->dbMutex));
+
+    _CounterPrint(&contiguousCounter, "gcvPOOL_CONTIGUOUS", m);
+    _CounterPrint(&virtualCounter, "gcvPOOL_VIRTUAL", m);
+
+    seq_printf(m, "\n");
+
+    seq_printf(m, "NON PAGED MEMORY:\n");
+    seq_printf(m, "    Used  : %10llu B\n", nonPagedCounter.bytes);
+
+    return 0;
+}
+
+static int
+_ShowRecord(
+    IN struct seq_file *file,
+    IN gcsDATABASE_RECORD_PTR record
+    )
+{
+    seq_printf(file, "%4d%8d%16p%16p%16zu\n",
+        record->type,
+        record->kernel->core,
+        record->data,
+        record->physical,
+        record->bytes
+        );
+
+    return 0;
+}
+
+static int
+_ShowRecords(
+    IN struct seq_file *File,
+    IN gcsDATABASE_PTR Database
+    )
+{
+    gctUINT i;
+
+    seq_printf(File, "Records:\n");
+
+    seq_printf(File, "%s%8s%16s%16s%16s\n",
+               "Type", "GPU", "Data", "Physical", "Bytes");
+
+    for (i = 0; i < gcmCOUNTOF(Database->list); i++)
+    {
+        gcsDATABASE_RECORD_PTR record = Database->list[i];
+
+        while (record != NULL)
+        {
+            _ShowRecord(File, record);
+            record = record->next;
+        }
+    }
+
+    return 0;
+}
+
+void
+_ShowCounters(
+    struct seq_file *File,
+    gcsDATABASE_PTR Database
+    );
+
+static void
+_ShowProcess(
+    IN struct seq_file *File,
+    IN gcsDATABASE_PTR Database
+    )
+{
+    gctINT pid;
+    gctUINT8 name[24];
+
+    /* Process ID and name */
+    pid = Database->processID;
+    gcmkVERIFY_OK(gckOS_ZeroMemory(name, gcmSIZEOF(name)));
+    gcmkVERIFY_OK(gckOS_GetProcessNameByPid(pid, gcmSIZEOF(name), name));
+
+    seq_printf(File, "--------------------------------------------------------------------------------\n");
+    seq_printf(File, "Process: %-8d %s\n", pid, name);
+
+    /* Detailed records */
+    _ShowRecords(File, Database);
+
+    seq_printf(File, "Counters:\n");
+
+    _ShowCounters(File, Database);
+}
+
+static void
+_ShowProcesses(
+    IN struct seq_file * file,
+    IN gckKERNEL Kernel
+    )
+{
+    gcsDATABASE_PTR database;
+    gctINT i;
+
+    /* Acquire the database mutex. */
+    gcmkVERIFY_OK(
+        gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+
+    /* Idle time since last call */
+    seq_printf(file, "GPU Idle: %llu ns\n",  Kernel->db->idleTime);
+    Kernel->db->idleTime = 0;
+
+    /* Walk the databases. */
+    for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
+    {
+        for (database = Kernel->db->db[i];
+             database != gcvNULL;
+             database = database->next)
+        {
+            _ShowProcess(file, database);
+        }
+    }
+
+    /* Release the database mutex. */
+    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+}
+
+static int
+gc_db_show(struct seq_file *m, void *data)
+{
+    gcsINFO_NODE *node = m->private;
+    gckGALDEVICE device = node->device;
+    gckKERNEL kernel = _GetValidKernel(device);
+    _ShowProcesses(m, kernel);
+    return 0 ;
+}
+
+static int
+gc_version_show(struct seq_file *m, void *data)
+{
+    seq_printf(m, "%s\n",  gcvVERSION_STRING);
+
+    return 0 ;
+}
+
+int gc_idle_show(struct seq_file* m, void* data)
+{
+    gcsINFO_NODE *node = m->private;
+    gckGALDEVICE device = node->device;
+    gckKERNEL kernel = _GetValidKernel(device);
+    gcuDATABASE_INFO info;
+
+    gckKERNEL_QueryProcessDB(kernel, 0, gcvFALSE, gcvDB_IDLE, &info);
+
+    seq_printf(m, "GPU idle time since last query: %llu ns\n", info.time);
+
+    return 0;
+}
+
+static gcsINFO InfoList[] =
+{
+    {"info", gc_info_show},
+    {"clients", gc_clients_show},
+    {"meminfo", gc_meminfo_show},
+    {"idle", gc_idle_show},
+    {"database", gc_db_show},
+    {"version", gc_version_show},
+};
+
+static gceSTATUS
+_DebugfsInit(
+    IN gckGALDEVICE Device
+    )
+{
+    gceSTATUS status;
+
+    gckDEBUGFS_DIR dir = &Device->debugfsDir;
+
+    gcmkONERROR(gckDEBUGFS_DIR_Init(dir, gcvNULL, "gc"));
+
+    gcmkONERROR(gckDEBUGFS_DIR_CreateFiles(dir, InfoList, gcmCOUNTOF(InfoList), Device));
+
+    return gcvSTATUS_OK;
+
+OnError:
+    return status;
+}
+
+static void
+_DebugfsCleanup(
+    IN gckGALDEVICE Device
+    )
+{
+    gckDEBUGFS_DIR dir = &Device->debugfsDir;
+
+    if (Device->debugfsDir.root)
+    {
+        gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(dir, InfoList, gcmCOUNTOF(InfoList)));
+
+        gckDEBUGFS_DIR_Deinit(dir);
+    }
+}
+
 
 /******************************************************************************\
 *************************** Memory Allocation Wrappers *************************
@@ -68,7 +450,7 @@ _AllocateMemory(
         Device->os, gcvFALSE, &Bytes, Physical, Logical
         ));
 
-    *PhysAddr = ((PLINUX_MDL)*Physical)->dmaHandle - Device->baseAddress;
+    *PhysAddr = ((PLINUX_MDL)*Physical)->dmaHandle;
 
     /* Success. */
     gcmkFOOTER_ARG(
@@ -78,38 +460,261 @@ _AllocateMemory(
 
     return gcvSTATUS_OK;
 
-OnError:
-    gcmkFOOTER();
-    return status;
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+static gceSTATUS
+_FreeMemory(
+    IN gckGALDEVICE Device,
+    IN gctPOINTER Logical,
+    IN gctPHYS_ADDR Physical)
+{
+    gceSTATUS status;
+
+    gcmkHEADER_ARG("Device=0x%x Logical=0x%x Physical=0x%x",
+                   Device, Logical, Physical);
+
+    gcmkVERIFY_ARGUMENT(Device != NULL);
+
+    status = gckOS_FreeContiguous(
+        Device->os, Physical, Logical,
+        ((PLINUX_MDL) Physical)->numPages * PAGE_SIZE
+        );
+
+    gcmkFOOTER();
+    return status;
+}
+
+
+
+/******************************************************************************\
+******************************* Interrupt Handler ******************************
+\******************************************************************************/
+#if gcdMULTI_GPU
+static irqreturn_t isrRoutine3D0(int irq, void *ctxt)
+{
+    gceSTATUS status;
+    gckGALDEVICE device;
+
+    device = (gckGALDEVICE) ctxt;
+
+    /* Call kernel interrupt notification. */
+    status = gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR],
+                              gcvCORE_3D_0_ID,
+                              gcvNOTIFY_INTERRUPT,
+                              gcvTRUE);
+
+    if (gcmIS_SUCCESS(status))
+    {
+        /* Wake up the threadRoutine to process events. */
+        device->dataReady3D[gcvCORE_3D_0_ID] = gcvTRUE;
+        wake_up_interruptible(&device->intrWaitQueue3D[gcvCORE_3D_0_ID]);
+
+        return IRQ_HANDLED;
+    }
+
+    return IRQ_NONE;
+}
+
+static int threadRoutine3D0(void *ctxt)
+{
+    gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                   "Starting isr Thread with extension=%p",
+                   device);
+
+    for (;;)
+    {
+        /* Sleep until being awaken by the interrupt handler. */
+        wait_event_interruptible(device->intrWaitQueue3D[gcvCORE_3D_0_ID],
+                                 device->dataReady3D[gcvCORE_3D_0_ID] == gcvTRUE);
+        device->dataReady3D[gcvCORE_3D_0_ID] = gcvFALSE;
+
+        if (device->killThread == gcvTRUE)
+        {
+            /* The daemon exits. */
+            while (!kthread_should_stop())
+            {
+                gckOS_Delay(device->os, 1);
+            }
+
+            return 0;
+        }
+
+        gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR],
+                         gcvCORE_3D_0_ID,
+                         gcvNOTIFY_INTERRUPT,
+                         gcvFALSE);
+    }
+}
+
+#if gcdMULTI_GPU > 1
+static irqreturn_t isrRoutine3D1(int irq, void *ctxt)
+{
+    gceSTATUS status;
+    gckGALDEVICE device;
+
+    device = (gckGALDEVICE) ctxt;
+
+    /* Call kernel interrupt notification. */
+    status = gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR],
+                              gcvCORE_3D_1_ID,
+                              gcvNOTIFY_INTERRUPT,
+                              gcvTRUE);
+
+    if (gcmIS_SUCCESS(status))
+    {
+        /* Wake up the worker thread to process events. */
+        device->dataReady3D[gcvCORE_3D_1_ID] = gcvTRUE;
+        wake_up_interruptible(&device->intrWaitQueue3D[gcvCORE_3D_1_ID]);
+
+        return IRQ_HANDLED;
+    }
+
+    return IRQ_NONE;
+}
+
+static int threadRoutine3D1(void *ctxt)
+{
+    gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                   "Starting isr Thread with extension=%p",
+                   device);
+
+    for (;;)
+    {
+        /* Sleep until being awaken by the interrupt handler. */
+        wait_event_interruptible(device->intrWaitQueue3D[gcvCORE_3D_1_ID],
+                                 device->dataReady3D[gcvCORE_3D_1_ID] == gcvTRUE);
+        device->dataReady3D[gcvCORE_3D_1_ID] = gcvFALSE;
+
+        if (device->killThread == gcvTRUE)
+        {
+            /* The daemon exits. */
+            while (!kthread_should_stop())
+            {
+                gckOS_Delay(device->os, 1);
+            }
+
+            return 0;
+        }
+
+        gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR],
+                         gcvCORE_3D_1_ID,
+                         gcvNOTIFY_INTERRUPT,
+                         gcvFALSE);
+    }
+}
+#endif
+#elif gcdMULTI_GPU_AFFINITY
+static irqreturn_t isrRoutine3D0(int irq, void *ctxt)
+{
+    gceSTATUS status;
+    gckGALDEVICE device;
+
+    device = (gckGALDEVICE) ctxt;
+
+    /* Call kernel interrupt notification. */
+    status = gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvTRUE);
+
+    if (gcmIS_SUCCESS(status))
+    {
+        up(&device->semas[gcvCORE_MAJOR]);
+
+        return IRQ_HANDLED;
+    }
+
+    return IRQ_NONE;
+}
+
+static int threadRoutine3D0(void *ctxt)
+{
+    gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                   "Starting isr Thread with extension=%p",
+                   device);
+
+    for (;;)
+    {
+        static int down;
+
+        down = down_interruptible(&device->semas[gcvCORE_MAJOR]);
+        if (down); /*To make gcc 4.6 happye*/
+
+        if (device->killThread == gcvTRUE)
+        {
+            /* The daemon exits. */
+            while (!kthread_should_stop())
+            {
+                gckOS_Delay(device->os, 1);
+            }
+
+            return 0;
+        }
+
+        gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR],
+                         gcvNOTIFY_INTERRUPT,
+                         gcvFALSE);
+    }
+}
+
+static irqreturn_t isrRoutine3D1(int irq, void *ctxt)
+{
+    gceSTATUS status;
+    gckGALDEVICE device;
+
+    device = (gckGALDEVICE) ctxt;
+
+    /* Call kernel interrupt notification. */
+    status = gckKERNEL_Notify(device->kernels[gcvCORE_OCL], gcvNOTIFY_INTERRUPT, gcvTRUE);
+
+    if (gcmIS_SUCCESS(status))
+    {
+        up(&device->semas[gcvCORE_OCL]);
+
+        return IRQ_HANDLED;
+    }
+
+    return IRQ_NONE;
 }
 
-static gceSTATUS
-_FreeMemory(
-    IN gckGALDEVICE Device,
-    IN gctPOINTER Logical,
-    IN gctPHYS_ADDR Physical)
+static int threadRoutine3D1(void *ctxt)
 {
-    gceSTATUS status;
-
-    gcmkHEADER_ARG("Device=0x%x Logical=0x%x Physical=0x%x",
-                   Device, Logical, Physical);
+    gckGALDEVICE device = (gckGALDEVICE) ctxt;
 
-    gcmkVERIFY_ARGUMENT(Device != NULL);
+    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+                   "Starting isr Thread with extension=%p",
+                   device);
 
-    status = gckOS_FreeContiguous(
-        Device->os, Physical, Logical,
-        ((PLINUX_MDL) Physical)->numPages * PAGE_SIZE
-        );
+    for (;;)
+    {
+        static int down;
 
-    gcmkFOOTER();
-    return status;
-}
+        down = down_interruptible(&device->semas[gcvCORE_OCL]);
+        if (down); /*To make gcc 4.6 happye*/
 
+        if (device->killThread == gcvTRUE)
+        {
+            /* The daemon exits. */
+            while (!kthread_should_stop())
+            {
+                gckOS_Delay(device->os, 1);
+            }
 
+            return 0;
+        }
 
-/******************************************************************************\
-******************************* Interrupt Handler ******************************
-\******************************************************************************/
+        gckKERNEL_Notify(device->kernels[gcvCORE_OCL],
+                         gcvNOTIFY_INTERRUPT,
+                         gcvFALSE);
+    }
+}
+#else
 static irqreturn_t isrRoutine(int irq, void *ctxt)
 {
     gceSTATUS status;
@@ -122,8 +727,6 @@ static irqreturn_t isrRoutine(int irq, void *ctxt)
 
     if (gcmIS_SUCCESS(status))
     {
-        device->dataReadys[gcvCORE_MAJOR] = gcvTRUE;
-
         up(&device->semas[gcvCORE_MAJOR]);
 
         return IRQ_HANDLED;
@@ -146,7 +749,6 @@ static int threadRoutine(void *ctxt)
 
         down = down_interruptible(&device->semas[gcvCORE_MAJOR]);
         if (down); /*To make gcc 4.6 happye*/
-        device->dataReadys[gcvCORE_MAJOR] = gcvFALSE;
 
         if (device->killThread == gcvTRUE)
         {
@@ -159,9 +761,12 @@ static int threadRoutine(void *ctxt)
             return 0;
         }
 
-        gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvFALSE);
+        gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR],
+                         gcvNOTIFY_INTERRUPT,
+                         gcvFALSE);
     }
 }
+#endif
 
 static irqreturn_t isrRoutine2D(int irq, void *ctxt)
 {
@@ -171,12 +776,14 @@ static irqreturn_t isrRoutine2D(int irq, void *ctxt)
     device = (gckGALDEVICE) ctxt;
 
     /* Call kernel interrupt notification. */
-    status = gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvTRUE);
-
+    status = gckKERNEL_Notify(device->kernels[gcvCORE_2D],
+#if gcdMULTI_GPU
+                              0,
+#endif
+                              gcvNOTIFY_INTERRUPT,
+                              gcvTRUE);
     if (gcmIS_SUCCESS(status))
     {
-        device->dataReadys[gcvCORE_2D] = gcvTRUE;
-
         up(&device->semas[gcvCORE_2D]);
 
         return IRQ_HANDLED;
@@ -199,7 +806,6 @@ static int threadRoutine2D(void *ctxt)
 
         down = down_interruptible(&device->semas[gcvCORE_2D]);
         if (down); /*To make gcc 4.6 happye*/
-        device->dataReadys[gcvCORE_2D] = gcvFALSE;
 
         if (device->killThread == gcvTRUE)
         {
@@ -211,8 +817,12 @@ static int threadRoutine2D(void *ctxt)
 
             return 0;
         }
-
-        gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvFALSE);
+        gckKERNEL_Notify(device->kernels[gcvCORE_2D],
+#if gcdMULTI_GPU
+                         0,
+#endif
+                         gcvNOTIFY_INTERRUPT,
+                         gcvFALSE);
     }
 }
 
@@ -224,13 +834,13 @@ static irqreturn_t isrRoutineVG(int irq, void *ctxt)
 
     device = (gckGALDEVICE) ctxt;
 
-       /* Serve the interrupt. */
-       status = gckVGINTERRUPT_Enque(device->kernels[gcvCORE_VG]->vg->interrupt);
+    /* Serve the interrupt. */
+    status = gckVGINTERRUPT_Enque(device->kernels[gcvCORE_VG]->vg->interrupt);
 
-       /* Determine the return value. */
-       return (status == gcvSTATUS_NOT_OUR_INTERRUPT)
-               ? IRQ_RETVAL(0)
-               : IRQ_RETVAL(1);
+    /* Determine the return value. */
+    return (status == gcvSTATUS_NOT_OUR_INTERRUPT)
+        ? IRQ_RETVAL(0)
+        : IRQ_RETVAL(1);
 #else
     return IRQ_NONE;
 #endif
@@ -250,7 +860,6 @@ static int threadRoutineVG(void *ctxt)
 
         down = down_interruptible(&device->semas[gcvCORE_VG]);
         if (down); /*To make gcc 4.6 happye*/
-        device->dataReadys[gcvCORE_VG] = gcvFALSE;
 
         if (device->killThread == gcvTRUE)
         {
@@ -262,8 +871,12 @@ static int threadRoutineVG(void *ctxt)
 
             return 0;
         }
-
-        gckKERNEL_Notify(device->kernels[gcvCORE_VG], gcvNOTIFY_INTERRUPT, gcvFALSE);
+        gckKERNEL_Notify(device->kernels[gcvCORE_VG],
+#if gcdMULTI_GPU
+                         0,
+#endif
+                         gcvNOTIFY_INTERRUPT,
+                         gcvFALSE);
     }
 }
 
@@ -287,9 +900,18 @@ static int threadRoutineVG(void *ctxt)
 */
 gceSTATUS
 gckGALDEVICE_Construct(
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
+    IN gctINT IrqLine3D0,
+    IN gctUINT32 RegisterMemBase3D0,
+    IN gctSIZE_T RegisterMemSize3D0,
+    IN gctINT IrqLine3D1,
+    IN gctUINT32 RegisterMemBase3D1,
+    IN gctSIZE_T RegisterMemSize3D1,
+#else
     IN gctINT IrqLine,
     IN gctUINT32 RegisterMemBase,
     IN gctSIZE_T RegisterMemSize,
+#endif
     IN gctINT IrqLine2D,
     IN gctUINT32 RegisterMemBase2D,
     IN gctSIZE_T RegisterMemSize2D,
@@ -305,9 +927,9 @@ gckGALDEVICE_Construct(
     IN gctUINT32 PhysSize,
     IN gctINT Signal,
     IN gctUINT LogFileSize,
-    IN struct device *pdev,
     IN gctINT PowerManagement,
     IN gctINT GpuProfiler,
+    IN gcsDEVICE_CONSTRUCT_ARGS * Args,
     OUT gckGALDEVICE *Device
     )
 {
@@ -320,10 +942,25 @@ gckGALDEVICE_Construct(
     gckGALDEVICE device;
     gceSTATUS status;
     gctINT32 i;
+#if gcdMULTI_GPU
+    gctINT32 j;
+#endif
     gceHARDWARE_TYPE type;
     gckDB sharedDB = gcvNULL;
     gckKERNEL kernel = gcvNULL;
 
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
+    gcmkHEADER_ARG("IrqLine3D0=%d RegisterMemBase3D0=0x%08x RegisterMemSize3D0=%u "
+                   "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
+                   "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
+                   "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
+                   "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
+                   IrqLine3D0, RegisterMemBase3D0, RegisterMemSize3D0,
+                   IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
+                   IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
+                   ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
+                   PhysBaseAddr, PhysSize, Signal);
+#else
     gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u "
                    "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
                    "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
@@ -334,9 +971,15 @@ gckGALDEVICE_Construct(
                    IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
                    ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
                    PhysBaseAddr, PhysSize, Signal);
+#endif
+
+#if gcdDISABLE_CORES_2D3D
+    IrqLine = -1;
+    IrqLine2D = -1;
+#endif
 
     /* Allocate device structure. */
-    device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL);
+    device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL | __GFP_NOWARN);
 
     if (!device)
     {
@@ -345,179 +988,182 @@ gckGALDEVICE_Construct(
 
     memset(device, 0, sizeof(struct _gckGALDEVICE));
 
-   device->dbgnode = gcvNULL;
-   if(LogFileSize != 0)
-   {
-       if(gckDebugFileSystemCreateNode(LogFileSize,PARENT_FILE,DEBUG_FILE,&(device->dbgnode)) != 0)
-       {
-               gcmkTRACE_ZONE(
-               gcvLEVEL_ERROR, gcvZONE_DRIVER,
-               "%s(%d): Failed to create  the debug file system  %s/%s \n",
-               __FUNCTION__, __LINE__,
-               PARENT_FILE, DEBUG_FILE
-               );
-       }
-       else
-       {
-               /*Everything is OK*/
-               gckDebugFileSystemSetCurrentNode(device->dbgnode);
-       }
-    }
-#ifdef CONFIG_PM
-    /*Init runtime pm for gpu*/
-    pm_runtime_enable(pdev);
-    device->pmdev = pdev;
-#endif
+    device->dbgNode = gcvNULL;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
-    /*get gpu regulator*/
-    device->gpu_regulator = regulator_get(pdev, "cpu_vddgpu");
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-    device->gpu_regulator = devm_regulator_get(pdev, "pu");
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-    if (IS_ERR(device->gpu_regulator)) {
-       gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
-               "%s(%d): Failed to get gpu regulator  %s/%s \n",
-               __FUNCTION__, __LINE__,
-               PARENT_FILE, DEBUG_FILE);
-       gcmkONERROR(gcvSTATUS_NOT_FOUND);
+    device->platform = Args->platform;
+
+    gcmkONERROR(_DebugfsInit(device));
+
+    if (gckDEBUGFS_CreateNode(
+            device, LogFileSize, device->debugfsDir.root ,DEBUG_FILE, &(device->dbgNode)))
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): Failed to create  the debug file system  %s/%s \n",
+            __FUNCTION__, __LINE__,
+            PARENT_FILE, DEBUG_FILE
+        );
     }
-#endif
-    /*Initialize the clock structure*/
-    if (IrqLine != -1) {
-        device->clk_3d_core = clk_get(pdev, "gpu3d_clk");
-        if (!IS_ERR(device->clk_3d_core)) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
-            if (cpu_is_mx6q()) {
-                   device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
-                   if (IS_ERR(device->clk_3d_shader)) {
-                       IrqLine = -1;
-                       clk_put(device->clk_3d_core);
-                       device->clk_3d_core = NULL;
-                       device->clk_3d_shader = NULL;
-                       gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
-                   }
-                 }
-#else
-                   device->clk_3d_axi = clk_get(pdev, "gpu3d_axi_clk");
-                   device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
-                   if (IS_ERR(device->clk_3d_shader)) {
-                       IrqLine = -1;
-                       clk_put(device->clk_3d_core);
-                       device->clk_3d_core = NULL;
-                       device->clk_3d_shader = NULL;
-                       gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
-                   }
-#endif
-        } else {
-            IrqLine = -1;
-            device->clk_3d_core = NULL;
-            gckOS_Print("galcore: clk_get gpu3d_clk failed, disable 3d!\n");
-        }
-    }
-    if ((IrqLine2D != -1) || (IrqLineVG != -1)) {
-        device->clk_2d_core = clk_get(pdev, "gpu2d_clk");
-        if (IS_ERR(device->clk_2d_core)) {
-            IrqLine2D = -1;
-            IrqLineVG = -1;
-            device->clk_2d_core = NULL;
-            gckOS_Print("galcore: clk_get 2d core clock failed, disable 2d/vg!\n");
-        } else {
-           if (IrqLine2D != -1) {
-                device->clk_2d_axi = clk_get(pdev, "gpu2d_axi_clk");
-                if (IS_ERR(device->clk_2d_axi)) {
-                    device->clk_2d_axi = NULL;
-                    IrqLine2D = -1;
-                    gckOS_Print("galcore: clk_get 2d axi clock failed, disable 2d\n");
-                }
-            }
-            if (IrqLineVG != -1) {
-                device->clk_vg_axi = clk_get(pdev, "openvg_axi_clk");
-                if (IS_ERR(device->clk_vg_axi)) {
-                    IrqLineVG = -1;
-                       device->clk_vg_axi = NULL;
-                       gckOS_Print("galcore: clk_get vg clock failed, disable vg!\n");
-                }
-            }
-        }
+    else if (LogFileSize)
+    {
+        gckDEBUGFS_SetCurrentNode(device->dbgNode);
+    }
+
+#if gcdMULTI_GPU
+    if (IrqLine3D0 != -1)
+    {
+        device->requestedRegisterMemBase3D[gcvCORE_3D_0_ID] = RegisterMemBase3D0;
+        device->requestedRegisterMemSize3D[gcvCORE_3D_0_ID] = RegisterMemSize3D0;
+    }
+
+    if (IrqLine3D1 != -1)
+    {
+        device->requestedRegisterMemBase3D[gcvCORE_3D_1_ID] = RegisterMemBase3D1;
+        device->requestedRegisterMemSize3D[gcvCORE_3D_1_ID] = RegisterMemSize3D1;
+    }
+#elif gcdMULTI_GPU_AFFINITY
+    if (IrqLine3D0 != -1)
+    {
+        device->requestedRegisterMemBases[gcvCORE_MAJOR] = RegisterMemBase3D0;
+        device->requestedRegisterMemSizes[gcvCORE_MAJOR] = RegisterMemSize3D0;
     }
 
+    if (IrqLine3D1 != -1)
+    {
+        device->requestedRegisterMemBases[gcvCORE_OCL] = RegisterMemBase3D1;
+        device->requestedRegisterMemSizes[gcvCORE_OCL] = RegisterMemSize3D1;
+    }
+#else
     if (IrqLine != -1)
     {
-        device->requestedRegisterMemBases[gcvCORE_MAJOR]    = RegisterMemBase;
-        device->requestedRegisterMemSizes[gcvCORE_MAJOR]    = RegisterMemSize;
+        device->requestedRegisterMemBases[gcvCORE_MAJOR] = RegisterMemBase;
+        device->requestedRegisterMemSizes[gcvCORE_MAJOR] = RegisterMemSize;
     }
+#endif
 
     if (IrqLine2D != -1)
     {
-        device->requestedRegisterMemBases[gcvCORE_2D]       = RegisterMemBase2D;
-        device->requestedRegisterMemSizes[gcvCORE_2D]       = RegisterMemSize2D;
+        device->requestedRegisterMemBases[gcvCORE_2D] = RegisterMemBase2D;
+        device->requestedRegisterMemSizes[gcvCORE_2D] = RegisterMemSize2D;
     }
 
     if (IrqLineVG != -1)
     {
-        device->requestedRegisterMemBases[gcvCORE_VG]       = RegisterMemBaseVG;
-        device->requestedRegisterMemSizes[gcvCORE_VG]       = RegisterMemSizeVG;
+        device->requestedRegisterMemBases[gcvCORE_VG] = RegisterMemBaseVG;
+        device->requestedRegisterMemSizes[gcvCORE_VG] = RegisterMemSizeVG;
     }
 
     device->requestedContiguousBase  = 0;
     device->requestedContiguousSize  = 0;
 
-
     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
     {
-        physical = device->requestedRegisterMemBases[i];
+#if gcdMULTI_GPU
+        if (i == gcvCORE_MAJOR)
+        {
+            for (j = 0; j < gcdMULTI_GPU; j++)
+            {
+                physical = device->requestedRegisterMemBase3D[j];
+
+                /* Set up register memory region. */
+                if (physical != 0)
+                {
+                    mem_region = request_mem_region(physical,
+                            device->requestedRegisterMemSize3D[j],
+                            "galcore register region");
+
+                    if (mem_region == gcvNULL)
+                    {
+                        gcmkTRACE_ZONE(
+                                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                                "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
+                                __FUNCTION__, __LINE__,
+                                physical, device->requestedRegisterMemSize3D[j]
+                        );
+
+                        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+                    }
+
+                    device->registerBase3D[j] = (gctPOINTER) ioremap_nocache(
+                            physical, device->requestedRegisterMemSize3D[j]);
+
+                    if (device->registerBase3D[j] == gcvNULL)
+                    {
+                        gcmkTRACE_ZONE(
+                                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                                "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
+                                __FUNCTION__, __LINE__,
+                                physical, device->requestedRegisterMemSize3D[j]
+                        );
+
+                        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+                    }
 
-        /* Set up register memory region. */
-        if (physical != 0)
+                    physical += device->requestedRegisterMemSize3D[j];
+                }
+                else
+                {
+                    device->registerBase3D[j] = gcvNULL;
+                }
+            }
+        }
+        else
+#endif
         {
-            mem_region = request_mem_region(
-                physical, device->requestedRegisterMemSizes[i], "galcore register region"
-                );
+            physical = device->requestedRegisterMemBases[i];
 
-            if (mem_region == gcvNULL)
+            /* Set up register memory region. */
+            if (physical != 0)
             {
-                gcmkTRACE_ZONE(
-                    gcvLEVEL_ERROR, gcvZONE_DRIVER,
-                    "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
-                    __FUNCTION__, __LINE__,
-                    physical, device->requestedRegisterMemSizes[i]
+                mem_region = request_mem_region(physical,
+                        device->requestedRegisterMemSizes[i],
+                        "galcore register region");
+
+                if (mem_region == gcvNULL)
+                {
+                    gcmkTRACE_ZONE(
+                            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                            "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
+                            __FUNCTION__, __LINE__,
+                            physical, device->requestedRegisterMemSizes[i]
                     );
 
-                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
-            }
+                    gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+                }
 
-            device->registerBases[i] = (gctPOINTER) ioremap_nocache(
-                physical, device->requestedRegisterMemSizes[i]);
+                device->registerBases[i] = (gctPOINTER) ioremap_nocache(
+                        physical, device->requestedRegisterMemSizes[i]);
 
-            if (device->registerBases[i] == gcvNULL)
-            {
-                gcmkTRACE_ZONE(
-                    gcvLEVEL_ERROR, gcvZONE_DRIVER,
-                    "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
-                    __FUNCTION__, __LINE__,
-                    physical, device->requestedRegisterMemSizes[i]
+                if (device->registerBases[i] == gcvNULL)
+                {
+                    gcmkTRACE_ZONE(
+                            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                            "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
+                            __FUNCTION__, __LINE__,
+                            physical, device->requestedRegisterMemSizes[i]
                     );
 
-                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
-            }
+                    gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+                }
 
-            physical += device->requestedRegisterMemSizes[i];
-        }
-        else
-        {
-            device->registerBases[i] = gcvNULL;
+                physical += device->requestedRegisterMemSizes[i];
+            }
         }
     }
 
     /* Set the base address */
-    device->baseAddress = PhysBaseAddr;
+    device->baseAddress = device->physBase = PhysBaseAddr;
+    device->physSize = PhysSize;
+    device->mmu      = Args->mmu;
 
     /* Construct the gckOS object. */
     gcmkONERROR(gckOS_Construct(device, &device->os));
 
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
+    if (IrqLine3D0 != -1)
+#else
     if (IrqLine != -1)
+#endif
     {
         /* Construct the gckKERNEL object. */
         gcmkONERROR(gckKERNEL_Construct(
@@ -544,14 +1190,42 @@ gckGALDEVICE_Construct(
             device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
             ));
 
-        gcmkONERROR(gckHARDWARE_SetPowerManagement(
-            device->kernels[gcvCORE_MAJOR]->hardware, PowerManagement
+        if(PowerManagement != -1)
+        {
+            gcmkONERROR(gckHARDWARE_SetPowerManagementLock(
+                device->kernels[gcvCORE_MAJOR]->hardware, gcvFALSE
+                ));
+            gcmkONERROR(gckHARDWARE_SetPowerManagement(
+                device->kernels[gcvCORE_MAJOR]->hardware, PowerManagement
+                ));
+            gcmkONERROR(gckHARDWARE_SetPowerManagementLock(
+                device->kernels[gcvCORE_MAJOR]->hardware, gcvTRUE
+                ));
+        }
+        else
+        {
+            gcmkONERROR(gckHARDWARE_SetPowerManagementLock(
+                device->kernels[gcvCORE_MAJOR]->hardware, gcvFALSE
+                ));
+            gcmkONERROR(gckHARDWARE_SetPowerManagement(
+                device->kernels[gcvCORE_MAJOR]->hardware, gcvTRUE
+                ));
+        }
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+        gcmkONERROR(gckHARDWARE_SetMinFscaleValue(
+            device->kernels[gcvCORE_MAJOR]->hardware, Args->gpu3DMinClock
             ));
+#endif
 
         gcmkONERROR(gckHARDWARE_SetGpuProfiler(
             device->kernels[gcvCORE_MAJOR]->hardware, GpuProfiler
             ));
 
+        gcmkVERIFY_OK(gckKERNEL_SetRecovery(
+            device->kernels[gcvCORE_MAJOR], Args->recovery, Args->stuckDump
+            ));
+
 #if COMMAND_PROCESSOR_VERSION == 1
         /* Start the command queue. */
         gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command));
@@ -562,6 +1236,79 @@ gckGALDEVICE_Construct(
         device->kernels[gcvCORE_MAJOR] = gcvNULL;
     }
 
+#if gcdMULTI_GPU_AFFINITY
+    if (IrqLine3D1 != -1)
+    {
+        /* Construct the gckKERNEL object. */
+        gcmkONERROR(gckKERNEL_Construct(
+            device->os, gcvCORE_OCL, device,
+            gcvNULL, &device->kernels[gcvCORE_OCL]));
+
+        if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_OCL]->db;
+
+        /* Initialize core mapping */
+        if (device->kernels[gcvCORE_MAJOR] == gcvNULL)
+        {
+            for (i = 0; i < 8; i++)
+            {
+                device->coreMapping[i] = gcvCORE_OCL;
+            }
+        }
+        else
+        {
+            device->coreMapping[gcvHARDWARE_OCL] = gcvCORE_OCL;
+        }
+
+        /* Setup the ISR manager. */
+        gcmkONERROR(gckHARDWARE_SetIsrManager(
+            device->kernels[gcvCORE_OCL]->hardware,
+            (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
+            (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
+            device
+            ));
+
+        gcmkONERROR(gckHARDWARE_SetFastClear(
+            device->kernels[gcvCORE_OCL]->hardware, FastClear, Compression
+            ));
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+        gcmkONERROR(gckHARDWARE_SetMinFscaleValue(
+            device->kernels[gcvCORE_OCL]->hardware, Args->gpu3DMinClock
+            ));
+#endif
+        if(PowerManagement != -1)
+        {
+            gcmkONERROR(gckHARDWARE_SetPowerManagementLock(
+                device->kernels[gcvCORE_OCL]->hardware, gcvFALSE
+                ));
+            gcmkONERROR(gckHARDWARE_SetPowerManagement(
+                device->kernels[gcvCORE_OCL]->hardware, PowerManagement
+                ));
+            gcmkONERROR(gckHARDWARE_SetPowerManagementLock(
+                device->kernels[gcvCORE_OCL]->hardware, gcvTRUE
+                ));
+        }
+        else
+        {
+            gcmkONERROR(gckHARDWARE_SetPowerManagementLock(
+                device->kernels[gcvCORE_OCL]->hardware, gcvFALSE
+                ));
+            gcmkONERROR(gckHARDWARE_SetPowerManagement(
+                device->kernels[gcvCORE_OCL]->hardware, gcvTRUE
+                ));
+        }
+
+#if COMMAND_PROCESSOR_VERSION == 1
+        /* Start the command queue. */
+        gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_OCL]->command));
+#endif
+    }
+    else
+    {
+        device->kernels[gcvCORE_OCL] = gcvNULL;
+    }
+#endif
+
     if (IrqLine2D != -1)
     {
         gcmkONERROR(gckKERNEL_Construct(
@@ -586,7 +1333,11 @@ gckGALDEVICE_Construct(
         }
 
         /* Initialize core mapping */
-        if (device->kernels[gcvCORE_MAJOR] == gcvNULL)
+        if (device->kernels[gcvCORE_MAJOR] == gcvNULL
+#if gcdMULTI_GPU_AFFINITY
+            && device->kernels[gcvCORE_OCL] == gcvNULL
+#endif
+            )
         {
             for (i = 0; i < 8; i++)
             {
@@ -606,10 +1357,37 @@ gckGALDEVICE_Construct(
             device
             ));
 
-        gcmkONERROR(gckHARDWARE_SetPowerManagement(
-            device->kernels[gcvCORE_2D]->hardware, PowerManagement
+        if(PowerManagement != -1)
+        {
+            gcmkONERROR(gckHARDWARE_SetPowerManagementLock(
+                device->kernels[gcvCORE_2D]->hardware, gcvFALSE
+                ));
+            gcmkONERROR(gckHARDWARE_SetPowerManagement(
+                device->kernels[gcvCORE_2D]->hardware, PowerManagement
+                ));
+            gcmkONERROR(gckHARDWARE_SetPowerManagementLock(
+                device->kernels[gcvCORE_2D]->hardware, gcvTRUE
+                ));
+        }
+        else
+        {
+            gcmkONERROR(gckHARDWARE_SetPowerManagementLock(
+                device->kernels[gcvCORE_2D]->hardware, gcvFALSE
+                ));
+            gcmkONERROR(gckHARDWARE_SetPowerManagement(
+                device->kernels[gcvCORE_2D]->hardware, gcvTRUE
+                ));
+        }
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+        gcmkONERROR(gckHARDWARE_SetMinFscaleValue(
+            device->kernels[gcvCORE_2D]->hardware, 1
             ));
+#endif
 
+        gcmkVERIFY_OK(gckKERNEL_SetRecovery(
+            device->kernels[gcvCORE_2D], Args->recovery, Args->stuckDump
+            ));
 
 #if COMMAND_PROCESSOR_VERSION == 1
         /* Start the command queue. */
@@ -630,6 +1408,9 @@ gckGALDEVICE_Construct(
         /* Initialize core mapping */
         if (device->kernels[gcvCORE_MAJOR] == gcvNULL
             && device->kernels[gcvCORE_2D] == gcvNULL
+#if gcdMULTI_GPU_AFFINITY
+            && device->kernels[gcvCORE_OCL] == gcvNULL
+#endif
             )
         {
             for (i = 0; i < 8; i++)
@@ -642,11 +1423,21 @@ gckGALDEVICE_Construct(
             device->coreMapping[gcvHARDWARE_VG] = gcvCORE_VG;
         }
 
+        if(PowerManagement != -1)
+        {
+            gcmkONERROR(gckVGHARDWARE_SetPowerManagement(
+                device->kernels[gcvCORE_VG]->vg->hardware,
+                PowerManagement
+                ));
+        }
+        else
+        {
+            gcmkONERROR(gckVGHARDWARE_SetPowerManagement(
+                device->kernels[gcvCORE_VG]->vg->hardware,
+                gcvTRUE
+                ));
+        }
 
-        gcmkONERROR(gckVGHARDWARE_SetPowerManagement(
-            device->kernels[gcvCORE_VG]->vg->hardware,
-            PowerManagement
-            ));
 
 #endif
     }
@@ -656,14 +1447,36 @@ gckGALDEVICE_Construct(
     }
 
     /* Initialize the ISR. */
+#if gcdMULTI_GPU
+    device->irqLine3D[gcvCORE_3D_0_ID] = IrqLine3D0;
+#if gcdMULTI_GPU > 1
+    device->irqLine3D[gcvCORE_3D_1_ID] = IrqLine3D1;
+#endif
+#elif gcdMULTI_GPU_AFFINITY
+    device->irqLines[gcvCORE_MAJOR] = IrqLine3D0;
+    device->irqLines[gcvCORE_OCL]   = IrqLine3D1;
+#else
     device->irqLines[gcvCORE_MAJOR] = IrqLine;
-    device->irqLines[gcvCORE_2D]    = IrqLine2D;
-    device->irqLines[gcvCORE_VG]    = IrqLineVG;
+#endif
+    device->irqLines[gcvCORE_2D] = IrqLine2D;
+    device->irqLines[gcvCORE_VG] = IrqLineVG;
 
     /* Initialize the kernel thread semaphores. */
     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
     {
-        if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
+#if gcdMULTI_GPU
+        if (i == gcvCORE_MAJOR)
+        {
+            for (j = 0; j < gcdMULTI_GPU; j++)
+            {
+                if (device->irqLine3D[j] != -1) init_waitqueue_head(&device->intrWaitQueue3D[j]);
+            }
+        }
+        else
+#endif
+        {
+            if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
+        }
     }
 
     device->signal = Signal;
@@ -674,9 +1487,9 @@ gckGALDEVICE_Construct(
     }
 
     if (i == gcdMAX_GPU_COUNT)
-       {
-               gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
-       }
+    {
+        gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+    }
 
 #if gcdENABLE_VG
     if (i == gcvCORE_VG)
@@ -718,10 +1531,26 @@ gckGALDEVICE_Construct(
     /* Grab the first availiable kernel */
     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
     {
-        if (device->irqLines[i] != -1)
+#if gcdMULTI_GPU
+        if (i == gcvCORE_MAJOR)
+        {
+            for (j = 0; j < gcdMULTI_GPU; j++)
+            {
+                if (device->irqLine3D[j] != -1)
+                {
+                    kernel = device->kernels[i];
+                    break;
+                }
+            }
+        }
+        else
+#endif
         {
-            kernel = device->kernels[i];
-            break;
+            if (device->irqLines[i] != -1)
+            {
+                kernel = device->kernels[i];
+                break;
+            }
         }
     }
 
@@ -862,45 +1691,28 @@ gckGALDEVICE_Construct(
             }
             else
             {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-                mem_region = request_mem_region(
-                    ContiguousBase, ContiguousSize, "galcore managed memory"
-                    );
-
-                if (mem_region == gcvNULL)
+                if (Args->contiguousRequested == gcvFALSE)
                 {
-                    gcmkTRACE_ZONE(
-                        gcvLEVEL_ERROR, gcvZONE_DRIVER,
-                        "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
-                        __FUNCTION__, __LINE__,
-                        ContiguousSize, ContiguousBase
+                    mem_region = request_mem_region(
+                        ContiguousBase, ContiguousSize, "galcore managed memory"
                         );
 
-                    gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
-                }
-#endif
-
-                device->requestedContiguousBase  = ContiguousBase;
-                device->requestedContiguousSize  = ContiguousSize;
-
-#if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
-                if (gcmIS_CORE_PRESENT(device, gcvCORE_VG))
-                {
-                    device->contiguousBase
-#if gcdPAGED_MEMORY_CACHEABLE
-                        = (gctPOINTER) ioremap_cached(ContiguousBase, ContiguousSize);
-#else
-                        = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize);
-#endif
-                    if (device->contiguousBase == gcvNULL)
+                    if (mem_region == gcvNULL)
                     {
-                        device->contiguousVidMem = gcvNULL;
-                        device->contiguousSize = 0;
+                        gcmkTRACE_ZONE(
+                            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                            "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
+                            __FUNCTION__, __LINE__,
+                            ContiguousSize, ContiguousBase
+                            );
 
                         gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
                     }
                 }
-#endif
+
+                device->requestedContiguousBase  = ContiguousBase;
+                device->requestedContiguousSize  = ContiguousSize;
+                device->contiguousRequested      = Args->contiguousRequested;
 
                 device->contiguousPhysical = gcvNULL;
                 device->contiguousPhysicalName = 0;
@@ -911,7 +1723,7 @@ gckGALDEVICE_Construct(
     }
 
     /* Return pointer to the device. */
-    * Device = device;
+    *Device = device;
 
     gcmkFOOTER_ARG("*Device=0x%x", * Device);
     return gcvSTATUS_OK;
@@ -947,7 +1759,9 @@ gckGALDEVICE_Destroy(
     gckGALDEVICE Device)
 {
     gctINT i;
-    gceSTATUS status = gcvSTATUS_OK;
+#if gcdMULTI_GPU
+    gctINT j;
+#endif
     gckKERNEL kernel = gcvNULL;
 
     gcmkHEADER_ARG("Device=0x%x", Device);
@@ -957,12 +1771,29 @@ gckGALDEVICE_Destroy(
         /* Grab the first availiable kernel */
         for (i = 0; i < gcdMAX_GPU_COUNT; i++)
         {
-            if (Device->irqLines[i] != -1)
+#if gcdMULTI_GPU
+            if (i == gcvCORE_MAJOR)
             {
-                kernel = Device->kernels[i];
-                break;
+                for (j = 0; j < gcdMULTI_GPU; j++)
+                {
+                    if (Device->irqLine3D[j] != -1)
+                    {
+                        kernel = Device->kernels[i];
+                        break;
+                    }
+                }
+            }
+            else
+#endif
+            {
+                if (Device->irqLines[i] != -1)
+                {
+                    kernel = Device->kernels[i];
+                    break;
+                }
             }
         }
+
         if (Device->internalPhysicalName != 0)
         {
             gcmRELEASE_NAME(Device->internalPhysicalName);
@@ -990,144 +1821,118 @@ gckGALDEVICE_Destroy(
             }
         }
 
+        if (Device->internalLogical != gcvNULL)
         {
-            if (Device->internalLogical != gcvNULL)
-            {
-                /* Unmap the internal memory. */
-                iounmap(Device->internalLogical);
-                Device->internalLogical = gcvNULL;
-            }
+            /* Unmap the internal memory. */
+            iounmap(Device->internalLogical);
+            Device->internalLogical = gcvNULL;
+        }
 
-            if (Device->internalVidMem != gcvNULL)
-            {
-                /* Destroy the internal heap. */
-                gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
-                Device->internalVidMem = gcvNULL;
-            }
+        if (Device->internalVidMem != gcvNULL)
+        {
+            /* Destroy the internal heap. */
+            gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
+            Device->internalVidMem = gcvNULL;
         }
 
+        if (Device->externalLogical != gcvNULL)
         {
-            if (Device->externalLogical != gcvNULL)
-            {
-                /* Unmap the external memory. */
-                iounmap(Device->externalLogical);
-                Device->externalLogical = gcvNULL;
-            }
+            /* Unmap the external memory. */
+            iounmap(Device->externalLogical);
+            Device->externalLogical = gcvNULL;
+        }
 
-            if (Device->externalVidMem != gcvNULL)
+        if (Device->externalVidMem != gcvNULL)
+        {
+            /* destroy the external heap */
+            gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
+            Device->externalVidMem = gcvNULL;
+        }
+
+        if (Device->contiguousBase != gcvNULL)
+        {
+            if (Device->contiguousMapped == gcvFALSE)
             {
-                /* destroy the external heap */
-                gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
-                Device->externalVidMem = gcvNULL;
+                gcmkVERIFY_OK(_FreeMemory(
+                    Device,
+                    Device->contiguousBase,
+                    Device->contiguousPhysical
+                    ));
             }
+
+            Device->contiguousBase     = gcvNULL;
+            Device->contiguousPhysical = gcvNULL;
         }
 
+        if (Device->requestedContiguousBase != 0
+         && Device->contiguousRequested == gcvFALSE
+        )
         {
-            if (Device->contiguousBase != gcvNULL)
-            {
-                if (Device->contiguousMapped)
-                {
-#if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
-                    if (Device->contiguousBase)
-                    {
-                        /* Unmap the contiguous memory. */
-                        iounmap(Device->contiguousBase);
-                    }
-#endif
-                }
-                else
-                {
-                    gcmkONERROR(_FreeMemory(
-                        Device,
-                        Device->contiguousBase,
-                        Device->contiguousPhysical
-                        ));
-                }
+            release_mem_region(Device->requestedContiguousBase, Device->requestedContiguousSize);
+            Device->requestedContiguousBase = 0;
+            Device->requestedContiguousSize = 0;
+        }
 
-                Device->contiguousBase     = gcvNULL;
-                Device->contiguousPhysical = gcvNULL;
-            }
+        if (Device->contiguousVidMem != gcvNULL)
+        {
+            /* Destroy the contiguous heap. */
+            gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
+            Device->contiguousVidMem = gcvNULL;
+        }
 
-            if (Device->requestedContiguousBase != 0)
-            {
-                release_mem_region(Device->requestedContiguousBase, Device->requestedContiguousSize);
-                Device->requestedContiguousBase = 0;
-                Device->requestedContiguousSize = 0;
-            }
+        if (Device->dbgNode)
+        {
+            gckDEBUGFS_FreeNode(Device->dbgNode);
 
-            if (Device->contiguousVidMem != gcvNULL)
+            if(Device->dbgNode != gcvNULL)
             {
-                /* Destroy the contiguous heap. */
-                gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
-                Device->contiguousVidMem = gcvNULL;
+                kfree(Device->dbgNode);
+                Device->dbgNode = gcvNULL;
             }
         }
 
-       {
-           if(gckDebugFileSystemIsEnabled())
-           {
-                gckDebugFileSystemFreeNode(Device->dbgnode);
-                kfree(Device->dbgnode);
-                Device->dbgnode = gcvNULL;
-           }
-       }
-
         for (i = 0; i < gcdMAX_GPU_COUNT; i++)
         {
-            if (Device->registerBases[i] != gcvNULL)
+#if gcdMULTI_GPU
+            if (i == gcvCORE_MAJOR)
             {
-                /* Unmap register memory. */
-                iounmap(Device->registerBases[i]);
-                           if (Device->requestedRegisterMemBases[i] != 0)
-                           {
-                                   release_mem_region(Device->requestedRegisterMemBases[i], Device->requestedRegisterMemSizes[i]);
-                           }
-
-                Device->registerBases[i] = gcvNULL;
-                Device->requestedRegisterMemBases[i] = 0;
-                Device->requestedRegisterMemSizes[i] = 0;
+                for (j = 0; j < gcdMULTI_GPU; j++)
+                {
+                    if (Device->registerBase3D[j] != gcvNULL)
+                    {
+                        /* Unmap register memory. */
+                        iounmap(Device->registerBase3D[j]);
+                        if (Device->requestedRegisterMemBase3D[j] != 0)
+                        {
+                            release_mem_region(Device->requestedRegisterMemBase3D[j],
+                                    Device->requestedRegisterMemSize3D[j]);
+                        }
+
+                        Device->registerBase3D[j] = gcvNULL;
+                        Device->requestedRegisterMemBase3D[j] = 0;
+                        Device->requestedRegisterMemSize3D[j] = 0;
+                    }
+                }
             }
-        }
-
-        /*Disable clock*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-        if (Device->clk_3d_axi) {
-           clk_put(Device->clk_3d_axi);
-           Device->clk_3d_axi = NULL;
-        }
-#endif
-        if (Device->clk_3d_core) {
-           clk_put(Device->clk_3d_core);
-           Device->clk_3d_core = NULL;
-        }
-        if (Device->clk_3d_shader) {
-           clk_put(Device->clk_3d_shader);
-           Device->clk_3d_shader = NULL;
-        }
-        if (Device->clk_2d_core) {
-           clk_put(Device->clk_2d_core);
-           Device->clk_2d_core = NULL;
-        }
-        if (Device->clk_2d_axi) {
-           clk_put(Device->clk_2d_axi);
-           Device->clk_2d_axi = NULL;
-        }
-        if (Device->clk_vg_axi) {
-           clk_put(Device->clk_vg_axi);
-           Device->clk_vg_axi = NULL;
-        }
-
-#ifdef CONFIG_PM
-        if(Device->pmdev)
-            pm_runtime_disable(Device->pmdev);
+            else
 #endif
+            {
+                if (Device->registerBases[i] != gcvNULL)
+                {
+                    /* Unmap register memory. */
+                    iounmap(Device->registerBases[i]);
+                    if (Device->requestedRegisterMemBases[i] != 0)
+                    {
+                        release_mem_region(Device->requestedRegisterMemBases[i],
+                                Device->requestedRegisterMemSizes[i]);
+                    }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
-        if (Device->gpu_regulator) {
-           regulator_put(Device->gpu_regulator);
-           Device->gpu_regulator = NULL;
+                    Device->registerBases[i] = gcvNULL;
+                    Device->requestedRegisterMemBases[i] = 0;
+                    Device->requestedRegisterMemSizes[i] = 0;
+                }
+            }
         }
-#endif
 
         /* Destroy the gckOS object. */
         if (Device->os != gcvNULL)
@@ -1136,16 +1941,14 @@ gckGALDEVICE_Destroy(
             Device->os = gcvNULL;
         }
 
+        _DebugfsCleanup(Device);
+
         /* Free the device. */
         kfree(Device);
     }
 
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
-
-OnError:
-    gcmkFOOTER();
-    return status;
 }
 
 /*******************************************************************************
@@ -1176,7 +1979,7 @@ gckGALDEVICE_Setup_ISR(
     )
 {
     gceSTATUS status;
-    gctINT ret;
+    gctINT ret = 0;
 
     gcmkHEADER_ARG("Device=0x%x", Device);
 
@@ -1198,12 +2001,94 @@ gckGALDEVICE_Setup_ISR(
     ret = dove_gpio_request(
         DOVE_GPIO0_7, &gc500_handle
         );
+#else
+#if gcdMULTI_GPU
+    ret = request_irq(
+        Device->irqLine3D[gcvCORE_3D_0_ID], isrRoutine3D0, IRQF_DISABLED,
+        "galcore_3d_0", Device
+        );
+
+    if (ret != 0)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): Could not register irq line %d (error=%d)\n",
+            __FUNCTION__, __LINE__,
+            Device->irqLine3D[gcvCORE_3D_0_ID], ret
+            );
+
+        gcmkONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    /* Mark ISR as initialized. */
+    Device->isrInitialized3D[gcvCORE_3D_0_ID] = gcvTRUE;
+
+#if gcdMULTI_GPU > 1
+    ret = request_irq(
+        Device->irqLine3D[gcvCORE_3D_1_ID], isrRoutine3D1, IRQF_DISABLED,
+        "galcore_3d_1", Device
+        );
+
+    if (ret != 0)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): Could not register irq line %d (error=%d)\n",
+            __FUNCTION__, __LINE__,
+            Device->irqLine3D[gcvCORE_3D_1_ID], ret
+            );
+
+        gcmkONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    /* Mark ISR as initialized. */
+    Device->isrInitialized3D[gcvCORE_3D_1_ID] = gcvTRUE;
+#endif
+#elif gcdMULTI_GPU_AFFINITY
+    ret = request_irq(
+        Device->irqLines[gcvCORE_MAJOR], isrRoutine3D0, IRQF_DISABLED,
+        "galcore_3d_0", Device
+        );
+
+    if (ret != 0)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): Could not register irq line %d (error=%d)\n",
+            __FUNCTION__, __LINE__,
+            Device->irqLines[gcvCORE_MAJOR], ret
+            );
+
+        gcmkONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    /* Mark ISR as initialized. */
+    Device->isrInitializeds[gcvCORE_MAJOR] = gcvTRUE;
+
+    ret = request_irq(
+        Device->irqLines[gcvCORE_OCL], isrRoutine3D1, IRQF_DISABLED,
+        "galcore_3d_1", Device
+        );
+
+    if (ret != 0)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_ERROR, gcvZONE_DRIVER,
+            "%s(%d): Could not register irq line %d (error=%d)\n",
+            __FUNCTION__, __LINE__,
+            Device->irqLines[gcvCORE_OCL], ret
+            );
+
+        gcmkONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    /* Mark ISR as initialized. */
+    Device->isrInitializeds[gcvCORE_OCL] = gcvTRUE;
 #else
     ret = request_irq(
         Device->irqLines[gcvCORE_MAJOR], isrRoutine, IRQF_DISABLED,
         "galcore interrupt service", Device
         );
-#endif
 
     if (ret != 0)
     {
@@ -1219,6 +2104,8 @@ gckGALDEVICE_Setup_ISR(
 
     /* Mark ISR as initialized. */
     Device->isrInitializeds[gcvCORE_MAJOR] = gcvTRUE;
+#endif
+#endif
 
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
@@ -1372,6 +2259,22 @@ gckGALDEVICE_Release_ISR(
 
     gcmkVERIFY_ARGUMENT(Device != NULL);
 
+#if gcdMULTI_GPU
+    /* release the irq */
+    if (Device->isrInitialized3D[gcvCORE_3D_0_ID])
+    {
+        free_irq(Device->irqLine3D[gcvCORE_3D_0_ID], Device);
+        Device->isrInitialized3D[gcvCORE_3D_0_ID] = gcvFALSE;
+    }
+#if gcdMULTI_GPU > 1
+    /* release the irq */
+    if (Device->isrInitialized3D[gcvCORE_3D_1_ID])
+    {
+        free_irq(Device->irqLine3D[gcvCORE_3D_1_ID], Device);
+        Device->isrInitialized3D[gcvCORE_3D_1_ID] = gcvFALSE;
+    }
+#endif
+#else
     /* release the irq */
     if (Device->isrInitializeds[gcvCORE_MAJOR])
     {
@@ -1380,9 +2283,9 @@ gckGALDEVICE_Release_ISR(
 #else
         free_irq(Device->irqLines[gcvCORE_MAJOR], Device);
 #endif
-
-           Device->isrInitializeds[gcvCORE_MAJOR] = gcvFALSE;
+        Device->isrInitializeds[gcvCORE_MAJOR] = gcvFALSE;
     }
+#endif
 
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
@@ -1406,7 +2309,7 @@ gckGALDEVICE_Release_ISR_2D(
         free_irq(Device->irqLines[gcvCORE_2D], Device);
 #endif
 
-           Device->isrInitializeds[gcvCORE_2D] = gcvFALSE;
+        Device->isrInitializeds[gcvCORE_2D] = gcvFALSE;
     }
 
     gcmkFOOTER_NO();
@@ -1431,7 +2334,7 @@ gckGALDEVICE_Release_ISR_VG(
         free_irq(Device->irqLines[gcvCORE_VG], Device);
 #endif
 
-           Device->isrInitializeds[gcvCORE_VG] = gcvFALSE;
+        Device->isrInitializeds[gcvCORE_VG] = gcvFALSE;
     }
 
     gcmkFOOTER_NO();
@@ -1472,6 +2375,86 @@ gckGALDEVICE_Start_Threads(
 
     gcmkVERIFY_ARGUMENT(Device != NULL);
 
+#if gcdMULTI_GPU
+    if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
+    {
+        /* Start the kernel thread. */
+        task = kthread_run(threadRoutine3D0, Device, "galcore_3d_0");
+
+        if (IS_ERR(task))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): Could not start the kernel thread.\n",
+                __FUNCTION__, __LINE__
+                );
+
+            gcmkONERROR(gcvSTATUS_GENERIC_IO);
+        }
+
+        Device->threadCtxt3D[gcvCORE_3D_0_ID]          = task;
+        Device->threadInitialized3D[gcvCORE_3D_0_ID]   = gcvTRUE;
+
+#if gcdMULTI_GPU > 1
+        /* Start the kernel thread. */
+        task = kthread_run(threadRoutine3D1, Device, "galcore_3d_1");
+
+        if (IS_ERR(task))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): Could not start the kernel thread.\n",
+                __FUNCTION__, __LINE__
+                );
+
+            gcmkONERROR(gcvSTATUS_GENERIC_IO);
+        }
+
+        Device->threadCtxt3D[gcvCORE_3D_1_ID]          = task;
+        Device->threadInitialized3D[gcvCORE_3D_1_ID]   = gcvTRUE;
+#endif
+    }
+#elif gcdMULTI_GPU_AFFINITY
+    if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
+    {
+        /* Start the kernel thread. */
+        task = kthread_run(threadRoutine3D0, Device, "galcore_3d_0");
+
+        if (IS_ERR(task))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): Could not start the kernel thread.\n",
+                __FUNCTION__, __LINE__
+                );
+
+            gcmkONERROR(gcvSTATUS_GENERIC_IO);
+        }
+
+        Device->threadCtxts[gcvCORE_MAJOR]          = task;
+        Device->threadInitializeds[gcvCORE_MAJOR]   = gcvTRUE;
+    }
+
+    if (Device->kernels[gcvCORE_OCL] != gcvNULL)
+    {
+        /* Start the kernel thread. */
+        task = kthread_run(threadRoutine3D1, Device, "galcore_3d_1");
+
+        if (IS_ERR(task))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                "%s(%d): Could not start the kernel thread.\n",
+                __FUNCTION__, __LINE__
+                );
+
+            gcmkONERROR(gcvSTATUS_GENERIC_IO);
+        }
+
+        Device->threadCtxts[gcvCORE_OCL]          = task;
+        Device->threadInitializeds[gcvCORE_OCL]   = gcvTRUE;
+    }
+#else
     if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
     {
         /* Start the kernel thread. */
@@ -1491,6 +2474,7 @@ gckGALDEVICE_Start_Threads(
         Device->threadCtxts[gcvCORE_MAJOR]          = task;
         Device->threadInitializeds[gcvCORE_MAJOR]   = gcvTRUE;
     }
+#endif
 
     if (Device->kernels[gcvCORE_2D] != gcvNULL)
     {
@@ -1574,6 +2558,9 @@ gckGALDEVICE_Stop_Threads(
     )
 {
     gctINT i;
+#if gcdMULTI_GPU
+    gctINT j;
+#endif
 
     gcmkHEADER_ARG("Device=0x%x", Device);
 
@@ -1581,15 +2568,37 @@ gckGALDEVICE_Stop_Threads(
 
     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
     {
-        /* Stop the kernel threads. */
-        if (Device->threadInitializeds[i])
+#if gcdMULTI_GPU
+        if (i == gcvCORE_MAJOR)
+        {
+            for (j = 0; j < gcdMULTI_GPU; j++)
+            {
+                /* Stop the kernel threads. */
+                if (Device->threadInitialized3D[j])
+                {
+                    Device->killThread = gcvTRUE;
+                    Device->dataReady3D[j] = gcvTRUE;
+                    wake_up_interruptible(&Device->intrWaitQueue3D[j]);
+
+                    kthread_stop(Device->threadCtxt3D[j]);
+                    Device->threadCtxt3D[j]        = gcvNULL;
+                    Device->threadInitialized3D[j] = gcvFALSE;
+                }
+            }
+        }
+        else
+#endif
         {
-            Device->killThread = gcvTRUE;
-            up(&Device->semas[i]);
+            /* Stop the kernel threads. */
+            if (Device->threadInitializeds[i])
+            {
+                Device->killThread = gcvTRUE;
+                up(&Device->semas[i]);
 
-            kthread_stop(Device->threadCtxts[i]);
-            Device->threadCtxts[i]        = gcvNULL;
-            Device->threadInitializeds[i] = gcvFALSE;
+                kthread_stop(Device->threadCtxts[i]);
+                Device->threadCtxts[i]        = gcvNULL;
+                Device->threadInitializeds[i] = gcvFALSE;
+            }
         }
     }
 
@@ -1657,10 +2666,12 @@ gckGALDEVICE_Start(
         /* Setup the ISR routine. */
         gcmkONERROR(gckGALDEVICE_Setup_ISR_VG(Device));
 
+#if gcdENABLE_VG
         /* Switch to SUSPEND power state. */
         gcmkONERROR(gckVGHARDWARE_SetPowerManagementState(
             Device->kernels[gcvCORE_VG]->vg->hardware, gcvPOWER_OFF_BROADCAST
             ));
+#endif
     }
 
     gcmkFOOTER_NO();
index c51432f47c17b6ba334935c56fccae269afe3cc1..08900158497704e79f12ecb68576abe57c1ced9d 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 #ifndef __gc_hal_kernel_device_h_
 #define __gc_hal_kernel_device_h_
 
+#include "gc_hal_kernel_debugfs.h"
+
 /******************************************************************************\
 ******************************* gckGALDEVICE Structure *******************************
 \******************************************************************************/
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-struct contiguous_mem_pool {
-       struct dma_attrs attrs;
-       dma_addr_t phys;
-       void *virt;
-       size_t size;
-};
-#endif
-
 typedef struct _gckGALDEVICE
 {
     /* Objects. */
     gckOS               os;
     gckKERNEL           kernels[gcdMAX_GPU_COUNT];
 
+    gcsPLATFORM*        platform;
+
     /* Attributes. */
     gctSIZE_T           internalSize;
     gctPHYS_ADDR        internalPhysical;
@@ -59,22 +54,43 @@ typedef struct _gckGALDEVICE
     gctSIZE_T           contiguousSize;
     gctBOOL             contiguousMapped;
     gctPOINTER          contiguousMappedUser;
+    gctBOOL             contiguousRequested;
     gctSIZE_T           systemMemorySize;
     gctUINT32           systemMemoryBaseAddress;
+#if gcdMULTI_GPU
+    gctPOINTER          registerBase3D[gcdMULTI_GPU];
+    gctSIZE_T           registerSize3D[gcdMULTI_GPU];
+#endif
     gctPOINTER          registerBases[gcdMAX_GPU_COUNT];
     gctSIZE_T           registerSizes[gcdMAX_GPU_COUNT];
     gctUINT32           baseAddress;
+    gctUINT32           physBase;
+    gctUINT32           physSize;
+    gctBOOL             mmu;
+#if gcdMULTI_GPU
+    gctUINT32           requestedRegisterMemBase3D[gcdMULTI_GPU];
+    gctSIZE_T           requestedRegisterMemSize3D[gcdMULTI_GPU];
+#endif
     gctUINT32           requestedRegisterMemBases[gcdMAX_GPU_COUNT];
     gctSIZE_T           requestedRegisterMemSizes[gcdMAX_GPU_COUNT];
     gctUINT32           requestedContiguousBase;
     gctSIZE_T           requestedContiguousSize;
 
     /* IRQ management. */
+#if gcdMULTI_GPU
+    gctINT              irqLine3D[gcdMULTI_GPU];
+    gctBOOL             isrInitialized3D[gcdMULTI_GPU];
+    gctBOOL             dataReady3D[gcdMULTI_GPU];
+#endif
     gctINT              irqLines[gcdMAX_GPU_COUNT];
     gctBOOL             isrInitializeds[gcdMAX_GPU_COUNT];
-    gctBOOL             dataReadys[gcdMAX_GPU_COUNT];
 
     /* Thread management. */
+#if gcdMULTI_GPU
+    struct task_struct  *threadCtxt3D[gcdMULTI_GPU];
+    wait_queue_head_t   intrWaitQueue3D[gcdMULTI_GPU];
+    gctBOOL             threadInitialized3D[gcdMULTI_GPU];
+#endif
     struct task_struct  *threadCtxts[gcdMAX_GPU_COUNT];
     struct semaphore    semas[gcdMAX_GPU_COUNT];
     gctBOOL             threadInitializeds[gcdMAX_GPU_COUNT];
@@ -89,27 +105,10 @@ typedef struct _gckGALDEVICE
     /* States before suspend. */
     gceCHIPPOWERSTATE   statesStored[gcdMAX_GPU_COUNT];
 
-    /*Device Debug File System Entry in Kernel*/
-   struct _gcsDebugFileSystemNode * dbgnode;
+    /* Device Debug File System Entry in kernel. */
+    struct _gcsDEBUGFS_Node * dbgNode;
 
-    /* Clock management.*/
-    struct clk         *clk_3d_core;
-    struct clk         *clk_3d_shader;
-    struct clk            *clk_3d_axi;
-    struct clk         *clk_2d_core;
-    struct clk         *clk_2d_axi;
-    struct clk         *clk_vg_axi;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-    /*Power management.*/
-    struct regulator      *gpu_regulator;
-#endif
-       /*Run time pm*/
-       struct device           *pmdev;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-       struct contiguous_mem_pool *pool;
-       struct reset_control *rstc[gcdMAX_GPU_COUNT];
-#endif
+    gcsDEBUGFS_DIR      debugfsDir;
 }
 * gckGALDEVICE;
 
@@ -123,6 +122,18 @@ typedef struct _gcsHAL_PRIVATE_DATA
 }
 gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
 
+typedef struct _gcsDEVICE_CONSTRUCT_ARGS
+{
+    gctBOOL             recovery;
+    gctUINT             stuckDump;
+    gctUINT             gpu3DMinClock;
+
+    gctBOOL             contiguousRequested;
+    gcsPLATFORM*        platform;
+    gctBOOL             mmu;
+}
+gcsDEVICE_CONSTRUCT_ARGS;
+
 gceSTATUS gckGALDEVICE_Setup_ISR(
     IN gckGALDEVICE Device
     );
@@ -164,9 +175,18 @@ gceSTATUS gckGALDEVICE_Stop(
     );
 
 gceSTATUS gckGALDEVICE_Construct(
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
+    IN gctINT IrqLine3D0,
+    IN gctUINT32 RegisterMemBase3D0,
+    IN gctSIZE_T RegisterMemSize3D0,
+    IN gctINT IrqLine3D1,
+    IN gctUINT32 RegisterMemBase3D1,
+    IN gctSIZE_T RegisterMemSize3D1,
+#else
     IN gctINT IrqLine,
     IN gctUINT32 RegisterMemBase,
     IN gctSIZE_T RegisterMemSize,
+#endif
     IN gctINT IrqLine2D,
     IN gctUINT32 RegisterMemBase2D,
     IN gctSIZE_T RegisterMemSize2D,
@@ -182,9 +202,9 @@ gceSTATUS gckGALDEVICE_Construct(
     IN gctUINT32 PhysSize,
     IN gctINT Signal,
     IN gctUINT LogFileSize,
-    IN struct device *pdev,
     IN gctINT PowerManagement,
     IN gctINT GpuProfiler,
+    IN gcsDEVICE_CONSTRUCT_ARGS * Args,
     OUT gckGALDEVICE *Device
     );
 
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_iommu.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_iommu.c
new file mode 100644 (file)
index 0000000..43202f6
--- /dev/null
@@ -0,0 +1,216 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2014 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 "gc_hal_kernel_device.h"
+
+#include <linux/iommu.h>
+#include <linux/platform_device.h>
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+typedef struct _gcsIOMMU
+{
+    struct iommu_domain * domain;
+    struct device *       device;
+}
+gcsIOMMU;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+static int
+_IOMMU_Fault_Handler(
+    struct iommu_domain * Domain,
+    struct device * Dev,
+    unsigned long DomainAddress,
+    int flags,
+    void * args
+    )
+#else
+static int
+_IOMMU_Fault_Handler(
+    struct iommu_domain * Domain,
+    struct device * Dev,
+    unsigned long DomainAddress,
+    int flags
+    )
+#endif
+{
+    return 0;
+}
+
+static int
+_FlatMapping(
+    IN gckIOMMU Iommu
+    )
+{
+    gceSTATUS status;
+    gctUINT32 physical;
+
+    for (physical = 0; physical < 0x80000000; physical += PAGE_SIZE)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS,
+            "Map %x => %x bytes = %d",
+            physical, physical, PAGE_SIZE
+            );
+
+        gcmkONERROR(gckIOMMU_Map(Iommu, physical, physical, PAGE_SIZE));
+    }
+
+    return gcvSTATUS_OK;
+
+OnError:
+    return status;
+}
+
+void
+gckIOMMU_Destory(
+    IN gckOS Os,
+    IN gckIOMMU Iommu
+    )
+{
+    gcmkHEADER();
+
+    if (Iommu->domain && Iommu->device)
+    {
+        iommu_attach_device(Iommu->domain, Iommu->device);
+    }
+
+    if (Iommu->domain)
+    {
+        iommu_domain_free(Iommu->domain);
+    }
+
+    if (Iommu)
+    {
+        gcmkOS_SAFE_FREE(Os, Iommu);
+    }
+
+    gcmkFOOTER_NO();
+}
+
+gceSTATUS
+gckIOMMU_Construct(
+    IN gckOS Os,
+    OUT gckIOMMU * Iommu
+    )
+{
+    gceSTATUS status;
+    gckIOMMU iommu = gcvNULL;
+    struct device *dev;
+    int ret;
+
+    gcmkHEADER();
+
+    dev = &Os->device->platform->device->dev;
+
+    gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsIOMMU), (gctPOINTER *)&iommu));
+
+    gckOS_ZeroMemory(iommu, gcmSIZEOF(gcsIOMMU));
+
+    iommu->domain = iommu_domain_alloc(&platform_bus_type);
+
+    if (!iommu->domain)
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "iommu_domain_alloc() fail");
+
+        gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+    }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+    iommu_set_fault_handler(iommu->domain, _IOMMU_Fault_Handler, dev);
+#else
+    iommu_set_fault_handler(iommu->domain, _IOMMU_Fault_Handler);
+#endif
+
+    ret = iommu_attach_device(iommu->domain, dev);
+
+    if (ret)
+    {
+        gcmkTRACE_ZONE(
+            gcvLEVEL_INFO, gcvZONE_OS, "iommu_attach_device() fail %d", ret);
+
+        gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+    }
+
+    iommu->device = dev;
+
+    _FlatMapping(iommu);
+
+    *Iommu = iommu;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+
+    gckIOMMU_Destory(Os, iommu);
+
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckIOMMU_Map(
+    IN gckIOMMU Iommu,
+    IN gctUINT32 DomainAddress,
+    IN gctUINT32 Physical,
+    IN gctUINT32 Bytes
+    )
+{
+    gceSTATUS status;
+    int ret;
+
+    gcmkHEADER_ARG("DomainAddress=%#X, Physical=%#X, Bytes=%d",
+                   DomainAddress, Physical, Bytes);
+
+    ret = iommu_map(Iommu->domain, DomainAddress, Physical, Bytes, 0);
+
+    if (ret)
+    {
+        gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+
+    gcmkFOOTER();
+    return status;
+
+}
+
+gceSTATUS
+gckIOMMU_Unmap(
+    IN gckIOMMU Iommu,
+    IN gctUINT32 DomainAddress,
+    IN gctUINT32 Bytes
+    )
+{
+    gcmkHEADER();
+
+    iommu_unmap(Iommu->domain, DomainAddress, Bytes);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
index de82c12f861724594df02c2640d4e653bbb13f97..344f05827a866cf09be70db774eb67e0c64e6a21 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -256,13 +256,15 @@ gckKERNEL_MapVideoMemoryEx(
     OUT gctPOINTER * Logical
     )
 {
-    gckGALDEVICE device;
-    PLINUX_MDL mdl;
-    PLINUX_MDL_MAP mdlMap;
-    gcePOOL pool;
-    gctUINT32 offset, base;
+    gckGALDEVICE device   = gcvNULL;
+    PLINUX_MDL mdl        = gcvNULL;
+    PLINUX_MDL_MAP mdlMap = gcvNULL;
+    gcePOOL pool          = gcvPOOL_UNKNOWN;
+    gctUINT32 offset      = 0;
+    gctUINT32 base        = 0;
     gceSTATUS status;
-    gctPOINTER logical;
+    gctPOINTER logical    = gcvNULL;
+    gctUINT32 baseAddress;
 
     gcmkHEADER_ARG("Kernel=%p InUserSpace=%d Address=%08x",
                    Kernel, InUserSpace, Address);
@@ -332,16 +334,23 @@ gckKERNEL_MapVideoMemoryEx(
         else
 #endif
         {
-            gctUINT32 baseAddress = 0;
+            gctUINT32 systemBaseAddress = 0;
 
             if (Kernel->hardware->mmuVersion == 0)
             {
-                gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &baseAddress));
+                gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &systemBaseAddress));
             }
 
+            gcmkVERIFY_OK(
+                gckOS_CPUPhysicalToGPUPhysical(
+                    Kernel->os,
+                    device->contiguousVidMem->baseAddress - systemBaseAddress,
+                    &baseAddress
+                    ));
+
             gcmkVERIFY_OK(
                 gckHARDWARE_SplitMemory(Kernel->hardware,
-                                        device->contiguousVidMem->baseAddress - baseAddress,
+                                        baseAddress,
                                         &pool,
                                         &base));
         }
@@ -421,6 +430,9 @@ gckKERNEL_MapVideoMemory(
 gceSTATUS
 gckKERNEL_Notify(
     IN gckKERNEL Kernel,
+#if gcdMULTI_GPU
+    IN gctUINT CoreId,
+#endif
     IN gceNOTIFY Notification,
     IN gctBOOL Data
     )
@@ -441,7 +453,11 @@ gckKERNEL_Notify(
 #if COMMAND_PROCESSOR_VERSION > 1
         status = gckINTERRUPT_Notify(Kernel->interrupt, Data);
 #else
-        status = gckHARDWARE_Interrupt(Kernel->hardware, Data);
+        status = gckHARDWARE_Interrupt(Kernel->hardware,
+#if gcdMULTI_GPU
+                                       CoreId,
+#endif
+                                       Data);
 #endif
         break;
 
index 3c148f6e33238e7d23b24d3577568532a43ef3d7..02847e90fad627c053567331ea817100241fd408 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -37,6 +37,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/kthread.h>
 
+#include <linux/idr.h>
+
 #ifdef MODVERSIONS
 #  include <linux/modversions.h>
 #endif
 
 #if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
 #include <linux/clk.h>
-#include <linux/regulator/consumer.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_platform.h"
 #include "gc_hal_kernel_device.h"
 #include "gc_hal_kernel_os.h"
 #include "gc_hal_kernel_debugfs.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_pid(x)
 #endif
 
-#define _WIDE(string)                          L##string
-#define WIDE(string)                           _WIDE(string)
+#define _WIDE(string)                L##string
+#define WIDE(string)                _WIDE(string)
 
-#define countof(a)                                     (sizeof(a) / sizeof(a[0]))
+#define countof(a)                    (sizeof(a) / sizeof(a[0]))
 
-#define DRV_NAME                               "galcore"
+#ifndef DEVICE_NAME
+#ifdef CONFIG_DOVE_GPU
+#   define DEVICE_NAME              "dove_gpu"
+#else
+#   define DEVICE_NAME              "galcore"
+#endif
+#endif
 
-#define GetPageCount(size, offset)     ((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
+#define GetPageCount(size, offset)     ((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION (3,7,0)
 #define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP)
 #define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED)
 #endif
 
+/* Protection bit when mapping memroy to user sapce */
+#define gcmkPAGED_MEMROY_PROT(x)    pgprot_writecombine(x)
+
+#if gcdNONPAGED_MEMORY_BUFFERABLE
+#define gcmkIOREMAP                 ioremap_wc
+#define gcmkNONPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
+#elif !gcdNONPAGED_MEMORY_CACHEABLE
+#define gcmkIOREMAP                 ioremap_nocache
+#define gcmkNONPAGED_MEMROY_PROT(x) pgprot_noncached(x)
+#endif
+
+#define gcdSUPPRESS_OOM_MESSAGE 1
+
+#if gcdSUPPRESS_OOM_MESSAGE
+#define gcdNOWARN __GFP_NOWARN
+#else
+#define gcdNOWARN 0
+#endif
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+typedef struct _gcsIOMMU * gckIOMMU;
+
+typedef struct _gcsUSER_MAPPING * gcsUSER_MAPPING_PTR;
+typedef struct _gcsUSER_MAPPING
+{
+    /* Pointer to next mapping structure. */
+    gcsUSER_MAPPING_PTR         next;
+
+    /* Physical address of this mapping. */
+    gctUINT32                   physical;
+
+    /* Logical address of this mapping. */
+    gctPOINTER                  logical;
+
+    /* Number of bytes of this mapping. */
+    gctSIZE_T                   bytes;
+
+    /* Starting address of this mapping. */
+    gctINT8_PTR                 start;
+
+    /* Ending address of this mapping. */
+    gctINT8_PTR                 end;
+}
+gcsUSER_MAPPING;
+
+typedef struct _gcsINTEGER_DB * gcsINTEGER_DB_PTR;
+typedef struct _gcsINTEGER_DB
+{
+    struct idr                  idr;
+    spinlock_t                  lock;
+    gctINT                      curr;
+}
+gcsINTEGER_DB;
+
+struct _gckOS
+{
+    /* Object. */
+    gcsOBJECT                   object;
+
+    /* Pointer to device */
+    gckGALDEVICE                device;
+
+    /* Memory management */
+    gctPOINTER                  memoryLock;
+    gctPOINTER                  memoryMapLock;
+
+    struct _LINUX_MDL           *mdlHead;
+    struct _LINUX_MDL           *mdlTail;
+
+    /* Kernel process ID. */
+    gctUINT32                   kernelProcessID;
+
+    /* Signal management. */
+
+    /* Lock. */
+    gctPOINTER                  signalMutex;
+
+    /* signal id database. */
+    gcsINTEGER_DB               signalDB;
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+    /* Lock. */
+    gctPOINTER                  syncPointMutex;
+
+    /* sync point id database. */
+    gcsINTEGER_DB               syncPointDB;
+#endif
+
+    gcsUSER_MAPPING_PTR         userMap;
+    gctPOINTER                  debugLock;
+
+    /* workqueue for os timer. */
+    struct workqueue_struct *   workqueue;
+
+    /* Allocate extra page to avoid cache overflow */
+    struct page* paddingPage;
+
+    /* Detect unfreed allocation. */
+    atomic_t                    allocateCount;
+
+    struct list_head            allocatorList;
+
+    gcsDEBUGFS_DIR              allocatorDebugfsDir;
+
+    /* Lock for register access check. */
+    struct mutex                registerAccessLocks[gcdMAX_GPU_COUNT];
+
+    /* External power states. */
+    gctBOOL                     powerStates[gcdMAX_GPU_COUNT];
+
+    /* External clock states. */
+    gctBOOL                     clockStates[gcdMAX_GPU_COUNT];
+
+    /* IOMMU. */
+    gckIOMMU                    iommu;
+};
+
+typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
+typedef struct _gcsSIGNAL
+{
+    /* Kernel sync primitive. */
+    struct completion obj;
+
+    /* Manual reset flag. */
+    gctBOOL manualReset;
+
+    /* The reference counter. */
+    atomic_t ref;
+
+    /* The owner of the signal. */
+    gctHANDLE process;
+
+    gckHARDWARE hardware;
+
+    /* ID. */
+    gctUINT32 id;
+}
+gcsSIGNAL;
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+typedef struct _gcsSYNC_POINT * gcsSYNC_POINT_PTR;
+typedef struct _gcsSYNC_POINT
+{
+    /* The reference counter. */
+    atomic_t ref;
+
+    /* State. */
+    atomic_t state;
+
+    /* timeline. */
+    struct sync_timeline * timeline;
+
+    /* ID. */
+    gctUINT32 id;
+}
+gcsSYNC_POINT;
+#endif
+
+typedef struct _gcsPageInfo * gcsPageInfo_PTR;
+typedef struct _gcsPageInfo
+{
+    struct page **pages;
+    gctUINT32_PTR pageTable;
+    gctUINT32   extraPage;
+    gctUINT32 address;
+#if gcdPROCESS_ADDRESS_SPACE
+    gckMMU mmu;
+#endif
+}
+gcsPageInfo;
+
+typedef struct _gcsOSTIMER * gcsOSTIMER_PTR;
+typedef struct _gcsOSTIMER
+{
+    struct delayed_work     work;
+    gctTIMERFUNCTION        function;
+    gctPOINTER              data;
+} gcsOSTIMER;
+
+gceSTATUS
+gckOS_ImportAllocators(
+    gckOS Os
+    );
+
+gceSTATUS
+gckOS_FreeAllocators(
+    gckOS Os
+    );
+
+gceSTATUS
+_HandleOuterCache(
+    IN gckOS Os,
+    IN gctUINT32 Physical,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes,
+    IN gceCACHEOPERATION Type
+    );
+
+gceSTATUS
+_ConvertLogical2Physical(
+    IN gckOS Os,
+    IN gctPOINTER Logical,
+    IN gctUINT32 ProcessID,
+    IN PLINUX_MDL Mdl,
+    OUT gctUINT32_PTR Physical
+    );
+
+gctSTRING
+_CreateKernelVirtualMapping(
+    IN PLINUX_MDL Mdl
+    );
+
+void
+_DestoryKernelVirtualMapping(
+    IN gctSTRING Addr
+    );
+
+void
+_UnmapUserLogical(
+    IN gctPOINTER Logical,
+    IN gctUINT32  Size
+    );
+
 static inline gctINT
-GetOrder(
-       IN gctINT numPages
-       )
+_GetProcessID(
+    void
+    )
 {
-    gctINT order = 0;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+    return task_tgid_vnr(current);
+#else
+    return current->tgid;
+#endif
+}
 
-       while ((1 << order) <  numPages) order++;
+static inline struct page *
+_NonContiguousToPage(
+    IN struct page ** Pages,
+    IN gctUINT32 Index
+    )
+{
+    gcmkASSERT(Pages != gcvNULL);
+    return Pages[Index];
+}
 
-       return order;
+static inline unsigned long
+_NonContiguousToPfn(
+    IN struct page ** Pages,
+    IN gctUINT32 Index
+    )
+{
+    gcmkASSERT(Pages != gcvNULL);
+    return page_to_pfn(_NonContiguousToPage(Pages, Index));
 }
 
+static inline unsigned long
+_NonContiguousToPhys(
+    IN struct page ** Pages,
+    IN gctUINT32 Index
+    )
+{
+    gcmkASSERT(Pages != gcvNULL);
+    return page_to_phys(_NonContiguousToPage(Pages, Index));
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+static inline int
+is_vmalloc_addr(
+    void *Addr
+    )
+{
+    unsigned long addr = (unsigned long)Addr;
+
+    return addr >= VMALLOC_START && addr < VMALLOC_END;
+}
+#endif
+
+#ifdef CONFIG_IOMMU_SUPPORT
+void
+gckIOMMU_Destory(
+    IN gckOS Os,
+    IN gckIOMMU Iommu
+    );
+
+gceSTATUS
+gckIOMMU_Construct(
+    IN gckOS Os,
+    OUT gckIOMMU * Iommu
+    );
+
+gceSTATUS
+gckIOMMU_Map(
+    IN gckIOMMU Iommu,
+    IN gctUINT32 DomainAddress,
+    IN gctUINT32 Physical,
+    IN gctUINT32 Bytes
+    );
+
+gceSTATUS
+gckIOMMU_Unmap(
+    IN gckIOMMU Iommu,
+    IN gctUINT32 DomainAddress,
+    IN gctUINT32 Bytes
+    );
+#endif
+
 #endif /* __gc_hal_kernel_linux_h_ */
index 992aeff43b8c838a6b436d152311a89223a212b9..326ec28418830f9366857258893f009e2123b912 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
index 9a55c90015cf47bd955d94ff092dd05583d632e3..2dbd73d0abe4b1c0d49dff79b726e70cef52414c 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 
 #include <linux/pagemap.h>
 #include <linux/seq_file.h>
-#include <linux/mm.h>
 #include <linux/mman.h>
-#include <linux/sched.h>
 #include <asm/atomic.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
-#include <linux/idr.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-#include <mach/hardware.h>
-#endif
 #include <linux/workqueue.h>
-#include <linux/idr.h>
+#include <linux/irqflags.h>
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
 #include <linux/math64.h>
 #endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-#include <linux/reset.h>
-static inline void imx_gpc_power_up_pu(bool flag) {}
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-#include <mach/common.h>
-#endif
 #include <linux/delay.h>
-#include <linux/pm_runtime.h>
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+#include <linux/anon_inodes.h>
+#endif
 
 #if gcdANDROID_NATIVE_FENCE_SYNC
 #include <linux/file.h>
 #include "gc_hal_kernel_sync.h"
 #endif
 
-
 #define _GC_OBJ_ZONE    gcvZONE_OS
 
-/*******************************************************************************
-***** Version Signature *******************************************************/
-
-#ifdef ANDROID
-const char * _PLATFORM = "\n\0$PLATFORM$Android$\n";
-#else
-const char * _PLATFORM = "\n\0$PLATFORM$Linux$\n";
-#endif
-
-#define USER_SIGNAL_TABLE_LEN_INIT  64
-#define gcdSUPPRESS_OOM_MESSAGE 1
+#include "gc_hal_kernel_allocator.h"
 
 #define MEMORY_LOCK(os) \
     gcmkVERIFY_OK(gckOS_AcquireMutex( \
@@ -86,206 +65,10 @@ const char * _PLATFORM = "\n\0$PLATFORM$Linux$\n";
 #define MEMORY_MAP_UNLOCK(os) \
     gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
 
-/* Protection bit when mapping memroy to user sapce */
-#define gcmkPAGED_MEMROY_PROT(x)    pgprot_writecombine(x)
-
-#if gcdNONPAGED_MEMORY_BUFFERABLE
-#define gcmkIOREMAP                 ioremap_wc
-#define gcmkNONPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
-#elif !gcdNONPAGED_MEMORY_CACHEABLE
-#define gcmkIOREMAP                 ioremap_nocache
-#define gcmkNONPAGED_MEMROY_PROT(x) pgprot_noncached(x)
-#endif
-
-#if gcdSUPPRESS_OOM_MESSAGE
-#define gcdNOWARN __GFP_NOWARN
-#else
-#define gcdNOWARN 0
-#endif
-
-#define gcdINFINITE_TIMEOUT     (60 * 1000)
-#define gcdDETECT_TIMEOUT       0
-#define gcdDETECT_DMA_ADDRESS   1
-#define gcdDETECT_DMA_STATE     1
-
-#define gcdUSE_NON_PAGED_MEMORY_CACHE 10
-
-/******************************************************************************\
-********************************** Structures **********************************
-\******************************************************************************/
-#if gcdUSE_NON_PAGED_MEMORY_CACHE
-typedef struct _gcsNonPagedMemoryCache
-{
-#ifndef NO_DMA_COHERENT
-    gctINT                           size;
-    gctSTRING                        addr;
-    dma_addr_t                       dmaHandle;
-#else
-    long                             order;
-    struct page *                    page;
-#endif
-
-    struct _gcsNonPagedMemoryCache * prev;
-    struct _gcsNonPagedMemoryCache * next;
-}
-gcsNonPagedMemoryCache;
-#endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
-
-typedef struct _gcsUSER_MAPPING * gcsUSER_MAPPING_PTR;
-typedef struct _gcsUSER_MAPPING
-{
-    /* Pointer to next mapping structure. */
-    gcsUSER_MAPPING_PTR         next;
-
-    /* Physical address of this mapping. */
-    gctUINT32                   physical;
-
-    /* Logical address of this mapping. */
-    gctPOINTER                  logical;
-
-    /* Number of bytes of this mapping. */
-    gctSIZE_T                   bytes;
-
-    /* Starting address of this mapping. */
-    gctINT8_PTR                 start;
-
-    /* Ending address of this mapping. */
-    gctINT8_PTR                 end;
-}
-gcsUSER_MAPPING;
-
-typedef struct _gcsINTEGER_DB * gcsINTEGER_DB_PTR;
-typedef struct _gcsINTEGER_DB
-{
-    struct idr                  idr;
-    spinlock_t                  lock;
-    gctINT                      curr;
-}
-gcsINTEGER_DB;
-
-struct _gckOS
-{
-    /* Object. */
-    gcsOBJECT                   object;
-
-    /* Heap. */
-    gckHEAP                     heap;
-
-    /* Pointer to device */
-    gckGALDEVICE                device;
-
-    /* Memory management */
-    gctPOINTER                  memoryLock;
-    gctPOINTER                  memoryMapLock;
-
-    struct _LINUX_MDL           *mdlHead;
-    struct _LINUX_MDL           *mdlTail;
-
-    /* Kernel process ID. */
-    gctUINT32                   kernelProcessID;
-
-    /* Signal management. */
-
-    /* Lock. */
-    gctPOINTER                  signalMutex;
-
-    /* signal id database. */
-    gcsINTEGER_DB               signalDB;
-
-#if gcdANDROID_NATIVE_FENCE_SYNC
-    /* Lock. */
-    gctPOINTER                  syncPointMutex;
-
-    /* sync point id database. */
-    gcsINTEGER_DB               syncPointDB;
-#endif
-
-    gcsUSER_MAPPING_PTR         userMap;
-    gctPOINTER                  debugLock;
-
-#if gcdUSE_NON_PAGED_MEMORY_CACHE
-    gctUINT                      cacheSize;
-    gcsNonPagedMemoryCache *     cacheHead;
-    gcsNonPagedMemoryCache *     cacheTail;
-#endif
-
-    /* workqueue for os timer. */
-    struct workqueue_struct *   workqueue;
-};
-
-typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
-typedef struct _gcsSIGNAL
-{
-    /* Kernel sync primitive. */
-    struct completion obj;
-
-    /* Manual reset flag. */
-    gctBOOL manualReset;
-
-    /* The reference counter. */
-    atomic_t ref;
-
-    /* The owner of the signal. */
-    gctHANDLE process;
-
-    gckHARDWARE hardware;
-
-    /* ID. */
-    gctUINT32 id;
-}
-gcsSIGNAL;
-
-#if gcdANDROID_NATIVE_FENCE_SYNC
-typedef struct _gcsSYNC_POINT * gcsSYNC_POINT_PTR;
-typedef struct _gcsSYNC_POINT
-{
-    /* The reference counter. */
-    atomic_t ref;
-
-    /* State. */
-    atomic_t state;
-
-    /* timeline. */
-    struct sync_timeline * timeline;
-
-    /* ID. */
-    gctUINT32 id;
-}
-gcsSYNC_POINT;
-#endif
-
-typedef struct _gcsPageInfo * gcsPageInfo_PTR;
-typedef struct _gcsPageInfo
-{
-    struct page **pages;
-    gctUINT32_PTR pageTable;
-}
-gcsPageInfo;
-
-typedef struct _gcsOSTIMER * gcsOSTIMER_PTR;
-typedef struct _gcsOSTIMER
-{
-    struct delayed_work     work;
-    gctTIMERFUNCTION        function;
-    gctPOINTER              data;
-} gcsOSTIMER;
 
 /******************************************************************************\
 ******************************* Private Functions ******************************
 \******************************************************************************/
-
-static gctINT
-_GetProcessID(
-    void
-    )
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
-    return task_tgid_vnr(current);
-#else
-    return current->tgid;
-#endif
-}
-
 static gctINT
 _GetThreadID(
     void
@@ -300,24 +83,14 @@ _GetThreadID(
 
 static PLINUX_MDL
 _CreateMdl(
-    IN gctINT ProcessID
+    void
     )
 {
     PLINUX_MDL  mdl;
 
-    gcmkHEADER_ARG("ProcessID=%d", ProcessID);
+    gcmkHEADER();
 
     mdl = (PLINUX_MDL)kzalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL | gcdNOWARN);
-    if (mdl == gcvNULL)
-    {
-        gcmkFOOTER_NO();
-        return gcvNULL;
-    }
-
-    mdl->pid    = ProcessID;
-    mdl->maps   = gcvNULL;
-    mdl->prev   = gcvNULL;
-    mdl->next   = gcvNULL;
 
     gcmkFOOTER_ARG("0x%X", mdl);
     return mdl;
@@ -456,346 +229,6 @@ FindMdlMap(
     return gcvNULL;
 }
 
-void
-OnProcessExit(
-    IN gckOS Os,
-    IN gckKERNEL Kernel
-    )
-{
-}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
-static inline int
-is_vmalloc_addr(
-    void *Addr
-    )
-{
-    unsigned long addr = (unsigned long)Addr;
-
-    return addr >= VMALLOC_START && addr < VMALLOC_END;
-}
-#endif
-
-static void
-_NonContiguousFree(
-    IN struct page ** Pages,
-    IN gctUINT32 NumPages
-    )
-{
-    gctINT i;
-
-    gcmkHEADER_ARG("Pages=0x%X, NumPages=%d", Pages, NumPages);
-
-    gcmkASSERT(Pages != gcvNULL);
-
-    for (i = 0; i < NumPages; i++)
-    {
-        __free_page(Pages[i]);
-    }
-
-    if (is_vmalloc_addr(Pages))
-    {
-        vfree(Pages);
-    }
-    else
-    {
-        kfree(Pages);
-    }
-
-    gcmkFOOTER_NO();
-}
-
-static struct page **
-_NonContiguousAlloc(
-    IN gctUINT32 NumPages
-    )
-{
-    struct page ** pages;
-    struct page *p;
-    gctINT i, size;
-
-    gcmkHEADER_ARG("NumPages=%lu", NumPages);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
-    if (NumPages > totalram_pages)
-#else
-    if (NumPages > num_physpages)
-#endif
-    {
-        gcmkFOOTER_NO();
-        return gcvNULL;
-    }
-
-    size = NumPages * sizeof(struct page *);
-
-    pages = kmalloc(size, GFP_KERNEL | gcdNOWARN);
-
-    if (!pages)
-    {
-        pages = vmalloc(size);
-
-        if (!pages)
-        {
-            gcmkFOOTER_NO();
-            return gcvNULL;
-        }
-    }
-
-    for (i = 0; i < NumPages; i++)
-    {
-        p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
-
-        if (!p)
-        {
-            _NonContiguousFree(pages, i);
-            gcmkFOOTER_NO();
-            return gcvNULL;
-        }
-
-        pages[i] = p;
-    }
-
-    gcmkFOOTER_ARG("pages=0x%X", pages);
-    return pages;
-}
-
-static inline struct page *
-_NonContiguousToPage(
-    IN struct page ** Pages,
-    IN gctUINT32 Index
-    )
-{
-    gcmkASSERT(Pages != gcvNULL);
-    return Pages[Index];
-}
-
-static inline unsigned long
-_NonContiguousToPfn(
-    IN struct page ** Pages,
-    IN gctUINT32 Index
-    )
-{
-    gcmkASSERT(Pages != gcvNULL);
-    return page_to_pfn(_NonContiguousToPage(Pages, Index));
-}
-
-static inline unsigned long
-_NonContiguousToPhys(
-    IN struct page ** Pages,
-    IN gctUINT32 Index
-    )
-{
-    gcmkASSERT(Pages != gcvNULL);
-    return page_to_phys(_NonContiguousToPage(Pages, Index));
-}
-
-
-#if gcdUSE_NON_PAGED_MEMORY_CACHE
-
-static gctBOOL
-_AddNonPagedMemoryCache(
-    gckOS Os,
-#ifndef NO_DMA_COHERENT
-    gctINT Size,
-    gctSTRING Addr,
-    dma_addr_t DmaHandle
-#else
-    long Order,
-    struct page * Page
-#endif
-    )
-{
-    gcsNonPagedMemoryCache *cache;
-
-    if (Os->cacheSize >= gcdUSE_NON_PAGED_MEMORY_CACHE)
-    {
-        return gcvFALSE;
-    }
-
-    /* Allocate the cache record */
-    cache = (gcsNonPagedMemoryCache *)kmalloc(sizeof(gcsNonPagedMemoryCache), GFP_ATOMIC);
-
-    if (cache == gcvNULL) return gcvFALSE;
-
-#ifndef NO_DMA_COHERENT
-    cache->size  = Size;
-    cache->addr  = Addr;
-    cache->dmaHandle = DmaHandle;
-#else
-    cache->order = Order;
-    cache->page  = Page;
-#endif
-
-    /* Add to list */
-    if (Os->cacheHead == gcvNULL)
-    {
-        cache->prev   = gcvNULL;
-        cache->next   = gcvNULL;
-        Os->cacheHead =
-        Os->cacheTail = cache;
-    }
-    else
-    {
-        /* Add to the tail. */
-        cache->prev         = Os->cacheTail;
-        cache->next         = gcvNULL;
-        Os->cacheTail->next = cache;
-        Os->cacheTail       = cache;
-    }
-
-    Os->cacheSize++;
-
-    return gcvTRUE;
-}
-
-#ifndef NO_DMA_COHERENT
-static gctSTRING
-_GetNonPagedMemoryCache(
-    gckOS Os,
-    gctINT Size,
-    dma_addr_t * DmaHandle
-    )
-#else
-static struct page *
-_GetNonPagedMemoryCache(
-    gckOS Os,
-    long Order
-    )
-#endif
-{
-    gcsNonPagedMemoryCache *cache;
-#ifndef NO_DMA_COHERENT
-    gctSTRING addr;
-#else
-    struct page * page;
-#endif
-
-    if (Os->cacheHead == gcvNULL) return gcvNULL;
-
-    /* Find the right cache */
-    cache = Os->cacheHead;
-
-    while (cache != gcvNULL)
-    {
-#ifndef NO_DMA_COHERENT
-        if (cache->size == Size) break;
-#else
-        if (cache->order == Order) break;
-#endif
-
-        cache = cache->next;
-    }
-
-    if (cache == gcvNULL) return gcvNULL;
-
-    /* Remove the cache from list */
-    if (cache == Os->cacheHead)
-    {
-        Os->cacheHead = cache->next;
-
-        if (Os->cacheHead == gcvNULL)
-        {
-            Os->cacheTail = gcvNULL;
-        }
-    }
-    else
-    {
-        cache->prev->next = cache->next;
-
-        if (cache == Os->cacheTail)
-        {
-            Os->cacheTail = cache->prev;
-        }
-        else
-        {
-            cache->next->prev = cache->prev;
-        }
-    }
-
-    /* Destroy cache */
-#ifndef NO_DMA_COHERENT
-    addr       = cache->addr;
-    *DmaHandle = cache->dmaHandle;
-#else
-    page       = cache->page;
-#endif
-
-    kfree(cache);
-
-    Os->cacheSize--;
-
-#ifndef NO_DMA_COHERENT
-    return addr;
-#else
-    return page;
-#endif
-}
-
-static void
-_FreeAllNonPagedMemoryCache(
-    gckOS Os
-    )
-{
-    gcsNonPagedMemoryCache *cache, *nextCache;
-
-    MEMORY_LOCK(Os);
-
-    cache = Os->cacheHead;
-
-    while (cache != gcvNULL)
-    {
-        if (cache != Os->cacheTail)
-        {
-            nextCache = cache->next;
-        }
-        else
-        {
-            nextCache = gcvNULL;
-        }
-
-        /* Remove the cache from list */
-        if (cache == Os->cacheHead)
-        {
-            Os->cacheHead = cache->next;
-
-            if (Os->cacheHead == gcvNULL)
-            {
-                Os->cacheTail = gcvNULL;
-            }
-        }
-        else
-        {
-            cache->prev->next = cache->next;
-
-            if (cache == Os->cacheTail)
-            {
-                Os->cacheTail = cache->prev;
-            }
-            else
-            {
-                cache->next->prev = cache->prev;
-            }
-        }
-
-#ifndef NO_DMA_COHERENT
-    dma_free_coherent(gcvNULL,
-                    cache->size,
-                    cache->addr,
-                    cache->dmaHandle);
-#else
-    free_pages((unsigned long)page_address(cache->page), cache->order);
-#endif
-
-        kfree(cache);
-
-        cache = nextCache;
-    }
-
-    MEMORY_UNLOCK(Os);
-}
-
-#endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
-
 /*******************************************************************************
 ** Integer Id Management.
 */
@@ -815,11 +248,15 @@ _AllocateIntegerId(
     spin_lock(&Database->lock);
 
     next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
+
     result = idr_alloc(&Database->idr, KernelPointer, next, 0, GFP_ATOMIC);
 
-    if (!result)
+    /* ID allocated should not be 0. */
+    gcmkASSERT(result != 0);
+
+    if (result > 0)
     {
-        Database->curr = *Id;
+        Database->curr = *Id = result;
     }
 
     spin_unlock(&Database->lock);
@@ -830,8 +267,6 @@ _AllocateIntegerId(
     {
         return gcvSTATUS_OUT_OF_RESOURCES;
     }
-
-    *Id = result;
 #else
 again:
     if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0)
@@ -843,7 +278,7 @@ again:
 
     next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
 
-    /* Try to get a id greater than current id. */
+    /* Try to get a id greater than 0. */
     result = idr_get_new_above(&Database->idr, KernelPointer, next, Id);
 
     if (!result)
@@ -913,93 +348,232 @@ _DestroyIntegerId(
     return gcvSTATUS_OK;
 }
 
-static void
-_UnmapUserLogical(
-    IN gctINT Pid,
+gceSTATUS
+_QueryProcessPageTable(
     IN gctPOINTER Logical,
-    IN gctUINT32  Size
-)
+    OUT gctUINT32 * Address
+    )
 {
-    if (unlikely(current->mm == gcvNULL))
+    spinlock_t *lock;
+    gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
+    pgd_t *pgd;
+    pud_t *pud;
+    pmd_t *pmd;
+    pte_t *pte;
+
+    if (!current->mm)
     {
-        /* Do nothing if process is exiting. */
-        return;
+        return gcvSTATUS_NOT_FOUND;
     }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-    if (vm_munmap((unsigned long)Logical, Size) < 0)
+    pgd = pgd_offset(current->mm, logical);
+    if (pgd_none(*pgd) || pgd_bad(*pgd))
     {
-        gcmkTRACE_ZONE(
-                gcvLEVEL_WARNING, gcvZONE_OS,
-                "%s(%d): vm_munmap failed",
-                __FUNCTION__, __LINE__
-                );
+        return gcvSTATUS_NOT_FOUND;
     }
-#else
-    down_write(&current->mm->mmap_sem);
-    if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
+
+    pud = pud_offset(pgd, logical);
+    if (pud_none(*pud) || pud_bad(*pud))
     {
-        gcmkTRACE_ZONE(
-                gcvLEVEL_WARNING, gcvZONE_OS,
-                "%s(%d): do_munmap failed",
-                __FUNCTION__, __LINE__
-                );
+        return gcvSTATUS_NOT_FOUND;
     }
-    up_write(&current->mm->mmap_sem);
-#endif
+
+    pmd = pmd_offset(pud, logical);
+    if (pmd_none(*pmd) || pmd_bad(*pmd))
+    {
+        return gcvSTATUS_NOT_FOUND;
+    }
+
+    pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
+    if (!pte)
+    {
+        return gcvSTATUS_NOT_FOUND;
+    }
+
+    if (!pte_present(*pte))
+    {
+        pte_unmap_unlock(pte, lock);
+        return gcvSTATUS_NOT_FOUND;
+    }
+
+    *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
+    pte_unmap_unlock(pte, lock);
+
+    return gcvSTATUS_OK;
+}
+
+#if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
+static inline gceSTATUS
+outer_func(
+    gceCACHEOPERATION Type,
+    unsigned long Start,
+    unsigned long End
+    )
+{
+    switch (Type)
+    {
+        case gcvCACHE_CLEAN:
+            outer_clean_range(Start, End);
+            break;
+        case gcvCACHE_INVALIDATE:
+            outer_inv_range(Start, End);
+            break;
+        case gcvCACHE_FLUSH:
+            outer_flush_range(Start, End);
+            break;
+        default:
+            return gcvSTATUS_INVALID_ARGUMENT;
+            break;
+    }
+    return gcvSTATUS_OK;
+}
+
+#if gcdENABLE_OUTER_CACHE_PATCH
+/*******************************************************************************
+**  _HandleOuterCache
+**
+**  Handle the outer cache for the specified addresses.
+**
+**  ARGUMENTS:
+**
+**      gckOS Os
+**          Pointer to gckOS object.
+**
+**      gctPOINTER Physical
+**          Physical address to flush.
+**
+**      gctPOINTER Logical
+**          Logical address to flush.
+**
+**      gctSIZE_T Bytes
+**          Size of the address range in bytes to flush.
+**
+**      gceOUTERCACHE_OPERATION Type
+**          Operation need to be execute.
+*/
+gceSTATUS
+_HandleOuterCache(
+    IN gckOS Os,
+    IN gctUINT32 Physical,
+    IN gctPOINTER Logical,
+    IN gctSIZE_T Bytes,
+    IN gceCACHEOPERATION Type
+    )
+{
+    gceSTATUS status;
+    unsigned long paddr;
+    gctPOINTER vaddr;
+    gctUINT32 offset, bytes, left;
+
+    gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu",
+                   Os, Logical, Bytes);
+
+    if (Physical != gcvINVALID_ADDRESS)
+    {
+        /* Non paged memory or gcvPOOL_USER surface */
+        paddr = (unsigned long) Physical;
+        gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
+    }
+    else
+    {
+        /* Non contiguous virtual memory */
+        vaddr = Logical;
+        left = Bytes;
+
+        while (left)
+        {
+            /* Handle (part of) current page. */
+            offset = (gctUINTPTR_T)vaddr & ~PAGE_MASK;
+
+            bytes = gcmMIN(left, PAGE_SIZE - offset);
+
+            gcmkONERROR(_QueryProcessPageTable(vaddr, (gctUINT32*)&paddr));
+            gcmkONERROR(outer_func(Type, paddr, paddr + bytes));
+
+            vaddr = (gctUINT8_PTR)vaddr + bytes;
+            left -= bytes;
+        }
+    }
+
+    mb();
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
 }
+#endif
+#endif
 
-gceSTATUS
-_QueryProcessPageTable(
-    IN gctPOINTER Logical,
-    OUT gctUINT32 * Address
+gctBOOL
+_AllowAccess(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctUINT32 Address
     )
 {
-    spinlock_t *lock;
-    gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
-    pgd_t *pgd;
-    pud_t *pud;
-    pmd_t *pmd;
-    pte_t *pte;
+    gctUINT32 data;
 
-    if (!current->mm)
+    /* Check external clock state. */
+    if (Os->clockStates[Core] == gcvFALSE)
     {
-        return gcvSTATUS_NOT_FOUND;
+        gcmkPRINT("[galcore]: %s(%d) External clock off", __FUNCTION__, __LINE__);
+        return gcvFALSE;
     }
 
-    pgd = pgd_offset(current->mm, logical);
-    if (pgd_none(*pgd) || pgd_bad(*pgd))
+    /* Check internal clock state. */
+    if (Address == 0)
     {
-        return gcvSTATUS_NOT_FOUND;
+        return gcvTRUE;
     }
 
-    pud = pud_offset(pgd, logical);
-    if (pud_none(*pud) || pud_bad(*pud))
+#if gcdMULTI_GPU
+    if (Core == gcvCORE_MAJOR)
     {
-        return gcvSTATUS_NOT_FOUND;
+        data = readl((gctUINT8 *)Os->device->registerBases[gcvCORE_3D_0_ID] + 0x0);
     }
-
-    pmd = pmd_offset(pud, logical);
-    if (pmd_none(*pmd) || pmd_bad(*pmd))
+    else
+#endif
     {
-        return gcvSTATUS_NOT_FOUND;
+        data = readl((gctUINT8 *)Os->device->registerBases[Core] + 0x0);
     }
 
-    pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
-    if (!pte)
+    if ((data & 0x3) == 0x3)
     {
-        return gcvSTATUS_NOT_FOUND;
+        gcmkPRINT("[galcore]: %s(%d) Internal clock off", __FUNCTION__, __LINE__);
+        return gcvFALSE;
     }
 
-    if (!pte_present(*pte))
+    return gcvTRUE;
+}
+
+static gceSTATUS
+_ShrinkMemory(
+    IN gckOS Os
+    )
+{
+    gcsPLATFORM * platform;
+
+    gcmkHEADER_ARG("Os=0x%X", Os);
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    platform = Os->device->platform;
+
+    if (platform && platform->ops->shrinkMemory)
     {
-        pte_unmap_unlock(pte, lock);
-        return gcvSTATUS_NOT_FOUND;
+        platform->ops->shrinkMemory(platform);
+    }
+    else
+    {
+        gcmkFOOTER_NO();
+        return gcvSTATUS_NOT_SUPPORTED;
     }
 
-    *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
-    pte_unmap_unlock(pte, lock);
-
+    gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 }
 
@@ -1027,6 +601,7 @@ gckOS_Construct(
 {
     gckOS os;
     gceSTATUS status;
+    gctINT i;
 
     gcmkHEADER_ARG("Context=0x%X", Context);
 
@@ -1052,8 +627,8 @@ gckOS_Construct(
     /* Set device device. */
     os->device = Context;
 
-    /* IMPORTANT! No heap yet. */
-    os->heap = gcvNULL;
+    /* Set allocateCount to 0, gckOS_Allocate has not been used yet. */
+    atomic_set(&os->allocateCount, 0);
 
     /* Initialize the memory lock. */
     gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
@@ -1062,7 +637,6 @@ gckOS_Construct(
     /* Create debug lock mutex. */
     gcmkONERROR(gckOS_CreateMutex(os, &os->debugLock));
 
-
     os->mdlHead = os->mdlTail = gcvNULL;
 
     /* Get the kernel process ID. */
@@ -1096,12 +670,6 @@ gckOS_Construct(
     idr_init(&os->syncPointDB.idr);
 #endif
 
-#if gcdUSE_NON_PAGED_MEMORY_CACHE
-    os->cacheSize = 0;
-    os->cacheHead = gcvNULL;
-    os->cacheTail = gcvNULL;
-#endif
-
     /* Create a workqueue for os timer. */
     os->workqueue = create_singlethread_workqueue("galcore workqueue");
 
@@ -1111,6 +679,41 @@ gckOS_Construct(
         gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
     }
 
+    os->paddingPage = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
+    if (os->paddingPage == gcvNULL)
+    {
+        /* Out of memory. */
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+    else
+    {
+        SetPageReserved(os->paddingPage);
+    }
+
+    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+    {
+        mutex_init(&os->registerAccessLocks[i]);
+    }
+
+    gckOS_ImportAllocators(os);
+
+#ifdef CONFIG_IOMMU_SUPPORT
+    if (((gckGALDEVICE)(os->device))->mmu == gcvFALSE)
+    {
+        /* Only use IOMMU when internal MMU is not enabled. */
+        status = gckIOMMU_Construct(os, &os->iommu);
+
+        if (gcmIS_ERROR(status))
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO, gcvZONE_OS,
+                "%s(%d): Fail to setup IOMMU",
+                __FUNCTION__, __LINE__
+                );
+        }
+    }
+#endif
+
     /* Return pointer to the gckOS object. */
     *Os = os;
 
@@ -1134,12 +737,6 @@ OnError:
             gckOS_DeleteMutex(os, os->signalMutex));
     }
 
-    if (os->heap != gcvNULL)
-    {
-        gcmkVERIFY_OK(
-            gckHEAP_Destroy(os->heap));
-    }
-
     if (os->memoryMapLock != gcvNULL)
     {
         gcmkVERIFY_OK(
@@ -1190,16 +787,17 @@ gckOS_Destroy(
     IN gckOS Os
     )
 {
-    gckHEAP heap;
-
     gcmkHEADER_ARG("Os=0x%X", Os);
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
 
-#if gcdUSE_NON_PAGED_MEMORY_CACHE
-    _FreeAllNonPagedMemoryCache(Os);
-#endif
+    if (Os->paddingPage != gcvNULL)
+    {
+        ClearPageReserved(Os->paddingPage);
+        __free_page(Os->paddingPage);
+        Os->paddingPage = gcvNULL;
+    }
 
 #if gcdANDROID_NATIVE_FENCE_SYNC
     /*
@@ -1217,16 +815,6 @@ gckOS_Destroy(
     /* Destroy the mutex. */
     gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->signalMutex));
 
-    if (Os->heap != gcvNULL)
-    {
-        /* Mark gckHEAP as gone. */
-        heap     = Os->heap;
-        Os->heap = gcvNULL;
-
-        /* Destroy the gckHEAP object. */
-        gcmkVERIFY_OK(gckHEAP_Destroy(heap));
-    }
-
     /* Destroy the memory lock. */
     gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryMapLock));
     gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryLock));
@@ -1240,12 +828,22 @@ gckOS_Destroy(
     /* Destory work queue. */
     destroy_workqueue(Os->workqueue);
 
+    gckOS_FreeAllocators(Os);
+
+#ifdef CONFIG_IOMMU_SUPPORT
+    if (Os->iommu)
+    {
+        gckIOMMU_Destory(Os, Os->iommu);
+    }
+#endif
+
     /* Flush the debug cache. */
     gcmkDEBUGFLUSH(~0U);
 
     /* Mark the gckOS object as unknown. */
     Os->object.type = gcvOBJ_UNKNOWN;
 
+
     /* Free the gckOS object. */
     kfree(Os);
 
@@ -1254,101 +852,73 @@ gckOS_Destroy(
     return gcvSTATUS_OK;
 }
 
-static gctSTRING
-_CreateKernelVirtualMapping(
-    IN PLINUX_MDL Mdl
+gceSTATUS
+gckOS_CreateKernelVirtualMapping(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Logical,
+    OUT gctSIZE_T * PageCount
     )
 {
-    gctSTRING addr = 0;
-    gctINT numPages = Mdl->numPages;
-
-#if gcdNONPAGED_MEMORY_CACHEABLE
-    if (Mdl->contiguous)
-    {
-        addr = page_address(Mdl->u.contiguousPages);
-    }
-    else
-    {
-        addr = vmap(Mdl->u.nonContiguousPages,
-                    numPages,
-                    0,
-                    PAGE_KERNEL);
-
-        /* Trigger a page fault. */
-        memset(addr, 0, numPages * PAGE_SIZE);
-    }
-#else
-    struct page ** pages;
-    gctBOOL free = gcvFALSE;
-    gctINT i;
-
-    if (Mdl->contiguous)
-    {
-        pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
-
-        if (!pages)
-        {
-            return gcvNULL;
-        }
-
-        for (i = 0; i < numPages; i++)
-        {
-            pages[i] = nth_page(Mdl->u.contiguousPages, i);
-        }
-
-        free = gcvTRUE;
-    }
-    else
-    {
-        pages = Mdl->u.nonContiguousPages;
-    }
+    gceSTATUS status;
+    PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+    gckALLOCATOR allocator = mdl->allocator;
 
-    /* ioremap() can't work on system memory since 2.6.38. */
-    addr = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
+    gcmkHEADER();
 
-    /* Trigger a page fault. */
-    memset(addr, 0, numPages * PAGE_SIZE);
+    *PageCount = mdl->numPages;
 
-    if (free)
-    {
-        kfree(pages);
-    }
+    gcmkONERROR(allocator->ops->MapKernel(allocator, mdl, Logical));
 
-#endif
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
 
-    return addr;
+OnError:
+    gcmkFOOTER();
+    return status;
 }
 
-static void
-_DestoryKernelVirtualMapping(
-    IN gctSTRING Addr
+gceSTATUS
+gckOS_DestroyKernelVirtualMapping(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
+    IN gctPOINTER Logical
     )
 {
-#if !gcdNONPAGED_MEMORY_CACHEABLE
-    vunmap(Addr);
-#endif
+    PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+    gckALLOCATOR allocator = mdl->allocator;
+
+    gcmkHEADER();
+
+    allocator->ops->UnmapKernel(allocator, mdl, Logical);
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
 }
 
 gceSTATUS
-gckOS_CreateKernelVirtualMapping(
+gckOS_CreateUserVirtualMapping(
+    IN gckOS Os,
     IN gctPHYS_ADDR Physical,
-    OUT gctSIZE_T * PageCount,
-    OUT gctPOINTER * Logical
+    IN gctSIZE_T Bytes,
+    OUT gctPOINTER * Logical,
+    OUT gctSIZE_T * PageCount
     )
 {
-    *PageCount = ((PLINUX_MDL)Physical)->numPages;
-    *Logical = _CreateKernelVirtualMapping((PLINUX_MDL)Physical);
-
-    return gcvSTATUS_OK;
+    return gckOS_LockPages(Os, Physical, Bytes, gcvFALSE, Logical, PageCount);
 }
 
 gceSTATUS
-gckOS_DestroyKernelVirtualMapping(
+gckOS_DestroyUserVirtualMapping(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T Bytes,
     IN gctPOINTER Logical
     )
 {
-    _DestoryKernelVirtualMapping((gctSTRING)Logical);
-    return gcvSTATUS_OK;
+    return gckOS_UnlockPages(Os, Physical, Bytes, Logical);
 }
 
 /*******************************************************************************
@@ -1386,16 +956,7 @@ gckOS_Allocate(
     gcmkVERIFY_ARGUMENT(Bytes > 0);
     gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
 
-    /* Do we have a heap? */
-    if (Os->heap != gcvNULL)
-    {
-        /* Allocate from the heap. */
-        gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
-    }
-    else
-    {
-        gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
-    }
+    gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
 
     /* Success. */
     gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
@@ -1439,16 +1000,7 @@ gckOS_Free(
     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
     gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
 
-    /* Do we have a heap? */
-    if (Os->heap != gcvNULL)
-    {
-        /* Free from the heap. */
-        gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
-    }
-    else
-    {
-        gcmkONERROR(gckOS_FreeMemory(Os, Memory));
-    }
+    gcmkONERROR(gckOS_FreeMemory(Os, Memory));
 
     /* Success. */
     gcmkFOOTER_NO();
@@ -1507,6 +1059,9 @@ gckOS_AllocateMemory(
         gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
     }
 
+    /* Increase count. */
+    atomic_inc(&Os->allocateCount);
+
     /* Return pointer to the memory allocation. */
     *Memory = memory;
 
@@ -1556,6 +1111,9 @@ gckOS_FreeMemory(
         kfree(Memory);
     }
 
+    /* Decrease count. */
+    atomic_dec(&Os->allocateCount);
+
     /* Success. */
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
@@ -1689,7 +1247,7 @@ gckOS_MapMemory(
         }
 
 #ifndef NO_DMA_COHERENT
-        if (dma_mmap_coherent(gcvNULL,
+        if (dma_mmap_writecombine(gcvNULL,
                     mdlMap->vma,
                     mdl->addr,
                     mdl->dmaHandle,
@@ -1863,7 +1421,7 @@ gckOS_UnmapMemoryEx(
             return gcvSTATUS_INVALID_ARGUMENT;
         }
 
-        _UnmapUserLogical(PID, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
+        _UnmapUserLogical(mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
 
         gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
     }
@@ -1968,6 +1526,7 @@ gckOS_AllocateNonPagedMemory(
     PLINUX_MDL mdl = gcvNULL;
     PLINUX_MDL_MAP mdlMap = gcvNULL;
     gctSTRING addr;
+    gckKERNEL kernel;
 #ifdef NO_DMA_COHERENT
     struct page * page;
     long size, order;
@@ -1993,7 +1552,7 @@ gckOS_AllocateNonPagedMemory(
     numPages = GetPageCount(bytes, 0);
 
     /* Allocate mdl+vector structure */
-    mdl = _CreateMdl(_GetProcessID());
+    mdl = _CreateMdl();
     if (mdl == gcvNULL)
     {
         gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
@@ -2006,45 +1565,19 @@ gckOS_AllocateNonPagedMemory(
     locked = gcvTRUE;
 
 #ifndef NO_DMA_COHERENT
-#if gcdUSE_NON_PAGED_MEMORY_CACHE
-    addr = _GetNonPagedMemoryCache(Os,
-                mdl->numPages * PAGE_SIZE,
-                &mdl->dmaHandle);
-
-    if (addr == gcvNULL)
-#endif
-    {
-        addr = dma_alloc_coherent(gcvNULL,
-                mdl->numPages * PAGE_SIZE,
-                &mdl->dmaHandle,
-                GFP_KERNEL | gcdNOWARN);
-    }
-#if gcdUSE_NON_PAGED_MEMORY_CACHE
-    if(addr == gcvNULL)
-    {
-            MEMORY_UNLOCK(Os);
-            locked = gcvFALSE;
-            /*Free all cache and try again*/
-            _FreeAllNonPagedMemoryCache(Os);
-            MEMORY_LOCK(Os);
-            locked = gcvTRUE;
-            addr = dma_alloc_coherent(gcvNULL,
-                mdl->numPages * PAGE_SIZE,
-                &mdl->dmaHandle,
-                GFP_KERNEL | gcdNOWARN);
-    }
+#ifdef CONFIG_ARM64
+    addr = dma_alloc_coherent(gcvNULL,
+#else
+    addr = dma_alloc_writecombine(gcvNULL,
 #endif
+            mdl->numPages * PAGE_SIZE,
+            &mdl->dmaHandle,
+            GFP_KERNEL | gcdNOWARN);
 #else
     size    = mdl->numPages * PAGE_SIZE;
     order   = get_order(size);
-#if gcdUSE_NON_PAGED_MEMORY_CACHE
-    page = _GetNonPagedMemoryCache(Os, order);
 
-    if (page == gcvNULL)
-#endif
-    {
-        page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
-    }
+    page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
 
     if (page == gcvNULL)
     {
@@ -2057,7 +1590,9 @@ gckOS_AllocateNonPagedMemory(
     addr            = _CreateKernelVirtualMapping(mdl);
     mdl->dmaHandle  = virt_to_phys(vaddr);
     mdl->kaddr      = vaddr;
-    mdl->u.contiguousPages = page;
+
+    /* Trigger a page fault. */
+    memset(addr, 0, numPages * PAGE_SIZE);
 
 #if !defined(CONFIG_PPC)
     /* Cache invalidate. */
@@ -2082,6 +1617,15 @@ gckOS_AllocateNonPagedMemory(
         gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
     }
 
+    kernel = Os->device->kernels[gcvCORE_MAJOR] != gcvNULL ?
+                Os->device->kernels[gcvCORE_MAJOR] : Os->device->kernels[gcvCORE_2D];
+    if (((Os->device->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000)) &&
+          kernel->hardware->mmuVersion == 0)
+    {
+        mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
+                       | (Os->device->baseAddress & 0x80000000);
+    }
+
     mdl->addr = addr;
 
     /* Return allocated memory. */
@@ -2168,7 +1712,9 @@ gckOS_AllocateNonPagedMemory(
             gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
         }
 #else
+#if !gcdSECURITY
         mdlMap->vma->vm_page_prot = gcmkNONPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
+#endif
         mdlMap->vma->vm_flags |= gcdVM_FLAGS;
         mdlMap->vma->vm_pgoff = 0;
 
@@ -2196,7 +1742,11 @@ gckOS_AllocateNonPagedMemory(
     }
     else
     {
+#if gcdSECURITY
+        *Logical = (gctPOINTER)mdl->kaddr;
+#else
         *Logical = (gctPOINTER)mdl->addr;
+#endif
     }
 
     /*
@@ -2237,6 +1787,8 @@ OnError:
         /* Free LINUX_MDL. */
         gcmkVERIFY_OK(_DestroyMdl(mdl));
     }
+    *Physical = gcvNULL;
+    *Bytes = 0;
 
     if (locked)
     {
@@ -2302,18 +1854,14 @@ gceSTATUS gckOS_FreeNonPagedMemory(
     MEMORY_LOCK(Os);
 
 #ifndef NO_DMA_COHERENT
-#if gcdUSE_NON_PAGED_MEMORY_CACHE
-    if (!_AddNonPagedMemoryCache(Os,
-                                 mdl->numPages * PAGE_SIZE,
-                                 mdl->addr,
-                                 mdl->dmaHandle))
+#ifdef CONFIG_ARM64
+    dma_free_coherent(gcvNULL,
+#else
+    dma_free_writecombine(gcvNULL,
 #endif
-    {
-        dma_free_coherent(gcvNULL,
-                mdl->numPages * PAGE_SIZE,
-                mdl->addr,
-                mdl->dmaHandle);
-    }
+            mdl->numPages * PAGE_SIZE,
+            mdl->addr,
+            mdl->dmaHandle);
 #else
     size    = mdl->numPages * PAGE_SIZE;
     vaddr   = mdl->kaddr;
@@ -2326,14 +1874,7 @@ gceSTATUS gckOS_FreeNonPagedMemory(
         size    -= PAGE_SIZE;
     }
 
-#if gcdUSE_NON_PAGED_MEMORY_CACHE
-    if (!_AddNonPagedMemoryCache(Os,
-                                 get_order(mdl->numPages * PAGE_SIZE),
-                                 virt_to_page(mdl->kaddr)))
-#endif
-    {
-        free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
-    }
+    free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
 
     _DestoryKernelVirtualMapping(mdl->addr);
 #endif /* NO_DMA_COHERENT */
@@ -2342,11 +1883,8 @@ gceSTATUS gckOS_FreeNonPagedMemory(
 
     while (mdlMap != gcvNULL)
     {
-        if (mdlMap->vmaAddr != gcvNULL)
-        {
-            /* No mapped memory exists when free nonpaged memory */
-            gcmkASSERT(0);
-        }
+        /* No mapped memory exists when free nonpaged memory */
+        gcmkASSERT(mdlMap->vmaAddr == gcvNULL);
 
         mdlMap = mdlMap->next;
     }
@@ -2422,15 +1960,63 @@ gckOS_ReadRegisterEx(
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+#if !gcdMULTI_GPU
     gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
+#endif
+    gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+    if (!in_interrupt())
+    {
+        mutex_lock(&Os->registerAccessLocks[Core]);
+    }
+
+    BUG_ON(!_AllowAccess(Os, Core, Address));
+
+#if gcdMULTI_GPU
+    if (Core == gcvCORE_MAJOR)
+    {
+       *Data = readl((gctUINT8 *)Os->device->registerBase3D[gcvCORE_3D_0_ID] + Address);
+    }
+    else
+#endif
+    {
+        *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
+    }
+
+    if (!in_interrupt())
+    {
+        mutex_unlock(&Os->registerAccessLocks[Core]);
+    }
+
+    /* Success. */
+    gcmkFOOTER_ARG("*Data=0x%08x", *Data);
+    return gcvSTATUS_OK;
+}
+
+#if gcdMULTI_GPU
+gceSTATUS
+gckOS_ReadRegisterByCoreId(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctUINT32 CoreId,
+    IN gctUINT32 Address,
+    OUT gctUINT32 * Data
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Core=%d CoreId=%d Address=0x%X",
+                   Os, Core, CoreId, Address);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
     gcmkVERIFY_ARGUMENT(Data != gcvNULL);
 
-    *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
+    *Data = readl((gctUINT8 *)Os->device->registerBase3D[CoreId] + Address);
 
     /* Success. */
     gcmkFOOTER_ARG("*Data=0x%08x", *Data);
     return gcvSTATUS_OK;
 }
+#endif
 
 /*******************************************************************************
 **
@@ -2473,14 +2059,61 @@ gckOS_WriteRegisterEx(
 {
     gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
 
+#if !gcdMULTI_GPU
     gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
+#endif
+
+    if (!in_interrupt())
+    {
+        mutex_lock(&Os->registerAccessLocks[Core]);
+    }
+
+    BUG_ON(!_AllowAccess(Os, Core, Address));
+
+#if gcdMULTI_GPU
+    if (Core == gcvCORE_MAJOR)
+    {
+        writel(Data, (gctUINT8 *)Os->device->registerBase3D[gcvCORE_3D_0_ID] + Address);
+#if gcdMULTI_GPU > 1
+        writel(Data, (gctUINT8 *)Os->device->registerBase3D[gcvCORE_3D_1_ID] + Address);
+#endif
+    }
+    else
+#endif
+    {
+        writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
+    }
+
+    if (!in_interrupt())
+    {
+        mutex_unlock(&Os->registerAccessLocks[Core]);
+    }
+
+    /* Success. */
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+#if gcdMULTI_GPU
+gceSTATUS
+gckOS_WriteRegisterByCoreId(
+    IN gckOS Os,
+    IN gceCORE Core,
+    IN gctUINT32 CoreId,
+    IN gctUINT32 Address,
+    IN gctUINT32 Data
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Core=%d CoreId=%d Address=0x%X Data=0x%08x",
+                   Os, Core, CoreId, Address, Data);
 
-    writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
+    writel(Data, (gctUINT8 *)Os->device->registerBase3D[CoreId] + Address);
 
     /* Success. */
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 }
+#endif
 
 /*******************************************************************************
 **
@@ -2565,6 +2198,8 @@ gckOS_GetPhysicalAddress(
             gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
     }
 
+    gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Os, *Address, Address));
+
     /* Success. */
     gcmkFOOTER_ARG("*Address=0x%08x", *Address);
     return gcvSTATUS_OK;
@@ -2575,6 +2210,34 @@ OnError:
     return status;
 }
 
+/*******************************************************************************
+**
+**  gckOS_UserLogicalToPhysical
+**
+**  Get the physical system address of a corresponding user 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 address.
+*/
+gceSTATUS gckOS_UserLogicalToPhysical(
+    IN gckOS Os,
+    IN gctPOINTER Logical,
+    OUT gctUINT32 * Address
+    )
+{
+    return gckOS_GetPhysicalAddress(Os, Logical, Address);
+}
+
 #if gcdSECURE_USER
 static gceSTATUS
 gckOS_AddMapping(
@@ -2660,7 +2323,7 @@ OnError:
 }
 #endif
 
-static gceSTATUS
+gceSTATUS
 _ConvertLogical2Physical(
     IN gckOS Os,
     IN gctPOINTER Logical,
@@ -2674,7 +2337,11 @@ _ConvertLogical2Physical(
     PLINUX_MDL_MAP map;
     gcsUSER_MAPPING_PTR userMap;
 
+#if gcdSECURITY
+    base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->kaddr;
+#else
     base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->addr;
+#endif
 
     /* Check for the logical address match. */
     if ((base != gcvNULL)
@@ -2696,7 +2363,7 @@ _ConvertLogical2Physical(
         }
         else
         {
-            *Physical = gcmPTR2INT(virt_to_phys(base)) + offset;
+            *Physical = gcmPTR2INT32(virt_to_phys(base)) + offset;
         }
 
         return gcvSTATUS_OK;
@@ -2784,6 +2451,7 @@ gckOS_GetPhysicalAddressProcess(
 {
     PLINUX_MDL mdl;
     gctINT8_PTR base;
+    gckALLOCATOR allocator = gcvNULL;
     gceSTATUS status = gcvSTATUS_INVALID_ADDRESS;
 
     gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os, Logical, ProcessID);
@@ -2826,11 +2494,27 @@ gckOS_GetPhysicalAddressProcess(
         for (mdl = Os->mdlHead; mdl != gcvNULL; mdl = mdl->next)
         {
             /* Try this MDL. */
-            status = _ConvertLogical2Physical(Os,
-                                              Logical,
-                                              ProcessID,
-                                              mdl,
-                                              Address);
+            allocator = mdl->allocator;
+
+            if (allocator)
+            {
+                status = allocator->ops->LogicalToPhysical(
+                            allocator,
+                            mdl,
+                            Logical,
+                            ProcessID,
+                            Address
+                            );
+            }
+            else
+            {
+                status = _ConvertLogical2Physical(Os,
+                            Logical,
+                            ProcessID,
+                            mdl,
+                            Address);
+            }
+
             if (gcmIS_SUCCESS(status))
             {
                 break;
@@ -2915,41 +2599,77 @@ gckOS_MapPhysical(
         mdl = mdl->next;
     }
 
+    MEMORY_UNLOCK(Os);
+
     if (mdl == gcvNULL)
     {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-       struct contiguous_mem_pool *pool = Os->device->pool;
+        struct page * page = pfn_to_page(physical >> PAGE_SHIFT);
 
-       if (Physical >= pool->phys && Physical < pool->phys + pool->size)
-               logical = (gctPOINTER)(Physical - pool->phys + pool->virt);
-       else
-               logical = gcvNULL;
-#else
-        /* Map memory as cached memory. */
-        request_mem_region(physical, Bytes, "MapRegion");
-        logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
-#endif
+        if (pfn_valid(page_to_pfn(page)))
+        {
+            gctUINT32 offset = physical & ~PAGE_MASK;
+            struct page ** pages;
+            gctUINT numPages;
+            gctINT i;
+
+            numPages = GetPageCount(PAGE_ALIGN(offset + Bytes), 0);
+
+            pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
+
+            if (!pages)
+            {
+                gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+                return gcvSTATUS_OUT_OF_MEMORY;
+            }
+
+            for (i = 0; i < numPages; i++)
+            {
+                pages[i] = nth_page(page, i);
+            }
 
-        if (logical == gcvNULL)
+            logical = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
+
+            kfree(pages);
+
+            if (logical == gcvNULL)
+            {
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_INFO, gcvZONE_OS,
+                    "%s(%d): Failed to vmap",
+                    __FUNCTION__, __LINE__
+                    );
+
+                /* Out of resources. */
+                gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+                return gcvSTATUS_OUT_OF_RESOURCES;
+            }
+
+            logical += offset;
+        }
+        else
         {
-            gcmkTRACE_ZONE(
-                gcvLEVEL_INFO, gcvZONE_OS,
-                "%s(%d): Failed to map physical address 0x%08x",
-                __FUNCTION__, __LINE__, Physical
-                );
+            /* Map memory as cached memory. */
+            request_mem_region(physical, Bytes, "MapRegion");
+            logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
 
-            MEMORY_UNLOCK(Os);
+            if (logical == gcvNULL)
+            {
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_INFO, gcvZONE_OS,
+                    "%s(%d): Failed to ioremap",
+                    __FUNCTION__, __LINE__
+                    );
 
-            /* Out of resources. */
-            gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
-            return gcvSTATUS_OUT_OF_RESOURCES;
+                /* Out of resources. */
+                gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+                return gcvSTATUS_OUT_OF_RESOURCES;
+            }
         }
 
         /* Return pointer to mapped memory. */
         *Logical = logical;
     }
 
-    MEMORY_UNLOCK(Os);
 
     /* Success. */
     gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
@@ -3014,7 +2734,7 @@ gckOS_UnmapPhysical(
     if (mdl == gcvNULL)
     {
         /* Unmap the memory. */
-        iounmap(Logical);
+        vunmap((void *)((unsigned long)Logical & PAGE_MASK));
     }
 
     MEMORY_UNLOCK(Os);
@@ -3103,7 +2823,7 @@ gckOS_DeleteMutex(
     gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
 
     /* Destroy the mutex. */
-    mutex_destroy(Mutex);
+    mutex_destroy((struct mutex *)Mutex);
 
     /* Free the mutex structure. */
     gcmkONERROR(gckOS_Free(Os, Mutex));
@@ -3147,84 +2867,12 @@ gckOS_AcquireMutex(
     IN gctUINT32 Timeout
     )
 {
-#if gcdDETECT_TIMEOUT
-    gctUINT32 timeout;
-#endif
-
     gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os, Mutex, Timeout);
 
     /* Validate the arguments. */
     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
     gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
 
-#if gcdDETECT_TIMEOUT
-    timeout = 0;
-
-    for (;;)
-    {
-        /* Try to acquire the mutex. */
-        if (mutex_trylock(Mutex))
-        {
-            /* Success. */
-            gcmkFOOTER_NO();
-            return gcvSTATUS_OK;
-        }
-
-        /* Advance the timeout. */
-        timeout += 1;
-
-        if (Timeout == gcvINFINITE)
-        {
-            if (timeout == gcdINFINITE_TIMEOUT)
-            {
-                gctUINT32 dmaAddress1, dmaAddress2;
-                gctUINT32 dmaState1, dmaState2;
-
-                dmaState1   = dmaState2   =
-                dmaAddress1 = dmaAddress2 = 0;
-
-                /* Verify whether DMA is running. */
-                gcmkVERIFY_OK(_VerifyDMA(
-                    Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
-                    ));
-
-#if gcdDETECT_DMA_ADDRESS
-                /* Dump only if DMA appears stuck. */
-                if (
-                    (dmaAddress1 == dmaAddress2)
-#if gcdDETECT_DMA_STATE
-                 && (dmaState1   == dmaState2)
-#      endif
-                )
-#   endif
-                {
-                    gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
-
-                    gcmkPRINT(
-                        "%s(%d): mutex 0x%X; forced message flush.",
-                        __FUNCTION__, __LINE__, Mutex
-                        );
-
-                    /* Flush the debug cache. */
-                    gcmkDEBUGFLUSH(dmaAddress2);
-                }
-
-                timeout = 0;
-            }
-        }
-        else
-        {
-            /* Timedout? */
-            if (timeout >= Timeout)
-            {
-                break;
-            }
-        }
-
-        /* Wait for 1 millisecond. */
-        gcmkVERIFY_OK(gckOS_Delay(Os, 1));
-    }
-#else
     if (Timeout == gcvINFINITE)
     {
         /* Lock the mutex. */
@@ -3253,7 +2901,6 @@ gckOS_AcquireMutex(
         /* Wait for 1 millisecond. */
         gcmkVERIFY_OK(gckOS_Delay(Os, 1));
     }
-#endif
 
     /* Timeout. */
     gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
@@ -3334,6 +2981,7 @@ gckOS_AtomicExchange(
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(OldValue != gcvNULL);
 
     /* Exchange the pair of 32-bit values. */
     *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
@@ -3379,6 +3027,7 @@ gckOS_AtomicExchangePtr(
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(OldValue != gcvNULL);
 
     /* Exchange the pair of pointers. */
     *OldValue = (gctPOINTER)(gctUINTPTR_T) atomic_xchg((atomic_t *) Target, (int)(gctUINTPTR_T) NewValue);
@@ -3388,7 +3037,6 @@ gckOS_AtomicExchangePtr(
     return gcvSTATUS_OK;
 }
 
-#if gcdSMP
 /*******************************************************************************
 **
 **  gckOS_AtomicSetMask
@@ -3464,7 +3112,6 @@ gckOS_AtomClearMask(
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 }
-#endif
 
 /*******************************************************************************
 **
@@ -3748,13 +3395,12 @@ gckOS_Delay(
     if (Delay > 0)
     {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
-        ktime_t delay = ktime_set(Delay/1000, (Delay%1000) * NSEC_PER_MSEC);
+        ktime_t delay = ktime_set((Delay / MSEC_PER_SEC), (Delay % MSEC_PER_SEC) * NSEC_PER_MSEC);
         __set_current_state(TASK_UNINTERRUPTIBLE);
         schedule_hrtimeout(&delay, HRTIMER_MODE_REL);
 #else
         msleep(Delay);
 #endif
-
     }
 
     /* Success. */
@@ -3842,9 +3488,12 @@ gckOS_GetTime(
     OUT gctUINT64_PTR Time
     )
 {
+    struct timeval tv;
     gcmkHEADER();
 
-    *Time = 0;
+    /* Return the time of day in microseconds. */
+    do_gettimeofday(&tv);
+    *Time = (tv.tv_sec * 1000000ULL) + tv.tv_usec;
 
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
@@ -3933,7 +3582,7 @@ gckOS_AllocatePagedMemory(
     gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
 
     /* Allocate the memory. */
-    gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical));
+    gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvALLOC_FLAG_NONE, Bytes, gcvNULL, Physical));
 
     /* Success. */
     gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
@@ -3956,14 +3605,17 @@ OnError:
 **      gckOS Os
 **          Pointer to an gckOS object.
 **
-**      gctBOOL Contiguous
-**          Need contiguous memory or not.
+**      gctUINT32 Flag
+**          Allocation attribute.
 **
 **      gctSIZE_T Bytes
 **          Number of bytes to allocate.
 **
 **  OUTPUT:
 **
+**      gctUINT32 * Gid
+**          Save the global ID for the piece of allocated memory.
+**
 **      gctPHYS_ADDR * Physical
 **          Pointer to a variable that receives the physical address of the
 **          memory allocation.
@@ -3971,22 +3623,19 @@ OnError:
 gceSTATUS
 gckOS_AllocatePagedMemoryEx(
     IN gckOS Os,
-    IN gctBOOL Contiguous,
+    IN gctUINT32 Flag,
     IN gctSIZE_T Bytes,
+    OUT gctUINT32 * Gid,
     OUT gctPHYS_ADDR * Physical
     )
 {
     gctINT numPages;
-    gctINT i;
     PLINUX_MDL mdl = gcvNULL;
     gctSIZE_T bytes;
-    gctBOOL locked = gcvFALSE;
-    gceSTATUS status;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
-    gctPOINTER addr = gcvNULL;
-#endif
+    gceSTATUS status = gcvSTATUS_OUT_OF_MEMORY;
+    gckALLOCATOR allocator;
 
-    gcmkHEADER_ARG("Os=0x%X Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
+    gcmkHEADER_ARG("Os=0x%X Flag=%x Bytes=%lu", Os, Flag, Bytes);
 
     /* Verify the arguments. */
     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
@@ -3997,90 +3646,51 @@ gckOS_AllocatePagedMemoryEx(
 
     numPages = GetPageCount(bytes, 0);
 
-    MEMORY_LOCK(Os);
-    locked = gcvTRUE;
-
-    mdl = _CreateMdl(_GetProcessID());
+    mdl = _CreateMdl();
     if (mdl == gcvNULL)
     {
         gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
     }
 
-    if (Contiguous)
+    /* Walk all allocators. */
+    list_for_each_entry(allocator, &Os->allocatorList, head)
     {
-        gctUINT32 order = get_order(bytes);
+        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+                       "%s(%d) flag = %x allocator->capability = %x",
+                        __FUNCTION__, __LINE__, Flag, allocator->capability);
 
-        if (order >= MAX_ORDER)
+        if ((Flag & allocator->capability) != Flag)
         {
-            gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+            continue;
         }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
-        addr =
-            alloc_pages_exact(numPages * PAGE_SIZE, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY);
+        status = allocator->ops->Alloc(allocator, mdl, numPages, Flag);
 
-        mdl->u.contiguousPages = addr
-                               ? virt_to_page(addr)
-                               : gcvNULL;
-
-        mdl->exact = gcvTRUE;
-#else
-        mdl->u.contiguousPages =
-            alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, order);
-#endif
-        if (mdl->u.contiguousPages == gcvNULL)
+        if (gcmIS_SUCCESS(status))
         {
-            mdl->u.contiguousPages =
-                alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, order);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
-            mdl->exact = gcvFALSE;
-#endif
+            mdl->allocator = allocator;
+            break;
         }
     }
-    else
-    {
-        mdl->u.nonContiguousPages = _NonContiguousAlloc(numPages);
-    }
 
-    if (mdl->u.contiguousPages == gcvNULL && mdl->u.nonContiguousPages == gcvNULL)
-    {
-        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
-    }
+    /* Check status. */
+    gcmkONERROR(status);
 
     mdl->dmaHandle  = 0;
     mdl->addr       = 0;
     mdl->numPages   = numPages;
     mdl->pagedMem   = 1;
-    mdl->contiguous = Contiguous;
-
-    for (i = 0; i < mdl->numPages; i++)
-    {
-        struct page *page;
-
-        if (mdl->contiguous)
-        {
-            page = nth_page(mdl->u.contiguousPages, i);
-        }
-        else
-        {
-            page = _NonContiguousToPage(mdl->u.nonContiguousPages, i);
-        }
+    mdl->contiguous = Flag & gcvALLOC_FLAG_CONTIGUOUS;
 
-        SetPageReserved(page);
+    /* Return physical address. */
+    *Physical = (gctPHYS_ADDR) mdl;
 
-        if (!PageHighMem(page) && page_to_phys(page))
-        {
-            gcmkVERIFY_OK(
-                gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
-                                 (gctPOINTER)(gctUINTPTR_T)page_to_phys(page),
-                                 page_address(page),
-                                 PAGE_SIZE));
-        }
+    if (Gid != gcvNULL)
+    {
+        *Gid = mdl->gid;
     }
 
-    /* Return physical address. */
-    *Physical = (gctPHYS_ADDR) mdl;
+    MEMORY_LOCK(Os);
 
     /*
      * Add this to a global list.
@@ -4112,15 +3722,10 @@ OnError:
         /* Free the memory. */
         _DestroyMdl(mdl);
     }
-
-    if (locked)
-    {
-        /* Unlock the memory. */
-        MEMORY_UNLOCK(Os);
-    }
+    *Physical = gcvNULL;
 
     /* Return the status. */
-    gcmkFOOTER();
+    gcmkFOOTER_ARG("Os=0x%X Flag=%x Bytes=%lu", Os, Flag, Bytes);
     return status;
 }
 
@@ -4153,7 +3758,7 @@ gckOS_FreePagedMemory(
     )
 {
     PLINUX_MDL mdl = (PLINUX_MDL) Physical;
-    gctINT i;
+    gckALLOCATOR allocator = (gckALLOCATOR)mdl->allocator;
 
     gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
 
@@ -4162,40 +3767,8 @@ gckOS_FreePagedMemory(
     gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
     gcmkVERIFY_ARGUMENT(Bytes > 0);
 
-    /*addr = mdl->addr;*/
-
     MEMORY_LOCK(Os);
 
-    for (i = 0; i < mdl->numPages; i++)
-    {
-        if (mdl->contiguous)
-        {
-            ClearPageReserved(nth_page(mdl->u.contiguousPages, i));
-        }
-        else
-        {
-            ClearPageReserved(_NonContiguousToPage(mdl->u.nonContiguousPages, i));
-        }
-    }
-
-    if (mdl->contiguous)
-    {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
-        if (mdl->exact == gcvTRUE)
-        {
-            free_pages_exact(page_address(mdl->u.contiguousPages), mdl->numPages * PAGE_SIZE);
-        }
-        else
-#endif
-        {
-            __free_pages(mdl->u.contiguousPages, GetOrder(mdl->numPages));
-        }
-    }
-    else
-    {
-        _NonContiguousFree(mdl->u.nonContiguousPages, mdl->numPages);
-    }
-
     /* Remove the node from global list. */
     if (mdl == Os->mdlHead)
     {
@@ -4220,6 +3793,8 @@ gckOS_FreePagedMemory(
 
     MEMORY_UNLOCK(Os);
 
+    allocator->ops->Free(allocator, mdl);
+
     /* Free the structure... */
     gcmkVERIFY_OK(_DestroyMdl(mdl));
 
@@ -4268,184 +3843,50 @@ gckOS_LockPages(
     OUT gctSIZE_T * PageCount
     )
 {
-    PLINUX_MDL      mdl;
-    PLINUX_MDL_MAP  mdlMap;
-    gctSTRING       addr;
-    unsigned long   start;
-    unsigned long   pfn;
-    gctINT          i;
-
-    gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
-
-    /* Verify the arguments. */
-    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
-    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
-    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
-    gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
-
-    mdl = (PLINUX_MDL) Physical;
-
-    MEMORY_LOCK(Os);
-
-    mdlMap = FindMdlMap(mdl, _GetProcessID());
-
-    if (mdlMap == gcvNULL)
-    {
-        mdlMap = _CreateMdlMap(mdl, _GetProcessID());
-
-        if (mdlMap == gcvNULL)
-        {
-            MEMORY_UNLOCK(Os);
-
-            gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
-            return gcvSTATUS_OUT_OF_MEMORY;
-        }
-    }
-
-    if (mdlMap->vmaAddr == gcvNULL)
-    {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
-        mdlMap->vmaAddr = (gctSTRING)vm_mmap(gcvNULL,
-                        0L,
-                        mdl->numPages * PAGE_SIZE,
-                        PROT_READ | PROT_WRITE,
-                        MAP_SHARED,
-                        0);
-#else
-        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);
-
-        up_write(&current->mm->mmap_sem);
-#endif
-
-        gcmkTRACE_ZONE(
-            gcvLEVEL_INFO, gcvZONE_OS,
-            "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
-            __FUNCTION__, __LINE__,
-            (gctUINT32)(gctUINTPTR_T)mdlMap->vmaAddr,
-            (gctUINT32)(gctUINTPTR_T)mdl
-            );
+    gceSTATUS       status;
+    PLINUX_MDL      mdl;
+    PLINUX_MDL_MAP  mdlMap;
+    gckALLOCATOR    allocator;
 
-        if (IS_ERR(mdlMap->vmaAddr))
-        {
-            gcmkTRACE_ZONE(
-                gcvLEVEL_INFO, gcvZONE_OS,
-                "%s(%d): do_mmap_pgoff error",
-                __FUNCTION__, __LINE__
-                );
+    gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
 
-            mdlMap->vmaAddr = gcvNULL;
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
 
-            MEMORY_UNLOCK(Os);
+    mdl = (PLINUX_MDL) Physical;
+    allocator = mdl->allocator;
 
-            gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
-            return gcvSTATUS_OUT_OF_MEMORY;
-        }
+    MEMORY_LOCK(Os);
 
-        down_write(&current->mm->mmap_sem);
+    mdlMap = FindMdlMap(mdl, _GetProcessID());
 
-        mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+    if (mdlMap == gcvNULL)
+    {
+        mdlMap = _CreateMdlMap(mdl, _GetProcessID());
 
-        if (mdlMap->vma == gcvNULL)
+        if (mdlMap == gcvNULL)
         {
-            up_write(&current->mm->mmap_sem);
-
-            gcmkTRACE_ZONE(
-                gcvLEVEL_INFO, gcvZONE_OS,
-                "%s(%d): find_vma error",
-                __FUNCTION__, __LINE__
-                );
-
-            mdlMap->vmaAddr = gcvNULL;
-
             MEMORY_UNLOCK(Os);
 
-            gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
-            return gcvSTATUS_OUT_OF_RESOURCES;
-        }
-
-        mdlMap->vma->vm_flags |= gcdVM_FLAGS;
-
-        if (Cacheable == gcvFALSE)
-        {
-            /* Make this mapping non-cached. */
-            mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
+            gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+            return gcvSTATUS_OUT_OF_MEMORY;
         }
+    }
 
-        addr = mdl->addr;
-
-        /* Now map all the vmalloc pages to this user address. */
-        if (mdl->contiguous)
-        {
-            /* map kernel memory to user space.. */
-            if (remap_pfn_range(mdlMap->vma,
-                                mdlMap->vma->vm_start,
-                                page_to_pfn(mdl->u.contiguousPages),
-                                mdlMap->vma->vm_end - mdlMap->vma->vm_start,
-                                mdlMap->vma->vm_page_prot) < 0)
-            {
-                up_write(&current->mm->mmap_sem);
-
-                gcmkTRACE_ZONE(
-                    gcvLEVEL_INFO, gcvZONE_OS,
-                    "%s(%d): unable to mmap ret",
-                    __FUNCTION__, __LINE__
-                    );
-
-                mdlMap->vmaAddr = gcvNULL;
-
-                MEMORY_UNLOCK(Os);
+    if (mdlMap->vmaAddr == gcvNULL)
+    {
+        status = allocator->ops->MapUser(allocator, mdl, mdlMap, Cacheable);
 
-                gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
-                return gcvSTATUS_OUT_OF_MEMORY;
-            }
-        }
-        else
+        if (gcmIS_ERROR(status))
         {
-            start = mdlMap->vma->vm_start;
-
-            for (i = 0; i < mdl->numPages; i++)
-            {
-                pfn = _NonContiguousToPfn(mdl->u.nonContiguousPages, i);
-
-                if (remap_pfn_range(mdlMap->vma,
-                                    start,
-                                    pfn,
-                                    PAGE_SIZE,
-                                    mdlMap->vma->vm_page_prot) < 0)
-                {
-                    up_write(&current->mm->mmap_sem);
-
-                    gcmkTRACE_ZONE(
-                        gcvLEVEL_INFO, gcvZONE_OS,
-                        "%s(%d): gctPHYS_ADDR->0x%X Logical->0x%X Unable to map addr->0x%X to start->0x%X",
-                        __FUNCTION__, __LINE__,
-                        (gctUINT32)(gctUINTPTR_T)Physical,
-                        (gctUINT32)(gctUINTPTR_T)*Logical,
-                        (gctUINT32)(gctUINTPTR_T)addr,
-                        (gctUINT32)(gctUINTPTR_T)start
-                        );
-
-                    mdlMap->vmaAddr = gcvNULL;
-
-                    MEMORY_UNLOCK(Os);
-
-                    gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
-                    return gcvSTATUS_OUT_OF_MEMORY;
-                }
+            MEMORY_UNLOCK(Os);
 
-                start += PAGE_SIZE;
-                addr += PAGE_SIZE;
-            }
+            gcmkFOOTER_ARG("*status=%d", status);
+            return status;
         }
-
-        up_write(&current->mm->mmap_sem);
     }
 
     mdlMap->count++;
@@ -4465,7 +3906,7 @@ gckOS_LockPages(
         Os,
         _GetProcessID(),
         Physical,
-        gcvNULL,
+        gcvINVALID_ADDRESS,
         (gctPOINTER)mdlMap->vmaAddr,
         mdl->numPages * PAGE_SIZE
         ));
@@ -4511,6 +3952,7 @@ gckOS_MapPages(
                             gcvCORE_MAJOR,
                             Physical,
                             PageCount,
+                            0,
                             PageTable);
 }
 
@@ -4520,6 +3962,7 @@ gckOS_MapPagesEx(
     IN gceCORE Core,
     IN gctPHYS_ADDR Physical,
     IN gctSIZE_T PageCount,
+    IN gctUINT32 Address,
     IN gctPOINTER PageTable
     )
 {
@@ -4534,6 +3977,12 @@ gckOS_MapPagesEx(
     gctPHYS_ADDR pageTablePhysical;
 #endif
 
+#if gcdPROCESS_ADDRESS_SPACE
+    gckKERNEL kernel = Os->device->kernels[Core];
+    gckMMU      mmu;
+#endif
+    gckALLOCATOR allocator;
+
     gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
                    Os, Core, Physical, PageCount, PageTable);
 
@@ -4546,6 +3995,8 @@ gckOS_MapPagesEx(
     /* Convert pointer to MDL. */
     mdl = (PLINUX_MDL)Physical;
 
+    allocator = mdl->allocator;
+
     gcmkTRACE_ZONE(
         gcvLEVEL_INFO, gcvZONE_OS,
         "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
@@ -4555,7 +4006,9 @@ gckOS_MapPagesEx(
         mdl->pagedMem
         );
 
-    MEMORY_LOCK(Os);
+#if gcdPROCESS_ADDRESS_SPACE
+    gcmkONERROR(gckKERNEL_GetProcessMMU(kernel, &mmu));
+#endif
 
     table = (gctUINT32 *)PageTable;
 #if gcdNONPAGED_MEMORY_CACHEABLE
@@ -4567,82 +4020,86 @@ gckOS_MapPagesEx(
      /* Get all the physical addresses and store them in the page table. */
 
     offset = 0;
+    PageCount = PageCount / (PAGE_SIZE / 4096);
 
-    if (mdl->pagedMem)
+    /* Try to get the user pages so DMA can happen. */
+    while (PageCount-- > 0)
     {
-        /* Try to get the user pages so DMA can happen. */
-        while (PageCount-- > 0)
+        gctUINT i;
+        gctUINT32 phys = ~0;
+
+        if (mdl->pagedMem && !mdl->contiguous)
+        {
+            allocator->ops->Physical(allocator, mdl, offset, &phys);
+        }
+        else
+        {
+            if (!mdl->pagedMem)
+            {
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_INFO, gcvZONE_OS,
+                    "%s(%d): we should not get this call for Non Paged Memory!",
+                    __FUNCTION__, __LINE__
+                    );
+            }
+
+            phys = page_to_phys(nth_page(mdl->u.contiguousPages, offset));
+        }
+
+        gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Os, phys, &phys));
+
+#ifdef CONFIG_IOMMU_SUPPORT
+        if (Os->iommu)
+        {
+            gcmkTRACE_ZONE(
+                gcvLEVEL_INFO, gcvZONE_OS,
+                "%s(%d): Setup mapping in IOMMU %x => %x",
+                __FUNCTION__, __LINE__,
+                Address + (offset * PAGE_SIZE), phys
+                );
+
+            /* When use IOMMU, GPU use system PAGE_SIZE. */
+            gcmkONERROR(gckIOMMU_Map(
+                Os->iommu, Address + (offset * PAGE_SIZE), phys, PAGE_SIZE));
+        }
+        else
+#endif
         {
+
 #if gcdENABLE_VG
             if (Core == gcvCORE_VG)
             {
-                if (mdl->contiguous)
+                for (i = 0; i < (PAGE_SIZE / 4096); i++)
                 {
                     gcmkONERROR(
                         gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
-                             page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
-                             table));
-                }
-                else
-                {
-                    gcmkONERROR(
-                        gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
-                             _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
-                             table));
+                            phys + (i * 4096),
+                            table++));
                 }
             }
             else
 #endif
             {
-                if (mdl->contiguous)
+                for (i = 0; i < (PAGE_SIZE / 4096); i++)
                 {
+#if gcdPROCESS_ADDRESS_SPACE
+                    gctUINT32_PTR pageTableEntry;
+                    gckMMU_GetPageEntry(mmu, Address + (offset * 4096), &pageTableEntry);
                     gcmkONERROR(
-                        gckMMU_SetPage(Os->device->kernels[Core]->mmu,
-                             page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
-                             table));
-                }
-                else
-                {
+                        gckMMU_SetPage(mmu,
+                            phys + (i * 4096),
+                            pageTableEntry));
+#else
                     gcmkONERROR(
                         gckMMU_SetPage(Os->device->kernels[Core]->mmu,
-                             _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
-                             table));
+                            phys + (i * 4096),
+                            table++));
+#endif
                 }
             }
-
-            table++;
-            offset += 1;
         }
-    }
-    else
-    {
-        gcmkTRACE_ZONE(
-            gcvLEVEL_INFO, gcvZONE_OS,
-            "%s(%d): we should not get this call for Non Paged Memory!",
-            __FUNCTION__, __LINE__
-            );
 
-        while (PageCount-- > 0)
-        {
-#if gcdENABLE_VG
-            if (Core == gcvCORE_VG)
-            {
-                gcmkONERROR(
-                        gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
-                                         page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
-                                         table));
-            }
-            else
-#endif
-            {
-                gcmkONERROR(
-                        gckMMU_SetPage(Os->device->kernels[Core]->mmu,
-                                         page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
-                                         table));
-            }
-            table++;
-            offset += 1;
-        }
+        offset += 1;
     }
 
 #if gcdNONPAGED_MEMORY_CACHEABLE
@@ -4663,13 +4120,29 @@ gckOS_MapPagesEx(
 
 OnError:
 
-    MEMORY_UNLOCK(Os);
-
     /* Return the status. */
     gcmkFOOTER();
     return status;
 }
 
+gceSTATUS
+gckOS_UnmapPages(
+    IN gckOS Os,
+    IN gctSIZE_T PageCount,
+    IN gctUINT32 Address
+    )
+{
+#ifdef CONFIG_IOMMU_SUPPORT
+    if (Os->iommu)
+    {
+        gcmkVERIFY_OK(gckIOMMU_Unmap(
+            Os->iommu, Address, PageCount * PAGE_SIZE));
+    }
+#endif
+
+    return gcvSTATUS_OK;
+}
+
 /*******************************************************************************
 **
 **  gckOS_UnlockPages
@@ -4704,6 +4177,7 @@ gckOS_UnlockPages(
 {
     PLINUX_MDL_MAP          mdlMap;
     PLINUX_MDL              mdl = (PLINUX_MDL)Physical;
+    gckALLOCATOR            allocator = mdl->allocator;
 
     gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
                    Os, Physical, Bytes, Logical);
@@ -4713,10 +4187,6 @@ gckOS_UnlockPages(
     gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
     gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
 
-    /* Make sure there is already a mapping...*/
-    gcmkVERIFY_ARGUMENT(mdl->u.nonContiguousPages != gcvNULL
-                       || mdl->u.contiguousPages != gcvNULL);
-
     MEMORY_LOCK(Os);
 
     mdlMap = mdl->maps;
@@ -4727,7 +4197,11 @@ gckOS_UnlockPages(
         {
             if (--mdlMap->count == 0)
             {
-                _UnmapUserLogical(mdlMap->pid, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
+                allocator->ops->UnmapUser(
+                    allocator,
+                    mdlMap->vmaAddr,
+                    mdl->numPages * PAGE_SIZE);
+
                 mdlMap->vmaAddr = gcvNULL;
             }
         }
@@ -5399,6 +4873,9 @@ OnError:
     gctUINTPTR_T start, end, memory;
     gctUINT32 offset;
     gctINT result = 0;
+#if gcdPROCESS_ADDRESS_SPACE
+    gckMMU mmu;
+#endif
 
     gcsPageInfo_PTR info = gcvNULL;
     struct page **pages = gcvNULL;
@@ -5412,6 +4889,8 @@ OnError:
 
     do
     {
+        gctSIZE_T extraPage;
+
         memory = (gctUINTPTR_T) Memory;
 
         /* Get the number of required pages. */
@@ -5419,6 +4898,9 @@ OnError:
         start = memory >> PAGE_SHIFT;
         pageCount = end - start;
 
+        /* Allocate extra 64 bytes to avoid cache overflow */
+        extraPage = (((memory + gcmALIGN(Size + 64, 64) + PAGE_SIZE - 1) >> PAGE_SHIFT) > end) ? 1 : 0;
+
         gcmkTRACE_ZONE(
             gcvLEVEL_INFO, gcvZONE_OS,
             "%s(%d): pageCount: %d.",
@@ -5444,8 +4926,10 @@ OnError:
             break;
         }
 
+        info->extraPage = 0;
+
         /* Allocate the array of page addresses. */
-        pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
+        pages = (struct page **)kmalloc((pageCount + extraPage) * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
 
         if (pages == gcvNULL)
         {
@@ -5458,7 +4942,11 @@ OnError:
             for (i = 0; i < pageCount; i++)
             {
                 pages[i] = pfn_to_page((Physical >> PAGE_SHIFT) + i);
-                get_page(pages[i]);
+
+                if (pfn_valid(page_to_pfn(pages[i])))
+                {
+                    get_page(pages[i]);
+                }
             }
         }
         else
@@ -5568,6 +5056,9 @@ OnError:
                             *Address = physical - Os->device->baseAddress;
                             *Info    = info;
 
+                            gcmkVERIFY_OK(
+                                gckOS_CPUPhysicalToGPUPhysical(Os, *Address, Address));
+
                             gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
                                            *Info, *Address);
 
@@ -5579,7 +5070,10 @@ OnError:
                 /* Reference pages. */
                 for (i = 0; i < pageCount; i++)
                 {
-                    get_page(pages[i]);
+                    if (pfn_valid(page_to_pfn(pages[i])))
+                    {
+                        get_page(pages[i]);
+                    }
                 }
             }
         }
@@ -5593,11 +5087,66 @@ OnError:
 
             /* Flush(clean) the data cache. */
             gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
-                             (gctPOINTER)(gctUINTPTR_T)page_to_phys(pages[i]),
+                             page_to_phys(pages[i]),
                              (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE,
                              PAGE_SIZE));
         }
 
+#if gcdPROCESS_ADDRESS_SPACE
+        gcmkONERROR(gckKERNEL_GetProcessMMU(Os->device->kernels[Core], &mmu));
+#endif
+
+        if (extraPage)
+        {
+            pages[pageCount++] = Os->paddingPage;
+            info->extraPage = 1;
+        }
+
+#if gcdSECURITY
+    {
+        gctPHYS_ADDR physicalArrayPhysical;
+        gctPOINTER physicalArrayLogical;
+        gctUINT32_PTR logical;
+        gctSIZE_T bytes = pageCount * gcmSIZEOF(gctUINT32);
+        pageTable = gcvNULL;
+
+        gcmkONERROR(gckOS_AllocateNonPagedMemory(
+            Os,
+            gcvFALSE,
+            &bytes,
+            &physicalArrayPhysical,
+            &physicalArrayLogical
+            ));
+
+        logical = physicalArrayLogical;
+
+        /* Fill the page table. */
+        for (i = 0; i < pageCount; i++)
+        {
+            gctUINT32 phys;
+            phys = page_to_phys(pages[i]);
+
+            logical[i] = phys;
+        }
+        j = 0;
+
+
+        gcmkONERROR(gckKERNEL_SecurityMapMemory(
+            Os->device->kernels[Core],
+            physicalArrayLogical,
+            pageCount,
+            &address
+            ));
+
+        gcmkONERROR(gckOS_FreeNonPagedMemory(
+            Os,
+            1,
+            physicalArrayPhysical,
+            physicalArrayLogical
+            ));
+    }
+
+#else
 #if gcdENABLE_VG
         if (Core == gcvCORE_VG)
         {
@@ -5610,11 +5159,19 @@ OnError:
         else
 #endif
         {
+#if gcdPROCESS_ADDRESS_SPACE
+            /* Allocate pages inside the page table. */
+            gcmkERR_BREAK(gckMMU_AllocatePages(mmu,
+                                              pageCount * (PAGE_SIZE/4096),
+                                              (gctPOINTER *) &pageTable,
+                                              &address));
+#else
             /* Allocate pages inside the page table. */
             gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernels[Core]->mmu,
                                               pageCount * (PAGE_SIZE/4096),
                                               (gctPOINTER *) &pageTable,
                                               &address));
+#endif
         }
 
         /* Fill the page table. */
@@ -5623,37 +5180,63 @@ OnError:
             gctUINT32 phys;
             gctUINT32_PTR tab = pageTable + i * (PAGE_SIZE/4096);
 
+#if gcdPROCESS_ADDRESS_SPACE
+            gckMMU_GetPageEntry(mmu, address + i * 4096, &tab);
+#endif
             phys = page_to_phys(pages[i]);
 
-#if gcdENABLE_VG
-            if (Core == gcvCORE_VG)
+#ifdef CONFIG_IOMMU_SUPPORT
+            if (Os->iommu)
             {
-                /* Get the physical address from page struct. */
-                gcmkONERROR(
-                    gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
-                                   phys,
-                                   tab));
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_INFO, gcvZONE_OS,
+                    "%s(%d): Setup mapping in IOMMU %x => %x",
+                    __FUNCTION__, __LINE__,
+                    Address + (i * PAGE_SIZE), phys
+                    );
+
+                gcmkONERROR(gckIOMMU_Map(
+                    Os->iommu, address + i * PAGE_SIZE, phys, PAGE_SIZE));
             }
             else
 #endif
             {
-                /* Get the physical address from page struct. */
-                gcmkONERROR(
-                    gckMMU_SetPage(Os->device->kernels[Core]->mmu,
-                                   phys,
-                                   tab));
-            }
 
-            for (j = 1; j < (PAGE_SIZE/4096); j++)
-            {
-                pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
+#if gcdENABLE_VG
+                if (Core == gcvCORE_VG)
+                {
+                    gcmkVERIFY_OK(
+                        gckOS_CPUPhysicalToGPUPhysical(Os, phys, &phys));
+
+                    /* Get the physical address from page struct. */
+                    gcmkONERROR(
+                        gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
+                                       phys,
+                                       tab));
+                }
+                else
+#endif
+                {
+                    /* Get the physical address from page struct. */
+                    gcmkONERROR(
+                        gckMMU_SetPage(Os->device->kernels[Core]->mmu,
+                                       phys,
+                                       tab));
+                }
+
+                for (j = 1; j < (PAGE_SIZE/4096); j++)
+                {
+                    pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
+                }
             }
 
+#if !gcdPROCESS_ADDRESS_SPACE
             gcmkTRACE_ZONE(
                 gcvLEVEL_INFO, gcvZONE_OS,
                 "%s(%d): pageTable[%d]: 0x%X 0x%X.",
                 __FUNCTION__, __LINE__,
                 i, phys, pageTable[i]);
+#endif
         }
 
 #if gcdENABLE_VG
@@ -5664,8 +5247,15 @@ OnError:
         else
 #endif
         {
-            gcmkONERROR(gckMMU_Flush(Os->device->kernels[Core]->mmu));
+#if gcdPROCESS_ADDRESS_SPACE
+            info->mmu = mmu;
+            gcmkONERROR(gckMMU_Flush(mmu));
+#else
+            gcmkONERROR(gckMMU_Flush(Os->device->kernels[Core]->mmu, gcvSURF_TYPE_UNKNOWN));
+#endif
         }
+#endif
+        info->address = address;
 
         /* Save pointer to page table. */
         info->pageTable = pageTable;
@@ -5881,8 +5471,29 @@ OnError:
 
         MEMORY_MAP_LOCK(Os);
 
+#if !gcdSECURITY
         gcmkASSERT(info->pageTable != gcvNULL);
+#endif
+
+        if (info->extraPage)
+        {
+            pageCount += 1;
+        }
 
+#if gcdSECURITY
+        if (info->address > 0x80000000)
+        {
+            gckKERNEL_SecurityUnmapMemory(
+                Os->device->kernels[Core],
+                info->address,
+                pageCount
+                );
+        }
+        else
+        {
+            gcmkPRINT("Wrong address %s(%d) %x", __FUNCTION__, __LINE__, info->address);
+        }
+#else
 #if gcdENABLE_VG
         if (Core == gcvCORE_VG)
         {
@@ -5895,11 +5506,32 @@ OnError:
         else
 #endif
         {
-            /* Free the pages from the MMU. */
-            gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernels[Core]->mmu,
-                                          info->pageTable,
-                                          pageCount * (PAGE_SIZE/4096)
-                                          ));
+            /* Free the pages from the MMU. */
+#if gcdPROCESS_ADDRESS_SPACE
+            gcmkERR_BREAK(gckMMU_FreePagesEx(info->mmu,
+                info->address,
+                pageCount * (PAGE_SIZE/4096)
+                ));
+
+#else
+            gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernels[Core]->mmu,
+                                          info->pageTable,
+                                          pageCount * (PAGE_SIZE/4096)
+                                          ));
+#endif
+
+            gcmkERR_BREAK(gckOS_UnmapPages(
+                Os,
+                pageCount * (PAGE_SIZE/4096),
+                info->address
+                ));
+        }
+#endif
+
+        if (info->extraPage)
+        {
+            pageCount -= 1;
+            info->extraPage = 0;
         }
 
         /* Release the page cache. */
@@ -5919,7 +5551,10 @@ OnError:
                      SetPageDirty(pages[i]);
                 }
 
-                page_cache_release(pages[i]);
+                if (pfn_valid(page_to_pfn(pages[i])))
+                {
+                    page_cache_release(pages[i]);
+                }
             }
         }
 
@@ -5992,6 +5627,32 @@ gckOS_SuspendInterrupt(
     return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
 }
 
+#if gcdMULTI_GPU
+gceSTATUS
+gckOS_SuspendInterruptEx(
+    IN gckOS Os,
+    IN gceCORE Core
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    if (Core == gcvCORE_MAJOR)
+    {
+        disable_irq(Os->device->irqLine3D[gcvCORE_3D_0_ID]);
+        disable_irq(Os->device->irqLine3D[gcvCORE_3D_1_ID]);
+    }
+    else
+    {
+        disable_irq(Os->device->irqLines[Core]);
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+#else
 gceSTATUS
 gckOS_SuspendInterruptEx(
     IN gckOS Os,
@@ -6008,6 +5669,7 @@ gckOS_SuspendInterruptEx(
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 }
+#endif
 
 gceSTATUS
 gckOS_ResumeInterrupt(
@@ -6017,6 +5679,32 @@ gckOS_ResumeInterrupt(
     return gckOS_ResumeInterruptEx(Os, gcvCORE_MAJOR);
 }
 
+#if gcdMULTI_GPU
+gceSTATUS
+gckOS_ResumeInterruptEx(
+    IN gckOS Os,
+    IN gceCORE Core
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    if (Core == gcvCORE_MAJOR)
+    {
+        enable_irq(Os->device->irqLine3D[gcvCORE_3D_0_ID]);
+        enable_irq(Os->device->irqLine3D[gcvCORE_3D_1_ID]);
+    }
+    else
+    {
+        enable_irq(Os->device->irqLines[Core]);
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+#else
 gceSTATUS
 gckOS_ResumeInterruptEx(
     IN gckOS Os,
@@ -6033,6 +5721,7 @@ gckOS_ResumeInterruptEx(
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 }
+#endif
 
 gceSTATUS
 gckOS_MemCopy(
@@ -6075,128 +5764,6 @@ gckOS_ZeroMemory(
 ********************************* Cache Control ********************************
 *******************************************************************************/
 
-#if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
-static inline gceSTATUS
-outer_func(
-    gceCACHEOPERATION Type,
-    unsigned long Start,
-    unsigned long End
-    )
-{
-    switch (Type)
-    {
-        case gcvCACHE_CLEAN:
-            outer_clean_range(Start, End);
-            break;
-        case gcvCACHE_INVALIDATE:
-            outer_inv_range(Start, End);
-            break;
-        case gcvCACHE_FLUSH:
-            outer_flush_range(Start, End);
-            break;
-        default:
-            return gcvSTATUS_INVALID_ARGUMENT;
-            break;
-    }
-    return gcvSTATUS_OK;
-}
-
-#if gcdENABLE_OUTER_CACHE_PATCH
-/*******************************************************************************
-**  _HandleOuterCache
-**
-**  Handle the outer cache for the specified addresses.
-**
-**  ARGUMENTS:
-**
-**      gckOS Os
-**          Pointer to gckOS object.
-**
-**      gctUINT32 ProcessID
-**          Process ID Logical belongs.
-**
-**      gctPHYS_ADDR Handle
-**          Physical address handle.  If gcvNULL it is video memory.
-**
-**      gctPOINTER Physical
-**          Physical address to flush.
-**
-**      gctPOINTER Logical
-**          Logical address to flush.
-**
-**      gctSIZE_T Bytes
-**          Size of the address range in bytes to flush.
-**
-**      gceOUTERCACHE_OPERATION Type
-**          Operation need to be execute.
-*/
-static gceSTATUS
-_HandleOuterCache(
-    IN gckOS Os,
-    IN gctUINT32 ProcessID,
-    IN gctPHYS_ADDR Handle,
-    IN gctPOINTER Physical,
-    IN gctPOINTER Logical,
-    IN gctSIZE_T Bytes,
-    IN gceCACHEOPERATION Type
-    )
-{
-    gceSTATUS status;
-    gctUINT32 i, pageNum;
-    unsigned long paddr;
-    gctPOINTER vaddr;
-
-    gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
-                   Os, ProcessID, Handle, Logical, Bytes);
-
-    if (Physical != gcvNULL)
-    {
-        /* Non paged memory or gcvPOOL_USER surface */
-        paddr = (unsigned long) Physical;
-        gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
-    }
-    else if ((Handle == gcvNULL)
-    || (Handle != gcvNULL && ((PLINUX_MDL)Handle)->contiguous)
-    )
-    {
-        /* Video Memory or contiguous virtual memory */
-        gcmkONERROR(gckOS_GetPhysicalAddress(Os, Logical, (gctUINT32*)&paddr));
-        gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
-    }
-    else
-    {
-        /* Non contiguous virtual memory */
-        vaddr = (gctPOINTER)gcmALIGN_BASE((gctUINTPTR_T)Logical, PAGE_SIZE);
-        pageNum = GetPageCount(Bytes, 0);
-
-        for (i = 0; i < pageNum; i += 1)
-        {
-            gcmkONERROR(_ConvertLogical2Physical(
-                Os,
-                vaddr + PAGE_SIZE * i,
-                ProcessID,
-                (PLINUX_MDL)Handle,
-                (gctUINT32*)&paddr
-                ));
-
-            gcmkONERROR(outer_func(Type, paddr, paddr + PAGE_SIZE));
-        }
-    }
-
-    mb();
-
-    /* Success. */
-    gcmkFOOTER_NO();
-    return gcvSTATUS_OK;
-
-OnError:
-    /* Return the status. */
-    gcmkFOOTER();
-    return status;
-}
-#endif
-#endif
-
 /*******************************************************************************
 **  gckOS_CacheClean
 **
@@ -6229,11 +5796,13 @@ gckOS_CacheClean(
     IN gckOS Os,
     IN gctUINT32 ProcessID,
     IN gctPHYS_ADDR Handle,
-    IN gctPOINTER Physical,
+    IN gctUINT32 Physical,
     IN gctPOINTER Logical,
     IN gctSIZE_T Bytes
     )
 {
+    gcsPLATFORM * platform;
+
     gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
                    Os, ProcessID, Handle, Logical, Bytes);
 
@@ -6242,6 +5811,25 @@ gckOS_CacheClean(
     gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
     gcmkVERIFY_ARGUMENT(Bytes > 0);
 
+    platform = Os->device->platform;
+
+    if (platform && platform->ops->cache)
+    {
+        platform->ops->cache(
+            platform,
+            ProcessID,
+            Handle,
+            Physical,
+            Logical,
+            Bytes,
+            gcvCACHE_CLEAN
+            );
+
+        /* Success. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
 #ifdef CONFIG_ARM
 
@@ -6255,7 +5843,7 @@ gckOS_CacheClean(
 #if defined(CONFIG_OUTER_CACHE)
     /* Outer cache. */
 #if gcdENABLE_OUTER_CACHE_PATCH
-    _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_CLEAN);
+    _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_CLEAN);
 #else
     outer_clean_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
 #endif
@@ -6312,11 +5900,13 @@ gckOS_CacheInvalidate(
     IN gckOS Os,
     IN gctUINT32 ProcessID,
     IN gctPHYS_ADDR Handle,
-    IN gctPOINTER Physical,
+    IN gctUINT32 Physical,
     IN gctPOINTER Logical,
     IN gctSIZE_T Bytes
     )
 {
+    gcsPLATFORM * platform;
+
     gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
                    Os, ProcessID, Handle, Logical, Bytes);
 
@@ -6325,6 +5915,25 @@ gckOS_CacheInvalidate(
     gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
     gcmkVERIFY_ARGUMENT(Bytes > 0);
 
+    platform = Os->device->platform;
+
+    if (platform && platform->ops->cache)
+    {
+        platform->ops->cache(
+            platform,
+            ProcessID,
+            Handle,
+            Physical,
+            Logical,
+            Bytes,
+            gcvCACHE_INVALIDATE
+            );
+
+        /* Success. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
 #ifdef CONFIG_ARM
 
@@ -6338,7 +5947,7 @@ gckOS_CacheInvalidate(
 #if defined(CONFIG_OUTER_CACHE)
     /* Outer cache. */
 #if gcdENABLE_OUTER_CACHE_PATCH
-    _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
+    _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
 #else
     outer_inv_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
 #endif
@@ -6391,11 +6000,13 @@ gckOS_CacheFlush(
     IN gckOS Os,
     IN gctUINT32 ProcessID,
     IN gctPHYS_ADDR Handle,
-    IN gctPOINTER Physical,
+    IN gctUINT32 Physical,
     IN gctPOINTER Logical,
     IN gctSIZE_T Bytes
     )
 {
+    gcsPLATFORM * platform;
+
     gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
                    Os, ProcessID, Handle, Logical, Bytes);
 
@@ -6404,6 +6015,25 @@ gckOS_CacheFlush(
     gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
     gcmkVERIFY_ARGUMENT(Bytes > 0);
 
+    platform = Os->device->platform;
+
+    if (platform && platform->ops->cache)
+    {
+        platform->ops->cache(
+            platform,
+            ProcessID,
+            Handle,
+            Physical,
+            Logical,
+            Bytes,
+            gcvCACHE_FLUSH
+            );
+
+        /* Success. */
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
 #ifdef CONFIG_ARM
     /* Inner cache. */
@@ -6412,7 +6042,7 @@ gckOS_CacheFlush(
 #if defined(CONFIG_OUTER_CACHE)
     /* Outer cache. */
 #if gcdENABLE_OUTER_CACHE_PATCH
-    _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_FLUSH);
+    _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_FLUSH);
 #else
     outer_flush_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
 #endif
@@ -6515,7 +6145,7 @@ gckOS_Broadcast(
         /* Put GPU IDLE. */
         gcmkONERROR(
             gckHARDWARE_SetPowerManagementState(Hardware,
-#if gcdPOWER_SUSNPEND_WHEN_IDLE
+#if gcdPOWER_SUSPEND_WHEN_IDLE
                                                 gcvPOWER_SUSPEND_BROADCAST));
 #else
                                                 gcvPOWER_IDLE_BROADCAST));
@@ -6544,9 +6174,6 @@ gckOS_Broadcast(
 
     case gcvBROADCAST_GPU_STUCK:
         gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
-#if !gcdENABLE_RECOVERY
-        gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
-#endif
         gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
         break;
 
@@ -6555,6 +6182,24 @@ gckOS_Broadcast(
         gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
         gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
         break;
+
+    case gcvBROADCAST_OUT_OF_MEMORY:
+        gcmkTRACE_N(gcvLEVEL_INFO, 0, "gcvBROADCAST_OUT_OF_MEMORY\n");
+
+        status = _ShrinkMemory(Os);
+
+        if (status == gcvSTATUS_NOT_SUPPORTED)
+        {
+            goto OnError;
+        }
+
+        gcmkONERROR(status);
+
+        break;
+
+    default:
+        /* Skip unimplemented broadcast. */
+        break;
     }
 
     /* Success. */
@@ -6944,7 +6589,7 @@ gckOS_GetThreadID(
 **      gckOS Os
 **          Pointer to a gckOS object.
 **
-**      gckCORE Core
+**      gceCORE Core
 **          GPU whose power is set.
 **
 **      gctBOOL Clock
@@ -6965,172 +6610,54 @@ gckOS_SetGPUPower(
     IN gctBOOL Power
     )
 {
-    struct clk *clk_3dcore = Os->device->clk_3d_core;
-    struct clk *clk_3dshader = Os->device->clk_3d_shader;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-    struct clk *clk_3d_axi = Os->device->clk_3d_axi;
-#endif
-    struct clk *clk_2dcore = Os->device->clk_2d_core;
-    struct clk *clk_2d_axi = Os->device->clk_2d_axi;
-    struct clk *clk_vg_axi = Os->device->clk_vg_axi;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-    int ret;
-#endif
+    gcsPLATFORM * platform;
 
-    gctBOOL oldClockState = gcvFALSE;
-    gctBOOL oldPowerState = gcvFALSE;
+    gctBOOL powerChange = gcvFALSE;
+    gctBOOL clockChange = gcvFALSE;
 
     gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    platform = Os->device->platform;
 
-    if (Os->device->kernels[Core] != NULL)
+    powerChange = (Power != Os->powerStates[Core]);
+
+    clockChange = (Clock != Os->clockStates[Core]);
+
+    if (powerChange && (Power == gcvTRUE))
     {
-#if gcdENABLE_VG
-        if (Core == gcvCORE_VG)
+        if (platform && platform->ops->setPower)
         {
-            oldClockState = Os->device->kernels[Core]->vg->hardware->clockState;
-            oldPowerState = Os->device->kernels[Core]->vg->hardware->powerState;
-        }
-        else
-        {
-#endif
-            oldClockState = Os->device->kernels[Core]->hardware->clockState;
-            oldPowerState = Os->device->kernels[Core]->hardware->powerState;
-#if gcdENABLE_VG
-        }
-#endif
-    }
-       if((Power == gcvTRUE) && (oldPowerState == gcvFALSE))
-       {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-        if(!IS_ERR(Os->device->gpu_regulator)) {
-            ret = regulator_enable(Os->device->gpu_regulator);
-            if (ret != 0)
-                gckOS_Print("%s(%d): fail to enable pu regulator %d!\n",
-                    __FUNCTION__, __LINE__, ret);
+            gcmkVERIFY_OK(platform->ops->setPower(platform, Core, Power));
         }
-#else
-        imx_gpc_power_up_pu(true);
-#endif
 
-#ifdef CONFIG_PM
-               pm_runtime_get_sync(Os->device->pmdev);
-#endif
-       }
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
-    if (Clock == gcvTRUE) {
-        if (oldClockState == gcvFALSE) {
-            switch (Core) {
-            case gcvCORE_MAJOR:
-                clk_enable(clk_3dcore);
-                if (cpu_is_mx6q())
-                    clk_enable(clk_3dshader);
-                break;
-            case gcvCORE_2D:
-                clk_enable(clk_2dcore);
-                clk_enable(clk_2d_axi);
-                break;
-            case gcvCORE_VG:
-                clk_enable(clk_2dcore);
-                clk_enable(clk_vg_axi);
-                break;
-            default:
-                break;
-            }
-        }
-    } else {
-        if (oldClockState == gcvTRUE) {
-            switch (Core) {
-            case gcvCORE_MAJOR:
-                if (cpu_is_mx6q())
-                    clk_disable(clk_3dshader);
-                clk_disable(clk_3dcore);
-                break;
-           case gcvCORE_2D:
-                clk_disable(clk_2dcore);
-                clk_disable(clk_2d_axi);
-                break;
-            case gcvCORE_VG:
-                clk_disable(clk_2dcore);
-                clk_disable(clk_vg_axi);
-                break;
-            default:
-                break;
-            }
-        }
+        Os->powerStates[Core] = Power;
     }
-#else
-    if (Clock == gcvTRUE) {
-        if (oldClockState == gcvFALSE) {
-            switch (Core) {
-            case gcvCORE_MAJOR:
-                clk_prepare(clk_3dcore);
-                clk_enable(clk_3dcore);
-                clk_prepare(clk_3dshader);
-                clk_enable(clk_3dshader);
-                clk_prepare(clk_3d_axi);
-                clk_enable(clk_3d_axi);
-                break;
-            case gcvCORE_2D:
-                clk_prepare(clk_2dcore);
-                clk_enable(clk_2dcore);
-                clk_prepare(clk_2d_axi);
-                clk_enable(clk_2d_axi);
-                break;
-            case gcvCORE_VG:
-                clk_prepare(clk_2dcore);
-                clk_enable(clk_2dcore);
-                clk_prepare(clk_vg_axi);
-                clk_enable(clk_vg_axi);
-                break;
-            default:
-                break;
-            }
-        }
-    } else {
-        if (oldClockState == gcvTRUE) {
-            switch (Core) {
-            case gcvCORE_MAJOR:
-                clk_disable(clk_3dshader);
-                clk_unprepare(clk_3dshader);
-                clk_disable(clk_3dcore);
-                clk_unprepare(clk_3dcore);
-                clk_disable(clk_3d_axi);
-                clk_unprepare(clk_3d_axi);
-                break;
-           case gcvCORE_2D:
-                clk_disable(clk_2dcore);
-                clk_unprepare(clk_2dcore);
-                clk_disable(clk_2d_axi);
-                clk_unprepare(clk_2d_axi);
-                break;
-            case gcvCORE_VG:
-                clk_disable(clk_2dcore);
-                clk_unprepare(clk_2dcore);
-                clk_disable(clk_vg_axi);
-                clk_unprepare(clk_vg_axi);
-                break;
-            default:
-                break;
-            }
+
+    if (clockChange)
+    {
+        mutex_lock(&Os->registerAccessLocks[Core]);
+
+        if (platform && platform->ops->setClock)
+        {
+            gcmkVERIFY_OK(platform->ops->setClock(platform, Core, Clock));
         }
+
+        Os->clockStates[Core] = Clock;
+
+        mutex_unlock(&Os->registerAccessLocks[Core]);
     }
-#endif
-       if((Power == gcvFALSE) && (oldPowerState == gcvTRUE))
-       {
-#ifdef CONFIG_PM
-               pm_runtime_put_sync(Os->device->pmdev);
-#endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-        if(!IS_ERR(Os->device->gpu_regulator))
-            regulator_disable(Os->device->gpu_regulator);
-#else
-        imx_gpc_power_up_pu(false);
-#endif
+    if (powerChange && (Power == gcvFALSE))
+    {
+        if (platform && platform->ops->setPower)
+        {
+            gcmkVERIFY_OK(platform->ops->setPower(platform, Core, Power));
+        }
+
+        Os->powerStates[Core] = Power;
+    }
 
-       }
-    /* TODO: Put your code here. */
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
 }
@@ -7159,41 +6686,21 @@ gckOS_ResetGPU(
     IN gceCORE Core
     )
 {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
-#define SRC_SCR_OFFSET 0
-#define BP_SRC_SCR_GPU3D_RST 1
-#define BP_SRC_SCR_GPU2D_RST 4
-    void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
-    gctUINT32 bit_offset,val;
+    gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
+    gcsPLATFORM * platform;
 
     gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
 
-    if(Core == gcvCORE_MAJOR) {
-        bit_offset = BP_SRC_SCR_GPU3D_RST;
-    } else if((Core == gcvCORE_VG)
-            ||(Core == gcvCORE_2D)) {
-        bit_offset = BP_SRC_SCR_GPU2D_RST;
-    } else {
-        return gcvSTATUS_INVALID_CONFIG;
-    }
-    val = __raw_readl(src_base + SRC_SCR_OFFSET);
-    val &= ~(1 << (bit_offset));
-    val |= (1 << (bit_offset));
-    __raw_writel(val, src_base + SRC_SCR_OFFSET);
+    platform = Os->device->platform;
 
-    while ((__raw_readl(src_base + SRC_SCR_OFFSET) &
-                (1 << (bit_offset))) != 0) {
+    if (platform && platform->ops->reset)
+    {
+        status = platform->ops->reset(platform, Core);
     }
 
     gcmkFOOTER_NO();
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-       struct reset_control *rstc = Os->device->rstc[Core];
-       if (rstc)
-               reset_control_reset(rstc);
-#else
-    imx_src_reset_gpu((int)Core);
-#endif
-    return gcvSTATUS_OK;
+    return status;
 }
 
 /*******************************************************************************
@@ -7656,7 +7163,11 @@ gckOS_Signal(
     else
     {
         /* Set the event to an unsignaled state. */
-       reinit_completion(&signal->obj);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
+        reinit_completion(&signal->obj);
+#else
+        INIT_COMPLETION(signal->obj);
+#endif
     }
 
     gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
@@ -7851,17 +7362,9 @@ gckOS_WaitSignal(
     else
     {
         /* Convert wait to milliseconds. */
-#if gcdDETECT_TIMEOUT
-        gctINT timeout = (Wait == gcvINFINITE)
-            ? gcdINFINITE_TIMEOUT * HZ / 1000
-            : Wait * HZ / 1000;
-
-        gctUINT complained = 0;
-#else
-        gctINT timeout = (Wait == gcvINFINITE)
+        long timeout = (Wait == gcvINFINITE)
             ? MAX_SCHEDULE_TIMEOUT
             : Wait * HZ / 1000;
-#endif
 
         DECLARE_WAITQUEUE(wait, current);
         wait.flags |= WQ_FLAG_EXCLUSIVE;
@@ -7892,49 +7395,6 @@ gckOS_WaitSignal(
                 break;
             }
 
-#if gcdDETECT_TIMEOUT
-            if ((Wait == gcvINFINITE) && (timeout == 0))
-            {
-                gctUINT32 dmaAddress1, dmaAddress2;
-                gctUINT32 dmaState1, dmaState2;
-
-                dmaState1   = dmaState2   =
-                dmaAddress1 = dmaAddress2 = 0;
-
-                /* Verify whether DMA is running. */
-                gcmkVERIFY_OK(_VerifyDMA(
-                    Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
-                    ));
-
-#if gcdDETECT_DMA_ADDRESS
-                /* Dump only if DMA appears stuck. */
-                if (
-                    (dmaAddress1 == dmaAddress2)
-#if gcdDETECT_DMA_STATE
-                 && (dmaState1   == dmaState2)
-#endif
-                )
-#endif
-                {
-                    /* Increment complain count. */
-                    complained += 1;
-
-                    gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
-
-                    gcmkPRINT(
-                        "%s(%d): signal 0x%X; forced message flush (%d).",
-                        __FUNCTION__, __LINE__, Signal, complained
-                        );
-
-                    /* Flush the debug cache. */
-                    gcmkDEBUGFLUSH(dmaAddress2);
-                }
-
-                /* Reset timeout. */
-                timeout = gcdINFINITE_TIMEOUT * HZ / 1000;
-            }
-#endif
-
             if (timeout == 0)
             {
 
@@ -7944,16 +7404,6 @@ gckOS_WaitSignal(
         }
 
         __remove_wait_queue(&signal->obj.wait, &wait);
-
-#if gcdDETECT_TIMEOUT
-        if (complained)
-        {
-            gcmkPRINT(
-                "%s(%d): signal=0x%X; waiting done; status=%d",
-                __FUNCTION__, __LINE__, Signal, status
-                );
-        }
-#endif
     }
 
     spin_unlock_irq(&signal->obj.wait.lock);
@@ -8022,17 +7472,17 @@ OnError:
 
 /*******************************************************************************
 **
-**     gckOS_UnmapSignal
+**  gckOS_UnmapSignal
 **
-**     Unmap a signal .
+**  Unmap a signal .
 **
-**     INPUT:
+**  INPUT:
 **
-**             gckOS Os
-**                     Pointer to an gckOS object.
+**      gckOS Os
+**          Pointer to an gckOS object.
 **
-**             gctSIGNAL Signal
-**                     Pointer to that gctSIGNAL mapped.
+**      gctSIGNAL Signal
+**          Pointer to that gctSIGNAL mapped.
 */
 gceSTATUS
 gckOS_UnmapSignal(
@@ -8076,9 +7526,10 @@ gckOS_CreateUserSignal(
     gctSIZE_T signal;
 
     /* Create a new signal. */
-    status = gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal);
+    gcmkONERROR(gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal));
     *SignalID = (gctINT) signal;
 
+OnError:
     return status;
 }
 
@@ -8191,11 +7642,11 @@ gckOS_CreateSemaphoreVG(
     do
     {
         /* Allocate the semaphore structure. */
-       newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
-       if (newSemaphore == gcvNULL)
-       {
-               gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
-       }
+        newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
+        if (newSemaphore == gcvNULL)
+        {
+            gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
+        }
 
         /* Initialize the semaphore. */
         sema_init(newSemaphore, 0);
@@ -8592,22 +8043,21 @@ gckOS_StartTimer(
 
     timer = (gcsOSTIMER_PTR)Timer;
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+    mod_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
+#else
     if (unlikely(delayed_work_pending(&timer->work)))
     {
-        if (unlikely(!cancel_delayed_work(&timer->work)))
-        {
-            cancel_work_sync(&timer->work.work);
-
-            if (unlikely(delayed_work_pending(&timer->work)))
-            {
-                gckOS_Print("gckOS_StartTimer error, the pending worker cannot complete!!!! \n");
-
-                return gcvSTATUS_INVALID_REQUEST;
-            }
-        }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+        cancel_delayed_work_sync(&timer->work);
+#else
+        cancel_delayed_work(&timer->work);
+        flush_workqueue(Os->workqueue);
+#endif
     }
 
     queue_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
+#endif
 
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
@@ -8651,23 +8101,6 @@ gckOS_StopTimer(
     return gcvSTATUS_OK;
 }
 
-
-gceSTATUS
-gckOS_DumpCallStack(
-    IN gckOS Os
-    )
-{
-    gcmkHEADER_ARG("Os=0x%X", Os);
-
-    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
-
-    dump_stack();
-
-    gcmkFOOTER_NO();
-    return gcvSTATUS_OK;
-}
-
-
 gceSTATUS
 gckOS_GetProcessNameByPid(
     IN gctINT Pid,
@@ -8696,6 +8129,56 @@ gckOS_GetProcessNameByPid(
     return gcvSTATUS_OK;
 }
 
+gceSTATUS
+gckOS_DumpCallStack(
+    IN gckOS Os
+    )
+{
+    gcmkHEADER_ARG("Os=0x%X", Os);
+
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+    dump_stack();
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+**  gckOS_DetectProcessByName
+**
+**      task->comm maybe part of process name, so this function
+**      can only be used for debugging.
+**
+**  INPUT:
+**
+**      gctCONST_POINTER Name
+**          Pointer to a string to hold name to be check. If the length
+**          of name is longer than TASK_COMM_LEN (16), use part of name
+**          to detect.
+**
+**  OUTPUT:
+**
+**      gcvSTATUS_TRUE if name of current process matches Name.
+**
+*/
+gceSTATUS
+gckOS_DetectProcessByName(
+    IN gctCONST_POINTER Name
+    )
+{
+    char comm[sizeof(current->comm)];
+
+    memset(comm, 0, sizeof(comm));
+
+    gcmkVERIFY_OK(
+        gckOS_GetProcessNameByPid(_GetProcessID(), sizeof(current->comm), comm));
+
+    return strstr(comm, Name) ? gcvSTATUS_TRUE
+                              : gcvSTATUS_FALSE;
+}
+
 #if gcdANDROID_NATIVE_FENCE_SYNC
 
 gceSTATUS
@@ -8834,6 +8317,7 @@ gckOS_SignalSyncPoint(
 {
     gceSTATUS status;
     gcsSYNC_POINT_PTR syncPoint;
+    struct sync_timeline * timeline;
     gctBOOL acquired = gcvFALSE;
 
     gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
@@ -8852,18 +8336,21 @@ gckOS_SignalSyncPoint(
 
     gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
 
-    /* Get state. */
-    atomic_set(&syncPoint->state, gcvTRUE);
+    /* Set signaled state. */
+    atomic_set(&syncPoint->state, 1);
 
-    /* Signal timeline. */
-    if (syncPoint->timeline)
-    {
-        sync_timeline_signal(syncPoint->timeline);
-    }
+    /* Get parent timeline. */
+    timeline = syncPoint->timeline;
 
     gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
     acquired = gcvFALSE;
 
+    /* Signal timeline. */
+    if (timeline)
+    {
+        sync_timeline_signal(timeline);
+    }
+
     /* Success. */
     gcmkFOOTER_NO();
     return gcvSTATUS_OK;
@@ -9031,3 +8518,223 @@ OnError:
     return status;
 }
 #endif
+
+#if gcdSECURITY
+gceSTATUS
+gckOS_AllocatePageArray(
+    IN gckOS Os,
+    IN gctPHYS_ADDR Physical,
+    IN gctSIZE_T PageCount,
+    OUT gctPOINTER * PageArrayLogical,
+    OUT gctPHYS_ADDR * PageArrayPhysical
+    )
+{
+    gceSTATUS status = gcvSTATUS_OK;
+    PLINUX_MDL  mdl;
+    gctUINT32*  table;
+    gctUINT32   offset;
+    gctSIZE_T   bytes;
+    gckALLOCATOR allocator;
+
+    gcmkHEADER_ARG("Os=0x%X Physical=0x%X PageCount=%u",
+                   Os, Physical, PageCount);
+
+    /* Verify the arguments. */
+    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+    gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+    gcmkVERIFY_ARGUMENT(PageCount > 0);
+
+    bytes = PageCount * gcmSIZEOF(gctUINT32);
+    gcmkONERROR(gckOS_AllocateNonPagedMemory(
+        Os,
+        gcvFALSE,
+        &bytes,
+        PageArrayPhysical,
+        PageArrayLogical
+        ));
+
+    table = *PageArrayLogical;
+
+    /* Convert pointer to MDL. */
+    mdl = (PLINUX_MDL)Physical;
+
+    allocator = mdl->allocator;
+
+     /* Get all the physical addresses and store them in the page table. */
+
+    offset = 0;
+    PageCount = PageCount / (PAGE_SIZE / 4096);
+
+    /* Try to get the user pages so DMA can happen. */
+    while (PageCount-- > 0)
+    {
+        unsigned long phys = ~0;
+
+        if (mdl->pagedMem && !mdl->contiguous)
+        {
+            if (allocator)
+            {
+                gctUINT32 phys_addr;
+                allocator->ops->Physical(allocator, mdl, offset, &phys_addr);
+                phys = (unsigned long)phys_addr;
+            }
+        }
+        else
+        {
+            if (!mdl->pagedMem)
+            {
+                gcmkTRACE_ZONE(
+                    gcvLEVEL_INFO, gcvZONE_OS,
+                    "%s(%d): we should not get this call for Non Paged Memory!",
+                    __FUNCTION__, __LINE__
+                    );
+            }
+
+            phys = page_to_phys(nth_page(mdl->u.contiguousPages, offset));
+        }
+
+        table[offset] = phys;
+
+        offset += 1;
+    }
+
+OnError:
+
+    /* Return the status. */
+    gcmkFOOTER();
+    return status;
+}
+#endif
+
+gceSTATUS
+gckOS_CPUPhysicalToGPUPhysical(
+    IN gckOS Os,
+    IN gctUINT32 CPUPhysical,
+    IN gctUINT32_PTR GPUPhysical
+    )
+{
+    gcsPLATFORM * platform;
+    gcmkHEADER_ARG("CPUPhysical=0x%X", CPUPhysical);
+
+    platform = Os->device->platform;
+
+    if (platform && platform->ops->getGPUPhysical)
+    {
+        gcmkVERIFY_OK(
+            platform->ops->getGPUPhysical(platform, CPUPhysical, GPUPhysical));
+    }
+    else
+    {
+        *GPUPhysical = CPUPhysical;
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_GPUPhysicalToCPUPhysical(
+    IN gckOS Os,
+    IN gctUINT32 GPUPhysical,
+    IN gctUINT32_PTR CPUPhysical
+    )
+{
+    gcmkHEADER_ARG("GPUPhysical=0x%X", GPUPhysical);
+
+    *CPUPhysical = GPUPhysical;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_PhysicalToPhysicalAddress(
+    IN gckOS Os,
+    IN gctPOINTER Physical,
+    OUT gctUINT32 * PhysicalAddress
+    )
+{
+    PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+    gckALLOCATOR allocator = mdl->allocator;
+
+    if (allocator)
+    {
+        return allocator->ops->Physical(allocator, mdl, 0, PhysicalAddress);
+    }
+
+    return gcvSTATUS_NOT_SUPPORTED;
+}
+
+gceSTATUS
+gckOS_QueryOption(
+    IN gckOS Os,
+    IN gctCONST_STRING Option,
+    OUT gctUINT32 * Value
+    )
+{
+    gckGALDEVICE device = Os->device;
+
+    if (!strcmp(Option, "physBase"))
+    {
+        *Value = device->physBase;
+        return gcvSTATUS_OK;
+    }
+    else if (!strcmp(Option, "physSize"))
+    {
+        *Value = device->physSize;
+        return gcvSTATUS_OK;
+    }
+    else if (!strcmp(Option, "mmu"))
+    {
+#if gcdSECURITY
+        *Value = 0;
+#else
+        *Value = device->mmu;
+#endif
+        return gcvSTATUS_OK;
+    }
+
+    return gcvSTATUS_NOT_SUPPORTED;
+}
+
+static int
+fd_release(
+    struct inode *inode,
+    struct file *file
+    )
+{
+    gcsFDPRIVATE_PTR private = (gcsFDPRIVATE_PTR)file->private_data;
+
+    if (private && private->release)
+    {
+        return private->release(private);
+    }
+
+    return 0;
+}
+
+static const struct file_operations fd_fops = {
+    .release = fd_release,
+};
+
+gceSTATUS
+gckOS_GetFd(
+    IN gctSTRING Name,
+    IN gcsFDPRIVATE_PTR Private,
+    OUT gctINT *Fd
+    )
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+    *Fd = anon_inode_getfd(Name, &fd_fops, Private, O_RDWR);
+
+    if (*Fd < 0)
+    {
+        return gcvSTATUS_OUT_OF_RESOURCES;
+    }
+
+    return gcvSTATUS_OK;
+#else
+    return gcvSTATUS_NOT_SUPPORTED;
+#endif
+}
+
index b22081740fdbd3b1b7e8471974e4c4d1b1b2e503..9d3126d1d77297814c2d5f0fac45f24a097c092e 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -36,7 +36,6 @@ typedef struct _LINUX_MDL_MAP * PLINUX_MDL_MAP;
 
 typedef struct _LINUX_MDL
 {
-    gctINT                  pid;
     char *                  addr;
 
     union _pages
@@ -62,6 +61,14 @@ typedef struct _LINUX_MDL
     PLINUX_MDL_MAP          maps;
     struct _LINUX_MDL *     prev;
     struct _LINUX_MDL *     next;
+
+    /* Pointer to allocator which allocates memory for this mdl. */
+    void *                  allocator;
+
+    /* Private data used by allocator. */
+    void *                  priv;
+
+    uint                    gid;
 }
 LINUX_MDL, *PLINUX_MDL;
 
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h
new file mode 100644 (file)
index 0000000..23b7178
--- /dev/null
@@ -0,0 +1,279 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2014 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_platform_h_
+#define _gc_hal_kernel_platform_h_
+#include <linux/mm.h>
+
+typedef struct _gcsMODULE_PARAMETERS
+{
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
+    gctINT  irqLine3D0;
+    gctUINT registerMemBase3D0;
+    gctUINT registerMemSize3D0;
+    gctINT  irqLine3D1;
+    gctUINT registerMemBase3D1;
+    gctUINT registerMemSize3D1;
+#else
+    gctINT  irqLine;
+    gctUINT registerMemBase;
+    gctUINT registerMemSize;
+#endif
+    gctINT  irqLine2D;
+    gctUINT registerMemBase2D;
+    gctUINT registerMemSize2D;
+    gctINT  irqLineVG;
+    gctUINT registerMemBaseVG;
+    gctUINT registerMemSizeVG;
+    gctUINT contiguousSize;
+    gctUINT contiguousBase;
+    gctUINT contiguousRequested;
+    gctUINT bankSize;
+    gctINT  fastClear;
+    gctINT  compression;
+    gctINT  powerManagement;
+    gctINT  gpuProfiler;
+    gctINT  signal;
+    gctUINT baseAddress;
+    gctUINT physSize;
+    gctUINT logFileSize;
+    gctUINT recovery;
+    gctUINT stuckDump;
+    gctUINT showArgs;
+    gctUINT gpu3DMinClock;
+}
+gcsMODULE_PARAMETERS;
+
+typedef struct _gcsPLATFORM * gckPLATFORM;
+
+typedef struct _gcsPLATFORM_OPERATIONS
+{
+    /*******************************************************************************
+    **
+    **  needAddDevice
+    **
+    **  Determine whether platform_device is created by initialization code.
+    **  If platform_device is created by BSP, return gcvFLASE here.
+    */
+    gctBOOL
+    (*needAddDevice)(
+        IN gckPLATFORM Platform
+        );
+
+    /*******************************************************************************
+    **
+    **  adjustParam
+    **
+    **  Override content of arguments, if a argument is not changed here, it will
+    **  keep as default value or value set by insmod command line.
+    */
+    gceSTATUS
+    (*adjustParam)(
+        IN gckPLATFORM Platform,
+        OUT gcsMODULE_PARAMETERS *Args
+        );
+
+    /*******************************************************************************
+    **
+    **  adjustDriver
+    **
+    **  Override content of platform_driver which will be registered.
+    */
+    gceSTATUS
+    (*adjustDriver)(
+        IN gckPLATFORM Platform
+        );
+
+    /*******************************************************************************
+    **
+    **  getPower
+    **
+    **  Prepare power and clock operation.
+    */
+    gceSTATUS
+    (*getPower)(
+        IN gckPLATFORM Platform
+        );
+
+    /*******************************************************************************
+    **
+    **  putPower
+    **
+    **  Finish power and clock operation.
+    */
+    gceSTATUS
+    (*putPower)(
+        IN gckPLATFORM Platform
+        );
+
+    /*******************************************************************************
+    **
+    **  allocPriv
+    **
+    **  Construct platform private data.
+    */
+    gceSTATUS
+    (*allocPriv)(
+        IN gckPLATFORM Platform
+        );
+
+    /*******************************************************************************
+    **
+    **  freePriv
+    **
+    **  free platform private data.
+    */
+    gceSTATUS
+    (*freePriv)(
+        IN gckPLATFORM Platform
+        );
+
+    /*******************************************************************************
+    **
+    **  setPower
+    **
+    **  Set power state of specified GPU.
+    **
+    **  INPUT:
+    **
+    **      gceCORE GPU
+    **          GPU neeed to config.
+    **
+    **      gceBOOL Enable
+    **          Enable or disable power.
+    */
+    gceSTATUS
+    (*setPower)(
+        IN gckPLATFORM Platform,
+        IN gceCORE GPU,
+        IN gctBOOL Enable
+        );
+
+    /*******************************************************************************
+    **
+    **  setClock
+    **
+    **  Set clock state of specified GPU.
+    **
+    **  INPUT:
+    **
+    **      gceCORE GPU
+    **          GPU neeed to config.
+    **
+    **      gceBOOL Enable
+    **          Enable or disable clock.
+    */
+    gceSTATUS
+    (*setClock)(
+        IN gckPLATFORM Platform,
+        IN gceCORE GPU,
+        IN gctBOOL Enable
+        );
+
+    /*******************************************************************************
+    **
+    **  reset
+    **
+    **  Reset GPU outside.
+    **
+    **  INPUT:
+    **
+    **      gceCORE GPU
+    **          GPU neeed to reset.
+    */
+    gceSTATUS
+    (*reset)(
+        IN gckPLATFORM Platform,
+        IN gceCORE GPU
+        );
+
+    /*******************************************************************************
+    **
+    **  getGPUPhysical
+    **
+    **  Convert CPU physical address to GPU physical address if they are
+    **  different.
+    */
+    gceSTATUS
+    (*getGPUPhysical)(
+        IN gckPLATFORM Platform,
+        IN gctUINT32 CPUPhysical,
+        OUT gctUINT32_PTR GPUPhysical
+        );
+
+    /*******************************************************************************
+    **
+    **  adjustProt
+    **
+    **  Override Prot flag when mapping paged memory to userspace.
+    */
+    gceSTATUS
+    (*adjustProt)(
+        IN struct vm_area_struct * vma
+        );
+
+    /*******************************************************************************
+    **
+    **  shrinkMemory
+    **
+    **  Do something to collect memory, eg, act as oom killer.
+    */
+    gceSTATUS
+    (*shrinkMemory)(
+        IN gckPLATFORM Platform
+        );
+
+    /*******************************************************************************
+    **
+    **  cache
+    **
+    **  Cache operation.
+    */
+    gceSTATUS
+    (*cache)(
+        IN gckPLATFORM Platform,
+        IN gctUINT32 ProcessID,
+        IN gctPHYS_ADDR Handle,
+        IN gctUINT32 Physical,
+        IN gctPOINTER Logical,
+        IN gctSIZE_T Bytes,
+        IN gceCACHEOPERATION Operation
+        );
+}
+gcsPLATFORM_OPERATIONS;
+
+typedef struct _gcsPLATFORM
+{
+    struct platform_device* device;
+    struct platform_driver* driver;
+
+    gcsPLATFORM_OPERATIONS* ops;
+
+    void*                   priv;
+}
+gcsPLATFORM;
+
+void
+gckPLATFORM_QueryOperations(
+    IN gcsPLATFORM_OPERATIONS ** Operations
+    );
+
+#endif
similarity index 62%
rename from drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
rename to drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_probe.c
index 3822f37a44e2cb3f80dde4ca61d05a8bb64fb68d..054e32e8f6a55a1b0794fcf4d4ac9bda38ef68dd 100644 (file)
@@ -1,7 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
-*    Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
+*    Copyright (C) 2005 - 2014 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
 *
 *****************************************************************************/
 
+
 #include <linux/device.h>
 #include <linux/slab.h>
-#include <linux/notifier.h>
+
 #include "gc_hal_kernel_linux.h"
 #include "gc_hal_driver.h"
 
 #endif
 
 
-#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
-#    include <linux/resmem_account.h>
-#    include <linux/kernel.h>
-#    include <linux/mm.h>
-#    include <linux/oom.h>
-#    include <linux/sched.h>
-#    include <linux/notifier.h>
-
-struct task_struct *lowmem_deathpending;
-
-static int
-task_notify_func(struct notifier_block *self, unsigned long val, void *data);
-
-static struct notifier_block task_nb = {
-       .notifier_call  = task_notify_func,
-};
-
-static int
-task_notify_func(struct notifier_block *self, unsigned long val, void *data)
-{
-       struct task_struct *task = data;
-
-       if (task == lowmem_deathpending)
-               lowmem_deathpending = NULL;
-
-       return NOTIFY_OK;
-}
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
-#include <mach/viv_gpu.h>
-#else
-#include <linux/pm_runtime.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-#include <mach/busfreq.h>
-#else
-#include <linux/reset.h>
-#endif
-#endif
 /* Zone used for header/footer. */
 #define _GC_OBJ_ZONE    gcvZONE_DRIVER
 
-#if gcdENABLE_FSCALE_VAL_ADJUST
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-#include <linux/device_cooling.h>
-#define REG_THERMAL_NOTIFIER(a) register_devfreq_cooling_notifier(a);
-#define UNREG_THERMAL_NOTIFIER(a) unregister_devfreq_cooling_notifier(a);
-#else
-extern int register_thermal_notifier(struct notifier_block *nb);
-extern int unregister_thermal_notifier(struct notifier_block *nb);
-#define REG_THERMAL_NOTIFIER(a) register_thermal_notifier(a);
-#define UNREG_THERMAL_NOTIFIER(a) unregister_thermal_notifier(a);
-#endif
-#endif
-
 MODULE_DESCRIPTION("Vivante Graphics Driver");
 MODULE_LICENSE("GPL");
 
 static struct class* gpuClass;
 
+static gcsPLATFORM platform;
+
 static gckGALDEVICE galDevice;
 
 static uint major = 199;
 module_param(major, uint, 0644);
 
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
+static int irqLine3D0 = -1;
+module_param(irqLine3D0, int, 0644);
+
+static ulong registerMemBase3D0 = 0;
+module_param(registerMemBase3D0, ulong, 0644);
+
+static ulong registerMemSize3D0 = 2 << 10;
+module_param(registerMemSize3D0, ulong, 0644);
+
+static int irqLine3D1 = -1;
+module_param(irqLine3D1, int, 0644);
+
+static ulong registerMemBase3D1 = 0;
+module_param(registerMemBase3D1, ulong, 0644);
+
+static ulong registerMemSize3D1 = 2 << 10;
+module_param(registerMemSize3D1, ulong, 0644);
+#else
 static int irqLine = -1;
 module_param(irqLine, int, 0644);
 
@@ -108,6 +77,7 @@ module_param(registerMemBase, ulong, 0644);
 
 static ulong registerMemSize = 2 << 10;
 module_param(registerMemSize, ulong, 0644);
+#endif
 
 static int irqLine2D = -1;
 module_param(irqLine2D, int, 0644);
@@ -127,11 +97,10 @@ module_param(registerMemBaseVG, ulong, 0644);
 static ulong registerMemSizeVG = 2 << 10;
 module_param(registerMemSizeVG, ulong, 0644);
 
-#if gcdENABLE_FSCALE_VAL_ADJUST
-static ulong contiguousSize = 128 << 20;
-#else
-static ulong contiguousSize = 4 << 20;
+#ifndef gcdDEFAULT_CONTIGUOUS_SIZE
+#define gcdDEFAULT_CONTIGUOUS_SIZE (4 << 20)
 #endif
+static ulong contiguousSize = gcdDEFAULT_CONTIGUOUS_SIZE;
 module_param(contiguousSize, ulong, 0644);
 
 static ulong contiguousBase = 0;
@@ -146,7 +115,7 @@ module_param(fastClear, int, 0644);
 static int compression = -1;
 module_param(compression, int, 0644);
 
-static int powerManagement = 1;
+static int powerManagement = -1;
 module_param(powerManagement, int, 0644);
 
 static int gpuProfiler = 0;
@@ -161,19 +130,27 @@ module_param(baseAddress, ulong, 0644);
 static ulong physSize = 0;
 module_param(physSize, ulong, 0644);
 
-static uint logFileSize=0;
+static uint logFileSize = 0;
 module_param(logFileSize,uint, 0644);
 
+static uint recovery = 1;
+module_param(recovery, uint, 0644);
+MODULE_PARM_DESC(recovery, "Recover GPU from stuck (1: Enable, 0: Disable)");
+
+/* Middle needs about 40KB buffer, Maximal may need more than 200KB buffer. */
+static uint stuckDump = 1;
+module_param(stuckDump, uint, 0644);
+MODULE_PARM_DESC(stuckDump, "Level of stuck dump content (1: Minimal, 2: Middle, 3: Maximal)");
+
 static int showArgs = 0;
 module_param(showArgs, int, 0644);
 
-int gpu3DMinClock = 0;
-module_param(gpu3DMinClock, int, 0644);
+static int mmu = 1;
+module_param(mmu, int, 0644);
 
-#if ENABLE_GPU_CLOCK_BY_DRIVER
-    unsigned long coreClock = 156000000;
-    module_param(coreClock, ulong, 0644);
-#endif
+static int gpu3DMinClock = 1;
+
+static int contiguousRequested = 0;
 
 static int drv_open(
     struct inode* inode,
@@ -208,29 +185,92 @@ static struct file_operations driver_fops =
     .mmap       = drv_mmap,
 };
 
-#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
-static size_t viv_gpu_resmem_query(struct task_struct *p, struct reserved_memory_account *m);
-static struct reserved_memory_account viv_gpu_resmem_handler = {
-    .name = "viv_gpu",
-    .get_page_used_by_process = viv_gpu_resmem_query,
-};
+void
+_UpdateModuleParam(
+    gcsMODULE_PARAMETERS *Param
+    )
+{
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
+#else
+    irqLine           = Param->irqLine ;
+    registerMemBase   = Param->registerMemBase;
+    registerMemSize   = Param->registerMemSize;
+#endif
+    irqLine2D         = Param->irqLine2D      ;
+    registerMemBase2D = Param->registerMemBase2D;
+    registerMemSize2D = Param->registerMemSize2D;
+    irqLineVG         = Param->irqLineVG;
+    registerMemBaseVG = Param->registerMemBaseVG;
+    registerMemSizeVG = Param->registerMemSizeVG;
+    contiguousSize    = Param->contiguousSize;
+    contiguousBase    = Param->contiguousBase;
+    bankSize          = Param->bankSize;
+    fastClear         = Param->fastClear;
+    compression       = Param->compression;
+    powerManagement   = Param->powerManagement;
+    gpuProfiler       = Param->gpuProfiler;
+    signal            = Param->signal;
+    baseAddress       = Param->baseAddress;
+    physSize          = Param->physSize;
+    logFileSize       = Param->logFileSize;
+    recovery          = Param->recovery;
+    stuckDump         = Param->stuckDump;
+    showArgs          = Param->showArgs;
+    contiguousRequested = Param->contiguousRequested;
+    gpu3DMinClock     = Param->gpu3DMinClock;
+}
 
-size_t viv_gpu_resmem_query(struct task_struct *p, struct reserved_memory_account *m)
+void
+gckOS_DumpParam(
+    void
+    )
 {
-    gcuDATABASE_INFO info;
-    unsigned int processid = p->pid;
-    gckKERNEL gpukernel = m->data;
+    printk("Galcore options:\n");
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
+    printk("  irqLine3D0         = %d\n",      irqLine3D0);
+    printk("  registerMemBase3D0 = 0x%08lX\n", registerMemBase3D0);
+    printk("  registerMemSize3D0 = 0x%08lX\n", registerMemSize3D0);
 
-    /* ignore error happens in this api. */
-    if (gckKERNEL_QueryProcessDB(gpukernel, processid, false, gcvDB_VIDEO_MEMORY, &info) != gcvSTATUS_OK)
-       return 0;
+    if (irqLine3D1 != -1)
+    {
+        printk("  irqLine3D1         = %d\n",      irqLine3D1);
+        printk("  registerMemBase3D1 = 0x%08lX\n", registerMemBase3D1);
+        printk("  registerMemSize3D1 = 0x%08lX\n", registerMemSize3D1);
+    }
+#else
+    printk("  irqLine           = %d\n",      irqLine);
+    printk("  registerMemBase   = 0x%08lX\n", registerMemBase);
+    printk("  registerMemSize   = 0x%08lX\n", registerMemSize);
+#endif
 
-    /* we return pages. */
-    if (info.counters.bytes > 0)
-       return info.counters.bytes / PAGE_SIZE;
-    return 0;
+    if (irqLine2D != -1)
+    {
+        printk("  irqLine2D         = %d\n",      irqLine2D);
+        printk("  registerMemBase2D = 0x%08lX\n", registerMemBase2D);
+        printk("  registerMemSize2D = 0x%08lX\n", registerMemSize2D);
+    }
+
+    if (irqLineVG != -1)
+    {
+        printk("  irqLineVG         = %d\n",      irqLineVG);
+        printk("  registerMemBaseVG = 0x%08lX\n", registerMemBaseVG);
+        printk("  registerMemSizeVG = 0x%08lX\n", registerMemSizeVG);
+    }
+
+    printk("  contiguousSize    = %ld\n",     contiguousSize);
+    printk("  contiguousBase    = 0x%08lX\n", contiguousBase);
+    printk("  bankSize          = 0x%08lX\n", bankSize);
+    printk("  fastClear         = %d\n",      fastClear);
+    printk("  compression       = %d\n",      compression);
+    printk("  signal            = %d\n",      signal);
+    printk("  powerManagement   = %d\n",      powerManagement);
+    printk("  baseAddress       = 0x%08lX\n", baseAddress);
+    printk("  physSize          = 0x%08lX\n", physSize);
+    printk("  logFileSize       = %d KB \n",  logFileSize);
+    printk("  recovery          = %d\n",      recovery);
+    printk("  stuckDump         = %d\n",      stuckDump);
+    printk("  gpuProfiler       = %d\n",      gpuProfiler);
 }
-#endif
 
 int drv_open(
     struct inode* inode,
@@ -255,7 +295,7 @@ int drv_open(
         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
     }
 
-    data = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL);
+    data = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL | __GFP_NOWARN);
 
     if (data == gcvNULL)
     {
@@ -285,12 +325,15 @@ int drv_open(
 
     if (!galDevice->contiguousMapped)
     {
-        gcmkONERROR(gckOS_MapMemory(
-            galDevice->os,
-            galDevice->contiguousPhysical,
-            galDevice->contiguousSize,
-            &data->contiguousLogical
-            ));
+        if (galDevice->contiguousPhysical != gcvNULL)
+        {
+            gcmkONERROR(gckOS_MapMemory(
+                galDevice->os,
+                galDevice->contiguousPhysical,
+                galDevice->contiguousSize,
+                &data->contiguousLogical
+                ));
+        }
     }
 
     filp->private_data = data;
@@ -429,6 +472,7 @@ long drv_ioctl(
     gckGALDEVICE device;
     gcsHAL_PRIVATE_DATA_PTR data;
     gctINT32 i, count;
+    gckVIDMEM_NODE nodeObject;
 
     gcmkHEADER_ARG(
         "filp=0x%08X ioctlCode=0x%08X arg=0x%08X",
@@ -558,7 +602,7 @@ long drv_ioctl(
     }
     else
     {
-        if (iface.hardwareType < 0 || iface.hardwareType > 7)
+        if (iface.hardwareType > 7)
         {
             gcmkTRACE_ZONE(
                 gcvLEVEL_ERROR, gcvZONE_DRIVER,
@@ -595,7 +639,17 @@ long drv_ioctl(
 
     if (gcmIS_SUCCESS(status) && (iface.command == gcvHAL_LOCK_VIDEO_MEMORY))
     {
-        gcuVIDMEM_NODE_PTR node = gcmUINT64_TO_PTR(iface.u.LockVideoMemory.node);
+        gcuVIDMEM_NODE_PTR node;
+        gctUINT32 processID;
+
+        gckOS_GetProcessID(&processID);
+
+        gcmkONERROR(gckVIDMEM_HANDLE_Lookup(device->kernels[device->coreMapping[iface.hardwareType]],
+                                processID,
+                                (gctUINT32)iface.u.LockVideoMemory.node,
+                                &nodeObject));
+        node = nodeObject->node;
+
         /* Special case for mapped memory. */
         if ((data->mappedMemory != gcvNULL)
         &&  (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
@@ -736,7 +790,6 @@ static int drv_mmap(
         return 0;
     }
 
-
 OnError:
     gcmkFOOTER();
     return -ENOTTY;
@@ -746,7 +799,7 @@ OnError:
 #if !USE_PLATFORM_DRIVER
 static int __init drv_init(void)
 #else
-static int drv_init(struct device *pdev)
+static int drv_init(void)
 #endif
 {
     int ret;
@@ -755,104 +808,49 @@ static int drv_init(struct device *pdev)
     gckGALDEVICE device = gcvNULL;
     struct class* device_class = gcvNULL;
 
-    gcmkHEADER();
-
-#if ENABLE_GPU_CLOCK_BY_DRIVER && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
-    {
-# if 0
-        struct clk * clk;
-
-        clk = clk_get(NULL, "GCCLK");
-
-        if (IS_ERR(clk))
-        {
-            gcmkTRACE_ZONE(
-                gcvLEVEL_ERROR, gcvZONE_DRIVER,
-                "%s(%d): clk get error: %d\n",
-                __FUNCTION__, __LINE__,
-                PTR_ERR(clk)
-                );
-
-            result = -ENODEV;
-            gcmkONERROR(gcvSTATUS_GENERIC_IO);
-        }
-
-        /*
-         * APMU_GC_156M, APMU_GC_312M, APMU_GC_PLL2, APMU_GC_PLL2_DIV2 currently.
-         * Use the 2X clock.
-         */
-        if (clk_set_rate(clk, coreClock * 2))
-        {
-            gcmkTRACE_ZONE(
-                gcvLEVEL_ERROR, gcvZONE_DRIVER,
-                "%s(%d): Failed to set core clock.\n",
-                __FUNCTION__, __LINE__
-                );
-
-            result = -EAGAIN;
-            gcmkONERROR(gcvSTATUS_GENERIC_IO);
-        }
-
-        clk_enable(clk);
+    gcsDEVICE_CONSTRUCT_ARGS args = {
+        .recovery           = recovery,
+        .stuckDump          = stuckDump,
+        .gpu3DMinClock      = gpu3DMinClock,
+        .contiguousRequested = contiguousRequested,
+        .platform           = &platform,
+        .mmu                = mmu,
+    };
 
-#if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
-        gc_pwr(1);
-#   endif
-# endif
-    }
-#endif
+    gcmkHEADER();
 
     printk(KERN_INFO "Galcore version %d.%d.%d.%d\n",
         gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
+
+#if !VIVANTE_PROFILER_PM
     /* when enable gpu profiler, we need to turn off gpu powerMangement */
-    if(gpuProfiler)
+    if (gpuProfiler)
+    {
         powerManagement = 0;
+    }
+#endif
+
     if (showArgs)
     {
-        printk("galcore options:\n");
-        printk("  irqLine           = %d\n",      irqLine);
-        printk("  registerMemBase   = 0x%08lX\n", registerMemBase);
-        printk("  registerMemSize   = 0x%08lX\n", registerMemSize);
-
-        if (irqLine2D != -1)
-        {
-            printk("  irqLine2D         = %d\n",      irqLine2D);
-            printk("  registerMemBase2D = 0x%08lX\n", registerMemBase2D);
-            printk("  registerMemSize2D = 0x%08lX\n", registerMemSize2D);
-        }
-
-        if (irqLineVG != -1)
-        {
-            printk("  irqLineVG         = %d\n",      irqLineVG);
-            printk("  registerMemBaseVG = 0x%08lX\n", registerMemBaseVG);
-            printk("  registerMemSizeVG = 0x%08lX\n", registerMemSizeVG);
-        }
-
-        printk("  contiguousSize    = %ld\n",     contiguousSize);
-        printk("  contiguousBase    = 0x%08lX\n", contiguousBase);
-        printk("  bankSize          = 0x%08lX\n", bankSize);
-        printk("  fastClear         = %d\n",      fastClear);
-        printk("  compression       = %d\n",      compression);
-        printk("  signal            = %d\n",      signal);
-        printk("  baseAddress       = 0x%08lX\n", baseAddress);
-        printk("  physSize          = 0x%08lX\n", physSize);
-        printk("  logFileSize       = %d KB \n",  logFileSize);
-        printk("  powerManagement   = %d\n",      powerManagement);
-        printk("  gpuProfiler   = %d\n",      gpuProfiler);
-#if ENABLE_GPU_CLOCK_BY_DRIVER
-        printk("  coreClock       = %lu\n",     coreClock);
-#endif
+        gckOS_DumpParam();
     }
 
-    if(logFileSize != 0)
+    if (logFileSize != 0)
     {
-       gckDebugFileSystemInitialize();
+        gckDEBUGFS_Initialize();
     }
 
     /* Create the GAL device. */
-    gcmkONERROR(gckGALDEVICE_Construct(
+    status = gckGALDEVICE_Construct(
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
+        irqLine3D0,
+        registerMemBase3D0, registerMemSize3D0,
+        irqLine3D1,
+        registerMemBase3D1, registerMemSize3D1,
+#else
         irqLine,
         registerMemBase, registerMemSize,
+#endif
         irqLine2D,
         registerMemBase2D, registerMemSize2D,
         irqLineVG,
@@ -860,15 +858,20 @@ static int drv_init(struct device *pdev)
         contiguousBase, contiguousSize,
         bankSize, fastClear, compression, baseAddress, physSize, signal,
         logFileSize,
-        pdev,
         powerManagement,
         gpuProfiler,
+        &args,
         &device
-        ));
+    );
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-       device->pool = dev_get_drvdata(pdev);
-#endif
+    if (gcmIS_ERROR(status))
+    {
+        gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+                       "%s(%d): Failed to create the GAL device: status=%d\n",
+                       __FUNCTION__, __LINE__, status);
+
+        goto OnError;
+    }
 
     /* Start the GAL device. */
     gcmkONERROR(gckGALDEVICE_Start(device));
@@ -877,31 +880,12 @@ static int drv_init(struct device *pdev)
        && (device->kernels[gcvCORE_MAJOR] != gcvNULL)
        && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0))
     {
-        status = gckMMU_Enable(device->kernels[gcvCORE_MAJOR]->mmu, baseAddress, physSize);
-        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
-            "Enable new MMU: status=%d\n", status);
-
-        if ((device->kernels[gcvCORE_2D] != gcvNULL)
-            && (device->kernels[gcvCORE_2D]->hardware->mmuVersion != 0))
-        {
-            status = gckMMU_Enable(device->kernels[gcvCORE_2D]->mmu, baseAddress, physSize);
-            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
-                "Enable new MMU for 2D: status=%d\n", status);
-        }
-
         /* Reset the base address */
         device->baseAddress = 0;
     }
 
-#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
-    task_free_register(&task_nb);
-    viv_gpu_resmem_handler.data = device->kernels[gcvCORE_MAJOR];
-    register_reserved_memory_account(&viv_gpu_resmem_handler);
-#endif
-
-
     /* Register the character device. */
-    ret = register_chrdev(major, DRV_NAME, &driver_fops);
+    ret = register_chrdev(major, DEVICE_NAME, &driver_fops);
 
     if (ret < 0)
     {
@@ -934,20 +918,29 @@ static int drv_init(struct device *pdev)
     }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
-    device_create(device_class, NULL, MKDEV(major, 0), NULL, "galcore");
+    device_create(device_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
 #else
-    device_create(device_class, NULL, MKDEV(major, 0), "galcore");
+    device_create(device_class, NULL, MKDEV(major, 0), DEVICE_NAME);
 #endif
 
     galDevice = device;
     gpuClass  = device_class;
 
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
+    gcmkTRACE_ZONE(
+        gcvLEVEL_INFO, gcvZONE_DRIVER,
+        "%s(%d): irqLine3D0=%d, contiguousSize=%lu, memBase3D0=0x%lX\n",
+        __FUNCTION__, __LINE__,
+        irqLine3D0, contiguousSize, registerMemBase3D0
+        );
+#else
     gcmkTRACE_ZONE(
         gcvLEVEL_INFO, gcvZONE_DRIVER,
         "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n",
         __FUNCTION__, __LINE__,
         irqLine, contiguousSize, registerMemBase
         );
+#endif
 
     /* Success. */
     gcmkFOOTER_NO();
@@ -979,38 +972,19 @@ static void drv_exit(void)
 {
     gcmkHEADER();
 
-#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
-    task_free_unregister(&task_nb);
-    unregister_reserved_memory_account(&viv_gpu_resmem_handler);
-#endif
-
     gcmkASSERT(gpuClass != gcvNULL);
     device_destroy(gpuClass, MKDEV(major, 0));
     class_destroy(gpuClass);
 
-    unregister_chrdev(major, DRV_NAME);
+    unregister_chrdev(major, DEVICE_NAME);
 
     gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice));
     gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice));
 
-   if(gckDebugFileSystemIsEnabled())
-   {
-        gckDebugFileSystemTerminate();
-   }
-
-#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+    if(gckDEBUGFS_IsEnabled())
     {
-# if 0
-        struct clk * clk = NULL;
-
-#if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
-        gc_pwr(0);
-#endif
-        clk = clk_get(NULL, "GCCLK");
-        clk_disable(clk);
-# endif
+        gckDEBUGFS_Terminate();
     }
-#endif
 
     gcmkFOOTER_NO();
 }
@@ -1020,40 +994,6 @@ static void drv_exit(void)
     module_exit(drv_exit);
 #else
 
-#ifdef CONFIG_DOVE_GPU
-#   define DEVICE_NAME "dove_gpu"
-#else
-#   define DEVICE_NAME "galcore"
-#endif
-
-#if gcdENABLE_FSCALE_VAL_ADJUST
-static int thermal_hot_pm_notify(struct notifier_block *nb, unsigned long event,
-       void *dummy)
-{
-    static gctUINT orgFscale, minFscale, maxFscale;
-    static gctBOOL bAlreadyTooHot = gcvFALSE;
-    gckHARDWARE hardware = galDevice->kernels[gcvCORE_MAJOR]->hardware;
-
-    if (event && !bAlreadyTooHot) {
-        gckHARDWARE_GetFscaleValue(hardware,&orgFscale,&minFscale, &maxFscale);
-        gckHARDWARE_SetFscaleValue(hardware, minFscale);
-        bAlreadyTooHot = gcvTRUE;
-        gckOS_Print("System is too hot. GPU3D will work at %d/64 clock.\n", minFscale);
-    } else if (!event && bAlreadyTooHot) {
-        gckHARDWARE_SetFscaleValue(hardware, orgFscale);
-        gckOS_Print("Hot alarm is canceled. GPU3D clock will return to %d/64\n", orgFscale);
-        bAlreadyTooHot = gcvFALSE;
-    }
-    return NOTIFY_OK;
-}
-
-static struct notifier_block thermal_hot_pm_notifier = {
-    .notifier_call = thermal_hot_pm_notify,
-    };
-#endif
-
-
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
 static int gpu_probe(struct platform_device *pdev)
 #else
@@ -1061,114 +1001,68 @@ static int __devinit gpu_probe(struct platform_device *pdev)
 #endif
 {
     int ret = -ENODEV;
-    struct resource* res;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-       struct contiguous_mem_pool *pool;
-       struct reset_control *rstc;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-       struct device_node *dn =pdev->dev.of_node;
-       const u32 *prop;
+    gcsMODULE_PARAMETERS moduleParam = {
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
 #else
-       struct viv_gpu_platform_data *pdata;
+        .irqLine            = irqLine,
+        .registerMemBase    = registerMemBase,
+        .registerMemSize    = registerMemSize,
 #endif
-    gcmkHEADER();
+        .irqLine2D          = irqLine2D,
+        .registerMemBase2D  = registerMemBase2D,
+        .registerMemSize2D  = registerMemSize2D,
+        .irqLineVG          = irqLineVG,
+        .registerMemBaseVG  = registerMemBaseVG,
+        .registerMemSizeVG  = registerMemSizeVG,
+        .contiguousSize     = contiguousSize,
+        .contiguousBase     = contiguousBase,
+        .bankSize           = bankSize,
+        .fastClear          = fastClear,
+        .compression        = compression,
+        .powerManagement    = powerManagement,
+        .gpuProfiler        = gpuProfiler,
+        .signal             = signal,
+        .baseAddress        = baseAddress,
+        .physSize           = physSize,
+        .logFileSize        = logFileSize,
+        .recovery           = recovery,
+        .stuckDump          = stuckDump,
+        .showArgs           = showArgs,
+        .gpu3DMinClock      = gpu3DMinClock,
+    };
 
-    res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phys_baseaddr");
-    if (res)
-        baseAddress = res->start;
+    gcmkHEADER();
 
-    res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_3d");
-    if (res)
-        irqLine = res->start;
+    platform.device = pdev;
 
-    res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_3d");
-    if (res)
+    if (platform.ops->getPower)
     {
-        registerMemBase = res->start;
-        registerMemSize = res->end - res->start + 1;
+        if (gcmIS_ERROR(platform.ops->getPower(&platform)))
+        {
+            gcmkFOOTER_NO();
+            return ret;
+        }
     }
 
-    res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_2d");
-    if (res)
-        irqLine2D = res->start;
-
-    res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_2d");
-    if (res)
+    if (platform.ops->adjustParam)
     {
-        registerMemBase2D = res->start;
-        registerMemSize2D = res->end - res->start + 1;
-    }
-
-    res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_vg");
-    if (res)
-        irqLineVG = res->start;
+        /* Override default module param. */
+        platform.ops->adjustParam(&platform, &moduleParam);
 
-    res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_vg");
-    if (res)
-    {
-        registerMemBaseVG = res->start;
-        registerMemSizeVG = res->end - res->start + 1;
+        /* Update module param because drv_init() uses them directly. */
+        _UpdateModuleParam(&moduleParam);
     }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-       pool = devm_kzalloc(&pdev->dev, sizeof(*pool), GFP_KERNEL);
-       if (!pool)
-               return -ENOMEM;
-       pool->size = contiguousSize;
-       init_dma_attrs(&pool->attrs);
-       dma_set_attr(DMA_ATTR_WRITE_COMBINE, &pool->attrs);
-       pool->virt = dma_alloc_attrs(&pdev->dev, pool->size, &pool->phys,
-                                    GFP_KERNEL, &pool->attrs);
-       if (!pool->virt) {
-               dev_err(&pdev->dev, "Failed to allocate contiguous memory\n");
-               return -ENOMEM;
-       }
-       contiguousBase = pool->phys;
-       dev_set_drvdata(&pdev->dev, pool);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-       prop = of_get_property(dn, "contiguousbase", NULL);
-       if(prop)
-               contiguousBase = *prop;
-       of_property_read_u32(dn,"contiguoussize", (u32 *)&contiguousSize);
-#else
-    pdata = pdev->dev.platform_data;
-    if (pdata) {
-        contiguousBase = pdata->reserved_mem_base;
-        contiguousSize = pdata->reserved_mem_size;
-     }
-#endif
-    if (contiguousSize == 0)
-       gckOS_Print("Warning: No contiguous memory is reserverd for gpu.!\n ");
-    ret = drv_init(&pdev->dev);
+    ret = drv_init();
 
     if (!ret)
     {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-       rstc = devm_reset_control_get(&pdev->dev, "gpu3d");
-       galDevice->rstc[gcvCORE_MAJOR] = IS_ERR(rstc) ? NULL : rstc;
-
-       rstc = devm_reset_control_get(&pdev->dev, "gpu2d");
-       galDevice->rstc[gcvCORE_2D] = IS_ERR(rstc) ? NULL : rstc;
-
-       rstc = devm_reset_control_get(&pdev->dev, "gpuvg");
-       galDevice->rstc[gcvCORE_VG] = IS_ERR(rstc) ? NULL : rstc;
-#endif
         platform_set_drvdata(pdev, galDevice);
 
-#if gcdENABLE_FSCALE_VAL_ADJUST
-        if (galDevice->kernels[gcvCORE_MAJOR])
-            REG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
-#endif
         gcmkFOOTER_NO();
         return ret;
     }
-#if gcdENABLE_FSCALE_VAL_ADJUST
-    UNREG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-       dma_free_attrs(&pdev->dev, pool->size, pool->virt, pool->phys,
-                      &pool->attrs);
-#endif
+
     gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret);
     return ret;
 }
@@ -1179,20 +1073,15 @@ static int gpu_remove(struct platform_device *pdev)
 static int __devexit gpu_remove(struct platform_device *pdev)
 #endif
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-       gckGALDEVICE device = platform_get_drvdata(pdev);
-       struct contiguous_mem_pool *pool = device->pool;
-#endif
     gcmkHEADER();
-#if gcdENABLE_FSCALE_VAL_ADJUST
-    if(galDevice->kernels[gcvCORE_MAJOR])
-        UNREG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
-#endif
+
     drv_exit();
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-       dma_free_attrs(&pdev->dev, pool->size, pool->virt, pool->phys,
-                      &pool->attrs);
-#endif
+
+    if (platform.ops->putPower)
+    {
+        platform.ops->putPower(&platform);
+    }
+
     gcmkFOOTER_NO();
     return 0;
 }
@@ -1205,6 +1094,11 @@ static int gpu_suspend(struct platform_device *dev, pm_message_t state)
 
     device = platform_get_drvdata(dev);
 
+    if (!device)
+    {
+        return -1;
+    }
+
     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
     {
         if (device->kernels[i] != gcvNULL)
@@ -1236,6 +1130,7 @@ static int gpu_suspend(struct platform_device *dev, pm_message_t state)
             {
                 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF);
             }
+
             if (gcmIS_ERROR(status))
             {
                 return -1;
@@ -1256,6 +1151,11 @@ static int gpu_resume(struct platform_device *dev)
 
     device = platform_get_drvdata(dev);
 
+    if (!device)
+    {
+        return -1;
+    }
+
     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
     {
         if (device->kernels[i] != gcvNULL)
@@ -1294,14 +1194,14 @@ static int gpu_resume(struct platform_device *dev)
             default:
                 statesStored = device->statesStored[i];
                 break;
-        }
+            }
 
             /* Restore states. */
 #if gcdENABLE_VG
             if (i == gcvCORE_VG)
             {
                 status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, statesStored);
-    }
+            }
             else
 #endif
             {
@@ -1318,47 +1218,24 @@ static int gpu_resume(struct platform_device *dev)
     return 0;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-static const struct of_device_id mxs_gpu_dt_ids[] = {
-       { .compatible = "fsl,imx6q-gpu", },
-       {/* sentinel */}
-};
-MODULE_DEVICE_TABLE(of, mxs_gpu_dt_ids);
-
-#ifdef CONFIG_PM
-static int gpu_runtime_suspend(struct device *dev)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-       release_bus_freq(BUS_FREQ_HIGH);
-#endif
-       return 0;
-}
-
-static int gpu_runtime_resume(struct device *dev)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-       request_bus_freq(BUS_FREQ_HIGH);
-#endif
-       return 0;
-}
-
+#if defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+#ifdef CONFIG_PM_SLEEP
 static int gpu_system_suspend(struct device *dev)
 {
-       pm_message_t state={0};
-       return gpu_suspend(to_platform_device(dev), state);
+    pm_message_t state={0};
+    return gpu_suspend(to_platform_device(dev), state);
 }
 
 static int gpu_system_resume(struct device *dev)
 {
-       return gpu_resume(to_platform_device(dev));
+    return gpu_resume(to_platform_device(dev));
 }
+#endif
 
 static const struct dev_pm_ops gpu_pm_ops = {
-       SET_RUNTIME_PM_OPS(gpu_runtime_suspend, gpu_runtime_resume, NULL)
-       SET_SYSTEM_SLEEP_PM_OPS(gpu_system_suspend, gpu_system_resume)
+    SET_SYSTEM_SLEEP_PM_OPS(gpu_system_suspend, gpu_system_resume)
 };
 #endif
-#endif
 
 static struct platform_driver gpu_driver = {
     .probe      = gpu_probe,
@@ -1373,72 +1250,65 @@ static struct platform_driver gpu_driver = {
 
     .driver     = {
         .name   = DEVICE_NAME,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-               .of_match_table = mxs_gpu_dt_ids,
-#if CONFIG_PM
-               .pm             = &gpu_pm_ops,
-#endif
+#if defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+        .pm     = &gpu_pm_ops,
 #endif
     }
 };
 
-#if 0 /*CONFIG_DOVE_GPU*/
-static struct resource gpu_resources[] = {
-    {
-        .name   = "gpu_irq",
-        .flags  = IORESOURCE_IRQ,
-    },
-    {
-        .name   = "gpu_base",
-        .flags  = IORESOURCE_MEM,
-    },
-    {
-        .name   = "gpu_mem",
-        .flags  = IORESOURCE_MEM,
-    },
-};
-
-static struct platform_device * gpu_device;
-#endif
-
 static int __init gpu_init(void)
 {
     int ret = 0;
 
-#if 0 /*ndef CONFIG_DOVE_GPU*/
-    gpu_resources[0].start = gpu_resources[0].end = irqLine;
-
-    gpu_resources[1].start = registerMemBase;
-    gpu_resources[1].end   = registerMemBase + registerMemSize - 1;
+    memset(&platform, 0, sizeof(gcsPLATFORM));
 
-    gpu_resources[2].start = contiguousBase;
-    gpu_resources[2].end   = contiguousBase + contiguousSize - 1;
+    gckPLATFORM_QueryOperations(&platform.ops);
 
-    /* Allocate device */
-    gpu_device = platform_device_alloc(DEVICE_NAME, -1);
-    if (!gpu_device)
+    if (platform.ops == gcvNULL)
     {
-        printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
-        ret = -ENOMEM;
+        printk(KERN_ERR "galcore: No platform specific operations.\n");
+        ret = -ENODEV;
         goto out;
     }
 
-    /* Insert resource */
-    ret = platform_device_add_resources(gpu_device, gpu_resources, 3);
-    if (ret)
+    if (platform.ops->allocPriv)
     {
-        printk(KERN_ERR "galcore: platform_device_add_resources failed.\n");
-        goto put_dev;
+        /* Allocate platform private data. */
+        if (gcmIS_ERROR(platform.ops->allocPriv(&platform)))
+        {
+            ret = -ENOMEM;
+            goto out;
+        }
     }
 
-    /* Add device */
-    ret = platform_device_add(gpu_device);
-    if (ret)
+    if (platform.ops->needAddDevice
+     && platform.ops->needAddDevice(&platform))
     {
-        printk(KERN_ERR "galcore: platform_device_add failed.\n");
-        goto put_dev;
+        /* Allocate device */
+        platform.device = platform_device_alloc(DEVICE_NAME, -1);
+        if (!platform.device)
+        {
+            printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
+            ret = -ENOMEM;
+            goto out;
+        }
+
+        /* Add device */
+        ret = platform_device_add(platform.device);
+        if (ret)
+        {
+            printk(KERN_ERR "galcore: platform_device_add failed.\n");
+            goto put_dev;
+        }
+    }
+
+    platform.driver = &gpu_driver;
+
+    if (platform.ops->adjustDriver)
+    {
+        /* Override default platform_driver struct. */
+        platform.ops->adjustDriver(&platform);
     }
-#endif
 
     ret = platform_driver_register(&gpu_driver);
     if (!ret)
@@ -1446,11 +1316,9 @@ static int __init gpu_init(void)
         goto out;
     }
 
-#if 0 /*ndef CONFIG_DOVE_GPU*/
-    platform_device_del(gpu_device);
+    platform_device_del(platform.device);
 put_dev:
-    platform_device_put(gpu_device);
-#endif
+    platform_device_put(platform.device);
 
 out:
     return ret;
@@ -1459,9 +1327,18 @@ out:
 static void __exit gpu_exit(void)
 {
     platform_driver_unregister(&gpu_driver);
-#if 0 /*ndef CONFIG_DOVE_GPU*/
-    platform_device_unregister(gpu_device);
-#endif
+
+    if (platform.ops->needAddDevice
+     && platform.ops->needAddDevice(&platform))
+    {
+        platform_device_unregister(platform.device);
+    }
+
+    if (platform.priv)
+    {
+        /* Free platform private data. */
+        platform.ops->freePriv(&platform);
+    }
 }
 
 module_init(gpu_init);
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel.c
new file mode 100644 (file)
index 0000000..e745a6f
--- /dev/null
@@ -0,0 +1,385 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2014 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/slab.h>
+
+#include "tee_client_api.h"
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+#define GPU3D_UUID   { 0xcc9f80ea, 0xa836, 0x11e3, { 0x9b, 0x07, 0x78, 0x2b, 0xcb, 0x5c, 0xf3, 0xe3 } }
+
+static const TEEC_UUID gpu3d_uuid = GPU3D_UUID;
+TEEC_Context teecContext;
+
+typedef struct _gcsSecurityChannel {
+    gckOS               os;
+    TEEC_Session        session;
+    int *               virtual;
+    TEEC_SharedMemory   inputBuffer;
+    gctUINT32           bytes;
+    gctPOINTER          mutex;
+} gcsSecurityChannel;
+
+TEEC_SharedMemory *
+gpu3d_allocate_secure_mem(
+    gckOS Os,
+    unsigned int size
+    )
+{
+    TEEC_Result result;
+    TEEC_Context *context = &teecContext;
+    TEEC_SharedMemory *shm = NULL;
+    void *handle = NULL;
+    unsigned int phyAddr = 0xFFFFFFFF;
+    gceSTATUS status;
+    gctSIZE_T bytes = size;
+
+    shm = kmalloc(sizeof(TEEC_SharedMemory), GFP_KERNEL);
+
+    if (NULL == shm)
+    {
+        return NULL;
+    }
+
+    memset(shm, 0, sizeof(TEEC_SharedMemory));
+
+    status = gckOS_AllocatePagedMemoryEx(
+                Os,
+                gcvALLOC_FLAG_SECURITY,
+                bytes,
+                gcvNULL,
+                (gctPHYS_ADDR *)&handle);
+
+    if (gcmIS_ERROR(status))
+    {
+         kfree(shm);
+         return NULL;
+    }
+
+    status = gckOS_PhysicalToPhysicalAddress(
+                Os,
+                handle,
+                &phyAddr);
+
+    if (gcmIS_ERROR(status))
+    {
+         kfree(shm);
+         return NULL;
+    }
+
+    /* record the handle into shm->user_data */
+    shm->userdata = handle;
+
+    /* [b] Bulk input buffer. */
+    shm->size = size;
+    shm->flags = TEEC_MEM_INPUT;
+
+    /* Use TEE Client API to register the underlying memory buffer. */
+    shm->phyAddr = (void *)phyAddr;
+
+    result = TEEC_RegisterSharedMemory(
+            context,
+            shm);
+
+    if (result != TEEC_SUCCESS)
+    {
+        gckOS_FreePagedMemory(Os, (gctPHYS_ADDR)handle, shm->size);
+        kfree(shm);
+        return NULL;
+    }
+
+    return shm;
+}
+
+void gpu3d_release_secure_mem(
+    gckOS Os,
+    void *shm_handle
+    )
+{
+    TEEC_SharedMemory *shm = shm_handle;
+    void * handle;
+
+    if (!shm)
+    {
+        return;
+    }
+
+    handle = shm->userdata;
+
+    TEEC_ReleaseSharedMemory(shm);
+    gckOS_FreePagedMemory(Os, (gctPHYS_ADDR)handle, shm->size);
+
+    kfree(shm);
+
+    return;
+}
+
+static TEEC_Result gpu3d_session_callback(
+    TEEC_Session*   session,
+    uint32_t    commandID,
+    TEEC_Operation* operation,
+    void*   userdata
+    )
+{
+    gcsSecurityChannel *channel = userdata;
+
+    if (channel == gcvNULL)
+    {
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+
+    switch(commandID)
+    {
+        case gcvTA_CALLBACK_ALLOC_SECURE_MEM:
+        {
+            uint32_t size = operation->params[0].value.a;
+            TEEC_SharedMemory *shm = NULL;
+
+            shm = gpu3d_allocate_secure_mem(channel->os, size);
+
+            /* use the value to save the pointer in client side */
+            operation->params[0].value.a = (uint32_t)shm;
+            operation->params[0].value.b = (uint32_t)shm->phyAddr;
+
+            break;
+        }
+        case gcvTA_CALLBACK_FREE_SECURE_MEM:
+        {
+            TEEC_SharedMemory *shm = (TEEC_SharedMemory *)operation->params[0].value.a;
+
+            gpu3d_release_secure_mem(channel->os, shm);
+            break;
+        }
+        default:
+            break;
+    }
+
+    return TEEC_SUCCESS;
+}
+
+gceSTATUS
+gckOS_OpenSecurityChannel(
+    IN gckOS Os,
+    IN gceCORE GPU,
+    OUT gctUINT32 *Channel
+    )
+{
+    gceSTATUS status;
+    TEEC_Result result;
+    static bool initialized = gcvFALSE;
+    gcsSecurityChannel *channel = gcvNULL;
+
+    TEEC_Operation operation = {0};
+
+    /* Connect to TEE. */
+    if (initialized == gcvFALSE)
+    {
+        result = TEEC_InitializeContext(NULL, &teecContext);
+
+        if (result != TEEC_SUCCESS) {
+            gcmkONERROR(gcvSTATUS_CHIP_NOT_READY);
+        }
+
+        initialized = gcvTRUE;
+    }
+
+    /* Construct channel. */
+    gcmkONERROR(
+        gckOS_Allocate(Os, gcmSIZEOF(*channel), (gctPOINTER *)&channel));
+
+    gckOS_ZeroMemory(channel, gcmSIZEOF(gcsSecurityChannel));
+
+    channel->os = Os;
+
+    gcmkONERROR(gckOS_CreateMutex(Os, &channel->mutex));
+
+    /* Allocate shared memory for passing gcTA_INTERFACE. */
+    channel->bytes = gcmSIZEOF(gcsTA_INTERFACE);
+    channel->virtual = kmalloc(channel->bytes, GFP_KERNEL | __GFP_NOWARN);
+
+    if (!channel->virtual)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    channel->inputBuffer.size    = channel->bytes;
+    channel->inputBuffer.flags   = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
+    channel->inputBuffer.phyAddr = (void *)virt_to_phys(channel->virtual);
+
+    result = TEEC_RegisterSharedMemory(&teecContext, &channel->inputBuffer);
+
+    if (result != TEEC_SUCCESS)
+    {
+        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+    }
+
+    operation.paramTypes = TEEC_PARAM_TYPES(
+            TEEC_VALUE_INPUT,
+            TEEC_NONE,
+            TEEC_NONE,
+            TEEC_NONE);
+
+    operation.params[0].value.a = GPU;
+
+    /* Open session with TEE application. */
+    result = TEEC_OpenSession(
+                &teecContext,
+                &channel->session,
+                &gpu3d_uuid,
+                TEEC_LOGIN_USER,
+                NULL,
+                &operation,
+                NULL);
+
+    /* Prepare callback. */
+    TEEC_RegisterCallback(&channel->session, gpu3d_session_callback, channel);
+
+    *Channel = (gctUINT32)channel;
+
+    return gcvSTATUS_OK;
+
+OnError:
+    if (channel)
+    {
+        if (channel->virtual)
+        {
+        }
+
+        if (channel->mutex)
+        {
+            gcmkVERIFY_OK(gckOS_DeleteMutex(Os, channel->mutex));
+        }
+
+        gcmkVERIFY_OK(gckOS_Free(Os, channel));
+    }
+
+    return status;
+}
+
+gceSTATUS
+gckOS_CloseSecurityChannel(
+    IN gctUINT32 Channel
+    )
+{
+    /* TODO . */
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_CallSecurityService(
+    IN gctUINT32 Channel,
+    IN gcsTA_INTERFACE *Interface
+    )
+{
+    gceSTATUS status;
+    TEEC_Result result;
+    gcsSecurityChannel *channel = (gcsSecurityChannel *)Channel;
+    TEEC_Operation operation = {0};
+
+    gcmkHEADER();
+    gcmkVERIFY_ARGUMENT(Channel != 0);
+
+    gckOS_AcquireMutex(channel->os, channel->mutex, gcvINFINITE);
+
+    gckOS_MemCopy(channel->virtual, Interface, channel->bytes);
+
+    operation.paramTypes = TEEC_PARAM_TYPES(
+            TEEC_MEMREF_PARTIAL_INPUT,
+            TEEC_NONE,
+            TEEC_NONE,
+            TEEC_NONE);
+
+    /* Note: we use the updated size in the MemRef output by the encryption. */
+    operation.params[0].memref.parent = &channel->inputBuffer;
+    operation.params[0].memref.offset = 0;
+    operation.params[0].memref.size = sizeof(gcsTA_INTERFACE);
+    operation.started = true;
+
+    /* Start the commit command within the TEE application. */
+    result = TEEC_InvokeCommand(
+            &channel->session,
+            gcvTA_COMMAND_DISPATCH,
+            &operation,
+            NULL);
+
+    gckOS_MemCopy(Interface, channel->virtual, channel->bytes);
+
+    gckOS_ReleaseMutex(channel->os, channel->mutex);
+
+    if (result != TEEC_SUCCESS)
+    {
+        gcmkONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
+gceSTATUS
+gckOS_InitSecurityChannel(
+    IN gctUINT32 Channel
+    )
+{
+    gceSTATUS status;
+    TEEC_Result result;
+    gcsSecurityChannel *channel = (gcsSecurityChannel *)Channel;
+    TEEC_Operation operation = {0};
+
+    gcmkHEADER();
+    gcmkVERIFY_ARGUMENT(Channel != 0);
+
+    operation.paramTypes = TEEC_PARAM_TYPES(
+            TEEC_MEMREF_PARTIAL_INPUT,
+            TEEC_NONE,
+            TEEC_NONE,
+            TEEC_NONE);
+
+    /* Note: we use the updated size in the MemRef output by the encryption. */
+    operation.params[0].memref.parent = &channel->inputBuffer;
+    operation.params[0].memref.offset = 0;
+    operation.params[0].memref.size = gcmSIZEOF(gcsTA_INTERFACE);
+    operation.started = true;
+
+    /* Start the commit command within the TEE application. */
+    result = TEEC_InvokeCommand(
+            &channel->session,
+            gcvTA_COMMAND_INIT,
+            &operation,
+            NULL);
+
+    if (result != TEEC_SUCCESS)
+    {
+        gcmkONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
index 7efae1c74bbeb29b2a153cc0b56610246cc714c0..0e5a816974231b38841ba8daea41167a8133ed94 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
 *****************************************************************************/
 
 
+#include <gc_hal.h>
+#include <gc_hal_base.h>
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+
 #include <linux/kernel.h>
 #include <linux/file.h>
 #include <linux/fs.h>
@@ -29,8 +34,6 @@
 
 #include "gc_hal_kernel_sync.h"
 
-#if gcdANDROID_NATIVE_FENCE_SYNC
-
 static struct sync_pt *
 viv_sync_pt_dup(
     struct sync_pt * sync_pt
index 6fc12e5d0832f2324bc01c551985b1dc776aacef..8a69921801ae6a778a6809dc1133e35255f881f3 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 *
-*    Copyright (C) 2005 - 2013 by Vivante Corp.
+*    Copyright (C) 2005 - 2014 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
@@ -24,7 +24,8 @@
 
 #include <linux/types.h>
 
-#include <linux/sync.h>
+/* sync.h is in drivers/staging/android/ for now. */
+#include <sync.h>
 
 #include <gc_hal.h>
 #include <gc_hal_base.h>
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c
new file mode 100644 (file)
index 0000000..b31d06e
--- /dev/null
@@ -0,0 +1,877 @@
+/****************************************************************************
+*
+*    Copyright (C) 2005 - 2014 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 "gc_hal_kernel_platform.h"
+#include "gc_hal_kernel_device.h"
+#include "gc_hal_driver.h"
+#include <linux/slab.h>
+
+#if USE_PLATFORM_DRIVER
+#   include <linux/platform_device.h>
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+#include <mach/viv_gpu.h>
+#else
+#include <linux/pm_runtime.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+#include <mach/busfreq.h>
+#else
+#include <linux/reset.h>
+#endif
+#endif
+
+#include <linux/clk.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+#include <mach/hardware.h>
+#endif
+#include <linux/pm_runtime.h>
+
+#include <linux/regulator/consumer.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#include <linux/device_cooling.h>
+#define REG_THERMAL_NOTIFIER(a) register_devfreq_cooling_notifier(a);
+#define UNREG_THERMAL_NOTIFIER(a) unregister_devfreq_cooling_notifier(a);
+#else
+extern int register_thermal_notifier(struct notifier_block *nb);
+extern int unregister_thermal_notifier(struct notifier_block *nb);
+#define REG_THERMAL_NOTIFIER(a) register_thermal_notifier(a);
+#define UNREG_THERMAL_NOTIFIER(a) unregister_thermal_notifier(a);
+#endif
+
+static int initgpu3DMinClock = 1;
+module_param(initgpu3DMinClock, int, 0644);
+
+struct platform_device *pdevice;
+
+#ifdef CONFIG_GPU_LOW_MEMORY_KILLER
+#    include <linux/kernel.h>
+#    include <linux/mm.h>
+#    include <linux/oom.h>
+#    include <linux/sched.h>
+
+struct task_struct *lowmem_deathpending;
+
+static int
+task_notify_func(struct notifier_block *self, unsigned long val, void *data);
+
+static struct notifier_block task_nb = {
+       .notifier_call  = task_notify_func,
+};
+
+static int
+task_notify_func(struct notifier_block *self, unsigned long val, void *data)
+{
+       struct task_struct *task = data;
+
+       if (task == lowmem_deathpending)
+               lowmem_deathpending = NULL;
+
+       return NOTIFY_OK;
+}
+
+extern struct task_struct *lowmem_deathpending;
+static unsigned long lowmem_deathpending_timeout;
+
+static int force_contiguous_lowmem_shrink(IN gckKERNEL Kernel)
+{
+       struct task_struct *p;
+       struct task_struct *selected = NULL;
+       int tasksize;
+        int ret = -1;
+       int min_adj = 0;
+       int selected_tasksize = 0;
+       int selected_oom_adj;
+       /*
+        * If we already have a death outstanding, then
+        * bail out right away; indicating to vmscan
+        * that we have nothing further to offer on
+        * this pass.
+        *
+        */
+       if (lowmem_deathpending &&
+           time_before_eq(jiffies, lowmem_deathpending_timeout))
+               return 0;
+       selected_oom_adj = min_adj;
+
+       rcu_read_lock();
+       for_each_process(p) {
+               struct mm_struct *mm;
+               struct signal_struct *sig;
+                gcuDATABASE_INFO info;
+               int oom_adj;
+
+               task_lock(p);
+               mm = p->mm;
+               sig = p->signal;
+               if (!mm || !sig) {
+                       task_unlock(p);
+                       continue;
+               }
+               oom_adj = sig->oom_score_adj;
+               if (oom_adj < min_adj) {
+                       task_unlock(p);
+                       continue;
+               }
+
+               tasksize = 0;
+               task_unlock(p);
+               rcu_read_unlock();
+
+               if (gckKERNEL_QueryProcessDB(Kernel, p->pid, gcvFALSE, gcvDB_VIDEO_MEMORY, &info) == gcvSTATUS_OK){
+                       tasksize += info.counters.bytes / PAGE_SIZE;
+               }
+               if (gckKERNEL_QueryProcessDB(Kernel, p->pid, gcvFALSE, gcvDB_CONTIGUOUS, &info) == gcvSTATUS_OK){
+                       tasksize += info.counters.bytes / PAGE_SIZE;
+               }
+
+               rcu_read_lock();
+
+               if (tasksize <= 0)
+                       continue;
+
+               gckOS_Print("<gpu> pid %d (%s), adj %d, size %d \n", p->pid, p->comm, oom_adj, tasksize);
+
+               if (selected) {
+                       if (oom_adj < selected_oom_adj)
+                               continue;
+                       if (oom_adj == selected_oom_adj &&
+                           tasksize <= selected_tasksize)
+                               continue;
+               }
+               selected = p;
+               selected_tasksize = tasksize;
+               selected_oom_adj = oom_adj;
+       }
+       if (selected) {
+               gckOS_Print("<gpu> send sigkill to %d (%s), adj %d, size %d\n",
+                            selected->pid, selected->comm,
+                            selected_oom_adj, selected_tasksize);
+               lowmem_deathpending = selected;
+               lowmem_deathpending_timeout = jiffies + HZ;
+               force_sig(SIGKILL, selected);
+               ret = 0;
+       }
+       rcu_read_unlock();
+       return ret;
+}
+
+
+gceSTATUS
+_ShrinkMemory(
+    IN gckPLATFORM Platform
+    )
+{
+    struct platform_device *pdev;
+    gckGALDEVICE galDevice;
+    gckKERNEL kernel;
+
+    pdev = Platform->device;
+
+    galDevice = platform_get_drvdata(pdev);
+
+    kernel = galDevice->kernels[gcvCORE_MAJOR];
+
+    if (kernel != gcvNULL)
+    {
+        force_contiguous_lowmem_shrink(kernel);
+    }
+    else
+    {
+        gcmkPRINT("%s(%d) can't find kernel! ", __FUNCTION__, __LINE__);
+    }
+
+    return gcvSTATUS_OK;
+}
+#endif
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+static int thermal_hot_pm_notify(struct notifier_block *nb, unsigned long event,
+       void *dummy)
+{
+    static gctUINT orgFscale, minFscale, maxFscale;
+    static gctBOOL bAlreadyTooHot = gcvFALSE;
+    gckHARDWARE hardware;
+    gckGALDEVICE galDevice;
+
+    galDevice = platform_get_drvdata(pdevice);
+    if (!galDevice)
+    {
+        /* GPU is not ready, so it is meaningless to change GPU freq. */
+        return NOTIFY_OK;
+    }
+
+    if (!galDevice->kernels[gcvCORE_MAJOR])
+    {
+        return NOTIFY_OK;
+    }
+
+    hardware = galDevice->kernels[gcvCORE_MAJOR]->hardware;
+
+    if (!hardware)
+    {
+        return NOTIFY_OK;
+    }
+
+    if (event && !bAlreadyTooHot) {
+        gckHARDWARE_GetFscaleValue(hardware,&orgFscale,&minFscale, &maxFscale);
+        gckHARDWARE_SetFscaleValue(hardware, minFscale);
+        bAlreadyTooHot = gcvTRUE;
+        gckOS_Print("System is too hot. GPU3D will work at %d/64 clock.\n", minFscale);
+    } else if (!event && bAlreadyTooHot) {
+        gckHARDWARE_SetFscaleValue(hardware, orgFscale);
+        gckOS_Print("Hot alarm is canceled. GPU3D clock will return to %d/64\n", orgFscale);
+        bAlreadyTooHot = gcvFALSE;
+    }
+    return NOTIFY_OK;
+}
+
+static struct notifier_block thermal_hot_pm_notifier = {
+    .notifier_call = thermal_hot_pm_notify,
+    };
+
+static ssize_t show_gpu3DMinClock(struct device_driver *dev, char *buf)
+{
+    gctUINT currentf,minf,maxf;
+    gckGALDEVICE galDevice;
+
+    galDevice = platform_get_drvdata(pdevice);
+    if(galDevice->kernels[gcvCORE_MAJOR])
+    {
+         gckHARDWARE_GetFscaleValue(galDevice->kernels[gcvCORE_MAJOR]->hardware,
+            &currentf, &minf, &maxf);
+    }
+    snprintf(buf, PAGE_SIZE, "%d\n", minf);
+    return strlen(buf);
+}
+
+static ssize_t update_gpu3DMinClock(struct device_driver *dev, const char *buf, size_t count)
+{
+
+    gctINT fields;
+    gctUINT MinFscaleValue;
+    gckGALDEVICE galDevice;
+
+    galDevice = platform_get_drvdata(pdevice);
+    if(galDevice->kernels[gcvCORE_MAJOR])
+    {
+         fields = sscanf(buf, "%d", &MinFscaleValue);
+         if (fields < 1)
+             return -EINVAL;
+
+         gckHARDWARE_SetMinFscaleValue(galDevice->kernels[gcvCORE_MAJOR]->hardware,MinFscaleValue);
+    }
+
+    return count;
+}
+
+static DRIVER_ATTR(gpu3DMinClock, S_IRUGO | S_IWUSR, show_gpu3DMinClock, update_gpu3DMinClock);
+#endif
+
+
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+static const struct of_device_id mxs_gpu_dt_ids[] = {
+    { .compatible = "fsl,imx6q-gpu", },
+    {/* sentinel */}
+};
+MODULE_DEVICE_TABLE(of, mxs_gpu_dt_ids);
+#endif
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+struct contiguous_mem_pool {
+    struct dma_attrs attrs;
+    dma_addr_t phys;
+    void *virt;
+    size_t size;
+};
+#endif
+
+struct imx_priv {
+    /* Clock management.*/
+    struct clk         *clk_3d_core;
+    struct clk         *clk_3d_shader;
+    struct clk         *clk_3d_axi;
+    struct clk         *clk_2d_core;
+    struct clk         *clk_2d_axi;
+    struct clk         *clk_vg_axi;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+    /*Power management.*/
+    struct regulator      *gpu_regulator;
+#endif
+#endif
+       /*Run time pm*/
+       struct device           *pmdev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+    struct contiguous_mem_pool *pool;
+    struct reset_control *rstc[gcdMAX_GPU_COUNT];
+#endif
+};
+
+static struct imx_priv imxPriv;
+
+gceSTATUS
+gckPLATFORM_AdjustParam(
+    IN gckPLATFORM Platform,
+    OUT gcsMODULE_PARAMETERS *Args
+    )
+{
+     struct resource* res;
+     struct platform_device* pdev = Platform->device;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+       struct device_node *dn =pdev->dev.of_node;
+       const u32 *prop;
+#else
+       struct viv_gpu_platform_data *pdata;
+#endif
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phys_baseaddr");
+    if (res)
+        Args->baseAddress = res->start;
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_3d");
+    if (res)
+        Args->irqLine = res->start;
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_3d");
+    if (res)
+    {
+        Args->registerMemBase = res->start;
+        Args->registerMemSize = res->end - res->start + 1;
+    }
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_2d");
+    if (res)
+        Args->irqLine2D = res->start;
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_2d");
+    if (res)
+    {
+        Args->registerMemBase2D = res->start;
+        Args->registerMemSize2D = res->end - res->start + 1;
+    }
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_vg");
+    if (res)
+        Args->irqLineVG = res->start;
+
+    res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_vg");
+    if (res)
+    {
+        Args->registerMemBaseVG = res->start;
+        Args->registerMemSizeVG = res->end - res->start + 1;
+    }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+       Args->contiguousBase = 0;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+       prop = of_get_property(dn, "contiguousbase", NULL);
+       if(prop)
+               Args->contiguousBase = *prop;
+       of_property_read_u32(dn,"contiguoussize", (u32 *)&contiguousSize);
+#else
+    pdata = pdev->dev.platform_data;
+    if (pdata) {
+        Args->contiguousBase = pdata->reserved_mem_base;
+       Args->contiguousSize = pdata->reserved_mem_size;
+     }
+#endif
+    if (Args->contiguousSize == 0)
+       gckOS_Print("Warning: No contiguous memory is reserverd for gpu.!\n ");
+
+    Args->gpu3DMinClock = initgpu3DMinClock;
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_AllocPriv(
+    IN gckPLATFORM Platform
+    )
+{
+    Platform->priv = &imxPriv;
+
+#ifdef CONFIG_GPU_LOW_MEMORY_KILLER
+    task_free_register(&task_nb);
+#endif
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_FreePriv(
+    IN gckPLATFORM Platform
+    )
+{
+#ifdef CONFIG_GPU_LOW_MEMORY_KILLER
+    task_free_unregister(&task_nb);
+#endif
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_GetPower(
+    IN gckPLATFORM Platform
+    )
+{
+    struct device* pdev = &Platform->device->dev;
+    struct imx_priv *priv = Platform->priv;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+    struct reset_control *rstc;
+#endif
+
+#ifdef CONFIG_PM
+    /*Init runtime pm for gpu*/
+    pm_runtime_enable(pdev);
+    priv->pmdev = pdev;
+#endif
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+    rstc = devm_reset_control_get(pdev, "gpu3d");
+    priv->rstc[gcvCORE_MAJOR] = IS_ERR(rstc) ? NULL : rstc;
+    rstc = devm_reset_control_get(pdev, "gpu2d");
+    priv->rstc[gcvCORE_2D] = IS_ERR(rstc) ? NULL : rstc;
+    rstc = devm_reset_control_get(pdev, "gpuvg");
+    priv->rstc[gcvCORE_VG] = IS_ERR(rstc) ? NULL : rstc;
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+    /*get gpu regulator*/
+    priv->gpu_regulator = regulator_get(pdev, "cpu_vddgpu");
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+    priv->gpu_regulator = devm_regulator_get(pdev, "pu");
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+    if (IS_ERR(priv->gpu_regulator)) {
+       gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+               "%s(%d): Failed to get gpu regulator \n",
+               __FUNCTION__, __LINE__);
+       return gcvSTATUS_NOT_FOUND;
+    }
+#endif
+#endif
+
+    /*Initialize the clock structure*/
+    priv->clk_3d_core = clk_get(pdev, "gpu3d_clk");
+    if (!IS_ERR(priv->clk_3d_core)) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+        if (cpu_is_mx6q()) {
+               priv->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
+               if (IS_ERR(priv->clk_3d_shader)) {
+                   clk_put(priv->clk_3d_core);
+                   priv->clk_3d_core = NULL;
+                   priv->clk_3d_shader = NULL;
+                   gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
+               }
+             }
+#else
+               priv->clk_3d_axi = clk_get(pdev, "gpu3d_axi_clk");
+               priv->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
+               if (IS_ERR(priv->clk_3d_shader)) {
+                   clk_put(priv->clk_3d_core);
+                   priv->clk_3d_core = NULL;
+                   priv->clk_3d_shader = NULL;
+                   gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
+               }
+#endif
+    } else {
+        priv->clk_3d_core = NULL;
+        gckOS_Print("galcore: clk_get gpu3d_clk failed, disable 3d!\n");
+    }
+
+    priv->clk_2d_core = clk_get(pdev, "gpu2d_clk");
+    if (IS_ERR(priv->clk_2d_core)) {
+        priv->clk_2d_core = NULL;
+        gckOS_Print("galcore: clk_get 2d core clock failed, disable 2d/vg!\n");
+    } else {
+        priv->clk_2d_axi = clk_get(pdev, "gpu2d_axi_clk");
+        if (IS_ERR(priv->clk_2d_axi)) {
+            priv->clk_2d_axi = NULL;
+            gckOS_Print("galcore: clk_get 2d axi clock failed, disable 2d\n");
+        }
+
+        priv->clk_vg_axi = clk_get(pdev, "openvg_axi_clk");
+        if (IS_ERR(priv->clk_vg_axi)) {
+               priv->clk_vg_axi = NULL;
+               gckOS_Print("galcore: clk_get vg clock failed, disable vg!\n");
+        }
+    }
+
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+    pdevice = Platform->device;
+    REG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
+    {
+        int ret = 0;
+        ret = driver_create_file(pdevice->dev.driver, &driver_attr_gpu3DMinClock);
+        if(ret)
+            dev_err(&pdevice->dev, "create gpu3DMinClock attr failed (%d)\n", ret);
+    }
+#endif
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_PutPower(
+    IN gckPLATFORM Platform
+    )
+{
+    struct imx_priv *priv = Platform->priv;
+
+    /*Disable clock*/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+    if (priv->clk_3d_axi) {
+       clk_put(priv->clk_3d_axi);
+       priv->clk_3d_axi = NULL;
+    }
+#endif
+    if (priv->clk_3d_core) {
+       clk_put(priv->clk_3d_core);
+       priv->clk_3d_core = NULL;
+    }
+    if (priv->clk_3d_shader) {
+       clk_put(priv->clk_3d_shader);
+       priv->clk_3d_shader = NULL;
+    }
+    if (priv->clk_2d_core) {
+       clk_put(priv->clk_2d_core);
+       priv->clk_2d_core = NULL;
+    }
+    if (priv->clk_2d_axi) {
+       clk_put(priv->clk_2d_axi);
+       priv->clk_2d_axi = NULL;
+    }
+    if (priv->clk_vg_axi) {
+       clk_put(priv->clk_vg_axi);
+       priv->clk_vg_axi = NULL;
+    }
+
+#ifdef CONFIG_PM
+    if(priv->pmdev)
+        pm_runtime_disable(priv->pmdev);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+    if (priv->gpu_regulator) {
+       regulator_put(priv->gpu_regulator);
+       priv->gpu_regulator = NULL;
+    }
+#endif
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+    UNREG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
+
+    driver_remove_file(pdevice->dev.driver, &driver_attr_gpu3DMinClock);
+#endif
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_SetPower(
+    IN gckPLATFORM Platform,
+    IN gceCORE GPU,
+    IN gctBOOL Enable
+    )
+{
+    struct imx_priv* priv = Platform->priv;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+    int ret;
+#endif
+#endif
+
+    if (Enable)
+    {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+        if(!IS_ERR(priv->gpu_regulator)) {
+            ret = regulator_enable(priv->gpu_regulator);
+            if (ret != 0)
+                gckOS_Print("%s(%d): fail to enable pu regulator %d!\n",
+                    __FUNCTION__, __LINE__, ret);
+        }
+#else
+        imx_gpc_power_up_pu(true);
+#endif
+#endif
+
+#ifdef CONFIG_PM
+               pm_runtime_get_sync(priv->pmdev);
+#endif
+       }
+    else
+    {
+#ifdef CONFIG_PM
+        pm_runtime_put_sync(priv->pmdev);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+        if(!IS_ERR(priv->gpu_regulator))
+            regulator_disable(priv->gpu_regulator);
+#else
+        imx_gpc_power_up_pu(false);
+#endif
+#endif
+
+    }
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_SetClock(
+    IN gckPLATFORM Platform,
+    IN gceCORE GPU,
+    IN gctBOOL Enable
+    )
+{
+    struct imx_priv* priv = Platform->priv;
+    struct clk *clk_3dcore = priv->clk_3d_core;
+    struct clk *clk_3dshader = priv->clk_3d_shader;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+    struct clk *clk_3d_axi = priv->clk_3d_axi;
+#endif
+    struct clk *clk_2dcore = priv->clk_2d_core;
+    struct clk *clk_2d_axi = priv->clk_2d_axi;
+    struct clk *clk_vg_axi = priv->clk_vg_axi;
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+    if (Enable) {
+        switch (GPU) {
+        case gcvCORE_MAJOR:
+            clk_enable(clk_3dcore);
+            if (cpu_is_mx6q())
+                clk_enable(clk_3dshader);
+            break;
+        case gcvCORE_2D:
+            clk_enable(clk_2dcore);
+            clk_enable(clk_2d_axi);
+            break;
+        case gcvCORE_VG:
+            clk_enable(clk_2dcore);
+            clk_enable(clk_vg_axi);
+            break;
+        default:
+            break;
+        }
+    } else {
+        switch (GPU) {
+        case gcvCORE_MAJOR:
+            if (cpu_is_mx6q())
+                clk_disable(clk_3dshader);
+            clk_disable(clk_3dcore);
+            break;
+       case gcvCORE_2D:
+            clk_disable(clk_2dcore);
+            clk_disable(clk_2d_axi);
+            break;
+        case gcvCORE_VG:
+            clk_disable(clk_2dcore);
+            clk_disable(clk_vg_axi);
+            break;
+        default:
+            break;
+        }
+    }
+#else
+    if (Enable) {
+        switch (GPU) {
+        case gcvCORE_MAJOR:
+            clk_prepare(clk_3dcore);
+            clk_enable(clk_3dcore);
+            clk_prepare(clk_3dshader);
+            clk_enable(clk_3dshader);
+            clk_prepare(clk_3d_axi);
+            clk_enable(clk_3d_axi);
+            break;
+        case gcvCORE_2D:
+            clk_prepare(clk_2dcore);
+            clk_enable(clk_2dcore);
+            clk_prepare(clk_2d_axi);
+            clk_enable(clk_2d_axi);
+            break;
+        case gcvCORE_VG:
+            clk_prepare(clk_2dcore);
+            clk_enable(clk_2dcore);
+            clk_prepare(clk_vg_axi);
+            clk_enable(clk_vg_axi);
+            break;
+        default:
+            break;
+        }
+    } else {
+        switch (GPU) {
+        case gcvCORE_MAJOR:
+            clk_disable(clk_3dshader);
+            clk_unprepare(clk_3dshader);
+            clk_disable(clk_3dcore);
+            clk_unprepare(clk_3dcore);
+            clk_disable(clk_3d_axi);
+            clk_unprepare(clk_3d_axi);
+            break;
+       case gcvCORE_2D:
+            clk_disable(clk_2dcore);
+            clk_unprepare(clk_2dcore);
+            clk_disable(clk_2d_axi);
+            clk_unprepare(clk_2d_axi);
+            break;
+        case gcvCORE_VG:
+            clk_disable(clk_2dcore);
+            clk_unprepare(clk_2dcore);
+            clk_disable(clk_vg_axi);
+            clk_unprepare(clk_vg_axi);
+            break;
+        default:
+            break;
+        }
+    }
+#endif
+
+    return gcvSTATUS_OK;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+#ifdef CONFIG_PM
+static int gpu_runtime_suspend(struct device *dev)
+{
+    return 0;
+}
+
+static int gpu_runtime_resume(struct device *dev)
+{
+    return 0;
+}
+
+static struct dev_pm_ops gpu_pm_ops;
+#endif
+#endif
+
+gceSTATUS
+_AdjustDriver(
+    IN gckPLATFORM Platform
+    )
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+    struct platform_driver * driver = Platform->driver;
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+    driver->driver.of_match_table = mxs_gpu_dt_ids;
+#endif
+
+    /* Override PM callbacks to add runtime PM callbacks. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+    /* Fill local structure with original value. */
+    memcpy(&gpu_pm_ops, driver->driver.pm, sizeof(struct dev_pm_ops));
+
+    /* Add runtime PM callback. */
+#ifdef CONFIG_PM_RUNTIME
+    gpu_pm_ops.runtime_suspend = gpu_runtime_suspend;
+    gpu_pm_ops.runtime_resume = gpu_runtime_resume;
+    gpu_pm_ops.runtime_idle = NULL;
+#endif
+
+    /* Replace callbacks. */
+    driver->driver.pm = &gpu_pm_ops;
+#endif
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_Reset(
+    IN gckPLATFORM Platform,
+    gceCORE GPU
+    )
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+#define SRC_SCR_OFFSET 0
+#define BP_SRC_SCR_GPU3D_RST 1
+#define BP_SRC_SCR_GPU2D_RST 4
+    void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
+    gctUINT32 bit_offset,val;
+
+    if(GPU == gcvCORE_MAJOR) {
+        bit_offset = BP_SRC_SCR_GPU3D_RST;
+    } else if((GPU == gcvCORE_VG)
+            ||(GPU == gcvCORE_2D)) {
+        bit_offset = BP_SRC_SCR_GPU2D_RST;
+    } else {
+        return gcvSTATUS_INVALID_CONFIG;
+    }
+    val = __raw_readl(src_base + SRC_SCR_OFFSET);
+    val &= ~(1 << (bit_offset));
+    val |= (1 << (bit_offset));
+    __raw_writel(val, src_base + SRC_SCR_OFFSET);
+
+    while ((__raw_readl(src_base + SRC_SCR_OFFSET) &
+                (1 << (bit_offset))) != 0) {
+    }
+
+    return gcvSTATUS_NOT_SUPPORTED;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+    struct imx_priv* priv = Platform->priv;
+    struct reset_control *rstc = priv->rstc[GPU];
+    if (rstc)
+        reset_control_reset(rstc);
+#else
+    imx_src_reset_gpu((int)GPU);
+#endif
+    return gcvSTATUS_OK;
+}
+
+gcsPLATFORM_OPERATIONS platformOperations = {
+    .adjustParam  = gckPLATFORM_AdjustParam,
+    .allocPriv    = _AllocPriv,
+    .freePriv     = _FreePriv,
+    .getPower     = _GetPower,
+    .putPower     = _PutPower,
+    .setPower     = _SetPower,
+    .setClock     = _SetClock,
+    .adjustDriver = _AdjustDriver,
+    .reset        = _Reset,
+#ifdef CONFIG_GPU_LOW_MEMORY_KILLER
+    .shrinkMemory = _ShrinkMemory,
+#endif
+};
+
+void
+gckPLATFORM_QueryOperations(
+    IN gcsPLATFORM_OPERATIONS ** Operations
+    )
+{
+     *Operations = &platformOperations;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config
new file mode 100644 (file)
index 0000000..6575148
--- /dev/null
@@ -0,0 +1,15 @@
+EXTRA_CFLAGS += -DgcdDEFAULT_CONTIGUOUS_SIZE=134217728
+
+ifneq ($(CONFIG_ANDROID),)
+# build for android
+EXTRA_CFLAGS += -DgcdANDROID_NATIVE_FENCE_SYNC=3
+
+ifeq ($(CONFIG_SYNC),)
+$(warn CONFIG_SYNC is not set in kernel config)
+$(warn Android native fence sync needs CONFIG_SYNC)
+endif
+endif
+
+EXTRA_CFLAGS += -DLINUX_CMA_FSL=1
+ALLOCATOR_ARRAY_H_LOCATION := $(OS_KERNEL_DIR)/allocator/freescale
+CUSTOMER_ALLOCATOR_OBJS := $(ALLOCATOR_ARRAY_H_LOCATION)/gc_hal_kernel_allocator_cma.o