summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Xiao <b49994@freescale.com>2015-08-26 15:29:26 +0800
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:20:42 +0300
commit8460c0e8d90844019ed516edfed6ffc9bc92f7f0 (patch)
tree0a65c7888e9274273e98255c5aee547088b1bce2
parent1e49e90e147a7168cdac19ef8966d62fc918f286 (diff)
MGS-955 GPU:Integrate GPU module
1. Upstream 5.0.11p7 driver to kernel 2. Add the GPU configuration to imx6q.dtsi 3. Remove IRQF_DISABLED in GPU driver The IRQF_DISABLED has been removed from 4.1.0 kernel. To accomodate with the change, add version check logic and use 0x0 instead of IRQF_DISABLED from 4.1.0 kernel on. 4. Convert file->f_dentry->d_inode to file_inode() in GPU driver The file struct has changed since 3.19. Changed the usage in GPU driver too. 5. Add version check for CONFIG_PM_RUNTIME The CONFIG_PM_RUNTIME will never be used in 4.1.0 kernel. Add version check to avoid calling it in GPU driver. Signed-off-by: Shawn Xiao <b49994@freescale.com>
-rw-r--r--arch/arm/boot/dts/imx6q.dtsi21
-rw-r--r--arch/arm/configs/imx_v7_defconfig1
-rw-r--r--drivers/mxc/Kconfig1
-rw-r--r--drivers/mxc/Makefile2
-rw-r--r--drivers/mxc/gpu-viv/Kbuild313
-rw-r--r--drivers/mxc/gpu-viv/Kconfig9
-rw-r--r--drivers/mxc/gpu-viv/config36
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.c2441
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.h247
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c8454
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h214
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_recorder.c713
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.c966
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.h353
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.c2256
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.h108
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c5256
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h1584
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c3496
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c3850
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c1905
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c2821
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c3526
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c892
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c911
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c2315
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c556
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c381
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h63
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security.c284
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c909
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h119
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c2917
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h2920
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h5737
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h1275
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h304
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h123
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h717
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h344
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h2662
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h1326
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h1715
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h259
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h564
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h1326
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h619
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h1078
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h277
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_security_interface.h171
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h133
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h976
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h69
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h931
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h84
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c353
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_array.h95
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c446
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c972
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h470
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h147
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c1189
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h169
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c2898
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h282
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_iommu.c250
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c534
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h437
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c66
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_mutex.h89
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c8955
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h124
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h342
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_probe.c1410
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel.c423
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c211
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h106
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c967
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config20
79 files changed, 92485 insertions, 0 deletions
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index c0c7fac5f979..78e0d6226d3f 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -94,6 +94,27 @@
fsl,max_ddr_freq = <528000000>;
};
+ gpu@00130000 {
+ compatible = "fsl,imx6q-gpu";
+ reg = <0x00130000 0x4000>, <0x00134000 0x4000>,
+ <0x02204000 0x4000>, <0x0 0x0>;
+ reg-names = "iobase_3d", "iobase_2d",
+ "iobase_vg", "phys_baseaddr";
+ interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>,
+ <0 10 IRQ_TYPE_LEVEL_HIGH>,
+ <0 11 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "irq_3d", "irq_2d", "irq_vg";
+ clocks = <&clks IMX6QDL_CLK_GPU2D_AXI>, <&clks IMX6QDL_CLK_OPENVG_AXI>,
+ <&clks IMX6QDL_CLK_GPU3D_AXI>, <&clks IMX6QDL_CLK_GPU2D_CORE>,
+ <&clks IMX6QDL_CLK_GPU3D_CORE>, <&clks IMX6QDL_CLK_GPU3D_SHADER>;
+ clock-names = "gpu2d_axi_clk", "openvg_axi_clk",
+ "gpu3d_axi_clk", "gpu2d_clk",
+ "gpu3d_clk", "gpu3d_shader_clk";
+ resets = <&src 0>, <&src 3>, <&src 3>;
+ reset-names = "gpu3d", "gpu2d", "gpuvg";
+ power-domains = <&gpc 1>;
+ };
+
ocram: sram@00905000 {
compatible = "mmio-sram";
reg = <0x00905000 0x3B000>;
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index 506d0f39dcab..960e68a4cc0c 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -299,6 +299,7 @@ CONFIG_MMC_SDHCI_ESDHC_IMX=y
CONFIG_MXC_IPU=y
CONFIG_MXC_MLB150=m
CONFIG_MXC_IPU_V3_PRE=y
+CONFIG_MXC_GPU_VIV=y
CONFIG_MXC_SIM=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
diff --git a/drivers/mxc/Kconfig b/drivers/mxc/Kconfig
index a81314e8db44..4d4c137dfc73 100644
--- a/drivers/mxc/Kconfig
+++ b/drivers/mxc/Kconfig
@@ -13,6 +13,7 @@ config MXC_IPU
source "drivers/mxc/mlb/Kconfig"
source "drivers/mxc/ipu3/Kconfig"
+source "drivers/mxc/gpu-viv/Kconfig"
source "drivers/mxc/sim/Kconfig"
source "drivers/mxc/vpu/Kconfig"
source "drivers/mxc/hdmi-cec/Kconfig"
diff --git a/drivers/mxc/Makefile b/drivers/mxc/Makefile
index 170e681c1c5f..d6e58cd701d8 100644
--- a/drivers/mxc/Makefile
+++ b/drivers/mxc/Makefile
@@ -3,3 +3,5 @@ obj-$(CONFIG_MXC_SIM) += sim/
obj-$(CONFIG_MXC_VPU) += vpu/
obj-$(CONFIG_MXC_IPU_V3) += ipu3/
obj-$(CONFIG_MXC_HDMI_CEC) += hdmi-cec/
+obj-$(CONFIG_MXC_SIM) += gpu-viv/
+>>>>>>> MGS-955 GPU:Integrate GPU module
diff --git a/drivers/mxc/gpu-viv/Kbuild b/drivers/mxc/gpu-viv/Kbuild
new file mode 100644
index 000000000000..b651bbf577f1
--- /dev/null
+++ b/drivers/mxc/gpu-viv/Kbuild
@@ -0,0 +1,313 @@
+##############################################################################
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2014 Vivante Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+##############################################################################
+#
+# The GPL License (GPL)
+#
+# Copyright (C) 2014 Vivante Corporation
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+##############################################################################
+#
+# Note: This software is released under dual MIT and GPL licenses. A
+# recipient may use this file under the terms of either the MIT license or
+# GPL License. If you wish to use only one license not the other, you can
+# indicate your decision by deleting one of the above license notices in your
+# version of this file.
+#
+##############################################################################
+
+
+#
+# Linux build file for kernel HAL driver.
+#
+
+AQROOT := $(srctree)/drivers/mxc/gpu-viv
+
+include $(AQROOT)/config
+
+KERNEL_DIR ?= $(TOOL_DIR)/kernel
+
+OS_KERNEL_DIR := hal/os/linux/kernel
+ARCH_KERNEL_DIR := hal/kernel/arch
+ARCH_VG_KERNEL_DIR := hal/kernel/archvg
+HAL_KERNEL_DIR := hal/kernel
+HOST := $(shell hostname)
+
+# 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_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_allocator.o \
+
+ifneq ($(CONFIG_DMA_SHARED_BUFFER),)
+OBJS += $(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_dmabuf.o
+endif
+
+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 \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_db.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_debug.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_event.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_power.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\
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_command_vg.o\
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_interrupt_vg.o\
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu_vg.o\
+ $(ARCH_VG_KERNEL_DIR)/gc_hal_kernel_hardware_command_vg.o\
+ $(ARCH_VG_KERNEL_DIR)/gc_hal_kernel_hardware_vg.o
+endif
+
+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
+
+# Define targets.
+all:
+ @make V=$(V) ARCH=$(ARCH_TYPE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
+
+clean:
+ @rm -rf $(OBJS)
+ @rm -rf modules.order Module.symvers
+ @find $(AQROOT) -name ".gc_*.cmd" | xargs rm -f
+
+install: all
+ @mkdir -p $(SDK_DIR)/drivers
+
+else
+
+
+EXTRA_CFLAGS += -DLINUX -DDRIVER
+
+ifeq ($(FLAREON),1)
+EXTRA_CFLAGS += -DFLAREON
+endif
+
+ifeq ($(DEBUG), 1)
+EXTRA_CFLAGS += -DDBG=1 -DDEBUG -D_DEBUG
+else
+EXTRA_CFLAGS += -DDBG=0
+endif
+
+ifeq ($(NO_DMA_COHERENT), 1)
+EXTRA_CFLAGS += -DNO_DMA_COHERENT
+endif
+
+ifeq ($(CONFIG_DOVE_GPU), 1)
+EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
+endif
+
+ifneq ($(USE_PLATFORM_DRIVER), 0)
+EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=1
+else
+EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=0
+endif
+
+EXTRA_CFLAGS += -DVIVANTE_PROFILER=1
+EXTRA_CFLAGS += -DVIVANTE_PROFILER_CONTEXT=1
+
+ifeq ($(ENABLE_GPU_CLOCK_BY_DRIVER), 1)
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=1
+else
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=0
+endif
+
+ifeq ($(USE_NEW_LINUX_SIGNAL), 1)
+EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=1
+else
+EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=0
+endif
+
+ifeq ($(FORCE_ALL_VIDEO_MEMORY_CACHED), 1)
+EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=1
+else
+EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=0
+endif
+
+ifeq ($(NONPAGED_MEMORY_CACHEABLE), 1)
+EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_CACHEABLE=1
+else
+EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_CACHEABLE=0
+endif
+
+ifeq ($(NONPAGED_MEMORY_BUFFERABLE), 1)
+EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_BUFFERABLE=1
+else
+EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_BUFFERABLE=0
+endif
+
+ifeq ($(CACHE_FUNCTION_UNIMPLEMENTED), 1)
+EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=1
+else
+EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=0
+endif
+
+ifeq ($(CONFIG_SMP), y)
+EXTRA_CFLAGS += -DgcdSMP=1
+else
+EXTRA_CFLAGS += -DgcdSMP=0
+endif
+
+ifeq ($(VIVANTE_ENABLE_3D),0)
+EXTRA_CFLAGS += -DgcdENABLE_3D=0
+else
+EXTRA_CFLAGS += -DgcdENABLE_3D=1
+endif
+
+ifeq ($(VIVANTE_ENABLE_2D),0)
+EXTRA_CFLAGS += -DgcdENABLE_2D=0
+else
+EXTRA_CFLAGS += -DgcdENABLE_2D=1
+endif
+
+ifeq ($(VIVANTE_ENABLE_VG),0)
+EXTRA_CFLAGS += -DgcdENABLE_VG=0
+else
+EXTRA_CFLAGS += -DgcdENABLE_VG=1
+endif
+
+ifeq ($(ENABLE_OUTER_CACHE_PATCH), 1)
+EXTRA_CFLAGS += -DgcdENABLE_OUTER_CACHE_PATCH=1
+else
+EXTRA_CFLAGS += -DgcdENABLE_OUTER_CACHE_PATCH=0
+endif
+
+ifeq ($(USE_BANK_ALIGNMENT), 1)
+ EXTRA_CFLAGS += -DgcdENABLE_BANK_ALIGNMENT=1
+ ifneq ($(BANK_BIT_START), 0)
+ ifneq ($(BANK_BIT_END), 0)
+ EXTRA_CFLAGS += -DgcdBANK_BIT_START=$(BANK_BIT_START)
+ EXTRA_CFLAGS += -DgcdBANK_BIT_END=$(BANK_BIT_END)
+ endif
+ endif
+
+ ifneq ($(BANK_CHANNEL_BIT), 0)
+ EXTRA_CFLAGS += -DgcdBANK_CHANNEL_BIT=$(BANK_CHANNEL_BIT)
+ endif
+endif
+
+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$(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$(AQROOT)/hal/kernel/archvg
+endif
+
+EXTRA_CFLAGS += -DHOST=\"$(HOST)\"
+
+obj-$(CONFIG_MXC_GPU_VIV) += galcore.o
+
+galcore-objs := $(OBJS)
+
+endif
diff --git a/drivers/mxc/gpu-viv/Kconfig b/drivers/mxc/gpu-viv/Kconfig
new file mode 100644
index 000000000000..e9cc4b27614c
--- /dev/null
+++ b/drivers/mxc/gpu-viv/Kconfig
@@ -0,0 +1,9 @@
+menu "MXC Vivante GPU support"
+ depends on SOC_IMX6Q
+
+config MXC_GPU_VIV
+ tristate "MXC Vivante GPU support"
+ ---help---
+ Say Y to get the GPU driver support.
+
+endmenu
diff --git a/drivers/mxc/gpu-viv/config b/drivers/mxc/gpu-viv/config
new file mode 100644
index 000000000000..94841414a07a
--- /dev/null
+++ b/drivers/mxc/gpu-viv/config
@@ -0,0 +1,36 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+
+
+ARCH_TYPE ?= arm
+SDK_DIR ?= $(AQROOT)/build/sdk
+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
+ENABLE_OUTER_CACHE_PATCH ?= 1
+USE_BANK_ALIGNMENT ?= 1
+BANK_BIT_START ?= 13
+BANK_BIT_END ?= 15
+BANK_CHANNEL_BIT ?= 12
+PLATFORM ?= freescale/gc_hal_kernel_platform_imx6q14
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.c b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.c
new file mode 100644
index 000000000000..04e669a36a74
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.c
@@ -0,0 +1,2441 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_context.h"
+#include "gc_hal_kernel_buffer.h"
+
+/******************************************************************************\
+******************************** Debugging Macro *******************************
+\******************************************************************************/
+
+/* Zone used for header/footer. */
+#define _GC_OBJ_ZONE gcvZONE_HARDWARE
+
+
+/******************************************************************************\
+************************** Context State Buffer Helpers ************************
+\******************************************************************************/
+
+#define _STATE(reg) \
+ _State(\
+ Context, index, \
+ reg ## _Address >> 2, \
+ reg ## _ResetValue, \
+ reg ## _Count, \
+ gcvFALSE, gcvFALSE \
+ )
+
+#define _STATE_COUNT(reg, count) \
+ _State(\
+ Context, index, \
+ reg ## _Address >> 2, \
+ reg ## _ResetValue, \
+ count, \
+ gcvFALSE, gcvFALSE \
+ )
+
+#define _STATE_COUNT_OFFSET(reg, offset, count) \
+ _State(\
+ Context, index, \
+ (reg ## _Address >> 2) + offset, \
+ reg ## _ResetValue, \
+ count, \
+ gcvFALSE, gcvFALSE \
+ )
+
+#define _STATE_MIRROR_COUNT(reg, mirror, count) \
+ _StateMirror(\
+ Context, \
+ reg ## _Address >> 2, \
+ count, \
+ mirror ## _Address >> 2 \
+ )
+
+#define _STATE_HINT(reg) \
+ _State(\
+ Context, index, \
+ reg ## _Address >> 2, \
+ reg ## _ResetValue, \
+ reg ## _Count, \
+ gcvFALSE, gcvTRUE \
+ )
+
+#define _STATE_HINT_BLOCK(reg, block, count) \
+ _State(\
+ Context, index, \
+ (reg ## _Address >> 2) + (block << reg ## _BLK), \
+ reg ## _ResetValue, \
+ count, \
+ gcvFALSE, gcvTRUE \
+ )
+
+#define _STATE_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, \
+ reg ## _Address >> 2, \
+ reg ## _ResetValue, \
+ reg ## _Count, \
+ 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 _ENABLE(reg, field) \
+ do \
+ { \
+ if (gcmVERIFYFIELDVALUE(data, reg, MASK_ ## field, ENABLED)) \
+ { \
+ enable |= gcmFIELDMASK(reg, field); \
+ } \
+ } \
+ while (gcvFALSE)
+
+#define _BLOCK_COUNT(reg) \
+ ((reg ## _Count) >> (reg ## _BLK))
+
+
+/******************************************************************************\
+*********************** Support Functions and Definitions **********************
+\******************************************************************************/
+
+#define gcdSTATE_MASK \
+ (gcmSETFIELDVALUE(0, AQ_COMMAND_NOP_COMMAND, OPCODE, NOP) | 0xC0FFEE)
+
+#if gcdENABLE_3D
+static gctUINT32
+_TerminateStateBlock(
+ IN gckCONTEXT Context,
+ IN gctUINT32 Index
+ )
+{
+ gctUINT32_PTR buffer;
+ gctUINT32 align;
+
+ /* Determine if we need alignment. */
+ align = (Index & 1) ? 1 : 0;
+
+ /* Address correct index. */
+ buffer = (Context->buffer == gcvNULL)
+ ? gcvNULL
+ : Context->buffer->logical;
+
+ /* Flush the current state block; make sure no pairing with the states
+ to follow happens. */
+ if (align && (buffer != gcvNULL))
+ {
+ buffer[Index] = 0xDEADDEAD;
+ }
+
+ /* Reset last address. */
+ Context->lastAddress = ~0U;
+
+ /* Return alignment requirement. */
+ return align;
+}
+#endif
+
+
+#if (gcdENABLE_3D || gcdENABLE_2D)
+static gctUINT32
+_FlushPipe(
+ IN gckCONTEXT Context,
+ IN gctUINT32 Index,
+ IN gcePIPE_SELECT Pipe
+ )
+{
+ gctUINT32 flushSlots;
+ gctBOOL txCacheFix;
+ gctBOOL fcFlushStall;
+ gctBOOL iCacheInvalidate;
+
+ txCacheFix
+ = gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_TEX_CACHE_FLUSH_FIX);
+
+ 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 (Pipe == gcvPIPE_3D)
+ {
+ if (!txCacheFix)
+ {
+ /* Semaphore stall */
+ flushSlots += 4;
+ }
+
+ /* VST cache */
+ flushSlots += 2;
+ }
+
+ if (fcFlushStall)
+ {
+ /* Flush tile status cache. */
+ flushSlots += 6;
+ }
+
+ if (iCacheInvalidate)
+ {
+ flushSlots += 12;
+ }
+
+ if (Context->buffer != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Address correct index. */
+ buffer = Context->buffer->logical + Index;
+
+ if (Pipe == gcvPIPE_3D && !txCacheFix)
+ {
+ /* 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)));
+ }
+
+ /* Flush the current pipe. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ *buffer++
+ = (Pipe == gcvPIPE_2D)
+ ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
+ : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
+ | ((((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)));
+
+ /* Flush VST in separate cmd. */
+ if (Pipe == gcvPIPE_3D)
+ {
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ *buffer++ = ((((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)));
+ }
+
+ /* 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 (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)));
+ }
+ }
+
+ /* Number of slots taken by flushing pipe. */
+ return flushSlots;
+}
+#endif
+
+#if gcdENABLE_3D
+static gctUINT32
+_SemaphoreStall(
+ IN gckCONTEXT Context,
+ IN gctUINT32 Index
+ )
+{
+ if (Context->buffer != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Address correct index. */
+ buffer = Context->buffer->logical + Index;
+
+ /* 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)));
+ }
+
+ /* Semaphore/stall takes 4 slots. */
+ return 4;
+}
+#endif
+
+#if (gcdENABLE_3D || gcdENABLE_2D)
+static gctUINT32
+_SwitchPipe(
+ IN gckCONTEXT Context,
+ IN gctUINT32 Index,
+ IN gcePIPE_SELECT Pipe
+ )
+{
+ gctUINT32 slots = 6;
+
+ if (Context->buffer != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Address correct index. */
+ buffer = Context->buffer->logical + Index;
+
+ /* LoadState(AQPipeSelect, 1), pipe. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++
+ = (Pipe == gcvPIPE_2D)
+ ? 0x1
+ : 0x0;
+
+ /* 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)));
+ }
+
+ Context->pipeSelectBytes = slots * gcmSIZEOF(gctUINT32);
+
+ return slots;
+}
+#endif
+
+#if gcdENABLE_3D
+static gctUINT32
+_State(
+ IN gckCONTEXT Context,
+ IN gctUINT32 Index,
+ IN gctUINT32 Address,
+ IN gctUINT32 Value,
+ IN gctUINT32 Size,
+ IN gctBOOL FixedPoint,
+ IN gctBOOL Hinted
+ )
+{
+ gctUINT32_PTR buffer;
+ gctUINT32 align;
+ gctUINT32 i;
+
+ /* Determine if we need alignment. */
+ align = (Index & 1) ? 1 : 0;
+
+ /* Address correct index. */
+ buffer = (Context->buffer == gcvNULL)
+ ? gcvNULL
+ : Context->buffer->logical;
+
+ if ((buffer == gcvNULL) && (Address + Size > Context->maxState))
+ {
+ /* Determine maximum state. */
+ Context->maxState = Address + Size;
+ }
+
+ if (buffer == gcvNULL)
+ {
+ /* Update number of states. */
+ Context->numStates += Size;
+ }
+
+ /* Do we need a new entry? */
+ if ((Address != Context->lastAddress) || (FixedPoint != Context->lastFixed))
+ {
+ if (buffer != gcvNULL)
+ {
+ if (align)
+ {
+ /* Add filler. */
+ buffer[Index++] = 0xDEADDEAD;
+ }
+
+ /* LoadState(Address, Count). */
+ gcmkASSERT((Index & 1) == 0);
+
+ if (FixedPoint)
+ {
+ buffer[Index]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) << (0 ? 26:26))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) << (0 ? 26:26)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Size) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+ }
+ else
+ {
+ buffer[Index]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) << (0 ? 26:26))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) << (0 ? 26:26)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Size) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+ }
+
+ /* Walk all the states. */
+ for (i = 0; i < (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 = (gctUINT)Index + 1 + i;
+
+#if gcdSECURE_USER
+ /* Save hint. */
+ if (Context->hint != gcvNULL)
+ {
+ Context->hint[Address + i] = Hinted;
+ }
+#endif
+ }
+ }
+
+ /* Save information for this LoadState. */
+ Context->lastIndex = (gctUINT)Index;
+ Context->lastAddress = Address + (gctUINT32)Size;
+ Context->lastSize = Size;
+ Context->lastFixed = FixedPoint;
+
+ /* Return size for load state. */
+ return align + 1 + Size;
+ }
+
+ /* Append this state to the previous one. */
+ if (buffer != gcvNULL)
+ {
+ /* Update last load state. */
+ buffer[Context->lastIndex] =
+ ((((gctUINT32) (buffer[Context->lastIndex])) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Context->lastSize + Size) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ /* Walk all the states. */
+ for (i = 0; i < (gctUINT32)Size; i += 1)
+ {
+ /* Set state to uninitialized value. */
+ buffer[Index + i] = Value;
+
+ /* Set index in state mapping table. */
+ Context->map[Address + i].index = (gctUINT)Index + i;
+
+#if gcdSECURE_USER
+ /* Save hint. */
+ if (Context->hint != gcvNULL)
+ {
+ Context->hint[Address + i] = Hinted;
+ }
+#endif
+ }
+ }
+
+ /* Update last address and size. */
+ Context->lastAddress += (gctUINT32)Size;
+ Context->lastSize += Size;
+
+ /* Return number of slots required. */
+ return Size;
+}
+
+static gctUINT32
+_StateMirror(
+ IN gckCONTEXT Context,
+ IN gctUINT32 Address,
+ IN gctUINT32 Size,
+ IN gctUINT32 AddressMirror
+ )
+{
+ gctUINT32 i;
+
+ /* Process when buffer is set. */
+ if (Context->buffer != gcvNULL)
+ {
+ /* Walk all states. */
+ for (i = 0; i < Size; i++)
+ {
+ /* Copy the mapping address. */
+ Context->map[Address + i].index =
+ Context->map[AddressMirror + i].index;
+ }
+ }
+
+ /* Return the number of required maps. */
+ return Size;
+}
+#endif
+
+#if (gcdENABLE_3D || gcdENABLE_2D)
+static gceSTATUS
+_InitializeContextBuffer(
+ IN gckCONTEXT Context
+ )
+{
+ gctUINT32_PTR buffer;
+ gctUINT32 index;
+
+#if gcdENABLE_3D
+ gctBOOL halti0, halti1, halti2, halti3;
+ gctUINT i;
+ gctUINT vertexUniforms, fragmentUniforms, vsConstBase, psConstBase, constMax;
+ gctBOOL unifiedUniform;
+ gctUINT fe2vsCount;
+#endif
+
+ /* Reset the buffer index. */
+ index = 0;
+
+ /* Reset the last state address. */
+ Context->lastAddress = ~0U;
+
+ /* Get the buffer pointer. */
+ buffer = (Context->buffer == gcvNULL)
+ ? gcvNULL
+ : Context->buffer->logical;
+
+
+ /**************************************************************************/
+ /* Build 2D states. *******************************************************/
+
+
+#if 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 how many uniforms can support for non-unified uniform mode. */
+ {if (Context->hardware->identity.numConstants > 256){ unifiedUniform = gcvTRUE; vsConstBase = 0xC000; psConstBase = 0xC000; vertexUniforms = gcmMIN(512, Context->hardware->identity.numConstants - 64); fragmentUniforms = gcmMIN(512, Context->hardware->identity.numConstants - 64); constMax = Context->hardware->identity.numConstants;}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;}};
+
+#if !gcdENABLE_UNIFIED_CONSTANT
+ if (Context->hardware->identity.numConstants > 256)
+ {
+ unifiedUniform = gcvTRUE;
+ }
+ else
+ {
+ unifiedUniform = gcvFALSE;
+ }
+#endif
+
+ /* Store the 3D entry index. */
+ Context->entryOffset3D = (gctUINT)index * gcmSIZEOF(gctUINT32);
+
+ /* Switch to 3D pipe. */
+ index += _SwitchPipe(Context, index, gcvPIPE_3D);
+
+ /* Current context pointer. */
+#if gcdDEBUG
+ index += _State(Context, index, 0x03850 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+#endif
+
+ index += _FlushPipe(Context, index, gcvPIPE_3D);
+
+ /* Global states. */
+ index += _State(Context, index, 0x03814 >> 2, 0x00000001, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x03818 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0381C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x03820 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x03828 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0382C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ 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 (halti0)
+ {
+ fe2vsCount = 16;
+ }
+ index += _State(Context, index, 0x00600 >> 2, 0x00000000, fe2vsCount, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+
+ index += _State(Context, index, 0x00644 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x00648 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0064C >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x00650 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00680 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x006A0 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 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);
+ index += _State(Context, index, 0x006C0 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00700 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+ 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, 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 += _CLOSE_RANGE();
+
+ /* Primitive Assembly states. */
+ index += _State(Context, index, 0x00A00 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00A04 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00A08 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A0C >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00A10 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00A14 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A18 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A1C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A28 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A2C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A30 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A40 >> 2, 0x00000000, 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);
+ index += _State(Context, index, 0x00C08 >> 2, 0x45000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00C0C >> 2, 0x45000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00C10 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00C14 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00C18 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00C1C >> 2, 0x42000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00C20 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00C24 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+
+ /* Raster states. */
+ index += _State(Context, index, 0x00E00 >> 2, 0x00000001, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00E10 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00E04 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00E40 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00E08 >> 2, 0x17000031, 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, 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, 0x01030 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ if (halti2)
+ {
+ index += _State(Context, index, 0x0102C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01034 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01038 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ index += _CLOSE_RANGE();
+
+ /* Texture states. */
+ index += _State(Context, index, 0x02000 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02040 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02080 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x020C0 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02100 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02140 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02180 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x021C0 >> 2, 0x00321000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02200 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02240 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, (0x02400 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02440 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02480 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x024C0 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02500 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02540 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02580 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x025C0 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02600 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02640 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02680 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x026C0 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02700 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02740 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _CLOSE_RANGE();
+
+ 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, 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);
+ index += _State(Context, index, 0x10300 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10380 >> 2, 0x00321000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10400 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10480 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+
+ if ((((((gctUINT32) (Context->hardware->identity.chipMinorFeatures2)) >> (0 ? 15:15)) & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1)))))) ))
+ {
+ index += _State(Context, index, 0x12000 >> 2, 0x00000000, 256, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x12400 >> 2, 0x00000000, 256, gcvFALSE, gcvFALSE);
+ }
+
+ 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);
+ index += _State(Context, index, 0x01680 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x01684 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01688 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x0168C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01690 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x01694 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01698 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x0169C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+
+ /* Thread walker states. */
+ index += _State(Context, index, 0x00900 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00904 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00908 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0090C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00910 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00914 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00918 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0091C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _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 (!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 = (gctUINT)index * gcmSIZEOF(gctUINT32);
+
+
+ /* Pixel Engine states. */
+ index += _State(Context, index, 0x01400 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01404 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01408 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0140C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01414 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01418 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0141C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01420 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01424 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01428 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0142C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01434 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01454 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01458 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x0145C >> 2, 0x00000010, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x014A0 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x014A8 >> 2, 0xFFFFFFFF, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x014AC >> 2, 0xFFFFFFFF, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x014B0 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x014B4 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x014A4 >> 2, 0x000E400C, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01580 >> 2, 0x00000000, 3, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x014B8 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ /* Composition states. */
+ index += _State(Context, index, 0x03008 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ if (Context->hardware->identity.pixelPipes == 1)
+ {
+ index += _State(Context, index, 0x01460 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
+
+ index += _State(Context, index, 0x01430 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x01410 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ }
+ else
+ {
+ index += _State(Context, index, (0x01460 >> 2) + (0 << 3), 0x00000000, Context->hardware->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);
+ }
+
+ if (halti2)
+ {
+ for (i = 0; i < 7; i++)
+ {
+ 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 (halti3)
+ {
+ index += _State(Context, index, 0x014BC >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ /* Resolve states. */
+ index += _State(Context, index, 0x01604 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01608 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x0160C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01610 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x01614 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01620 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01630 >> 2, 0x00000000, 2, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01640 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0163C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x016A0 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x016B4 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+
+ if ((Context->hardware->identity.pixelPipes > 1) || halti1)
+ {
+ index += _State(Context, index, (0x016C0 >> 2) + (0 << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
+
+ index += _State(Context, index, (0x016E0 >> 2) + (0 << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
+
+ 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);
+
+ index += _CLOSE_RANGE();
+ index += _State(Context, index, 0x01658 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x0165C >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x01660 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01664 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x01668 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x0166C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01670 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01674 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x016A4 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x016AC >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x016A8 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ 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
+
+ /**************************************************************************/
+ /* Link to another address. ***********************************************/
+
+ Context->linkIndex3D = (gctUINT)index;
+
+ if (buffer != gcvNULL)
+ {
+ buffer[index + 0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ buffer[index + 1]
+ = 0;
+ }
+
+ index += 2;
+
+ /* Store the end of the context buffer. */
+ Context->bufferSize = index * gcmSIZEOF(gctUINT32);
+
+
+ /**************************************************************************/
+ /* Pipe switch for the case where neither 2D nor 3D are used. *************/
+
+ /* Store the 3D entry index. */
+ Context->entryOffsetXDFrom2D = (gctUINT)index * gcmSIZEOF(gctUINT32);
+
+ /* Flush 2D pipe. */
+ index += _FlushPipe(Context, index, gcvPIPE_2D);
+
+ /* Switch to 3D pipe. */
+ index += _SwitchPipe(Context, index, gcvPIPE_3D);
+
+ /* Store the location of the link. */
+ Context->linkIndexXD = (gctUINT)index;
+
+ if (buffer != gcvNULL)
+ {
+ buffer[index + 0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ buffer[index + 1]
+ = 0;
+ }
+
+ index += 2;
+
+
+ /**************************************************************************/
+ /* Save size for buffer. **************************************************/
+
+ Context->totalSize = index * gcmSIZEOF(gctUINT32);
+
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+#endif
+
+static gceSTATUS
+_DestroyContext(
+ IN gckCONTEXT Context
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ if (Context != gcvNULL)
+ {
+ gcsCONTEXT_PTR bufferHead;
+
+ /* Free context buffers. */
+ for (bufferHead = Context->buffer; Context->buffer != gcvNULL;)
+ {
+ /* Get a shortcut to the current buffer. */
+ gcsCONTEXT_PTR buffer = Context->buffer;
+
+ /* Get the next buffer. */
+ gcsCONTEXT_PTR next = buffer->next;
+
+ /* Last item? */
+ if (next == bufferHead)
+ {
+ next = gcvNULL;
+ }
+
+ /* Destroy the signal. */
+ if (buffer->signal != gcvNULL)
+ {
+ gcmkONERROR(gckOS_DestroySignal(
+ Context->os, buffer->signal
+ ));
+
+ buffer->signal = gcvNULL;
+ }
+
+ /* Free state delta map. */
+ if (buffer->logical != gcvNULL)
+ {
+ 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;
+ }
+
+ /* Free context buffer. */
+ gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, buffer));
+
+ /* Remove from the list. */
+ Context->buffer = next;
+ }
+
+#if gcdSECURE_USER
+ /* Free the hint array. */
+ if (Context->hint != gcvNULL)
+ {
+ gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->hint));
+ }
+#endif
+ /* Free record array copy. */
+#if 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
+
+ /* Mark the gckCONTEXT object as unknown. */
+ Context->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckCONTEXT object. */
+ gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context));
+ }
+
+OnError:
+ return status;
+}
+
+
+/******************************************************************************\
+**************************** Context Management API ****************************
+\******************************************************************************/
+
+/******************************************************************************\
+**
+** gckCONTEXT_Construct
+**
+** Construct a new gckCONTEXT object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctUINT32 ProcessID
+** Current process ID.
+**
+** gckHARDWARE Hardware
+** Pointer to gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gckCONTEXT * Context
+** Pointer to a variable thet will receive the gckCONTEXT object
+** pointer.
+*/
+#if (gcdENABLE_3D || gcdENABLE_2D)
+gceSTATUS
+gckCONTEXT_Construct(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 ProcessID,
+ OUT gckCONTEXT * Context
+ )
+{
+ gceSTATUS status;
+ gckCONTEXT context = gcvNULL;
+ gctUINT32 allocationSize;
+ gctUINT i;
+ gctPOINTER pointer = gcvNULL;
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Os=0x%08X Hardware=0x%08X", Os, Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Context != gcvNULL);
+
+
+ /**************************************************************************/
+ /* Allocate and initialize basic fields of gckCONTEXT. ********************/
+
+ /* The context object size. */
+ allocationSize = gcmSIZEOF(struct _gckCONTEXT);
+
+ /* Allocate the object. */
+ gcmkONERROR(gckOS_Allocate(
+ Os, allocationSize, &pointer
+ ));
+
+ context = pointer;
+
+ /* Reset the entire object. */
+ gcmkONERROR(gckOS_ZeroMemory(context, allocationSize));
+
+ /* Initialize the gckCONTEXT object. */
+ context->object.type = gcvOBJ_CONTEXT;
+ context->os = Os;
+ context->hardware = Hardware;
+
+
+#if !gcdENABLE_3D
+ context->entryPipe = gcvPIPE_2D;
+ context->exitPipe = gcvPIPE_2D;
+#elif gcdCMD_NO_2D_CONTEXT
+ context->entryPipe = gcvPIPE_3D;
+ context->exitPipe = gcvPIPE_3D;
+#else
+ context->entryPipe
+ = (((((gctUINT32) (context->hardware->identity.chipFeatures)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) )
+ ? gcvPIPE_2D
+ : gcvPIPE_3D;
+ context->exitPipe = gcvPIPE_3D;
+#endif
+
+ /* Get the command buffer requirements. */
+ gcmkONERROR(gckHARDWARE_QueryCommandBuffer(
+ Hardware,
+ &context->alignment,
+ &context->reservedHead,
+ &context->reservedTail
+ ));
+
+ /* Mark the context as dirty to force loading of the entire state table
+ the first time. */
+ context->dirty = gcvTRUE;
+
+
+ /**************************************************************************/
+ /* Get the size of the context buffer. ************************************/
+
+ gcmkONERROR(_InitializeContextBuffer(context));
+
+
+ /**************************************************************************/
+ /* Compute the size of the record array. **********************************/
+
+ context->recordArraySize
+#ifdef DISABLE_RECORD_ARRAY_SIZE_OPTIMIZATION
+ = gcmSIZEOF(gcsSTATE_DELTA_RECORD) * (gctUINT)context->maxState;
+#else
+ = gcmSIZEOF(gcsSTATE_DELTA_RECORD) * (gctUINT)context->numStates;
+#endif
+
+
+ if (context->maxState > 0)
+ {
+ /**************************************************************************/
+ /* Allocate and reset the state mapping table. ****************************/
+ if (context->hardware->kernel->command->stateMap == gcvNULL)
+ {
+ /* Allocate the state mapping table. */
+ gcmkONERROR(gckOS_Allocate(
+ Os,
+ gcmSIZEOF(gcsSTATE_MAP) * context->maxState,
+ &pointer
+ ));
+
+ context->map = pointer;
+
+ /* Zero the state mapping table. */
+ gcmkONERROR(gckOS_ZeroMemory(
+ context->map, gcmSIZEOF(gcsSTATE_MAP) * context->maxState
+ ));
+
+ context->hardware->kernel->command->stateMap = pointer;
+ }
+ else
+ {
+ context->map = context->hardware->kernel->command->stateMap;
+ }
+
+ /**************************************************************************/
+ /* Allocate the hint array. ***********************************************/
+
+#if gcdSECURE_USER
+ /* Allocate hints. */
+ gcmkONERROR(gckOS_Allocate(
+ Os,
+ gcmSIZEOF(gctBOOL) * context->maxState,
+ &pointer
+ ));
+
+ context->hint = pointer;
+#endif
+ }
+
+ /**************************************************************************/
+ /* Allocate the context and state delta buffers. **************************/
+
+ for (i = 0; i < gcdCONTEXT_BUFFER_COUNT; i += 1)
+ {
+ /* Allocate a context buffer. */
+ gcsCONTEXT_PTR buffer;
+
+ gctSIZE_T totalSize = context->totalSize;
+
+ /* Allocate the context buffer structure. */
+ gcmkONERROR(gckOS_Allocate(
+ Os,
+ gcmSIZEOF(gcsCONTEXT),
+ &pointer
+ ));
+
+ buffer = pointer;
+
+ /* Reset the context buffer structure. */
+ gcmkVERIFY_OK(gckOS_ZeroMemory(
+ buffer, gcmSIZEOF(gcsCONTEXT)
+ ));
+
+ /* Append to the list. */
+ if (context->buffer == gcvNULL)
+ {
+ buffer->next = buffer;
+ context->buffer = buffer;
+ }
+ else
+ {
+ buffer->next = context->buffer->next;
+ context->buffer->next = buffer;
+ }
+
+ /* Set the number of delta in the order of creation. */
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ buffer->num = i;
+#endif
+
+ /* Create the busy signal. */
+ gcmkONERROR(gckOS_CreateSignal(
+ Os, gcvFALSE, &buffer->signal
+ ));
+
+ /* Set the signal, buffer is currently not busy. */
+ gcmkONERROR(gckOS_Signal(
+ Os, buffer->signal, gcvTRUE
+ ));
+
+ /* Create a new physical context buffer. */
+ if (context->hardware->kernel->virtualCommandBuffer)
+ {
+ gcmkONERROR(gckKERNEL_AllocateVirtualCommandBuffer(
+ context->hardware->kernel,
+ gcvFALSE,
+ &totalSize,
+ &buffer->physical,
+ &pointer
+ ));
+
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ context->hardware->kernel,
+ pointer,
+ gcvFALSE,
+ buffer->physical,
+ &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;
+
+ /* Set the pointers to the LINK commands. */
+ if (context->linkIndex2D != 0)
+ {
+ buffer->link2D = &buffer->logical[context->linkIndex2D];
+ }
+
+ if (context->linkIndex3D != 0)
+ {
+ buffer->link3D = &buffer->logical[context->linkIndex3D];
+ }
+
+ if (context->linkIndexXD != 0)
+ {
+ gctPOINTER xdLink;
+ gctUINT32 xdEntryAddress;
+ gctUINT32 xdEntrySize;
+ gctUINT32 linkBytes;
+
+ /* Determine LINK parameters. */
+ xdLink
+ = &buffer->logical[context->linkIndexXD];
+
+ xdEntryAddress
+ = buffer->address
+ + context->entryOffsetXDFrom3D;
+
+ xdEntrySize
+ = context->bufferSize
+ - context->entryOffsetXDFrom3D;
+
+ /* Query LINK size. */
+ gcmkONERROR(gckHARDWARE_Link(
+ Hardware, gcvNULL, 0, 0, &linkBytes, gcvNULL, gcvNULL
+ ));
+
+ /* Generate a LINK. */
+ gcmkONERROR(gckHARDWARE_Link(
+ Hardware,
+ xdLink,
+ xdEntryAddress,
+ xdEntrySize,
+ &linkBytes,
+ gcvNULL,
+ gcvNULL
+ ));
+ }
+ }
+
+
+ /**************************************************************************/
+ /* Initialize the context buffers. ****************************************/
+
+ /* Initialize the current context buffer. */
+ gcmkONERROR(_InitializeContextBuffer(context));
+
+ /* Make all created contexts equal. */
+ {
+ gcsCONTEXT_PTR currContext, tempContext;
+
+ /* Set the current context buffer. */
+ currContext = context->buffer;
+
+ /* Get the next context buffer. */
+ tempContext = currContext->next;
+
+ /* Loop through all buffers. */
+ while (tempContext != currContext)
+ {
+ if (tempContext == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+
+ /* Copy the current context. */
+ gckOS_MemCopy(
+ tempContext->logical,
+ currContext->logical,
+ context->totalSize
+ );
+
+ /* Get the next context buffer. */
+ tempContext = tempContext->next;
+ }
+ }
+
+ /* Return pointer to the gckCONTEXT object. */
+ *Context = context;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Context=0x%08X", *Context);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back on error. */
+ gcmkVERIFY_OK(_DestroyContext(context));
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/******************************************************************************\
+**
+** gckCONTEXT_Destroy
+**
+** Destroy a gckCONTEXT object.
+**
+** INPUT:
+**
+** gckCONTEXT Context
+** Pointer to an gckCONTEXT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCONTEXT_Destroy(
+ IN gckCONTEXT Context
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Context=0x%08X", Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
+
+ /* Destroy the context and all related objects. */
+ status = _DestroyContext(Context);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return status;
+}
+
+/******************************************************************************\
+**
+** gckCONTEXT_Update
+**
+** Merge all pending state delta buffers into the current context buffer.
+**
+** INPUT:
+**
+** gckCONTEXT Context
+** Pointer to an gckCONTEXT object.
+**
+** gctUINT32 ProcessID
+** Current process ID.
+**
+** gcsSTATE_DELTA_PTR StateDelta
+** Pointer to the state delta.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCONTEXT_Update(
+ IN gckCONTEXT Context,
+ IN gctUINT32 ProcessID,
+ IN gcsSTATE_DELTA_PTR StateDelta
+ )
+{
+#if gcdENABLE_3D
+ gceSTATUS status = gcvSTATUS_OK;
+ gcsSTATE_DELTA _stateDelta;
+ gckKERNEL kernel;
+ gcsCONTEXT_PTR buffer;
+ gcsSTATE_MAP_PTR map;
+ gctBOOL needCopy = gcvFALSE;
+ gcsSTATE_DELTA_PTR nDelta;
+ gcsSTATE_DELTA_PTR uDelta = gcvNULL;
+ gcsSTATE_DELTA_PTR kDelta = gcvNULL;
+ gcsSTATE_DELTA_RECORD_PTR record;
+ gcsSTATE_DELTA_RECORD_PTR recordArray = gcvNULL;
+#if REMOVE_DUPLICATED_COPY_FROM_USER
+ gcsRECORD_ARRAY_MAP_PTR recordArrayMap = gcvNULL;
+#endif
+ gctUINT elementCount;
+ gctUINT address;
+ gctUINT32 mask;
+ gctUINT32 data;
+ gctUINT index;
+ gctUINT i, j;
+ gctUINT32 dirtyRecordArraySize;
+
+#if gcdSECURE_USER
+ gcskSECURE_CACHE_PTR cache;
+#endif
+
+ gcmkHEADER_ARG(
+ "Context=0x%08X ProcessID=%d StateDelta=0x%08X",
+ Context, ProcessID, StateDelta
+ );
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
+
+ /* Get a shortcut to the kernel object. */
+ kernel = Context->hardware->kernel;
+
+ /* Check wehther we need to copy the structures or not. */
+ gcmkONERROR(gckOS_QueryNeedCopy(Context->os, ProcessID, &needCopy));
+
+ /* Allocate the copy buffer for the user record array. */
+#if 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. */
+ gcmkONERROR(gckOS_Allocate(
+ Context->os,
+ Context->recordArraySize,
+ (gctPOINTER *) &Context->recordArray
+ ));
+ }
+#endif
+
+ /* Get the current context buffer. */
+ buffer = Context->buffer;
+
+ /* Wait until the context buffer becomes available; this will
+ also reset the signal and mark the buffer as busy. */
+ gcmkONERROR(gckOS_WaitSignal(
+ Context->os, buffer->signal, gcvINFINITE
+ ));
+
+#if gcdSECURE_USER
+ /* Get the cache form the database. */
+ gcmkONERROR(gckKERNEL_GetProcessDBCache(kernel, ProcessID, &cache));
+#endif
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE) && 1 && gcdENABLE_3D
+ /* Update current context token. */
+ buffer->logical[Context->map[0x0E14].index]
+ = (gctUINT32)gcmPTR2INT32(Context);
+#endif
+
+ /* Are there any pending deltas? */
+ if (buffer->deltaCount != 0)
+ {
+ /* Get the state map. */
+ map = Context->map;
+
+ /* Get the first delta item. */
+ uDelta = buffer->delta;
+
+ /* Reset the vertex stream count. */
+ elementCount = 0;
+
+ /* Merge all pending deltas. */
+ for (i = 0; i < buffer->deltaCount; i += 1)
+ {
+ /* Get access to the state delta. */
+ gcmkONERROR(gckKERNEL_OpenUserData(
+ kernel, needCopy,
+ &_stateDelta,
+ uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+ (gctPOINTER *) &kDelta
+ ));
+
+ dirtyRecordArraySize
+ = gcmSIZEOF(gcsSTATE_DELTA_RECORD) * kDelta->recordCount;
+
+#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;
+ }
+
+ if (dirtyRecordArraySize)
+ {
+ /* Get access to the state records. */
+ gcmkONERROR(gckOS_CopyFromUserData(
+ kernel->os,
+ recordArrayMap->kData,
+ gcmUINT64_TO_PTR(kDelta->recordArray),
+ dirtyRecordArraySize
+ ));
+ }
+
+ /* Save user pointer as key. */
+ recordArrayMap->key = kDelta->recordArray;
+ recordArray = recordArrayMap->kData;
+ }
+ }
+ else
+ {
+ if (dirtyRecordArraySize)
+ {
+ /* Get access to the state records. */
+ gcmkONERROR(gckOS_MapUserPointer(
+ kernel->os,
+ gcmUINT64_TO_PTR(kDelta->recordArray),
+ dirtyRecordArraySize,
+ (gctPOINTER *) &recordArray
+ ));
+ }
+ }
+#else
+ if (dirtyRecordArraySize)
+ {
+ /* Get access to the state records. */
+ gcmkONERROR(gckKERNEL_OpenUserData(
+ kernel, needCopy,
+ Context->recordArray,
+ gcmUINT64_TO_PTR(kDelta->recordArray),
+ dirtyRecordArraySize,
+ (gctPOINTER *) &recordArray
+ ));
+ }
+#endif
+
+ /* Merge all pending states. */
+ for (j = 0; j < kDelta->recordCount; j += 1)
+ {
+ if (j >= Context->numStates)
+ {
+ break;
+ }
+
+ /* Get the current state record. */
+ record = &recordArray[j];
+
+ /* Get the state address. */
+ address = record->address;
+
+ /* Make sure the state is a part of the mapping table. */
+ if (address >= Context->maxState)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): State 0x%04X is not mapped.\n",
+ __FUNCTION__, __LINE__,
+ address
+ );
+
+ continue;
+ }
+
+ /* Get the state index. */
+ index = map[address].index;
+
+ /* Skip the state if not mapped. */
+ if (index == 0)
+ {
+ continue;
+ }
+
+ /* Get the data mask. */
+ mask = record->mask;
+
+ /* Masked states that are being completly reset or regular states. */
+ if ((mask == 0) || (mask == ~0U))
+ {
+ /* Get the new data value. */
+ data = record->data;
+
+ /* Process special states. */
+ if (address == 0x0595)
+ {
+ /* Force auto-disable to be disabled. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1))))))) << (0 ? 13:13))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1))))))) << (0 ? 13:13)));
+ }
+
+#if gcdSECURE_USER
+ /* Do we need to convert the logical address? */
+ if (Context->hint[address])
+ {
+ /* Map handle into physical address. */
+ gcmkONERROR(gckKERNEL_MapLogicalToPhysical(
+ kernel, cache, (gctPOINTER) &data
+ ));
+ }
+#endif
+
+ /* Set new data. */
+ buffer->logical[index] = data;
+ }
+
+ /* Masked states that are being set partially. */
+ else
+ {
+ buffer->logical[index]
+ = (~mask & buffer->logical[index])
+ | (mask & record->data);
+ }
+ }
+
+ /* Get the element count. */
+ if (kDelta->elementCount != 0)
+ {
+ elementCount = kDelta->elementCount;
+ }
+
+ /* Dereference delta. */
+ kDelta->refCount -= 1;
+ gcmkASSERT(kDelta->refCount >= 0);
+
+ /* Get the next state delta. */
+ nDelta = 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
+ {
+ if (dirtyRecordArraySize)
+ {
+ /* Close access to the state records. */
+ gcmkONERROR(gckOS_UnmapUserPointer(
+ kernel->os,
+ gcmUINT64_TO_PTR(kDelta->recordArray),
+ dirtyRecordArraySize,
+ (gctPOINTER *) recordArray
+ ));
+ }
+
+ recordArray = gcvNULL;
+ }
+#else
+ if (dirtyRecordArraySize)
+ {
+ /* Get access to the state records. */
+ gcmkONERROR(gckKERNEL_CloseUserData(
+ kernel, needCopy,
+ gcvFALSE,
+ gcmUINT64_TO_PTR(kDelta->recordArray),
+ dirtyRecordArraySize,
+ (gctPOINTER *) &recordArray
+ ));
+ }
+#endif
+
+ /* Close access to the current state delta. */
+ gcmkONERROR(gckKERNEL_CloseUserData(
+ kernel, needCopy,
+ gcvTRUE,
+ uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+ (gctPOINTER *) &kDelta
+ ));
+
+ /* Update the user delta pointer. */
+ uDelta = nDelta;
+ }
+
+ /* Hardware disables all input streams when the stream 0 is programmed,
+ it then reenables those streams that were explicitely programmed by
+ the software. Because of this we cannot program the entire array of
+ values, otherwise we'll get all streams reenabled, but rather program
+ only those that are actully needed by the software. */
+ if (elementCount != 0)
+ {
+ gctUINT base;
+ gctUINT nopCount;
+ gctUINT32_PTR nop;
+ gctUINT fe2vsCount = 12;
+
+ if ((((((gctUINT32) (Context->hardware->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;
+ }
+
+ /* Determine the base index of the vertex stream array. */
+ base = map[0x0180].index;
+
+ /* Set the proper state count. */
+ buffer->logical[base - 1]
+ = ((((gctUINT32) (buffer->logical[base - 1])) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (elementCount ) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ /* Determine the number of NOP commands. */
+ nopCount
+ = (fe2vsCount / 2)
+ - (elementCount / 2);
+
+ /* Determine the location of the first NOP. */
+ nop = &buffer->logical[base + (elementCount | 1)];
+
+ /* Fill the unused space with NOPs. */
+ for (i = 0; i < nopCount; i += 1)
+ {
+ if (nop >= buffer->logical + Context->totalSize)
+ {
+ break;
+ }
+
+ /* Generate a NOP command. */
+ *nop = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+ /* Advance. */
+ nop += 2;
+ }
+ }
+
+ /* Reset pending deltas. */
+ buffer->deltaCount = 0;
+ buffer->delta = gcvNULL;
+ }
+
+ /* Set state delta user pointer. */
+ uDelta = StateDelta;
+
+ /* Get access to the state delta. */
+ gcmkONERROR(gckKERNEL_OpenUserData(
+ kernel, needCopy,
+ &_stateDelta,
+ uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+ (gctPOINTER *) &kDelta
+ ));
+
+ /* State delta cannot be attached to anything yet. */
+ if (kDelta->refCount != 0)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): kDelta->refCount = %d (has to be 0).\n",
+ __FUNCTION__, __LINE__,
+ kDelta->refCount
+ );
+ }
+
+ /* Attach to all contexts. */
+ buffer = Context->buffer;
+
+ do
+ {
+ /* Attach to the context if nothing is attached yet. If a delta
+ is allready attached, all we need to do is to increment
+ the number of deltas in the context. */
+ if (buffer->delta == gcvNULL)
+ {
+ buffer->delta = uDelta;
+ }
+
+ /* Update reference count. */
+ kDelta->refCount += 1;
+
+ /* Update counters. */
+ buffer->deltaCount += 1;
+
+ /* Get the next context buffer. */
+ buffer = buffer->next;
+
+ if (buffer == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+ }
+ while (Context->buffer != buffer);
+
+ /* Close access to the current state delta. */
+ gcmkONERROR(gckKERNEL_CloseUserData(
+ kernel, needCopy,
+ gcvTRUE,
+ uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+ (gctPOINTER *) &kDelta
+ ));
+
+ /* Schedule an event to mark the context buffer as available. */
+ gcmkONERROR(gckEVENT_Signal(
+ buffer->eventObj, buffer->signal, gcvKERNEL_PIXEL
+ ));
+
+ /* Advance to the next context buffer. */
+ Context->buffer = buffer->next;
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Get access to the state records. */
+ if (kDelta != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+ kernel, needCopy,
+ gcvFALSE,
+ gcmUINT64_TO_PTR(kDelta->recordArray), Context->recordArraySize,
+ (gctPOINTER *) &recordArray
+ ));
+ }
+
+ /* Close access to the current state delta. */
+ gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+ kernel, needCopy,
+ gcvTRUE,
+ uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+ (gctPOINTER *) &kDelta
+ ));
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+#else
+ return gcvSTATUS_OK;
+#endif
+}
+
+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;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.h b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.h
new file mode 100644
index 000000000000..b02878b82339
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.h
@@ -0,0 +1,247 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_context_h_
+#define __gc_hal_kernel_context_h_
+
+#include "gc_hal_kernel_buffer.h"
+
+/* Exprimental optimization. */
+#define REMOVE_DUPLICATED_COPY_FROM_USER 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Maps state locations within the context buffer. */
+typedef struct _gcsSTATE_MAP * gcsSTATE_MAP_PTR;
+typedef struct _gcsSTATE_MAP
+{
+ /* Index of the state in the context buffer. */
+ gctUINT index;
+
+ /* State mask. */
+ gctUINT32 mask;
+}
+gcsSTATE_MAP;
+
+/* Context buffer. */
+typedef struct _gcsCONTEXT * gcsCONTEXT_PTR;
+typedef struct _gcsCONTEXT
+{
+ /* For debugging: the number of context buffer in the order of creation. */
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ gctUINT num;
+#endif
+
+ /* Pointer to gckEVENT object. */
+ gckEVENT eventObj;
+
+ /* Context busy signal. */
+ gctSIGNAL signal;
+
+ /* Physical address of the context buffer. */
+ gctPHYS_ADDR physical;
+
+ /* Logical address of the context buffer. */
+ gctUINT32_PTR logical;
+
+ /* Hardware address of the context buffer. */
+ gctUINT32 address;
+
+ /* Pointer to the LINK commands. */
+ gctPOINTER link2D;
+ gctPOINTER link3D;
+
+ /* The number of pending state deltas. */
+ gctUINT deltaCount;
+
+ /* Pointer to the first delta to be applied. */
+ gcsSTATE_DELTA_PTR delta;
+
+ /* Next context buffer. */
+ gcsCONTEXT_PTR next;
+}
+gcsCONTEXT;
+
+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;
+
+};
+
+#define USE_SW_RESET 1
+
+/* gckCONTEXT structure that hold the current context. */
+struct _gckCONTEXT
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Pointer to gckHARDWARE object. */
+ gckHARDWARE hardware;
+
+ /* Command buffer alignment. */
+ gctUINT32 alignment;
+ gctUINT32 reservedHead;
+ gctUINT32 reservedTail;
+
+ /* Context buffer metrics. */
+ gctSIZE_T maxState;
+ gctUINT32 numStates;
+ gctUINT32 totalSize;
+ gctUINT32 bufferSize;
+ gctUINT32 linkIndex2D;
+ gctUINT32 linkIndex3D;
+ gctUINT32 linkIndexXD;
+ gctUINT32 entryOffset3D;
+ gctUINT32 entryOffsetXDFrom2D;
+ gctUINT32 entryOffsetXDFrom3D;
+
+ /* Dirty flags. */
+ gctBOOL dirty;
+ gctBOOL dirty2D;
+ gctBOOL dirty3D;
+ gcsCONTEXT_PTR dirtyBuffer;
+
+ /* State mapping. */
+ gcsSTATE_MAP_PTR map;
+
+ /* List of context buffers. */
+ gcsCONTEXT_PTR buffer;
+
+ /* A copy of the user record array. */
+ gctUINT recordArraySize;
+#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;
+ gcePIPE_SELECT exitPipe;
+
+ /* Variables used for building state buffer. */
+ gctUINT32 lastAddress;
+ gctSIZE_T lastSize;
+ gctUINT32 lastIndex;
+ gctBOOL lastFixed;
+
+ gctUINT32 pipeSelectBytes;
+
+ /* Hint array. */
+#if gcdSECURE_USER
+ gctBOOL_PTR hint;
+#endif
+
+#if VIVANTE_PROFILER_CONTEXT
+ gcsPROFILER_COUNTERS latestProfiler;
+ gcsPROFILER_COUNTERS histroyProfiler;
+
+#if USE_SW_RESET
+ /* RA */
+ gctUINT32 prevRaValidPixelCount;
+ gctUINT32 prevRaTotalQuadCount;
+ gctUINT32 prevRaValidQuadCountAfterEarlyZ;
+ gctUINT32 prevRaTotalPrimitiveCount;
+ gctUINT32 prevRaPipeCacheMissCounter;
+ gctUINT32 prevRaPrefetchCacheMissCounter;
+
+ /* PE */
+ gctUINT32 prevPePixelCountKilledByColorPipe;
+ gctUINT32 prevPePixelCountKilledByDepthPipe;
+ gctUINT32 prevPePixelCountDrawnByColorPipe;
+ gctUINT32 prevPePixelCountDrawnByDepthPipe;
+
+ /* PA */
+ gctUINT32 prevPaInputVtxCounter;
+ gctUINT32 prevPaInputPrimCounter;
+ gctUINT32 prevPaOutputPrimCounter;
+ gctUINT32 prevPaDepthClippedCounter;
+ gctUINT32 prevPaTrivialRejectedCounter;
+ gctUINT32 prevPaCulledCounter;
+
+ /* SH */
+ gctUINT32 prevVSInstCount;
+ gctUINT32 prevVSBranchInstCount;
+ gctUINT32 prevVSTexInstCount;
+ gctUINT32 prevVSVertexCount;
+ gctUINT32 prevPSInstCount;
+ gctUINT32 prevPSBranchInstCount;
+ gctUINT32 prevPSTexInstCount;
+ gctUINT32 prevPSPixelCount;
+#endif
+
+#endif
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_context_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c
new file mode 100644
index 000000000000..d672d859e2bd
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c
@@ -0,0 +1,8454 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+#if VIVANTE_PROFILER_CONTEXT
+#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
+{
+ gctSTRING module;
+ gctUINT index;
+ gctUINT shift;
+ gctUINT data;
+ gctUINT count;
+ gctUINT32 signature;
+}
+gcsiDEBUG_REGISTERS;
+
+/******************************************************************************\
+********************************* 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,
+ IN gckOS Os,
+ IN gceCORE Core
+ );
+
+static gceSTATUS
+_IdentifyHardware(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
+ )
+{
+ gceSTATUS status;
+
+ gctUINT32 chipIdentity;
+
+ gctUINT32 streamCount = 0;
+ gctUINT32 registerMax = 0;
+ gctUINT32 threadCount = 0;
+ gctUINT32 shaderCoreCount = 0;
+ gctUINT32 vertexCacheSize = 0;
+ gctUINT32 vertexOutputBufferSize = 0;
+ gctUINT32 pixelPipes = 0;
+ gctUINT32 instructionCount = 0;
+ gctUINT32 numConstants = 0;
+ gctUINT32 bufferSize = 0;
+ gctUINT32 varyingsCount = 0;
+#if gcdMULTI_GPU
+ gctUINT32 gpuCoreCount = 0;
+#endif
+ gctUINT32 debugControl0 = 0;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /***************************************************************************
+ ** Get chip ID and revision.
+ */
+
+ /* Read chip identity register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00018,
+ &chipIdentity));
+
+ /* Special case for older graphic cores. */
+ if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
+ {
+ Identity->chipModel = gcv500;
+ Identity->chipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
+ }
+
+ else
+ {
+ /* Read chip identity register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00020,
+ (gctUINT32_PTR) &Identity->chipModel));
+
+ if (((Identity->chipModel & 0xFF00) == 0x0400)
+ && (Identity->chipModel != 0x0420)
+ && (Identity->chipModel != 0x0428))
+ {
+ Identity->chipModel = (gceCHIPMODEL) (Identity->chipModel & 0x0400);
+ }
+
+ /* Read CHIP_REV register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00024,
+ &Identity->chipRevision));
+
+ if ((Identity->chipModel == gcv2000) && (Identity->chipRevision & 0xffff0000) == 0xffff0000)
+ {
+ Identity->chipModel = gcv3000;
+ Identity->chipRevision &= 0xffff;
+ Identity->chipFlags |= gcvCHIP_FLAG_GC2000_R2;
+ }
+
+ if ((Identity->chipModel == gcv300)
+ && (Identity->chipRevision == 0x2201)
+ )
+ {
+ gctUINT32 chipDate;
+ gctUINT32 chipTime;
+
+ /* Read date and time registers. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00028,
+ &chipDate));
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x0002C,
+ &chipTime));
+
+ if ((chipDate == 0x20080814) && (chipTime == 0x12051100))
+ {
+ /* This IP has an ECO; put the correct revision in it. */
+ Identity->chipRevision = 0x1051;
+ }
+ }
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x000A8,
+ &Identity->productID));
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Identity: chipModel=%X",
+ Identity->chipModel);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Identity: chipRevision=%X",
+ Identity->chipRevision);
+
+
+ /***************************************************************************
+ ** Get chip features.
+ */
+
+ /* Read chip feature register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x0001C,
+ &Identity->chipFeatures));
+
+#if gcdENABLE_3D
+ /* Disable fast clear on GC700. */
+ if (Identity->chipModel == gcv700)
+ {
+ Identity->chipFeatures
+ = ((((gctUINT32) (Identity->chipFeatures)) & ~(((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)));
+ }
+#endif
+
+ if (((Identity->chipModel == gcv500) && (Identity->chipRevision < 2))
+ || ((Identity->chipModel == gcv300) && (Identity->chipRevision < 0x2000))
+ )
+ {
+ /* GC500 rev 1.x and GC300 rev < 2.0 doesn't have these registers. */
+ Identity->chipMinorFeatures = 0;
+ Identity->chipMinorFeatures1 = 0;
+ Identity->chipMinorFeatures2 = 0;
+ Identity->chipMinorFeatures3 = 0;
+ Identity->chipMinorFeatures4 = 0;
+ Identity->chipMinorFeatures5 = 0;
+ Identity->chipMinorFeatures6 = 0;
+ }
+ else
+ {
+ /* Read chip minor feature register #0. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00034,
+ &Identity->chipMinorFeatures));
+
+ 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)))))))
+ )
+ {
+ /* Read chip minor featuress register #1. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00074,
+ &Identity->chipMinorFeatures1));
+
+ /* Read chip minor featuress register #2. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00084,
+ &Identity->chipMinorFeatures2));
+
+ /*Identity->chipMinorFeatures2 &= ~(0x1 << 3);*/
+
+ /* Read chip minor featuress register #1. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00088,
+ &Identity->chipMinorFeatures3));
+
+
+ /* 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));
+
+ /* Read chip minor featuress register #6. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x000DC,
+ &Identity->chipMinorFeatures6));
+ }
+ else
+ {
+ /* Chip doesn't has minor features register #1 or 2 or 3 or 4. */
+ Identity->chipMinorFeatures1 = 0;
+ Identity->chipMinorFeatures2 = 0;
+ Identity->chipMinorFeatures3 = 0;
+ Identity->chipMinorFeatures4 = 0;
+ Identity->chipMinorFeatures5 = 0;
+ Identity->chipMinorFeatures6 = 0;
+ }
+ }
+
+ /* Get the Supertile layout in the hardware. */
+ if (((((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))))))))
+ {
+ Identity->superTileMode = 2;
+ }
+ else if (((((gctUINT32) (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))))))))
+ {
+ Identity->superTileMode = 1;
+ }
+ else
+ {
+ Identity->superTileMode = 0;
+ }
+
+ /* Exception for GC1000, revision 5035 & GC800, revision 4612 */
+ if (((Identity->chipModel == gcv1000) && ((Identity->chipRevision == 0x5035)
+ || (Identity->chipRevision == 0x5036)
+ || (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;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Identity: chipFeatures=0x%08X",
+ Identity->chipFeatures);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Identity: chipMinorFeatures=0x%08X",
+ Identity->chipMinorFeatures);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Identity: chipMinorFeatures1=0x%08X",
+ Identity->chipMinorFeatures1);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Identity: chipMinorFeatures2=0x%08X",
+ Identity->chipMinorFeatures2);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Identity: chipMinorFeatures3=0x%08X",
+ Identity->chipMinorFeatures3);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Identity: chipMinorFeatures4=0x%08X",
+ Identity->chipMinorFeatures4);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Identity: chipMinorFeatures5=0x%08X",
+ Identity->chipMinorFeatures5);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Identity: chipMinorFeatures6=0x%08X",
+ Identity->chipMinorFeatures6);
+
+ /***************************************************************************
+ ** 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, specs4;
+
+ /* Read gcChipSpecs register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00048,
+ &specs));
+
+ /* Extract the fields. */
+ registerMax = (((((gctUINT32) (specs)) >> (0 ? 7:4)) & ((gctUINT32) ((((1 ? 7:4) - (0 ? 7:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:4) - (0 ? 7:4) + 1)))))) );
+ threadCount = (((((gctUINT32) (specs)) >> (0 ? 11:8)) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1)))))) );
+ shaderCoreCount = (((((gctUINT32) (specs)) >> (0 ? 24:20)) & ((gctUINT32) ((((1 ? 24:20) - (0 ? 24:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:20) - (0 ? 24:20) + 1)))))) );
+ vertexCacheSize = (((((gctUINT32) (specs)) >> (0 ? 16:12)) & ((gctUINT32) ((((1 ? 16:12) - (0 ? 16:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:12) - (0 ? 16:12) + 1)))))) );
+ vertexOutputBufferSize = (((((gctUINT32) (specs)) >> (0 ? 31:28)) & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1)))))) );
+ pixelPipes = (((((gctUINT32) (specs)) >> (0 ? 27:25)) & ((gctUINT32) ((((1 ? 27:25) - (0 ? 27:25) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:25) - (0 ? 27:25) + 1)))))) );
+
+ /* Read gcChipSpecs2 register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00080,
+ &specs2));
+
+ instructionCount = (((((gctUINT32) (specs2)) >> (0 ? 15:8)) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1)))))) );
+ numConstants = (((((gctUINT32) (specs2)) >> (0 ? 31:16)) & ((gctUINT32) ((((1 ? 31:16) - (0 ? 31:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:16) - (0 ? 31:16) + 1)))))) );
+ bufferSize = (((((gctUINT32) (specs2)) >> (0 ? 7:0)) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1)))))) );
+
+ /* Read gcChipSpecs3 register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x0008C,
+ &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. */
+ Identity->pixelPipes = gcmMAX(pixelPipes, 1);
+
+ /* Get the stream count. */
+ Identity->streamCount = (streamCount != 0)
+ ? streamCount
+ : (Identity->chipModel >= gcv1000) ? 4 : 1;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: streamCount=%u%s",
+ Identity->streamCount,
+ (streamCount == 0) ? " (default)" : "");
+
+ /* Get the vertex output buffer size. */
+ Identity->vertexOutputBufferSize = (vertexOutputBufferSize != 0)
+ ? 1 << vertexOutputBufferSize
+ : (Identity->chipModel == gcv400)
+ ? (Identity->chipRevision < 0x4000) ? 512
+ : (Identity->chipRevision < 0x4200) ? 256
+ : 128
+ : (Identity->chipModel == gcv530)
+ ? (Identity->chipRevision < 0x4200) ? 512
+ : 128
+ : 512;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: vertexOutputBufferSize=%u%s",
+ Identity->vertexOutputBufferSize,
+ (vertexOutputBufferSize == 0) ? " (default)" : "");
+
+ /* Get the maximum number of threads. */
+ Identity->threadCount = (threadCount != 0)
+ ? 1 << threadCount
+ : (Identity->chipModel == gcv400) ? 64
+ : (Identity->chipModel == gcv500) ? 128
+ : (Identity->chipModel == gcv530) ? 128
+ : 256;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: threadCount=%u%s",
+ Identity->threadCount,
+ (threadCount == 0) ? " (default)" : "");
+
+ /* Get the number of shader cores. */
+ Identity->shaderCoreCount = (shaderCoreCount != 0)
+ ? shaderCoreCount
+ : (Identity->chipModel >= gcv1000) ? 2
+ : 1;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: shaderCoreCount=%u%s",
+ Identity->shaderCoreCount,
+ (shaderCoreCount == 0) ? " (default)" : "");
+
+ /* Get the vertex cache size. */
+ Identity->vertexCacheSize = (vertexCacheSize != 0)
+ ? vertexCacheSize
+ : 8;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: vertexCacheSize=%u%s",
+ Identity->vertexCacheSize,
+ (vertexCacheSize == 0) ? " (default)" : "");
+
+ /* Get the maximum number of temporary registers. */
+ Identity->registerMax = (registerMax != 0)
+ /* Maximum of registerMax/4 registers are accessible to 1 shader */
+ ? 1 << registerMax
+ : (Identity->chipModel == gcv400) ? 32
+ : 64;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: registerMax=%u%s",
+ Identity->registerMax,
+ (registerMax == 0) ? " (default)" : "");
+
+ /* Get the instruction count. */
+ Identity->instructionCount = (instructionCount == 0) ? 256
+ : (instructionCount == 1) ? 1024
+ : (instructionCount == 2) ? 2048
+ : (instructionCount == 0xFF) ? 512
+ : 256;
+
+ if (Identity->instructionCount == 256)
+ {
+ if ((Identity->chipModel == gcv2000 && Identity->chipRevision == 0x5108)
+ || Identity->chipModel == gcv880)
+ {
+ 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,
+ "Specs: instructionCount=%u%s",
+ Identity->instructionCount,
+ (instructionCount == 0) ? " (default)" : "");
+
+ /* Get the number of constants. */
+ Identity->numConstants = (numConstants == 0) ? 168 : numConstants;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: numConstants=%u%s",
+ Identity->numConstants,
+ (numConstants == 0) ? " (default)" : "");
+
+ /* Get the buffer size. */
+ Identity->bufferSize = bufferSize;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: bufferSize=%u%s",
+ Identity->bufferSize,
+ (bufferSize == 0) ? " (default)" : "");
+
+
+ if (varyingsCount != 0)
+ {
+ 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))))))))
+ {
+ Identity->varyingsCount = 12;
+ }
+ else
+ {
+ Identity->varyingsCount = 8;
+ }
+
+ /* For some cores, it consumes two varying for position, so the max varying vectors should minus one. */
+ 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
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00470,
+ &debugControl0));
+
+ if (debugControl0 & (1 << 16))
+ {
+ Identity->chipFlags |= gcvCHIP_FLAG_MSAA_COHERENCEY_ECO_FIX;
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ 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(
+ gctPOINTER Data
+ )
+{
+ gckHARDWARE hardware = (gckHARDWARE)Data;
+ gcmkVERIFY_OK(
+ gckHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF_TIMEOUT));
+}
+#endif
+
+static gceSTATUS
+_VerifyDMA(
+ IN gckOS Os,
+ IN gceCORE Core,
+ gctUINT32_PTR Address1,
+ gctUINT32_PTR Address2,
+ gctUINT32_PTR State1,
+ gctUINT32_PTR State2
+ )
+{
+ gceSTATUS status;
+ gctUINT32 i;
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x660, State1));
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x664, Address1));
+
+ for (i = 0; i < 500; i += 1)
+ {
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x660, State2));
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x664, Address2));
+
+ if (*Address1 != *Address2)
+ {
+ break;
+ }
+
+ if (*State1 != *State2)
+ {
+ break;
+ }
+ }
+
+OnError:
+ return status;
+}
+
+static gceSTATUS
+_DumpDebugRegisters(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gcsiDEBUG_REGISTERS_PTR Descriptor
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctUINT32 select;
+ gctUINT32 data = 0;
+ gctUINT i;
+
+ gcmkHEADER_ARG("Os=0x%X Descriptor=0x%X", Os, Descriptor);
+
+ gcmkPRINT_N(4, " %s debug registers:\n", Descriptor->module);
+
+ for (i = 0; i < Descriptor->count; i += 1)
+ {
+ select = i << Descriptor->shift;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, select));
+#if gcdFPGA_BUILD
+ gcmkONERROR(gckOS_Delay(Os, 1000));
+#endif
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &data));
+
+ gcmkPRINT_N(12, " [0x%02X] 0x%08X\n", i, data);
+ }
+
+ select = 0xF << Descriptor->shift;
+
+ for (i = 0; i < 500; i += 1)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, select));
+#if gcdFPGA_BUILD
+ gcmkONERROR(gckOS_Delay(Os, 1000));
+#endif
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &data));
+
+ if (data == Descriptor->signature)
+ {
+ break;
+ }
+ }
+
+ if (i == 500)
+ {
+ gcmkPRINT_N(4, " failed to obtain the signature (read 0x%08X).\n", data);
+ }
+ else
+ {
+ gcmkPRINT_N(8, " signature = 0x%08X (%d read attempt(s))\n", data, i + 1);
+ }
+
+OnError:
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_IsGPUPresent(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gcsHAL_QUERY_CHIP_IDENTITY identity;
+ gctUINT32 control;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &control));
+
+ control = ((((gctUINT32) (control)) & ~(((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)));
+ control = ((((gctUINT32) (control)) & ~(((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)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ control));
+
+ /* Identify the hardware. */
+ gcmkONERROR(_IdentifyHardware(Hardware->os,
+ Hardware->core,
+ &identity));
+
+ /* Check if these are the same values as saved before. */
+ if ((Hardware->identity.chipModel != identity.chipModel)
+ || (Hardware->identity.chipRevision != identity.chipRevision)
+ || (Hardware->identity.chipFeatures != identity.chipFeatures)
+ || (Hardware->identity.chipMinorFeatures != identity.chipMinorFeatures)
+ || (Hardware->identity.chipMinorFeatures1 != identity.chipMinorFeatures1)
+ || (Hardware->identity.chipMinorFeatures2 != identity.chipMinorFeatures2)
+ )
+ {
+ gcmkPRINT("[galcore]: GPU is not present.");
+ gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+_FlushCache(
+ gckHARDWARE Hardware,
+ gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gctUINT32 bytes, requested;
+ gctPOINTER buffer;
+
+ /* Get the size of the flush command. */
+ gcmkONERROR(gckHARDWARE_Flush(Hardware,
+ gcvFLUSH_ALL,
+ gcvNULL,
+ &requested));
+
+ /* Reserve space in the command queue. */
+ gcmkONERROR(gckCOMMAND_Reserve(Command,
+ requested,
+ &buffer,
+ &bytes));
+
+ /* Append a flush. */
+ gcmkONERROR(gckHARDWARE_Flush(
+ Hardware, gcvFLUSH_ALL, buffer, &bytes
+ ));
+
+ /* Execute the command queue. */
+ gcmkONERROR(gckCOMMAND_Execute(Command, requested));
+
+ return gcvSTATUS_OK;
+
+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)))))) )
+ ;
+}
+
+/*
+* State timer helper must be called with powerMutex held.
+*/
+void
+gckSTATETIMER_Reset(
+ IN gcsSTATETIMER * StateTimer,
+ IN gctUINT64 Start
+ )
+{
+ gctUINT64 now;
+
+ if (Start)
+ {
+ now = Start;
+ }
+ else
+ {
+ gckOS_GetProfileTick(&now);
+ }
+
+ StateTimer->recent = StateTimer->start = now;
+
+ gckOS_ZeroMemory(StateTimer->elapse, gcmSIZEOF(StateTimer->elapse));
+}
+
+void
+gckSTATETIMER_Accumulate(
+ IN gcsSTATETIMER * StateTimer,
+ IN gceCHIPPOWERSTATE OldState
+ )
+{
+ gctUINT64 now;
+ gctUINT64 elapse;
+
+ gckOS_GetProfileTick(&now);
+
+ elapse = now - StateTimer->recent;
+
+ StateTimer->recent = now;
+
+ StateTimer->elapse[OldState] += elapse;
+}
+
+void
+gckSTATETIMER_Query(
+ IN gcsSTATETIMER * StateTimer,
+ IN gceCHIPPOWERSTATE State,
+ OUT gctUINT64_PTR Start,
+ OUT gctUINT64_PTR End,
+ OUT gctUINT64_PTR On,
+ OUT gctUINT64_PTR Off,
+ OUT gctUINT64_PTR Idle,
+ OUT gctUINT64_PTR Suspend
+ )
+{
+ *Start = StateTimer->start;
+
+ gckSTATETIMER_Accumulate(StateTimer, State);
+
+ *End = StateTimer->recent;
+
+ *On = StateTimer->elapse[gcvPOWER_ON];
+ *Off = StateTimer->elapse[gcvPOWER_OFF];
+ *Idle = StateTimer->elapse[gcvPOWER_IDLE];
+ *Suspend = StateTimer->elapse[gcvPOWER_SUSPEND];
+
+ gckSTATETIMER_Reset(StateTimer, StateTimer->recent);
+}
+
+/******************************************************************************\
+****************************** gckHARDWARE API code *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckHARDWARE_Construct
+**
+** Construct a new gckHARDWARE object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an initialized gckOS object.
+**
+** gceCORE Core
+** Specified core.
+**
+** OUTPUT:
+**
+** gckHARDWARE * Hardware
+** Pointer to a variable that will hold the pointer to the gckHARDWARE
+** object.
+*/
+gceSTATUS
+gckHARDWARE_Construct(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gckHARDWARE * Hardware
+ )
+{
+ gceSTATUS status;
+ gckHARDWARE hardware = gcvNULL;
+ gctUINT16 data = 0xff00;
+ gctPOINTER pointer = gcvNULL;
+#if gcdMULTI_GPU_AFFINITY
+ gctUINT32 control;
+#endif
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
+
+ /* Enable the GPU. */
+ gcmkONERROR(gckOS_SetGPUPower(Os, Core, gcvTRUE, gcvTRUE));
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ 0x00000900));
+
+ /* Allocate the gckHARDWARE object. */
+ gcmkONERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckHARDWARE),
+ &pointer));
+
+ gckOS_ZeroMemory(pointer, gcmSIZEOF(struct _gckHARDWARE));
+
+ hardware = (gckHARDWARE) pointer;
+
+ /* Initialize the gckHARDWARE object. */
+ hardware->object.type = gcvOBJ_HARDWARE;
+ hardware->os = Os;
+ hardware->core = Core;
+
+ /* Identify the hardware. */
+ gcmkONERROR(_IdentifyHardware(Os, Core, &hardware->identity));
+
+ /* Determine the hardware type */
+ switch (hardware->identity.chipModel)
+ {
+ case gcv350:
+ case gcv355:
+ hardware->type = gcvHARDWARE_VG;
+ break;
+
+ case gcv200:
+ case gcv300:
+ case gcv320:
+ case gcv328:
+ case gcv420:
+ case gcv428:
+ case gcv520:
+ hardware->type = gcvHARDWARE_2D;
+ break;
+
+ default:
+#if gcdMULTI_GPU_AFFINITY
+ hardware->type = (Core == gcvCORE_MAJOR) ? gcvHARDWARE_3D : gcvHARDWARE_OCL;
+#else
+ hardware->type = gcvHARDWARE_3D;
+#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)) | 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);
+ }
+ }
+
+ hardware->powerBaseAddress
+ = ((hardware->identity.chipModel == gcv300)
+ && (hardware->identity.chipRevision < 0x2000))
+ ? 0x0100
+ : 0x0000;
+
+ /* VIV: Don't do sftware reset here for 0x2000, 0xfff5450 to workaround #12789. */
+ if (!(_IsHardwareMatch(hardware, gcv3000, 0x5450)))
+ {
+ /* _ResetGPU need powerBaseAddress. */
+ status = _ResetGPU(hardware, Os, Core);
+
+ if (status != gcvSTATUS_OK)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "_ResetGPU failed: status=%d\n", status);
+ }
+ }
+
+#if gcdENABLE_DEC_COMPRESSION && !gcdDEC_ENABLE_AHB
+ gcmkONERROR(gckOS_WriteRegisterEx(Os, gcvCORE_DEC, 0x18180, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))) << (0 ? 22:22))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))) << (0 ? 22:22)))));
+#endif
+
+#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
+ = (((((gctUINT32) (hardware->identity.chipMinorFeatures1)) >> (0 ? 28:28)) & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))) );
+
+ /* Determine whether bug fixes #1 are present. */
+ hardware->extraEventStates = ((((gctUINT32) (hardware->identity.chipMinorFeatures1)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x0 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))));
+
+ /* Check if big endian */
+ hardware->bigEndian = (*(gctUINT8 *)&data == 0xff);
+
+ /* Initialize the fast clear. */
+ gcmkONERROR(gckHARDWARE_SetFastClear(hardware, -1, -1));
+
+#if !gcdENABLE_128B_MERGE
+
+ if (((((gctUINT32) (hardware->identity.chipMinorFeatures2)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))))
+ {
+ /* 128B merge is turned on by default. Disable it. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00558, 0));
+ }
+
+#endif
+
+ /* Set power state to ON. */
+ hardware->chipPowerState = gcvPOWER_ON;
+ hardware->clockState = gcvTRUE;
+ hardware->powerState = gcvTRUE;
+ hardware->lastWaitLink = ~0U;
+ hardware->lastEnd = ~0U;
+ hardware->globalSemaphore = gcvNULL;
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ hardware->powerOnFscaleVal = 64;
+#endif
+
+ gcmkONERROR(gckOS_CreateMutex(Os, &hardware->powerMutex));
+ gcmkONERROR(gckOS_CreateSemaphore(Os, &hardware->globalSemaphore));
+ hardware->startIsr = gcvNULL;
+ hardware->stopIsr = gcvNULL;
+
+#if gcdPOWEROFF_TIMEOUT
+ hardware->powerOffTimeout = gcdPOWEROFF_TIMEOUT;
+
+ gcmkVERIFY_OK(gckOS_CreateTimer(Os,
+ _PowerTimerFunction,
+ (gctPOINTER)hardware,
+ &hardware->powerOffTimer));
+#endif
+
+ gcmkONERROR(gckOS_AtomConstruct(Os, &hardware->pageTableDirty));
+ gcmkONERROR(gckOS_AtomConstruct(Os, &hardware->pendingEvent));
+
+#if gcdLINK_QUEUE_SIZE
+ hardware->linkQueue.front = 0;
+ hardware->linkQueue.rear = 0;
+ hardware->linkQueue.count = 0;
+#endif
+
+ /* Enable power management by default. */
+ hardware->powerManagement = gcvTRUE;
+
+ /* 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;
+
+ gckSTATETIMER_Reset(&hardware->powerStateTimer, 0);
+
+ /* Return pointer to the gckHARDWARE object. */
+ *Hardware = hardware;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Hardware=0x%x", *Hardware);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (hardware != gcvNULL)
+ {
+ /* Turn off the power. */
+ gcmkVERIFY_OK(gckOS_SetGPUPower(Os, Core, gcvFALSE, gcvFALSE));
+
+ if (hardware->globalSemaphore != gcvNULL)
+ {
+ /* Destroy the global semaphore. */
+ gcmkVERIFY_OK(gckOS_DestroySemaphore(Os,
+ hardware->globalSemaphore));
+ }
+
+ if (hardware->powerMutex != gcvNULL)
+ {
+ /* Destroy the power mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, hardware->powerMutex));
+ }
+
+#if gcdPOWEROFF_TIMEOUT
+ if (hardware->powerOffTimer != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
+ }
+#endif
+
+ if (hardware->pageTableDirty != gcvNULL)
+ {
+ 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));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Destroy
+**
+** Destroy an gckHARDWARE object.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object that needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Destroy(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Destroy the power semaphore. */
+ gcmkVERIFY_OK(gckOS_DestroySemaphore(Hardware->os,
+ Hardware->globalSemaphore));
+
+ /* Destroy the power mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Hardware->os, Hardware->powerMutex));
+
+#if gcdPOWEROFF_TIMEOUT
+ gcmkVERIFY_OK(gckOS_StopTimer(Hardware->os, Hardware->powerOffTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Hardware->os, Hardware->powerOffTimer));
+#endif
+
+ 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;
+
+ /* Free the object. */
+ gcmkONERROR(gcmkOS_SAFE_FREE(Hardware->os, Hardware));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_GetType
+**
+** Get the hardware type.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gceHARDWARE_TYPE * Type
+** Pointer to a variable that receives the type of hardware object.
+*/
+gceSTATUS
+gckHARDWARE_GetType(
+ IN gckHARDWARE Hardware,
+ OUT gceHARDWARE_TYPE * Type
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+ gcmkVERIFY_ARGUMENT(Type != gcvNULL);
+
+ *Type = Hardware->type;
+
+ gcmkFOOTER_ARG("*Type=%d", *Type);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_InitializeHardware
+**
+** Initialize the hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_InitializeHardware(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 baseAddress;
+ gctUINT32 chipRev;
+ gctUINT32 control;
+ gctUINT32 data;
+ gctUINT32 regPMC = 0;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Read the chip revision register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00024,
+ &chipRev));
+
+ chipRev &= 0xffff;
+
+ if (chipRev != Hardware->identity.chipRevision)
+ {
+ /* Chip is not there! */
+ gcmkONERROR(gcvSTATUS_CONTEXT_LOSSED);
+ }
+
+ /* Disable isolate GPU bit. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)))));
+
+ gcmkONERROR(gckOS_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)))));
+
+ /* Reset memory counters. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0003C,
+ ~0U));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0003C,
+ 0));
+
+ /* Get the system's physical base address. */
+ gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
+
+ /* Program the base addesses. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0041C,
+ baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00418,
+ baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00428,
+ baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00420,
+ baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00424,
+ baseAddress));
+
+ {
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress +
+ 0x00100,
+ &data));
+
+ /* Enable clock gating. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ if ((Hardware->identity.chipRevision == 0x4301)
+ || (Hardware->identity.chipRevision == 0x4302)
+ )
+ {
+ /* Disable stall module level clock gating for 4.3.0.1 and 4.3.0.2
+ ** revisions. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)));
+ }
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00100,
+ data));
+
+#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)))))))
+ )
+ {
+ if (regPMC == 0)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &regPMC));
+ }
+
+ /* Disable PE clock gating. */
+ 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
+ }
+
+ if (Hardware->identity.chipModel == gcv4000 &&
+ ((Hardware->identity.chipRevision == 0x5208) || (Hardware->identity.chipRevision == 0x5222)))
+ {
+ 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 (Hardware->identity.chipModel == gcv1000 &&
+ (Hardware->identity.chipRevision == 0x5039 ||
+ Hardware->identity.chipRevision == 0x5040))
+ {
+ 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,
+ 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)))));
+ }
+
+ if ((gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI2) == gcvSTATUS_FALSE)
+ || (Hardware->identity.chipRevision < 0x5422)
+ )
+ {
+ 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,
+ 0x00480,
+ &data));
+
+ /* Set FE bus to one, TX bus to zero */
+ 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)));
+ 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) (0) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7)));
+
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00480,
+ data));
+ }
+
+ gcmkONERROR(
+ gckHARDWARE_SetMMU(Hardware,
+ Hardware->kernel->mmu->pageTableLogical));
+
+ 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)
+ )
+ {
+ if (regPMC == 0)
+ {
+ 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)));
+ }
+
+ /* Limit 2D outstanding request. */
+ if (_IsHardwareMatch(Hardware, gcv880, 0x5107))
+ {
+ 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,
+ 0x00414,
+ &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.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,
+ 0x00414,
+ data));
+ }
+
+ if (_IsHardwareMatch(Hardware, gcv1000, 0x5035))
+ {
+ 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(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00414,
+ data));
+ }
+
+ if (_IsHardwareMatch(Hardware, gcv4000, 0x5222)
+ || _IsHardwareMatch(Hardware, gcv2000, 0x5108)
+ )
+ {
+ 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 (_IsHardwareMatch(Hardware, gcv880, 0x5106))
+ {
+ Hardware->kernel->timeOut = 140 * 1000;
+ }
+
+ if (regPMC == 0)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 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, gcv3000, 0x5450) && (Hardware->identity.chipFlags & gcvCHIP_FLAG_GC2000_R2))
+ || _IsHardwareMatch(Hardware, gcv320, 0x5007)
+ || _IsHardwareMatch(Hardware, gcv320, 0x5303)
+ || _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,
+ 0x0010C,
+ &data));
+
+ /* 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,
+ Hardware->core,
+ 0x0010C,
+ data));
+ }
+
+#if gcdDEBUG_MODULE_CLOCK_GATING
+ _ConfigureModuleLevelClockGating(Hardware);
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryMemory
+**
+** Query the amount of memory available on the hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * InternalSize
+** Pointer to a variable that will hold the size of the internal video
+** memory in bytes. If 'InternalSize' is gcvNULL, no information of the
+** internal memory will be returned.
+**
+** gctUINT32 * InternalBaseAddress
+** Pointer to a variable that will hold the hardware's base address for
+** the internal video memory. This pointer cannot be gcvNULL if
+** 'InternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * InternalAlignment
+** Pointer to a variable that will hold the hardware's base address for
+** the internal video memory. This pointer cannot be gcvNULL if
+** 'InternalSize' is also non-gcvNULL.
+**
+** gctSIZE_T * ExternalSize
+** Pointer to a variable that will hold the size of the external video
+** memory in bytes. If 'ExternalSize' is gcvNULL, no information of the
+** external memory will be returned.
+**
+** gctUINT32 * ExternalBaseAddress
+** Pointer to a variable that will hold the hardware's base address for
+** the external video memory. This pointer cannot be gcvNULL if
+** 'ExternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * ExternalAlignment
+** Pointer to a variable that will hold the hardware's base address for
+** the external video memory. This pointer cannot be gcvNULL if
+** 'ExternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * HorizontalTileSize
+** Number of horizontal pixels per tile. If 'HorizontalTileSize' is
+** gcvNULL, no horizontal pixel per tile will be returned.
+**
+** gctUINT32 * VerticalTileSize
+** Number of vertical pixels per tile. If 'VerticalTileSize' is
+** gcvNULL, no vertical pixel per tile will be returned.
+*/
+gceSTATUS
+gckHARDWARE_QueryMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctUINT32 * InternalBaseAddress,
+ OUT gctUINT32 * InternalAlignment,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctUINT32 * ExternalBaseAddress,
+ OUT gctUINT32 * ExternalAlignment,
+ OUT gctUINT32 * HorizontalTileSize,
+ OUT gctUINT32 * VerticalTileSize
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (InternalSize != gcvNULL)
+ {
+ /* No internal memory. */
+ *InternalSize = 0;
+ }
+
+ if (ExternalSize != gcvNULL)
+ {
+ /* No external memory. */
+ *ExternalSize = 0;
+ }
+
+ if (HorizontalTileSize != gcvNULL)
+ {
+ /* 4x4 tiles. */
+ *HorizontalTileSize = 4;
+ }
+
+ if (VerticalTileSize != gcvNULL)
+ {
+ /* 4x4 tiles. */
+ *VerticalTileSize = 4;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*InternalSize=%lu *InternalBaseAddress=0x%08x "
+ "*InternalAlignment=0x%08x *ExternalSize=%lu "
+ "*ExternalBaseAddress=0x%08x *ExtenalAlignment=0x%08x "
+ "*HorizontalTileSize=%u *VerticalTileSize=%u",
+ gcmOPT_VALUE(InternalSize),
+ gcmOPT_VALUE(InternalBaseAddress),
+ gcmOPT_VALUE(InternalAlignment),
+ gcmOPT_VALUE(ExternalSize),
+ gcmOPT_VALUE(ExternalBaseAddress),
+ gcmOPT_VALUE(ExternalAlignment),
+ gcmOPT_VALUE(HorizontalTileSize),
+ gcmOPT_VALUE(VerticalTileSize));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryChipIdentity
+**
+** Query the identity of the hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
+** Pointer to the identity structure.
+**
+*/
+gceSTATUS
+gckHARDWARE_QueryChipIdentity(
+ IN gckHARDWARE Hardware,
+ OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
+ )
+{
+ gctUINT32 features;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Identity != gcvNULL);
+
+ /* Return chip model and revision. */
+ Identity->chipModel = Hardware->identity.chipModel;
+ Identity->chipRevision = Hardware->identity.chipRevision;
+
+ /* Return feature set. */
+ features = Hardware->identity.chipFeatures;
+
+ if ((((((gctUINT32) (features)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+ {
+ /* Override fast clear by command line. */
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (Hardware->allowFastClear) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+ }
+
+ if ((((((gctUINT32) (features)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) ))
+ {
+ /* Override compression by command line. */
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (Hardware->allowCompression) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+ }
+
+ /* Mark 2D pipe as available for GC500.0 through GC500.2 and GC300,
+ ** since they did not have this bit. */
+ if (((Hardware->identity.chipModel == gcv500) && (Hardware->identity.chipRevision <= 2))
+ || (Hardware->identity.chipModel == gcv300)
+ )
+ {
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
+ }
+
+ Identity->chipFeatures = features;
+
+ /* Return minor features. */
+ Identity->chipMinorFeatures = Hardware->identity.chipMinorFeatures;
+ Identity->chipMinorFeatures1 = Hardware->identity.chipMinorFeatures1;
+ Identity->chipMinorFeatures2 = Hardware->identity.chipMinorFeatures2;
+ Identity->chipMinorFeatures3 = Hardware->identity.chipMinorFeatures3;
+ Identity->chipMinorFeatures4 = Hardware->identity.chipMinorFeatures4;
+ Identity->chipMinorFeatures5 = Hardware->identity.chipMinorFeatures5;
+ Identity->chipMinorFeatures6 = Hardware->identity.chipMinorFeatures6;
+
+ /* Return chip specs. */
+ Identity->streamCount = Hardware->identity.streamCount;
+ Identity->registerMax = Hardware->identity.registerMax;
+ Identity->threadCount = Hardware->identity.threadCount;
+ Identity->shaderCoreCount = Hardware->identity.shaderCoreCount;
+ Identity->vertexCacheSize = Hardware->identity.vertexCacheSize;
+ Identity->vertexOutputBufferSize = Hardware->identity.vertexOutputBufferSize;
+ Identity->pixelPipes = Hardware->identity.pixelPipes;
+ Identity->instructionCount = Hardware->identity.instructionCount;
+ Identity->numConstants = Hardware->identity.numConstants;
+ 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;
+ Identity->chipFlags = Hardware->identity.chipFlags;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_SplitMemory
+**
+** Split a hardware specific memory address into a pool and offset.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gctUINT32 Address
+** Address in hardware specific format.
+**
+** OUTPUT:
+**
+** gcePOOL * Pool
+** Pointer to a variable that will hold the pool type for the address.
+**
+** gctUINT32 * Offset
+** Pointer to a variable that will hold the offset for the address.
+*/
+gceSTATUS
+gckHARDWARE_SplitMemory(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Addres=0x%08x", Hardware, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
+
+ if (Hardware->mmuVersion == 0)
+ {
+ /* Dispatch on memory type. */
+ switch ((((((gctUINT32) (Address)) >> (0 ? 31:31)) & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))) ))
+ {
+ case 0x0:
+ /* System memory. */
+ *Pool = gcvPOOL_SYSTEM;
+ break;
+
+ case 0x1:
+ /* Virtual memory. */
+ *Pool = gcvPOOL_VIRTUAL;
+ break;
+
+ default:
+ /* Invalid memory type. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Return offset of address. */
+ *Offset = (((((gctUINT32) (Address)) >> (0 ? 30:0)) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1)))))) );
+ }
+ else
+ {
+ *Pool = gcvPOOL_SYSTEM;
+ *Offset = Address;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Pool=%d *Offset=0x%08x", *Pool, *Offset);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Execute
+**
+** Kickstart the hardware's command processor with an initialized command
+** buffer.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gctUINT32 Address
+** Hardware address of command buffer.
+**
+** gctSIZE_T Bytes
+** Number of bytes for the prefetch unit (until after the first LINK).
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Execute(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ IN gctSIZE_T Bytes
+ )
+{
+ gceSTATUS status;
+ gctUINT32 control;
+
+ gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Bytes=%lu",
+ Hardware, Address, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Enable all events. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00014, ~0U));
+
+ /* Write address register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00654, Address));
+
+ /* Build control register. */
+ control = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) ((Bytes + 7) >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ /* Set big endian */
+ if (Hardware->bigEndian)
+ {
+ control |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 21:20) - (0 ? 21:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:20) - (0 ? 21:20) + 1))))))) << (0 ? 21:20))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 21:20) - (0 ? 21:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:20) - (0 ? 21:20) + 1))))))) << (0 ? 21:20)));
+ }
+
+ /* Write control register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00658, control));
+
+ /* Increase execute count. */
+ Hardware->executeCount++;
+
+ /* Record last execute address. */
+ Hardware->lastExecuteAddress = Address;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Started command buffer @ 0x%08x",
+ Address);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_WaitLink
+**
+** Append a WAIT/LINK command sequence at the specified location in the command
+** queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** WAIT/LINK command sequence at or gcvNULL just to query the size of the
+** WAIT/LINK command sequence.
+**
+** gctUINT32 Offset
+** Offset into command buffer required for alignment.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the WAIT/LINK command
+** sequence. If 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** by the WAIT/LINK command sequence. If 'Bytes' is gcvNULL, nothing will
+** be returned.
+**
+** gctUINT32 * WaitOffset
+** Pointer to a variable that will receive the offset of the WAIT command
+** from the specified logcial pointer.
+** If 'WaitOffset' is gcvNULL nothing will be returned.
+**
+** gctSIZE_T * WaitSize
+** Pointer to a variable that will receive the number of bytes used by
+** the WAIT command. If 'LinkSize' is gcvNULL nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_WaitLink(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN OUT gctUINT32 * Bytes,
+ OUT gctUINT32 * WaitOffset,
+ OUT gctUINT32 * WaitSize
+ )
+{
+ static const gctUINT waitCount = 200;
+
+ gceSTATUS status;
+ gctUINT32 address;
+ gctUINT32_PTR logical;
+ gctUINT32 bytes;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=0x%08x *Bytes=%lu",
+ Hardware, Logical, Offset, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
+
+#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;
+
+ if (logical != gcvNULL)
+ {
+ /* Not enough space? */
+ if (*Bytes < bytes)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Convert logical into hardware specific address. */
+ gcmkONERROR(gckHARDWARE_ConvertLogical(Hardware, logical, gcvFALSE, &address));
+
+ /* Store the WAIT/LINK address. */
+ Hardware->lastWaitLink = address;
+
+ /* Append WAIT(count). */
+ logical[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (waitCount) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+#if 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;
+
+ logical[3] = 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[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)));
+
+ 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[7] = 0;
+
+ /* 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)));
+
+ logical[9] = address;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: WAIT %u", address, waitCount
+ );
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH 0x%x", address + 8, logical[3]);
+
+ 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)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ logical[3] = address;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: WAIT %u", address, waitCount
+ );
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: LINK 0x%08x, #%lu",
+ address + 8, address, bytes
+ );
+#endif
+ if (WaitOffset != gcvNULL)
+ {
+ /* Return the offset pointer to WAIT command. */
+ *WaitOffset = 0;
+ }
+
+ if (WaitSize != gcvNULL)
+ {
+ /* Return number of bytes used by the WAIT command. */
+#if gcdMULTI_GPU && !gcdDISABLE_FE_L2
+ *WaitSize = 32;
+#else
+ *WaitSize = 8;
+#endif
+ }
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the WAIT/LINK command
+ ** sequence. */
+ *Bytes = bytes;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu *WaitOffset=0x%x *WaitSize=%lu",
+ gcmOPT_VALUE(Bytes), gcmOPT_VALUE(WaitOffset),
+ gcmOPT_VALUE(WaitSize));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_End
+**
+** Append an END command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** END command at or gcvNULL just to query the size of the END command.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the END command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the END command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_End(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gctUINT32 address;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
+ Hardware, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append END. */
+ logical[0] =
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+ /* Record the count of execution which is finised by this END. */
+ logical[1] =
+ Hardware->executeCount;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: END", Logical);
+
+ /* Make sure the CPU writes out the data to memory. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, Logical));
+
+ gcmkONERROR(gckHARDWARE_ConvertLogical(Hardware, logical, gcvFALSE, &address));
+
+ Hardware->lastEnd = address;
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the END command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdMULTI_GPU
+gceSTATUS
+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 ChipEnable=0x%x *Bytes=%lu",
+ Hardware, Logical, ChipEnable, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append 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: CHIPENABLE 0x%x", Logical, ChipEnable);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the CHIPENABLE command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckHARDWARE_Nop
+**
+** Append a NOP command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** NOP command at or gcvNULL just to query the size of the NOP command.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the NOP command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the NOP command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Nop(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
+ Hardware, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append NOP. */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: NOP", Logical);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the NOP command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Event
+**
+** Append an EVENT command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** the EVENT command at or gcvNULL just to query the size of the EVENT
+** command.
+**
+** gctUINT8 Event
+** Event ID to program.
+**
+** gceKERNEL_WHERE FromWhere
+** Location of the pipe to send the event.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the EVENT command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the EVENT command. If 'Bytes' is gcvNULL, nothing will be
+** returned.
+*/
+gceSTATUS
+gckHARDWARE_Event(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT8 Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gctUINT size;
+ gctUINT32 destination = 0;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Event=%u FromWhere=%d *Bytes=%lu",
+ Hardware, Logical, Event, FromWhere, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+ gcmkVERIFY_ARGUMENT(Event < 32);
+
+#if gcdMULTI_GPU
+ if (FromWhere == gcvKERNEL_COMMAND) FromWhere = gcvKERNEL_PIXEL;
+#endif
+
+ /* Determine the size of the command. */
+
+ size = (Hardware->extraEventStates && (FromWhere == gcvKERNEL_PIXEL))
+ ? gcmALIGN(8 + (1 + 5) * 4, 8) /* EVENT + 5 STATES */
+ : 8;
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < size)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ switch (FromWhere)
+ {
+ case gcvKERNEL_COMMAND:
+ /* From command processor. */
+ destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+ break;
+
+ case gcvKERNEL_PIXEL:
+ /* From pixel engine. */
+ destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+ break;
+
+ default:
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Append EVENT(Event, destiantion). */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[1] = ((((gctUINT32) (destination)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (Event) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
+
+ /* Make sure the event ID gets written out before GPU can access it. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, logical + 1));
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ {
+ gctPHYS_ADDR_T phys;
+ gckOS_GetPhysicalAddress(Hardware->os, Logical, &phys);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: EVENT %d", phys, Event);
+ }
+#endif
+
+ /* Append the extra states. These are needed for the chips that do not
+ ** support back-to-back events due to the async interface. The extra
+ ** states add the necessary delay to ensure that event IDs do not
+ ** collide. */
+ if (size > 8)
+ {
+ logical[2] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0100) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+ logical[3] = 0;
+ logical[4] = 0;
+ logical[5] = 0;
+ logical[6] = 0;
+ logical[7] = 0;
+ }
+
+#if gcdINTERRUPT_STATISTIC
+ if (Event < gcmCOUNTOF(Hardware->kernel->eventObj->queues))
+ {
+ gckOS_AtomSetMask(Hardware->pendingEvent, 1 << Event);
+ }
+#endif
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the EVENT command. */
+ *Bytes = size;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_PipeSelect
+**
+** Append a PIPESELECT command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** the PIPESELECT command at or gcvNULL just to query the size of the
+** PIPESELECT command.
+**
+** gcePIPE_SELECT Pipe
+** Pipe value to select.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the PIPESELECT command.
+** If 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the PIPESELECT command. If 'Bytes' is gcvNULL, nothing will be
+** returned.
+*/
+gceSTATUS
+gckHARDWARE_PipeSelect(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gcePIPE_SELECT Pipe,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Pipe=%d *Bytes=%lu",
+ Hardware, Logical, Pipe, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ /* Append a PipeSelect. */
+ if (Logical != gcvNULL)
+ {
+ gctUINT32 flush, stall;
+
+ if (*Bytes < 32)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ flush = (Pipe == gcvPIPE_2D)
+ ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)));
+
+ stall = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* LoadState(AQFlush, 1), flush. */
+ logical[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[1]
+ = flush;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH 0x%x", logical, flush);
+
+ /* LoadState(AQSempahore, 1), stall. */
+ logical[2]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ logical[3]
+ = stall;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: SEMAPHORE 0x%x", logical + 2, stall);
+
+ /* Stall, stall. */
+ logical[4] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+ logical[5] = stall;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: STALL 0x%x", logical + 4, stall);
+
+ /* LoadState(AQPipeSelect, 1), pipe. */
+ logical[6]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[7] = (Pipe == gcvPIPE_2D)
+ ? 0x1
+ : 0x0;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: PIPE %d", logical + 6, Pipe);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the PIPESELECT command. */
+ *Bytes = 32;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Link
+**
+** Append a LINK command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** the LINK command at or gcvNULL just to query the size of the LINK
+** command.
+**
+** gctUINT32 FetchAddress
+** Hardware address of destination of LINK.
+**
+** gctSIZE_T FetchSize
+** Number of bytes in destination of LINK.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the LINK command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the LINK command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Link(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT32 FetchSize,
+ IN OUT gctUINT32 * Bytes,
+ OUT gctUINT32 * Low,
+ OUT gctUINT32 * High
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T bytes;
+ gctUINT32 link;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x FetchAddress=0x%x FetchSize=%lu "
+ "*Bytes=%lu",
+ Hardware, Logical, FetchAddress, FetchSize,
+ gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ gcmkONERROR(
+ gckOS_WriteMemory(Hardware->os, logical + 1, FetchAddress));
+
+ if (High)
+ {
+ *High = 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(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)))
+ | ((((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)));
+
+ gcmkONERROR(
+ gckOS_WriteMemory(Hardware->os, logical, link));
+
+ if (Low)
+ {
+ *Low = link;
+ }
+
+ /* Memory barrier. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, logical));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the LINK command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_UpdateQueueTail
+**
+** Update the tail of the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address of the start of the command queue.
+**
+** gctUINT32 Offset
+** Offset into the command queue of the tail (last command).
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_UpdateQueueTail(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=0x%08x",
+ Hardware, Logical, Offset);
+
+ /* Verify the hardware. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Force a barrier. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, Logical));
+
+ /* Notify gckKERNEL object of change. */
+#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_DEVICE);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_ConvertLogical
+**
+** Convert a logical system address into a hardware specific address.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address to convert.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the memory in user space.
+**
+** gctUINT32* Address
+** Return hardware specific address.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ConvertLogical(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctBOOL InUserSpace,
+ OUT gctUINT32 * Address
+ )
+{
+ gctUINT32 address;
+ gceSTATUS status;
+ gctUINT32 baseAddress;
+ gctPHYS_ADDR_T physical;
+
+ 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);
+
+ /* Convert logical address into a physical address. */
+ if (InUserSpace)
+ {
+ gcmkONERROR(gckOS_UserLogicalToPhysical(Hardware->os, Logical, &physical));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, Logical, &physical));
+ }
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ /* 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;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=0x%08x", *Address);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Interrupt
+**
+** Process an interrupt.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctBOOL InterruptValid
+** If gcvTRUE, this function will read the interrupt acknowledge
+** register, stores the data, and return whether or not the interrupt
+** is ours or not. If gcvFALSE, this functions will read the interrupt
+** acknowledge register and combine it with any stored value to handle
+** the event notifications.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Interrupt(
+ IN gckHARDWARE Hardware,
+#if gcdMULTI_GPU
+ IN gctUINT CoreId,
+#endif
+ IN gctBOOL InterruptValid
+ )
+{
+ gckEVENT eventObj;
+ gctUINT32 data = 0;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x InterruptValid=%d", Hardware, InterruptValid);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Extract gckEVENT object. */
+ eventObj = Hardware->kernel->eventObj;
+ gcmkVERIFY_OBJECT(eventObj, gcvOBJ_EVENT);
+
+ if (InterruptValid)
+ {
+ /* Read AQIntrAcknowledge register. */
+#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)
+ {
+ /* Not our interrupt. */
+ status = gcvSTATUS_NOT_OUR_INTERRUPT;
+ }
+ else
+ {
+
+#if gcdINTERRUPT_STATISTIC
+ gckOS_AtomClearMask(Hardware->pendingEvent, data);
+#endif
+
+ /* Inform gckEVENT of the interrupt. */
+ status = gckEVENT_Interrupt(eventObj,
+#if gcdMULTI_GPU
+ CoreId,
+#endif
+ data);
+ }
+ }
+ else
+ {
+ /* Handle events. */
+ status = gckEVENT_Notify(eventObj, 0);
+ }
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryCommandBuffer
+**
+** Query the command buffer alignment and number of reserved bytes.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Alignment
+** Pointer to a variable receiving the alignment for each command.
+**
+** gctSIZE_T * ReservedHead
+** Pointer to a variable receiving the number of reserved bytes at the
+** head of each command buffer.
+**
+** gctSIZE_T * ReservedTail
+** Pointer to a variable receiving the number of bytes reserved at the
+** tail of each command buffer.
+*/
+gceSTATUS
+gckHARDWARE_QueryCommandBuffer(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32 * Alignment,
+ OUT gctUINT32 * ReservedHead,
+ OUT gctUINT32 * ReservedTail
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (Alignment != gcvNULL)
+ {
+ /* Align every 8 bytes. */
+ *Alignment = 8;
+ }
+
+ if (ReservedHead != gcvNULL)
+ {
+ /* Reserve space for SelectPipe(). */
+ *ReservedHead = 32;
+ }
+
+ if (ReservedTail != gcvNULL)
+ {
+ /* Reserve space for Link(). */
+ *ReservedTail = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Alignment=%lu *ReservedHead=%lu *ReservedTail=%lu",
+ gcmOPT_VALUE(Alignment), gcmOPT_VALUE(ReservedHead),
+ gcmOPT_VALUE(ReservedTail));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QuerySystemMemory
+**
+** Query the command buffer alignment and number of reserved bytes.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * SystemSize
+** Pointer to a variable that receives the maximum size of the system
+** memory.
+**
+** gctUINT32 * SystemBaseAddress
+** Poinetr to a variable that receives the base address for system
+** memory.
+*/
+gceSTATUS
+gckHARDWARE_QuerySystemMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * SystemSize,
+ OUT gctUINT32 * SystemBaseAddress
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (SystemSize != gcvNULL)
+ {
+ /* Maximum system memory can be 2GB. */
+ *SystemSize = 1U << 31;
+ }
+
+ if (SystemBaseAddress != gcvNULL)
+ {
+ /* Set system memory base address. */
+ *SystemBaseAddress = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*SystemSize=%lu *SystemBaseAddress=%lu",
+ gcmOPT_VALUE(SystemSize), gcmOPT_VALUE(SystemBaseAddress));
+ return gcvSTATUS_OK;
+}
+
+#if gcdENABLE_3D
+/*******************************************************************************
+**
+** gckHARDWARE_QueryShaderCaps
+**
+** Query the shader capabilities.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT * VertexUniforms
+** Pointer to a variable receiving the number of uniforms in the vertex
+** shader.
+**
+** gctUINT * FragmentUniforms
+** Pointer to a variable receiving the number of uniforms in the
+** fragment shader.
+**
+** 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 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 UnifiedUnforms=0x%x",
+ Hardware, VertexUniforms,
+ FragmentUniforms, UnifiedUnforms);
+
+ {if (Hardware->identity.numConstants > 256){ unifiedConst = gcvTRUE; vsConstBase = 0xC000; psConstBase = 0xC000; vsConstMax = gcmMIN(512, Hardware->identity.numConstants - 64); psConstMax = gcmMIN(512, Hardware->identity.numConstants - 64); ConstMax = Hardware->identity.numConstants;}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 (UnifiedUnforms != gcvNULL)
+ {
+ /* Return whether the uniformas are unified. */
+ *UnifiedUnforms = unifiedConst;
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetMMU
+**
+** Set the page table base address.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address of the page table.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_SetMMU(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical
+ )
+{
+ gceSTATUS status;
+ gctUINT32 address = 0;
+ gctUINT32 idle;
+ gctUINT32 timer = 0, delay = 1;
+ gctPHYS_ADDR_T physical;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x", Hardware, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (Hardware->mmuVersion == 0)
+ {
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Convert the logical address into physical address. */
+ gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, Logical, &physical));
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ 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));
+
+ /* 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));
+
+
+ /* 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));
+ }
+ else if (Hardware->enableMMU == gcvTRUE)
+ {
+ /* Prepared command sequence contains an END,
+ ** so update lastEnd and store executeCount to END command.
+ */
+ gcsHARDWARE_FUNCTION *function = &Hardware->functions[gcvHARDWARE_FUNCTION_MMU];
+ gctUINT32_PTR endLogical = (gctUINT32_PTR)function->endLogical;
+
+ Hardware->lastEnd = function->endAddress;
+
+ *(endLogical + 1) = Hardware->executeCount + 1;
+
+ /* Execute prepared command sequence. */
+ gcmkONERROR(gckHARDWARE_Execute(
+ Hardware,
+ function->address,
+ function->bytes
+ ));
+
+#if gcdLINK_QUEUE_SIZE
+ gckLINKQUEUE_Enqueue(
+ &Hardware->linkQueue,
+ function->address,
+ function->address + function->bytes,
+ 0,
+ 0
+ );
+#endif
+
+ /* 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)
+ {
+ gckHARDWARE_DumpGPUState(Hardware);
+ gckCOMMAND_DumpExecutingBuffer(Hardware->kernel->command);
+
+ /* 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 gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_FlushMMU
+**
+** Flush the page table.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_FlushMMU(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gckCOMMAND command;
+ gctUINT32_PTR buffer;
+ gctUINT32 bufferSize;
+ gctPOINTER pointer = gcvNULL;
+ gctUINT32 flushSize;
+ gctUINT32 count;
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Verify the gckCOMMAND object pointer. */
+ command = Hardware->kernel->command;
+
+ /* Flush the memory controller. */
+ if (Hardware->mmuVersion == 0)
+ {
+ gcmkONERROR(gckCOMMAND_Reserve(
+ command, 8, &pointer, &bufferSize
+ ));
+
+ buffer = (gctUINT32_PTR) pointer;
+
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E04) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ buffer[1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+
+ gcmkONERROR(gckCOMMAND_Execute(command, 8));
+ }
+ else
+ {
+ /* semaphore stall cmd size */
+ gctUINT32 stCmds = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_TEX_CACHE_FLUSH_FIX) ? 0 : 4;
+
+ flushSize = (stCmds + 18) * 4;
+
+ gcmkONERROR(gckCOMMAND_Reserve(
+ command, flushSize, &pointer, &bufferSize
+ ));
+
+ buffer = (gctUINT32_PTR) pointer;
+
+ count = ((gctUINT)bufferSize - flushSize + 7) >> 3;
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(command->os, buffer, &physical));
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ if (stCmds)
+ {
+ /* 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++
+ = ((((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 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++
+ = ((((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)));
+ }
+
+ /* 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)));
+
+ *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 ? 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 ? 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)));
+
+ /* Flush VTS in separate command */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ *buffer++
+ = ((((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)));
+
+ /* 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++
+ = ((((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 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++
+ = ((((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)));
+
+ /* 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++
+ = address + (stCmds + 10) * gcmSIZEOF(gctUINT32);
+
+ /* Flush MMU 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 ? 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++
+ = (((((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))));
+
+ /* 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++
+ = ((((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 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++
+ = ((((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)));
+
+ /* 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) (count) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ *buffer++
+ = address + flushSize;
+
+ gcmkONERROR(gckCOMMAND_Execute(command, flushSize));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_SetMMUStates(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER MtlbAddress,
+ IN gceMMU_MODE Mode,
+ IN gctPOINTER SafeAddress,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gceSTATUS status;
+ gctUINT32 config, address;
+ gctUINT32 extMtlb, extSafeAddrss, configEx = 0;
+ gctPHYS_ADDR_T physical;
+ gctUINT32_PTR buffer;
+ gctBOOL ace;
+ gctUINT32 reserveBytes = 16 + 4 * 4;
+
+ gctBOOL config2D;
+
+ 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);
+
+ if (config2D)
+ {
+ reserveBytes +=
+ /* Pipe Select. */
+ 4 * 4
+ /* Configure MMU States. */
+ + 4 * 4
+ /* Semaphore stall */
+ + 4 * 8;
+
+ if (ace)
+ {
+ reserveBytes += 8;
+ }
+ }
+
+ /* Convert logical address into physical address. */
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Hardware->os, MtlbAddress, &physical));
+
+ config = (gctUINT32)(physical & 0xFFFFFFFF);
+ extMtlb = (gctUINT32)(physical >> 32);
+
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Hardware->os, SafeAddress, &physical));
+
+ address = (gctUINT32)(physical & 0xFFFFFFFF);
+ extSafeAddrss = (gctUINT32)(physical >> 32);
+
+ if (address & 0x3F)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+ }
+
+ switch (Mode)
+ {
+ case gcvMMU_MODE_1K:
+ if (config & 0x3FF)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+ }
+
+ config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ break;
+
+ case gcvMMU_MODE_4K:
+ if (config & 0xFFF)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+ }
+
+ config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ break;
+
+ default:
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (ace)
+ {
+ configEx = ((((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) (extSafeAddrss) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
+ | ((((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) (extMtlb) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)));
+ }
+
+ 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++
+ = configEx;
+ }
+
+ 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;
+
+ 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++
+ = configEx;
+ }
+
+ 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;
+ gctSIZE_T stCmds; /* semaphore stall cmd size */;
+
+ gcmkHEADER_ARG("Hardware=0x%08X Logical=0x%08x MtlbLogical=0x%08X",
+ Hardware, Logical, MtlbLogical);
+
+ stCmds = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_TEX_CACHE_FLUSH_FIX) ? 0 : 4;
+
+ bytes
+ /* Semaphore stall states. */
+ = stCmds * 4
+ /* Flush cache states. */
+ + 20 * 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)
+ {
+ if (MtlbLogical == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Get physical address of this command buffer segment. */
+ gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, buffer, &physical));
+
+ /* 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)))
+ | ((((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)));
+
+ if (stCmds)
+ {
+ /* 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++
+ = ((((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 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++
+ = ((((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)));
+ }
+
+ /* 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)));
+
+ *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 ? 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)));
+
+ /* Flush VTS in separate command */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ *buffer++
+ = ((((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 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)));
+
+ *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)));
+
+ /* 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++
+ = ((((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 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++
+ = ((((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)));
+
+ /* 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++
+ = physical + (stCmds + 12) * gcmSIZEOF(gctUINT32);
+
+ /* 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) (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++
+ = (((((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))));
+
+ /* 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++
+ = ((((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 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++
+ = ((((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)));
+
+ /* 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 + (stCmds + 20) * 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) (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;
+
+ /* 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++
+ = ((((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 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++
+ = ((((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)));
+
+ /* 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)));
+
+ 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)));
+
+ *buffer++
+ = event;
+
+ /* 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 (Bytes != gcvNULL)
+ {
+ *Bytes = bytesAligned;
+ }
+
+ if (WaitLinkOffset != gcvNULL)
+ {
+ *WaitLinkOffset = bytes - 4 * 4;
+ }
+
+ if (WaitLinkBytes != gcvNULL)
+ {
+#if gcdMULTI_GPU
+ *WaitLinkBytes = 40;
+#else
+ *WaitLinkBytes = 4 * 4;
+#endif
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckHARDWARE_BuildVirtualAddress
+**
+** Build a virtual address.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctUINT32 Index
+** Index into page table.
+**
+** gctUINT32 Offset
+** Offset into page.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Pointer to a variable receiving te hardware address.
+*/
+gceSTATUS
+gckHARDWARE_BuildVirtualAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Index,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Index=%u Offset=%u", Hardware, Index, Offset);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Build virtual address. */
+ *Address = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (Offset | (Index << 12)) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=0x%08x", *Address);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_GetIdle(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Wait,
+ OUT gctUINT32 * Data
+ )
+{
+ gceSTATUS status;
+ gctUINT32 idle = 0;
+ gctINT retry, poll, pollCount;
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Hardware=0x%x Wait=%d", Hardware, Wait);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+
+ /* If we have to wait, try 100 polls per millisecond. */
+ pollCount = Wait ? 100 : 1;
+
+ /* At most, try for 1 second. */
+ for (retry = 0; retry < 1000; ++retry)
+ {
+ /* If we have to wait, try 100 polls per millisecond. */
+ for (poll = pollCount; poll > 0; --poll)
+ {
+ /* Read register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00004, &idle));
+
+ /* Read the current FE address. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00664,
+ &address));
+
+
+ /* See if we have to wait for FE idle. */
+ if (_IsGPUIdle(idle)
+ && (address == Hardware->lastEnd + 8)
+ )
+ {
+ /* FE is idle. */
+ break;
+ }
+ }
+
+ /* Check if we need to wait for FE and FE is busy. */
+ if (Wait && !_IsGPUIdle(idle))
+ {
+ /* Wait a little. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "%s: Waiting for idle: 0x%08X",
+ __FUNCTION__, idle);
+
+ gcmkVERIFY_OK(gckOS_Delay(Hardware->os, 1));
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ /* Return idle to caller. */
+ *Data = idle;
+
+#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;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/* Flush the caches. */
+gceSTATUS
+gckHARDWARE_Flush(
+ IN gckHARDWARE Hardware,
+ IN gceKERNEL_FLUSH Flush,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gctUINT32 pipe;
+ gctUINT32 flush = 0;
+ gctUINT32 flushVST = 0;
+ gctBOOL flushTileStatus;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Flush=0x%x Logical=0x%x *Bytes=%lu",
+ Hardware, Flush, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Get current pipe. */
+ pipe = Hardware->kernel->command->pipeSelect;
+
+ /* Flush tile status cache. */
+ flushTileStatus = Flush & gcvFLUSH_TILE_STATUS;
+
+ /* Flush 3D color cache. */
+ if ((Flush & gcvFLUSH_COLOR) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)));
+ }
+
+ /* Flush 3D depth cache. */
+ if ((Flush & gcvFLUSH_DEPTH) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+ }
+
+ /* Flush 3D texture cache. */
+ if ((Flush & gcvFLUSH_TEXTURE) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)));
+ flushVST = ((((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. */
+ if ((Flush & gcvFLUSH_2D) && (pipe == 0x1))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)));
+ }
+
+#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
+
+ /* See if there is a valid flush. */
+ if ((flush == 0) && (flushTileStatus == gcvFALSE))
+ {
+ if (Bytes != gcvNULL)
+ {
+ /* No bytes required. */
+ *Bytes = 0;
+ }
+ }
+ else
+ {
+ gctUINT32 reserveBytes = 0;
+ gctBOOL txCacheFix = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_TEX_CACHE_FLUSH_FIX)
+ ? gcvTRUE : gcvFALSE;
+
+ /* Determine reserve bytes. */
+ if (!txCacheFix)
+ {
+ /* Semaphore/Stall */
+ reserveBytes += 4 * gcmSIZEOF(gctUINT32);
+ }
+
+ if (flush)
+ {
+ reserveBytes += 2 * gcmSIZEOF(gctUINT32);
+ }
+
+ if (flushVST)
+ {
+ reserveBytes += 2 * gcmSIZEOF(gctUINT32);
+ }
+
+ if (flushTileStatus)
+ {
+ reserveBytes += 2 * gcmSIZEOF(gctUINT32);
+ }
+
+ /* Semaphore/Stall */
+ reserveBytes += 4 * gcmSIZEOF(gctUINT32);
+
+ /* Copy to command queue. */
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < reserveBytes)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ if (!txCacheFix)
+ {
+ /* 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) (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 (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++ = flush;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: FLUSH 0x%x", logical - 1, flush);
+ }
+
+ if (flushVST)
+ {
+ /* 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++ = flushVST;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: FLUSH 0x%x", logical - 1, flush);
+ }
+
+ if (flushTileStatus)
+ {
+ *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 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) (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 (Bytes != gcvNULL)
+ {
+ /* bytes required. */
+ *Bytes = reserveBytes;
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_SetFastClear(
+ IN gckHARDWARE Hardware,
+ IN gctINT Enable,
+ IN gctINT Compression
+ )
+{
+#if gcdENABLE_3D
+ gctUINT32 debug;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Enable=%d Compression=%d",
+ Hardware, Enable, Compression);
+
+ /* Only process if fast clear is available. */
+ if ((((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+ {
+ if (Enable == -1)
+ {
+ /* Determine automatic value for fast clear. */
+ Enable = ((Hardware->identity.chipModel != gcv500)
+ || (Hardware->identity.chipRevision >= 3)
+ ) ? 1 : 0;
+ }
+
+ if (Compression == -1)
+ {
+ /* Determine automatic value for compression. */
+ Compression = Enable
+ & (((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) );
+ }
+
+ /* Read AQMemoryDebug register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00414, &debug));
+
+ /* Set fast clear bypass. */
+ debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20)));
+
+ if (
+ ((((gctUINT32) (Hardware->identity.chipMinorFeatures2)) >> (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))))))) ||
+ (Hardware->identity.chipModel >= gcv4000))
+ {
+ /* Set compression bypass. */
+ debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))) << (0 ? 21:21))) | (((gctUINT32) ((gctUINT32) (Compression == 0) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))) << (0 ? 21:21)));
+ }
+
+ /* Write back AQMemoryDebug register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00414,
+ debug));
+
+ /* Store fast clear and comprersison flags. */
+ Hardware->allowFastClear = Enable;
+ Hardware->allowCompression = Compression;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "FastClear=%d Compression=%d", Enable, Compression);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+#else
+ return gcvSTATUS_OK;
+#endif
+}
+
+typedef enum
+{
+ gcvPOWER_FLAG_INITIALIZE = 1 << 0,
+ gcvPOWER_FLAG_STALL = 1 << 1,
+ gcvPOWER_FLAG_STOP = 1 << 2,
+ gcvPOWER_FLAG_START = 1 << 3,
+ gcvPOWER_FLAG_RELEASE = 1 << 4,
+ gcvPOWER_FLAG_DELAY = 1 << 5,
+ gcvPOWER_FLAG_SAVE = 1 << 6,
+ gcvPOWER_FLAG_ACQUIRE = 1 << 7,
+ gcvPOWER_FLAG_POWER_OFF = 1 << 8,
+ gcvPOWER_FLAG_CLOCK_OFF = 1 << 9,
+ gcvPOWER_FLAG_CLOCK_ON = 1 << 10,
+}
+gcePOWER_FLAGS;
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+static gctCONST_STRING
+_PowerEnum(gceCHIPPOWERSTATE State)
+{
+ const gctCONST_STRING states[] =
+ {
+ gcmSTRING(gcvPOWER_ON),
+ gcmSTRING(gcvPOWER_OFF),
+ gcmSTRING(gcvPOWER_IDLE),
+ gcmSTRING(gcvPOWER_SUSPEND),
+ gcmSTRING(gcvPOWER_SUSPEND_ATPOWERON),
+ gcmSTRING(gcvPOWER_OFF_ATPOWERON),
+ gcmSTRING(gcvPOWER_IDLE_BROADCAST),
+ gcmSTRING(gcvPOWER_SUSPEND_BROADCAST),
+ gcmSTRING(gcvPOWER_OFF_BROADCAST),
+ gcmSTRING(gcvPOWER_OFF_RECOVERY),
+ gcmSTRING(gcvPOWER_OFF_TIMEOUT),
+ gcmSTRING(gcvPOWER_ON_AUTO)
+ };
+
+ if ((State >= gcvPOWER_ON) && (State <= gcvPOWER_ON_AUTO))
+ {
+ return states[State - gcvPOWER_ON];
+ }
+
+ return "unknown";
+}
+#endif
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetPowerManagementState
+**
+** Set GPU to a specified power state.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gceCHIPPOWERSTATE State
+** Power State.
+**
+*/
+gceSTATUS
+gckHARDWARE_SetPowerManagementState(
+ IN gckHARDWARE Hardware,
+ IN gceCHIPPOWERSTATE State
+ )
+{
+ gceSTATUS status;
+ gckCOMMAND command = gcvNULL;
+ gckOS os;
+ gctUINT flag, clock;
+ gctPOINTER buffer;
+ gctUINT32 bytes, requested;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL mutexAcquired = gcvFALSE;
+ gctBOOL stall = gcvTRUE;
+ gctBOOL broadcast = gcvFALSE;
+#if gcdPOWEROFF_TIMEOUT
+ gctBOOL timeout = gcvFALSE;
+ gctBOOL isAfter = gcvFALSE;
+ gctUINT32 currentTime;
+#endif
+ gctUINT32 process, thread;
+ gctBOOL commitEntered = gcvFALSE;
+ gctBOOL commandStarted = gcvFALSE;
+ gctBOOL isrStarted = gcvFALSE;
+
+#if gcdENABLE_PROFILING
+ gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
+ initTime, offTime, startTime, totalTime;
+#endif
+ gctBOOL global = gcvFALSE;
+ gctBOOL globalAcquired = gcvFALSE;
+ gctBOOL configMmu = gcvFALSE;
+
+ /* State transition flags. */
+ static const gctUINT flags[4][4] =
+ {
+ /* gcvPOWER_ON */
+ { /* ON */ 0,
+ /* OFF */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_POWER_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL,
+ /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_OFF */
+ { /* ON */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY,
+ /* OFF */ 0,
+ /* IDLE */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_DELAY,
+ /* SUSPEND */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_IDLE */
+ { /* ON */ gcvPOWER_FLAG_RELEASE,
+ /* OFF */ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_POWER_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ 0,
+ /* SUSPEND */ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_SUSPEND */
+ { /* ON */ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY |
+ gcvPOWER_FLAG_CLOCK_ON,
+ /* OFF */ gcvPOWER_FLAG_SAVE |
+ gcvPOWER_FLAG_POWER_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_DELAY |
+ gcvPOWER_FLAG_CLOCK_ON,
+ /* SUSPEND */ 0,
+ },
+ };
+
+ /* Clocks. */
+ static const gctUINT clocks[4] =
+ {
+ /* gcvPOWER_ON */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (64) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))),
+
+ /* gcvPOWER_OFF */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))),
+
+ /* gcvPOWER_IDLE */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))),
+
+ /* gcvPOWER_SUSPEND */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))),
+ };
+
+ gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Switching to power state %d(%s)",
+ State, _PowerEnum(State));
+#endif
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Get the gckOS object pointer. */
+ os = Hardware->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Get the gckCOMMAND object pointer. */
+ gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
+ command = Hardware->kernel->command;
+ gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
+ /* Start profiler. */
+ gcmkPROFILE_INIT(freq, time);
+
+ /* Convert the broadcast power state. */
+ switch (State)
+ {
+ case gcvPOWER_SUSPEND_ATPOWERON:
+ /* Convert to SUSPEND and don't wait for STALL. */
+ State = gcvPOWER_SUSPEND;
+ stall = gcvFALSE;
+ break;
+
+ case gcvPOWER_OFF_ATPOWERON:
+ /* Convert to OFF and don't wait for STALL. */
+ State = gcvPOWER_OFF;
+ stall = gcvFALSE;
+ break;
+
+ case gcvPOWER_IDLE_BROADCAST:
+ /* Convert to IDLE and note we are inside broadcast. */
+ State = gcvPOWER_IDLE;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_SUSPEND_BROADCAST:
+ /* Convert to SUSPEND and note we are inside broadcast. */
+ State = gcvPOWER_SUSPEND;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_OFF_BROADCAST:
+ /* Convert to OFF and note we are inside broadcast. */
+ State = gcvPOWER_OFF;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_OFF_RECOVERY:
+ /* Convert to OFF and note we are inside recovery. */
+ State = gcvPOWER_OFF;
+ stall = gcvFALSE;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_ON_AUTO:
+ /* Convert to ON and note we are inside recovery. */
+ State = gcvPOWER_ON;
+ break;
+
+ case gcvPOWER_ON:
+ case gcvPOWER_IDLE:
+ case gcvPOWER_SUSPEND:
+ case gcvPOWER_OFF:
+ /* Mark as global power management. */
+ global = gcvTRUE;
+ break;
+
+#if gcdPOWEROFF_TIMEOUT
+ case gcvPOWER_OFF_TIMEOUT:
+ /* Convert to OFF and note we are inside broadcast. */
+ State = gcvPOWER_OFF;
+ broadcast = gcvTRUE;
+ /* Check time out */
+ timeout = gcvTRUE;
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ 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));
+
+ if (broadcast)
+ {
+ /* Try to acquire the power mutex. */
+ status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
+
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ /* Check if we already own this mutex. */
+ if ((Hardware->powerProcess == process)
+ && (Hardware->powerThread == thread)
+ )
+ {
+ /* Bail out on recursive power management. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ else if (State != gcvPOWER_ON)
+ {
+ /* Called from IST,
+ ** so waiting here will cause deadlock,
+ ** if lock holder call gckCOMMAND_Stall() */
+ status = gcvSTATUS_INVALID_REQUEST;
+ goto OnError;
+ }
+ else
+ {
+ /* Acquire the power mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os,
+ Hardware->powerMutex,
+ gcvINFINITE));
+ }
+ }
+ }
+ else
+ {
+ /* Acquire the power mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
+ }
+
+ /* Get time until mtuex acquired. */
+ gcmkPROFILE_QUERY(time, mutexTime);
+
+ Hardware->powerProcess = process;
+ Hardware->powerThread = thread;
+ mutexAcquired = gcvTRUE;
+
+ /* Grab control flags and clock. */
+ flag = flags[Hardware->chipPowerState][State];
+ clock = clocks[State];
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ if (State == gcvPOWER_ON)
+ {
+ clock = ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (Hardware->powerOnFscaleVal) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)));
+ }
+#endif
+
+ if (State == gcvPOWER_SUSPEND && Hardware->chipPowerState == gcvPOWER_OFF && broadcast)
+ {
+#if gcdPOWER_SUSPEND_WHEN_IDLE
+ /* Do nothing */
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+#else
+ /* 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))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) ;
+#endif
+ }
+
+#if gcdPOWEROFF_TIMEOUT
+ if (timeout)
+ {
+ gcmkONERROR(gckOS_GetTicks(&currentTime));
+
+ gcmkONERROR(
+ gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
+
+ /* powerOffTime is pushed forward, give up.*/
+ if (isAfter
+ /* Expect a transition start from IDLE or SUSPEND. */
+ || (Hardware->chipPowerState == gcvPOWER_ON)
+ || (Hardware->chipPowerState == gcvPOWER_OFF)
+ )
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Power Off GPU[%d] at %u [supposed to be at %u]",
+ Hardware->core, currentTime, Hardware->powerOffTime);
+ }
+#endif
+
+ if (flag == 0)
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* If this is an internal power management, we have to check if we can grab
+ ** the global power semaphore. If we cannot, we have to wait until the
+ ** external world changes power management. */
+ if (!global)
+ {
+ /* Try to acquire the global semaphore. */
+ status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ if (State == gcvPOWER_IDLE || State == gcvPOWER_SUSPEND)
+ {
+ /* Called from thread routine which should NEVER sleep.*/
+ gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+ }
+
+ /* Release the power mutex. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Releasing the power mutex.");
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+ mutexAcquired = gcvFALSE;
+
+ /* Wait for the semaphore. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Waiting for global semaphore.");
+ gcmkONERROR(gckOS_AcquireSemaphore(os, Hardware->globalSemaphore));
+ globalAcquired = gcvTRUE;
+
+ /* Acquire the power mutex. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Reacquiring the power mutex.");
+ gcmkONERROR(gckOS_AcquireMutex(os,
+ Hardware->powerMutex,
+ gcvINFINITE));
+ mutexAcquired = gcvTRUE;
+
+ /* chipPowerState may be changed by external world during the time
+ ** we give up powerMutex, so updating flag now is necessary. */
+ flag = flags[Hardware->chipPowerState][State];
+
+ if (flag == 0)
+ {
+ gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
+ globalAcquired = gcvFALSE;
+
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+ mutexAcquired = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ }
+ else
+ {
+ /* Error. */
+ gcmkONERROR(status);
+ }
+
+ /* Release the global semaphore again. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
+ globalAcquired = gcvFALSE;
+ }
+ else
+ {
+ if (State == gcvPOWER_OFF || State == gcvPOWER_SUSPEND || State == gcvPOWER_IDLE)
+ {
+ /* Acquire the global semaphore if it has not been acquired. */
+ status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
+ if (status == gcvSTATUS_OK)
+ {
+ globalAcquired = gcvTRUE;
+ }
+ else if (status != gcvSTATUS_TIMEOUT)
+ {
+ /* Other errors. */
+ gcmkONERROR(status);
+ }
+ /* Ignore gcvSTATUS_TIMEOUT and leave globalAcquired as gcvFALSE.
+ ** gcvSTATUS_TIMEOUT means global semaphore has already
+ ** been acquired before this operation, so even if we fail,
+ ** we should not release it in our error handling. It should be
+ ** released by the next successful global gcvPOWER_ON. */
+ }
+
+ /* Global power management can't be aborted, so sync with
+ ** proceeding last commit. */
+ if (flag & gcvPOWER_FLAG_ACQUIRE)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+ acquired = gcvTRUE;
+
+ /* avoid acquiring again. */
+ flag &= ~gcvPOWER_FLAG_ACQUIRE;
+ }
+ }
+
+ if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
+ {
+ /* Turn on the power. */
+ gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvTRUE, gcvTRUE));
+
+ /* Mark clock and power as enabled. */
+ Hardware->clockState = gcvTRUE;
+ Hardware->powerState = gcvTRUE;
+
+ for (;;)
+ {
+ /* Check if GPU is present and awake. */
+ status = _IsGPUPresent(Hardware);
+
+ /* Check if the GPU is not responding. */
+ if (status == gcvSTATUS_GPU_NOT_RESPONDING)
+ {
+ /* Turn off the power and clock. */
+ gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvFALSE, gcvFALSE));
+
+ Hardware->clockState = gcvFALSE;
+ Hardware->powerState = gcvFALSE;
+
+ /* Wait a little. */
+ gckOS_Delay(os, 1);
+
+ /* Turn on the power and clock. */
+ gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvTRUE, gcvTRUE));
+
+ Hardware->clockState = gcvTRUE;
+ Hardware->powerState = gcvTRUE;
+
+ /* We need to initialize the hardware and start the command
+ * processor. */
+ flag |= gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_START;
+ }
+ else
+ {
+ /* Test for error. */
+ gcmkONERROR(status);
+
+ /* Break out of loop. */
+ break;
+ }
+ }
+ }
+
+ /* Get time until powered on. */
+ gcmkPROFILE_QUERY(time, onTime);
+
+ if ((flag & gcvPOWER_FLAG_STALL) && stall)
+ {
+ gctBOOL idle;
+ gctINT32 atomValue;
+
+ /* For global operation, all pending commits have already been
+ ** blocked by globalSemaphore or powerSemaphore.*/
+ if (!global)
+ {
+ /* Check commit atom. */
+ gcmkONERROR(gckOS_AtomGet(os, command->atomCommit, &atomValue));
+
+ if (atomValue > 0)
+ {
+ /* Commits are pending - abort power management. */
+ status = broadcast ? gcvSTATUS_CHIP_NOT_READY
+ : gcvSTATUS_MORE_DATA;
+ goto OnError;
+ }
+ }
+
+ if (broadcast)
+ {
+ /* Check for idle. */
+ gcmkONERROR(gckHARDWARE_QueryIdle(Hardware, &idle));
+
+ if (!idle)
+ {
+ status = gcvSTATUS_CHIP_NOT_READY;
+ goto OnError;
+ }
+ }
+
+ else
+ {
+ /* Acquire the command queue. */
+ gcmkONERROR(gckCOMMAND_EnterCommit(command, gcvTRUE));
+ commitEntered = gcvTRUE;
+
+ /* Get the size of the flush command. */
+ gcmkONERROR(gckHARDWARE_Flush(Hardware,
+ gcvFLUSH_ALL,
+ gcvNULL,
+ &requested));
+
+ /* Reserve space in the command queue. */
+ gcmkONERROR(gckCOMMAND_Reserve(command,
+ requested,
+ &buffer,
+ &bytes));
+
+ /* Append a flush. */
+ gcmkONERROR(gckHARDWARE_Flush(
+ Hardware, gcvFLUSH_ALL, buffer, &bytes
+ ));
+
+ /* Execute the command queue. */
+ gcmkONERROR(gckCOMMAND_Execute(command, requested));
+
+ /* Release the command queue. */
+ gcmkONERROR(gckCOMMAND_ExitCommit(command, gcvTRUE));
+ commitEntered = gcvFALSE;
+
+ /* Wait to finish all commands. */
+#if gcdMULTI_GPU
+ gcmkONERROR(gckCOMMAND_Stall(command, gcvTRUE, gcvCORE_3D_ALL_MASK));
+#else
+ gcmkONERROR(gckCOMMAND_Stall(command, gcvTRUE));
+#endif
+ }
+ }
+
+ /* Get time until stalled. */
+ gcmkPROFILE_QUERY(time, stallTime);
+
+ if (flag & gcvPOWER_FLAG_ACQUIRE)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+ acquired = gcvTRUE;
+ }
+
+ if (flag & gcvPOWER_FLAG_STOP)
+ {
+ /* Stop the command parser. */
+ gcmkONERROR(gckCOMMAND_Stop(command, gcvFALSE));
+
+ /* Stop the Isr. */
+ if (Hardware->stopIsr)
+ {
+ gcmkONERROR(Hardware->stopIsr(Hardware->isrContext));
+ }
+ }
+
+ /* Flush Cache before Power Off. */
+ if (flag & gcvPOWER_FLAG_POWER_OFF)
+ {
+ if (Hardware->clockState == gcvFALSE)
+ {
+ /* Turn off the GPU power. */
+ gcmkONERROR(
+ gckOS_SetGPUPower(os,
+ Hardware->core,
+ gcvTRUE,
+ gcvTRUE));
+
+ Hardware->clockState = gcvTRUE;
+
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_DYNAMIC_FREQUENCY_SCALING) != gcvTRUE)
+ {
+ /* Write the clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(os,
+ Hardware->core,
+ 0x00000,
+ clocks[0]));
+
+ /* Done loading the frequency scaler. */
+ gcmkONERROR(gckOS_WriteRegisterEx(os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (clocks[0])) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
+ }
+ }
+
+ gcmkONERROR(gckCOMMAND_Start(command));
+
+ gcmkONERROR(_FlushCache(Hardware, command));
+
+ gckOS_Delay(gcvNULL, 1);
+
+ /* Stop the command parser. */
+ gcmkONERROR(gckCOMMAND_Stop(command, gcvFALSE));
+
+ flag |= gcvPOWER_FLAG_CLOCK_OFF;
+ }
+
+ /* Get time until stopped. */
+ gcmkPROFILE_QUERY(time, stopTime);
+
+ /* Only process this when hardware is enabled. */
+ if (Hardware->clockState && Hardware->powerState
+ /* Don't touch clock control if dynamic frequency scaling is available. */
+ && gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_DYNAMIC_FREQUENCY_SCALING) != gcvTRUE
+ )
+ {
+ if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
+ {
+ if (Hardware->identity.chipModel == gcv4000
+ && ((Hardware->identity.chipRevision == 0x5208) || (Hardware->identity.chipRevision == 0x5222)))
+ {
+ clock &= ~2U;
+ }
+ }
+
+ /* Write the clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(os,
+ Hardware->core,
+ 0x00000,
+ clock));
+
+ /* Done loading the frequency scaler. */
+ gcmkONERROR(gckOS_WriteRegisterEx(os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
+ }
+
+ if (flag & gcvPOWER_FLAG_DELAY)
+ {
+ /* Wait for the specified amount of time to settle coming back from
+ ** power-off or suspend state. */
+ gcmkONERROR(gckOS_Delay(os, gcdPOWER_CONTROL_DELAY));
+ }
+
+ /* Get time until delayed. */
+ gcmkPROFILE_QUERY(time, delayTime);
+
+ if (flag & gcvPOWER_FLAG_INITIALIZE)
+ {
+ /* Initialize hardware. */
+ gcmkONERROR(gckHARDWARE_InitializeHardware(Hardware));
+
+ gcmkONERROR(gckHARDWARE_SetFastClear(Hardware,
+ Hardware->allowFastClear,
+ Hardware->allowCompression));
+
+ /* Force the command queue to reload the next context. */
+ command->currContext = gcvNULL;
+
+ /* Need to config mmu after command start. */
+ configMmu = gcvTRUE;
+ }
+
+ /* Get time until initialized. */
+ gcmkPROFILE_QUERY(time, initTime);
+
+ if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
+ {
+ /* Turn off the GPU power. */
+ gcmkONERROR(
+ gckOS_SetGPUPower(os,
+ Hardware->core,
+ (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
+ : gcvTRUE,
+ (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
+ : gcvTRUE));
+
+ /* Save current hardware power and clock states. */
+ Hardware->clockState = (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
+ : gcvTRUE;
+ Hardware->powerState = (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
+ : gcvTRUE;
+ }
+
+ /* Get time until off. */
+ gcmkPROFILE_QUERY(time, offTime);
+
+ if (flag & gcvPOWER_FLAG_START)
+ {
+ /* Start the command processor. */
+ gcmkONERROR(gckCOMMAND_Start(command));
+ commandStarted = gcvTRUE;
+
+ if (Hardware->startIsr)
+ {
+ /* Start the Isr. */
+ gcmkONERROR(Hardware->startIsr(Hardware->isrContext));
+ isrStarted = gcvTRUE;
+ }
+ }
+
+ /* Get time until started. */
+ gcmkPROFILE_QUERY(time, startTime);
+
+ if (flag & gcvPOWER_FLAG_RELEASE)
+ {
+ /* Release the power management semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
+ acquired = gcvFALSE;
+
+ if (global)
+ {
+ /* Verify global semaphore has been acquired already before
+ ** we release it.
+ ** If it was acquired, gckOS_TryAcquireSemaphore will return
+ ** gcvSTATUS_TIMEOUT and we release it. Otherwise, global
+ ** semaphore will be acquried now, but it still is released
+ ** immediately. */
+ status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
+ if (status != gcvSTATUS_TIMEOUT)
+ {
+ gcmkONERROR(status);
+ }
+
+ /* Release the global semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
+ globalAcquired = gcvFALSE;
+ }
+ }
+
+ gckSTATETIMER_Accumulate(&Hardware->powerStateTimer, Hardware->chipPowerState);
+
+ /* Save the new power state. */
+ Hardware->chipPowerState = State;
+
+#if gcdDVFS
+ if (State == gcvPOWER_ON && Hardware->kernel->dvfs)
+ {
+ gckDVFS_Start(Hardware->kernel->dvfs);
+ }
+#endif
+
+#if gcdPOWEROFF_TIMEOUT
+ /* Reset power off time */
+ gcmkONERROR(gckOS_GetTicks(&currentTime));
+
+ Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
+
+ if (State == gcvPOWER_IDLE || State == gcvPOWER_SUSPEND)
+ {
+ /* Start a timer to power off GPU when GPU enters IDLE or SUSPEND. */
+ gcmkVERIFY_OK(gckOS_StartTimer(os,
+ Hardware->powerOffTimer,
+ Hardware->powerOffTimeout));
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "Cancel powerOfftimer");
+
+ /* Cancel running timer when GPU enters ON or OFF. */
+ gcmkVERIFY_OK(gckOS_StopTimer(os, Hardware->powerOffTimer));
+ }
+#endif
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* Get total time. */
+ gcmkPROFILE_QUERY(time, totalTime);
+#if gcdENABLE_PROFILING
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "PROF(%llu): mutex:%llu on:%llu stall:%llu stop:%llu",
+ freq, mutexTime, onTime, stallTime, stopTime);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ " delay:%llu init:%llu off:%llu start:%llu total:%llu",
+ delayTime, initTime, offTime, startTime, totalTime);
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (commandStarted)
+ {
+ gcmkVERIFY_OK(gckCOMMAND_Stop(command, gcvFALSE));
+ }
+
+ if (isrStarted)
+ {
+ gcmkVERIFY_OK(Hardware->stopIsr(Hardware->isrContext));
+ }
+
+ if (commitEntered)
+ {
+ /* Release the command queue mutex. */
+ gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, gcvTRUE));
+ }
+
+ if (acquired)
+ {
+ /* Release semaphore. */
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
+ command->powerSemaphore));
+ }
+
+ if (globalAcquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
+ Hardware->globalSemaphore));
+ }
+
+ if (mutexAcquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryPowerManagementState
+**
+** Get GPU power state.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gceCHIPPOWERSTATE* State
+** Power State.
+**
+*/
+gceSTATUS
+gckHARDWARE_QueryPowerManagementState(
+ IN gckHARDWARE Hardware,
+ OUT gceCHIPPOWERSTATE* State
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(State != gcvNULL);
+
+ /* Return the statue. */
+ *State = Hardware->chipPowerState;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*State=%d", *State);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetPowerManagement
+**
+** Configure GPU power management function.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctBOOL PowerManagement
+** Power Mangement State.
+**
+*/
+gceSTATUS
+gckHARDWARE_SetPowerManagement(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL PowerManagement
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ if(!Hardware->powerManagementLock)
+ {
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE));
+
+ 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
+**
+** Configure GPU profiler function.
+** Only used in driver initialization stage.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctBOOL GpuProfiler
+** GOU Profiler State.
+**
+*/
+gceSTATUS
+gckHARDWARE_SetGpuProfiler(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL GpuProfiler
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* 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. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+gceSTATUS
+gckHARDWARE_SetFscaleValue(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 FscaleValue
+ )
+{
+ gceSTATUS status;
+ gctUINT32 clock;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Hardware=0x%x FscaleValue=%d", Hardware, FscaleValue);
+
+ gcmkVERIFY_ARGUMENT(FscaleValue > 0 && FscaleValue <= 64);
+
+ gcmkONERROR(
+ gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ Hardware->powerOnFscaleVal = FscaleValue;
+
+ if (Hardware->chipPowerState == gcvPOWER_ON)
+ {
+ gctUINT32 data;
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &data));
+
+ /* Disable all clock gating. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 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)))
+ | ((((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) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((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) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)))
+ | ((((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) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11)))));
+
+ 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) (FscaleValue) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ clock));
+
+ /* Done loading the frequency scaler. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
+
+ /* Restore all clock gating. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ data));
+ }
+
+ gcmkVERIFY(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_GetFscaleValue(
+ IN gckHARDWARE Hardware,
+ IN gctUINT * FscaleValue,
+ IN gctUINT * MinFscaleValue,
+ IN gctUINT * MaxFscaleValue
+ )
+{
+ *FscaleValue = Hardware->powerOnFscaleVal;
+ *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
+gceSTATUS
+gckHARDWARE_SetPowerOffTimeout(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Timeout
+)
+{
+ gcmkHEADER_ARG("Hardware=0x%x Timeout=%d", Hardware, Timeout);
+
+ Hardware->powerOffTimeout = Timeout;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+
+gceSTATUS
+gckHARDWARE_QueryPowerOffTimeout(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32* Timeout
+)
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ *Timeout = Hardware->powerOffTimeout;
+
+ gcmkFOOTER_ARG("*Timeout=%d", *Timeout);
+ return gcvSTATUS_OK;
+}
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryIdle(
+ IN gckHARDWARE Hardware,
+ OUT gctBOOL_PTR IsIdle
+ )
+{
+ 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);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
+
+ /* We are idle when the power is not ON. */
+ if (Hardware->chipPowerState != gcvPOWER_ON)
+ {
+ isIdle = gcvTRUE;
+#if gcdMULTI_GPU > 1
+ isIdle3D1 = gcvTRUE;
+#endif
+ }
+
+ else
+ {
+ /* Read idle register. */
+ 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)
+ || ((((((gctUINT32) (idle)) >> (0 ? 4:4)) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1)))))) ) != 1)
+ || ((((((gctUINT32) (idle)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) ) != 1)
+ || ((((((gctUINT32) (idle)) >> (0 ? 6:6)) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1)))))) ) != 1)
+ || ((((((gctUINT32) (idle)) >> (0 ? 7:7)) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1)))))) ) != 1)
+ || ((((((gctUINT32) (idle)) >> (0 ? 2:2)) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) ) != 1)
+ )
+ {
+ /* Something is busy. */
+ isIdle = gcvFALSE;
+ }
+
+ else
+ {
+#if gcdSECURITY
+ isIdle = gcvTRUE;
+ address = 0;
+#else
+ /* Read the current FE address. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00664,
+ &address));
+
+ /* Test if address is inside the last WAIT/LINK sequence. */
+ if ((address >= Hardware->lastWaitLink)
+#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;
+ }
+ else
+ {
+ /* FE is not in WAIT/LINK yet. */
+ 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. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** Handy macros that will help in reading those debug registers.
+*/
+
+#define gcmkREAD_DEBUG_REGISTER(control, block, index, data) \
+ gcmkONERROR(\
+ gckOS_WriteRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ index))); \
+ gcmkONERROR(\
+ gckOS_ReadRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_SIGNALS_##block##_Address, \
+ &profiler->data))
+
+#define gcmkREAD_DEBUG_REGISTER_N(control, block, index, data) \
+ gcmkONERROR(\
+ gckOS_WriteRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ index))); \
+ gcmkONERROR(\
+ gckOS_ReadRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_SIGNALS_##block##_Address, \
+ &data))
+
+#define gcmkRESET_DEBUG_REGISTER(control, block, value) \
+ gcmkONERROR(\
+ gckOS_WriteRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ value))); \
+ gcmkONERROR(\
+ gckOS_WriteRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ 0)))
+
+/*******************************************************************************
+**
+** gckHARDWARE_ProfileEngine2D
+**
+** Read the profile registers available in the 2D engine and sets them in the
+** profile. The function will also reset the pixelsRendered counter every time.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** OPTIONAL gcs2D_PROFILE_PTR Profile
+** Pointer to a gcs2D_Profile structure.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ProfileEngine2D(
+ IN gckHARDWARE Hardware,
+ OPTIONAL gcs2D_PROFILE_PTR Profile
+ )
+{
+ gceSTATUS status;
+ gcs2D_PROFILE_PTR profiler = Profile;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (Profile != gcvNULL)
+ {
+ /* Read the cycle count. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00438,
+ &Profile->cycleCount));
+
+ /* Read pixels rendered by 2D engine. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (11) & ((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, 0x00454, &profiler->pixelsRendered));
+
+ /* Reset counter. */
+ 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)))
+));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gckHARDWARE_QueryProfileRegisters(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Reset,
+ OUT gcsPROFILER_COUNTERS * Counters
+ )
+{
+ gceSTATUS status;
+ gcsPROFILER_COUNTERS * profiler = Counters;
+ gctUINT i, clock;
+ gctUINT32 colorKilled, colorDrawn, depthKilled, depthDrawn;
+ gctUINT32 totalRead, totalWrite;
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 resetValue = 0xF;
+
+ gcmkHEADER_ARG("Hardware=0x%x Counters=0x%x", Hardware, Counters);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ chipModel = Hardware->identity.chipModel;
+ chipRevision = Hardware->identity.chipRevision;
+ if ((chipModel == gcv5000 && chipRevision == 0x5434) || (chipModel == gcv3000 && chipRevision == 0x5435))
+ {
+ resetValue = 0xFF;
+ }
+
+ /* Read the counters. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00438,
+ &profiler->gpuCyclesCounter));
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ &profiler->gpuTotalCyclesCounter));
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0007C,
+ &profiler->gpuIdleCyclesCounter));
+
+
+ /* Read clock control register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &clock));
+
+ profiler->gpuTotalRead64BytesPerFrame = 0;
+ profiler->gpuTotalWrite64BytesPerFrame = 0;
+ profiler->pe_pixel_count_killed_by_color_pipe = 0;
+ profiler->pe_pixel_count_killed_by_depth_pipe = 0;
+ profiler->pe_pixel_count_drawn_by_color_pipe = 0;
+ profiler->pe_pixel_count_drawn_by_depth_pipe = 0;
+
+ /* 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)))));
+
+ /* BW */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00040,
+ &totalRead));
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00044,
+ &totalWrite));
+
+ profiler->gpuTotalRead64BytesPerFrame += totalRead;
+ profiler->gpuTotalWrite64BytesPerFrame += totalWrite;
+
+ /* PE */
+ 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)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &colorKilled));
+ 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) (1) & ((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, 0x00454, &depthKilled));
+ 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) (2) & ((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, 0x00454, &colorDrawn));
+ 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) (3) & ((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, 0x00454, &depthDrawn));
+
+ profiler->pe_pixel_count_killed_by_color_pipe += colorKilled;
+ profiler->pe_pixel_count_killed_by_depth_pipe += depthKilled;
+ profiler->pe_pixel_count_drawn_by_color_pipe += colorDrawn;
+ profiler->pe_pixel_count_drawn_by_depth_pipe += depthDrawn;
+ }
+
+ /* Reset clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ clock));
+
+ /* 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) (resetValue) & ((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))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->ps_inst_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((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->rendered_pixel_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) (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, 0x0045C, &profiler->vs_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) (10) & ((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->rendered_vertice_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) (11) & ((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->vtx_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) (12) & ((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->vtx_texld_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) (13) & ((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_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));
+ 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) (resetValue) & ((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))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_vtx_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (4) & ((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_input_prim_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) (5) & ((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_output_prim_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) (6) & ((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_depth_clipped_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) (7) & ((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_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));
+ 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) (resetValue) & ((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));
+ 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) (resetValue) & ((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))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_pixel_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((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_total_quad_count));
+ 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) (2) & ((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_valid_quad_count_after_early_z));
+ 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) (3) & ((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_total_primitive_count));
+ 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) (9) & ((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_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));
+ 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) (resetValue) & ((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))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_bilinear_requests));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (1) & ((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_total_trilinear_requests));
+ 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) (2) & ((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_total_discarded_texture_requests));
+ 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) (3) & ((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_total_texture_requests));
+ 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) (5) & ((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_mem_read_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) (6) & ((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_mem_read_in_8B_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) (7) & ((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_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) (8) & ((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_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));
+ 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) (resetValue) & ((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))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_pipeline));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (2) & ((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_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));
+ 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) (resetValue) & ((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))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_read_request_stalled));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 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, 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));
+ 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) (resetValue) & ((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();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+
+#if VIVANTE_PROFILER_CONTEXT
+#define gcmkUPDATE_PROFILE_DATA(data) \
+ profilerHistroy->data += profiler->data
+
+gceSTATUS
+gckHARDWARE_QueryContextProfile(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Reset,
+ IN gckCONTEXT Context,
+ OUT gcsPROFILER_COUNTERS * Counters
+ )
+{
+ gceSTATUS status;
+ gckCOMMAND command = Hardware->kernel->command;
+ gcsPROFILER_COUNTERS * profiler = Counters;
+
+ gcmkHEADER_ARG("Hardware=0x%x Counters=0x%x", Hardware, Counters);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Acquire the context sequnence mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ command->os, command->mutexContextSeq, gcvINFINITE
+ ));
+
+ /* Read the counters. */
+ gcmkVERIFY_OK(gckOS_MemCopy(
+ profiler, &Context->histroyProfiler, gcmSIZEOF(gcsPROFILER_COUNTERS)
+ ));
+
+ /* Reset counters. */
+ gcmkVERIFY_OK(gckOS_ZeroMemory(
+ &Context->histroyProfiler, gcmSIZEOF(gcsPROFILER_COUNTERS)
+ ));
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(
+ command->os, command->mutexContextSeq
+ ));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gctUINT32
+CalcDelta(
+ IN gctUINT32 new,
+ IN gctUINT32 old
+ )
+{
+ if (new >= old)
+ {
+ return new - old;
+ }
+ else
+ {
+ return (gctUINT32)((gctUINT64)new + 0x100000000ll - old);
+ }
+}
+
+#if USE_SW_RESET
+#define gcmkRESET_PROFILE_DATA(counterName, prevCounterName) \
+ temp = profiler->counterName; \
+ profiler->counterName = CalcDelta(temp, Context->prevCounterName); \
+ Context->prevCounterName = temp
+
+#endif
+
+gceSTATUS
+gckHARDWARE_UpdateContextProfile(
+ IN gckHARDWARE Hardware,
+ IN gckCONTEXT Context
+ )
+{
+ gceSTATUS status;
+ gcsPROFILER_COUNTERS * profiler = &Context->latestProfiler;
+ gcsPROFILER_COUNTERS * profilerHistroy = &Context->histroyProfiler;
+ gctUINT i, clock;
+ gctUINT32 colorKilled = 0, colorDrawn = 0, depthKilled = 0, depthDrawn = 0;
+ gctUINT32 totalRead, totalWrite;
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 temp;
+ gctUINT32 resetValue = 0xF;
+
+ gcmkHEADER_ARG("Hardware=0x%x Context=0x%x", Hardware, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
+
+ chipModel = Hardware->identity.chipModel;
+ chipRevision = Hardware->identity.chipRevision;
+ if ((chipModel == gcv5000 && chipRevision == 0x5434) || (chipModel == gcv3000 && chipRevision == 0x5435))
+ {
+ resetValue = 0xFF;
+ }
+
+ /* Read the counters. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00438,
+ &profiler->gpuCyclesCounter));
+ gcmkUPDATE_PROFILE_DATA(gpuCyclesCounter);
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ &profiler->gpuTotalCyclesCounter));
+ gcmkUPDATE_PROFILE_DATA(gpuTotalCyclesCounter);
+
+ if (chipModel == gcv2100 || chipModel == gcv2000 || chipModel == gcv880)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ &profiler->gpuIdleCyclesCounter));
+ }
+ else
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0007C,
+ &profiler->gpuIdleCyclesCounter));
+ }
+ gcmkUPDATE_PROFILE_DATA(gpuIdleCyclesCounter);
+
+ /* Read clock control register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &clock));
+
+ profiler->gpuTotalRead64BytesPerFrame = 0;
+ profiler->gpuTotalWrite64BytesPerFrame = 0;
+ profiler->pe_pixel_count_killed_by_color_pipe = 0;
+ profiler->pe_pixel_count_killed_by_depth_pipe = 0;
+ profiler->pe_pixel_count_drawn_by_color_pipe = 0;
+ profiler->pe_pixel_count_drawn_by_depth_pipe = 0;
+
+ /* 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)))));
+
+ /* BW */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00040,
+ &totalRead));
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00044,
+ &totalWrite));
+
+ profiler->gpuTotalRead64BytesPerFrame += totalRead;
+ profiler->gpuTotalWrite64BytesPerFrame += totalWrite;
+
+ /* PE */
+ 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)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &colorKilled));
+ 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) (1) & ((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, 0x00454, &depthKilled));
+ 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) (2) & ((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, 0x00454, &colorDrawn));
+ 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) (3) & ((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, 0x00454, &depthDrawn));
+
+ profiler->pe_pixel_count_killed_by_color_pipe += colorKilled;
+ profiler->pe_pixel_count_killed_by_depth_pipe += depthKilled;
+ profiler->pe_pixel_count_drawn_by_color_pipe += colorDrawn;
+ profiler->pe_pixel_count_drawn_by_depth_pipe += depthDrawn;
+ }
+
+ gcmkUPDATE_PROFILE_DATA(gpuTotalRead64BytesPerFrame);
+ gcmkUPDATE_PROFILE_DATA(gpuTotalWrite64BytesPerFrame);
+#if USE_SW_RESET
+ gcmkRESET_PROFILE_DATA(pe_pixel_count_killed_by_color_pipe, prevPePixelCountKilledByColorPipe);
+ gcmkRESET_PROFILE_DATA(pe_pixel_count_killed_by_depth_pipe, prevPePixelCountKilledByDepthPipe);
+ gcmkRESET_PROFILE_DATA(pe_pixel_count_drawn_by_color_pipe, prevPePixelCountDrawnByColorPipe);
+ gcmkRESET_PROFILE_DATA(pe_pixel_count_drawn_by_depth_pipe, prevPePixelCountDrawnByDepthPipe);
+#endif
+ gcmkUPDATE_PROFILE_DATA(pe_pixel_count_killed_by_color_pipe);
+ gcmkUPDATE_PROFILE_DATA(pe_pixel_count_killed_by_depth_pipe);
+ gcmkUPDATE_PROFILE_DATA(pe_pixel_count_drawn_by_color_pipe);
+ gcmkUPDATE_PROFILE_DATA(pe_pixel_count_drawn_by_depth_pipe);
+
+ /* Reset clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ clock));
+
+ /* 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));
+#if !USE_SW_RESET
+ 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) (resetValue) & ((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)))
+));
+#endif
+ /* 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))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->ps_inst_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((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->rendered_pixel_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) (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, 0x0045C, &profiler->vs_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) (10) & ((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->rendered_vertice_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) (11) & ((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->vtx_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) (12) & ((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->vtx_texld_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) (13) & ((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_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 USE_SW_RESET
+ gcmkRESET_PROFILE_DATA(ps_inst_counter, prevPSInstCount);
+ gcmkRESET_PROFILE_DATA(rendered_pixel_counter, prevPSPixelCount);
+ gcmkRESET_PROFILE_DATA(vs_inst_counter, prevVSInstCount);
+ gcmkRESET_PROFILE_DATA(rendered_vertice_counter, prevVSVertexCount);
+ gcmkRESET_PROFILE_DATA(vtx_branch_inst_counter, prevVSBranchInstCount);
+ gcmkRESET_PROFILE_DATA(vtx_texld_inst_counter, prevVSTexInstCount);
+ gcmkRESET_PROFILE_DATA(pxl_branch_inst_counter, prevPSBranchInstCount);
+ gcmkRESET_PROFILE_DATA(pxl_texld_inst_counter, prevPSTexInstCount);
+#endif
+
+ gcmkUPDATE_PROFILE_DATA(ps_inst_counter);
+ gcmkUPDATE_PROFILE_DATA(rendered_pixel_counter);
+ gcmkUPDATE_PROFILE_DATA(vs_inst_counter);
+ gcmkUPDATE_PROFILE_DATA(rendered_vertice_counter);
+ gcmkUPDATE_PROFILE_DATA(vtx_branch_inst_counter);
+ gcmkUPDATE_PROFILE_DATA(vtx_texld_inst_counter);
+ gcmkUPDATE_PROFILE_DATA(pxl_branch_inst_counter);
+ gcmkUPDATE_PROFILE_DATA(pxl_texld_inst_counter);
+
+#if !USE_SW_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) (resetValue) & ((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)))
+));
+#endif
+
+ /* 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))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_vtx_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (4) & ((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_input_prim_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) (5) & ((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_output_prim_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) (6) & ((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_depth_clipped_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) (7) & ((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_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 USE_SW_RESET
+ gcmkRESET_PROFILE_DATA(pa_input_vtx_counter, prevPaInputVtxCounter);
+ gcmkRESET_PROFILE_DATA(pa_input_prim_counter, prevPaInputPrimCounter);
+ gcmkRESET_PROFILE_DATA(pa_output_prim_counter, prevPaOutputPrimCounter);
+ gcmkRESET_PROFILE_DATA(pa_depth_clipped_counter, prevPaDepthClippedCounter);
+ gcmkRESET_PROFILE_DATA(pa_trivial_rejected_counter, prevPaTrivialRejectedCounter);
+ gcmkRESET_PROFILE_DATA(pa_culled_counter, prevPaCulledCounter);
+#endif
+ gcmkUPDATE_PROFILE_DATA(pa_input_vtx_counter);
+ gcmkUPDATE_PROFILE_DATA(pa_input_prim_counter);
+ gcmkUPDATE_PROFILE_DATA(pa_output_prim_counter);
+ gcmkUPDATE_PROFILE_DATA(pa_depth_clipped_counter);
+ gcmkUPDATE_PROFILE_DATA(pa_trivial_rejected_counter);
+ gcmkUPDATE_PROFILE_DATA(pa_culled_counter);
+#if !USE_SW_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) (resetValue) & ((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)))
+));
+#endif
+
+ /* 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));
+ gcmkUPDATE_PROFILE_DATA(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));
+ gcmkUPDATE_PROFILE_DATA(se_culled_lines_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) (resetValue) & ((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))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_pixel_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((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_total_quad_count));
+ 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) (2) & ((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_valid_quad_count_after_early_z));
+ 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) (3) & ((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_total_primitive_count));
+ 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) (9) & ((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_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 USE_SW_RESET
+ gcmkRESET_PROFILE_DATA(ra_valid_pixel_count, prevRaValidPixelCount);
+ gcmkRESET_PROFILE_DATA(ra_total_quad_count, prevRaTotalQuadCount);
+ gcmkRESET_PROFILE_DATA(ra_valid_quad_count_after_early_z, prevRaValidQuadCountAfterEarlyZ);
+ gcmkRESET_PROFILE_DATA(ra_total_primitive_count, prevRaTotalPrimitiveCount);
+ gcmkRESET_PROFILE_DATA(ra_pipe_cache_miss_counter, prevRaPipeCacheMissCounter);
+ gcmkRESET_PROFILE_DATA(ra_prefetch_cache_miss_counter, prevRaPrefetchCacheMissCounter);
+#endif
+ gcmkUPDATE_PROFILE_DATA(ra_valid_pixel_count);
+ gcmkUPDATE_PROFILE_DATA(ra_total_quad_count);
+ gcmkUPDATE_PROFILE_DATA(ra_valid_quad_count_after_early_z);
+ gcmkUPDATE_PROFILE_DATA(ra_total_primitive_count);
+ gcmkUPDATE_PROFILE_DATA(ra_pipe_cache_miss_counter);
+ gcmkUPDATE_PROFILE_DATA(ra_prefetch_cache_miss_counter);
+#if !USE_SW_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) (resetValue) & ((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)))
+));
+#endif
+
+ /* 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))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_bilinear_requests));
+ gcmkUPDATE_PROFILE_DATA(tx_total_bilinear_requests);
+ 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) (1) & ((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_total_trilinear_requests));
+ gcmkUPDATE_PROFILE_DATA(tx_total_trilinear_requests);
+ 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) (2) & ((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_total_discarded_texture_requests));
+ gcmkUPDATE_PROFILE_DATA(tx_total_discarded_texture_requests);
+ 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) (3) & ((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_total_texture_requests));
+ gcmkUPDATE_PROFILE_DATA(tx_total_texture_requests);
+ 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) (5) & ((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_mem_read_count));
+ gcmkUPDATE_PROFILE_DATA(tx_mem_read_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) (6) & ((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_mem_read_in_8B_count));
+ gcmkUPDATE_PROFILE_DATA(tx_mem_read_in_8B_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) (7) & ((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_count));
+ gcmkUPDATE_PROFILE_DATA(tx_cache_miss_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) (8) & ((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_hit_texel_count));
+ gcmkUPDATE_PROFILE_DATA(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));
+ gcmkUPDATE_PROFILE_DATA(tx_cache_miss_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) (resetValue) & ((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))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_pipeline));
+ gcmkUPDATE_PROFILE_DATA(mc_total_read_req_8B_from_pipeline);
+ 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) (2) & ((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_read_req_8B_from_IP));
+ gcmkUPDATE_PROFILE_DATA(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));
+ gcmkUPDATE_PROFILE_DATA(mc_total_write_req_8B_from_pipeline);
+ 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) (resetValue) & ((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))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_read_request_stalled));
+ gcmkUPDATE_PROFILE_DATA(hi_axi_cycles_read_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) (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, 0x0046C, &profiler->hi_axi_cycles_write_request_stalled));
+ gcmkUPDATE_PROFILE_DATA(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));
+ gcmkUPDATE_PROFILE_DATA(hi_axi_cycles_write_data_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) (resetValue) & ((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();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+
+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;
+}
+
+static gceSTATUS
+_ResetGPU(
+ IN gckHARDWARE Hardware,
+ IN gckOS Os,
+ IN gceCORE Core
+ )
+{
+ gctUINT32 control, idle;
+ gceSTATUS status;
+
+ for (;;)
+ {
+ /* Disable clock gating. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ Hardware->powerBaseAddress +
+ 0x00104,
+ 0x00000000));
+
+ control = ((((gctUINT32) (0x01590880)) & ~(((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 pulse-eater. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x0010C,
+ control));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x0010C,
+ ((((gctUINT32) (control)) & ~(((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)))));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x0010C,
+ control));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ ((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ 0x00000900));
+
+ /* Wait for clock being stable. */
+ gcmkONERROR(gckOS_Delay(Os, 1));
+
+ /* Isolate the GPU. */
+ control = ((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ control));
+
+ /* Set soft reset. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
+
+ /* Wait for reset. */
+ gcmkONERROR(gckOS_Delay(Os, 1));
+
+ /* Reset soft reset bit. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
+
+ /* Reset GPU isolation. */
+ control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ control));
+
+ /* Read idle register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Os,
+ Core,
+ 0x00004,
+ &idle));
+
+ if ((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) == 0)
+ {
+ continue;
+ }
+
+#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,
+ 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;
+ }
+
+#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;
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Return the error. */
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_Reset(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
+
+ /* 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));
+ }
+
+ /* Initialize hardware. */
+ gcmkONERROR(gckHARDWARE_InitializeHardware(Hardware));
+
+ /* 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:
+ gcmkPRINT("[galcore]: Hardware not reset successfully, give up");
+
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_GetBaseAddress(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR BaseAddress
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+ /* Test if we have a new Memory Controller. */
+ if (((((gctUINT32) (Hardware->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))))))))
+ {
+ /* No base address required. */
+ *BaseAddress = 0;
+ }
+ else
+ {
+ /* Get the base address from the OS. */
+ gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, BaseAddress));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_NeedBaseAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 State,
+ OUT gctBOOL_PTR NeedBase
+ )
+{
+ gctBOOL need = gcvFALSE;
+
+ gcmkHEADER_ARG("Hardware=0x%x State=0x%08x", Hardware, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(NeedBase != gcvNULL);
+
+ /* Make sure this is a load state. */
+ if (((((gctUINT32) (State)) >> (0 ? 31:27) & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))))
+ {
+#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)))))) ))
+ {
+ case 0x0596:
+ case 0x0597:
+ case 0x0599:
+ case 0x059A:
+ case 0x05A9:
+ /* These states need a TRUE physical address. */
+ need = gcvTRUE;
+ break;
+ }
+#else
+ /* 2D addresses don't need a base address. */
+#endif
+ }
+
+ /* Return the flag. */
+ *NeedBase = need;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*NeedBase=%d", *NeedBase);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_SetIsrManager(
+ IN gckHARDWARE Hardware,
+ IN gctISRMANAGERFUNC StartIsr,
+ IN gctISRMANAGERFUNC StopIsr,
+ IN gctPOINTER Context
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ gcmkHEADER_ARG("Hardware=0x%x, StartIsr=0x%x, StopIsr=0x%x, Context=0x%x",
+ Hardware, StartIsr, StopIsr, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (StartIsr == gcvNULL ||
+ StopIsr == gcvNULL ||
+ Context == gcvNULL)
+ {
+ status = gcvSTATUS_INVALID_ARGUMENT;
+
+ gcmkFOOTER();
+ return status;
+ }
+
+ Hardware->startIsr = StartIsr;
+ Hardware->stopIsr = StopIsr;
+ Hardware->isrContext = Context;
+
+ /* Success. */
+ gcmkFOOTER();
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Compose
+**
+** Start a composition.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Compose(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 ProcessID,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Offset,
+ IN gctSIZE_T Size,
+ IN gctUINT8 EventID
+ )
+{
+#if gcdENABLE_3D
+ gceSTATUS status;
+ gctUINT32_PTR triggerState;
+
+ gcmkHEADER_ARG("Hardware=0x%x Physical=0x%x Logical=0x%x"
+ " Offset=%d Size=%d EventID=%d",
+ Hardware, Physical, Logical, Offset, Size, EventID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(((Size + 8) & 63) == 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Program the trigger state. */
+ triggerState = (gctUINT32_PTR) ((gctUINT8_PTR) Logical + Offset + Size);
+ triggerState[0] = 0x0C03;
+ triggerState[1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:4) - (0 ? 5:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:4) - (0 ? 5:4) + 1))))))) << (0 ? 5:4))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 5:4) - (0 ? 5:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:4) - (0 ? 5:4) + 1))))))) << (0 ? 5:4)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:16) - (0 ? 20:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:16) - (0 ? 20:16) + 1))))))) << (0 ? 20:16))) | (((gctUINT32) ((gctUINT32) (EventID) & ((gctUINT32) ((((1 ? 20:16) - (0 ? 20:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:16) - (0 ? 20:16) + 1))))))) << (0 ? 20:16)))
+ ;
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache for the wait/link. */
+ gcmkONERROR(gckOS_CacheClean(
+ Hardware->os, ProcessID, gcvNULL,
+ (gctUINT32)Physical, Logical, Offset + Size
+ ));
+#endif
+
+ /* Start composition. */
+ gcmkONERROR(gckOS_WriteRegisterEx(
+ Hardware->os, Hardware->core, 0x00554,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)))
+ ));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+#else
+ /* Return the status. */
+ return gcvSTATUS_NOT_SUPPORTED;
+#endif
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_IsFeatureAvailable
+**
+** Verifies whether the specified feature is available in hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gceFEATURE Feature
+** Feature to be verified.
+*/
+gceSTATUS
+gckHARDWARE_IsFeatureAvailable(
+ IN gckHARDWARE Hardware,
+ IN gceFEATURE Feature
+ )
+{
+ gctBOOL available;
+
+ gcmkHEADER_ARG("Hardware=0x%x Feature=%d", Hardware, Feature);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Only features needed by common kernel logic added here. */
+ switch (Feature)
+ {
+ case gcvFEATURE_END_EVENT:
+ /*available = gcmVERIFYFIELDVALUE(Hardware->identity.chipMinorFeatures2,
+ GC_MINOR_FEATURES2, END_EVENT, AVAILABLE
+ );*/
+ 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:
+ available = ((((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)))))) == (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))));
+ break;
+
+ case gcvFEATURE_PIPE_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_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;
+
+ case gcvFEATURE_TEX_CACHE_FLUSH_FIX:
+ available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures5)) >> (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)))))));
+ break;
+
+ case gcvFEATURE_MMU:
+ available= ((((gctUINT32) (Hardware->identity.chipMinorFeatures1)) >> (0 ? 28:28) & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))));
+ break;
+
+ default:
+ gcmkFATAL("Invalid feature has been requested.");
+ available = gcvFALSE;
+ }
+
+ /* Return result. */
+ gcmkFOOTER_ARG("%d", available ? gcvSTATUS_TRUE : gcvSTATUS_FALSE);
+ return available ? gcvSTATUS_TRUE : gcvSTATUS_FALSE;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_DumpMMUException
+**
+** Dump the MMU debug info on an MMU exception.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_DumpMMUException(
+ IN gckHARDWARE Hardware
+ )
+{
+ 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);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ gcmkPRINT("GPU[%d](ChipModel=0x%x ChipRevision=0x%x):\n",
+ Hardware->core,
+ Hardware->identity.chipModel,
+ Hardware->identity.chipRevision);
+
+ gcmkPRINT("**************************\n");
+ gcmkPRINT("*** MMU ERROR DUMP ***\n");
+ gcmkPRINT("**************************\n");
+
+ gcmkVERIFY_OK(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00188,
+ &mmuStatus));
+
+ gcmkPRINT(" MMU status = 0x%08X\n", mmuStatus);
+
+ for (i = 0; i < 4; i += 1)
+ {
+ mmu = mmuStatus & 0xF;
+ mmuStatus >>= 4;
+
+ if (mmu == 0)
+ {
+ continue;
+ }
+
+ switch (mmu)
+ {
+ case 1:
+ gcmkPRINT(" MMU%d: slave not present\n", i);
+ break;
+
+ case 2:
+ gcmkPRINT(" MMU%d: page not present\n", i);
+ break;
+
+ case 3:
+ gcmkPRINT(" MMU%d: write violation\n", i);
+ break;
+
+ default:
+ gcmkPRINT(" MMU%d: unknown state\n", i);
+ }
+
+ gcmkVERIFY_OK(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00190 + i * 4,
+ &address));
+
+ mtlb = (address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
+ stlb = (address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
+ offset = address & gcdMMU_OFFSET_4K_MASK;
+
+ gcmkPRINT(" MMU%d: exception address = 0x%08X\n", i, address);
+
+ gcmkPRINT(" MTLB entry = %d\n", mtlb);
+
+ gcmkPRINT(" STLB entry = %d\n", stlb);
+
+ gcmkPRINT(" Offset = 0x%08X (%d)\n", offset, offset);
+
+ 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();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_DumpGPUState
+**
+** Dump the GPU debug registers.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_DumpGPUState(
+ IN gckHARDWARE Hardware
+ )
+{
+ static gctCONST_STRING _cmdState[] =
+ {
+ "PAR_IDLE_ST", "PAR_DEC_ST", "PAR_ADR0_ST", "PAR_LOAD0_ST",
+ "PAR_ADR1_ST", "PAR_LOAD1_ST", "PAR_3DADR_ST", "PAR_3DCMD_ST",
+ "PAR_3DCNTL_ST", "PAR_3DIDXCNTL_ST", "PAR_INITREQDMA_ST",
+ "PAR_DRAWIDX_ST", "PAR_DRAW_ST", "PAR_2DRECT0_ST", "PAR_2DRECT1_ST",
+ "PAR_2DDATA0_ST", "PAR_2DDATA1_ST", "PAR_WAITFIFO_ST", "PAR_WAIT_ST",
+ "PAR_LINK_ST", "PAR_END_ST", "PAR_STALL_ST"
+ };
+
+ static gctCONST_STRING _cmdDmaState[] =
+ {
+ "CMD_IDLE_ST", "CMD_START_ST", "CMD_REQ_ST", "CMD_END_ST"
+ };
+
+ static gctCONST_STRING _cmdFetState[] =
+ {
+ "FET_IDLE_ST", "FET_RAMVALID_ST", "FET_VALID_ST"
+ };
+
+ static gctCONST_STRING _reqDmaState[] =
+ {
+ "REQ_IDLE_ST", "REQ_WAITIDX_ST", "REQ_CAL_ST"
+ };
+
+ static gctCONST_STRING _calState[] =
+ {
+ "CAL_IDLE_ST", "CAL_LDADR_ST", "CAL_IDXCALC_ST"
+ };
+
+ static gctCONST_STRING _veReqState[] =
+ {
+ "VER_IDLE_ST", "VER_CKCACHE_ST", "VER_MISS_ST"
+ };
+
+ static gcsiDEBUG_REGISTERS _dbgRegs[] =
+ {
+ { "RA", 0x474, 16, 0x448, 32, 0x12344321 },
+ { "TX", 0x474, 24, 0x44C, 32, 0x12211221 },
+ { "FE", 0x470, 0, 0x450, 32, 0xBABEF00D },
+ { "PE", 0x470, 16, 0x454, 48, 0xBABEF00D },
+ { "DE", 0x470, 8, 0x458, 32, 0xBABEF00D },
+ { "SH", 0x470, 24, 0x45C, 32, 0xDEADBEEF },
+ { "PA", 0x474, 0, 0x460, 32, 0x0000AAAA },
+ { "SE", 0x474, 8, 0x464, 32, 0x5E5E5E5E },
+ { "MC", 0x478, 0, 0x468, 32, 0x12345678 },
+ { "HI", 0x478, 8, 0x46C, 32, 0xAAAAAAAA }
+ };
+
+ static gctUINT32 _otherRegs[] =
+ {
+ 0x040, 0x044, 0x04C, 0x050, 0x054, 0x058, 0x05C, 0x060,
+ 0x43c, 0x440, 0x444, 0x414,
+ };
+
+ gceSTATUS status;
+ 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 = 0, pixelPipes = 0;
+ gctUINT32 control = 0, oldControl = 0;
+ gckOS os = Hardware->os;
+ gceCORE core = Hardware->core;
+
+ gcmkHEADER_ARG("Hardware=0x%X", Hardware);
+
+ kernel = Hardware->kernel;
+
+ gcmkPRINT_N(12, "GPU[%d](ChipModel=0x%x ChipRevision=0x%x):\n",
+ core,
+ Hardware->identity.chipModel,
+ Hardware->identity.chipRevision);
+
+ pixelPipes = Hardware->identity.pixelPipes
+ ? Hardware->identity.pixelPipes
+ : 1;
+
+ /* Reset register values. */
+ idle = axi =
+ dmaState1 = dmaState2 =
+ dmaAddress1 = dmaAddress2 =
+ dmaLow = dmaHigh = 0;
+
+ /* Verify whether DMA is running. */
+ gcmkONERROR(_VerifyDMA(
+ os, core, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
+ ));
+
+ cmdState = dmaState2 & 0x1F;
+ cmdDmaState = (dmaState2 >> 8) & 0x03;
+ cmdFetState = (dmaState2 >> 10) & 0x03;
+ dmaReqState = (dmaState2 >> 12) & 0x03;
+ calState = (dmaState2 >> 14) & 0x03;
+ veReqState = (dmaState2 >> 16) & 0x03;
+
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x004, &idle));
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x00C, &axi));
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x668, &dmaLow));
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x66C, &dmaHigh));
+
+ gcmkPRINT_N(0, "**************************\n");
+ gcmkPRINT_N(0, "*** GPU STATE DUMP ***\n");
+ gcmkPRINT_N(0, "**************************\n");
+
+ gcmkPRINT_N(4, " axi = 0x%08X\n", axi);
+
+ gcmkPRINT_N(4, " idle = 0x%08X\n", idle);
+ if ((idle & 0x00000001) == 0) gcmkPRINT_N(0, " FE not idle\n");
+ if ((idle & 0x00000002) == 0) gcmkPRINT_N(0, " DE not idle\n");
+ if ((idle & 0x00000004) == 0) gcmkPRINT_N(0, " PE not idle\n");
+ if ((idle & 0x00000008) == 0) gcmkPRINT_N(0, " SH not idle\n");
+ if ((idle & 0x00000010) == 0) gcmkPRINT_N(0, " PA not idle\n");
+ if ((idle & 0x00000020) == 0) gcmkPRINT_N(0, " SE not idle\n");
+ if ((idle & 0x00000040) == 0) gcmkPRINT_N(0, " RA not idle\n");
+ if ((idle & 0x00000080) == 0) gcmkPRINT_N(0, " TX not idle\n");
+ if ((idle & 0x00000100) == 0) gcmkPRINT_N(0, " VG not idle\n");
+ if ((idle & 0x00000200) == 0) gcmkPRINT_N(0, " IM not idle\n");
+ if ((idle & 0x00000400) == 0) gcmkPRINT_N(0, " FP not idle\n");
+ if ((idle & 0x00000800) == 0) gcmkPRINT_N(0, " TS not idle\n");
+ if ((idle & 0x80000000) != 0) gcmkPRINT_N(0, " AXI low power mode\n");
+
+ if (
+ (dmaAddress1 == dmaAddress2)
+ && (dmaState1 == dmaState2)
+ )
+ {
+ gcmkPRINT_N(0, " DMA appears to be stuck at this address:\n");
+ gcmkPRINT_N(4, " 0x%08X\n", dmaAddress1);
+ }
+ else
+ {
+ if (dmaAddress1 == dmaAddress2)
+ {
+ gcmkPRINT_N(0, " DMA address is constant, but state is changing:\n");
+ gcmkPRINT_N(4, " 0x%08X\n", dmaState1);
+ gcmkPRINT_N(4, " 0x%08X\n", dmaState2);
+ }
+ else
+ {
+ gcmkPRINT_N(0, " DMA is running; known addresses are:\n");
+ gcmkPRINT_N(4, " 0x%08X\n", dmaAddress1);
+ gcmkPRINT_N(4, " 0x%08X\n", dmaAddress2);
+ }
+ }
+
+ gcmkPRINT_N(4, " dmaLow = 0x%08X\n", dmaLow);
+ gcmkPRINT_N(4, " dmaHigh = 0x%08X\n", dmaHigh);
+ gcmkPRINT_N(4, " dmaState = 0x%08X\n", dmaState2);
+ gcmkPRINT_N(8, " command state = %d (%s)\n", cmdState, _cmdState [cmdState]);
+ gcmkPRINT_N(8, " command DMA state = %d (%s)\n", cmdDmaState, _cmdDmaState[cmdDmaState]);
+ gcmkPRINT_N(8, " command fetch state = %d (%s)\n", cmdFetState, _cmdFetState[cmdFetState]);
+ gcmkPRINT_N(8, " DMA request state = %d (%s)\n", dmaReqState, _reqDmaState[dmaReqState]);
+ gcmkPRINT_N(8, " cal state = %d (%s)\n", calState, _calState [calState]);
+ gcmkPRINT_N(8, " VE request state = %d (%s)\n", veReqState, _veReqState [veReqState]);
+
+ /* Record control. */
+ gckOS_ReadRegisterEx(os, core, 0x0, &oldControl);
+
+ for (pipe = 0; pipe < pixelPipes; pipe++)
+ {
+ gcmkPRINT_N(4, " Debug registers of pipe[%d]:\n", pipe);
+
+ /* Switch pipe. */
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x0, &control));
+ control &= ~(0xF << 20);
+ control |= (pipe << 20);
+ gcmkONERROR(gckOS_WriteRegisterEx(os, core, 0x0, control));
+
+ for (i = 0; i < gcmCOUNTOF(_dbgRegs); i += 1)
+ {
+ gcmkONERROR(_DumpDebugRegisters(os, core, &_dbgRegs[i]));
+ }
+
+ gcmkPRINT_N(0, " Other Registers:\n");
+ for (i = 0; i < gcmCOUNTOF(_otherRegs); i += 1)
+ {
+ gctUINT32 read;
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, _otherRegs[i], &read));
+ gcmkPRINT_N(12, " [0x%04X] 0x%08X\n", _otherRegs[i], read);
+ }
+
+ if (Hardware->mmuVersion)
+ {
+ gcmkPRINT(" MMU status from MC[%d]:", pipe);
+
+ gckHARDWARE_DumpMMUException(Hardware);
+ }
+ }
+
+ if (kernel->hardware->identity.chipFeatures & (1 << 4))
+ {
+ gctUINT32 read0, read1, write;
+
+ read0 = read1 = write = 0;
+
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x43C, &read0));
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x440, &read1));
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x444, &write));
+
+ gcmkPRINT_N(4, " read0 = 0x%08X\n", read0);
+ gcmkPRINT_N(4, " read1 = 0x%08X\n", read1);
+ gcmkPRINT_N(4, " write = 0x%08X\n", write);
+ }
+
+ /* Restore control. */
+ gcmkONERROR(gckOS_WriteRegisterEx(os, core, 0x0, oldControl));
+
+ gcmkPRINT_N(0, "**************************\n");
+ gcmkPRINT_N(0, "***** SW COUNTERS *****\n");
+ gcmkPRINT_N(0, "**************************\n");
+ gcmkPRINT_N(4, " Execute Count = 0x%08X\n", Hardware->executeCount);
+ gcmkPRINT_N(4, " Execute Addr = 0x%08X\n", Hardware->lastExecuteAddress);
+ gcmkPRINT_N(4, " End Addr = 0x%08X\n", Hardware->lastEnd);
+
+ /* dump stack. */
+ gckOS_DumpCallStack(os);
+
+OnError:
+
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+gckHARDWARE_ReadPerformanceRegister(
+ IN gckHARDWARE Hardware,
+ IN gctUINT PerformanceAddress,
+ IN gctUINT IndexAddress,
+ IN gctUINT IndexShift,
+ IN gctUINT Index,
+ OUT gctUINT32_PTR Value
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x PerformanceAddress=0x%x IndexAddress=0x%x "
+ "IndexShift=%u Index=%u",
+ Hardware, PerformanceAddress, IndexAddress, IndexShift,
+ Index);
+
+ /* Write the index. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ IndexAddress,
+ Index << IndexShift));
+
+ /* Read the register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ PerformanceAddress,
+ Value));
+
+ /* Test for reset. */
+ if (Index == 15)
+ {
+ /* Index another register to get out of reset. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, IndexAddress, 0));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=0x%x", *Value);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_GetFrameInfo(
+ IN gckHARDWARE Hardware,
+ OUT gcsHAL_FRAME_INFO * FrameInfo
+ )
+{
+ gceSTATUS status;
+ gctUINT i, clock;
+ gcsHAL_FRAME_INFO info;
+#if gcdFRAME_DB_RESET
+ gctUINT reset;
+#endif
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Get profile tick. */
+ gcmkONERROR(gckOS_GetProfileTick(&info.ticks));
+
+ /* Read SH counters and reset them. */
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0045C,
+ 0x00470,
+ 24,
+ 4,
+ &info.shaderCycles));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0045C,
+ 0x00470,
+ 24,
+ 9,
+ &info.vsInstructionCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0045C,
+ 0x00470,
+ 24,
+ 12,
+ &info.vsTextureCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0045C,
+ 0x00470,
+ 24,
+ 7,
+ &info.psInstructionCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0045C,
+ 0x00470,
+ 24,
+ 14,
+ &info.psTextureCount));
+#if gcdFRAME_DB_RESET
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0045C,
+ 0x00470,
+ 24,
+ 15,
+ &reset));
+#endif
+
+ /* Read PA counters and reset them. */
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 3,
+ &info.vertexCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 4,
+ &info.primitiveCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 7,
+ &info.rejectedPrimitives));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 8,
+ &info.culledPrimitives));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 6,
+ &info.clippedPrimitives));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 5,
+ &info.outPrimitives));
+#if gcdFRAME_DB_RESET
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 15,
+ &reset));
+#endif
+
+ /* Read RA counters and reset them. */
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00448,
+ 0x00474,
+ 16,
+ 3,
+ &info.inPrimitives));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00448,
+ 0x00474,
+ 16,
+ 11,
+ &info.culledQuadCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00448,
+ 0x00474,
+ 16,
+ 1,
+ &info.totalQuadCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00448,
+ 0x00474,
+ 16,
+ 2,
+ &info.quadCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00448,
+ 0x00474,
+ 16,
+ 0,
+ &info.totalPixelCount));
+#if gcdFRAME_DB_RESET
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00448,
+ 0x00474,
+ 16,
+ 15,
+ &reset));
+#endif
+
+ /* Read TX counters and reset them. */
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0044C,
+ 0x00474,
+ 24,
+ 0,
+ &info.bilinearRequests));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0044C,
+ 0x00474,
+ 24,
+ 1,
+ &info.trilinearRequests));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0044C,
+ 0x00474,
+ 24,
+ 8,
+ &info.txHitCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0044C,
+ 0x00474,
+ 24,
+ 9,
+ &info.txMissCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0044C,
+ 0x00474,
+ 24,
+ 6,
+ &info.txBytes8));
+#if gcdFRAME_DB_RESET
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0044C,
+ 0x00474,
+ 24,
+ 15,
+ &reset));
+#endif
+
+ /* Read clock control register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &clock));
+
+ /* Walk through all avaiable pixel pipes. */
+ for (i = 0; i < Hardware->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)))));
+
+ /* Read cycle registers. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ &info.cycles[i]));
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0007C,
+ &info.idleCycles[i]));
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00438,
+ &info.mcCycles[i]));
+
+ /* Read bandwidth registers. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0005C,
+ &info.readRequests[i]));
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00040,
+ &info.readBytes8[i]));
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00050,
+ &info.writeRequests[i]));
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00044,
+ &info.writeBytes8[i]));
+
+ /* Read PE counters. */
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00454,
+ 0x00470,
+ 16,
+ 0,
+ &info.colorKilled[i]));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00454,
+ 0x00470,
+ 16,
+ 2,
+ &info.colorDrawn[i]));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00454,
+ 0x00470,
+ 16,
+ 1,
+ &info.depthKilled[i]));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00454,
+ 0x00470,
+ 16,
+ 3,
+ &info.depthDrawn[i]));
+ }
+
+ /* Zero out remaning reserved counters. */
+ for (; i < 8; ++i)
+ {
+ info.readBytes8[i] = 0;
+ info.writeBytes8[i] = 0;
+ info.cycles[i] = 0;
+ info.idleCycles[i] = 0;
+ info.mcCycles[i] = 0;
+ info.readRequests[i] = 0;
+ info.writeRequests[i] = 0;
+ info.colorKilled[i] = 0;
+ info.colorDrawn[i] = 0;
+ info.depthKilled[i] = 0;
+ info.depthDrawn[i] = 0;
+ }
+
+ /* Reset clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ clock));
+
+ /* Reset cycle and bandwidth counters. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0003C,
+ 1));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0003C,
+ 0));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ 0));
+
+#if gcdFRAME_DB_RESET
+ /* Reset PE counters. */
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00454,
+ 0x00470,
+ 16,
+ 15,
+ &reset));
+#endif
+
+ /* Copy to user. */
+ gcmkONERROR(gckOS_CopyToUserData(Hardware->os,
+ &info,
+ FrameInfo,
+ gcmSIZEOF(info)));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdDVFS
+#define READ_FROM_EATER1 0
+
+gceSTATUS
+gckHARDWARE_QueryLoad(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32 * Load
+ )
+{
+ gctUINT32 debug1;
+ gceSTATUS status;
+ gcmkHEADER_ARG("Hardware=0x%X", Hardware);
+
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Load != gcvNULL);
+
+ gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE);
+
+ if (Hardware->chipPowerState == gcvPOWER_ON)
+ {
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00110,
+ Load));
+#if READ_FROM_EATER1
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00134,
+ Load));
+#endif
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00114,
+ &debug1));
+
+ /* Patch result of 0x110 with result of 0x114. */
+ if ((debug1 & 0xFF) == 1)
+ {
+ *Load &= ~0xFF;
+ *Load |= 1;
+ }
+
+ if (((debug1 & 0xFF00) >> 8) == 1)
+ {
+ *Load &= ~(0xFF << 8);
+ *Load |= 1 << 8;
+ }
+
+ if (((debug1 & 0xFF0000) >> 16) == 1)
+ {
+ *Load &= ~(0xFF << 16);
+ *Load |= 1 << 16;
+ }
+
+ if (((debug1 & 0xFF000000) >> 24) == 1)
+ {
+ *Load &= ~(0xFF << 24);
+ *Load |= 1 << 24;
+ }
+ }
+ else
+ {
+ status = gcvSTATUS_INVALID_REQUEST;
+ }
+
+OnError:
+
+ gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_SetDVFSPeroid(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32 Frequency
+ )
+{
+ gceSTATUS status;
+ gctUINT32 period;
+ gctUINT32 eater;
+
+#if READ_FROM_EATER1
+ gctUINT32 period1;
+ gctUINT32 eater1;
+#endif
+
+ gcmkHEADER_ARG("Hardware=0x%X Frequency=%d", Hardware, Frequency);
+
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ period = 0;
+
+ while((64 << period) < (gcdDVFS_ANAYLSE_WINDOW * Frequency * 1000) )
+ {
+ period++;
+ }
+
+#if READ_FROM_EATER1
+ /*
+ * Peroid = F * 1000 * 1000 / (60 * 16 * 1024);
+ */
+ period1 = Frequency * 6250 / 6114;
+#endif
+
+ gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE);
+
+ if (Hardware->chipPowerState == gcvPOWER_ON)
+ {
+ /* Get current configure. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0010C,
+ &eater));
+
+ /* Change peroid. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0010C,
+ ((((gctUINT32) (eater)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (period) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))));
+
+#if READ_FROM_EATER1
+ /* Config eater1. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00130,
+ &eater1));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00130,
+ ((((gctUINT32) (eater1)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:16) - (0 ? 31:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:16) - (0 ? 31:16) + 1))))))) << (0 ? 31:16))) | (((gctUINT32) ((gctUINT32) (period1) & ((gctUINT32) ((((1 ? 31:16) - (0 ? 31:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:16) - (0 ? 31:16) + 1))))))) << (0 ? 31:16)))));
+#endif
+ }
+ else
+ {
+ status = gcvSTATUS_INVALID_REQUEST;
+ }
+
+OnError:
+ gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_InitDVFS(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 data;
+
+ gcmkHEADER_ARG("Hardware=0x%X", Hardware);
+
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0010C,
+ &data));
+
+ 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)));
+ 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)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20)));
+ data = ((((gctUINT32) (data)) & ~(((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)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))) << (0 ? 22:22))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))) << (0 ? 22:22)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "DVFS Configure=0x%X",
+ data);
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0010C,
+ data));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+#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;
+ gctPHYS_ADDR_T physical;
+
+ 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,
+ &physical
+ ));
+
+ gcmkSAFECASTPHYSADDRT(Hardware->functionAddress, physical);
+
+ 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;
+
+ Hardware->functions[gcvHARDWARE_FUNCTION_MMU].endAddress =
+ Hardware->functions[gcvHARDWARE_FUNCTION_MMU].address + mmuBytes;
+
+ Hardware->functions[gcvHARDWARE_FUNCTION_MMU].endLogical =
+ logical + mmuBytes;
+ }
+
+ gcmkASSERT(offset < Hardware->functionBytes);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_AddressInHardwareFuncions(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gctPOINTER *Pointer
+ )
+{
+ if (Address >= Hardware->functionAddress && Address <= Hardware->functionAddress - 1 + Hardware->functionBytes)
+ {
+ *Pointer = (gctUINT8_PTR)Hardware->functionLogical
+ + (Address - Hardware->functionAddress)
+ ;
+
+ return gcvSTATUS_OK;
+ }
+
+ return gcvSTATUS_NOT_FOUND;
+}
+
+gceSTATUS
+gckHARDWARE_QueryStateTimer(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT64_PTR Start,
+ OUT gctUINT64_PTR End,
+ OUT gctUINT64_PTR On,
+ OUT gctUINT64_PTR Off,
+ OUT gctUINT64_PTR Idle,
+ OUT gctUINT64_PTR Suspend
+ )
+{
+ gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE);
+
+ gckSTATETIMER_Query(
+ &Hardware->powerStateTimer, Hardware->chipPowerState, Start, End, On, Off, Idle, Suspend);
+
+ gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
+
+ return gcvSTATUS_OK;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h
new file mode 100644
index 000000000000..3a5187058e7f
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h
@@ -0,0 +1,214 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_hardware_h_
+#define __gc_hal_kernel_hardware_h_
+
+#if gcdENABLE_VG
+#include "gc_hal_kernel_hardware_vg.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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;
+
+ /* Hardware address of END in this function. */
+ gctUINT32 endAddress;
+
+ /* Logical of END in this function. */
+ gctUINT8_PTR endLogical;
+}
+gcsHARDWARE_FUNCTION;
+
+typedef struct _gcsSTATETIMER
+{
+ gctUINT64 start;
+ gctUINT64 recent;
+
+ /* Elapse of each power state. */
+ gctUINT64 elapse[4];
+}
+gcsSTATETIMER;
+
+/* gckHARDWARE object. */
+struct _gckHARDWARE
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gctKERNEL object. */
+ gckKERNEL kernel;
+
+ /* Pointer to gctOS object. */
+ gckOS os;
+
+ /* Core */
+ gceCORE core;
+
+ /* Chip characteristics. */
+ gcsHAL_QUERY_CHIP_IDENTITY identity;
+ gctBOOL allowFastClear;
+ gctBOOL allowCompression;
+ gctUINT32 powerBaseAddress;
+ gctBOOL extraEventStates;
+
+ /* Big endian */
+ gctBOOL bigEndian;
+
+ /* Chip status */
+ gctPOINTER powerMutex;
+ gctUINT32 powerProcess;
+ gctUINT32 powerThread;
+ gceCHIPPOWERSTATE chipPowerState;
+ gctUINT32 lastWaitLink;
+ gctUINT32 lastEnd;
+ gctBOOL clockState;
+ gctBOOL powerState;
+ gctPOINTER globalSemaphore;
+
+ gctISRMANAGERFUNC startIsr;
+ gctISRMANAGERFUNC stopIsr;
+ gctPOINTER isrContext;
+
+ gctUINT32 mmuVersion;
+
+ /* Whether use new MMU. It is meaningless
+ ** for old MMU since old MMU is always enabled.
+ */
+ gctBOOL enableMMU;
+
+ /* Type */
+ gceHARDWARE_TYPE type;
+
+#if gcdPOWEROFF_TIMEOUT
+ gctUINT32 powerOffTime;
+ gctUINT32 powerOffTimeout;
+ gctPOINTER powerOffTimer;
+#endif
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ 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];
+
+ gcsSTATETIMER powerStateTimer;
+ gctUINT32 executeCount;
+ gctUINT32 lastExecuteAddress;
+};
+
+gceSTATUS
+gckHARDWARE_GetBaseAddress(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR BaseAddress
+ );
+
+gceSTATUS
+gckHARDWARE_NeedBaseAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 State,
+ OUT gctBOOL_PTR NeedBase
+ );
+
+gceSTATUS
+gckHARDWARE_GetFrameInfo(
+ IN gckHARDWARE Hardware,
+ OUT gcsHAL_FRAME_INFO * FrameInfo
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_hardware_h_ */
+
diff --git a/drivers/mxc/gpu-viv/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
index 000000000000..540d9e83b9b7
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_recorder.c
@@ -0,0 +1,713 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal.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 maxState;
+}
+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.maxState = context->maxState;
+
+ mapSize = context->maxState * 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.maxState)
+ {
+ /* 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);
+ }
+}
+
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.c b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.c
new file mode 100644
index 000000000000..c111f98c8442
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.c
@@ -0,0 +1,966 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+
+#if gcdENABLE_VG
+
+#include "gc_hal_kernel_hardware_command_vg.h"
+
+#define _GC_OBJ_ZONE gcvZONE_COMMAND
+
+/******************************************************************************\
+****************************** gckVGCOMMAND API code *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_InitializeInfo
+**
+** Initialize architecture dependent command buffer information.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to the Command object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVGCOMMAND_InitializeInfo(
+ IN gckVGCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ do
+ {
+ /* Reset interrupts. */
+ Command->info.feBufferInt = -1;
+ Command->info.tsOverflowInt = -1;
+
+ /* Set command buffer attributes. */
+ Command->info.addressAlignment = 64;
+ Command->info.commandAlignment = 8;
+
+ /* Determine command alignment address mask. */
+ Command->info.addressMask = ((((gctUINT32) (Command->info.addressAlignment - 1)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) ((gctUINT32) (0 ) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+
+ /* Query the number of bytes needed by the STATE command. */
+ gcmkERR_BREAK(gckVGCOMMAND_StateCommand(
+ Command, 0x0, gcvNULL, (gctUINT32)~0, 0,
+ &Command->info.stateCommandSize
+ ));
+
+ /* Query the number of bytes needed by the RESTART command. */
+ gcmkERR_BREAK(gckVGCOMMAND_RestartCommand(
+ Command, gcvNULL, (gctUINT32)~0, 0,
+ &Command->info.restartCommandSize
+ ));
+
+ /* Query the number of bytes needed by the FETCH command. */
+ gcmkERR_BREAK(gckVGCOMMAND_FetchCommand(
+ Command, gcvNULL, (gctUINT32)~0, 0,
+ &Command->info.fetchCommandSize
+ ));
+
+ /* Query the number of bytes needed by the CALL command. */
+ gcmkERR_BREAK(gckVGCOMMAND_CallCommand(
+ Command, gcvNULL, (gctUINT32)~0, 0,
+ &Command->info.callCommandSize
+ ));
+
+ /* Query the number of bytes needed by the RETURN command. */
+ gcmkERR_BREAK(gckVGCOMMAND_ReturnCommand(
+ Command, gcvNULL,
+ &Command->info.returnCommandSize
+ ));
+
+ /* Query the number of bytes needed by the EVENT command. */
+ gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
+ Command, gcvNULL, gcvBLOCK_PIXEL, -1,
+ &Command->info.eventCommandSize
+ ));
+
+ /* Query the number of bytes needed by the END command. */
+ gcmkERR_BREAK(gckVGCOMMAND_EndCommand(
+ Command, gcvNULL, -1,
+ &Command->info.endCommandSize
+ ));
+
+ /* Determine the tail reserve size. */
+ Command->info.staticTailSize = gcmMAX(
+ Command->info.fetchCommandSize,
+ gcmMAX(
+ Command->info.returnCommandSize,
+ Command->info.endCommandSize
+ )
+ );
+
+ /* Determine the maximum tail size. */
+ Command->info.dynamicTailSize
+ = Command->info.staticTailSize
+ + Command->info.eventCommandSize * gcvBLOCK_COUNT;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_StateCommand
+**
+** Append a STATE command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to an gckVGCOMMAND object.
+**
+** gctUINT32 Pipe
+** Harwdare destination pipe.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** STATE command at or gcvNULL to query the size of the command.
+**
+** gctUINT32 Address
+** Starting register address of the state buffer.
+** If 'Logical' is gcvNULL, this argument is ignored.
+**
+** gctUINT32 Count
+** Number of states in state buffer.
+** If 'Logical' is gcvNULL, this argument is ignored.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the STATE command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the STATE command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_StateCommand(
+ IN gckVGCOMMAND Command,
+ IN gctUINT32 Pipe,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Address,
+ IN 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",
+ Command, Pipe, Logical, Address, Count, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append STATE. */
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:0) - (0 ? 11:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ? 11:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 11:0) - (0 ? 11:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ? 11:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:16) - (0 ? 27:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:16) - (0 ? 27:16) + 1))))))) << (0 ? 27:16))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 27:16) - (0 ? 27:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:16) - (0 ? 27:16) + 1))))))) << (0 ? 27:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12))) | (((gctUINT32) ((gctUINT32) (Pipe) & ((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12)));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the STATE command. */
+ *Bytes = 4 * (Count + 1);
+ }
+ }
+ else
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append LOAD_STATE. */
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the STATE command. */
+ *Bytes = 4 * (Count + 1);
+ }
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_RestartCommand
+**
+** Form a RESTART command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to an gckVGCOMMAND object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** RESTART command at or gcvNULL to query the size of the command.
+**
+** gctUINT32 FetchAddress
+** The address of another command buffer to be executed by this RESTART
+** command. If 'Logical' is gcvNULL, this argument is ignored.
+**
+** gctUINT FetchCount
+** The number of 64-bit data quantities in another command buffer to
+** be executed by this RESTART command. If 'Logical' is gcvNULL, this
+** argument is ignored.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the RESTART command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the RESTART command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_RestartCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT FetchCount,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
+ Command, Logical, FetchAddress, FetchCount, Bytes);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+ gctUINT32 beginEndMark;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Determine Begin/End flag. */
+ beginEndMark = (FetchCount > 0)
+ ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24)))
+ : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24)));
+
+ /* Append RESTART. */
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x9 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0)))
+ | beginEndMark;
+
+ buffer[1]
+ = FetchAddress;
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the RESTART command. */
+ *Bytes = 8;
+ }
+ }
+ else
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_FetchCommand
+**
+** Form a FETCH command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to an gckVGCOMMAND object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** FETCH command at or gcvNULL to query the size of the command.
+**
+** gctUINT32 FetchAddress
+** The address of another command buffer to be executed by this FETCH
+** command. If 'Logical' is gcvNULL, this argument is ignored.
+**
+** gctUINT FetchCount
+** The number of 64-bit data quantities in another command buffer to
+** be executed by this FETCH command. If 'Logical' is gcvNULL, this
+** argument is ignored.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the FETCH command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the FETCH command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_FetchCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT FetchCount,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
+ Command, Logical, FetchAddress, FetchCount, Bytes);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append FETCH. */
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x5 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0)));
+
+ buffer[1]
+ = gcmkFIXADDRESS(FetchAddress);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the FETCH command. */
+ *Bytes = 8;
+ }
+ }
+ else
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append LINK. */
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ buffer[1]
+ = gcmkFIXADDRESS(FetchAddress);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the LINK command. */
+ *Bytes = 8;
+ }
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_CallCommand
+**
+** Append a CALL command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to an gckVGCOMMAND object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** CALL command at or gcvNULL to query the size of the command.
+**
+** gctUINT32 FetchAddress
+** The address of another command buffer to be executed by this CALL
+** command. If 'Logical' is gcvNULL, this argument is ignored.
+**
+** gctUINT FetchCount
+** The number of 64-bit data quantities in another command buffer to
+** be executed by this CALL command. If 'Logical' is gcvNULL, this
+** argument is ignored.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the CALL command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the CALL command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_CallCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT FetchCount,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
+ Command, Logical, FetchAddress, FetchCount, Bytes);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append CALL. */
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x6 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0)));
+
+ buffer[1]
+ = gcmkFIXADDRESS(FetchAddress);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the CALL command. */
+ *Bytes = 8;
+ }
+ }
+ else
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_ReturnCommand
+**
+** Append a RETURN command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to an gckVGCOMMAND object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** RETURN command at or gcvNULL to query the size of the command.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the RETURN command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the RETURN command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_ReturnCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Logical=0x%x Bytes = 0x%x",
+ Command, Logical, Bytes);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append RETURN. */
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x7 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the RETURN command. */
+ *Bytes = 8;
+ }
+ }
+ else
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_EventCommand
+**
+** Form an EVENT command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to the Command object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** EVENT command at or gcvNULL to query the size of the command.
+**
+** gctINT32 InterruptId
+** The ID of the interrupt to generate.
+** If 'Logical' is gcvNULL, this argument is ignored.
+**
+** gceBLOCK Block
+** Block that will generate the interrupt.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the EVENT command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the END command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_EventCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gceBLOCK Block,
+ IN gctINT32 InterruptId,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Logical=0x%x Block=0x%x InterruptId=0x%x Bytes = 0x%x",
+ Command, Logical, Block, InterruptId, Bytes);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ typedef struct _gcsEVENTSTATES
+ {
+ /* Chips before VG21 use these values. */
+ gctUINT eventFromFE;
+ gctUINT eventFromPE;
+
+ /* VG21 chips and later use SOURCE field. */
+ gctUINT eventSource;
+ }
+ gcsEVENTSTATES;
+
+ static gcsEVENTSTATES states[] =
+ {
+ /* gcvBLOCK_COMMAND */
+ {
+ (gctUINT)~0,
+ (gctUINT)~0,
+ (gctUINT)~0
+ },
+
+ /* gcvBLOCK_TESSELLATOR */
+ {
+ 0x0,
+ 0x1,
+ 0x10
+ },
+
+ /* gcvBLOCK_TESSELLATOR2 */
+ {
+ 0x0,
+ 0x1,
+ 0x12
+ },
+
+ /* gcvBLOCK_TESSELLATOR3 */
+ {
+ 0x0,
+ 0x1,
+ 0x14
+ },
+
+ /* gcvBLOCK_RASTER */
+ {
+ 0x0,
+ 0x1,
+ 0x07,
+ },
+
+ /* gcvBLOCK_VG */
+ {
+ 0x0,
+ 0x1,
+ 0x0F
+ },
+
+ /* gcvBLOCK_VG2 */
+ {
+ 0x0,
+ 0x1,
+ 0x11
+ },
+
+ /* gcvBLOCK_VG3 */
+ {
+ 0x0,
+ 0x1,
+ 0x13
+ },
+
+ /* gcvBLOCK_PIXEL */
+ {
+ 0x0,
+ 0x1,
+ 0x07
+ },
+ };
+
+ /* Verify block ID. */
+ gcmkVERIFY_ARGUMENT(gcmIS_VALID_INDEX(Block, states));
+
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Verify the event ID. */
+ gcmkVERIFY_ARGUMENT(InterruptId >= 0);
+ gcmkVERIFY_ARGUMENT(InterruptId <= ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))));
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append EVENT. */
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:0) - (0 ? 11:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ? 11:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 11:0) - (0 ? 11:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ? 11:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:16) - (0 ? 27:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:16) - (0 ? 27:16) + 1))))))) << (0 ? 27:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:16) - (0 ? 27:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:16) - (0 ? 27:16) + 1))))))) << (0 ? 27:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12)));
+
+ /* Determine chip version. */
+ if (Command->vg21)
+ {
+ /* Get the event source for the block. */
+ gctUINT eventSource = states[Block].eventSource;
+
+ /* Supported? */
+ if (eventSource == ~0)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ buffer[1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) ((gctUINT32) (eventSource) & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+ }
+ else
+ {
+ /* Get the event source for the block. */
+ gctUINT eventFromFE = states[Block].eventFromFE;
+ gctUINT eventFromPE = states[Block].eventFromPE;
+
+ /* Supported? */
+ if (eventFromFE == ~0)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ buffer[1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (eventFromFE) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) ((gctUINT32) (eventFromPE) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+ }
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Make sure the events are directly supported for the block. */
+ if (states[Block].eventSource == ~0)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ /* Return number of bytes required by the END command. */
+ *Bytes = 8;
+ }
+ }
+ else
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Verify the event ID. */
+ gcmkVERIFY_ARGUMENT(InterruptId >= 0);
+ gcmkVERIFY_ARGUMENT(InterruptId <= ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))));
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append EVENT. */
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ /* Determine event source. */
+ if (Block == gcvBLOCK_COMMAND)
+ {
+ buffer[1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+ }
+ else
+ {
+ buffer[1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+ }
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the EVENT and END commands. */
+ *Bytes = 8;
+ }
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_EndCommand
+**
+** Form an END command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to the Command object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** END command at or gcvNULL to query the size of the command.
+**
+** gctINT32 InterruptId
+** The ID of the interrupt to generate.
+** If 'Logical' is gcvNULL, this argument will be ignored.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the END command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the END command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_EndCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctINT32 InterruptId,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Logical=0x%x InterruptId=0x%x Bytes = 0x%x",
+ Command, Logical, InterruptId, Bytes);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Verify the event ID. */
+ gcmkVERIFY_ARGUMENT(InterruptId >= 0);
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append END. */
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the END command. */
+ *Bytes = 8;
+ }
+ }
+ else
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR memory;
+
+ /* Verify the event ID. */
+ gcmkVERIFY_ARGUMENT(InterruptId >= 0);
+
+ /* Cast the buffer pointer. */
+ memory = (gctUINT32_PTR) Logical;
+
+ /* Append EVENT. */
+ memory[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ memory[1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+
+ /* Append END. */
+ memory[2]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the EVENT and END commands. */
+ *Bytes = 16;
+ }
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+#endif /* gcdENABLE_VG */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.h b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.h
new file mode 100644
index 000000000000..8f1185584340
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.h
@@ -0,0 +1,353 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_hardware_command_vg_h_
+#define __gc_hal_kernel_hardware_command_vg_h_
+
+/******************************************************************************\
+******************* Task and Interrupt Management Structures. ******************
+\******************************************************************************/
+
+/* Task storage header. */
+typedef struct _gcsTASK_STORAGE * gcsTASK_STORAGE_PTR;
+typedef struct _gcsTASK_STORAGE
+{
+ /* Next allocated storage buffer. */
+ gcsTASK_STORAGE_PTR next;
+}
+gcsTASK_STORAGE;
+
+/* Task container header. */
+typedef struct _gcsTASK_CONTAINER * gcsTASK_CONTAINER_PTR;
+typedef struct _gcsTASK_CONTAINER
+{
+ /* The number of tasks left to be processed in the container. */
+ gctINT referenceCount;
+
+ /* Size of the buffer. */
+ gctUINT size;
+
+ /* Link to the previous and the next allocated containers. */
+ gcsTASK_CONTAINER_PTR allocPrev;
+ gcsTASK_CONTAINER_PTR allocNext;
+
+ /* Link to the previous and the next containers in the free list. */
+ gcsTASK_CONTAINER_PTR freePrev;
+ gcsTASK_CONTAINER_PTR freeNext;
+}
+gcsTASK_CONTAINER;
+
+/* Kernel space task master table entry. */
+typedef struct _gcsBLOCK_TASK_ENTRY * gcsBLOCK_TASK_ENTRY_PTR;
+typedef struct _gcsBLOCK_TASK_ENTRY
+{
+ /* Pointer to the current task container for the block. */
+ gcsTASK_CONTAINER_PTR container;
+
+ /* Pointer to the current task data within the container. */
+ gcsTASK_HEADER_PTR task;
+
+ /* Pointer to the last link task within the container. */
+ gcsTASK_LINK_PTR link;
+
+ /* Number of interrupts allocated for this block. */
+ gctUINT interruptCount;
+
+ /* The index of the current interrupt. */
+ gctUINT interruptIndex;
+
+ /* Interrupt semaphore. */
+ gctSEMAPHORE interruptSemaphore;
+
+ /* Interrupt value array. */
+ gctINT32 interruptArray[32];
+}
+gcsBLOCK_TASK_ENTRY;
+
+
+/******************************************************************************\
+********************* Command Queue Management Structures. *********************
+\******************************************************************************/
+
+/* Command queue kernel element pointer. */
+typedef struct _gcsKERNEL_CMDQUEUE * gcsKERNEL_CMDQUEUE_PTR;
+
+/* Command queue object handler function type. */
+typedef gceSTATUS (* gctOBJECT_HANDLER) (
+ gckVGKERNEL Kernel,
+ gcsKERNEL_CMDQUEUE_PTR Entry
+ );
+
+/* Command queue kernel element. */
+typedef struct _gcsKERNEL_CMDQUEUE
+{
+ /* The number of buffers in the queue. */
+ gcsCMDBUFFER_PTR commandBuffer;
+
+ /* Pointer to the object handler function. */
+ gctOBJECT_HANDLER handler;
+}
+gcsKERNEL_CMDQUEUE;
+
+/* Command queue header. */
+typedef struct _gcsKERNEL_QUEUE_HEADER * gcsKERNEL_QUEUE_HEADER_PTR;
+typedef struct _gcsKERNEL_QUEUE_HEADER
+{
+ /* The size of the buffer in bytes. */
+ gctUINT size;
+
+ /* The number of pending entries to be processed. */
+ volatile gctUINT pending;
+
+ /* The current command queue entry. */
+ gcsKERNEL_CMDQUEUE_PTR currentEntry;
+
+ /* Next buffer. */
+ gcsKERNEL_QUEUE_HEADER_PTR next;
+}
+gcsKERNEL_QUEUE_HEADER;
+
+
+/******************************************************************************\
+******************************* gckVGCOMMAND Object *******************************
+\******************************************************************************/
+
+/* gckVGCOMMAND object. */
+struct _gckVGCOMMAND
+{
+ /***************************************************************************
+ ** Object data and pointers.
+ */
+
+ gcsOBJECT object;
+ gckVGKERNEL kernel;
+ gckOS os;
+ gckVGHARDWARE hardware;
+
+ /* Features. */
+ gctBOOL fe20;
+ gctBOOL vg20;
+ gctBOOL vg21;
+
+
+ /***************************************************************************
+ ** Enable command queue dumping.
+ */
+
+ gctBOOL enableDumping;
+
+
+ /***************************************************************************
+ ** Bus Error interrupt.
+ */
+
+ gctINT32 busErrorInt;
+
+
+ /***************************************************************************
+ ** Command buffer information.
+ */
+
+ gcsCOMMAND_BUFFER_INFO info;
+
+
+ /***************************************************************************
+ ** Synchronization objects.
+ */
+
+ gctPOINTER queueMutex;
+ gctPOINTER taskMutex;
+ gctPOINTER commitMutex;
+
+
+ /***************************************************************************
+ ** Task management.
+ */
+
+ /* The head of the storage buffer linked list. */
+ gcsTASK_STORAGE_PTR taskStorage;
+
+ /* Allocation size. */
+ gctUINT taskStorageGranularity;
+ gctUINT taskStorageUsable;
+
+ /* The free container list. */
+ gcsTASK_CONTAINER_PTR taskFreeHead;
+ gcsTASK_CONTAINER_PTR taskFreeTail;
+
+ /* Task table */
+ gcsBLOCK_TASK_ENTRY taskTable[gcvBLOCK_COUNT];
+
+
+ /***************************************************************************
+ ** Command queue.
+ */
+
+ /* Pointer to the allocated queue memory. */
+ gcsKERNEL_QUEUE_HEADER_PTR queue;
+
+ /* Pointer to the current available queue from which new queue entries
+ will be allocated. */
+ gcsKERNEL_QUEUE_HEADER_PTR queueHead;
+
+ /* If different from queueHead, points to the command queue which is
+ currently being executed by the hardware. */
+ gcsKERNEL_QUEUE_HEADER_PTR queueTail;
+
+ /* Points to the queue to merge the tail with when the tail is processed. */
+ gcsKERNEL_QUEUE_HEADER_PTR mergeQueue;
+
+ /* Queue overflow counter. */
+ gctUINT queueOverflow;
+
+
+ /***************************************************************************
+ ** Context.
+ */
+
+ /* Context counter used for unique ID. */
+ gctUINT64 contextCounter;
+
+ /* Current context ID. */
+ gctUINT64 currentContext;
+
+ /* Command queue power semaphore. */
+ gctPOINTER powerSemaphore;
+ gctINT32 powerStallInt;
+ gcsCMDBUFFER_PTR powerStallBuffer;
+ gctSIGNAL powerStallSignal;
+
+};
+
+/******************************************************************************\
+************************ gckVGCOMMAND Object Internal API. ***********************
+\******************************************************************************/
+
+/* Initialize architecture dependent command buffer information. */
+gceSTATUS
+gckVGCOMMAND_InitializeInfo(
+ IN gckVGCOMMAND Command
+ );
+
+/* Form a STATE command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_StateCommand(
+ IN gckVGCOMMAND Command,
+ IN gctUINT32 Pipe,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Address,
+ IN gctUINT32 Count,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Form a RESTART command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_RestartCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT FetchCount,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Form a FETCH command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_FetchCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT FetchCount,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Form a CALL command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_CallCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT FetchCount,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Form a RETURN command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_ReturnCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Form an EVENT command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_EventCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gceBLOCK Block,
+ IN gctINT32 InterruptId,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Form an END command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_EndCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctINT32 InterruptId,
+ IN OUT gctUINT32 * Bytes
+ );
+
+#endif /* __gc_hal_kernel_hardware_command_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.c b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.c
new file mode 100644
index 000000000000..d50c471c2ec5
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.c
@@ -0,0 +1,2256 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_hardware_command_vg.h"
+
+#if gcdENABLE_VG
+
+#define _GC_OBJ_ZONE gcvZONE_HARDWARE
+
+typedef enum
+{
+ gcvPOWER_FLAG_INITIALIZE = 1 << 0,
+ gcvPOWER_FLAG_STALL = 1 << 1,
+ gcvPOWER_FLAG_STOP = 1 << 2,
+ gcvPOWER_FLAG_START = 1 << 3,
+ gcvPOWER_FLAG_RELEASE = 1 << 4,
+ gcvPOWER_FLAG_DELAY = 1 << 5,
+ gcvPOWER_FLAG_SAVE = 1 << 6,
+ gcvPOWER_FLAG_ACQUIRE = 1 << 7,
+ gcvPOWER_FLAG_POWER_OFF = 1 << 8,
+ gcvPOWER_FLAG_CLOCK_OFF = 1 << 9,
+ gcvPOWER_FLAG_CLOCK_ON = 1 << 10,
+ gcvPOWER_FLAG_NOP = 1 << 11,
+}
+gcePOWER_FLAGS;
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+static gceSTATUS
+_ResetGPU(
+ IN gckOS Os
+ )
+{
+ gctUINT32 control, idle;
+ gceSTATUS status;
+
+ /* Read register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00000,
+ &control));
+
+ for (;;)
+ {
+ /* Disable clock gating. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00104,
+ 0x00000000));
+
+ /* Wait for clock being stable. */
+ gcmkONERROR(gckOS_Delay(Os, 1));
+
+ /* Isolate the GPU. */
+ control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00000,
+ control));
+
+ /* Set soft reset. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
+
+ /* Wait for reset. */
+ gcmkONERROR(gckOS_Delay(Os, 1));
+
+ /* Reset soft reset bit. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
+
+ /* Reset GPU isolation. */
+ control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00000,
+ control));
+
+ /* Read idle register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00004,
+ &idle));
+
+ if ((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) == 0)
+ {
+ continue;
+ }
+
+ /* Read reset register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00000,
+ &control));
+
+ if (((((((gctUINT32) (control)) >> (0 ? 16:16)) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) ) == 0)
+ || ((((((gctUINT32) (control)) >> (0 ? 17:17)) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1)))))) ) == 0)
+ )
+ {
+ continue;
+ }
+
+ /* GPU is idle. */
+ break;
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Return the error. */
+ return status;
+}
+
+
+static gceSTATUS
+_IdentifyHardware(
+ IN gckOS Os,
+ OUT gceCHIPMODEL * ChipModel,
+ OUT gctUINT32 * ChipRevision,
+ OUT gctUINT32 * ChipFeatures,
+ OUT gctUINT32 * ChipMinorFeatures,
+ OUT gctUINT32 * ChipMinorFeatures2
+ )
+{
+ gceSTATUS status;
+ gctUINT32 chipIdentity;
+
+ do
+ {
+ /* Read chip identity register. */
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG, 0x00018, &chipIdentity));
+
+ /* Special case for older graphic cores. */
+ if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
+ {
+ *ChipModel = gcv500;
+ *ChipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
+ }
+
+ else
+ {
+ /* Read chip identity register. */
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
+ 0x00020,
+ (gctUINT32 *) ChipModel));
+
+ /* Read CHIP_REV register. */
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
+ 0x00024,
+ ChipRevision));
+ }
+
+ /* Read chip feature register. */
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(
+ Os, gcvCORE_VG, 0x0001C, ChipFeatures
+ ));
+
+ /* Read chip minor feature register. */
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(
+ Os, gcvCORE_VG, 0x00034, ChipMinorFeatures
+ ));
+
+ /* Read chip minor feature register #2. */
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(
+ Os, gcvCORE_VG, 0x00074, ChipMinorFeatures2
+ ));
+
+ gcmkTRACE(
+ gcvLEVEL_VERBOSE,
+ "ChipModel=0x%08X\n"
+ "ChipRevision=0x%08X\n"
+ "ChipFeatures=0x%08X\n"
+ "ChipMinorFeatures=0x%08X\n"
+ "ChipMinorFeatures2=0x%08X\n",
+ *ChipModel,
+ *ChipRevision,
+ *ChipFeatures,
+ *ChipMinorFeatures,
+ *ChipMinorFeatures2
+ );
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Return the status. */
+ return status;
+}
+
+#if gcdPOWEROFF_TIMEOUT
+void
+_VGPowerTimerFunction(
+ gctPOINTER Data
+ )
+{
+ gckVGHARDWARE hardware = (gckVGHARDWARE)Data;
+ gcmkVERIFY_OK(
+ gckVGHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF_TIMEOUT));
+}
+#endif
+
+/******************************************************************************\
+****************************** gckVGHARDWARE API code *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_Construct
+**
+** Construct a new gckVGHARDWARE object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an initialized gckOS object.
+**
+** OUTPUT:
+**
+** gckVGHARDWARE * Hardware
+** Pointer to a variable that will hold the pointer to the gckVGHARDWARE
+** object.
+*/
+gceSTATUS
+gckVGHARDWARE_Construct(
+ IN gckOS Os,
+ OUT gckVGHARDWARE * Hardware
+ )
+{
+ gckVGHARDWARE hardware = gcvNULL;
+ gceSTATUS status;
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 chipFeatures;
+ gctUINT32 chipMinorFeatures;
+ gctUINT32 chipMinorFeatures2;
+
+ gcmkHEADER_ARG("Os=0x%x Hardware=0x%x ", Os, Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
+
+ do
+ {
+ gcmkERR_BREAK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvTRUE, gcvTRUE));
+
+ status = _ResetGPU(Os);
+
+ if (status != gcvSTATUS_OK)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "_ResetGPU failed: status=%d\n", status);
+ }
+
+ /* Identify the hardware. */
+ gcmkERR_BREAK(_IdentifyHardware(Os,
+ &chipModel, &chipRevision,
+ &chipFeatures, &chipMinorFeatures, &chipMinorFeatures2
+ ));
+
+ /* Allocate the gckVGHARDWARE object. */
+ gcmkERR_BREAK(gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckVGHARDWARE), (gctPOINTER *) &hardware
+ ));
+
+ /* Initialize the gckVGHARDWARE object. */
+ hardware->object.type = gcvOBJ_HARDWARE;
+ hardware->os = Os;
+
+ /* Set chip identity. */
+ hardware->chipModel = chipModel;
+ hardware->chipRevision = chipRevision;
+ hardware->chipFeatures = chipFeatures;
+ hardware->chipMinorFeatures = chipMinorFeatures;
+ hardware->chipMinorFeatures2 = chipMinorFeatures2;
+
+ hardware->powerMutex = gcvNULL;
+ hardware->chipPowerState = gcvPOWER_ON;
+ hardware->chipPowerStateGlobal = gcvPOWER_ON;
+ hardware->clockState = gcvTRUE;
+ hardware->powerState = gcvTRUE;
+
+#if gcdPOWEROFF_TIMEOUT
+ hardware->powerOffTime = 0;
+ hardware->powerOffTimeout = gcdPOWEROFF_TIMEOUT;
+
+ gcmkVERIFY_OK(gckOS_CreateTimer(Os,
+ _VGPowerTimerFunction,
+ (gctPOINTER)hardware,
+ &hardware->powerOffTimer));
+#endif
+
+ /* Determine whether FE 2.0 is present. */
+ hardware->fe20 = ((((gctUINT32) (hardware->chipFeatures)) >> (0 ? 28:28) & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))));
+
+ /* Determine whether VG 2.0 is present. */
+ hardware->vg20 = ((((gctUINT32) (hardware->chipMinorFeatures)) >> (0 ? 13:13) & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1)))))));
+
+ /* Determine whether VG 2.1 is present. */
+ hardware->vg21 = ((((gctUINT32) (hardware->chipMinorFeatures)) >> (0 ? 18:18) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))));
+
+ /* Set default event mask. */
+ hardware->eventMask = 0xFFFFFFFF;
+
+ gcmkERR_BREAK(gckOS_AtomConstruct(Os, &hardware->pageTableDirty));
+
+ /* Set fast clear to auto. */
+ gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(hardware, -1));
+
+ gcmkERR_BREAK(gckOS_CreateMutex(Os, &hardware->powerMutex));
+
+ /* Enable power management by default. */
+ hardware->powerManagement = gcvTRUE;
+
+ /* Return pointer to the gckVGHARDWARE object. */
+ *Hardware = hardware;
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+#if gcdPOWEROFF_TIMEOUT
+ if (hardware->powerOffTimer != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
+ }
+#endif
+
+ gcmkVERIFY_OK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvFALSE, gcvFALSE));
+
+ if (hardware != gcvNULL && hardware->pageTableDirty != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
+ }
+
+ if (hardware != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_Free(Os, hardware));
+ }
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_Destroy
+**
+** Destroy an gckVGHARDWARE object.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to the gckVGHARDWARE object that needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVGHARDWARE_Destroy(
+ IN gckVGHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Mark the object as unknown. */
+ Hardware->object.type = gcvOBJ_UNKNOWN;
+
+ if (Hardware->powerMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(
+ Hardware->os, Hardware->powerMutex));
+ }
+
+#if gcdPOWEROFF_TIMEOUT
+ gcmkVERIFY_OK(gckOS_StopTimer(Hardware->os, Hardware->powerOffTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Hardware->os, Hardware->powerOffTimer));
+#endif
+
+ if (Hardware->pageTableDirty != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pageTableDirty));
+ }
+
+ /* Free the object. */
+ status = gckOS_Free(Hardware->os, Hardware);
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_QueryMemory
+**
+** Query the amount of memory available on the hardware.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to the gckVGHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * InternalSize
+** Pointer to a variable that will hold the size of the internal video
+** memory in bytes. If 'InternalSize' is gcvNULL, no information of the
+** internal memory will be returned.
+**
+** gctUINT32 * InternalBaseAddress
+** Pointer to a variable that will hold the hardware's base address for
+** the internal video memory. This pointer cannot be gcvNULL if
+** 'InternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * InternalAlignment
+** Pointer to a variable that will hold the hardware's base address for
+** the internal video memory. This pointer cannot be gcvNULL if
+** 'InternalSize' is also non-gcvNULL.
+**
+** gctSIZE_T * ExternalSize
+** Pointer to a variable that will hold the size of the external video
+** memory in bytes. If 'ExternalSize' is gcvNULL, no information of the
+** external memory will be returned.
+**
+** gctUINT32 * ExternalBaseAddress
+** Pointer to a variable that will hold the hardware's base address for
+** the external video memory. This pointer cannot be gcvNULL if
+** 'ExternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * ExternalAlignment
+** Pointer to a variable that will hold the hardware's base address for
+** the external video memory. This pointer cannot be gcvNULL if
+** 'ExternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * HorizontalTileSize
+** Number of horizontal pixels per tile. If 'HorizontalTileSize' is
+** gcvNULL, no horizontal pixel per tile will be returned.
+**
+** gctUINT32 * VerticalTileSize
+** Number of vertical pixels per tile. If 'VerticalTileSize' is
+** gcvNULL, no vertical pixel per tile will be returned.
+*/
+gceSTATUS
+gckVGHARDWARE_QueryMemory(
+ IN gckVGHARDWARE Hardware,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctUINT32 * InternalBaseAddress,
+ OUT gctUINT32 * InternalAlignment,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctUINT32 * ExternalBaseAddress,
+ OUT gctUINT32 * ExternalAlignment,
+ OUT gctUINT32 * HorizontalTileSize,
+ OUT gctUINT32 * VerticalTileSize
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x InternalSize=0x%x InternalBaseAddress=0x%x InternalAlignment=0x%x"
+ "ExternalSize=0x%x ExternalBaseAddress=0x%x ExternalAlignment=0x%x HorizontalTileSize=0x%x VerticalTileSize=0x%x",
+ Hardware, InternalSize, InternalBaseAddress, InternalAlignment,
+ ExternalSize, ExternalBaseAddress, ExternalAlignment, HorizontalTileSize, VerticalTileSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (InternalSize != gcvNULL)
+ {
+ /* No internal memory. */
+ *InternalSize = 0;
+ }
+
+ if (ExternalSize != gcvNULL)
+ {
+ /* No external memory. */
+ *ExternalSize = 0;
+ }
+
+ if (HorizontalTileSize != gcvNULL)
+ {
+ /* 4x4 tiles. */
+ *HorizontalTileSize = 4;
+ }
+
+ if (VerticalTileSize != gcvNULL)
+ {
+ /* 4x4 tiles. */
+ *VerticalTileSize = 4;
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_QueryChipIdentity
+**
+** Query the identity of the hardware.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to the gckVGHARDWARE object.
+**
+** OUTPUT:
+**
+** gceCHIPMODEL * ChipModel
+** If 'ChipModel' is not gcvNULL, the variable it points to will
+** receive the model of the chip.
+**
+** gctUINT32 * ChipRevision
+** If 'ChipRevision' is not gcvNULL, the variable it points to will
+** receive the revision of the chip.
+**
+** gctUINT32 * ChipFeatures
+** If 'ChipFeatures' is not gcvNULL, the variable it points to will
+** receive the feature set of the chip.
+**
+** gctUINT32 * ChipMinorFeatures
+** If 'ChipMinorFeatures' is not gcvNULL, the variable it points to
+** will receive the minor feature set of the chip.
+**
+** gctUINT32 * ChipMinorFeatures2
+** If 'ChipMinorFeatures2' is not gcvNULL, the variable it points to
+** will receive the minor feature set of the chip.
+**
+*/
+gceSTATUS
+gckVGHARDWARE_QueryChipIdentity(
+ IN gckVGHARDWARE Hardware,
+ OUT gceCHIPMODEL * ChipModel,
+ OUT gctUINT32 * ChipRevision,
+ OUT gctUINT32* ChipFeatures,
+ OUT gctUINT32* ChipMinorFeatures,
+ OUT gctUINT32* ChipMinorFeatures2
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x ChipModel=0x%x ChipRevision=0x%x ChipFeatures = 0x%x ChipMinorFeatures = 0x%x ChipMinorFeatures2 = 0x%x",
+ Hardware, ChipModel, ChipRevision, ChipFeatures, ChipMinorFeatures, ChipMinorFeatures2);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Return chip model. */
+ if (ChipModel != gcvNULL)
+ {
+ *ChipModel = Hardware->chipModel;
+ }
+
+ /* Return revision number. */
+ if (ChipRevision != gcvNULL)
+ {
+ *ChipRevision = Hardware->chipRevision;
+ }
+
+ /* Return feature set. */
+ if (ChipFeatures != gcvNULL)
+ {
+ gctUINT32 features = Hardware->chipFeatures;
+
+ if ((((((gctUINT32) (features)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+ {
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (Hardware->allowFastClear) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+ }
+
+ /* Mark 2D pipe as available for GC500.0 since it did not have this *\
+ \* bit. */
+ if ((Hardware->chipModel == gcv500)
+ && (Hardware->chipRevision == 0)
+ )
+ {
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
+ }
+
+ /* Mark 2D pipe as available for GC300 since it did not have this *\
+ \* bit. */
+ if (Hardware->chipModel == gcv300)
+ {
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
+ }
+
+ *ChipFeatures = features;
+ }
+
+ /* Return minor feature set. */
+ if (ChipMinorFeatures != gcvNULL)
+ {
+ *ChipMinorFeatures = Hardware->chipMinorFeatures;
+ }
+
+ /* Return minor feature set #2. */
+ if (ChipMinorFeatures2 != gcvNULL)
+ {
+ *ChipMinorFeatures2 = Hardware->chipMinorFeatures2;
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_ConvertFormat
+**
+** Convert an API format to hardware parameters.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to the gckVGHARDWARE object.
+**
+** gceSURF_FORMAT Format
+** API format to convert.
+**
+** OUTPUT:
+**
+** gctUINT32 * BitsPerPixel
+** Pointer to a variable that will hold the number of bits per pixel.
+**
+** gctUINT32 * BytesPerTile
+** Pointer to a variable that will hold the number of bytes per tile.
+*/
+gceSTATUS
+gckVGHARDWARE_ConvertFormat(
+ IN gckVGHARDWARE Hardware,
+ IN gceSURF_FORMAT Format,
+ OUT gctUINT32 * BitsPerPixel,
+ OUT gctUINT32 * BytesPerTile
+ )
+{
+ gctUINT32 bitsPerPixel;
+ gctUINT32 bytesPerTile;
+
+ gcmkHEADER_ARG("Hardware=0x%x Format=0x%x BitsPerPixel=0x%x BytesPerTile = 0x%x",
+ Hardware, Format, BitsPerPixel, BytesPerTile);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Dispatch on format. */
+ switch (Format)
+ {
+ case gcvSURF_A1:
+ case gcvSURF_L1:
+ /* 1-bpp format. */
+ bitsPerPixel = 1;
+ bytesPerTile = (1 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_A4:
+ /* 4-bpp format. */
+ bitsPerPixel = 4;
+ bytesPerTile = (4 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_INDEX8:
+ case gcvSURF_A8:
+ case gcvSURF_L8:
+ /* 8-bpp format. */
+ bitsPerPixel = 8;
+ bytesPerTile = (8 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_YV12:
+ /* 12-bpp planar YUV formats. */
+ bitsPerPixel = 12;
+ bytesPerTile = (12 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_NV12:
+ /* 12-bpp planar YUV formats. */
+ bitsPerPixel = 12;
+ bytesPerTile = (12 * 4 * 4) / 8;
+ break;
+
+ /* 4444 variations. */
+ case gcvSURF_X4R4G4B4:
+ case gcvSURF_A4R4G4B4:
+ case gcvSURF_R4G4B4X4:
+ case gcvSURF_R4G4B4A4:
+ case gcvSURF_B4G4R4X4:
+ case gcvSURF_B4G4R4A4:
+ case gcvSURF_X4B4G4R4:
+ case gcvSURF_A4B4G4R4:
+
+ /* 1555 variations. */
+ case gcvSURF_X1R5G5B5:
+ case gcvSURF_A1R5G5B5:
+ case gcvSURF_R5G5B5X1:
+ case gcvSURF_R5G5B5A1:
+ case gcvSURF_X1B5G5R5:
+ case gcvSURF_A1B5G5R5:
+ case gcvSURF_B5G5R5X1:
+ case gcvSURF_B5G5R5A1:
+
+ /* 565 variations. */
+ case gcvSURF_R5G6B5:
+ case gcvSURF_B5G6R5:
+
+ case gcvSURF_A8L8:
+ case gcvSURF_YUY2:
+ case gcvSURF_UYVY:
+ case gcvSURF_D16:
+ /* 16-bpp format. */
+ bitsPerPixel = 16;
+ bytesPerTile = (16 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_X8R8G8B8:
+ case gcvSURF_A8R8G8B8:
+ case gcvSURF_X8B8G8R8:
+ case gcvSURF_A8B8G8R8:
+ case gcvSURF_R8G8B8X8:
+ case gcvSURF_R8G8B8A8:
+ case gcvSURF_B8G8R8X8:
+ case gcvSURF_B8G8R8A8:
+ case gcvSURF_D32:
+ /* 32-bpp format. */
+ bitsPerPixel = 32;
+ bytesPerTile = (32 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_D24S8:
+ /* 24-bpp format. */
+ bitsPerPixel = 32;
+ bytesPerTile = (32 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_DXT1:
+ case gcvSURF_ETC1:
+ bitsPerPixel = 4;
+ bytesPerTile = (4 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_DXT2:
+ case gcvSURF_DXT3:
+ case gcvSURF_DXT4:
+ case gcvSURF_DXT5:
+ bitsPerPixel = 8;
+ bytesPerTile = (8 * 4 * 4) / 8;
+ break;
+
+ default:
+ /* Invalid format. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Set the result. */
+ if (BitsPerPixel != gcvNULL)
+ {
+ * BitsPerPixel = bitsPerPixel;
+ }
+
+ if (BytesPerTile != gcvNULL)
+ {
+ * BytesPerTile = bytesPerTile;
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_SplitMemory
+**
+** Split a hardware specific memory address into a pool and offset.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to the gckVGHARDWARE object.
+**
+** gctUINT32 Address
+** Address in hardware specific format.
+**
+** OUTPUT:
+**
+** gcePOOL * Pool
+** Pointer to a variable that will hold the pool type for the address.
+**
+** gctUINT32 * Offset
+** Pointer to a variable that will hold the offset for the address.
+*/
+gceSTATUS
+gckVGHARDWARE_SplitMemory(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Pool=0x%x Offset = 0x%x",
+ Hardware, Address, Pool, Offset);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
+
+ /* Dispatch on memory type. */
+ switch ((((((gctUINT32) (Address)) >> (0 ? 1:0)) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1)))))) ))
+ {
+ case 0x0:
+ /* System memory. */
+ *Pool = gcvPOOL_SYSTEM;
+ break;
+
+ case 0x2:
+ /* Virtual memory. */
+ *Pool = gcvPOOL_VIRTUAL;
+ break;
+
+ default:
+ /* Invalid memory type. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Return offset of address. */
+ *Offset = ((((gctUINT32) (Address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_Execute
+**
+** Kickstart the hardware's command processor with an initialized command
+** buffer.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to the gckVGHARDWARE object.
+**
+** gctUINT32 Address
+** Address of the command buffer.
+**
+** gctSIZE_T Count
+** Number of command-sized data units to be executed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVGHARDWARE_Execute(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Address,
+ IN gctUINT32 Count
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Count=0x%x",
+ Hardware, Address, Count);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ do
+ {
+ /* Enable all events. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(
+ Hardware->os,
+ gcvCORE_VG,
+ 0x00014,
+ Hardware->eventMask
+ ));
+
+ if (Hardware->fe20)
+ {
+ /* Write address register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(
+ Hardware->os,
+ gcvCORE_VG,
+ 0x00500,
+ gcmkFIXADDRESS(Address)
+ ));
+
+ /* Write control register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(
+ Hardware->os,
+ gcvCORE_VG,
+ 0x00504,
+ Count
+ ));
+ }
+ else
+ {
+ /* Write address register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(
+ Hardware->os,
+ gcvCORE_VG,
+ 0x00654,
+ gcmkFIXADDRESS(Address)
+ ));
+
+ /* Write control register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(
+ Hardware->os,
+ gcvCORE_VG,
+ 0x00658,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ ));
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_AlignToTile
+**
+** Align the specified width and height to tile boundaries.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to an gckVGHARDWARE object.
+**
+** gceSURF_TYPE Type
+** Type of alignment.
+**
+** gctUINT32 * Width
+** Pointer to the width to be aligned. If 'Width' is gcvNULL, no width
+** will be aligned.
+**
+** gctUINT32 * Height
+** Pointer to the height to be aligned. If 'Height' is gcvNULL, no height
+** will be aligned.
+**
+** OUTPUT:
+**
+** gctUINT32 * Width
+** Pointer to a variable that will receive the aligned width.
+**
+** gctUINT32 * Height
+** Pointer to a variable that will receive the aligned height.
+*/
+gceSTATUS
+gckVGHARDWARE_AlignToTile(
+ IN gckVGHARDWARE Hardware,
+ IN gceSURF_TYPE Type,
+ IN OUT gctUINT32 * Width,
+ IN OUT gctUINT32 * Height
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Type=0x%x Width=0x%x Height=0x%x",
+ Hardware, Type, Width, Height);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (Width != gcvNULL)
+ {
+ /* Align the width. */
+ *Width = gcmALIGN(*Width, (Type == gcvSURF_TEXTURE) ? 4 : 16);
+ }
+
+ if (Height != gcvNULL)
+ {
+ /* Special case for VG images. */
+ if ((*Height == 0) && (Type == gcvSURF_IMAGE))
+ {
+ *Height = 4;
+ }
+ else
+ {
+ /* Align the height. */
+ *Height = gcmALIGN(*Height, 4);
+ }
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_ConvertLogical
+**
+** Convert a logical system address into a hardware specific address.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to an gckVGHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address to convert.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the memory in user space.
+**
+** gctUINT32* Address
+** Return hardware specific address.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVGHARDWARE_ConvertLogical(
+ IN gckVGHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctBOOL InUserSpace,
+ OUT gctUINT32 * Address
+ )
+{
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address;
+ gceSTATUS status;
+
+ 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);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ do
+ {
+ /* Convert logical address into a physical address. */
+ if (InUserSpace)
+ {
+ gcmkERR_BREAK(gckOS_UserLogicalToPhysical(
+ Hardware->os, Logical, &physical
+ ));
+ }
+ else
+ {
+ gcmkERR_BREAK(gckOS_GetPhysicalAddress(
+ Hardware->os, Logical, &physical
+ ));
+ }
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ /* Return hardware specific address. */
+ *Address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_QuerySystemMemory
+**
+** Query the command buffer alignment and number of reserved bytes.
+**
+** INPUT:
+**
+** gckVGHARDWARE Harwdare
+** Pointer to an gckVGHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * SystemSize
+** Pointer to a variable that receives the maximum size of the system
+** memory.
+**
+** gctUINT32 * SystemBaseAddress
+** Poinetr to a variable that receives the base address for system
+** memory.
+*/
+gceSTATUS gckVGHARDWARE_QuerySystemMemory(
+ IN gckVGHARDWARE Hardware,
+ OUT gctSIZE_T * SystemSize,
+ OUT gctUINT32 * SystemBaseAddress
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x SystemSize=0x%x SystemBaseAddress=0x%x",
+ Hardware, SystemSize, SystemBaseAddress);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (SystemSize != gcvNULL)
+ {
+ /* Maximum system memory can be 2GB. */
+ *SystemSize = (gctSIZE_T)(1 << 31);
+ }
+
+ if (SystemBaseAddress != gcvNULL)
+ {
+ /* Set system memory base address. */
+ *SystemBaseAddress = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_SetMMU
+**
+** Set the page table base address.
+**
+** INPUT:
+**
+** gckVGHARDWARE Harwdare
+** Pointer to an gckVGHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address of the page table.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckVGHARDWARE_SetMMU(
+ IN gckVGHARDWARE Hardware,
+ IN gctPOINTER Logical
+ )
+{
+ gceSTATUS status;
+ gctUINT32 address = 0;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x",
+ Hardware, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ do
+ {
+ /* Convert the logical address into an hardware address. */
+ gcmkERR_BREAK(gckVGHARDWARE_ConvertLogical(Hardware, Logical,
+ gcvFALSE, &address));
+
+ /* Write the AQMemoryFePageTable register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00400,
+ gcmkFIXADDRESS(address)));
+
+ /* Write the AQMemoryTxPageTable register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00404,
+ gcmkFIXADDRESS(address)));
+
+ /* Write the AQMemoryPePageTable register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00408,
+ gcmkFIXADDRESS(address)));
+
+ /* Write the AQMemoryPezPageTable register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x0040C,
+ gcmkFIXADDRESS(address)));
+
+ /* Write the AQMemoryRaPageTable register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00410,
+ gcmkFIXADDRESS(address)));
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_FlushMMU
+**
+** Flush the page table.
+**
+** INPUT:
+**
+** gckVGHARDWARE Harwdare
+** Pointer to an gckVGHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckVGHARDWARE_FlushMMU(
+ IN gckVGHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gckVGCOMMAND command;
+
+ gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ do
+ {
+ gcsCMDBUFFER_PTR commandBuffer;
+ gctUINT32_PTR buffer;
+
+ /* Create a shortcut to the command buffer object. */
+ command = Hardware->kernel->command;
+
+ /* Allocate command buffer space. */
+ gcmkERR_BREAK(gckVGCOMMAND_Allocate(
+ command, 8, &commandBuffer, (gctPOINTER *) &buffer
+ ));
+
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E04) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ buffer[1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+
+ gcmkERR_BREAK(gckVGCOMMAND_Execute(
+ command,
+ commandBuffer
+ ));
+ }
+ while(gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_BuildVirtualAddress
+**
+** Build a virtual address.
+**
+** INPUT:
+**
+** gckVGHARDWARE Harwdare
+** Pointer to an gckVGHARDWARE object.
+**
+** gctUINT32 Index
+** Index into page table.
+**
+** gctUINT32 Offset
+** Offset into page.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Pointer to a variable receiving te hardware address.
+*/
+gceSTATUS gckVGHARDWARE_BuildVirtualAddress(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Index,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ )
+{
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Hardware=0x%x Index=0x%x Offset=0x%x Address=0x%x",
+ Hardware, Index, Offset, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Build virtual address. */
+ address = (Index << 12) | Offset;
+
+ /* Set virtual type. */
+ address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+
+ /* Set the result. */
+ *Address = address;
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVGHARDWARE_GetIdle(
+ IN gckVGHARDWARE Hardware,
+ OUT gctUINT32 * Data
+ )
+{
+ gceSTATUS status;
+ gcmkHEADER_ARG("Hardware=0x%x Data=0x%x", Hardware, Data);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+ /* Read register and return. */
+ status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, Data);
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckVGHARDWARE_SetFastClear(
+ IN gckVGHARDWARE Hardware,
+ IN gctINT Enable
+ )
+{
+ gctUINT32 debug;
+ gceSTATUS status;
+
+ if (!(((((gctUINT32) (Hardware->chipFeatures)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+ {
+ return gcvSTATUS_OK;
+ }
+
+ do
+ {
+ if (Enable == -1)
+ {
+ Enable = (Hardware->chipModel > gcv500) ||
+ ((Hardware->chipModel == gcv500) && (Hardware->chipRevision >= 3));
+ }
+
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00414,
+ &debug));
+
+ debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20)));
+
+#ifdef AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION
+ debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1) == 32) ? ~0 : (~(~0 << ((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1))))))) << (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1) == 32) ? ~0 : (~(~0 << ((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1))))))) << (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION)));
+#endif
+
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00414,
+ debug));
+
+ Hardware->allowFastClear = Enable;
+
+ status = gcvFALSE;
+ }
+ while (gcvFALSE);
+
+ return status;
+}
+
+gceSTATUS
+gckVGHARDWARE_ReadInterrupt(
+ IN gckVGHARDWARE Hardware,
+ OUT gctUINT32_PTR IDs
+ )
+{
+ gceSTATUS status;
+ gcmkHEADER_ARG("Hardware=0x%x IDs=0x%x", Hardware, IDs);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(IDs != gcvNULL);
+
+ /* Read AQIntrAcknowledge register. */
+ status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00010,
+ IDs);
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS _CommandStall(
+ gckVGHARDWARE Hardware)
+{
+ gceSTATUS status;
+ gckVGCOMMAND command;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ do
+ {
+ gctUINT32_PTR buffer;
+ command = Hardware->kernel->command;
+
+ /* Allocate command buffer space. */
+ gcmkERR_BREAK(gckVGCOMMAND_Allocate(
+ command, 8, &command->powerStallBuffer,
+ (gctPOINTER *) &buffer
+ ));
+
+ gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
+ command, buffer, gcvBLOCK_PIXEL,
+ command->powerStallInt, gcvNULL));
+
+ gcmkERR_BREAK(gckVGCOMMAND_Execute(
+ command,
+ command->powerStallBuffer
+ ));
+
+ /* Wait the signal. */
+ gcmkERR_BREAK(gckOS_WaitSignal(
+ command->os,
+ command->powerStallSignal,
+ command->kernel->kernel->timeOut));
+
+
+ }
+ while(gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+static gceSTATUS
+_IsGPUPresent(
+ IN gckVGHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRev, chipFeatures, chipMinorFeatures, chipMinorFeatures2;
+ /*gcsHAL_QUERY_CHIP_IDENTITY identity;*/
+ gctUINT32 control;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ gcvCORE_VG,
+ 0x00000,
+ &control));
+
+ control = ((((gctUINT32) (control)) & ~(((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)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ gcvCORE_VG,
+ 0x00000,
+ control));
+
+ /* Identify the hardware. */
+ gcmkONERROR(_IdentifyHardware(Hardware->os,
+ &chipModel, &chipRev,
+ &chipFeatures,
+ &chipMinorFeatures,
+ &chipMinorFeatures2
+ ));
+ /* Check if these are the same values as saved before. */
+ if ((Hardware->chipModel != chipModel)
+ || (Hardware->chipRevision != chipRev)
+ || (Hardware->chipFeatures != chipFeatures)
+ || (Hardware->chipMinorFeatures != chipMinorFeatures)
+ || (Hardware->chipMinorFeatures2 != chipMinorFeatures2)
+ )
+ {
+ gcmkPRINT("[galcore]: GPU is not present.");
+ gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetPowerManagementState
+**
+** Set GPU to a specified power state.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gceCHIPPOWERSTATE State
+** Power State.
+**
+*/
+gceSTATUS
+gckVGHARDWARE_SetPowerManagementState(
+ IN gckVGHARDWARE Hardware,
+ IN gceCHIPPOWERSTATE State
+ )
+{
+ gceSTATUS status;
+ gckVGCOMMAND command = gcvNULL;
+ gckOS os;
+ gctUINT flag/*, clock*/;
+
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL stall = gcvTRUE;
+ gctBOOL commitMutex = gcvFALSE;
+ gctBOOL mutexAcquired = gcvFALSE;
+
+#if gcdPOWEROFF_TIMEOUT
+ gctBOOL timeout = gcvFALSE;
+ gctBOOL isAfter = gcvFALSE;
+ gctUINT32 currentTime;
+#endif
+
+ gctBOOL broadcast = gcvFALSE;
+ gctUINT32 process, thread;
+ gctBOOL global = gcvFALSE;
+
+#if gcdENABLE_PROFILING
+ gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
+ initTime, offTime, startTime, totalTime;
+#endif
+
+ /* State transition flags. */
+ static const gctUINT flags[4][4] =
+ {
+ /* gcvPOWER_ON */
+ { /* ON */ 0,
+ /* OFF */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_POWER_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ gcvPOWER_FLAG_NOP,
+ /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_OFF */
+ { /* ON */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY,
+ /* OFF */ 0,
+ /* IDLE */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY,
+ /* SUSPEND */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_IDLE */
+ { /* ON */ gcvPOWER_FLAG_NOP,
+ /* OFF */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_POWER_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ 0,
+ /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_SUSPEND */
+ { /* ON */ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY |
+ gcvPOWER_FLAG_CLOCK_ON,
+ /* OFF */ gcvPOWER_FLAG_SAVE |
+ gcvPOWER_FLAG_POWER_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_DELAY |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_CLOCK_ON,
+ /* SUSPEND */ 0,
+ },
+ };
+
+ gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Switching to power state %d",
+ State);
+#endif
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Get the gckOS object pointer. */
+ os = Hardware->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Get the gckCOMMAND object pointer. */
+ gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
+ command = Hardware->kernel->command;
+ gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
+ if (Hardware->powerManagement == gcvFALSE)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Start profiler. */
+ gcmkPROFILE_INIT(freq, time);
+
+ /* Convert the broadcast power state. */
+ switch (State)
+ {
+ case gcvPOWER_SUSPEND_ATPOWERON:
+ /* Convert to SUSPEND and don't wait for STALL. */
+ State = gcvPOWER_SUSPEND;
+ stall = gcvFALSE;
+ break;
+
+ case gcvPOWER_OFF_ATPOWERON:
+ /* Convert to OFF and don't wait for STALL. */
+ State = gcvPOWER_OFF;
+ stall = gcvFALSE;
+ break;
+
+ case gcvPOWER_IDLE_BROADCAST:
+ /* Convert to IDLE and note we are inside broadcast. */
+ State = gcvPOWER_IDLE;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_SUSPEND_BROADCAST:
+ /* Convert to SUSPEND and note we are inside broadcast. */
+ State = gcvPOWER_SUSPEND;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_OFF_BROADCAST:
+ /* Convert to OFF and note we are inside broadcast. */
+ State = gcvPOWER_OFF;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_OFF_RECOVERY:
+ /* Convert to OFF and note we are inside recovery. */
+ State = gcvPOWER_OFF;
+ stall = gcvFALSE;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_ON_AUTO:
+ /* Convert to ON and note we are inside recovery. */
+ State = gcvPOWER_ON;
+ break;
+
+ case gcvPOWER_ON:
+ case gcvPOWER_IDLE:
+ case gcvPOWER_SUSPEND:
+ case gcvPOWER_OFF:
+ /* Mark as global power management. */
+ global = gcvTRUE;
+ break;
+
+#if gcdPOWEROFF_TIMEOUT
+ case gcvPOWER_OFF_TIMEOUT:
+ /* Convert to OFF and note we are inside broadcast. */
+ State = gcvPOWER_OFF;
+ broadcast = gcvTRUE;
+ /* Check time out */
+ timeout = gcvTRUE;
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ /* Get current process and thread IDs. */
+ gcmkONERROR(gckOS_GetProcessID(&process));
+ gcmkONERROR(gckOS_GetThreadID(&thread));
+
+ /* Acquire the power mutex. */
+ if (broadcast)
+ {
+ /* Try to acquire the power mutex. */
+ status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
+
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ /* Check if we already own this mutex. */
+ if ((Hardware->powerProcess == process)
+ && (Hardware->powerThread == thread)
+ )
+ {
+ /* Bail out on recursive power management. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ else if (State == gcvPOWER_IDLE)
+ {
+ /* gcvPOWER_IDLE_BROADCAST is from IST,
+ ** so waiting here will cause deadlock,
+ ** if lock holder call gckCOMMAND_Stall() */
+ gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+ }
+ else
+ {
+ /* Acquire the power mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os,
+ Hardware->powerMutex,
+ gcvINFINITE));
+ }
+ }
+ }
+ else
+ {
+ /* Acquire the power mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
+ }
+
+ /* Get time until mtuex acquired. */
+ gcmkPROFILE_QUERY(time, mutexTime);
+
+ Hardware->powerProcess = process;
+ Hardware->powerThread = thread;
+ mutexAcquired = gcvTRUE;
+
+ /* Grab control flags and clock. */
+ flag = flags[Hardware->chipPowerState][State];
+ /*clock = clocks[State];*/
+
+#if gcdPOWEROFF_TIMEOUT
+ if (timeout)
+ {
+ gcmkONERROR(gckOS_GetTicks(&currentTime));
+
+ gcmkONERROR(
+ gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
+
+ /* powerOffTime is pushed forward, give up.*/
+ if (isAfter
+ /* Expect a transition start from IDLE. */
+ || (Hardware->chipPowerState == gcvPOWER_ON)
+ || (Hardware->chipPowerState == gcvPOWER_OFF)
+ )
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ }
+#endif
+
+ if (flag == 0)
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* internal power control */
+ if (!global)
+ {
+ if (Hardware->chipPowerStateGlobal == gcvPOWER_OFF)
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ }
+ else
+ {
+ if (flag & gcvPOWER_FLAG_ACQUIRE)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+ acquired = gcvTRUE;
+
+ /* avoid acquiring again. */
+ flag &= ~gcvPOWER_FLAG_ACQUIRE;
+ }
+ }
+
+ if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
+ {
+ /* Turn on the power. */
+ gcmkONERROR(gckOS_SetGPUPower(os, gcvCORE_VG, gcvTRUE, gcvTRUE));
+
+ /* Mark clock and power as enabled. */
+ Hardware->clockState = gcvTRUE;
+ Hardware->powerState = gcvTRUE;
+ }
+
+ for (;;)
+ {
+ /* Check if GPU is present and awake. */
+ status = _IsGPUPresent(Hardware);
+
+ /* Check if the GPU is not responding. */
+ if (status == gcvSTATUS_GPU_NOT_RESPONDING)
+ {
+ /* Turn off the power and clock. */
+ gcmkONERROR(gckOS_SetGPUPower(os, gcvCORE_VG, gcvFALSE, gcvFALSE));
+
+ Hardware->clockState = gcvFALSE;
+ Hardware->powerState = gcvFALSE;
+
+ /* Wait a little. */
+ gckOS_Delay(os, 1);
+
+ /* Turn on the power and clock. */
+ gcmkONERROR(gckOS_SetGPUPower(os, gcvCORE_VG, gcvTRUE, gcvTRUE));
+
+ Hardware->clockState = gcvTRUE;
+ Hardware->powerState = gcvTRUE;
+
+ /* We need to initialize the hardware and start the command
+ * processor. */
+ flag |= gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_START;
+ }
+ else
+ {
+ /* Test for error. */
+ gcmkONERROR(status);
+
+ /* Break out of loop. */
+ break;
+ }
+ }
+
+
+ /* Get time until powered on. */
+ gcmkPROFILE_QUERY(time, onTime);
+
+ if ((flag & gcvPOWER_FLAG_STALL) && stall)
+ {
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ command->os,
+ command->commitMutex,
+ gcvINFINITE
+ ));
+
+ commitMutex = gcvTRUE;
+
+ gcmkONERROR(_CommandStall(Hardware));
+ }
+
+ /* Get time until stalled. */
+ gcmkPROFILE_QUERY(time, stallTime);
+
+ if (flag & gcvPOWER_FLAG_ACQUIRE)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+
+ acquired = gcvTRUE;
+ }
+
+
+ /* Get time until stopped. */
+ gcmkPROFILE_QUERY(time, stopTime);
+
+
+ if (flag & gcvPOWER_FLAG_DELAY)
+ {
+ /* Wait for the specified amount of time to settle coming back from
+ ** power-off or suspend state. */
+ gcmkONERROR(gckOS_Delay(os, gcdPOWER_CONTROL_DELAY));
+ }
+
+ /* Get time until delayed. */
+ gcmkPROFILE_QUERY(time, delayTime);
+
+ if (flag & gcvPOWER_FLAG_INITIALIZE)
+ {
+
+ /* Initialize 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;
+ }
+
+ /* Get time until initialized. */
+ gcmkPROFILE_QUERY(time, initTime);
+
+ if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
+ {
+ /* Turn off the GPU power. */
+ gcmkONERROR(
+ gckOS_SetGPUPower(os,
+ gcvCORE_VG,
+ (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
+ : gcvTRUE,
+ (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
+ : gcvTRUE));
+
+ /* Save current hardware power and clock states. */
+ Hardware->clockState = (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
+ : gcvTRUE;
+ Hardware->powerState = (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
+ : gcvTRUE;
+ }
+
+ /* Get time until off. */
+ gcmkPROFILE_QUERY(time, offTime);
+
+
+ /* Get time until started. */
+ gcmkPROFILE_QUERY(time, startTime);
+
+ if (flag & gcvPOWER_FLAG_RELEASE)
+ {
+ /* Release the power management semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
+ acquired = gcvFALSE;
+ }
+
+ /* Save the new power state. */
+ Hardware->chipPowerState = State;
+
+ if (global)
+ {
+ /* Save the new power state. */
+ Hardware->chipPowerStateGlobal = State;
+ }
+
+ if (commitMutex)
+ {
+ /* Acquire the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(
+ command->os,
+ command->commitMutex
+ ));
+ }
+
+#if gcdPOWEROFF_TIMEOUT
+ /* Reset power off time */
+ gcmkONERROR(gckOS_GetTicks(&currentTime));
+
+ Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
+
+ if (State == gcvPOWER_IDLE)
+ {
+ /* Start a timer to power off GPU when GPU enters IDLE or SUSPEND. */
+ gcmkVERIFY_OK(gckOS_StartTimer(os,
+ Hardware->powerOffTimer,
+ Hardware->powerOffTimeout));
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "Cancel powerOfftimer");
+
+ /* Cancel running timer when GPU enters ON or OFF. */
+ gcmkVERIFY_OK(gckOS_StopTimer(os, Hardware->powerOffTimer));
+ }
+#endif
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* Get total time. */
+ gcmkPROFILE_QUERY(time, totalTime);
+#if gcdENABLE_PROFILING
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "PROF(%llu): mutex:%llu on:%llu stall:%llu stop:%llu",
+ freq, mutexTime, onTime, stallTime, stopTime);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ " delay:%llu init:%llu off:%llu start:%llu total:%llu",
+ delayTime, initTime, offTime, startTime, totalTime);
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+
+ if (acquired)
+ {
+ /* Release semaphore. */
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
+ command->powerSemaphore));
+ }
+
+ if (mutexAcquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+ }
+
+ if (commitMutex)
+ {
+ /* Acquire the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(
+ command->os,
+ command->commitMutex
+ ));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryPowerManagementState
+**
+** Get GPU power state.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gceCHIPPOWERSTATE* State
+** Power State.
+**
+*/
+gceSTATUS
+gckVGHARDWARE_QueryPowerManagementState(
+ IN gckVGHARDWARE Hardware,
+ OUT gceCHIPPOWERSTATE* State
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(State != gcvNULL);
+
+ /* Return the statue. */
+ *State = Hardware->chipPowerState;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*State=%d", *State);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_SetPowerManagement
+**
+** Configure GPU power management function.
+** Only used in driver initialization stage.
+**
+** INPUT:
+**
+** gckVGHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctBOOL PowerManagement
+** Power Mangement State.
+**
+*/
+gceSTATUS
+gckVGHARDWARE_SetPowerManagement(
+ IN gckVGHARDWARE Hardware,
+ IN gctBOOL PowerManagement
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ Hardware->powerManagement = PowerManagement;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#if gcdPOWEROFF_TIMEOUT
+gceSTATUS
+gckVGHARDWARE_SetPowerOffTimeout(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Timeout
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Timeout=%d", Hardware, Timeout);
+
+ Hardware->powerOffTimeout = Timeout;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+
+gceSTATUS
+gckVGHARDWARE_QueryPowerOffTimeout(
+ IN gckVGHARDWARE Hardware,
+ OUT gctUINT32* Timeout
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ *Timeout = Hardware->powerOffTimeout;
+
+ gcmkFOOTER_ARG("*Timeout=%d", *Timeout);
+ return gcvSTATUS_OK;
+}
+#endif
+
+gceSTATUS
+gckVGHARDWARE_QueryIdle(
+ IN gckVGHARDWARE Hardware,
+ OUT gctBOOL_PTR IsIdle
+ )
+{
+ gceSTATUS status;
+ gctUINT32 idle;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
+
+ /* We are idle when the power is not ON. */
+ if (Hardware->chipPowerState != gcvPOWER_ON)
+ {
+ *IsIdle = gcvTRUE;
+ }
+
+ else
+ {
+ /* Read idle register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, &idle));
+
+ /* Pipe must be 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)))))) ) != 1)
+ || ((((((gctUINT32) (idle)) >> (0 ? 8:8)) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) ) != 1)
+ || ((((((gctUINT32) (idle)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) ) != 1)
+ || ((((((gctUINT32) (idle)) >> (0 ? 10:10)) & ((gctUINT32) ((((1 ? 10:10) - (0 ? 10:10) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 10:10) - (0 ? 10:10) + 1)))))) ) != 1)
+ || ((((((gctUINT32) (idle)) >> (0 ? 11:11)) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1)))))) ) != 1)
+ )
+ {
+ /* Something is busy. */
+ *IsIdle = gcvFALSE;
+ }
+
+ else
+ {
+ *IsIdle = gcvTRUE;
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif /* gcdENABLE_VG */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.h b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.h
new file mode 100644
index 000000000000..1ab69db22b1d
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_hardware_vg_h_
+#define __gc_hal_kernel_hardware_vg_h_
+
+/* gckHARDWARE object. */
+struct _gckVGHARDWARE
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckKERNEL object. */
+ gckVGKERNEL kernel;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Chip characteristics. */
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 chipFeatures;
+ gctUINT32 chipMinorFeatures;
+ gctUINT32 chipMinorFeatures2;
+ gctBOOL allowFastClear;
+
+ /* Features. */
+ gctBOOL fe20;
+ gctBOOL vg20;
+ gctBOOL vg21;
+
+ /* Event mask. */
+ gctUINT32 eventMask;
+
+ gctBOOL clockState;
+ gctBOOL powerState;
+ gctPOINTER powerMutex;
+ gctUINT32 powerProcess;
+ gctUINT32 powerThread;
+ gceCHIPPOWERSTATE chipPowerState;
+ gceCHIPPOWERSTATE chipPowerStateGlobal;
+ gctISRMANAGERFUNC startIsr;
+ gctISRMANAGERFUNC stopIsr;
+ gctPOINTER isrContext;
+ gctPOINTER pageTableDirty;
+#if gcdPOWEROFF_TIMEOUT
+ gctUINT32 powerOffTime;
+ gctUINT32 powerOffTimeout;
+ gctPOINTER powerOffTimer;
+#endif
+
+ gctBOOL powerManagement;
+};
+
+#endif /* __gc_hal_kernel_hardware_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
new file mode 100644
index 000000000000..9fbfbf1d6847
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
@@ -0,0 +1,5256 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdENABLE_DEC_COMPRESSION && gcdDEC_ENABLE_AHB
+#include "viv_dec300_main.h"
+#endif
+
+#define _GC_OBJ_ZONE gcvZONE_KERNEL
+
+/*******************************************************************************
+***** Version Signature *******************************************************/
+
+#define _gcmTXT2STR(t) #t
+#define gcmTXT2STR(t) _gcmTXT2STR(t)
+const char * _VERSION = "\n\0$VERSION$"
+ gcmTXT2STR(gcvVERSION_MAJOR) "."
+ gcmTXT2STR(gcvVERSION_MINOR) "."
+ gcmTXT2STR(gcvVERSION_PATCH) ":"
+ gcmTXT2STR(gcvVERSION_BUILD) "$\n";
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+#define gcmDEFINE2TEXT(d) #d
+gctCONST_STRING _DispatchText[] =
+{
+ gcmDEFINE2TEXT(gcvHAL_QUERY_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_QUERY_CHIP_IDENTITY),
+ gcmDEFINE2TEXT(gcvHAL_ALLOCATE_NON_PAGED_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_FREE_NON_PAGED_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_FREE_CONTIGUOUS_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_ALLOCATE_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_RELEASE_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_MAP_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_UNMAP_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_MAP_USER_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_UNMAP_USER_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_LOCK_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_UNLOCK_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_EVENT_COMMIT),
+ gcmDEFINE2TEXT(gcvHAL_USER_SIGNAL),
+ gcmDEFINE2TEXT(gcvHAL_SIGNAL),
+ gcmDEFINE2TEXT(gcvHAL_WRITE_DATA),
+ gcmDEFINE2TEXT(gcvHAL_COMMIT),
+ gcmDEFINE2TEXT(gcvHAL_STALL),
+ gcmDEFINE2TEXT(gcvHAL_READ_REGISTER),
+ gcmDEFINE2TEXT(gcvHAL_WRITE_REGISTER),
+ gcmDEFINE2TEXT(gcvHAL_GET_PROFILE_SETTING),
+ gcmDEFINE2TEXT(gcvHAL_SET_PROFILE_SETTING),
+ gcmDEFINE2TEXT(gcvHAL_READ_ALL_PROFILE_REGISTERS),
+ gcmDEFINE2TEXT(gcvHAL_PROFILE_REGISTERS_2D),
+#if VIVANTE_PROFILER_PERDRAW
+ gcvHAL_READ_PROFILER_REGISTER_SETTING,
+#endif
+ gcmDEFINE2TEXT(gcvHAL_SET_POWER_MANAGEMENT_STATE),
+ gcmDEFINE2TEXT(gcvHAL_QUERY_POWER_MANAGEMENT_STATE),
+ gcmDEFINE2TEXT(gcvHAL_GET_BASE_ADDRESS),
+ gcmDEFINE2TEXT(gcvHAL_SET_IDLE),
+ gcmDEFINE2TEXT(gcvHAL_QUERY_KERNEL_SETTINGS),
+ gcmDEFINE2TEXT(gcvHAL_RESET),
+ gcmDEFINE2TEXT(gcvHAL_MAP_PHYSICAL),
+ gcmDEFINE2TEXT(gcvHAL_DEBUG),
+ gcmDEFINE2TEXT(gcvHAL_CACHE),
+ gcmDEFINE2TEXT(gcvHAL_TIMESTAMP),
+ gcmDEFINE2TEXT(gcvHAL_DATABASE),
+ gcmDEFINE2TEXT(gcvHAL_VERSION),
+ gcmDEFINE2TEXT(gcvHAL_CHIP_INFO),
+ gcmDEFINE2TEXT(gcvHAL_ATTACH),
+ 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 gcdGPU_TIMEOUT && gcdINTERRUPT_STATISTIC
+void
+_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
+ && kernel->hardware->chipPowerState == gcvPOWER_ON
+ )
+ {
+ /* 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");
+
+ 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));
+
+ 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
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Construct
+**
+** Construct a new gckKERNEL object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gceCORE Core
+** Specified core.
+**
+** IN gctPOINTER Context
+** Pointer to a driver defined context.
+**
+** IN gckDB SharedDB,
+** Pointer to a shared DB.
+**
+** OUTPUT:
+**
+** gckKERNEL * Kernel
+** Pointer to a variable that will hold the pointer to the gckKERNEL
+** object.
+*/
+
+gceSTATUS
+gckKERNEL_Construct(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPOINTER Context,
+ IN gckDB SharedDB,
+ OUT gckKERNEL * Kernel
+ )
+{
+ gckKERNEL kernel = gcvNULL;
+ gceSTATUS status;
+ gctSIZE_T i;
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
+
+ /* Allocate the gckKERNEL object. */
+ gcmkONERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckKERNEL),
+ &pointer));
+
+ kernel = pointer;
+
+ /* Zero the object pointers. */
+ kernel->hardware = gcvNULL;
+ kernel->command = gcvNULL;
+ kernel->eventObj = gcvNULL;
+ kernel->mmu = gcvNULL;
+#if 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,
+ gcmSIZEOF(struct _gckDB),
+ &pointer));
+
+ kernel->db = pointer;
+ kernel->dbCreated = gcvTRUE;
+ kernel->db->freeDatabase = gcvNULL;
+ kernel->db->freeRecord = gcvNULL;
+ kernel->db->dbMutex = gcvNULL;
+ kernel->db->lastDatabase = gcvNULL;
+ kernel->db->idleTime = 0;
+ kernel->db->lastIdle = 0;
+ kernel->db->lastSlowdown = 0;
+
+ for (i = 0; i < gcmCOUNTOF(kernel->db->db); ++i)
+ {
+ kernel->db->db[i] = gcvNULL;
+ }
+
+ /* Construct a database mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->dbMutex));
+
+ /* 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 pointer name database mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->pointerDatabaseMutex));
+ }
+ else
+ {
+ kernel->db = SharedDB;
+ kernel->dbCreated = gcvFALSE;
+ }
+
+ for (i = 0; i < gcmCOUNTOF(kernel->timers); ++i)
+ {
+ kernel->timers[i].startTime = 0;
+ kernel->timers[i].stopTime = 0;
+ }
+
+ /* Save context. */
+ kernel->context = Context;
+
+ /* Construct atom holding number of clients. */
+ kernel->atomClients = gcvNULL;
+ gcmkONERROR(gckOS_AtomConstruct(Os, &kernel->atomClients));
+
+#if gcdENABLE_VG
+ kernel->vg = gcvNULL;
+
+ if (Core == gcvCORE_VG)
+ {
+ /* Construct the gckMMU object. */
+ gcmkONERROR(
+ gckVGKERNEL_Construct(Os, Context, kernel, &kernel->vg));
+
+ kernel->timeOut = gcdGPU_TIMEOUT;
+ }
+ else
+#endif
+ {
+ /* Construct the gckHARDWARE object. */
+ gcmkONERROR(
+ gckHARDWARE_Construct(Os, kernel->core, &kernel->hardware));
+
+ /* Set pointer to gckKERNEL object in gckHARDWARE object. */
+ kernel->hardware->kernel = kernel;
+
+ 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__)) && !gcdALLOC_CMD_FROM_RESERVE
+ kernel->virtualCommandBuffer = gcvTRUE;
+#else
+ kernel->virtualCommandBuffer = gcvFALSE;
+#endif
+
+#if gcdSECURITY
+ kernel->virtualCommandBuffer = gcvFALSE;
+#endif
+
+ /* Construct the gckCOMMAND object. */
+ gcmkONERROR(
+ gckCOMMAND_Construct(kernel, &kernel->command));
+
+ /* Construct the gckEVENT object. */
+ gcmkONERROR(
+ gckEVENT_Construct(kernel, &kernel->eventObj));
+
+ /* Construct the gckMMU object. */
+ gcmkONERROR(
+ gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
+
+ gcmkVERIFY_OK(gckOS_GetTime(&kernel->resetTimeStamp));
+
+ gcmkONERROR(gckHARDWARE_PrepareFunctions(kernel->hardware));
+
+ /* Initialize the hardware. */
+ gcmkONERROR(
+ gckHARDWARE_InitializeHardware(kernel->hardware));
+
+#if gcdDVFS
+ if (gckHARDWARE_IsFeatureAvailable(kernel->hardware,
+ gcvFEATURE_DYNAMIC_FREQUENCY_SCALING))
+ {
+ gcmkONERROR(gckDVFS_Construct(kernel->hardware, &kernel->dvfs));
+ gcmkONERROR(gckDVFS_Start(kernel->dvfs));
+ }
+#endif
+ }
+
+#if VIVANTE_PROFILER
+ /* Initialize profile setting */
+ kernel->profileEnable = gcvFALSE;
+ kernel->profileCleanRegister = gcvTRUE;
+#endif
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+ gcmkONERROR(gckOS_CreateSyncTimeline(Os, &kernel->timeline));
+#endif
+
+ kernel->recovery = gcvTRUE;
+ kernel->stuckDump = gcvSTUCK_DUMP_NONE;
+
+ 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;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (kernel != gcvNULL)
+ {
+#if gcdENABLE_VG
+ if (Core != gcvCORE_VG)
+#endif
+ {
+ if (kernel->eventObj != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckEVENT_Destroy(kernel->eventObj));
+ }
+
+ if (kernel->command != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckCOMMAND_Destroy(kernel->command));
+ }
+
+ if (kernel->hardware != gcvNULL)
+ {
+ /* Turn off the power. */
+ gcmkVERIFY_OK(gckOS_SetGPUPower(kernel->hardware->os,
+ kernel->hardware->core,
+ gcvFALSE,
+ gcvFALSE));
+ gcmkVERIFY_OK(gckHARDWARE_Destroy(kernel->hardware));
+ }
+ }
+
+ if (kernel->atomClients != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Os, kernel->atomClients));
+ }
+
+ if (kernel->dbCreated && kernel->db != gcvNULL)
+ {
+ if (kernel->db->dbMutex != gcvNULL)
+ {
+ /* Destroy the database mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, kernel->db->dbMutex));
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, kernel->db));
+ }
+
+ if (kernel->virtualBufferLock != gcvNULL)
+ {
+ /* Destroy the virtual command buffer mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, kernel->virtualBufferLock));
+ }
+
+#if gcdDVFS
+ if (kernel->dvfs)
+ {
+ gcmkVERIFY_OK(gckDVFS_Stop(kernel->dvfs));
+ gcmkVERIFY_OK(gckDVFS_Destroy(kernel->dvfs));
+ }
+#endif
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+ if (kernel->timeline)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySyncTimeline(Os, kernel->timeline));
+ }
+#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));
+ }
+
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Destroy
+**
+** Destroy an gckKERNEL object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Destroy(
+ IN gckKERNEL Kernel
+ )
+{
+ gctSIZE_T i;
+ gcsDATABASE_PTR database, databaseNext;
+ gcsDATABASE_RECORD_PTR record, recordNext;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+#if QNX_SINGLE_THREADED_DEBUGGING
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->debugMutex));
+#endif
+
+ /* Destroy the database. */
+ if (Kernel->dbCreated)
+ {
+ for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
+ {
+ if (Kernel->db->db[i] != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckKERNEL_DestroyProcessDB(Kernel, Kernel->db->db[i]->processID));
+ }
+ }
+
+ /* Free all databases. */
+ for (database = Kernel->db->freeDatabase;
+ database != gcvNULL;
+ database = databaseNext)
+ {
+ databaseNext = database->next;
+
+ gcmkVERIFY_OK(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));
+ }
+
+ /* Free all database records. */
+ for (record = Kernel->db->freeRecord; record != gcvNULL; record = recordNext)
+ {
+ recordNext = record->next;
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, record));
+ }
+
+ /* Destroy the database mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* 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
+ if (Kernel->vg)
+ {
+ gcmkVERIFY_OK(gckVGKERNEL_Destroy(Kernel->vg));
+ }
+ else
+#endif
+ {
+ /* Destroy the gckMMU object. */
+ gcmkVERIFY_OK(gckMMU_Destroy(Kernel->mmu));
+
+ /* Destroy the gckCOMMNAND object. */
+ gcmkVERIFY_OK(gckCOMMAND_Destroy(Kernel->command));
+
+ /* Destroy the gckEVENT object. */
+ gcmkVERIFY_OK(gckEVENT_Destroy(Kernel->eventObj));
+
+ /* Destroy the gckHARDWARE object. */
+ gcmkVERIFY_OK(gckHARDWARE_Destroy(Kernel->hardware));
+ }
+
+ /* Detsroy the client atom. */
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Kernel->atomClients));
+
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->virtualBufferLock));
+
+#if gcdDVFS
+ if (Kernel->dvfs)
+ {
+ gcmkVERIFY_OK(gckDVFS_Stop(Kernel->dvfs));
+ gcmkVERIFY_OK(gckDVFS_Destroy(Kernel->dvfs));
+ }
+#endif
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+ 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;
+
+ /* Free the gckKERNEL object. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** _AllocateMemory
+**
+** Private function to walk all required memory pools to allocate the requested
+** amount of video memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that defines the command to
+** be dispatched.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+** returned.
+*/
+gceSTATUS
+gckKERNEL_AllocateLinearMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN OUT gcePOOL * Pool,
+ IN gctSIZE_T Bytes,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+ IN gctUINT32 Flag,
+ OUT gctUINT32 * Node
+ )
+{
+ gcePOOL pool;
+ gceSTATUS status;
+ gckVIDMEM videoMemory;
+ gctINT loopCount;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+ gctBOOL tileStatusInVirtual;
+ 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);
+
+ gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes != 0);
+
+ /* 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:
+ case gcvPOOL_LOCAL:
+ pool = gcvPOOL_LOCAL_INTERNAL;
+ loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
+ break;
+
+ case gcvPOOL_UNIFIED:
+ pool = gcvPOOL_SYSTEM;
+ loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
+ break;
+
+ case gcvPOOL_CONTIGUOUS:
+ loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
+ break;
+
+ default:
+ loopCount = 1;
+ break;
+ }
+
+ while (loopCount-- > 0)
+ {
+ if (pool == gcvPOOL_VIRTUAL)
+ {
+ /* Create a gcuVIDMEM_NODE for virtual memory. */
+ gcmkONERROR(
+ gckVIDMEM_ConstructVirtual(Kernel, Flag | gcvALLOC_FLAG_NON_CONTIGUOUS, Bytes, &node));
+
+ bytes = node->Virtual.bytes;
+ node->Virtual.type = Type;
+
+ /* Success. */
+ break;
+ }
+
+ else
+ if (pool == gcvPOOL_CONTIGUOUS)
+ {
+#if gcdCONTIGUOUS_SIZE_LIMIT
+ if (Bytes > gcdCONTIGUOUS_SIZE_LIMIT && contiguous == gcvFALSE)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ }
+ else
+#endif
+ {
+ /* Create a gcuVIDMEM_NODE from contiguous memory. */
+ status = gckVIDMEM_ConstructVirtual(
+ Kernel,
+ Flag | gcvALLOC_FLAG_CONTIGUOUS,
+ Bytes,
+ &node);
+ }
+
+ if (gcmIS_SUCCESS(status))
+ {
+ 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. */
+ status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Allocate memory. */
+#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;
+ }
+ }
+ }
+
+ if (pool == gcvPOOL_LOCAL_INTERNAL)
+ {
+ /* Advance to external memory. */
+ pool = gcvPOOL_LOCAL_EXTERNAL;
+ }
+
+ else
+ if (pool == gcvPOOL_LOCAL_EXTERNAL)
+ {
+ /* Advance to contiguous system memory. */
+ pool = gcvPOOL_SYSTEM;
+ }
+
+ else
+ if (pool == gcvPOOL_SYSTEM)
+ {
+ /* Advance to contiguous memory. */
+ pool = gcvPOOL_CONTIGUOUS;
+ }
+
+ else
+ if (pool == gcvPOOL_CONTIGUOUS)
+ {
+#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;
+ }
+
+ else
+ {
+ /* Out of pools. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+ }
+
+ if (node == gcvNULL)
+ {
+ if (contiguous)
+ {
+ /* Broadcast OOM message. */
+ status = gckOS_Broadcast(Kernel->os, Kernel->hardware, gcvBROADCAST_OUT_OF_MEMORY);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Get some memory. */
+ gckOS_Delay(gcvNULL, 1);
+ goto AllocateMemory;
+ }
+ }
+
+ /* 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 = 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;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_ReleaseVideoMemory
+**
+** Release handle of a video memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** ProcessID of current process.
+**
+** gctUINT32 Handle
+** Handle of video memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_ReleaseVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE nodeObject;
+ gceDATABASE_TYPE type;
+
+ gcmkHEADER_ARG("Kernel=0x%08X ProcessID=%d Handle=%d",
+ Kernel, ProcessID, Handle);
+
+ gcmkONERROR(
+ gckVIDMEM_HANDLE_Lookup(Kernel, ProcessID, Handle, &nodeObject));
+
+ type = gcvDB_VIDEO_MEMORY
+ | (nodeObject->type << gcdDB_VIDEO_MEMORY_TYPE_SHIFT)
+ | (nodeObject->pool << gcdDB_VIDEO_MEMORY_POOL_SHIFT);
+
+ gcmkONERROR(
+ gckKERNEL_RemoveProcessDB(Kernel,
+ ProcessID,
+ type,
+ gcmINT2PTR(Handle)));
+
+ gckVIDMEM_HANDLE_Dereference(Kernel, ProcessID, Handle);
+
+ gckVIDMEM_NODE_Dereference(Kernel, nodeObject);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** 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
+
+ gcmkHEADER_ARG("Kernel=0x%08X ProcessID=%d",
+ Kernel, ProcessID);
+
+ gcmkONERROR(
+ gckVIDMEM_HANDLE_LookupAndReference(Kernel,
+ Interface->u.LockVideoMemory.node,
+ &nodeObject));
+
+ node = nodeObject->node;
+
+ Interface->u.LockVideoMemory.gid = 0;
+
+ /* Lock video memory. */
+ gcmkONERROR(
+ gckVIDMEM_Lock(Kernel,
+ nodeObject,
+ Interface->u.LockVideoMemory.cacheable,
+ &Interface->u.LockVideoMemory.address,
+ &Interface->u.LockVideoMemory.gid,
+ &Interface->u.LockVideoMemory.physicalAddress));
+
+ locked = gcvTRUE;
+
+ 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(
+ gckKERNEL_MapVideoMemoryEx(Kernel,
+ Core,
+ FromUser,
+ Interface->u.LockVideoMemory.address,
+ &pointer));
+
+ Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(pointer);
+#endif
+ }
+ else
+ {
+ Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->Virtual.logical);
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gcmkONERROR(gckVIDMEM_Node_Lock(
+ Kernel,
+ nodeObject,
+ &Interface->u.LockVideoMemory.address
+ ));
+#endif
+
+
+#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));
+
+ gckVIDMEM_HANDLE_Reference(
+ Kernel, ProcessID, (gctUINT32)Interface->u.LockVideoMemory.node);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (locked)
+ {
+ /* Roll back the lock. */
+ gcmkVERIFY_OK(gckVIDMEM_Unlock(Kernel,
+ nodeObject,
+ gcvSURF_TYPE_UNKNOWN,
+ &asynchronous));
+
+ if (gcvTRUE == asynchronous)
+ {
+ /* Bottom Half */
+ gcmkVERIFY_OK(gckVIDMEM_Unlock(Kernel,
+ nodeObject,
+ gcvSURF_TYPE_UNKNOWN,
+ gcvNULL));
+ }
+ }
+
+ if (nodeObject != gcvNULL)
+ {
+ gckVIDMEM_NODE_Dereference(Kernel, nodeObject);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** 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;
+
+ gcmkHEADER_ARG("Kernel=0x%08X ProcessID=%d",
+ Kernel, ProcessID);
+
+ gcmkONERROR(gckVIDMEM_HANDLE_Lookup(
+ Kernel,
+ ProcessID,
+ (gctUINT32)Interface->u.UnlockVideoMemory.node,
+ &nodeObject));
+
+ node = nodeObject->node;
+
+ /* 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
+
+ /* Unlock video memory. */
+ gcmkONERROR(gckVIDMEM_Unlock(
+ Kernel,
+ nodeObject,
+ 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
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_QueryDatabase(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gceSTATUS status;
+ gctINT i;
+ gcuDATABASE_INFO tmp;
+
+ 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),
+ };
+
+ gcmkHEADER();
+
+ /* 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));
+ 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));
+
+ 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;
+
+ 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;
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gckKERNEL_DumpVidMemUsage(Kernel, Interface->u.Database.processID);
+#endif
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_ConfigPowerManagement(
+ IN gckKERNEL Kernel,
+ IN OUT gcsHAL_INTERFACE * Interface
+)
+{
+ gceSTATUS status;
+ gctBOOL enable = Interface->u.ConfigPowerManagement.enable;
+
+ gcmkHEADER();
+
+ gcmkONERROR(gckHARDWARE_SetPowerManagement(Kernel->hardware, enable));
+
+ if (enable == gcvFALSE)
+ {
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Kernel->hardware, gcvPOWER_ON));
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_WrapUserMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gcsUSER_MEMORY_DESC_PTR Desc,
+ OUT gctUINT32 * Node
+ )
+{
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+ gctUINT32 handle;
+ gceDATABASE_TYPE databaseRecordType;
+
+ gcmkHEADER_ARG("Kernel=0x%X Desc=%x", Kernel, Desc);
+
+ gcmkONERROR(gckVIDMEM_ConstructVirtualFromUserMemory(
+ Kernel,
+ Desc,
+ &node
+ ));
+
+ /* Allocate handle for this video memory. */
+ gcmkONERROR(gckVIDMEM_NODE_Allocate(
+ Kernel,
+ node,
+ gcvSURF_BITMAP,
+ gcvPOOL_VIRTUAL,
+ &handle
+ ));
+
+ /* Wrapped node is treated as gcvPOOL_VIRTUAL, but in statistic view,
+ * it is gcvPOOL_USER.
+ */
+ databaseRecordType
+ = gcvDB_VIDEO_MEMORY
+ | (gcvSURF_BITMAP << gcdDB_VIDEO_MEMORY_TYPE_SHIFT)
+ | (gcvPOOL_USER << gcdDB_VIDEO_MEMORY_POOL_SHIFT)
+ ;
+
+ /* Record in process db. */
+ gcmkONERROR(gckKERNEL_AddProcessDB(
+ Kernel,
+ ProcessID,
+ databaseRecordType,
+ gcmINT2PTR(handle),
+ gcvNULL,
+ node->Virtual.bytes
+ ));
+
+ /* Return handle of the node. */
+ *Node = handle;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Dispatch
+**
+** Dispatch a command received from the user HAL layer.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL FromUser
+** whether the call is from the user space.
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that defines the command to
+** be dispatched.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+** returned.
+*/
+gceSTATUS
+gckKERNEL_Dispatch(
+ IN gckKERNEL Kernel,
+ IN gctBOOL FromUser,
+ IN OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctPHYS_ADDR physical = gcvNULL;
+ gctSIZE_T bytes;
+ gctPOINTER logical = gcvNULL;
+ gctPOINTER info = gcvNULL;
+#if (gcdENABLE_3D || gcdENABLE_2D)
+ gckCONTEXT context = gcvNULL;
+#endif
+ gckKERNEL kernel = Kernel;
+ gctUINT32 address;
+ gctUINT32 processID;
+#if gcdSECURE_USER
+ gcskSECURE_CACHE_PTR cache;
+ gctPOINTER logical;
+#endif
+ gctUINT64 paddr = gcvINVALID_ADDRESS;
+#if !USE_NEW_LINUX_SIGNAL
+ gctSIGNAL signal;
+#endif
+ gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
+
+ gckVIDMEM_NODE nodeObject;
+ gctBOOL powerMutexAcquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
+ Kernel, FromUser, Interface);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "Dispatching command %d (%s)",
+ Interface->command, _DispatchText[Interface->command]);
+#endif
+#if QNX_SINGLE_THREADED_DEBUGGING
+ gckOS_AcquireMutex(Kernel->os, Kernel->debugMutex, gcvINFINITE);
+#endif
+
+ /* Get the current process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+
+#if gcdSECURE_USER
+ gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
+#endif
+
+ /* Dispatch on command. */
+ switch (Interface->command)
+ {
+ case gcvHAL_GET_BASE_ADDRESS:
+ /* Get base address. */
+ gcmkONERROR(
+ gckOS_GetBaseAddress(Kernel->os,
+ &Interface->u.GetBaseAddress.baseAddress));
+ break;
+
+ case gcvHAL_QUERY_VIDEO_MEMORY:
+ /* Query video memory size. */
+ gcmkONERROR(gckKERNEL_QueryVideoMemory(Kernel, Interface));
+ break;
+
+ case gcvHAL_QUERY_CHIP_IDENTITY:
+ /* Query chip identity. */
+ gcmkONERROR(
+ gckHARDWARE_QueryChipIdentity(
+ Kernel->hardware,
+ &Interface->u.QueryChipIdentity));
+ 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 ?
+ 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));
+#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:
+ /* Map user memory to DMA. */
+ gcmkONERROR(
+ gckOS_MapUserMemory(Kernel->os,
+ Kernel->core,
+ gcmUINT64_TO_PTR(Interface->u.MapUserMemory.memory),
+ Interface->u.MapUserMemory.physical,
+ (gctSIZE_T) Interface->u.MapUserMemory.size,
+ &info,
+ &Interface->u.MapUserMemory.address));
+
+ Interface->u.MapUserMemory.info = gcmPTR_TO_NAME(info);
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_MAP_USER_MEMORY,
+ gcmINT2PTR(Interface->u.MapUserMemory.info),
+ gcmUINT64_TO_PTR(Interface->u.MapUserMemory.memory),
+ (gctSIZE_T) Interface->u.MapUserMemory.size));
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+ 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,
+ Kernel->core,
+ gcmUINT64_TO_PTR(Interface->u.UnmapUserMemory.memory),
+ (gctSIZE_T) Interface->u.UnmapUserMemory.size,
+ info,
+ address));
+
+#if gcdSECURE_USER
+ gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+ Kernel,
+ cache,
+ gcmUINT64_TO_PTR(Interface->u.UnmapUserMemory.memory),
+ (gctSIZE_T) Interface->u.UnmapUserMemory.size));
+#endif
+
+ gcmRELEASE_NAME(Interface->u.UnmapUserMemory.info);
+ break;
+
+#if !USE_NEW_LINUX_SIGNAL
+ case gcvHAL_USER_SIGNAL:
+ /* Dispatch depends on the user signal subcommands. */
+ switch(Interface->u.UserSignal.command)
+ {
+ case gcvUSER_SIGNAL_CREATE:
+ /* Create a signal used in the user space. */
+ gcmkONERROR(
+ gckOS_CreateUserSignal(Kernel->os,
+ Interface->u.UserSignal.manualReset,
+ &Interface->u.UserSignal.id));
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_SIGNAL,
+ gcmINT2PTR(Interface->u.UserSignal.id),
+ gcvNULL,
+ 0));
+ break;
+
+ case gcvUSER_SIGNAL_DESTROY:
+ 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:
+ /* Signal the signal. */
+ gcmkONERROR(
+ gckOS_SignalUserSignal(Kernel->os,
+ Interface->u.UserSignal.id,
+ Interface->u.UserSignal.state));
+ break;
+
+ case gcvUSER_SIGNAL_WAIT:
+ /* Wait on the signal. */
+ status = gckOS_WaitUserSignal(Kernel->os,
+ Interface->u.UserSignal.id,
+ Interface->u.UserSignal.wait);
+
+ break;
+
+ case gcvUSER_SIGNAL_MAP:
+ gcmkONERROR(
+ gckOS_MapSignal(Kernel->os,
+ (gctSIGNAL)(gctUINTPTR_T)Interface->u.UserSignal.id,
+ (gctHANDLE)(gctUINTPTR_T)processID,
+ &signal));
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_SIGNAL,
+ gcmINT2PTR(Interface->u.UserSignal.id),
+ gcvNULL,
+ 0));
+ break;
+
+ case gcvUSER_SIGNAL_UNMAP:
+ 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:
+ /* Invalid user signal command. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+ break;
+#endif
+
+ case gcvHAL_SET_POWER_MANAGEMENT_STATE:
+ /* Set the power management state. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(
+ Kernel->hardware,
+ Interface->u.SetPowerManagement.state));
+ break;
+
+ case gcvHAL_QUERY_POWER_MANAGEMENT_STATE:
+ /* Chip is not idle. */
+ Interface->u.QueryPowerManagement.isIdle = gcvFALSE;
+
+ /* Query the power management state. */
+ gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
+ Kernel->hardware,
+ &Interface->u.QueryPowerManagement.state));
+
+ /* Query the idle state. */
+ gcmkONERROR(
+ gckHARDWARE_QueryIdle(Kernel->hardware,
+ &Interface->u.QueryPowerManagement.isIdle));
+ break;
+
+ case gcvHAL_READ_REGISTER:
+#if gcdREGISTER_ACCESS_FROM_USER
+ {
+ gceCHIPPOWERSTATE power;
+
+ gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->hardware->powerMutex, gcvINFINITE));
+ powerMutexAcquired = gcvTRUE;
+ gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
+ &power));
+ if (power == gcvPOWER_ON)
+ {
+ /* Read a register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(
+ Kernel->os,
+ Kernel->core,
+ Interface->u.ReadRegisterData.address,
+ &Interface->u.ReadRegisterData.data));
+ }
+ else
+ {
+ /* Chip is in power-state. */
+ Interface->u.ReadRegisterData.data = 0;
+ status = gcvSTATUS_CHIP_NOT_READY;
+ }
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
+ powerMutexAcquired = gcvFALSE;
+ }
+#else
+ /* No access from user land to read registers. */
+ Interface->u.ReadRegisterData.data = 0;
+ status = gcvSTATUS_NOT_SUPPORTED;
+#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
+ {
+ gceCHIPPOWERSTATE power;
+
+ gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->hardware->powerMutex, gcvINFINITE));
+ powerMutexAcquired = gcvTRUE;
+ gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
+ &power));
+ if (power == gcvPOWER_ON)
+ {
+ /* Write a register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Kernel->os,
+ Kernel->core,
+ Interface->u.WriteRegisterData.address,
+ Interface->u.WriteRegisterData.data));
+ }
+ else
+ {
+ /* Chip is in power-state. */
+ Interface->u.WriteRegisterData.data = 0;
+ status = gcvSTATUS_CHIP_NOT_READY;
+ }
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
+ powerMutexAcquired = gcvFALSE;
+ }
+#else
+ /* No access from user land to write registers. */
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+
+ case gcvHAL_READ_ALL_PROFILE_REGISTERS:
+#if VIVANTE_PROFILER && VIVANTE_PROFILER_CONTEXT
+ /* Read profile data according to the context. */
+ gcmkONERROR(
+ gckHARDWARE_QueryContextProfile(
+ Kernel->hardware,
+ Kernel->profileCleanRegister,
+ gcmNAME_TO_PTR(Interface->u.RegisterProfileData.context),
+ &Interface->u.RegisterProfileData.counters));
+#elif VIVANTE_PROFILER
+ /* Read all 3D profile registers. */
+ gcmkONERROR(
+ gckHARDWARE_QueryProfileRegisters(
+ Kernel->hardware,
+ Kernel->profileCleanRegister,
+ &Interface->u.RegisterProfileData.counters));
+#else
+ status = gcvSTATUS_OK;
+#endif
+ break;
+
+ case gcvHAL_PROFILE_REGISTERS_2D:
+#if VIVANTE_PROFILER
+ /* Read all 2D profile registers. */
+ gcmkONERROR(
+ gckHARDWARE_ProfileEngine2D(
+ Kernel->hardware,
+ gcmUINT64_TO_PTR(Interface->u.RegisterProfileData2D.hwProfile2D)));
+#else
+ status = gcvSTATUS_OK;
+#endif
+ break;
+
+ case gcvHAL_GET_PROFILE_SETTING:
+#if VIVANTE_PROFILER
+ /* Get profile setting */
+ Interface->u.GetProfileSetting.enable = Kernel->profileEnable;
+#endif
+
+ 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 ((Kernel->hardware->identity.chipModel == gcv1500 && Kernel->hardware->identity.chipRevision == 0x5246) ||
+ (Kernel->hardware->identity.chipModel == gcv3000 && Kernel->hardware->identity.chipRevision == 0x5450))
+ gcmkONERROR(gckHARDWARE_InitProfiler(Kernel->hardware));
+
+#if VIVANTE_PROFILER_NEW
+ if (Kernel->profileEnable)
+ gckHARDWARE_InitProfiler(Kernel->hardware);
+#endif
+ }
+ else
+ {
+ status = gcvSTATUS_NOT_SUPPORTED;
+ break;
+ }
+#endif
+
+ status = gcvSTATUS_OK;
+ break;
+
+#if VIVANTE_PROFILER_PERDRAW
+ case gcvHAL_READ_PROFILER_REGISTER_SETTING:
+ #if VIVANTE_PROFILER
+ Kernel->profileCleanRegister = Interface->u.SetProfilerRegisterClear.bclear;
+ #endif
+ status = gcvSTATUS_OK;
+ break;
+#endif
+
+ case gcvHAL_QUERY_KERNEL_SETTINGS:
+ /* Get kernel settings. */
+ gcmkONERROR(
+ gckKERNEL_QuerySettings(Kernel,
+ &Interface->u.QueryKernelSettings.settings));
+ break;
+
+ case gcvHAL_RESET:
+ /* Reset the hardware. */
+ gcmkONERROR(
+ gckHARDWARE_Reset(Kernel->hardware));
+ break;
+
+ case gcvHAL_DEBUG:
+ /* Set debug level and zones. */
+ if (Interface->u.Debug.set)
+ {
+ gckOS_SetDebugLevel(Interface->u.Debug.level);
+ gckOS_SetDebugZones(Interface->u.Debug.zones,
+ Interface->u.Debug.enable);
+ }
+
+ if (Interface->u.Debug.message[0] != '\0')
+ {
+ /* Print a message to the debugger. */
+ if (Interface->u.Debug.type == gcvMESSAGE_TEXT)
+ {
+ gckOS_CopyPrint(Interface->u.Debug.message);
+ }
+ else
+ {
+ gckOS_DumpBuffer(Kernel->os,
+ Interface->u.Debug.message,
+ Interface->u.Debug.messageSize,
+ gceDUMP_BUFFER_FROM_USER,
+ gcvTRUE);
+ }
+ }
+ status = gcvSTATUS_OK;
+ break;
+
+ case gcvHAL_DUMP_GPU_STATE:
+ {
+ gceCHIPPOWERSTATE power;
+
+ _DumpDriverConfigure(Kernel);
+
+ gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
+ Kernel->hardware,
+ &power
+ ));
+
+ if (power == gcvPOWER_ON)
+ {
+ Interface->u.ReadRegisterData.data = 1;
+
+ _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:
+ break;
+
+ case gcvHAL_CACHE:
+
+ logical = gcmUINT64_TO_PTR(Interface->u.Cache.logical);
+
+ if (Interface->u.Cache.node)
+ {
+ 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_UserLogicalToPhysical(
+ Kernel->os, logical, &paddr));
+ }
+ }
+
+ bytes = (gctSIZE_T) Interface->u.Cache.bytes;
+ switch(Interface->u.Cache.operation)
+ {
+ case gcvCACHE_FLUSH:
+ /* Clean and invalidate the cache. */
+ status = gckOS_CacheFlush(Kernel->os,
+ processID,
+ physical,
+ paddr,
+ logical,
+ bytes);
+ break;
+ case gcvCACHE_CLEAN:
+ /* Clean the cache. */
+ status = gckOS_CacheClean(Kernel->os,
+ processID,
+ physical,
+ paddr,
+ logical,
+ bytes);
+ break;
+ case gcvCACHE_INVALIDATE:
+ /* Invalidate the cache. */
+ status = gckOS_CacheInvalidate(Kernel->os,
+ processID,
+ physical,
+ paddr,
+ logical,
+ bytes);
+ break;
+
+ case gcvCACHE_MEMORY_BARRIER:
+ status = gckOS_MemoryBarrier(Kernel->os,
+ logical);
+ break;
+ default:
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+ break;
+
+ case gcvHAL_TIMESTAMP:
+ /* Check for invalid timer. */
+ if ((Interface->u.TimeStamp.timer >= gcmCOUNTOF(Kernel->timers))
+ || (Interface->u.TimeStamp.request != 2))
+ {
+ Interface->u.TimeStamp.timeDelta = 0;
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Return timer results and reset timer. */
+ {
+ gcsTIMER_PTR timer = &(Kernel->timers[Interface->u.TimeStamp.timer]);
+ gctUINT64 timeDelta = 0;
+
+ if (timer->stopTime < timer->startTime )
+ {
+ Interface->u.TimeStamp.timeDelta = 0;
+ gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW);
+ }
+
+ timeDelta = timer->stopTime - timer->startTime;
+
+ /* Check truncation overflow. */
+ Interface->u.TimeStamp.timeDelta = (gctINT32) timeDelta;
+ /*bit0~bit30 is available*/
+ if (timeDelta>>31)
+ {
+ Interface->u.TimeStamp.timeDelta = 0;
+ gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW);
+ }
+
+ status = gcvSTATUS_OK;
+ }
+ break;
+
+ case gcvHAL_DATABASE:
+ gcmkONERROR(gckKERNEL_QueryDatabase(Kernel, processID, Interface));
+ break;
+
+ case gcvHAL_VERSION:
+ Interface->u.Version.major = gcvVERSION_MAJOR;
+ Interface->u.Version.minor = gcvVERSION_MINOR;
+ Interface->u.Version.patch = gcvVERSION_PATCH;
+ Interface->u.Version.build = gcvVERSION_BUILD;
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "KERNEL version %d.%d.%d build %u",
+ gcvVERSION_MAJOR, gcvVERSION_MINOR,
+ gcvVERSION_PATCH, gcvVERSION_BUILD);
+#endif
+ break;
+
+ case gcvHAL_CHIP_INFO:
+ /* Only if not support multi-core */
+ Interface->u.ChipInfo.count = 1;
+ Interface->u.ChipInfo.types[0] = Kernel->hardware->type;
+ break;
+
+#if (gcdENABLE_3D || gcdENABLE_2D)
+ case gcvHAL_ATTACH:
+ /* Attach user process. */
+ gcmkONERROR(
+ gckCOMMAND_Attach(Kernel->command,
+ &context,
+ &bytes,
+ &Interface->u.Attach.numStates,
+ processID));
+
+ Interface->u.Attach.maxState = 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,
+ gcmINT2PTR(Interface->u.Attach.context),
+ gcvNULL,
+ 0));
+ break;
+#endif
+
+ case gcvHAL_DETACH:
+ 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;
+
+ case gcvHAL_COMPOSE:
+ Interface->u.Compose.physical = gcmPTR_TO_UINT64(gcmNAME_TO_PTR(Interface->u.Compose.physical));
+ /* Start composition. */
+ gcmkONERROR(
+ gckEVENT_Compose(Kernel->eventObj,
+ &Interface->u.Compose));
+ break;
+
+ case gcvHAL_SET_TIMEOUT:
+ /* set timeOut value from user */
+ gckKERNEL_SetTimeOut(Kernel, Interface->u.SetTimeOut.timeOut);
+ break;
+
+ case gcvHAL_GET_FRAME_INFO:
+ gcmkONERROR(gckHARDWARE_GetFrameInfo(
+ Kernel->hardware,
+ gcmUINT64_TO_PTR(Interface->u.GetFrameInfo.frameInfo)));
+ break;
+
+ case gcvHAL_SET_FSCALE_VALUE:
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ status = gckHARDWARE_SetFscaleValue(Kernel->hardware,
+ Interface->u.SetFscaleValue.value);
+#else
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+ case gcvHAL_GET_FSCALE_VALUE:
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ status = gckHARDWARE_GetFscaleValue(Kernel->hardware,
+ &Interface->u.GetFscaleValue.value,
+ &Interface->u.GetFscaleValue.minValue,
+ &Interface->u.GetFscaleValue.maxValue);
+#else
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+
+ case gcvHAL_NAME_VIDEO_MEMORY:
+ gcmkONERROR(gckVIDMEM_NODE_Name(Kernel,
+ Interface->u.NameVideoMemory.handle,
+ &Interface->u.NameVideoMemory.name));
+ 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_GET_VIDEO_MEMORY_FD:
+ gcmkONERROR(gckVIDMEM_NODE_GetFd(
+ Kernel,
+ Interface->u.GetVideoMemoryFd.handle,
+ &Interface->u.GetVideoMemoryFd.fd
+ ));
+
+ /* 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;
+
+ case gcvSYNC_POINT_DESTROY:
+ syncPoint = gcmUINT64_TO_PTR(Interface->u.SyncPoint.syncPoint);
+
+ gcmkONERROR(gckOS_DestroySyncPoint(Kernel->os, syncPoint));
+
+ gcmkVERIFY_OK(
+ gckKERNEL_RemoveProcessDB(Kernel,
+ processID, gcvDB_SYNC_POINT,
+ syncPoint));
+ break;
+
+ default:
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ break;
+ }
+ }
+ break;
+
+ case gcvHAL_CREATE_NATIVE_FENCE:
+ {
+ gctINT fenceFD;
+ gctSYNC_POINT syncPoint =
+ gcmUINT64_TO_PTR(Interface->u.CreateNativeFence.syncPoint);
+
+ gcmkONERROR(
+ gckOS_CreateNativeFence(Kernel->os,
+ Kernel->timeline,
+ syncPoint,
+ &fenceFD));
+
+ Interface->u.CreateNativeFence.fenceFD = fenceFD;
+ }
+ break;
+
+ case gcvHAL_WAIT_NATIVE_FENCE:
+ {
+ gctINT fenceFD;
+ gctUINT32 timeout;
+
+ fenceFD = Interface->u.WaitNativeFence.fenceFD;
+ timeout = Interface->u.WaitNativeFence.timeout;
+
+ gcmkONERROR(
+ gckOS_WaitNativeFence(Kernel->os,
+ Kernel->timeline,
+ fenceFD,
+ timeout));
+ }
+ 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;
+
+ case gcvHAL_WRAP_USER_MEMORY:
+ gcmkONERROR(gckKERNEL_WrapUserMemory(
+ Kernel,
+ processID,
+ &Interface->u.WrapUserMemory.desc,
+ &Interface->u.WrapUserMemory.node
+ ));
+ break;
+
+#if gcdENABLE_DEC_COMPRESSION && gcdDEC_ENABLE_AHB
+ case gcvHAL_DEC300_READ:
+ gcmkONERROR(viv_dec300_read(
+ Interface->u.DEC300Read.enable,
+ Interface->u.DEC300Read.readId,
+ Interface->u.DEC300Read.format,
+ Interface->u.DEC300Read.strides,
+ Interface->u.DEC300Read.is3D,
+ Interface->u.DEC300Read.isMSAA,
+ Interface->u.DEC300Read.clearValue,
+ Interface->u.DEC300Read.isTPC,
+ Interface->u.DEC300Read.isTPCCompressed,
+ Interface->u.DEC300Read.surfAddrs,
+ Interface->u.DEC300Read.tileAddrs
+ ));
+ break;
+
+ case gcvHAL_DEC300_WRITE:
+ gcmkONERROR(viv_dec300_write(
+ Interface->u.DEC300Write.enable,
+ Interface->u.DEC300Write.readId,
+ Interface->u.DEC300Write.writeId,
+ Interface->u.DEC300Write.format,
+ Interface->u.DEC300Write.surfAddr,
+ Interface->u.DEC300Write.tileAddr
+ ));
+ break;
+
+ case gcvHAL_DEC300_FLUSH:
+ gcmkONERROR(viv_dec300_flush(0));
+ break;
+
+ case gcvHAL_DEC300_FLUSH_WAIT:
+ gcmkONERROR(viv_dec300_flush_done(&Interface->u.DEC300FlushWait.done));
+ break;
+#endif
+
+ default:
+ /* Invalid command. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+OnError:
+ /* Save status. */
+ Interface->status = status;
+
+#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;
+}
+
+/*******************************************************************************
+** gckKERNEL_AttachProcess
+**
+** Attach or detach a process.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL Attach
+** gcvTRUE if a new process gets attached or gcFALSE when a process
+** gets detatched.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_AttachProcess(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Attach
+ )
+{
+ gceSTATUS status;
+ gctUINT32 processID;
+
+ gcmkHEADER_ARG("Kernel=0x%x Attach=%d", Kernel, Attach);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Get current process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+
+ gcmkONERROR(gckKERNEL_AttachProcessEx(Kernel, Attach, processID));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_AttachProcessEx
+**
+** Attach or detach a process with the given PID. Can be paired with gckKERNEL_AttachProcess
+** provided the programmer is aware of the consequences.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL Attach
+** gcvTRUE if a new process gets attached or gcFALSE when a process
+** gets detatched.
+**
+** gctUINT32 PID
+** PID of the process to attach or detach.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_AttachProcessEx(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Attach,
+ IN gctUINT32 PID
+ )
+{
+ gceSTATUS status;
+ gctINT32 old;
+
+ gcmkHEADER_ARG("Kernel=0x%x Attach=%d PID=%d", Kernel, Attach, PID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ if (Attach)
+ {
+ /* Increment the number of clients attached. */
+ gcmkONERROR(
+ gckOS_AtomIncrement(Kernel->os, Kernel->atomClients, &old));
+
+ if (old == 0)
+ {
+#if gcdENABLE_VG
+ if (Kernel->vg == gcvNULL)
+#endif
+ {
+ gcmkONERROR(gckOS_Broadcast(Kernel->os,
+ Kernel->hardware,
+ gcvBROADCAST_FIRST_PROCESS));
+ }
+ }
+
+ if (Kernel->dbCreated)
+ {
+ /* Create the process database. */
+ gcmkONERROR(gckKERNEL_CreateProcessDB(Kernel, PID));
+ }
+
+#if gcdPROCESS_ADDRESS_SPACE
+ /* Map kernel command buffer in the process's own MMU. */
+ gcmkONERROR(_MapCommandBuffer(Kernel));
+#endif
+ }
+ else
+ {
+ if (Kernel->dbCreated)
+ {
+ /* Clean up the process database. */
+ gcmkONERROR(gckKERNEL_DestroyProcessDB(Kernel, PID));
+
+ /* Save the last know process ID. */
+ Kernel->db->lastProcessID = PID;
+ }
+
+#if gcdENABLE_VG
+ 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)
+ {
+ gcmkONERROR(gckOS_StartTimer(Kernel->os,
+ Kernel->eventObj->submitTimer,
+ 1));
+ }
+ else
+ {
+ gcmkONERROR(status);
+ }
+ }
+
+ /* Decrement the number of clients attached. */
+ gcmkONERROR(
+ gckOS_AtomDecrement(Kernel->os, Kernel->atomClients, &old));
+
+ if (old == 1)
+ {
+#if gcdENABLE_VG
+ if (Kernel->vg == gcvNULL)
+#endif
+ {
+ /* Last client detached, switch to SUSPEND power state. */
+ gcmkONERROR(gckOS_Broadcast(Kernel->os,
+ Kernel->hardware,
+ gcvBROADCAST_LAST_PROCESS));
+ }
+
+ /* Flush the debug cache. */
+ gcmkDEBUGFLUSH(~0U);
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdSECURE_USER
+gceSTATUS
+gckKERNEL_MapLogicalToPhysical(
+ IN gckKERNEL Kernel,
+ IN gcskSECURE_CACHE_PTR Cache,
+ IN OUT gctPOINTER * Data
+ )
+{
+ gceSTATUS status;
+ static gctBOOL baseAddressValid = gcvFALSE;
+ static gctUINT32 baseAddress;
+ gctBOOL needBase;
+ gcskLOGICAL_CACHE_PTR slot;
+
+ gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x *Data=0x%x",
+ Kernel, Cache, gcmOPT_POINTER(Data));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ if (!baseAddressValid)
+ {
+ /* Get base address. */
+ gcmkONERROR(gckHARDWARE_GetBaseAddress(Kernel->hardware, &baseAddress));
+
+ baseAddressValid = gcvTRUE;
+ }
+
+ /* Does this state load need a base address? */
+ gcmkONERROR(gckHARDWARE_NeedBaseAddress(Kernel->hardware,
+ ((gctUINT32_PTR) Data)[-1],
+ &needBase));
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
+ {
+ gcskLOGICAL_CACHE_PTR next;
+ gctINT i;
+
+ /* Walk all used cache slots. */
+ for (i = 1, slot = Cache->cache[0].next, next = gcvNULL;
+ (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+ ++i, slot = slot->next
+ )
+ {
+ if (slot->logical == *Data)
+ {
+ /* Bail out. */
+ next = slot;
+ break;
+ }
+ }
+
+ /* See if we had a miss. */
+ if (next == gcvNULL)
+ {
+ /* Use the tail of the cache. */
+ slot = Cache->cache[0].prev;
+
+ /* Initialize the cache line. */
+ slot->logical = *Data;
+
+ /* Map the logical address to a DMA address. */
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
+ }
+
+ /* Move slot to head of list. */
+ if (slot != Cache->cache[0].next)
+ {
+ /* Unlink. */
+ slot->prev->next = slot->next;
+ slot->next->prev = slot->prev;
+
+ /* Move to head of chain. */
+ slot->prev = &Cache->cache[0];
+ slot->next = Cache->cache[0].next;
+ slot->prev->next = slot;
+ slot->next->prev = slot;
+ }
+ }
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
+ {
+ gctINT i;
+ gcskLOGICAL_CACHE_PTR next = gcvNULL;
+ gcskLOGICAL_CACHE_PTR oldestSlot = gcvNULL;
+ slot = gcvNULL;
+
+ if (Cache->cacheIndex != gcvNULL)
+ {
+ /* Walk the cache forwards. */
+ for (i = 1, slot = Cache->cacheIndex;
+ (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+ ++i, slot = slot->next)
+ {
+ if (slot->logical == *Data)
+ {
+ /* Bail out. */
+ next = slot;
+ break;
+ }
+
+ /* Determine age of this slot. */
+ if ((oldestSlot == gcvNULL)
+ || (oldestSlot->stamp > slot->stamp)
+ )
+ {
+ oldestSlot = slot;
+ }
+ }
+
+ if (next == gcvNULL)
+ {
+ /* Walk the cache backwards. */
+ for (slot = Cache->cacheIndex->prev;
+ (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+ ++i, slot = slot->prev)
+ {
+ if (slot->logical == *Data)
+ {
+ /* Bail out. */
+ next = slot;
+ break;
+ }
+
+ /* Determine age of this slot. */
+ if ((oldestSlot == gcvNULL)
+ || (oldestSlot->stamp > slot->stamp)
+ )
+ {
+ oldestSlot = slot;
+ }
+ }
+ }
+ }
+
+ /* See if we had a miss. */
+ if (next == gcvNULL)
+ {
+ if (Cache->cacheFree != 0)
+ {
+ slot = &Cache->cache[Cache->cacheFree];
+ gcmkASSERT(slot->logical == gcvNULL);
+
+ ++ Cache->cacheFree;
+ if (Cache->cacheFree >= gcmCOUNTOF(Cache->cache))
+ {
+ Cache->cacheFree = 0;
+ }
+ }
+ else
+ {
+ /* Use the oldest cache slot. */
+ gcmkASSERT(oldestSlot != gcvNULL);
+ slot = oldestSlot;
+
+ /* Unlink from the chain. */
+ slot->prev->next = slot->next;
+ slot->next->prev = slot->prev;
+
+ /* Append to the end. */
+ slot->prev = Cache->cache[0].prev;
+ slot->next = &Cache->cache[0];
+ slot->prev->next = slot;
+ slot->next->prev = slot;
+ }
+
+ /* Initialize the cache line. */
+ slot->logical = *Data;
+
+ /* Map the logical address to a DMA address. */
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
+ }
+
+ /* Save time stamp. */
+ slot->stamp = ++ Cache->cacheStamp;
+
+ /* Save current slot for next lookup. */
+ Cache->cacheIndex = slot;
+ }
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ {
+ gctINT i;
+ gctUINT32 data = gcmPTR2INT32(*Data);
+ gctUINT32 key, index;
+ gcskLOGICAL_CACHE_PTR hash;
+
+ /* Generate a hash key. */
+ key = (data >> 24) + (data >> 16) + (data >> 8) + data;
+ index = key % gcmCOUNTOF(Cache->hash);
+
+ /* Get the hash entry. */
+ hash = &Cache->hash[index];
+
+ for (slot = hash->nextHash, i = 0;
+ (slot != gcvNULL) && (i < gcdSECURE_CACHE_SLOTS);
+ slot = slot->nextHash, ++i
+ )
+ {
+ if (slot->logical == (*Data))
+ {
+ break;
+ }
+ }
+
+ if (slot == gcvNULL)
+ {
+ /* Grab from the tail of the cache. */
+ slot = Cache->cache[0].prev;
+
+ /* Unlink slot from any hash table it is part of. */
+ if (slot->prevHash != gcvNULL)
+ {
+ slot->prevHash->nextHash = slot->nextHash;
+ }
+ if (slot->nextHash != gcvNULL)
+ {
+ slot->nextHash->prevHash = slot->prevHash;
+ }
+
+ /* Initialize the cache line. */
+ slot->logical = *Data;
+
+ /* Map the logical address to a DMA address. */
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
+
+ if (hash->nextHash != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "Hash Collision: logical=0x%x key=0x%08x",
+ *Data, key);
+ }
+
+ /* Insert the slot at the head of the hash list. */
+ slot->nextHash = hash->nextHash;
+ if (slot->nextHash != gcvNULL)
+ {
+ slot->nextHash->prevHash = slot;
+ }
+ slot->prevHash = hash;
+ hash->nextHash = slot;
+ }
+
+ /* Move slot to head of list. */
+ if (slot != Cache->cache[0].next)
+ {
+ /* Unlink. */
+ slot->prev->next = slot->next;
+ slot->next->prev = slot->prev;
+
+ /* Move to head of chain. */
+ slot->prev = &Cache->cache[0];
+ slot->next = Cache->cache[0].next;
+ slot->prev->next = slot;
+ slot->next->prev = slot;
+ }
+ }
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
+ {
+ gctUINT32 index = (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 == gcvSTUCK_DUMP_NONE)
+ {
+ 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)
+ {
+ gcmkONERROR(gckOS_CopyToUserData(
+ Kernel->os, * KernelPointer, UserPointer, Size
+ ));
+ }
+ }
+ else
+ {
+ /* Unmap record from kernel memory. */
+ gcmkONERROR(gckOS_UnmapUserPointer(
+ Kernel->os,
+ UserPointer,
+ Size,
+ * KernelPointer
+ ));
+ }
+
+ /* Reset the kernel pointer. */
+ * KernelPointer = gcvNULL;
+ }
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+void
+gckKERNEL_SetTimeOut(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 timeOut
+ )
+{
+ gcmkHEADER_ARG("Kernel=0x%x timeOut=%d", Kernel, timeOut);
+#if gcdGPU_TIMEOUT
+ Kernel->timeOut = timeOut;
+#endif
+ gcmkFOOTER_NO();
+}
+
+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;
+
+ gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
+ os, InUserSpace, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
+ gcmkVERIFY_ARGUMENT(*Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ gcmkONERROR(gckOS_Allocate(os,
+ sizeof(gckVIRTUAL_COMMAND_BUFFER),
+ (gctPOINTER)&buffer));
+
+ gcmkONERROR(gckOS_ZeroMemory(buffer, sizeof(gckVIRTUAL_COMMAND_BUFFER)));
+
+ buffer->bytes = bytes;
+
+ gcmkONERROR(gckOS_AllocatePagedMemoryEx(os,
+ flag,
+ bytes,
+ gcvNULL,
+ &buffer->physical));
+
+ if (InUserSpace)
+ {
+ gcmkONERROR(gckOS_CreateUserVirtualMapping(os,
+ buffer->physical,
+ bytes,
+ &logical,
+ &pageCount));
+
+ *Logical =
+ buffer->userLogical = logical;
+ }
+ else
+ {
+ gcmkONERROR(gckOS_CreateKernelVirtualMapping(os,
+ buffer->physical,
+ bytes,
+ &logical,
+ &pageCount));
+
+ *Logical =
+ buffer->kernelLogical = logical;
+ }
+
+ buffer->pageCount = pageCount;
+ buffer->kernel = Kernel;
+
+ gcmkONERROR(gckOS_GetProcessID(&buffer->pid));
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gcmkONERROR(gckKERNEL_GetProcessMMU(Kernel, &mmu));
+ buffer->mmu = mmu;
+#else
+ mmu = Kernel->mmu;
+#endif
+
+ gcmkONERROR(gckMMU_AllocatePages(mmu,
+ pageCount,
+ &buffer->pageTable,
+ &buffer->gpuAddress));
+
+
+ gcmkONERROR(gckOS_MapPagesEx(os,
+ Kernel->core,
+ buffer->physical,
+ pageCount,
+ buffer->gpuAddress,
+ buffer->pageTable));
+
+ gcmkONERROR(gckMMU_Flush(mmu, gcvSURF_INDEX));
+
+ *Physical = buffer;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "gpuAddress = %x pageCount = %d kernelLogical = %x userLogical=%x",
+ buffer->gpuAddress, buffer->pageCount,
+ buffer->kernelLogical, buffer->userLogical);
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(os, Kernel->virtualBufferLock, gcvINFINITE));
+
+ if (Kernel->virtualBufferHead == gcvNULL)
+ {
+ Kernel->virtualBufferHead =
+ Kernel->virtualBufferTail = buffer;
+ }
+ else
+ {
+ buffer->prev = Kernel->virtualBufferTail;
+ Kernel->virtualBufferTail->next = buffer;
+ Kernel->virtualBufferTail = buffer;
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Kernel->virtualBufferLock));
+
+ 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
+ }
+
+ 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;
+}
+
+gceSTATUS
+gckKERNEL_DestroyVirtualCommandBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ )
+{
+ gckOS os;
+ gckKERNEL kernel;
+ gckVIRTUAL_COMMAND_BUFFER_PTR buffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)Physical;
+
+ gcmkHEADER();
+ gcmkVERIFY_ARGUMENT(buffer != gcvNULL);
+
+ kernel = buffer->kernel;
+ os = kernel->os;
+
+ if (!buffer->userLogical)
+ {
+ gcmkVERIFY_OK(gckOS_DestroyKernelVirtualMapping(os,
+ buffer->physical,
+ Bytes,
+ Logical));
+ }
+
+#if !gcdPROCESS_ADDRESS_SPACE
+ gcmkVERIFY_OK(
+ gckMMU_FreePages(kernel->mmu, buffer->pageTable, buffer->pageCount));
+#endif
+
+ gcmkVERIFY_OK(gckOS_UnmapPages(os, buffer->pageCount, buffer->gpuAddress));
+
+ gcmkVERIFY_OK(gckOS_FreePagedMemory(os, buffer->physical, Bytes));
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(os, kernel->virtualBufferLock, gcvINFINITE));
+
+ if (buffer == kernel->virtualBufferHead)
+ {
+ if ((kernel->virtualBufferHead = buffer->next) == gcvNULL)
+ {
+ kernel->virtualBufferTail = gcvNULL;
+ }
+ }
+ else
+ {
+ buffer->prev->next = buffer->next;
+
+ if (buffer == kernel->virtualBufferTail)
+ {
+ kernel->virtualBufferTail = buffer->prev;
+ }
+ else
+ {
+ buffer->next->prev = buffer->prev;
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, kernel->virtualBufferLock));
+
+ gcmkVERIFY_OK(gckOS_Free(os, buffer));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckKERNEL_GetGPUAddress(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Logical,
+ IN gctBOOL InUserSpace,
+ IN gckVIRTUAL_COMMAND_BUFFER_PTR Buffer,
+ OUT gctUINT32 * Address
+ )
+{
+ gckVIRTUAL_COMMAND_BUFFER_PTR buffer = Buffer;
+ gctPOINTER start;
+
+ gcmkHEADER_ARG("Logical = %x InUserSpace=%d.", Logical, InUserSpace);
+
+ if (InUserSpace)
+ {
+ start = buffer->userLogical;
+ }
+ else
+ {
+ start = buffer->kernelLogical;
+ }
+
+ gcmkASSERT(Logical >= start
+ && (Logical < (gctPOINTER)((gctUINT8_PTR)start + buffer->pageCount * 4096)));
+
+ * Address = buffer->gpuAddress + (gctUINT32)((gctUINT8_PTR)Logical - (gctUINT8_PTR)start);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckKERNEL_QueryGPUAddress(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GpuAddress,
+ OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
+ )
+{
+ gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
+ gctUINT32 start;
+ gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, Kernel->virtualBufferLock, gcvINFINITE));
+
+ /* Walk all command buffers. */
+ for (buffer = Kernel->virtualBufferHead; buffer != gcvNULL; buffer = buffer->next)
+ {
+ start = (gctUINT32)buffer->gpuAddress;
+
+ if (GpuAddress >= start && GpuAddress < (start + buffer->pageCount * 4096))
+ {
+ /* Find a range matched. */
+ *Buffer = buffer;
+ status = gcvSTATUS_OK;
+ break;
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->virtualBufferLock));
+
+ return status;
+}
+
+#if gcdLINK_QUEUE_SIZE
+static void
+gckLINKQUEUE_Dequeue(
+ IN gckLINKQUEUE LinkQueue
+ )
+{
+ gcmkASSERT(LinkQueue->count == gcdLINK_QUEUE_SIZE);
+
+ LinkQueue->count--;
+ LinkQueue->front = (LinkQueue->front + 1) % gcdLINK_QUEUE_SIZE;
+}
+
+void
+gckLINKQUEUE_Enqueue(
+ IN gckLINKQUEUE LinkQueue,
+ IN gctUINT32 start,
+ IN gctUINT32 end,
+ IN gctUINT32 LinkLow,
+ IN gctUINT32 LinkHigh
+ )
+{
+ if (LinkQueue->count == gcdLINK_QUEUE_SIZE)
+ {
+ gckLINKQUEUE_Dequeue(LinkQueue);
+ }
+
+ gcmkASSERT(LinkQueue->count < gcdLINK_QUEUE_SIZE);
+
+ LinkQueue->count++;
+
+ LinkQueue->data[LinkQueue->rear].start = start;
+ LinkQueue->data[LinkQueue->rear].end = end;
+ LinkQueue->data[LinkQueue->rear].linkLow = LinkLow;
+ LinkQueue->data[LinkQueue->rear].linkHigh = LinkHigh;
+
+
+ gcmkVERIFY_OK(
+ gckOS_GetProcessID(&LinkQueue->data[LinkQueue->rear].pid));
+
+ LinkQueue->rear = (LinkQueue->rear + 1) % gcdLINK_QUEUE_SIZE;
+}
+
+void
+gckLINKQUEUE_GetData(
+ IN gckLINKQUEUE LinkQueue,
+ IN gctUINT32 Index,
+ OUT gckLINKDATA * Data
+ )
+{
+ gcmkASSERT(Index >= 0 && Index < gcdLINK_QUEUE_SIZE);
+
+ *Data = &LinkQueue->data[(Index + LinkQueue->front) % gcdLINK_QUEUE_SIZE];
+}
+#endif
+
+/*
+* gckENTRYQUEUE_Enqueue is called with Command->mutexQueue acquired.
+*/
+gceSTATUS
+gckENTRYQUEUE_Enqueue(
+ IN gckKERNEL Kernel,
+ IN gckENTRYQUEUE Queue,
+ IN gctUINT32 physical,
+ IN gctUINT32 bytes
+ )
+{
+ gctUINT32 next = (Queue->rear + 1) % gcdENTRY_QUEUE_SIZE;
+
+ if (next == Queue->front)
+ {
+ /* Queue is full. */
+ return gcvSTATUS_INVALID_REQUEST;
+ }
+
+ /* Copy data. */
+ Queue->data[Queue->rear].physical = physical;
+ Queue->data[Queue->rear].bytes = bytes;
+
+ gcmkVERIFY_OK(gckOS_MemoryBarrier(Kernel->os, &Queue->rear));
+
+ /* Update rear. */
+ Queue->rear = next;
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckENTRYQUEUE_Dequeue(
+ IN gckENTRYQUEUE Queue,
+ OUT gckENTRYDATA * Data
+ )
+{
+ if (Queue->front == Queue->rear)
+ {
+ /* Queue is empty. */
+ return gcvSTATUS_INVALID_REQUEST;
+ }
+
+ /* 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;
+
+ gcmkHEADER_ARG("Kernel=0x%08X Datbase=0x%08X", Kernel, Database);
+
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Database != gcvNULL);
+
+ /* Allocate a database. */
+ gcmkONERROR(gckOS_Allocate(
+ Kernel->os, gcmSIZEOF(gcsINTEGERDB), (gctPOINTER *)&database));
+
+ gcmkONERROR(gckOS_ZeroMemory(database, gcmSIZEOF(gcsINTEGERDB)));
+
+ /* Allocate a pointer table. */
+ gcmkONERROR(gckOS_Allocate(
+ Kernel->os, gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH, (gctPOINTER *)&database->table));
+
+ gcmkONERROR(gckOS_ZeroMemory(database->table, gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH));
+
+ /* Allocate a database mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Kernel->os, &database->mutex));
+
+ /* Initialize. */
+ database->currentID = 0;
+ database->unused = gcdID_TABLE_LENGTH;
+ database->os = Kernel->os;
+ database->tableLen = gcdID_TABLE_LENGTH;
+
+ *Database = database;
+
+ gcmkFOOTER_ARG("*Database=0x%08X", *Database);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Rollback. */
+ if (database)
+ {
+ if (database->table)
+ {
+ gcmkOS_SAFE_FREE(Kernel->os, database->table);
+ }
+
+ gcmkOS_SAFE_FREE(Kernel->os, database);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+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
+ )
+{
+ 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)
+ {
+ /* 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;
+ }
+
+ table = database->table;
+ currentID = database->currentID;
+ tableLen = database->tableLen;
+ unused = database->unused;
+
+ /* Connect id with pointer. */
+ table[currentID] = Pointer;
+
+ *Id = currentID + 1;
+
+ /* Update the currentID. */
+ if (--unused > 0)
+ {
+ for (i = 0; i < tableLen; i++)
+ {
+ if (++currentID >= tableLen)
+ {
+ /* Wrap to the begin. */
+ currentID = 0;
+ }
+
+ if (table[currentID] == gcvNULL)
+ {
+ break;
+ }
+ }
+ }
+
+ database->table = table;
+ database->currentID = currentID;
+ database->tableLen = tableLen;
+ database->unused = unused;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_ARG("*Id=%d", *Id);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_FreeIntegerId(
+ IN gctPOINTER Database,
+ IN gctUINT32 Id
+ )
+{
+ gceSTATUS status;
+ gckINTEGERDB database = Database;
+ gckOS os = database->os;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Database=0x%08X Id=%d", Database, Id);
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (!(Id > 0 && Id <= database->tableLen))
+ {
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+
+ Id -= 1;
+
+ database->table[Id] = gcvNULL;
+
+ if (database->unused++ == 0)
+ {
+ database->currentID = Id;
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_QueryIntegerId(
+ IN gctPOINTER Database,
+ IN gctUINT32 Id,
+ OUT gctPOINTER * Pointer
+ )
+{
+ gceSTATUS status;
+ gckINTEGERDB database = Database;
+ gctPOINTER pointer;
+ gckOS os = database->os;
+ 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;
+
+ if (!(Id > 0 && Id <= database->tableLen))
+ {
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+
+ Id -= 1;
+
+ pointer = database->table[Id];
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+ acquired = gcvFALSE;
+
+ if (pointer)
+ {
+ *Pointer = pointer;
+ }
+ else
+ {
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+
+ gcmkFOOTER_ARG("*Pointer=0x%08X", *Pointer);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+
+gctUINT32
+gckKERNEL_AllocateNameFromPointer(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Pointer
+ )
+{
+ gceSTATUS status;
+ gctUINT32 name;
+ gctPOINTER database = Kernel->db->pointerDatabase;
+
+ 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;
+}
+
+gctPOINTER
+gckKERNEL_QueryPointerFromName(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Name
+ )
+{
+ gceSTATUS status;
+ gctPOINTER pointer = gcvNULL;
+ gctPOINTER database = Kernel->db->pointerDatabase;
+
+ gcmkHEADER_ARG("Kernel=0x%X Name=%d", Kernel, Name);
+
+ /* Lookup in database to get pointer. */
+ gcmkONERROR(gckKERNEL_QueryIntegerId(database, Name, &pointer));
+
+ gcmkFOOTER_ARG("pointer=0x%X", pointer);
+ return pointer;
+
+OnError:
+ gcmkFOOTER();
+ return gcvNULL;
+}
+
+gceSTATUS
+gckKERNEL_DeleteName(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Name
+ )
+{
+ gctPOINTER database = Kernel->db->pointerDatabase;
+
+ 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;
+}
+
+gceSTATUS
+gckKERNEL_SetRecovery(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Recovery,
+ IN gctUINT32 StuckDump
+ )
+{
+ Kernel->recovery = Recovery;
+
+ if (Recovery == gcvFALSE)
+ {
+ /* Dump stuck information if Recovery is disabled. */
+ Kernel->stuckDump = gcmMAX(StuckDump, gcvSTUCK_DUMP_USER_COMMAND);
+ }
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+***** 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_CreateShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Size,
+ OUT gctSHBUF * ShBuf
+ )
+{
+ gceSTATUS status;
+ gcsSHBUF_PTR shBuf = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%X, Size=%u", Kernel, Size);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ if (Size == 0)
+ {
+ /* Invalid size. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+ else if (Size > 1024)
+ {
+ /* Limite shared buffer size. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Create a shared buffer structure. */
+ gcmkONERROR(
+ gckOS_Allocate(Kernel->os,
+ sizeof (gcsSHBUF),
+ (gctPOINTER *)&shBuf));
+
+ /* Initialize shared buffer. */
+ shBuf->id = 0;
+ shBuf->reference = gcvNULL;
+ shBuf->size = Size;
+ shBuf->data = gcvNULL;
+
+ /* Allocate integer id for this shared buffer. */
+ gcmkONERROR(
+ gckKERNEL_AllocateIntegerId(Kernel->db->pointerDatabase,
+ shBuf,
+ &shBuf->id));
+
+ /* Allocate atom. */
+ gcmkONERROR(gckOS_AtomConstruct(Kernel->os, &shBuf->reference));
+
+ /* Set default reference count to 1. */
+ gcmkVERIFY_OK(gckOS_AtomSet(Kernel->os, shBuf->reference, 1));
+
+ /* Return integer id. */
+ *ShBuf = (gctSHBUF)(gctUINTPTR_T)shBuf->id;
+
+ gcmkFOOTER_ARG("*ShBuf=%u", shBuf->id);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Error roll back. */
+ if (shBuf != gcvNULL)
+ {
+ if (shBuf->id != 0)
+ {
+ gcmkVERIFY_OK(
+ gckKERNEL_FreeIntegerId(Kernel->db->pointerDatabase,
+ shBuf->id));
+ }
+
+ 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_DestroyShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSHBUF ShBuf
+ )
+{
+ gceSTATUS status;
+ gcsSHBUF_PTR shBuf;
+ gctINT32 oldValue = 0;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u",
+ Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
+
+ /* Acquire mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os,
+ Kernel->db->pointerDatabaseMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Find shared buffer structure. */
+ gcmkONERROR(
+ gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
+ (gctUINT32)(gctUINTPTR_T)ShBuf,
+ (gctPOINTER)&shBuf));
+
+ gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
+
+ /* Decrease the reference count. */
+ gckOS_AtomDecrement(Kernel->os, shBuf->reference, &oldValue);
+
+ if (oldValue == 1)
+ {
+ /* Free integer id. */
+ gcmkVERIFY_OK(
+ gckKERNEL_FreeIntegerId(Kernel->db->pointerDatabase,
+ shBuf->id));
+
+ /* Free atom. */
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, shBuf->reference));
+
+ if (shBuf->data)
+ {
+ gcmkOS_SAFE_FREE(Kernel->os, shBuf->data);
+ shBuf->data = gcvNULL;
+ }
+
+ /* Free the shared buffer. */
+ gcmkOS_SAFE_FREE(Kernel->os, shBuf);
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* 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_MapShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSHBUF ShBuf
+ )
+{
+ gceSTATUS status;
+ gcsSHBUF_PTR shBuf;
+ gctINT32 oldValue = 0;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u",
+ Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
+
+ /* Acquire mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os,
+ Kernel->db->pointerDatabaseMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Find shared buffer structure. */
+ gcmkONERROR(
+ gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
+ (gctUINT32)(gctUINTPTR_T)ShBuf,
+ (gctPOINTER)&shBuf));
+
+ gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
+
+ /* Increase the reference count. */
+ gckOS_AtomIncrement(Kernel->os, shBuf->reference, &oldValue);
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* 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_WriteShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSHBUF ShBuf,
+ IN gctPOINTER UserData,
+ IN gctUINT32 ByteCount
+ )
+{
+ gceSTATUS status;
+ gcsSHBUF_PTR shBuf;
+ gctBOOL acquired = gcvFALSE;
+
+ 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(
+ gckOS_AcquireMutex(Kernel->os,
+ Kernel->db->pointerDatabaseMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Find shared buffer structure. */
+ gcmkONERROR(
+ gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
+ (gctUINT32)(gctUINTPTR_T)ShBuf,
+ (gctPOINTER)&shBuf));
+
+ gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
+
+ if ((ByteCount > shBuf->size) ||
+ (ByteCount == 0) ||
+ (UserData == gcvNULL))
+ {
+ /* Exceeds buffer max size or invalid. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (shBuf->data == gcvNULL)
+ {
+ /* Allocate buffer data when first time write. */
+ gcmkONERROR(gckOS_Allocate(Kernel->os, ByteCount, &shBuf->data));
+ }
+
+ /* 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)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** 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 gctSHBUF ShBuf,
+ IN gctPOINTER UserData,
+ IN gctUINT32 ByteCount,
+ OUT gctUINT32 * BytesRead
+ )
+{
+ gceSTATUS status;
+ gcsSHBUF_PTR shBuf;
+ gctUINT32 bytes;
+ gctBOOL acquired = gcvFALSE;
+
+ 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(
+ gckOS_AcquireMutex(Kernel->os,
+ Kernel->db->pointerDatabaseMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Find shared buffer structure. */
+ gcmkONERROR(
+ gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
+ (gctUINT32)(gctUINTPTR_T)ShBuf,
+ (gctPOINTER)&shBuf));
+
+ gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
+
+ if (shBuf->data == gcvNULL)
+ {
+ *BytesRead = 0;
+
+ /* No data in shared buffer, skip copy. */
+ status = gcvSTATUS_SKIP;
+ goto OnError;
+ }
+ else if (ByteCount == 0)
+ {
+ /* Invalid size to read. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Determine bytes to copy. */
+ bytes = (ByteCount < shBuf->size) ? ByteCount : shBuf->size;
+
+ /* Copy data to user. */
+ gcmkONERROR(
+ gckOS_CopyToUserData(Kernel->os,
+ shBuf->data,
+ UserData,
+ bytes));
+
+ /* Return copied size. */
+ *BytesRead = bytes;
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_ARG("*BytesRead=%u", bytes);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************\
+********************************* Fence *****************************************
+\*******************************************************************************/
+
+gceSTATUS
+gckFENCE_Create(
+ IN gckOS Os,
+ IN gckKERNEL Kernel,
+ OUT gckFENCE * Fence
+ )
+{
+ gceSTATUS status;
+ gckFENCE fence = gcvNULL;
+ gctSIZE_T pageSize = 4096;
+
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsFENCE), (gctPOINTER *)&fence));
+
+ gcmkONERROR(gckOS_CreateMutex(Os, (gctPOINTER *)&fence->mutex));
+
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(
+ Os,
+ gcvFALSE,
+ &pageSize,
+ &fence->physical,
+ &fence->logical
+ ));
+
+ gcmkONERROR(gckHARDWARE_ConvertLogical(
+ Kernel->hardware,
+ fence->logical,
+ gcvFALSE,
+ &fence->address
+ ));
+
+ *Fence = fence;
+
+ return gcvSTATUS_OK;
+OnError:
+ if (fence)
+ {
+ gckFENCE_Destory(Os, fence);
+ }
+
+ return status;
+}
+
+gceSTATUS
+gckFENCE_Destory(
+ IN gckOS Os,
+ OUT gckFENCE Fence
+ )
+{
+ if (Fence->mutex)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Fence->mutex));
+ }
+
+ if (Fence->logical)
+ {
+ gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+ Os,
+ 4096,
+ Fence->physical,
+ Fence->logical
+ ));
+ }
+
+ gcmkOS_SAFE_FREE(Os, Fence);
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+***** Test Code ****************************************************************
+*******************************************************************************/
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
new file mode 100644
index 000000000000..c04f1f849b6c
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
@@ -0,0 +1,1584 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_h_
+#define __gc_hal_kernel_h_
+
+#include "gc_hal.h"
+#include "gc_hal_kernel_hardware.h"
+#include "gc_hal_driver.h"
+
+#include "gc_hal_kernel_mutex.h"
+
+#if gcdENABLE_VG
+#include "gc_hal_kernel_vg.h"
+#endif
+
+#if gcdSECURITY
+#include "gc_hal_security_interface.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+***** New MMU Defination *******************************************************/
+#define gcdMMU_MTLB_SHIFT 22
+#define gcdMMU_STLB_4K_SHIFT 12
+#define gcdMMU_STLB_64K_SHIFT 16
+
+#define gcdMMU_MTLB_BITS (32 - gcdMMU_MTLB_SHIFT)
+#define gcdMMU_PAGE_4K_BITS gcdMMU_STLB_4K_SHIFT
+#define gcdMMU_STLB_4K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_4K_BITS)
+#define gcdMMU_PAGE_64K_BITS gcdMMU_STLB_64K_SHIFT
+#define gcdMMU_STLB_64K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_64K_BITS)
+
+#define gcdMMU_MTLB_ENTRY_NUM (1 << gcdMMU_MTLB_BITS)
+#define gcdMMU_MTLB_SIZE (gcdMMU_MTLB_ENTRY_NUM << 2)
+#define gcdMMU_STLB_4K_ENTRY_NUM (1 << gcdMMU_STLB_4K_BITS)
+#define gcdMMU_STLB_4K_SIZE (gcdMMU_STLB_4K_ENTRY_NUM << 2)
+#define gcdMMU_PAGE_4K_SIZE (1 << gcdMMU_STLB_4K_SHIFT)
+#define gcdMMU_STLB_64K_ENTRY_NUM (1 << gcdMMU_STLB_64K_BITS)
+#define gcdMMU_STLB_64K_SIZE (gcdMMU_STLB_64K_ENTRY_NUM << 2)
+#define gcdMMU_PAGE_64K_SIZE (1 << gcdMMU_STLB_64K_SHIFT)
+
+#define gcdMMU_MTLB_MASK (~((1U << gcdMMU_MTLB_SHIFT)-1))
+#define gcdMMU_STLB_4K_MASK ((~0U << gcdMMU_STLB_4K_SHIFT) ^ gcdMMU_MTLB_MASK)
+#define gcdMMU_PAGE_4K_MASK (gcdMMU_PAGE_4K_SIZE - 1)
+#define gcdMMU_STLB_64K_MASK ((~((1U << gcdMMU_STLB_64K_SHIFT)-1)) ^ gcdMMU_MTLB_MASK)
+#define gcdMMU_PAGE_64K_MASK (gcdMMU_PAGE_64K_SIZE - 1)
+
+/* Page offset definitions. */
+#define gcdMMU_OFFSET_4K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_STLB_4K_BITS)
+#define gcdMMU_OFFSET_4K_MASK ((1U << gcdMMU_OFFSET_4K_BITS) - 1)
+#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 ********************************************************/
+
+/* Dump nonthing when stuck happens. */
+#define gcvSTUCK_DUMP_NONE 0
+
+/* Dump GPU state and memory near stuck point. */
+#define gcvSTUCK_DUMP_NEARBY_MEMORY 1
+
+/* Beside gcvSTUCK_DUMP_NEARBY_MEMORY, dump context buffer and user command buffer. */
+#define gcvSTUCK_DUMP_USER_COMMAND 2
+
+/* Beside gcvSTUCK_DUMP_USER_COMMAND, commit will be stall
+** to make sure command causing stuck isn't missed. */
+#define gcvSTUCK_DUMP_STALL_COMMAND 3
+
+/* Beside gcvSTUCK_DUMP_USER_COMMAND, dump kernel command buffer. */
+#define gcvSTUCK_DUMP_ALL_COMMAND 4
+
+/*******************************************************************************
+***** Process Secure Cache ****************************************************/
+
+#define gcdSECURE_CACHE_LRU 1
+#define gcdSECURE_CACHE_LINEAR 2
+#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
+{
+ /* Logical address. */
+ gctPOINTER logical;
+
+ /* DMAable address. */
+ gctUINT32 dma;
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ /* Pointer to the previous and next hash tables. */
+ gcskLOGICAL_CACHE_PTR nextHash;
+ gcskLOGICAL_CACHE_PTR prevHash;
+#endif
+
+#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
+ /* Pointer to the previous and next slot. */
+ gcskLOGICAL_CACHE_PTR next;
+ gcskLOGICAL_CACHE_PTR prev;
+#endif
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
+ /* Time stamp. */
+ gctUINT64 stamp;
+#endif
+};
+
+typedef struct _gcskSECURE_CACHE * gcskSECURE_CACHE_PTR;
+typedef struct _gcskSECURE_CACHE
+{
+ /* Cache memory. */
+ gcskLOGICAL_CACHE cache[1 + gcdSECURE_CACHE_SLOTS];
+
+ /* Last known index for LINEAR mode. */
+ gcskLOGICAL_CACHE_PTR cacheIndex;
+
+ /* Current free slot for LINEAR mode. */
+ gctUINT32 cacheFree;
+
+ /* Time stamp for LINEAR mode. */
+ gctUINT64 cacheStamp;
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ /* Hash table for HASH mode. */
+ gcskLOGICAL_CACHE hash[256];
+#endif
+}
+gcskSECURE_CACHE;
+
+/*******************************************************************************
+***** Process Database Management *********************************************/
+
+typedef enum _gceDATABASE_TYPE
+{
+ gcvDB_VIDEO_MEMORY = 1, /* Video memory created. */
+ gcvDB_COMMAND_BUFFER, /* Command Buffer. */
+ gcvDB_NON_PAGED, /* Non paged memory. */
+ gcvDB_CONTIGUOUS, /* Contiguous memory. */
+ gcvDB_SIGNAL, /* Signal. */
+ gcvDB_VIDEO_MEMORY_LOCKED, /* Video memory locked. */
+ gcvDB_CONTEXT, /* Context */
+ gcvDB_IDLE, /* GPU idle. */
+ gcvDB_MAP_MEMORY, /* Map memory */
+ gcvDB_MAP_USER_MEMORY, /* Map user memory */
+ gcvDB_SYNC_POINT, /* Sync point. */
+ 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
+{
+ /* Pointer to kernel. */
+ gckKERNEL kernel;
+
+ /* Pointer to next database record. */
+ gcsDATABASE_RECORD_PTR next;
+
+ /* Type of record. */
+ gceDATABASE_TYPE type;
+
+ /* Data for record. */
+ gctPOINTER data;
+ gctPHYS_ADDR physical;
+ gctSIZE_T bytes;
+}
+gcsDATABASE_RECORD;
+
+typedef struct _gcsDATABASE * gcsDATABASE_PTR;
+typedef struct _gcsDATABASE
+{
+ /* Pointer to next entry is hash list. */
+ gcsDATABASE_PTR next;
+ gctSIZE_T slot;
+
+ /* Process ID. */
+ gctUINT32 processID;
+
+ /* Sizes to query. */
+ gcsDATABASE_COUNTERS vidMem;
+ gcsDATABASE_COUNTERS nonPaged;
+ gcsDATABASE_COUNTERS contiguous;
+ gcsDATABASE_COUNTERS mapUserMemory;
+ gcsDATABASE_COUNTERS mapMemory;
+ 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;
+ gctUINT64 idle;
+
+ /* Pointer to database. */
+ gcsDATABASE_RECORD_PTR list[48];
+
+#if gcdSECURE_USER
+ /* Secure cache. */
+ gcskSECURE_CACHE cache;
+#endif
+
+ 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(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID
+ );
+
+/* Add a record to the process database. */
+gceSTATUS
+gckKERNEL_AddProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Pointer,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Size
+ );
+
+/* Remove a record to the process database. */
+gceSTATUS
+gckKERNEL_RemoveProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Pointer
+ );
+
+/* Destroy the process database. */
+gceSTATUS
+gckKERNEL_DestroyProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID
+ );
+
+/* Find a record to the process database. */
+gceSTATUS
+gckKERNEL_FindProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 ThreadID,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Pointer,
+ OUT gcsDATABASE_RECORD_PTR Record
+ );
+
+/* Query the process database. */
+gceSTATUS
+gckKERNEL_QueryProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctBOOL LastProcessID,
+ IN gceDATABASE_TYPE Type,
+ OUT gcuDATABASE_INFO * Info
+ );
+
+/* Dump the process database. */
+gceSTATUS
+gckKERNEL_DumpProcessDB(
+ IN gckKERNEL Kernel
+ );
+
+/* 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,
+ OUT gctPOINTER * Database
+ );
+
+gceSTATUS
+gckKERNEL_DestroyIntegerDatabase(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Database
+ );
+
+gceSTATUS
+gckKERNEL_AllocateIntegerId(
+ IN gctPOINTER Database,
+ IN gctPOINTER Pointer,
+ OUT gctUINT32 * Id
+ );
+
+gceSTATUS
+gckKERNEL_FreeIntegerId(
+ IN gctPOINTER Database,
+ IN gctUINT32 Id
+ );
+
+gceSTATUS
+gckKERNEL_QueryIntegerId(
+ IN gctPOINTER Database,
+ IN gctUINT32 Id,
+ OUT gctPOINTER * Pointer
+ );
+
+/* Pointer rename */
+gctUINT32
+gckKERNEL_AllocateNameFromPointer(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Pointer
+ );
+
+gctPOINTER
+gckKERNEL_QueryPointerFromName(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Name
+ );
+
+gceSTATUS
+gckKERNEL_DeleteName(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Name
+ );
+
+#if gcdSECURE_USER
+/* Get secure cache from the process database. */
+gceSTATUS
+gckKERNEL_GetProcessDBCache(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ OUT gcskSECURE_CACHE_PTR * Cache
+ );
+#endif
+
+/*******************************************************************************
+********* Timer Management ****************************************************/
+typedef struct _gcsTIMER * gcsTIMER_PTR;
+typedef struct _gcsTIMER
+{
+ /* Start and Stop time holders. */
+ gctUINT64 startTime;
+ gctUINT64 stopTime;
+}
+gcsTIMER;
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+/* gckDB object. */
+struct _gckDB
+{
+ /* Database management. */
+ gcsDATABASE_PTR db[16];
+ gctPOINTER dbMutex;
+ gcsDATABASE_PTR freeDatabase;
+ gcsDATABASE_RECORD_PTR freeRecord;
+ gcsDATABASE_PTR lastDatabase;
+ gctUINT32 lastProcessID;
+ gctUINT64 lastIdle;
+ gctUINT64 idleTime;
+ gctUINT64 lastSlowdown;
+ gctUINT64 lastSlowdownIdle;
+ gctPOINTER nameDatabase;
+ gctPOINTER nameDatabaseMutex;
+
+ gctPOINTER pointerDatabase;
+ gctPOINTER pointerDatabaseMutex;
+};
+
+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;
+ gctUINT pid;
+ gckVIRTUAL_COMMAND_BUFFER_PTR next;
+ gckVIRTUAL_COMMAND_BUFFER_PTR prev;
+ gckKERNEL kernel;
+#if gcdPROCESS_ADDRESS_SPACE
+ gckMMU mmu;
+#endif
+}
+gckVIRTUAL_COMMAND_BUFFER;
+
+/* gckKERNEL object. */
+struct _gckKERNEL
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Core */
+ gceCORE core;
+
+ /* Pointer to gckHARDWARE object. */
+ gckHARDWARE hardware;
+
+ /* Pointer to gckCOMMAND object. */
+ gckCOMMAND command;
+
+ /* Pointer to gckEVENT object. */
+ gckEVENT eventObj;
+
+ /* Pointer to context. */
+ gctPOINTER context;
+
+ /* Pointer to gckMMU object. */
+ gckMMU mmu;
+
+ /* Arom holding number of clients. */
+ gctPOINTER atomClients;
+
+#if VIVANTE_PROFILER
+ /* Enable profiling */
+ gctBOOL profileEnable;
+ /* Clear profile register or not*/
+ gctBOOL profileCleanRegister;
+#endif
+
+#ifdef QNX_SINGLE_THREADED_DEBUGGING
+ gctPOINTER debugMutex;
+#endif
+
+ /* Database management. */
+ gckDB db;
+ gctBOOL dbCreated;
+
+ gctUINT64 resetTimeStamp;
+
+ /* Pointer to gckEVENT object. */
+ gcsTIMER timers[8];
+ gctUINT32 timeOut;
+
+#if gcdENABLE_VG
+ gckVGKERNEL vg;
+#endif
+
+ /* Virtual command buffer list. */
+ gckVIRTUAL_COMMAND_BUFFER_PTR virtualBufferHead;
+ gckVIRTUAL_COMMAND_BUFFER_PTR virtualBufferTail;
+ gctPOINTER virtualBufferLock;
+
+ /* Enable virtual command buffer. */
+ gctBOOL virtualCommandBuffer;
+
+#if gcdDVFS
+ gckDVFS dvfs;
+#endif
+
+#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
+{
+ gctUINT32 frequency;
+ gctUINT32 count;
+};
+
+/* gckDVFS object. */
+struct _gckDVFS
+{
+ gckOS os;
+ gckHARDWARE hardware;
+ gctPOINTER timer;
+ gctUINT32 pollingTime;
+ gctBOOL stop;
+ gctUINT32 totalConfig;
+ gctUINT32 loads[8];
+ gctUINT8 currentScale;
+ struct _FrequencyHistory frequencyHistory[16];
+};
+
+typedef struct _gcsFENCE * gckFENCE;
+typedef struct _gcsFENCE
+{
+ /* Fence location. */
+ gctPHYS_ADDR physical;
+ gctPOINTER logical;
+ gctUINT32 address;
+
+ gctPOINTER mutex;
+}
+gcsFENCE;
+
+/* gckCOMMAND object. */
+struct _gckCOMMAND
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to required object. */
+ gckKERNEL kernel;
+ gckOS os;
+
+ /* Number of bytes per page. */
+ gctUINT32 pageSize;
+
+ /* Current pipe select. */
+ gcePIPE_SELECT pipeSelect;
+
+ /* Command queue running flag. */
+ gctBOOL running;
+
+ /* Idle flag and commit stamp. */
+ gctBOOL idle;
+ gctUINT64 commitStamp;
+
+ /* Command queue mutex. */
+ gctPOINTER mutexQueue;
+
+ /* Context switching mutex. */
+ gctPOINTER mutexContext;
+
+#if VIVANTE_PROFILER_CONTEXT
+ /* Context sequence mutex. */
+ gctPOINTER mutexContextSeq;
+#endif
+
+ /* Command queue power semaphore. */
+ gctPOINTER powerSemaphore;
+
+ /* Current command queue. */
+ struct _gcskCOMMAND_QUEUE
+ {
+ gctSIGNAL signal;
+ gctPHYS_ADDR physical;
+ gctPOINTER logical;
+ gctUINT32 address;
+ }
+ queues[gcdCOMMAND_QUEUES];
+
+ gctUINT32 physical;
+ gctPOINTER logical;
+ gctUINT32 address;
+ gctUINT32 offset;
+ gctINT index;
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gctUINT wrapCount;
+#endif
+
+ /* The command queue is new. */
+ gctBOOL newQueue;
+
+ /* Context management. */
+ gckCONTEXT currContext;
+ gctPOINTER stateMap;
+
+ /* Pointer to last WAIT command. */
+ gctUINT32 waitPhysical;
+ gctPOINTER waitLogical;
+ gctUINT32 waitSize;
+
+ /* Command buffer alignment. */
+ gctUINT32 alignment;
+ gctUINT32 reservedHead;
+ gctUINT32 reservedTail;
+
+ /* Commit counter. */
+ gctPOINTER atomCommit;
+
+ /* Kernel process ID. */
+ gctUINT32 kernelProcessID;
+
+ /* End Event signal. */
+ gctSIGNAL endEventSignal;
+
+#if gcdSECURE_USER
+ /* Hint array copy buffer. */
+ gctBOOL hintArrayAllocated;
+ gctUINT hintArraySize;
+ gctUINT32_PTR hintArray;
+#endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gckMMU currentMmu;
+#endif
+ struct _gckENTRYQUEUE queue;
+
+ gckFENCE fence;
+};
+
+typedef struct _gcsEVENT * gcsEVENT_PTR;
+
+/* Structure holding one event to be processed. */
+typedef struct _gcsEVENT
+{
+ /* Pointer to next event in queue. */
+ gcsEVENT_PTR next;
+
+ /* Event information. */
+ gcsHAL_INTERFACE info;
+
+ /* Process ID owning the event. */
+ gctUINT32 processID;
+
+#ifdef __QNXNTO__
+ /* Kernel. */
+ gckKERNEL kernel;
+#endif
+
+ gctBOOL fromKernel;
+}
+gcsEVENT;
+
+/* Structure holding a list of events to be processed by an interrupt. */
+typedef struct _gcsEVENT_QUEUE * gcsEVENT_QUEUE_PTR;
+typedef struct _gcsEVENT_QUEUE
+{
+ /* Time stamp. */
+ gctUINT64 stamp;
+
+ /* Source of the event. */
+ gceKERNEL_WHERE source;
+
+#if gcdMULTI_GPU
+ /* Which chip(s) of the event */
+ gceCORE_3D_MASK chipEnable;
+#endif
+
+ /* Pointer to head of event queue. */
+ gcsEVENT_PTR head;
+
+ /* Pointer to tail of event queue. */
+ gcsEVENT_PTR tail;
+
+ /* Next list of events. */
+ gcsEVENT_QUEUE_PTR next;
+
+ /* Current commit stamp. */
+ gctUINT64 commitStamp;
+}
+gcsEVENT_QUEUE;
+
+/*
+ gcdREPO_LIST_COUNT defines the maximum number of event queues with different
+ hardware module sources that may coexist at the same time. Only two sources
+ are supported - gcvKERNEL_COMMAND and gcvKERNEL_PIXEL. gcvKERNEL_COMMAND
+ source is used only for managing the kernel command queue and is only issued
+ when the current command queue gets full. Since we commit event queues every
+ time we commit command buffers, in the worst case we can have up to three
+ pending event queues:
+ - gcvKERNEL_PIXEL
+ - gcvKERNEL_COMMAND (queue overflow)
+ - gcvKERNEL_PIXEL
+*/
+#define gcdREPO_LIST_COUNT 3
+
+/* gckEVENT object. */
+struct _gckEVENT
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to required objects. */
+ gckOS os;
+ gckKERNEL kernel;
+
+ /* Time stamp. */
+ gctUINT64 stamp;
+ gctUINT32 lastCommitStamp;
+
+ /* Queue mutex. */
+ gctPOINTER eventQueueMutex;
+
+ /* Array of event queues. */
+ 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;
+ gctSIZE_T freeEventCount;
+ gctPOINTER freeEventMutex;
+
+ /* Event queues. */
+ gcsEVENT_QUEUE_PTR queueHead;
+ gcsEVENT_QUEUE_PTR queueTail;
+ gcsEVENT_QUEUE_PTR freeList;
+ gcsEVENT_QUEUE repoList[gcdREPO_LIST_COUNT];
+ gctPOINTER eventListMutex;
+
+ gctPOINTER submitTimer;
+
+#if gcdINTERRUPT_STATISTIC
+ gctPOINTER interruptCount;
+#endif
+
+#if gcdRECORD_COMMAND
+ gckRECORDER recorder;
+#endif
+};
+
+/* Free all events belonging to a process. */
+gceSTATUS
+gckEVENT_FreeProcess(
+ IN gckEVENT Event,
+ IN gctUINT32 ProcessID
+ );
+
+gceSTATUS
+gckEVENT_Stop(
+ IN gckEVENT Event,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle,
+ IN gctPOINTER Logical,
+ IN gctSIGNAL Signal,
+ IN OUT gctUINT32 * waitSize
+ );
+
+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
+{
+ /* Allocated from gckVIDMEM. */
+ struct _gcsVIDMEM_NODE_VIDMEM
+ {
+ /* Owner of this node. */
+ gckVIDMEM memory;
+
+ /* Dual-linked list of nodes. */
+ gcuVIDMEM_NODE_PTR next;
+ gcuVIDMEM_NODE_PTR prev;
+
+ /* Dual linked list of free nodes. */
+ gcuVIDMEM_NODE_PTR nextFree;
+ gcuVIDMEM_NODE_PTR prevFree;
+
+ /* Information for this node. */
+ gctSIZE_T offset;
+ gctSIZE_T bytes;
+ gctUINT32 alignment;
+
+#ifdef __QNXNTO__
+ /* Client virtual address. */
+ gctPOINTER logical;
+#endif
+
+ /* Locked counter. */
+ gctINT32 locked;
+
+ /* Memory pool. */
+ gcePOOL pool;
+ gctUINT32 physical;
+
+ /* Process ID owning this memory. */
+ gctUINT32 processID;
+
+#if gcdENABLE_VG
+ gctPOINTER kernelVirtual;
+#endif
+ }
+ VidMem;
+
+ /* Allocated from gckOS. */
+ struct _gcsVIDMEM_NODE_VIRTUAL
+ {
+ /* Pointer to gckKERNEL object. */
+ gckKERNEL kernel;
+
+ /* Information for this node. */
+ /* Contiguously allocated? */
+ gctBOOL contiguous;
+ /* mdl record pointer... a kmalloc address. Process agnostic. */
+ gctPHYS_ADDR physical;
+ gctSIZE_T bytes;
+ /* do_mmap_pgoff address... mapped per-process. */
+ gctPOINTER logical;
+
+#if gcdENABLE_VG
+ /* Physical address of this node, only meaningful when it is contiguous. */
+ gctUINT64 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;
+
+ /* Used only when node is not contiguous */
+ gctPOINTER pageTables[gcdMAX_GPU_COUNT];
+ /* Pointer to gckKERNEL object who lock this. */
+ gckKERNEL lockKernels[gcdMAX_GPU_COUNT];
+ /* Actual physical address */
+ gctUINT32 addresses[gcdMAX_GPU_COUNT];
+
+ /* Locked counter. */
+ gctINT32 lockeds[gcdMAX_GPU_COUNT];
+
+ /* Process ID owning this memory. */
+ gctUINT32 processID;
+
+ /* Surface type. */
+ gceSURF_TYPE type;
+ }
+ Virtual;
+}
+gcuVIDMEM_NODE;
+
+/* gckVIDMEM object. */
+struct _gckVIDMEM
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Information for this video memory heap. */
+ gctUINT32 baseAddress;
+ gctSIZE_T bytes;
+ gctSIZE_T freeBytes;
+
+ /* Mapping for each type of surface. */
+ gctINT mapping[gcvSURF_NUM_TYPES];
+
+ /* Sentinel nodes for up to 8 banks. */
+ gcuVIDMEM_NODE sentinel[8];
+
+ /* Allocation threshold. */
+ gctSIZE_T threshold;
+
+ /* The heap mutex. */
+ gctPOINTER mutex;
+};
+
+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 gcdPROCESS_ADDRESS_SPACE
+ /* Head of mapping list. */
+ gcsGPU_MAP_PTR mapHead;
+
+ /* 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
+ );
+
+gceSTATUS
+gckVIDMEM_ConstructVirtualFromUserMemory(
+ IN gckKERNEL Kernel,
+ IN gcsUSER_MEMORY_DESC_PTR Desc,
+ OUT gcuVIDMEM_NODE_PTR * Node
+ );
+
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+gckEVENT_DestroyMmu(
+ IN gckEVENT Event,
+ IN gckMMU Mmu,
+ IN gceKERNEL_WHERE FromWhere
+ );
+#endif
+
+/* gckMMU object. */
+struct _gckMMU
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Pointer to gckHARDWARE object. */
+ gckHARDWARE hardware;
+
+ /* The page table mutex. */
+ gctPOINTER pageTableMutex;
+
+ /* Page table information. */
+ gctSIZE_T pageTableSize;
+ gctPHYS_ADDR pageTablePhysical;
+ gctUINT32_PTR pageTableLogical;
+ gctUINT32 pageTableEntries;
+
+ /* Master TLB information. */
+ gctSIZE_T mtlbSize;
+ gctPHYS_ADDR mtlbPhysical;
+ gctUINT32_PTR mtlbLogical;
+ gctUINT32 mtlbEntries;
+
+ /* Free entries. */
+ gctUINT32 heapList;
+ gctBOOL freeNodes;
+
+ gctPOINTER staticSTLB;
+ gctBOOL enabled;
+
+ gctUINT32 dynamicMappingStart;
+
+ gctUINT32_PTR mapLogical;
+#if gcdPROCESS_ADDRESS_SPACE
+ gctPOINTER pageTableDirty[gcdMAX_GPU_COUNT];
+ gctPOINTER stlbs;
+#endif
+};
+
+gceSTATUS
+gckOS_CreateKernelVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ 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,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+gceSTATUS
+gckKERNEL_DestroyVirtualCommandBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ );
+
+gceSTATUS
+gckKERNEL_GetGPUAddress(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Logical,
+ IN gctBOOL InUserSpace,
+ IN gckVIRTUAL_COMMAND_BUFFER_PTR Buffer,
+ OUT gctUINT32 * Address
+ );
+
+gceSTATUS
+gckKERNEL_QueryGPUAddress(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GpuAddress,
+ OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
+ );
+
+gceSTATUS
+gckKERNEL_AttachProcess(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Attach
+ );
+
+gceSTATUS
+gckKERNEL_AttachProcessEx(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Attach,
+ IN gctUINT32 PID
+ );
+
+#if gcdSECURE_USER
+gceSTATUS
+gckKERNEL_MapLogicalToPhysical(
+ IN gckKERNEL Kernel,
+ IN gcskSECURE_CACHE_PTR Cache,
+ IN OUT gctPOINTER * Data
+ );
+
+gceSTATUS
+gckKERNEL_FlushTranslationCache(
+ IN gckKERNEL Kernel,
+ IN gcskSECURE_CACHE_PTR Cache,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryIdle(
+ IN gckHARDWARE Hardware,
+ OUT gctBOOL_PTR IsIdle
+ );
+
+gceSTATUS
+gckHARDWARE_AddressInHardwareFuncions(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gctPOINTER *Pointer
+ );
+
+#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 *******************************
+\******************************************************************************/
+
+gceSTATUS
+gckCONTEXT_Construct(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 ProcessID,
+ OUT gckCONTEXT * Context
+ );
+
+gceSTATUS
+gckCONTEXT_Destroy(
+ IN gckCONTEXT Context
+ );
+
+gceSTATUS
+gckCONTEXT_Update(
+ IN gckCONTEXT Context,
+ IN gctUINT32 ProcessID,
+ IN gcsSTATE_DELTA_PTR StateDelta
+ );
+
+gceSTATUS
+gckCONTEXT_MapBuffer(
+ IN gckCONTEXT Context,
+ OUT gctUINT32 *Physicals,
+ OUT gctUINT64 *Logicals,
+ OUT gctUINT32 *Bytes
+ );
+
+#if gcdLINK_QUEUE_SIZE
+void
+gckLINKQUEUE_Enqueue(
+ IN gckLINKQUEUE LinkQueue,
+ IN gctUINT32 start,
+ IN gctUINT32 end,
+ IN gctUINT32 LinkLow,
+ IN gctUINT32 LinkHigh
+ );
+
+void
+gckLINKQUEUE_GetData(
+ IN gckLINKQUEUE LinkQueue,
+ IN gctUINT32 Index,
+ OUT gckLINKDATA * Data
+ );
+#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
+ );
+
+gceSTATUS
+gckFENCE_Create(
+ IN gckOS Os,
+ IN gckKERNEL Kernel,
+ OUT gckFENCE * Fence
+ );
+
+gceSTATUS
+gckFENCE_Destory(
+ IN gckOS Os,
+ OUT gckFENCE Fence
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
new file mode 100644
index 000000000000..2c322d153305
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
@@ -0,0 +1,3496 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+#include "gc_hal_kernel_context.h"
+
+#define _GC_OBJ_ZONE gcvZONE_COMMAND
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** _NewQueue
+**
+** Allocate a new command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** OUTPUT:
+**
+** gckCOMMAND Command
+** gckCOMMAND object has been updated with a new command queue.
+*/
+static gceSTATUS
+_NewQueue(
+ IN OUT gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gctINT currentIndex, newIndex;
+ gctPHYS_ADDR_T physical;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Switch to the next command buffer. */
+ currentIndex = Command->index;
+ newIndex = (currentIndex + 1) % gcdCOMMAND_QUEUES;
+
+ /* Wait for availability. */
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.waitsignal]");
+#endif
+
+ gcmkONERROR(gckOS_WaitSignal(
+ Command->os,
+ Command->queues[newIndex].signal,
+ gcvINFINITE
+ ));
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ if (newIndex < currentIndex)
+ {
+ Command->wrapCount += 1;
+
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_COMMAND,
+ 2 * 4,
+ "%s(%d): queue array wrapped around.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_COMMAND,
+ 3 * 4,
+ "%s(%d): total queue wrap arounds %d.\n",
+ __FUNCTION__, __LINE__, Command->wrapCount
+ );
+
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_COMMAND,
+ 3 * 4,
+ "%s(%d): switched to queue %d.\n",
+ __FUNCTION__, __LINE__, newIndex
+ );
+#endif
+
+ /* Update gckCOMMAND object with new command queue. */
+ Command->index = newIndex;
+ Command->newQueue = gcvTRUE;
+ Command->logical = Command->queues[newIndex].logical;
+ Command->address = Command->queues[newIndex].address;
+ Command->offset = 0;
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(
+ Command->os,
+ Command->logical,
+ &physical
+ ));
+
+ gcmkSAFECASTPHYSADDRT(Command->physical, physical);
+
+ if (currentIndex != -1)
+ {
+ /* Mark the command queue as available. */
+ gcmkONERROR(gckEVENT_Signal(
+ Command->kernel->eventObj,
+ Command->queues[currentIndex].signal,
+ gcvKERNEL_COMMAND
+ ));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("Command->index=%d", Command->index);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_IncrementCommitAtom(
+ IN gckCOMMAND Command,
+ IN gctBOOL Increment
+ )
+{
+ gceSTATUS status;
+ gckHARDWARE hardware;
+ gctINT32 atomValue;
+ gctBOOL powerAcquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Extract the gckHARDWARE and gckEVENT objects. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Grab the power mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ Command->os, hardware->powerMutex, gcvINFINITE
+ ));
+ powerAcquired = gcvTRUE;
+
+ /* Increment the commit atom. */
+ if (Increment)
+ {
+ gcmkONERROR(gckOS_AtomIncrement(
+ Command->os, Command->atomCommit, &atomValue
+ ));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_AtomDecrement(
+ Command->os, Command->atomCommit, &atomValue
+ ));
+ }
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(
+ Command->os, hardware->powerMutex
+ ));
+ powerAcquired = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (powerAcquired)
+ {
+ /* Release the power mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(
+ Command->os, hardware->powerMutex
+ ));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdSECURE_USER
+static gceSTATUS
+_ProcessHints(
+ IN gckCOMMAND Command,
+ IN gctUINT32 ProcessID,
+ IN gcoCMDBUF CommandBuffer
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gckKERNEL kernel;
+ gctBOOL needCopy = gcvFALSE;
+ gcskSECURE_CACHE_PTR cache;
+ gctUINT8_PTR commandBufferLogical;
+ gctUINT8_PTR hintedData;
+ gctUINT32_PTR hintArray;
+ gctUINT i, hintCount;
+
+ gcmkHEADER_ARG(
+ "Command=0x%08X ProcessID=%d CommandBuffer=0x%08X",
+ Command, ProcessID, CommandBuffer
+ );
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Reset state array pointer. */
+ hintArray = gcvNULL;
+
+ /* Get the kernel object. */
+ kernel = Command->kernel;
+
+ /* Get the cache form the database. */
+ gcmkONERROR(gckKERNEL_GetProcessDBCache(kernel, ProcessID, &cache));
+
+ /* Determine the start of the command buffer. */
+ commandBufferLogical
+ = (gctUINT8_PTR) CommandBuffer->logical
+ + CommandBuffer->startOffset;
+
+ /* Determine the number of records in the state array. */
+ hintCount = CommandBuffer->hintArrayTail - CommandBuffer->hintArray;
+
+ /* Check wehther we need to copy the structures or not. */
+ gcmkONERROR(gckOS_QueryNeedCopy(Command->os, ProcessID, &needCopy));
+
+ /* Get access to the state array. */
+ if (needCopy)
+ {
+ gctUINT copySize;
+
+ if (Command->hintArrayAllocated &&
+ (Command->hintArraySize < CommandBuffer->hintArraySize))
+ {
+ gcmkONERROR(gcmkOS_SAFE_FREE(Command->os, gcmUINT64_TO_PTR(Command->hintArray)));
+ Command->hintArraySize = gcvFALSE;
+ }
+
+ if (!Command->hintArrayAllocated)
+ {
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkONERROR(gckOS_Allocate(
+ Command->os,
+ CommandBuffer->hintArraySize,
+ &pointer
+ ));
+
+ Command->hintArray = gcmPTR_TO_UINT64(pointer);
+ Command->hintArrayAllocated = gcvTRUE;
+ Command->hintArraySize = CommandBuffer->hintArraySize;
+ }
+
+ hintArray = gcmUINT64_TO_PTR(Command->hintArray);
+ copySize = hintCount * gcmSIZEOF(gctUINT32);
+
+ gcmkONERROR(gckOS_CopyFromUserData(
+ Command->os,
+ hintArray,
+ gcmUINT64_TO_PTR(CommandBuffer->hintArray),
+ copySize
+ ));
+ }
+ else
+ {
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkONERROR(gckOS_MapUserPointer(
+ Command->os,
+ gcmUINT64_TO_PTR(CommandBuffer->hintArray),
+ CommandBuffer->hintArraySize,
+ &pointer
+ ));
+
+ hintArray = pointer;
+ }
+
+ /* Scan through the buffer. */
+ for (i = 0; i < hintCount; i += 1)
+ {
+ /* Determine the location of the hinted data. */
+ hintedData = commandBufferLogical + hintArray[i];
+
+ /* Map handle into physical address. */
+ gcmkONERROR(gckKERNEL_MapLogicalToPhysical(
+ kernel, cache, (gctPOINTER) hintedData
+ ));
+ }
+
+OnError:
+ /* Get access to the state array. */
+ if (!needCopy && (hintArray != gcvNULL))
+ {
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+ Command->os,
+ gcmUINT64_TO_PTR(CommandBuffer->hintArray),
+ CommandBuffer->hintArraySize,
+ hintArray
+ ));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+static gceSTATUS
+_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,
+ 0,
+ &oldValue));
+
+ if (oldValue)
+ {
+ /* 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
+}
+
+static void
+_DumpBuffer(
+ IN gctPOINTER Buffer,
+ IN gctUINT32 GpuAddress,
+ IN gctSIZE_T Size
+ )
+{
+ gctSIZE_T i, line, left;
+ gctUINT32_PTR data = Buffer;
+
+ line = Size / 32;
+ left = Size % 32;
+
+ for (i = 0; i < line; i++)
+ {
+ gcmkPRINT("%08X : %08X %08X %08X %08X %08X %08X %08X %08X",
+ GpuAddress, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
+ data += 8;
+ GpuAddress += 8 * 4;
+ }
+
+ switch(left)
+ {
+ case 28:
+ gcmkPRINT("%08X : %08X %08X %08X %08X %08X %08X %08X",
+ GpuAddress, data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
+ break;
+ case 24:
+ gcmkPRINT("%08X : %08X %08X %08X %08X %08X %08X",
+ GpuAddress, data[0], data[1], data[2], data[3], data[4], data[5]);
+ break;
+ case 20:
+ gcmkPRINT("%08X : %08X %08X %08X %08X %08X",
+ GpuAddress, data[0], data[1], data[2], data[3], data[4]);
+ break;
+ case 16:
+ gcmkPRINT("%08X : %08X %08X %08X %08X",
+ GpuAddress, data[0], data[1], data[2], data[3]);
+ break;
+ case 12:
+ gcmkPRINT("%08X : %08X %08X %08X",
+ GpuAddress, data[0], data[1], data[2]);
+ break;
+ case 8:
+ gcmkPRINT("%08X : %08X %08X",
+ GpuAddress, data[0], data[1]);
+ break;
+ case 4:
+ gcmkPRINT("%08X : %08X",
+ GpuAddress, data[0]);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+_DumpKernelCommandBuffer(
+ IN gckCOMMAND Command
+ )
+{
+ gctINT i;
+ gctUINT64 physical = 0;
+ gctUINT32 address;
+ gctPOINTER entry = gcvNULL;
+
+ for (i = 0; i < gcdCOMMAND_QUEUES; i++)
+ {
+ entry = Command->queues[i].logical;
+
+ gckOS_GetPhysicalAddress(Command->os, entry, &physical);
+
+ gcmkPRINT("Kernel command buffer %d\n", i);
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ _DumpBuffer(entry, address, Command->pageSize);
+ }
+}
+
+/******************************************************************************\
+****************************** gckCOMMAND API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckCOMMAND_Construct
+**
+** Construct a new gckCOMMAND object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** gckCOMMAND * Command
+** Pointer to a variable that will hold the pointer to the gckCOMMAND
+** object.
+*/
+gceSTATUS
+gckCOMMAND_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckCOMMAND * Command
+ )
+{
+ gckOS os;
+ gckCOMMAND command = gcvNULL;
+ gceSTATUS status;
+ gctINT i;
+ gctPOINTER pointer = gcvNULL;
+ gctSIZE_T pageSize;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Command != gcvNULL);
+
+ /* Extract the gckOS object. */
+ os = Kernel->os;
+
+ /* Allocate the gckCOMMAND structure. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckCOMMAND), &pointer));
+ command = pointer;
+
+ /* Reset the entire object. */
+ gcmkONERROR(gckOS_ZeroMemory(command, gcmSIZEOF(struct _gckCOMMAND)));
+
+ /* Initialize the gckCOMMAND object.*/
+ command->object.type = gcvOBJ_COMMAND;
+ command->kernel = Kernel;
+ command->os = os;
+
+ /* Get the command buffer requirements. */
+ gcmkONERROR(gckHARDWARE_QueryCommandBuffer(
+ Kernel->hardware,
+ &command->alignment,
+ &command->reservedHead,
+ &command->reservedTail
+ ));
+
+ /* Create the command queue mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &command->mutexQueue));
+
+ /* Create the context switching mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &command->mutexContext));
+
+#if VIVANTE_PROFILER_CONTEXT
+ /* Create the context switching mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &command->mutexContextSeq));
+#endif
+
+ /* Create the power management semaphore. */
+ gcmkONERROR(gckOS_CreateSemaphore(os, &command->powerSemaphore));
+
+ /* Create the commit atom. */
+ gcmkONERROR(gckOS_AtomConstruct(os, &command->atomCommit));
+
+ /* Get the page size from teh OS. */
+ gcmkONERROR(gckOS_GetPageSize(os, &pageSize));
+
+ gcmkSAFECASTSIZET(command->pageSize, pageSize);
+
+ /* Get process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&command->kernelProcessID));
+
+ /* Set hardware to pipe 0. */
+ command->pipeSelect = gcvPIPE_INVALID;
+
+ /* Pre-allocate the command queues. */
+ for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+ {
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(
+ os,
+ gcvFALSE,
+ &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
+ ));
+
+ gcmkONERROR(gckOS_Signal(
+ os, command->queues[i].signal, gcvTRUE
+ ));
+ }
+
+#if gcdRECORD_COMMAND
+ gcmkONERROR(gckRECORDER_Construct(os, Kernel->hardware, &command->recorder));
+#endif
+
+ gcmkONERROR(gckFENCE_Create(
+ os, Kernel, &command->fence
+ ));
+
+ /* No command queue in use yet. */
+ command->index = -1;
+ command->logical = gcvNULL;
+ command->newQueue = gcvFALSE;
+
+ /* Command is not yet running. */
+ command->running = gcvFALSE;
+
+ /* Command queue is idle. */
+ command->idle = gcvTRUE;
+
+ /* Commit stamp is zero. */
+ command->commitStamp = 0;
+
+ /* END event signal not created. */
+ command->endEventSignal = gcvNULL;
+
+ command->queue.front = 0;
+ command->queue.rear = 0;
+ command->queue.count = 0;
+
+ /* Return pointer to the gckCOMMAND object. */
+ *Command = command;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Command=0x%x", *Command);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (command != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckCOMMAND_Destroy(command));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Destroy
+**
+** Destroy an gckCOMMAND object.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Destroy(
+ IN gckCOMMAND Command
+ )
+{
+ gctINT i;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Stop the command queue. */
+ gcmkVERIFY_OK(gckCOMMAND_Stop(Command, gcvFALSE));
+
+ for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+ {
+ if (Command->queues[i].signal)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySignal(
+ Command->os, Command->queues[i].signal
+ ));
+ }
+
+ if (Command->queues[i].logical)
+ {
+ gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+ Command->os,
+ Command->pageSize,
+ Command->queues[i].physical,
+ Command->queues[i].logical
+ ));
+ }
+ }
+
+ /* END event signal. */
+ if (Command->endEventSignal != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySignal(
+ Command->os, Command->endEventSignal
+ ));
+ }
+
+ if (Command->mutexContext)
+ {
+ /* Delete the context switching mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexContext));
+ }
+
+#if VIVANTE_PROFILER_CONTEXT
+ if (Command->mutexContextSeq != gcvNULL)
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexContextSeq));
+#endif
+
+ if (Command->mutexQueue)
+ {
+ /* Delete the command queue mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexQueue));
+ }
+
+ if (Command->powerSemaphore)
+ {
+ /* Destroy the power management semaphore. */
+ gcmkVERIFY_OK(gckOS_DestroySemaphore(Command->os, Command->powerSemaphore));
+ }
+
+ if (Command->atomCommit)
+ {
+ /* Destroy the commit atom. */
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Command->os, Command->atomCommit));
+ }
+
+#if gcdSECURE_USER
+ /* Free state array. */
+ if (Command->hintArrayAllocated)
+ {
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Command->os, gcmUINT64_TO_PTR(Command->hintArray)));
+ Command->hintArrayAllocated = gcvFALSE;
+ }
+#endif
+
+#if gcdRECORD_COMMAND
+ gckRECORDER_Destory(Command->os, Command->recorder);
+#endif
+
+ if (Command->stateMap)
+ {
+ gcmkOS_SAFE_FREE(Command->os, Command->stateMap);
+ }
+
+ if (Command->fence)
+ {
+ gcmkVERIFY_OK(gckFENCE_Destory(Command->os, Command->fence));
+ }
+
+ /* Mark object as unknown. */
+ Command->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckCOMMAND object. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Command->os, Command));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_EnterCommit
+**
+** Acquire command queue synchronization objects.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to destroy.
+**
+** gctBOOL FromPower
+** Determines whether the call originates from inside the power
+** management or not.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_EnterCommit(
+ IN gckCOMMAND Command,
+ IN gctBOOL FromPower
+ )
+{
+ gceSTATUS status;
+ gckHARDWARE hardware;
+ gctBOOL atomIncremented = gcvFALSE;
+ gctBOOL semaAcquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Extract the gckHARDWARE and gckEVENT objects. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ if (!FromPower)
+ {
+ /* Increment COMMIT atom to let power management know that a commit is
+ ** in progress. */
+ gcmkONERROR(_IncrementCommitAtom(Command, gcvTRUE));
+ atomIncremented = gcvTRUE;
+
+ /* Notify the system the GPU has a commit. */
+ gcmkONERROR(gckOS_Broadcast(Command->os,
+ hardware,
+ gcvBROADCAST_GPU_COMMIT));
+
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(Command->os,
+ Command->powerSemaphore));
+ semaAcquired = gcvTRUE;
+ }
+
+ /* Grab the conmmand queue mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Command->os,
+ Command->mutexQueue,
+ gcvINFINITE));
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (semaAcquired)
+ {
+ /* Release the power management semaphore. */
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(
+ Command->os, Command->powerSemaphore
+ ));
+ }
+
+ if (atomIncremented)
+ {
+ /* Decrement the commit atom. */
+ gcmkVERIFY_OK(_IncrementCommitAtom(
+ Command, gcvFALSE
+ ));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_ExitCommit
+**
+** Release command queue synchronization objects.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to destroy.
+**
+** gctBOOL FromPower
+** Determines whether the call originates from inside the power
+** management or not.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_ExitCommit(
+ IN gckCOMMAND Command,
+ IN gctBOOL FromPower
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+
+ if (!FromPower)
+ {
+ /* Release the power management semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(Command->os,
+ Command->powerSemaphore));
+
+ /* Decrement the commit atom. */
+ gcmkONERROR(_IncrementCommitAtom(Command, gcvFALSE));
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Start
+**
+** Start up the command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to start.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Start(
+ IN gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gckHARDWARE hardware;
+ gctUINT32 waitOffset = 0;
+ gctUINT32 waitLinkBytes;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->running)
+ {
+ /* Command queue already running. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Extract the gckHARDWARE object. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ if (Command->logical == gcvNULL)
+ {
+ /* Start at beginning of a new queue. */
+ gcmkONERROR(_NewQueue(Command));
+ }
+
+ /* Start at beginning of page. */
+ Command->offset = 0;
+
+ /* Set abvailable number of bytes for WAIT/LINK command sequence. */
+ waitLinkBytes = Command->pageSize;
+
+ /* Append WAIT/LINK. */
+ gcmkONERROR(gckHARDWARE_WaitLink(
+ hardware,
+ Command->logical,
+ 0,
+ &waitLinkBytes,
+ &waitOffset,
+ &Command->waitSize
+ ));
+
+ Command->waitLogical = (gctUINT8_PTR) Command->logical + waitOffset;
+ Command->waitPhysical = Command->physical + waitOffset;
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache for the wait/link. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)Command->physical,
+ Command->logical,
+ waitLinkBytes
+ ));
+#endif
+
+ /* Adjust offset. */
+ Command->offset = waitLinkBytes;
+ Command->newQueue = gcvFALSE;
+
+#if gcdSECURITY
+ /* Start FE by calling security service. */
+ gckKERNEL_SecurityStartCommand(
+ Command->kernel
+ );
+#else
+ /* Enable command processor. */
+ gcmkONERROR(gckHARDWARE_Execute(
+ hardware,
+ Command->address,
+ waitLinkBytes
+ ));
+#endif
+
+ /* Command queue is running. */
+ Command->running = gcvTRUE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Stop
+**
+** Stop the command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to stop.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Stop(
+ IN gckCOMMAND Command,
+ IN gctBOOL FromRecovery
+ )
+{
+ gckHARDWARE hardware;
+ gceSTATUS status;
+ gctUINT32 idle;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (!Command->running)
+ {
+ /* Command queue is not running. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Extract the gckHARDWARE object. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware,
+ gcvFEATURE_END_EVENT) == gcvSTATUS_TRUE)
+ {
+ /* Allocate the signal. */
+ if (Command->endEventSignal == gcvNULL)
+ {
+ gcmkONERROR(gckOS_CreateSignal(Command->os,
+ gcvTRUE,
+ &Command->endEventSignal));
+ }
+
+ /* Append the END EVENT command to trigger the signal. */
+ gcmkONERROR(gckEVENT_Stop(Command->kernel->eventObj,
+ Command->kernelProcessID,
+ Command->waitPhysical,
+ Command->waitLogical,
+ Command->endEventSignal,
+ &Command->waitSize));
+ }
+ else
+ {
+ /* Replace last WAIT with END. */
+ gcmkONERROR(gckHARDWARE_End(
+ hardware, Command->waitLogical, &Command->waitSize
+ ));
+
+#if gcdSECURITY
+ gcmkONERROR(gckKERNEL_SecurityExecute(
+ Command->kernel, Command->waitLogical, 8
+ ));
+#endif
+
+ /* Update queue tail pointer. */
+ gcmkONERROR(gckHARDWARE_UpdateQueueTail(Command->kernel->hardware,
+ Command->logical,
+ Command->offset));
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache for the END. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)Command->waitPhysical,
+ Command->waitLogical,
+ Command->waitSize
+ ));
+#endif
+
+ /* Wait for idle. */
+ gcmkONERROR(gckHARDWARE_GetIdle(hardware, !FromRecovery, &idle));
+ }
+
+ /* Command queue is no longer running. */
+ Command->running = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Commit
+**
+** Commit a command buffer to the command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to a gckCOMMAND object.
+**
+** gckCONTEXT Context
+** Pointer to a gckCONTEXT object.
+**
+** gcoCMDBUF CommandBuffer
+** Pointer to a gcoCMDBUF object.
+**
+** gcsSTATE_DELTA_PTR StateDelta
+** Pointer to the state delta.
+**
+** gctUINT32 ProcessID
+** Current process ID.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+#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,
+ IN gckCONTEXT Context,
+ IN gcoCMDBUF CommandBuffer,
+ IN gcsSTATE_DELTA_PTR StateDelta,
+ IN gcsQUEUE_PTR EventQueue,
+ IN gctUINT32 ProcessID
+ )
+#endif
+{
+ gceSTATUS status;
+ gctBOOL commitEntered = gcvFALSE;
+ gctBOOL contextAcquired = gcvFALSE;
+ gckHARDWARE hardware;
+ gctBOOL needCopy = gcvFALSE;
+ gcsQUEUE_PTR eventRecord = gcvNULL;
+ gcsQUEUE _eventRecord;
+ gcsQUEUE_PTR nextEventRecord;
+ gctBOOL commandBufferMapped = gcvFALSE;
+ gcoCMDBUF commandBufferObject = gcvNULL;
+ gctBOOL stall = gcvFALSE;
+
+#if !gcdNULL_DRIVER
+ gcsCONTEXT_PTR contextBuffer;
+ struct _gcoCMDBUF _commandBufferObject;
+ gctPHYS_ADDR_T commandBufferPhysical;
+ gctUINT8_PTR commandBufferLogical = gcvNULL;
+ gctUINT32 commandBufferAddress = 0;
+ gctUINT8_PTR commandBufferLink = gcvNULL;
+ gctUINT commandBufferSize;
+ gctSIZE_T nopBytes;
+ gctUINT32 pipeBytes;
+ gctUINT32 linkBytes;
+ gctSIZE_T bytes;
+ gctUINT32 offset;
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ gctPHYS_ADDR entryPhysical;
+#endif
+ gctPOINTER entryLogical;
+ gctUINT32 entryAddress;
+ gctUINT32 entryBytes;
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ gctPHYS_ADDR exitPhysical;
+#endif
+ gctPOINTER exitLogical;
+ gctUINT32 exitAddress;
+ gctUINT32 exitBytes;
+ gctUINT32 waitLinkPhysical;
+ gctPOINTER waitLinkLogical;
+ gctUINT32 waitLinkAddress;
+ gctUINT32 waitLinkBytes;
+ gctUINT32 waitPhysical;
+ gctPOINTER waitLogical;
+ gctUINT32 waitOffset;
+ 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;
+ gctSIZE_T contextDumpBytes = 0;
+ gctPOINTER bufferDumpLogical = gcvNULL;
+ gctSIZE_T bufferDumpBytes = 0;
+# endif
+#endif
+
+#if VIVANTE_PROFILER_CONTEXT
+ gctBOOL sequenceAcquired = gcvFALSE;
+#endif
+
+ gctPOINTER pointer = gcvNULL;
+
+#if gcdMULTI_GPU
+ gctSIZE_T chipEnableBytes;
+#endif
+
+ gctUINT32 exitLinkLow = 0, exitLinkHigh = 0;
+ gctUINT32 entryLinkLow = 0, entryLinkHigh = 0;
+ gctUINT32 commandLinkLow = 0, commandLinkHigh = 0;
+
+ gckVIRTUAL_COMMAND_BUFFER_PTR virtualCommandBuffer = gcvNULL;
+
+ gcmkHEADER_ARG(
+ "Command=0x%x CommandBuffer=0x%x ProcessID=%d",
+ Command, CommandBuffer, ProcessID
+ );
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->kernel->hardware->type== gcvHARDWARE_2D)
+ {
+ /* There is no context for 2D. */
+ Context = gcvNULL;
+ }
+
+#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))
+ {
+ /* Acquire the context sequnence mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ Command->os, Command->mutexContextSeq, gcvINFINITE
+ ));
+ sequenceAcquired = gcvTRUE;
+ }
+#endif
+
+ /* Acquire the command queue. */
+ gcmkONERROR(gckCOMMAND_EnterCommit(Command, gcvFALSE));
+ commitEntered = gcvTRUE;
+
+ /* Acquire the context switching mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ Command->os, Command->mutexContext, gcvINFINITE
+ ));
+ contextAcquired = gcvTRUE;
+
+ /* Extract the gckHARDWARE and gckEVENT objects. */
+ hardware = Command->kernel->hardware;
+
+ /* Check wehther we need to copy the structures or not. */
+ gcmkONERROR(gckOS_QueryNeedCopy(Command->os, ProcessID, &needCopy));
+
+#if gcdNULL_DRIVER
+ /* Context switch required? */
+ if ((Context != gcvNULL) && (Command->currContext != Context))
+ {
+ /* Yes, merge in the deltas. */
+ gckCONTEXT_Update(Context, ProcessID, StateDelta);
+
+ /* Update the current context. */
+ Command->currContext = Context;
+ }
+#else
+ if (needCopy)
+ {
+ commandBufferObject = &_commandBufferObject;
+
+ gcmkONERROR(gckOS_CopyFromUserData(
+ Command->os,
+ commandBufferObject,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF)
+ ));
+
+ gcmkVERIFY_OBJECT(commandBufferObject, gcvOBJ_COMMANDBUFFER);
+ }
+ else
+ {
+ gcmkONERROR(gckOS_MapUserPointer(
+ Command->os,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ &pointer
+ ));
+
+ commandBufferObject = pointer;
+
+ gcmkVERIFY_OBJECT(commandBufferObject, gcvOBJ_COMMANDBUFFER);
+ commandBufferMapped = gcvTRUE;
+ }
+
+ /* Query the size of NOP command. */
+ gcmkONERROR(gckHARDWARE_Nop(
+ hardware, gcvNULL, &nopBytes
+ ));
+
+ /* Query the size of pipe select command sequence. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ hardware, gcvNULL, gcvPIPE_3D, &pipeBytes
+ ));
+
+ /* Query the size of LINK command. */
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware, gcvNULL, 0, 0, &linkBytes, gcvNULL, gcvNULL
+ ));
+
+#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;
+
+ /* Get the hardware address. */
+ if (Command->kernel->virtualCommandBuffer)
+ {
+ gckKERNEL kernel = Command->kernel;
+
+ virtualCommandBuffer = gcmNAME_TO_PTR(commandBufferObject->physical);
+
+ if (virtualCommandBuffer == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ Command->kernel,
+ commandBufferLogical,
+ gcvTRUE,
+ virtualCommandBuffer,
+ &commandBufferAddress
+ ));
+ }
+ else
+ {
+ gcmkONERROR(gckHARDWARE_ConvertLogical(
+ hardware,
+ commandBufferLogical,
+ gcvTRUE,
+ &commandBufferAddress
+ ));
+ }
+
+ /* Get the physical address. */
+ gcmkONERROR(gckOS_UserLogicalToPhysical(
+ Command->os,
+ commandBufferLogical,
+ &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,
+ gcvNULL,
+ offset,
+ &waitLinkBytes,
+ gcvNULL,
+ gcvNULL
+ ));
+
+ /* Is there enough space in the current command queue? */
+ if (bytes < waitLinkBytes)
+ {
+ /* No, create a new one. */
+ gcmkONERROR(_NewQueue(Command));
+
+ /* Get the new current offset. */
+ offset = Command->offset;
+
+ /* Recompute the number of bytes in the new kernel command queue. */
+ bytes = Command->pageSize - offset;
+ gcmkASSERT(bytes >= waitLinkBytes);
+ }
+
+ /* Compute the location if WAIT/LINK command sequence. */
+ waitLinkPhysical = Command->physical + offset;
+ waitLinkLogical = (gctUINT8_PTR) Command->logical + offset;
+ waitLinkAddress = Command->address + offset;
+
+ /* Context switch required? */
+ if (Context == gcvNULL)
+ {
+ /* See if we have to switch pipes for the command buffer. */
+ if (commandBufferObject->entryPipe == Command->pipeSelect)
+ {
+ /* Skip pipe switching sequence. */
+ offset = pipeBytes;
+ }
+ else
+ {
+ /* The current hardware and the entry command buffer pipes
+ ** are different, switch to the correct pipe. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ commandBufferObject->entryPipe,
+ &pipeBytes
+ ));
+
+ /* Do not skip pipe switching sequence. */
+ offset = 0;
+ }
+
+ /* Compute the entry. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) commandBufferPhysical + offset;
+#endif
+ entryLogical = commandBufferLogical + offset;
+ entryAddress = commandBufferAddress + offset;
+ entryBytes = commandBufferSize - offset;
+
+ Command->currContext = gcvNULL;
+ }
+ else if (Command->currContext != Context)
+ {
+ /* Temporary disable context length oprimization. */
+ Context->dirty = gcvTRUE;
+
+ /* Get the current context buffer. */
+ contextBuffer = Context->buffer;
+
+ /* Yes, merge in the deltas. */
+ gcmkONERROR(gckCONTEXT_Update(Context, ProcessID, StateDelta));
+
+ /* Determine context entry and exit points. */
+ if (0)
+ {
+ /* Reset 2D dirty flag. */
+ Context->dirty2D = gcvFALSE;
+
+ if (Context->dirty || commandBufferObject->using3D)
+ {
+ /***************************************************************
+ ** SWITCHING CONTEXT: 2D and 3D are used.
+ */
+
+ /* Reset 3D dirty flag. */
+ Context->dirty3D = gcvFALSE;
+
+ /* Compute the entry. */
+ if (Command->pipeSelect == gcvPIPE_2D)
+ {
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
+#endif
+ entryLogical = (gctUINT8_PTR) contextBuffer->logical + pipeBytes;
+ entryAddress = contextBuffer->address + pipeBytes;
+ entryBytes = Context->bufferSize - pipeBytes;
+ }
+ else
+ {
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
+#endif
+ entryLogical = (gctUINT8_PTR) contextBuffer->logical;
+ entryAddress = contextBuffer->address;
+ entryBytes = Context->bufferSize;
+ }
+
+ /* See if we have to switch pipes between the context
+ and command buffers. */
+ if (commandBufferObject->entryPipe == gcvPIPE_3D)
+ {
+ /* Skip pipe switching sequence. */
+ offset = pipeBytes;
+ }
+ else
+ {
+ /* The current hardware and the initial context pipes are
+ different, switch to the correct pipe. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ commandBufferObject->entryPipe,
+ &pipeBytes
+ ));
+
+ /* Do not skip pipe switching sequence. */
+ offset = 0;
+ }
+
+ /* Ensure the NOP between 2D and 3D is in place so that the
+ execution falls through from 2D to 3D. */
+ gcmkONERROR(gckHARDWARE_Nop(
+ hardware,
+ contextBuffer->link2D,
+ &nopBytes
+ ));
+
+ /* Generate a LINK from the context buffer to
+ the command buffer. */
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware,
+ contextBuffer->link3D,
+ commandBufferAddress + offset,
+ commandBufferSize - offset,
+ &linkBytes,
+ &commandLinkLow,
+ &commandLinkHigh
+ ));
+
+ /* Mark context as not dirty. */
+ Context->dirty = gcvFALSE;
+ }
+ else
+ {
+ /***************************************************************
+ ** SWITCHING CONTEXT: 2D only command buffer.
+ */
+
+ /* Mark 3D as dirty. */
+ Context->dirty3D = gcvTRUE;
+
+ /* Compute the entry. */
+ if (Command->pipeSelect == gcvPIPE_2D)
+ {
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
+#endif
+ entryLogical = (gctUINT8_PTR) contextBuffer->logical + pipeBytes;
+ entryAddress = contextBuffer->address + pipeBytes;
+ entryBytes = Context->entryOffset3D - pipeBytes;
+ }
+ else
+ {
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
+#endif
+ entryLogical = (gctUINT8_PTR) contextBuffer->logical;
+ entryAddress = contextBuffer->address;
+ entryBytes = Context->entryOffset3D;
+ }
+
+ /* Store the current context buffer. */
+ Context->dirtyBuffer = contextBuffer;
+
+ /* See if we have to switch pipes between the context
+ and command buffers. */
+ if (commandBufferObject->entryPipe == gcvPIPE_2D)
+ {
+ /* Skip pipe switching sequence. */
+ offset = pipeBytes;
+ }
+ else
+ {
+ /* The current hardware and the initial context pipes are
+ different, switch to the correct pipe. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ commandBufferObject->entryPipe,
+ &pipeBytes
+ ));
+
+ /* Do not skip pipe switching sequence. */
+ offset = 0;
+ }
+
+ /* 3D is not used, generate a LINK from the end of 2D part of
+ the context buffer to the command buffer. */
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware,
+ contextBuffer->link2D,
+ commandBufferAddress + offset,
+ commandBufferSize - offset,
+ &linkBytes,
+ &commandLinkLow,
+ &commandLinkHigh
+ ));
+ }
+ }
+
+ /* Not using 2D. */
+ else
+ {
+
+ /* Store the current context buffer. */
+ Context->dirtyBuffer = contextBuffer;
+
+ if (Context->dirty || commandBufferObject->using3D)
+ {
+ /***************************************************************
+ ** SWITCHING CONTEXT: 3D only command buffer.
+ */
+
+ /* Reset 3D dirty flag. */
+ Context->dirty3D = gcvFALSE;
+
+ /* Determine context buffer entry offset. */
+ offset = (Command->pipeSelect == gcvPIPE_3D)
+
+ /* Skip pipe switching sequence. */
+ ? Context->entryOffset3D + Context->pipeSelectBytes
+
+ /* Do not skip pipe switching sequence. */
+ : Context->entryOffset3D;
+
+ /* Compute the entry. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ 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
+ and command buffers. */
+ if (commandBufferObject->entryPipe == gcvPIPE_3D)
+ {
+ /* Skip pipe switching sequence. */
+ offset = pipeBytes;
+ }
+ else
+ {
+ /* The current hardware and the initial context pipes are
+ different, switch to the correct pipe. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ commandBufferObject->entryPipe,
+ &pipeBytes
+ ));
+
+ /* Do not skip pipe switching sequence. */
+ offset = 0;
+ }
+
+ /* Generate a LINK from the context buffer to
+ the command buffer. */
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware,
+ contextBuffer->link3D,
+ commandBufferAddress + offset,
+ commandBufferSize - offset,
+ &linkBytes,
+ &commandLinkLow,
+ &commandLinkHigh
+ ));
+ }
+ else
+ {
+ /***************************************************************
+ ** SWITCHING CONTEXT: "XD" command buffer - neither 2D nor 3D.
+ */
+
+ /* Mark 3D as dirty. */
+ Context->dirty3D = gcvTRUE;
+
+ /* Compute the entry. */
+ if (Command->pipeSelect == gcvPIPE_3D)
+ {
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical
+ = (gctUINT8_PTR) contextBuffer->physical
+ + Context->entryOffsetXDFrom3D;
+#endif
+ entryLogical
+ = (gctUINT8_PTR) contextBuffer->logical
+ + Context->entryOffsetXDFrom3D;
+
+ entryAddress
+ = contextBuffer->address
+ + Context->entryOffsetXDFrom3D;
+
+ entryBytes
+ = Context->bufferSize
+ - Context->entryOffsetXDFrom3D;
+ }
+ else
+ {
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical
+ = (gctUINT8_PTR) contextBuffer->physical
+ + Context->entryOffsetXDFrom2D;
+#endif
+ entryLogical
+ = (gctUINT8_PTR) contextBuffer->logical
+ + Context->entryOffsetXDFrom2D;
+
+ entryAddress
+ = contextBuffer->address
+ + Context->entryOffsetXDFrom2D;
+
+ entryBytes
+ = Context->totalSize
+ - Context->entryOffsetXDFrom2D;
+ }
+
+ /* See if we have to switch pipes between the context
+ and command buffers. */
+ if (commandBufferObject->entryPipe == gcvPIPE_3D)
+ {
+ /* Skip pipe switching sequence. */
+ offset = pipeBytes;
+ }
+ else
+ {
+ /* The current hardware and the initial context pipes are
+ different, switch to the correct pipe. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ commandBufferObject->entryPipe,
+ &pipeBytes
+ ));
+
+ /* Do not skip pipe switching sequence. */
+ offset = 0;
+ }
+
+ /* Generate a LINK from the context buffer to
+ the command buffer. */
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware,
+ contextBuffer->link3D,
+ commandBufferAddress + offset,
+ commandBufferSize - offset,
+ &linkBytes,
+ &commandLinkLow,
+ &commandLinkHigh
+ ));
+ }
+ }
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the context buffer cache. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)entryPhysical,
+ entryLogical,
+ entryBytes
+ ));
+#endif
+
+ /* Update the current context. */
+ Command->currContext = Context;
+
+#if gcdDUMP_COMMAND
+ 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. */
+ else
+ {
+ /* Determine context entry and exit points. */
+ if (commandBufferObject->using2D && Context->dirty2D)
+ {
+ /* Reset 2D dirty flag. */
+ Context->dirty2D = gcvFALSE;
+
+ /* Get the "dirty" context buffer. */
+ contextBuffer = Context->dirtyBuffer;
+
+ if (commandBufferObject->using3D && Context->dirty3D)
+ {
+ /* Reset 3D dirty flag. */
+ Context->dirty3D = gcvFALSE;
+
+ /* Compute the entry. */
+ if (Command->pipeSelect == gcvPIPE_2D)
+ {
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
+#endif
+ entryLogical = (gctUINT8_PTR) contextBuffer->logical + pipeBytes;
+ entryAddress = contextBuffer->address + pipeBytes;
+ entryBytes = Context->bufferSize - pipeBytes;
+ }
+ else
+ {
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
+#endif
+ entryLogical = (gctUINT8_PTR) contextBuffer->logical;
+ entryAddress = contextBuffer->address;
+ entryBytes = Context->bufferSize;
+ }
+
+ /* See if we have to switch pipes between the context
+ and command buffers. */
+ if (commandBufferObject->entryPipe == gcvPIPE_3D)
+ {
+ /* Skip pipe switching sequence. */
+ offset = pipeBytes;
+ }
+ else
+ {
+ /* The current hardware and the initial context pipes are
+ different, switch to the correct pipe. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ commandBufferObject->entryPipe,
+ &pipeBytes
+ ));
+
+ /* Do not skip pipe switching sequence. */
+ offset = 0;
+ }
+
+ /* Ensure the NOP between 2D and 3D is in place so that the
+ execution falls through from 2D to 3D. */
+ gcmkONERROR(gckHARDWARE_Nop(
+ hardware,
+ contextBuffer->link2D,
+ &nopBytes
+ ));
+
+ /* Generate a LINK from the context buffer to
+ the command buffer. */
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware,
+ contextBuffer->link3D,
+ commandBufferAddress + offset,
+ commandBufferSize - offset,
+ &linkBytes,
+ &commandLinkLow,
+ &commandLinkHigh
+ ));
+ }
+ else
+ {
+ /* Compute the entry. */
+ if (Command->pipeSelect == gcvPIPE_2D)
+ {
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
+#endif
+ entryLogical = (gctUINT8_PTR) contextBuffer->logical + pipeBytes;
+ entryAddress = contextBuffer->address + pipeBytes;
+ entryBytes = Context->entryOffset3D - pipeBytes;
+ }
+ else
+ {
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
+#endif
+ entryLogical = (gctUINT8_PTR) contextBuffer->logical;
+ entryAddress = contextBuffer->address;
+ entryBytes = Context->entryOffset3D;
+ }
+
+ /* See if we have to switch pipes between the context
+ and command buffers. */
+ if (commandBufferObject->entryPipe == gcvPIPE_2D)
+ {
+ /* Skip pipe switching sequence. */
+ offset = pipeBytes;
+ }
+ else
+ {
+ /* The current hardware and the initial context pipes are
+ different, switch to the correct pipe. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ commandBufferObject->entryPipe,
+ &pipeBytes
+ ));
+
+ /* Do not skip pipe switching sequence. */
+ offset = 0;
+ }
+
+ /* 3D is not used, generate a LINK from the end of 2D part of
+ the context buffer to the command buffer. */
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware,
+ contextBuffer->link2D,
+ commandBufferAddress + offset,
+ commandBufferSize - offset,
+ &linkBytes,
+ &commandLinkLow,
+ &commandLinkHigh
+ ));
+ }
+ }
+ else
+ {
+ if (commandBufferObject->using3D && Context->dirty3D)
+ {
+ /* Reset 3D dirty flag. */
+ Context->dirty3D = gcvFALSE;
+
+ /* Get the "dirty" context buffer. */
+ contextBuffer = Context->dirtyBuffer;
+
+ /* Determine context buffer entry offset. */
+ offset = (Command->pipeSelect == gcvPIPE_3D)
+
+ /* Skip pipe switching sequence. */
+ ? Context->entryOffset3D + pipeBytes
+
+ /* Do not skip pipe switching sequence. */
+ : Context->entryOffset3D;
+
+ /* Compute the entry. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ 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
+ and command buffers. */
+ if (commandBufferObject->entryPipe == gcvPIPE_3D)
+ {
+ /* Skip pipe switching sequence. */
+ offset = pipeBytes;
+ }
+ else
+ {
+ /* The current hardware and the initial context pipes are
+ different, switch to the correct pipe. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ commandBufferObject->entryPipe,
+ &pipeBytes
+ ));
+
+ /* Do not skip pipe switching sequence. */
+ offset = 0;
+ }
+
+ /* Generate a LINK from the context buffer to
+ the command buffer. */
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware,
+ contextBuffer->link3D,
+ commandBufferAddress + offset,
+ commandBufferSize - offset,
+ &linkBytes,
+ &commandLinkLow,
+ &commandLinkHigh
+ ));
+ }
+ else
+ {
+ /* See if we have to switch pipes for the command buffer. */
+ if (commandBufferObject->entryPipe == Command->pipeSelect)
+ {
+ /* Skip pipe switching sequence. */
+ offset = pipeBytes;
+ }
+ else
+ {
+ /* The current hardware and the entry command buffer pipes
+ ** are different, switch to the correct pipe. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ commandBufferObject->entryPipe,
+ &pipeBytes
+ ));
+
+ /* Do not skip pipe switching sequence. */
+ offset = 0;
+ }
+
+ /* Compute the entry. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) commandBufferPhysical + offset;
+#endif
+ entryLogical = commandBufferLogical + offset;
+ entryAddress = commandBufferAddress + offset;
+ entryBytes = commandBufferSize - offset;
+ }
+ }
+ }
+
+#if gcdDUMP_COMMAND
+ bufferDumpLogical = commandBufferLogical + offset;
+ bufferDumpBytes = commandBufferSize - offset;
+#endif
+
+#if gcdSECURE_USER
+ /* Process user hints. */
+ gcmkONERROR(_ProcessHints(Command, ProcessID, commandBufferObject));
+#endif
+
+ /* Determine the location to jump to for the command buffer being
+ ** scheduled. */
+ if (Command->newQueue)
+ {
+ /* New command queue, jump to the beginning of it. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ exitPhysical = Command->physical;
+#endif
+
+ exitLogical = Command->logical;
+ exitAddress = Command->address;
+ exitBytes = Command->offset + waitLinkBytes;
+ }
+ else
+ {
+ /* Still within the preexisting command queue, jump to the new
+ WAIT/LINK command sequence. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ exitPhysical = waitLinkPhysical;
+#endif
+ exitLogical = waitLinkLogical;
+ exitAddress = waitLinkAddress;
+ exitBytes = waitLinkBytes;
+ }
+
+ /* Add a new WAIT/LINK command sequence. When the command buffer which is
+ currently being scheduled is fully executed by the GPU, the FE will
+ jump to this WAIT/LINK sequence. */
+ gcmkONERROR(gckHARDWARE_WaitLink(
+ hardware,
+ waitLinkLogical,
+ offset,
+ &waitLinkBytes,
+ &waitOffset,
+ &waitSize
+ ));
+
+ /* Compute the location if WAIT command. */
+ waitPhysical = waitLinkPhysical + waitOffset;
+ waitLogical = (gctUINT8_PTR) waitLinkLogical + waitOffset;
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the command queue cache. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)exitPhysical,
+ exitLogical,
+ exitBytes
+ ));
+#endif
+
+ /* Determine the location of the LINK command in the command buffer. */
+ commandBufferLink
+ = (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,
+ exitAddress,
+ exitBytes,
+ &linkBytes,
+ &exitLinkLow,
+ &exitLinkHigh
+ ));
+#endif
+
+#ifdef __QNXNTO__
+ gcmkONERROR(gckOS_UnmapUserPointer(
+ Command->os,
+ userCommandBufferLink,
+ 0,
+ commandBufferLink));
+
+ userCommandBufferLinkMapped = gcvFALSE;
+#endif
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the command buffer cache. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ ProcessID,
+ gcvNULL,
+ (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);
+#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
+ pair, therefore we use WAIT metrics for generation of this LINK.
+ This action will execute the entire sequence. */
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware,
+ Command->waitLogical,
+ entryAddress,
+ entryBytes,
+ &Command->waitSize,
+ &entryLinkLow,
+ &entryLinkHigh
+ ));
+#endif
+
+#if gcdLINK_QUEUE_SIZE
+ if (Command->kernel->stuckDump >= gcvSTUCK_DUMP_USER_COMMAND)
+ {
+ gckLINKQUEUE_Enqueue(
+ &hardware->linkQueue,
+ entryAddress,
+ entryAddress + entryBytes,
+ entryLinkLow,
+ entryLinkHigh
+ );
+
+ if (commandBufferAddress + offset != entryAddress)
+ {
+ gckLINKQUEUE_Enqueue(
+ &hardware->linkQueue,
+ commandBufferAddress + offset,
+ commandBufferAddress + commandBufferSize,
+ commandLinkLow,
+ commandLinkHigh
+ );
+ }
+
+ if (Command->kernel->stuckDump >= gcvSTUCK_DUMP_ALL_COMMAND)
+ {
+ /* Dump kernel command.*/
+ gckLINKQUEUE_Enqueue(
+ &hardware->linkQueue,
+ exitAddress,
+ exitAddress + exitBytes,
+ exitLinkLow,
+ exitLinkHigh
+ );
+ }
+ }
+#endif
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache for the link. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)Command->waitPhysical,
+ Command->waitLogical,
+ Command->waitSize
+ ));
+#endif
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ Command->waitLogical,
+ Command->waitSize,
+ gceDUMP_BUFFER_LINK,
+ gcvFALSE
+ );
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ contextDumpLogical,
+ contextDumpBytes,
+ gceDUMP_BUFFER_CONTEXT,
+ gcvFALSE
+ );
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ bufferDumpLogical,
+ bufferDumpBytes,
+ gceDUMP_BUFFER_USER,
+ gcvFALSE
+ );
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ waitLinkLogical,
+ waitLinkBytes,
+ gceDUMP_BUFFER_WAITLINK,
+ gcvFALSE
+ );
+
+ /* Update the current pipe. */
+ Command->pipeSelect = commandBufferObject->exitPipe;
+
+ /* Update command queue offset. */
+ Command->offset += waitLinkBytes;
+ Command->newQueue = gcvFALSE;
+
+ /* Update address of last WAIT. */
+ Command->waitPhysical = waitPhysical;
+ Command->waitLogical = waitLogical;
+ Command->waitSize = waitSize;
+
+ /* Update queue tail pointer. */
+ gcmkONERROR(gckHARDWARE_UpdateQueueTail(
+ hardware, Command->logical, Command->offset
+ ));
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.commit]");
+#endif
+#endif /* gcdNULL_DRIVER */
+
+ /* Release the context switching mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ contextAcquired = gcvFALSE;
+
+ Command->commitStamp++;
+
+ stall = gcvFALSE;
+
+#if gcdLINK_QUEUE_SIZE
+ if (Command->kernel->stuckDump == gcvSTUCK_DUMP_STALL_COMMAND)
+ {
+ if ((Command->commitStamp % (gcdLINK_QUEUE_SIZE/2)) == 0)
+ {
+ /* If only context buffer and command buffer is recorded,
+ ** each commit costs 2 slot in queue, to make sure command
+ ** causing stuck is recorded, number of pending command buffer
+ ** is limited to (gckLINK_QUEUE_SIZE/2)
+ */
+ stall = gcvTRUE;
+ }
+ }
+#endif
+
+ /* Release the command queue. */
+ gcmkONERROR(gckCOMMAND_ExitCommit(Command, gcvFALSE));
+ commitEntered = gcvFALSE;
+
+ if (stall)
+ {
+#if gcdMULTI_GPU
+ gcmkONERROR(gckCOMMAND_Stall(Command, gcvFALSE, ChipEnable));
+#else
+ gcmkONERROR(gckCOMMAND_Stall(Command, gcvFALSE));
+#endif
+ }
+
+#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(
+ hardware,
+ Command->currContext));
+ }
+
+ /* Release the context switching mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContextSeq));
+ sequenceAcquired = gcvFALSE;
+ }
+#endif
+
+ /* Loop while there are records in the queue. */
+ while (EventQueue != gcvNULL)
+ {
+ if (needCopy)
+ {
+ /* Point to stack record. */
+ eventRecord = &_eventRecord;
+
+ /* Copy the data from the client. */
+ gcmkONERROR(gckOS_CopyFromUserData(
+ Command->os, eventRecord, EventQueue, gcmSIZEOF(gcsQUEUE)
+ ));
+ }
+ else
+ {
+ /* Map record into kernel memory. */
+ gcmkONERROR(gckOS_MapUserPointer(Command->os,
+ EventQueue,
+ gcmSIZEOF(gcsQUEUE),
+ &pointer));
+
+ eventRecord = pointer;
+ }
+
+ /* Append event record to event queue. */
+ gcmkONERROR(gckEVENT_AddList(
+ Command->kernel->eventObj, &eventRecord->iface, gcvKERNEL_PIXEL, gcvTRUE, gcvFALSE
+ ));
+
+ /* Next record in the queue. */
+ nextEventRecord = gcmUINT64_TO_PTR(eventRecord->next);
+
+ if (!needCopy)
+ {
+ /* Unmap record from kernel memory. */
+ gcmkONERROR(gckOS_UnmapUserPointer(
+ Command->os, EventQueue, gcmSIZEOF(gcsQUEUE), (gctPOINTER *) eventRecord
+ ));
+
+ eventRecord = gcvNULL;
+ }
+
+ EventQueue = nextEventRecord;
+ }
+
+ if (Command->kernel->eventObj->queueHead == gcvNULL
+ && Command->kernel->hardware->powerManagement == gcvTRUE
+ )
+ {
+ /* Commit done event by which work thread knows all jobs done. */
+ gcmkVERIFY_OK(
+ gckEVENT_CommitDone(Command->kernel->eventObj, gcvKERNEL_PIXEL));
+ }
+
+ /* 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(
+ gcvLEVEL_INFO,
+ "%s(%d): Intterupted in gckEVENT_Submit",
+ __FUNCTION__, __LINE__
+ );
+ status = gcvSTATUS_OK;
+ }
+ else
+ {
+ gcmkONERROR(status);
+ }
+
+#ifdef __QNXNTO__
+ if (userCommandBufferLogicalMapped)
+ {
+ gcmkONERROR(gckOS_UnmapUserPointer(
+ Command->os,
+ userCommandBufferLogical,
+ 0,
+ commandBufferLogical));
+
+ userCommandBufferLogicalMapped = gcvFALSE;
+ }
+#endif
+
+ /* Unmap the command buffer pointer. */
+ if (commandBufferMapped)
+ {
+ gcmkONERROR(gckOS_UnmapUserPointer(
+ Command->os,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ commandBufferObject
+ ));
+
+ commandBufferMapped = gcvFALSE;
+ }
+
+ /* Return status. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if ((eventRecord != gcvNULL) && !needCopy)
+ {
+ /* Roll back. */
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+ Command->os,
+ EventQueue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) eventRecord
+ ));
+ }
+
+ if (contextAcquired)
+ {
+ /* Release the context switching mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ }
+
+ if (commitEntered)
+ {
+ /* Release the command queue mutex. */
+ gcmkVERIFY_OK(gckCOMMAND_ExitCommit(Command, gcvFALSE));
+ }
+
+#if VIVANTE_PROFILER_CONTEXT
+ if (sequenceAcquired)
+ {
+ /* Release the context sequence mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContextSeq));
+ }
+#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)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+ Command->os,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ commandBufferObject
+ ));
+ }
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Reserve
+**
+** Reserve space in the command queue. Also acquire the command queue mutex.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** gctSIZE_T RequestedBytes
+** Number of bytes previously reserved.
+**
+** OUTPUT:
+**
+** gctPOINTER * Buffer
+** Pointer to a variable that will receive the address of the reserved
+** space.
+**
+** gctSIZE_T * BufferSize
+** Pointer to a variable that will receive the number of bytes
+** available in the command queue.
+*/
+gceSTATUS
+gckCOMMAND_Reserve(
+ IN gckCOMMAND Command,
+ IN gctUINT32 RequestedBytes,
+ OUT gctPOINTER * Buffer,
+ OUT gctUINT32 * BufferSize
+ )
+{
+ gceSTATUS status;
+ gctUINT32 bytes;
+ gctUINT32 requiredBytes;
+ gctUINT32 requestedAligned;
+
+ gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Compute aligned number of reuested bytes. */
+ requestedAligned = gcmALIGN(RequestedBytes, Command->alignment);
+
+ /* Another WAIT/LINK command sequence will have to be appended after
+ the requested area being reserved. Compute the number of bytes
+ required for WAIT/LINK at the location after the reserved area. */
+ gcmkONERROR(gckHARDWARE_WaitLink(
+ Command->kernel->hardware,
+ gcvNULL,
+ Command->offset + requestedAligned,
+ &requiredBytes,
+ gcvNULL,
+ gcvNULL
+ ));
+
+ /* Compute total number of bytes required. */
+ requiredBytes += requestedAligned;
+
+ /* Compute number of bytes available in command queue. */
+ bytes = Command->pageSize - Command->offset;
+
+ /* Is there enough space in the current command queue? */
+ if (bytes < requiredBytes)
+ {
+ /* Create a new command queue. */
+ gcmkONERROR(_NewQueue(Command));
+
+ /* Recompute the number of bytes in the new kernel command queue. */
+ bytes = Command->pageSize - Command->offset;
+
+ /* Still not enough space? */
+ if (bytes < requiredBytes)
+ {
+ /* Rare case, not enough room in command queue. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+ }
+
+ /* Return pointer to empty slot command queue. */
+ *Buffer = (gctUINT8 *) Command->logical + Command->offset;
+
+ /* Return number of bytes left in command queue. */
+ *BufferSize = bytes;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Buffer=0x%x *BufferSize=%lu", *Buffer, *BufferSize);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Execute
+**
+** Execute a previously reserved command queue by appending a WAIT/LINK command
+** sequence after it and modifying the last WAIT into a LINK command. The
+** command FIFO mutex will be released whether this function succeeds or not.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** gctSIZE_T RequestedBytes
+** Number of bytes previously reserved.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Execute(
+ IN gckCOMMAND Command,
+ IN gctUINT32 RequestedBytes
+ )
+{
+ gceSTATUS status;
+
+ gctUINT32 waitLinkPhysical;
+ gctUINT8_PTR waitLinkLogical;
+ gctUINT32 waitLinkOffset;
+ gctUINT32 waitLinkBytes;
+
+ gctUINT32 waitPhysical;
+ gctPOINTER waitLogical;
+ gctUINT32 waitOffset;
+ gctUINT32 waitBytes;
+
+ gctUINT32 linkLow, linkHigh;
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ gctPHYS_ADDR execPhysical;
+#endif
+ gctPOINTER execLogical;
+ gctUINT32 execAddress;
+ gctUINT32 execBytes;
+
+ gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Compute offset for WAIT/LINK. */
+ waitLinkOffset = Command->offset + RequestedBytes;
+
+ /* Compute number of bytes left in command queue. */
+ waitLinkBytes = Command->pageSize - waitLinkOffset;
+
+ /* Compute the location if WAIT/LINK command sequence. */
+ waitLinkPhysical = Command->physical + waitLinkOffset;
+ waitLinkLogical = (gctUINT8_PTR) Command->logical + waitLinkOffset;
+
+ /* Append WAIT/LINK in command queue. */
+ gcmkONERROR(gckHARDWARE_WaitLink(
+ Command->kernel->hardware,
+ waitLinkLogical,
+ waitLinkOffset,
+ &waitLinkBytes,
+ &waitOffset,
+ &waitBytes
+ ));
+
+ /* Compute the location if WAIT command. */
+ waitPhysical = waitLinkPhysical + waitOffset;
+ waitLogical = waitLinkLogical + waitOffset;
+
+ /* Determine the location to jump to for the command buffer being
+ ** scheduled. */
+ if (Command->newQueue)
+ {
+ /* New command queue, jump to the beginning of it. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ execPhysical = Command->physical;
+#endif
+ execLogical = Command->logical;
+ execAddress = Command->address;
+ execBytes = waitLinkOffset + waitLinkBytes;
+ }
+ else
+ {
+ /* Still within the preexisting command queue, jump directly to the
+ reserved area. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ execPhysical = (gctUINT8 *) Command->physical + Command->offset;
+#endif
+ execLogical = (gctUINT8 *) Command->logical + Command->offset;
+ execAddress = Command->address + Command->offset;
+ execBytes = RequestedBytes + waitLinkBytes;
+ }
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)execPhysical,
+ execLogical,
+ execBytes
+ ));
+#endif
+
+ /* Convert the last WAIT into a LINK. */
+ gcmkONERROR(gckHARDWARE_Link(
+ Command->kernel->hardware,
+ Command->waitLogical,
+ execAddress,
+ execBytes,
+ &Command->waitSize,
+ &linkLow,
+ &linkHigh
+ ));
+
+#if gcdLINK_QUEUE_SIZE
+ if (Command->kernel->stuckDump >= gcvSTUCK_DUMP_ALL_COMMAND)
+ {
+ gckLINKQUEUE_Enqueue(
+ &Command->kernel->hardware->linkQueue,
+ execAddress,
+ execAddress + execBytes,
+ linkLow,
+ linkHigh
+ );
+ }
+#endif
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)Command->waitPhysical,
+ Command->waitLogical,
+ Command->waitSize
+ ));
+#endif
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ Command->waitLogical,
+ Command->waitSize,
+ gceDUMP_BUFFER_LINK,
+ gcvFALSE
+ );
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ execLogical,
+ execBytes,
+ gceDUMP_BUFFER_KERNEL,
+ gcvFALSE
+ );
+
+ /* Update the pointer to the last WAIT. */
+ Command->waitPhysical = waitPhysical;
+ Command->waitLogical = waitLogical;
+ Command->waitSize = waitBytes;
+
+ /* Update the command queue. */
+ Command->offset += RequestedBytes + waitLinkBytes;
+ Command->newQueue = gcvFALSE;
+
+ /* Update queue tail pointer. */
+ gcmkONERROR(gckHARDWARE_UpdateQueueTail(
+ Command->kernel->hardware, Command->logical, Command->offset
+ ));
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.execute]");
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Stall
+**
+** The calling thread will be suspended until the command queue has been
+** completed.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** gctBOOL FromPower
+** Determines whether the call originates from inside the power
+** management or not.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+#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. */
+ return gcvSTATUS_OK;
+#else
+ gckOS os;
+ gckHARDWARE hardware;
+ gckEVENT eventObject;
+ gceSTATUS status;
+ gctSIGNAL signal = gcvNULL;
+ gctUINT timer = 0;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Extract the gckOS object pointer. */
+ os = Command->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Extract the gckHARDWARE object pointer. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Extract the gckEVENT object pointer. */
+ eventObject = Command->kernel->eventObj;
+ gcmkVERIFY_OBJECT(eventObject, gcvOBJ_EVENT);
+
+ /* Allocate the signal. */
+ gcmkONERROR(gckOS_CreateSignal(os, gcvTRUE, &signal));
+
+ /* Append the EVENT command to trigger the signal. */
+ gcmkONERROR(gckEVENT_Signal(eventObject, signal, gcvKERNEL_PIXEL));
+
+ /* Submit the event queue. */
+#if gcdMULTI_GPU
+ gcmkONERROR(gckEVENT_Submit(eventObject, gcvTRUE, FromPower, ChipEnable));
+#else
+ gcmkONERROR(gckEVENT_Submit(eventObject, gcvTRUE, FromPower));
+#endif
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.stall]");
+#endif
+
+ if (status == gcvSTATUS_CHIP_NOT_READY)
+ {
+ /* Error. */
+ goto OnError;
+ }
+
+ do
+ {
+ /* Wait for the signal. */
+ status = gckOS_WaitSignal(os, signal, gcdGPU_ADVANCETIMER);
+
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ gctUINT32 idle;
+
+ /* Read idle register. */
+ gcmkVERIFY_OK(gckHARDWARE_GetIdle(
+ hardware, gcvFALSE, &idle
+ ));
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): idle=%08x",
+ __FUNCTION__, __LINE__, idle
+ );
+
+ gcmkVERIFY_OK(gckOS_MemoryBarrier(os, gcvNULL));
+#endif
+
+ /* Advance timer. */
+ timer += gcdGPU_ADVANCETIMER;
+ }
+ else if (status == gcvSTATUS_INTERRUPTED)
+ {
+ gcmkONERROR(gcvSTATUS_INTERRUPTED);
+ }
+
+ }
+ while (gcmIS_ERROR(status));
+
+ /* Bail out on timeout. */
+ if (gcmIS_ERROR(status))
+ {
+ /* Broadcast the stuck GPU. */
+ gcmkONERROR(gckOS_Broadcast(
+ os, hardware, gcvBROADCAST_GPU_STUCK
+ ));
+ }
+
+ /* Delete the signal. */
+ gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (signal != gcvNULL)
+ {
+ /* Free the signal. */
+ gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+#endif
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Attach
+**
+** Attach user process.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to a gckCOMMAND object.
+**
+** gctUINT32 ProcessID
+** Current process ID.
+**
+** OUTPUT:
+**
+** gckCONTEXT * Context
+** Pointer to a variable that will receive a pointer to a new
+** gckCONTEXT object.
+**
+** gctSIZE_T * StateCount
+** Pointer to a variable that will receive the number of states
+** in the context buffer.
+*/
+#if (gcdENABLE_3D || gcdENABLE_2D)
+gceSTATUS
+gckCOMMAND_Attach(
+ IN gckCOMMAND Command,
+ OUT gckCONTEXT * Context,
+ OUT gctSIZE_T * MaxState,
+ OUT gctUINT32 * NumStates,
+ IN gctUINT32 ProcessID
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Acquire the context switching mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ Command->os, Command->mutexContext, gcvINFINITE
+ ));
+ acquired = gcvTRUE;
+
+ /* Construct a gckCONTEXT object. */
+ gcmkONERROR(gckCONTEXT_Construct(
+ Command->os,
+ Command->kernel->hardware,
+ ProcessID,
+ Context
+ ));
+
+ /* Return the number of states in the context. */
+ * MaxState = (* Context)->maxState;
+ * NumStates = (* Context)->numStates;
+
+ /* Release the context switching mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ acquired = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Context=0x%x", *Context);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Release mutex. */
+ if (acquired)
+ {
+ /* Release the context switching mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ acquired = gcvFALSE;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckCOMMAND_Detach
+**
+** Detach user process.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to a gckCOMMAND object.
+**
+** gckCONTEXT Context
+** Pointer to a gckCONTEXT object to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Detach(
+ IN gckCOMMAND Command,
+ IN gckCONTEXT Context
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x Context=0x%x", Command, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Acquire the context switching mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ Command->os, Command->mutexContext, gcvINFINITE
+ ));
+ acquired = gcvTRUE;
+
+ /* Construct a gckCONTEXT object. */
+ gcmkONERROR(gckCONTEXT_Destroy(Context));
+
+ if (Command->currContext == Context)
+ {
+ /* Detach from gckCOMMAND object if the destoryed context is current context. */
+ Command->currContext = gcvNULL;
+ }
+
+ /* Release the context switching mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ acquired = gcvFALSE;
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Release mutex. */
+ if (acquired)
+ {
+ /* Release the context switching mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ acquired = gcvFALSE;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_DumpExecutingBuffer
+**
+** Dump the command buffer which GPU is executing.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to a gckCOMMAND object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_DumpExecutingBuffer(
+ IN gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gckVIRTUAL_COMMAND_BUFFER_PTR buffer = gcvNULL;
+ gctUINT32 gpuAddress;
+ gctSIZE_T pageCount;
+ gctPOINTER entry;
+ gckOS os = Command->os;
+ gckKERNEL kernel = Command->kernel;
+ gctUINT32 i;
+ gctUINT32 dumpRear;
+ gckLINKQUEUE queue = &kernel->hardware->linkQueue;
+ gctSIZE_T bytes;
+ gckLINKDATA linkData;
+ gctUINT32 offset;
+ gctPOINTER entryDump;
+ gctUINT32 pid;
+ gctUINT8 processName[24] = {0};
+
+ gcmkPRINT("**************************\n");
+ gcmkPRINT("**** COMMAND BUF DUMP ****\n");
+ gcmkPRINT("**************************\n");
+
+ gcmkPRINT(" Submitted commit stamp = %lld", Command->commitStamp - 1);
+ gcmkPRINT(" Executed commit stamp = %lld", *(gctUINT64_PTR)Command->fence->logical);
+
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(os, kernel->core, 0x664, &gpuAddress));
+
+ gcmkPRINT("DMA Address 0x%08X, memory around:", gpuAddress);
+
+ /* Search and dump memory around DMA address. */
+ if (kernel->virtualCommandBuffer)
+ {
+ status = gckKERNEL_QueryGPUAddress(kernel, gpuAddress, &buffer);
+ }
+ else
+ {
+ status = gcvSTATUS_OK;
+ }
+
+ if (gcmIS_SUCCESS(status))
+ {
+ if (kernel->virtualCommandBuffer)
+ {
+ gcmkVERIFY_OK(gckOS_CreateKernelVirtualMapping(
+ os, buffer->physical, buffer->bytes, &entry, &pageCount));
+
+ offset = gpuAddress - buffer->gpuAddress;
+
+ entryDump = entry;
+
+ /* Dump one pages. */
+ bytes = 4096;
+
+ /* Align to page. */
+ offset &= 0xfffff000;
+
+ /* Kernel address of page where stall point stay. */
+ entryDump = (gctUINT8_PTR)entryDump + offset;
+
+ /* Align to page. */
+ gpuAddress &= 0xfffff000;
+ }
+ else
+ {
+ gcmkVERIFY_OK(gckOS_MapPhysical(os, gpuAddress, 4096, &entry));
+
+ /* Align to page start. */
+ entryDump = (gctPOINTER)((gctUINTPTR_T)entry & ~0xFFF);
+ gpuAddress = gpuAddress & ~0xFFF;
+ bytes = 4096;
+ }
+
+ gcmkPRINT("User Command Buffer:\n");
+ _DumpBuffer(entryDump, gpuAddress, bytes);
+
+ if (kernel->virtualCommandBuffer)
+ {
+ gcmkVERIFY_OK(gckOS_DestroyKernelVirtualMapping(
+ os, buffer->physical, buffer->bytes, entry));
+ }
+ else
+ {
+ gcmkVERIFY_OK(gckOS_UnmapPhysical(os, entry, 4096));
+ }
+ }
+ else
+ {
+ _DumpKernelCommandBuffer(Command);
+ }
+
+ /* Dump link queue. */
+ if (queue->count)
+ {
+ gcmkPRINT("Dump Level is %d, dump %d valid record in link queue:",
+ Command->kernel->stuckDump, queue->count);
+
+ dumpRear = queue->count;
+
+ for (i = 0; i < dumpRear; i++)
+ {
+ gckLINKQUEUE_GetData(queue, i, &linkData);
+
+ /* Get gpu address of this command buffer. */
+ gpuAddress = linkData->start;
+ bytes = linkData->end - gpuAddress;
+
+ pid = linkData->pid;
+
+ gckOS_GetProcessNameByPid(pid, 16, processName);
+
+ if (kernel->virtualCommandBuffer)
+ {
+ buffer = gcvNULL;
+
+ /* Get the whole buffer. */
+ status = gckKERNEL_QueryGPUAddress(kernel, gpuAddress, &buffer);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Get kernel address of kernel command buffer. */
+ status = gckCOMMAND_AddressInKernelCommandBuffer(
+ kernel->command, gpuAddress, &entry);
+
+ if (gcmIS_ERROR(status))
+ {
+ status = gckHARDWARE_AddressInHardwareFuncions(
+ kernel->hardware, gpuAddress, &entry);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkPRINT("Buffer [%08X - %08X] not found, may be freed",
+ linkData->start,
+ linkData->end);
+ continue;
+ }
+ }
+
+ offset = 0;
+ gcmkPRINT("Kernel Command Buffer: %08X, %08X", linkData->linkLow, linkData->linkHigh);
+ }
+ else
+ {
+ /* Get kernel logical for dump. */
+ if (buffer->kernelLogical)
+ {
+ /* Get kernel logical directly if it is a context buffer. */
+ entry = buffer->kernelLogical;
+ gcmkPRINT("Context Buffer: %08X, %08X PID:%d %s",
+ linkData->linkLow, linkData->linkHigh, linkData->pid, processName);
+ }
+ 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: %08X, %08X PID:%d %s",
+ linkData->linkLow, linkData->linkHigh, linkData->pid, processName);
+ }
+
+ offset = gpuAddress - buffer->gpuAddress;
+ }
+
+ /* Dump from the entry. */
+ _DumpBuffer((gctUINT8_PTR)entry + offset, gpuAddress, bytes);
+
+ /* Release kernel logical address if neccessary. */
+ if (buffer && !buffer->kernelLogical)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DestroyKernelVirtualMapping(os,
+ buffer->physical,
+ buffer->bytes,
+ entry));
+ }
+ }
+ else
+ {
+ gcmkVERIFY_OK(gckOS_MapPhysical(os, gpuAddress, bytes, &entry));
+
+ gcmkPRINT("Command Buffer: %08X, %08X PID:%d %s",
+ linkData->linkLow, linkData->linkHigh, linkData->pid, processName);
+
+ _DumpBuffer((gctUINT8_PTR)entry, gpuAddress, bytes);
+
+ gcmkVERIFY_OK(gckOS_UnmapPhysical(os, entry, bytes));
+ }
+ }
+ }
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckCOMMAND_AddressInKernelCommandBuffer(
+ IN gckCOMMAND Command,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * Pointer
+ )
+{
+ gctINT i;
+
+ for (i = 0; i < gcdCOMMAND_QUEUES; i++)
+ {
+ if ((Address >= Command->queues[i].address)
+ && (Address < (Command->queues[i].address + Command->pageSize))
+ )
+ {
+ *Pointer = (gctUINT8_PTR)Command->queues[i].logical
+ + (Address - Command->queues[i].address)
+ ;
+
+ return gcvSTATUS_OK;
+ }
+ }
+
+ return gcvSTATUS_NOT_FOUND;
+}
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
new file mode 100644
index 000000000000..1ae1c62de2d3
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
@@ -0,0 +1,3850 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdENABLE_VG
+
+#include "gc_hal_kernel_hardware_command_vg.h"
+
+#define _GC_OBJ_ZONE gcvZONE_COMMAND
+
+#ifdef __QNXNTO__
+extern gceSTATUS
+drv_signal_mgr_add(
+ gctUINT32 Pid,
+ gctINT32 Coid,
+ gctINT32 Rcvid,
+ gctUINT64 Signal,
+ gctPOINTER *Handle);
+#endif
+
+/******************************************************************************\
+*********************************** Debugging **********************************
+\******************************************************************************/
+
+#define gcvDISABLE_TIMEOUT 1
+#define gcvDUMP_COMMAND_BUFFER 0
+#define gcvDUMP_COMMAND_LINES 0
+
+
+#if gcvDEBUG || defined(EMULATOR) || gcvDISABLE_TIMEOUT
+# define gcvQUEUE_TIMEOUT ~0
+#else
+# define gcvQUEUE_TIMEOUT 10
+#endif
+
+
+/******************************************************************************\
+********************************** Definitions *********************************
+\******************************************************************************/
+
+/* Minimum buffer size. */
+#define gcvMINUMUM_BUFFER \
+ gcmSIZEOF(gcsKERNEL_QUEUE_HEADER) + \
+ gcmSIZEOF(gcsKERNEL_CMDQUEUE) * 2
+
+#define gcmDECLARE_INTERRUPT_HANDLER(Block, Number) \
+ static gceSTATUS \
+ _EventHandler_##Block##_##Number( \
+ IN gckVGKERNEL Kernel \
+ )
+
+#define gcmDEFINE_INTERRUPT_HANDLER(Block, Number) \
+ gcmDECLARE_INTERRUPT_HANDLER(Block, Number) \
+ { \
+ return _EventHandler_Block( \
+ Kernel, \
+ &Kernel->command->taskTable[gcvBLOCK_##Block], \
+ gcvFALSE \
+ ); \
+ }
+
+#define gcmDEFINE_INTERRUPT_HANDLER_ENTRY(Block, Number) \
+ { gcvBLOCK_##Block, _EventHandler_##Block##_##Number }
+
+/* Block interrupt handling table entry. */
+typedef struct _gcsBLOCK_INTERRUPT_HANDLER * gcsBLOCK_INTERRUPT_HANDLER_PTR;
+typedef struct _gcsBLOCK_INTERRUPT_HANDLER
+{
+ gceBLOCK block;
+ gctINTERRUPT_HANDLER handler;
+}
+gcsBLOCK_INTERRUPT_HANDLER;
+
+/* Queue control functions. */
+typedef struct _gcsQUEUE_UPDATE_CONTROL * gcsQUEUE_UPDATE_CONTROL_PTR;
+typedef struct _gcsQUEUE_UPDATE_CONTROL
+{
+ gctOBJECT_HANDLER execute;
+ gctOBJECT_HANDLER update;
+ gctOBJECT_HANDLER lastExecute;
+ gctOBJECT_HANDLER lastUpdate;
+}
+gcsQUEUE_UPDATE_CONTROL;
+
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+static gceSTATUS
+_FlushMMU(
+ IN gckVGCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gctUINT32 oldValue;
+ gckVGHARDWARE hardware = Command->hardware;
+
+ gcmkONERROR(gckOS_AtomicExchange(Command->os,
+ hardware->pageTableDirty,
+ 0,
+ &oldValue));
+
+ if (oldValue)
+ {
+ /* Page Table is upated, flush mmu before commit. */
+ gcmkONERROR(gckVGHARDWARE_FlushMMU(hardware));
+ }
+
+ return gcvSTATUS_OK;
+OnError:
+ return status;
+}
+
+static gceSTATUS
+_WaitForIdle(
+ IN gckVGCOMMAND Command,
+ IN gcsKERNEL_QUEUE_HEADER_PTR Queue
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctUINT32 idle;
+ gctUINT timeout = 0;
+
+ /* Loop while not idle. */
+ while (Queue->pending)
+ {
+ /* Did we reach the timeout limit? */
+ if (timeout == gcvQUEUE_TIMEOUT)
+ {
+ /* Hardware is probably dead... */
+ return gcvSTATUS_TIMEOUT;
+ }
+
+ /* Sleep for 100ms. */
+ gcmkERR_BREAK(gckOS_Delay(Command->os, 100));
+
+ /* Not the first loop? */
+ if (timeout > 0)
+ {
+ /* Read IDLE register. */
+ gcmkVERIFY_OK(gckVGHARDWARE_GetIdle(Command->hardware, &idle));
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_COMMAND,
+ "%s: timeout, IDLE=%08X\n",
+ __FUNCTION__, idle
+ );
+ }
+
+ /* Increment the timeout counter. */
+ timeout += 1;
+ }
+
+ /* Return status. */
+ return status;
+}
+
+static gctINT32
+_GetNextInterrupt(
+ IN gckVGCOMMAND Command,
+ IN gceBLOCK Block
+ )
+{
+ gctUINT index;
+ gcsBLOCK_TASK_ENTRY_PTR entry;
+ gctINT32 interrupt;
+
+ /* Get the block entry. */
+ entry = &Command->taskTable[Block];
+
+ /* Make sure we have initialized interrupts. */
+ gcmkASSERT(entry->interruptCount > 0);
+
+ /* Decrement the interrupt usage semaphore. */
+ gcmkVERIFY_OK(gckOS_DecrementSemaphore(
+ Command->os, entry->interruptSemaphore
+ ));
+
+ /* Get the value index. */
+ index = entry->interruptIndex;
+
+ /* Get the interrupt value. */
+ interrupt = entry->interruptArray[index];
+
+ /* Must be a valid value. */
+ gcmkASSERT((interrupt >= 0) && (interrupt <= 31));
+
+ /* Advance the index to the next value. */
+ index += 1;
+
+ /* Set the new index. */
+ entry->interruptIndex = (index == entry->interruptCount)
+ ? 0
+ : index;
+
+ /* Return interrupt value. */
+ return interrupt;
+}
+
+
+/******************************************************************************\
+***************************** Task Storage Management **************************
+\******************************************************************************/
+
+/* Minimum task buffer size. */
+#define gcvMIN_TASK_BUFFER \
+( \
+ gcmSIZEOF(gcsTASK_CONTAINER) + 128 \
+)
+
+/* Free list terminator. */
+#define gcvFREE_TASK_TERMINATOR \
+( \
+ (gcsTASK_CONTAINER_PTR) gcmINT2PTR(~0) \
+)
+
+
+/*----------------------------------------------------------------------------*/
+/*------------------- Allocated Task Buffer List Management ------------------*/
+
+static void
+_InsertTaskBuffer(
+ IN gcsTASK_CONTAINER_PTR AddAfter,
+ IN gcsTASK_CONTAINER_PTR Buffer
+ )
+{
+ gcsTASK_CONTAINER_PTR addBefore;
+
+ /* Cannot add before the first buffer. */
+ gcmkASSERT(AddAfter != gcvNULL);
+
+ /* Create a shortcut to the next buffer. */
+ addBefore = AddAfter->allocNext;
+
+ /* Initialize the links. */
+ Buffer->allocPrev = AddAfter;
+ Buffer->allocNext = addBefore;
+
+ /* Link to the previous buffer. */
+ AddAfter->allocNext = Buffer;
+
+ /* Link to the next buffer. */
+ if (addBefore != gcvNULL)
+ {
+ addBefore->allocPrev = Buffer;
+ }
+}
+
+static void
+_RemoveTaskBuffer(
+ IN gcsTASK_CONTAINER_PTR Buffer
+ )
+{
+ gcsTASK_CONTAINER_PTR prev;
+ gcsTASK_CONTAINER_PTR next;
+
+ /* Cannot remove the first buffer. */
+ gcmkASSERT(Buffer->allocPrev != gcvNULL);
+
+ /* Create shortcuts to the previous and next buffers. */
+ prev = Buffer->allocPrev;
+ next = Buffer->allocNext;
+
+ /* Tail buffer? */
+ if (next == gcvNULL)
+ {
+ /* Remove from the list. */
+ prev->allocNext = gcvNULL;
+ }
+
+ /* Buffer from the middle. */
+ else
+ {
+ prev->allocNext = next;
+ next->allocPrev = prev;
+ }
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*--------------------- Free Task Buffer List Management ---------------------*/
+
+static void
+_AppendToFreeList(
+ IN gckVGCOMMAND Command,
+ IN gcsTASK_CONTAINER_PTR Buffer
+ )
+{
+ /* Cannot be a part of the free list already. */
+ gcmkASSERT(Buffer->freePrev == gcvNULL);
+ gcmkASSERT(Buffer->freeNext == gcvNULL);
+
+ /* First buffer to add? */
+ if (Command->taskFreeHead == gcvNULL)
+ {
+ /* Terminate the links. */
+ Buffer->freePrev = gcvFREE_TASK_TERMINATOR;
+ Buffer->freeNext = gcvFREE_TASK_TERMINATOR;
+
+ /* Initialize the list pointer. */
+ Command->taskFreeHead = Command->taskFreeTail = Buffer;
+ }
+
+ /* Not the first, add after the tail. */
+ else
+ {
+ /* Initialize the new tail buffer. */
+ Buffer->freePrev = Command->taskFreeTail;
+ Buffer->freeNext = gcvFREE_TASK_TERMINATOR;
+
+ /* Add after the tail. */
+ Command->taskFreeTail->freeNext = Buffer;
+ Command->taskFreeTail = Buffer;
+ }
+}
+
+static void
+_RemoveFromFreeList(
+ IN gckVGCOMMAND Command,
+ IN gcsTASK_CONTAINER_PTR Buffer
+ )
+{
+ /* Has to be a part of the free list. */
+ gcmkASSERT(Buffer->freePrev != gcvNULL);
+ gcmkASSERT(Buffer->freeNext != gcvNULL);
+
+ /* Head buffer? */
+ if (Buffer->freePrev == gcvFREE_TASK_TERMINATOR)
+ {
+ /* Tail buffer as well? */
+ if (Buffer->freeNext == gcvFREE_TASK_TERMINATOR)
+ {
+ /* Reset the list pointer. */
+ Command->taskFreeHead = Command->taskFreeTail = gcvNULL;
+ }
+
+ /* No, just the head. */
+ else
+ {
+ /* Update the head. */
+ Command->taskFreeHead = Buffer->freeNext;
+
+ /* Terminate the next buffer. */
+ Command->taskFreeHead->freePrev = gcvFREE_TASK_TERMINATOR;
+ }
+ }
+
+ /* Not the head. */
+ else
+ {
+ /* Tail buffer? */
+ if (Buffer->freeNext == gcvFREE_TASK_TERMINATOR)
+ {
+ /* Update the tail. */
+ Command->taskFreeTail = Buffer->freePrev;
+
+ /* Terminate the previous buffer. */
+ Command->taskFreeTail->freeNext = gcvFREE_TASK_TERMINATOR;
+ }
+
+ /* A buffer in the middle. */
+ else
+ {
+ /* Remove the buffer from the list. */
+ Buffer->freePrev->freeNext = Buffer->freeNext;
+ Buffer->freeNext->freePrev = Buffer->freePrev;
+ }
+ }
+
+ /* Reset free list pointers. */
+ Buffer->freePrev = gcvNULL;
+ Buffer->freeNext = gcvNULL;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*-------------------------- Task Buffer Allocation --------------------------*/
+
+static void
+_SplitTaskBuffer(
+ IN gckVGCOMMAND Command,
+ IN gcsTASK_CONTAINER_PTR Buffer,
+ IN gctUINT Size
+ )
+{
+ /* Determine the size of the new buffer. */
+ gctINT splitBufferSize = Buffer->size - Size;
+ gcmkASSERT(splitBufferSize >= 0);
+
+ /* Is the split buffer big enough to become a separate buffer? */
+ if (splitBufferSize >= gcvMIN_TASK_BUFFER)
+ {
+ /* Place the new path data. */
+ gcsTASK_CONTAINER_PTR splitBuffer = (gcsTASK_CONTAINER_PTR)
+ (
+ (gctUINT8_PTR) Buffer + Size
+ );
+
+ /* Set the trimmed buffer size. */
+ Buffer->size = Size;
+
+ /* Initialize the split buffer. */
+ splitBuffer->referenceCount = 0;
+ splitBuffer->size = splitBufferSize;
+ splitBuffer->freePrev = gcvNULL;
+ splitBuffer->freeNext = gcvNULL;
+
+ /* Link in. */
+ _InsertTaskBuffer(Buffer, splitBuffer);
+ _AppendToFreeList(Command, splitBuffer);
+ }
+}
+
+static gceSTATUS
+_AllocateTaskContainer(
+ IN gckVGCOMMAND Command,
+ IN gctUINT Size,
+ OUT gcsTASK_CONTAINER_PTR * Buffer
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Command=0x%x Size=0x%x, Buffer ==0x%x", Command, Size, Buffer);
+
+ /* Verify arguments. */
+ gcmkVERIFY_ARGUMENT(Buffer != gcvNULL);
+
+ do
+ {
+ gcsTASK_STORAGE_PTR storage;
+ gcsTASK_CONTAINER_PTR buffer;
+
+ /* Adjust the size. */
+ Size += gcmSIZEOF(gcsTASK_CONTAINER);
+
+ /* Adjust the allocation size if not big enough. */
+ if (Size > Command->taskStorageUsable)
+ {
+ Command->taskStorageGranularity
+ = gcmALIGN(Size + gcmSIZEOF(gcsTASK_STORAGE), 1024);
+
+ Command->taskStorageUsable
+ = Command->taskStorageGranularity - gcmSIZEOF(gcsTASK_STORAGE);
+ }
+
+ /* Is there a free buffer available? */
+ else if (Command->taskFreeHead != gcvNULL)
+ {
+ /* Set the initial free buffer. */
+ gcsTASK_CONTAINER_PTR buffer = Command->taskFreeHead;
+
+ do
+ {
+ /* Is the buffer big enough? */
+ if (buffer->size >= Size)
+ {
+ /* Remove the buffer from the free list. */
+ _RemoveFromFreeList(Command, buffer);
+
+ /* Split the buffer. */
+ _SplitTaskBuffer(Command, buffer, Size);
+
+ /* Set the result. */
+ * Buffer = buffer;
+
+ gcmkFOOTER_ARG("*Buffer=0x%x",*Buffer);
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+
+ /* Get the next free buffer. */
+ buffer = buffer->freeNext;
+ }
+ while (buffer != gcvFREE_TASK_TERMINATOR);
+ }
+
+ /* Allocate a container. */
+ gcmkERR_BREAK(gckOS_Allocate(
+ Command->os,
+ Command->taskStorageGranularity,
+ (gctPOINTER *) &storage
+ ));
+
+ /* Link in the storage buffer. */
+ storage->next = Command->taskStorage;
+ Command->taskStorage = storage;
+
+ /* Place the task buffer. */
+ buffer = (gcsTASK_CONTAINER_PTR) (storage + 1);
+
+ /* Determine the size of the buffer. */
+ buffer->size
+ = Command->taskStorageGranularity
+ - gcmSIZEOF(gcsTASK_STORAGE);
+
+ /* Initialize the task buffer. */
+ buffer->referenceCount = 0;
+ buffer->allocPrev = gcvNULL;
+ buffer->allocNext = gcvNULL;
+ buffer->freePrev = gcvNULL;
+ buffer->freeNext = gcvNULL;
+
+ /* Split the buffer. */
+ _SplitTaskBuffer(Command, buffer, Size);
+
+ /* Set the result. */
+ * Buffer = buffer;
+
+ gcmkFOOTER_ARG("*Buffer=0x%x",*Buffer);
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+static void
+_FreeTaskContainer(
+ IN gckVGCOMMAND Command,
+ IN gcsTASK_CONTAINER_PTR Buffer
+ )
+{
+ gcsTASK_CONTAINER_PTR prev;
+ gcsTASK_CONTAINER_PTR next;
+ gcsTASK_CONTAINER_PTR merged;
+
+ gctUINT32 mergedSize;
+
+ /* Verify arguments. */
+ gcmkASSERT(Buffer != gcvNULL);
+ gcmkASSERT(Buffer->freePrev == gcvNULL);
+ gcmkASSERT(Buffer->freeNext == gcvNULL);
+
+ /* Get shortcuts to the previous and next path data buffers. */
+ prev = Buffer->allocPrev;
+ next = Buffer->allocNext;
+
+ /* Is the previous path data buffer already free? */
+ if (prev && prev->freeNext)
+ {
+ /* The previous path data buffer is the one that remains. */
+ merged = prev;
+
+ /* Is the next path data buffer already free? */
+ if (next && next->freeNext)
+ {
+ /* Merge all three path data buffers into the previous. */
+ mergedSize = prev->size + Buffer->size + next->size;
+
+ /* Remove the next path data buffer. */
+ _RemoveFromFreeList(Command, next);
+ _RemoveTaskBuffer(next);
+ }
+ else
+ {
+ /* Merge the current path data buffer into the previous. */
+ mergedSize = prev->size + Buffer->size;
+ }
+
+ /* Delete the current path data buffer. */
+ _RemoveTaskBuffer(Buffer);
+
+ /* Set new size. */
+ merged->size = mergedSize;
+ }
+ else
+ {
+ /* The current path data buffer is the one that remains. */
+ merged = Buffer;
+
+ /* Is the next buffer already free? */
+ if (next && next->freeNext)
+ {
+ /* Merge the next into the current. */
+ mergedSize = Buffer->size + next->size;
+
+ /* Remove the next buffer. */
+ _RemoveFromFreeList(Command, next);
+ _RemoveTaskBuffer(next);
+
+ /* Set new size. */
+ merged->size = mergedSize;
+ }
+
+ /* Add the current buffer into the free list. */
+ _AppendToFreeList(Command, merged);
+ }
+}
+
+gceSTATUS
+_RemoveRecordFromProcesDB(
+ IN gckVGCOMMAND Command,
+ 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;
+
+ gcmkVERIFY_OK(gckOS_GetProcessID((gctUINT32_PTR)&pid));
+
+ do
+ {
+ switch (Task->id)
+ {
+ 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,
+ type,
+ gcmINT2PTR(handle)));
+
+ /* Advance to next task. */
+ size -= sizeof(gcsTASK_FREE_VIDEO_MEMORY);
+ Task = (gcsTASK_HEADER_PTR)(freeVideoMemory + 1);
+
+ break;
+ case gcvTASK_UNLOCK_VIDEO_MEMORY:
+ unlockVideoMemory = (gcsTASK_UNLOCK_VIDEO_MEMORY_PTR)Task;
+
+ /* Remove record from process db. */
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Command->kernel->kernel,
+ pid,
+ 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);
+
+ break;
+ default:
+ /* Skip the whole task. */
+ size = 0;
+ break;
+ }
+ }
+ while(size);
+
+ return gcvSTATUS_OK;
+}
+
+/******************************************************************************\
+********************************* Task Scheduling ******************************
+\******************************************************************************/
+
+static gceSTATUS
+_ScheduleTasks(
+ IN gckVGCOMMAND Command,
+ IN gcsTASK_MASTER_TABLE_PTR TaskTable,
+ IN gctUINT8_PTR PreviousEnd
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ gctINT block;
+ gcsTASK_CONTAINER_PTR container;
+ gcsTASK_MASTER_ENTRY_PTR userTaskEntry;
+ gcsBLOCK_TASK_ENTRY_PTR kernelTaskEntry;
+ gcsTASK_PTR userTask;
+ gctUINT8_PTR kernelTask;
+ gctINT32 interrupt;
+ gctUINT8_PTR eventCommand;
+
+#ifdef __QNXNTO__
+ gcsTASK_PTR oldUserTask = gcvNULL;
+ gctPOINTER pointer;
+#endif
+
+ /* Nothing to schedule? */
+ if (TaskTable->size == 0)
+ {
+ status = gcvSTATUS_OK;
+ break;
+ }
+
+ /* Acquire the mutex. */
+ gcmkERR_BREAK(gckOS_AcquireMutex(
+ Command->os,
+ Command->taskMutex,
+ gcvINFINITE
+ ));
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d)\n",
+ __FUNCTION__, __LINE__
+ );
+
+ do
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " number of tasks scheduled = %d\n"
+ " size of event data in bytes = %d\n",
+ TaskTable->count,
+ TaskTable->size
+ );
+
+ /* Allocate task buffer. */
+ gcmkERR_BREAK(_AllocateTaskContainer(
+ Command,
+ TaskTable->size,
+ &container
+ ));
+
+ /* Determine the task data pointer. */
+ kernelTask = (gctUINT8_PTR) (container + 1);
+
+ /* Initialize the reference count. */
+ container->referenceCount = TaskTable->count;
+
+ /* Process tasks. */
+ for (block = gcvBLOCK_COUNT - 1; block >= 0; block -= 1)
+ {
+ /* Get the current user table entry. */
+ userTaskEntry = &TaskTable->table[block];
+
+ /* Are there tasks scheduled? */
+ if (userTaskEntry->head == gcvNULL)
+ {
+ /* No, skip to the next block. */
+ continue;
+ }
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " processing tasks for block %d\n",
+ block
+ );
+
+ /* Get the current kernel table entry. */
+ kernelTaskEntry = &Command->taskTable[block];
+
+ /* Are there tasks for the current block scheduled? */
+ if (kernelTaskEntry->container == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " first task container for the block added\n",
+ block
+ );
+
+ /* Nothing yet, set the container buffer pointer. */
+ kernelTaskEntry->container = container;
+ kernelTaskEntry->task = (gcsTASK_HEADER_PTR) kernelTask;
+ }
+
+ /* Yes, append to the end. */
+ else
+ {
+ kernelTaskEntry->link->cotainer = container;
+ kernelTaskEntry->link->task = (gcsTASK_HEADER_PTR) kernelTask;
+ }
+
+ /* Set initial task. */
+ userTask = userTaskEntry->head;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " copying user tasks over to the kernel\n"
+ );
+
+ /* Copy tasks. */
+ do
+ {
+ 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));
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " task ID = %d, size = %d\n",
+ ((gcsTASK_HEADER_PTR) (userTask + 1))->id,
+ userTask->size
+ );
+
+ /* Copy the task data. */
+ gcmkVERIFY_OK(gckOS_MemCopy(
+ kernelTask, taskHeader, userTask->size
+ ));
+
+#ifdef __QNXNTO__
+ if (taskHeader->id == gcvTASK_SIGNAL)
+ {
+ gcsTASK_SIGNAL_PTR taskSignal = (gcsTASK_SIGNAL_PTR)kernelTask;
+ gctPOINTER signal;
+ gctUINT32 pid;
+
+ gcmkVERIFY_OK(gckOS_GetProcessID(&pid));
+
+ taskSignal->coid = TaskTable->coid;
+ taskSignal->rcvid = TaskTable->rcvid;
+
+ gcmkERR_BREAK(drv_signal_mgr_add(
+ pid,
+ taskSignal->coid,
+ taskSignal->rcvid,
+ gcmPTR_TO_UINT64(taskSignal->signal),
+ &signal));
+
+ taskSignal->signal = signal;
+ }
+#endif
+
+ /* 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);
+
+ /* Update link pointer in the header. */
+ kernelTaskEntry->link = (gcsTASK_LINK_PTR) kernelTask;
+
+ /* Initialize link task. */
+ kernelTaskEntry->link->id = gcvTASK_LINK;
+ kernelTaskEntry->link->cotainer = gcvNULL;
+ kernelTaskEntry->link->task = gcvNULL;
+
+ /* Advance the task data pointer. */
+ kernelTask += gcmSIZEOF(gcsTASK_LINK);
+ }
+ }
+ while (gcvFALSE);
+
+ /* Release the mutex. */
+ gcmkERR_BREAK(gckOS_ReleaseMutex(
+ Command->os,
+ Command->taskMutex
+ ));
+
+ /* Assign interrupts to the blocks. */
+ eventCommand = PreviousEnd;
+
+ for (block = gcvBLOCK_COUNT - 1; block >= 0; block -= 1)
+ {
+ /* Get the current user table entry. */
+ userTaskEntry = &TaskTable->table[block];
+
+ /* Are there tasks scheduled? */
+ if (userTaskEntry->head == gcvNULL)
+ {
+ /* No, skip to the next block. */
+ continue;
+ }
+
+ /* Get the interrupt number. */
+ interrupt = _GetNextInterrupt(Command, block);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): block = %d interrupt = %d\n",
+ __FUNCTION__, __LINE__,
+ block, interrupt
+ );
+
+ /* Determine the command position. */
+ eventCommand -= Command->info.eventCommandSize;
+
+ /* Append an EVENT command. */
+ gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
+ Command, eventCommand, block, interrupt, gcvNULL
+ ));
+ }
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+
+/******************************************************************************\
+******************************** Memory Management *****************************
+\******************************************************************************/
+
+static gceSTATUS
+_HardwareToKernel(
+ IN gckOS Os,
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM memory;
+ gctUINT32 offset;
+ gctUINT32 nodePhysical;
+ gctPOINTER *logical;
+ gctSIZE_T bytes;
+ status = gcvSTATUS_OK;
+
+ memory = Node->VidMem.memory;
+
+ 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
+ {
+ gcmkSAFECASTPHYSADDRT(nodePhysical, Node->Virtual.physicalAddress);
+ bytes = Node->Virtual.bytes;
+ logical = &Node->Virtual.kernelVirtual;
+ }
+
+ if (*logical == gcvNULL)
+ {
+ status = gckOS_MapPhysical(Os, nodePhysical, bytes, logical);
+
+ if (gcmkIS_ERROR(status))
+ {
+ return status;
+ }
+ }
+
+ offset = Address - nodePhysical;
+ *KernelPointer = (gctPOINTER)((gctUINT8_PTR)(*logical) + offset);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_ConvertUserCommandBufferPointer(
+ IN gckVGCOMMAND Command,
+ IN gcsCMDBUFFER_PTR UserCommandBuffer,
+ OUT gcsCMDBUFFER_PTR * KernelCommandBuffer
+ )
+{
+ gceSTATUS status, last;
+ gcsCMDBUFFER_PTR mappedUserCommandBuffer = gcvNULL;
+ gckKERNEL kernel = Command->kernel->kernel;
+ gctUINT32 pid;
+ gckVIDMEM_NODE node;
+
+ gckOS_GetProcessID(&pid);
+
+ do
+ {
+ gctUINT32 headerAddress;
+
+ /* Map the command buffer structure into the kernel space. */
+ gcmkERR_BREAK(gckOS_MapUserPointer(
+ Command->os,
+ UserCommandBuffer,
+ gcmSIZEOF(gcsCMDBUFFER),
+ (gctPOINTER *) &mappedUserCommandBuffer
+ ));
+
+ /* Determine the address of the header. */
+ headerAddress
+ = mappedUserCommandBuffer->address
+ - mappedUserCommandBuffer->bufferOffset;
+
+ gcmkERR_BREAK(gckVIDMEM_HANDLE_Lookup(
+ kernel,
+ pid,
+ gcmPTR2INT32(mappedUserCommandBuffer->node),
+ &node));
+
+ /* Translate the logical address to the kernel space. */
+ gcmkERR_BREAK(_HardwareToKernel(
+ Command->os,
+ node->node,
+ headerAddress,
+ (gctPOINTER *) KernelCommandBuffer
+ ));
+ }
+ while (gcvFALSE);
+
+ /* Unmap the user command buffer. */
+ if (mappedUserCommandBuffer != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_UnmapUserPointer(
+ Command->os,
+ UserCommandBuffer,
+ gcmSIZEOF(gcsCMDBUFFER),
+ mappedUserCommandBuffer
+ ));
+ }
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_AllocateLinear(
+ IN gckVGCOMMAND Command,
+ IN gctUINT Size,
+ IN gctUINT Alignment,
+ OUT gcuVIDMEM_NODE_PTR * Node,
+ OUT gctUINT32 * Address,
+ OUT gctPOINTER * Logical
+ )
+{
+ gceSTATUS status, last;
+ gctPOINTER logical;
+ gctPHYS_ADDR physical;
+ gctUINT32 address;
+ gctSIZE_T size = Size;
+ gctPHYS_ADDR_T paddr;
+
+ do
+ {
+ gcmkERR_BREAK(gckOS_AllocateContiguous(
+ Command->os,
+ gcvFALSE,
+ &size,
+ &physical,
+ &logical
+ ));
+
+ gcmkERR_BREAK(gckOS_GetPhysicalAddress(Command->os, logical, &paddr));
+
+ gcmkSAFECASTPHYSADDRT(address, paddr);
+
+ /* Set return values. */
+ * Node = physical;
+ * Address = address;
+ * Logical = logical;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Roll back. */
+ if (physical != gcvNULL)
+ {
+ /* Free the command buffer. */
+ gcmkCHECK_STATUS(gckOS_FreeContiguous(Command->os, physical, logical, size));
+ }
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_FreeLinear(
+ IN gckVGKERNEL Kernel,
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gctPOINTER Logical
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ do
+ {
+ gcmkERR_BREAK(gckOS_FreeContiguous(Kernel->os, Node, Logical, 1));
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+gceSTATUS
+_AllocateCommandBuffer(
+ IN gckVGCOMMAND Command,
+ IN gctSIZE_T Size,
+ OUT gcsCMDBUFFER_PTR * CommandBuffer
+ )
+{
+ gceSTATUS status, last;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+ gcsCMDBUFFER_PTR commandBuffer = gcvNULL;
+
+ do
+ {
+ gctUINT alignedHeaderSize;
+ gctUINT requestedSize;
+ gctUINT allocationSize;
+ gctUINT32 address = 0;
+ gctUINT8_PTR endCommand;
+
+ /* Determine the aligned header size. */
+ alignedHeaderSize
+ = (gctUINT32)gcmALIGN(gcmSIZEOF(gcsCMDBUFFER), Command->info.addressAlignment);
+
+ /* Align the requested size. */
+ requestedSize
+ = (gctUINT32)gcmALIGN(Size, Command->info.commandAlignment);
+
+ /* Determine the size of the buffer to allocate. */
+ allocationSize
+ = alignedHeaderSize
+ + requestedSize
+ + (gctUINT32)Command->info.staticTailSize;
+
+ /* Allocate the command buffer. */
+ gcmkERR_BREAK(_AllocateLinear(
+ Command,
+ allocationSize,
+ Command->info.addressAlignment,
+ &node,
+ &address,
+ (gctPOINTER *) &commandBuffer
+ ));
+
+ /* Initialize the structure. */
+ commandBuffer->completion = gcvVACANT_BUFFER;
+ commandBuffer->node = node;
+ commandBuffer->address = address + alignedHeaderSize;
+ commandBuffer->bufferOffset = alignedHeaderSize;
+ commandBuffer->size = requestedSize;
+ commandBuffer->offset = requestedSize;
+ commandBuffer->nextAllocated = gcvNULL;
+ commandBuffer->nextSubBuffer = gcvNULL;
+
+ /* Determine the data count. */
+ commandBuffer->dataCount
+ = (requestedSize + Command->info.staticTailSize)
+ / Command->info.commandAlignment;
+
+ /* Determine the location of the END command. */
+ endCommand
+ = (gctUINT8_PTR) commandBuffer
+ + alignedHeaderSize
+ + requestedSize;
+
+ /* Append an END command. */
+ gcmkERR_BREAK(gckVGCOMMAND_EndCommand(
+ Command,
+ endCommand,
+ Command->info.feBufferInt,
+ gcvNULL
+ ));
+
+ /* Set the return pointer. */
+ * CommandBuffer = commandBuffer;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Roll back. */
+ if (node != gcvNULL)
+ {
+ /* Free the command buffer. */
+ gcmkCHECK_STATUS(_FreeLinear(Command->kernel, node, commandBuffer));
+ }
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_FreeCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsCMDBUFFER_PTR CommandBuffer
+ )
+{
+ gceSTATUS status;
+
+ /* Free the buffer. */
+ status = _FreeLinear(Kernel, CommandBuffer->node, CommandBuffer);
+
+ /* Return status. */
+ return status;
+}
+
+
+/******************************************************************************\
+****************************** TS Overflow Handler *****************************
+\******************************************************************************/
+
+static gceSTATUS
+_EventHandler_TSOverflow(
+ IN gckVGKERNEL Kernel
+ )
+{
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): **** TS OVERFLOW ENCOUNTERED ****\n",
+ __FUNCTION__, __LINE__
+ );
+
+ return gcvSTATUS_OK;
+}
+
+
+/******************************************************************************\
+****************************** Bus Error Handler *******************************
+\******************************************************************************/
+
+static gceSTATUS
+_EventHandler_BusError(
+ IN gckVGKERNEL Kernel
+ )
+{
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): **** BUS ERROR ENCOUNTERED ****\n",
+ __FUNCTION__, __LINE__
+ );
+
+ return gcvSTATUS_OK;
+}
+
+/******************************************************************************\
+****************************** Power Stall Handler *******************************
+\******************************************************************************/
+
+static gceSTATUS
+_EventHandler_PowerStall(
+ IN gckVGKERNEL Kernel
+ )
+{
+ /* Signal. */
+ return gckOS_Signal(
+ Kernel->os,
+ Kernel->command->powerStallSignal,
+ gcvTRUE);
+}
+
+/******************************************************************************\
+******************************** Task Routines *********************************
+\******************************************************************************/
+
+typedef gceSTATUS (* gctTASKROUTINE) (
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskLink(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskCluster(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskIncrement(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskDecrement(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskSignal(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskLockdown(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskUnlockVideoMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskFreeVideoMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskFreeContiguousMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskUnmapUserMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gctTASKROUTINE _taskRoutine[] =
+{
+ _TaskLink, /* gcvTASK_LINK */
+ _TaskCluster, /* gcvTASK_CLUSTER */
+ _TaskIncrement, /* gcvTASK_INCREMENT */
+ _TaskDecrement, /* gcvTASK_DECREMENT */
+ _TaskSignal, /* gcvTASK_SIGNAL */
+ _TaskLockdown, /* gcvTASK_LOCKDOWN */
+ _TaskUnlockVideoMemory, /* gcvTASK_UNLOCK_VIDEO_MEMORY */
+ _TaskFreeVideoMemory, /* gcvTASK_FREE_VIDEO_MEMORY */
+ _TaskFreeContiguousMemory, /* gcvTASK_FREE_CONTIGUOUS_MEMORY */
+ _TaskUnmapUserMemory, /* gcvTASK_UNMAP_USER_MEMORY */
+};
+
+static gceSTATUS
+_TaskLink(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ /* Cast the task pointer. */
+ gcsTASK_LINK_PTR task = (gcsTASK_LINK_PTR) TaskHeader->task;
+
+ /* Save the pointer to the container. */
+ gcsTASK_CONTAINER_PTR container = TaskHeader->container;
+
+ /* No more tasks in the list? */
+ if (task->task == gcvNULL)
+ {
+ /* Reset the entry. */
+ TaskHeader->container = gcvNULL;
+ TaskHeader->task = gcvNULL;
+ TaskHeader->link = gcvNULL;
+ }
+ else
+ {
+ /* Update the entry. */
+ TaskHeader->container = task->cotainer;
+ TaskHeader->task = task->task;
+ }
+
+ /* Decrement the task buffer reference. */
+ gcmkASSERT(container->referenceCount >= 0);
+ if (container->referenceCount == 0)
+ {
+ /* Free the container. */
+ _FreeTaskContainer(Command, container);
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_TaskCluster(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ /* Cast the task pointer. */
+ gcsTASK_CLUSTER_PTR cluster = (gcsTASK_CLUSTER_PTR) TaskHeader->task;
+
+ /* Get the number of tasks. */
+ gctUINT taskCount = cluster->taskCount;
+
+ /* Advance to the next task. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (cluster + 1);
+
+ /* Perform all tasks in the cluster. */
+ while (taskCount)
+ {
+ /* Perform the current task. */
+ gcmkERR_BREAK(_taskRoutine[TaskHeader->task->id](
+ Command,
+ TaskHeader
+ ));
+
+ /* Update the task count. */
+ taskCount -= 1;
+ }
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskIncrement(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_INCREMENT_PTR task = (gcsTASK_INCREMENT_PTR) TaskHeader->task;
+
+ /* Convert physical into logical address. */
+ gctUINT32_PTR logical;
+ gcmkERR_BREAK(gckOS_MapPhysical(
+ Command->os,
+ task->address,
+ gcmSIZEOF(gctUINT32),
+ (gctPOINTER *) &logical
+ ));
+
+ /* Increment data. */
+ (* logical) += 1;
+
+ /* Unmap the physical memory. */
+ gcmkERR_BREAK(gckOS_UnmapPhysical(
+ Command->os,
+ logical,
+ gcmSIZEOF(gctUINT32)
+ ));
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskDecrement(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_DECREMENT_PTR task = (gcsTASK_DECREMENT_PTR) TaskHeader->task;
+
+ /* Convert physical into logical address. */
+ gctUINT32_PTR logical;
+ gcmkERR_BREAK(gckOS_MapPhysical(
+ Command->os,
+ task->address,
+ gcmSIZEOF(gctUINT32),
+ (gctPOINTER *) &logical
+ ));
+
+ /* Decrement data. */
+ (* logical) -= 1;
+
+ /* Unmap the physical memory. */
+ gcmkERR_BREAK(gckOS_UnmapPhysical(
+ Command->os,
+ logical,
+ gcmSIZEOF(gctUINT32)
+ ));
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskSignal(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_SIGNAL_PTR task = (gcsTASK_SIGNAL_PTR) TaskHeader->task;
+
+
+ /* Map the signal into kernel space. */
+#ifdef __QNXNTO__
+ gcmkERR_BREAK(gckOS_UserSignal(
+ Command->os, task->signal, task->rcvid, task->coid
+ ));
+#else
+ gcmkERR_BREAK(gckOS_UserSignal(
+ Command->os, task->signal, task->process
+ ));
+#endif /* __QNXNTO__ */
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskLockdown(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+ gctUINT32_PTR userCounter = gcvNULL;
+ gctUINT32_PTR kernelCounter = gcvNULL;
+ gctSIGNAL signal = gcvNULL;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_LOCKDOWN_PTR task = (gcsTASK_LOCKDOWN_PTR) TaskHeader->task;
+
+ /* Convert physical addresses into logical. */
+ gcmkERR_BREAK(gckOS_MapPhysical(
+ Command->os,
+ task->userCounter,
+ gcmSIZEOF(gctUINT32),
+ (gctPOINTER *) &userCounter
+ ));
+
+ gcmkERR_BREAK(gckOS_MapPhysical(
+ Command->os,
+ task->kernelCounter,
+ gcmSIZEOF(gctUINT32),
+ (gctPOINTER *) &kernelCounter
+ ));
+
+ /* Update the kernel counter. */
+ (* kernelCounter) += 1;
+
+ /* Are the counters equal? */
+ if ((* userCounter) == (* kernelCounter))
+ {
+ /* Map the signal into kernel space. */
+ gcmkERR_BREAK(gckOS_MapSignal(
+ Command->os, task->signal, task->process, &signal
+ ));
+
+ if (signal == gcvNULL)
+ {
+ /* Signal. */
+ gcmkERR_BREAK(gckOS_Signal(
+ Command->os, task->signal, gcvTRUE
+ ));
+ }
+ else
+ {
+ /* Signal. */
+ gcmkERR_BREAK(gckOS_Signal(
+ Command->os, signal, gcvTRUE
+ ));
+ }
+ }
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Destroy the mapped signal. */
+ if (signal != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySignal(
+ Command->os, signal
+ ));
+ }
+
+ /* Unmap the physical memory. */
+ if (kernelCounter != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapPhysical(
+ Command->os,
+ kernelCounter,
+ gcmSIZEOF(gctUINT32)
+ ));
+ }
+
+ if (userCounter != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapPhysical(
+ Command->os,
+ userCounter,
+ gcmSIZEOF(gctUINT32)
+ ));
+ }
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskUnlockVideoMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_UNLOCK_VIDEO_MEMORY_PTR task
+ = (gcsTASK_UNLOCK_VIDEO_MEMORY_PTR) TaskHeader->task;
+
+ /* Unlock video memory. */
+ gcmkERR_BREAK(gckVIDMEM_Unlock(
+ Command->kernel->kernel,
+ (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;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskFreeVideoMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_FREE_VIDEO_MEMORY_PTR task
+ = (gcsTASK_FREE_VIDEO_MEMORY_PTR) TaskHeader->task;
+
+ /* Free video memory. */
+ gcmkERR_BREAK(gckVIDMEM_NODE_Dereference(
+ Command->kernel->kernel,
+ gcmINT2PTR(task->node)));
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskFreeContiguousMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR task
+ = (gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR) TaskHeader->task;
+
+ /* Free contiguous memory. */
+ gcmkERR_BREAK(gckOS_FreeContiguous(
+ Command->os, task->physical, task->logical, task->bytes
+ ));
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskUnmapUserMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+ gctPOINTER info;
+
+ do
+ {
+ /* Cast the task pointer. */
+ 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, info, task->address
+ ));
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+/******************************************************************************\
+************ Hardware Block Interrupt Handlers For Scheduled Events ************
+\******************************************************************************/
+
+static gceSTATUS
+_EventHandler_Block(
+ IN gckVGKERNEL Kernel,
+ IN gcsBLOCK_TASK_ENTRY_PTR TaskHeader,
+ IN gctBOOL ProcessAll
+ )
+{
+ gceSTATUS status = 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;
+
+ /* Get the command buffer object. */
+ command = Kernel->command;
+
+ /* Increment the interrupt usage semaphore. */
+ gcmkERR_BREAK(gckOS_IncrementSemaphore(
+ command->os, TaskHeader->interruptSemaphore
+ ));
+
+ /* Acquire the mutex. */
+ gcmkERR_BREAK(gckOS_AcquireMutex(
+ command->os,
+ command->taskMutex,
+ gcvINFINITE
+ ));
+
+ /* Verify inputs. */
+ gcmkASSERT(TaskHeader != gcvNULL);
+ gcmkASSERT(TaskHeader->container != gcvNULL);
+ gcmkASSERT(TaskHeader->task != gcvNULL);
+ gcmkASSERT(TaskHeader->link != gcvNULL);
+
+ /* Process tasks. */
+ do
+ {
+ /* Process the current task. */
+ gcmkERR_BREAK(_taskRoutine[TaskHeader->task->id](
+ command,
+ TaskHeader
+ ));
+
+ /* Is the next task is LINK? */
+ if (TaskHeader->task->id == gcvTASK_LINK)
+ {
+ gcmkERR_BREAK(_taskRoutine[TaskHeader->task->id](
+ command,
+ TaskHeader
+ ));
+
+ /* Done. */
+ break;
+ }
+ }
+ while (ProcessAll);
+
+ /* Release the mutex. */
+ gcmkCHECK_STATUS(gckOS_ReleaseMutex(
+ command->os,
+ command->taskMutex
+ ));
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+gcmDECLARE_INTERRUPT_HANDLER(COMMAND, 0)
+{
+ gceSTATUS status, last;
+
+ gcmkHEADER_ARG("Kernel=0x%x ", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+
+ do
+ {
+ gckVGCOMMAND command;
+ gcsKERNEL_QUEUE_HEADER_PTR mergeQueue;
+ gcsKERNEL_QUEUE_HEADER_PTR queueTail;
+ gcsKERNEL_CMDQUEUE_PTR entry;
+ gctUINT entryCount;
+
+ /* Get the command buffer object. */
+ command = Kernel->command;
+
+ /* Acquire the mutex. */
+ gcmkERR_BREAK(gckOS_AcquireMutex(
+ command->os,
+ command->queueMutex,
+ gcvINFINITE
+ ));
+
+ /* Get the current queue. */
+ queueTail = command->queueTail;
+
+ /* Get the current queue entry. */
+ entry = queueTail->currentEntry;
+
+ /* Get the number of entries in the queue. */
+ entryCount = queueTail->pending;
+
+ /* Process all entries. */
+ while (gcvTRUE)
+ {
+ /* Call post-execution function. */
+ status = entry->handler(Kernel, entry);
+
+ /* Failed? */
+ if (gcmkIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR,
+ gcvZONE_COMMAND,
+ "[%s] line %d: post action failed.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+
+ /* Executed the next buffer? */
+ if (status == gcvSTATUS_EXECUTED)
+ {
+ /* Update the queue. */
+ queueTail->pending = entryCount;
+ queueTail->currentEntry = entry;
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+
+ /* Break out of the loop. */
+ break;
+ }
+
+ /* Advance to the next entry. */
+ entry += 1;
+ entryCount -= 1;
+
+ /* Last entry? */
+ if (entryCount == 0)
+ {
+ /* Reset the queue to idle. */
+ queueTail->pending = 0;
+
+ /* Get a shortcut to the queue to merge with. */
+ mergeQueue = command->mergeQueue;
+
+ /* Merge the queues if necessary. */
+ if (mergeQueue != queueTail)
+ {
+ gcmkASSERT(mergeQueue < queueTail);
+ gcmkASSERT(mergeQueue->next == queueTail);
+
+ mergeQueue->size
+ += gcmSIZEOF(gcsKERNEL_QUEUE_HEADER)
+ + queueTail->size;
+
+ mergeQueue->next = queueTail->next;
+ }
+
+ /* Advance to the next queue. */
+ queueTail = queueTail->next;
+
+ /* Did it wrap around? */
+ if (command->queue == queueTail)
+ {
+ /* Reset merge queue. */
+ command->mergeQueue = queueTail;
+ }
+
+ /* Set new queue. */
+ command->queueTail = queueTail;
+
+ /* Is the next queue scheduled? */
+ if (queueTail->pending > 0)
+ {
+ gcsCMDBUFFER_PTR commandBuffer;
+
+ /* The first entry must be a command buffer. */
+ commandBuffer = queueTail->currentEntry->commandBuffer;
+
+ /* Start the command processor. */
+ status = gckVGHARDWARE_Execute(
+ command->hardware,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ );
+
+ /* Failed? */
+ if (gcmkIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR,
+ gcvZONE_COMMAND,
+ "[%s] line %d: failed to start the next queue.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+ }
+ else
+ {
+ status = gckVGHARDWARE_SetPowerManagementState(
+ Kernel->command->hardware, gcvPOWER_IDLE_BROADCAST
+ );
+ }
+
+ /* Break out of the loop. */
+ break;
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkCHECK_STATUS(gckOS_ReleaseMutex(
+ command->os,
+ command->queueMutex
+ ));
+ }
+ while (gcvFALSE);
+
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+/* Define standard block interrupt handlers. */
+gcmDEFINE_INTERRUPT_HANDLER(TESSELLATOR, 0)
+gcmDEFINE_INTERRUPT_HANDLER(VG, 0)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 0)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 1)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 2)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 3)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 4)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 5)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 6)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 7)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 8)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 9)
+
+/* The entries in the array are arranged by event priority. */
+static gcsBLOCK_INTERRUPT_HANDLER _blockHandlers[] =
+{
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(TESSELLATOR, 0),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(VG, 0),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 0),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 1),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 2),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 3),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 4),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 5),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 6),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 7),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 8),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 9),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(COMMAND, 0),
+};
+
+
+/******************************************************************************\
+************************* Static Command Buffer Handlers ***********************
+\******************************************************************************/
+
+static gceSTATUS
+_UpdateStaticCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d)\n",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_ExecuteStaticCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ gcsCMDBUFFER_PTR commandBuffer;
+
+ /* Cast the command buffer header. */
+ commandBuffer = Entry->commandBuffer;
+
+ /* Set to update the command buffer next time. */
+ Entry->handler = _UpdateStaticCommandBuffer;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
+ __FUNCTION__, __LINE__,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ );
+
+ /* Start the command processor. */
+ gcmkERR_BREAK(gckVGHARDWARE_Execute(
+ Kernel->hardware,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ ));
+
+ /* Success. */
+ return gcvSTATUS_EXECUTED;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_UpdateLastStaticCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+#if gcvDEBUG || gcdFORCE_MESSAGES
+ /* Get the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+ /* Validate the command buffer. */
+ gcmkASSERT(commandBuffer->completion != gcvNULL);
+ gcmkASSERT(commandBuffer->completion != gcvVACANT_BUFFER);
+
+#endif
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): processing all tasks scheduled for FE.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Perform scheduled tasks. */
+ return _EventHandler_Block(
+ Kernel,
+ &Kernel->command->taskTable[gcvBLOCK_COMMAND],
+ gcvTRUE
+ );
+}
+
+static gceSTATUS
+_ExecuteLastStaticCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+ /* Set to update the command buffer next time. */
+ Entry->handler = _UpdateLastStaticCommandBuffer;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
+ __FUNCTION__, __LINE__,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ );
+
+ /* Start the command processor. */
+ gcmkERR_BREAK(gckVGHARDWARE_Execute(
+ Kernel->hardware,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ ));
+
+ /* Success. */
+ return gcvSTATUS_EXECUTED;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+
+/******************************************************************************\
+************************* Dynamic Command Buffer Handlers **********************
+\******************************************************************************/
+
+static gceSTATUS
+_UpdateDynamicCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d)\n",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_ExecuteDynamicCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+ /* Set to update the command buffer next time. */
+ Entry->handler = _UpdateDynamicCommandBuffer;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
+ __FUNCTION__, __LINE__,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ );
+
+ /* Start the command processor. */
+ gcmkERR_BREAK(gckVGHARDWARE_Execute(
+ Kernel->hardware,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ ));
+
+ /* Success. */
+ return gcvSTATUS_EXECUTED;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_UpdateLastDynamicCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+#if gcvDEBUG || gcdFORCE_MESSAGES
+ /* Get the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+ /* Validate the command buffer. */
+ gcmkASSERT(commandBuffer->completion != gcvNULL);
+ gcmkASSERT(commandBuffer->completion != gcvVACANT_BUFFER);
+
+#endif
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): processing all tasks scheduled for FE.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Perform scheduled tasks. */
+ return _EventHandler_Block(
+ Kernel,
+ &Kernel->command->taskTable[gcvBLOCK_COMMAND],
+ gcvTRUE
+ );
+}
+
+static gceSTATUS
+_ExecuteLastDynamicCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+ /* Set to update the command buffer next time. */
+ Entry->handler = _UpdateLastDynamicCommandBuffer;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
+ __FUNCTION__, __LINE__,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ );
+
+ /* Start the command processor. */
+ gcmkERR_BREAK(gckVGHARDWARE_Execute(
+ Kernel->hardware,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ ));
+
+ /* Success. */
+ return gcvSTATUS_EXECUTED;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+
+/******************************************************************************\
+********************************* Other Handlers *******************************
+\******************************************************************************/
+
+static gceSTATUS
+_FreeKernelCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gceSTATUS status;
+
+ /* Free the command buffer. */
+ status = _FreeCommandBuffer(Kernel, Entry->commandBuffer);
+
+ /* Return status. */
+ return status;
+}
+
+
+/******************************************************************************\
+******************************* Queue Management *******************************
+\******************************************************************************/
+
+#if gcvDUMP_COMMAND_BUFFER
+static void
+_DumpCommandQueue(
+ IN gckVGCOMMAND Command,
+ IN gcsKERNEL_QUEUE_HEADER_PTR QueueHeader,
+ IN gctUINT EntryCount
+ )
+{
+ gcsKERNEL_CMDQUEUE_PTR entry;
+ gctUINT queueIndex;
+
+#if defined(gcvCOMMAND_BUFFER_NAME)
+ static gctUINT arrayCount = 0;
+#endif
+
+ /* Is dumpinng enabled? */
+ if (!Commad->enableDumping)
+ {
+ return;
+ }
+
+#if !defined(gcvCOMMAND_BUFFER_NAME)
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_COMMAND,
+ "COMMAND QUEUE DUMP: %d entries\n", EntryCount
+ );
+#endif
+
+ /* Get the pointer to the first entry. */
+ entry = QueueHeader->currentEntry;
+
+ /* Iterate through the queue. */
+ for (queueIndex = 0; queueIndex < EntryCount; queueIndex += 1)
+ {
+ gcsCMDBUFFER_PTR buffer;
+ gctUINT bufferCount;
+ gctUINT bufferIndex;
+ gctUINT i, count;
+ gctUINT size;
+ gctUINT32_PTR data;
+
+#if gcvDUMP_COMMAND_LINES
+ gctUINT lineNumber;
+#endif
+
+#if !defined(gcvCOMMAND_BUFFER_NAME)
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_COMMAND,
+ "ENTRY %d\n", queueIndex
+ );
+#endif
+
+ /* Reset the count. */
+ bufferCount = 0;
+
+ /* Set the initial buffer. */
+ buffer = entry->commandBuffer;
+
+ /* Loop through all subbuffers. */
+ while (buffer)
+ {
+ /* Update the count. */
+ bufferCount += 1;
+
+ /* Advance to the next subbuffer. */
+ buffer = buffer->nextSubBuffer;
+ }
+
+#if !defined(gcvCOMMAND_BUFFER_NAME)
+ if (bufferCount > 1)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO,
+ gcvZONE_COMMAND,
+ " COMMAND BUFFER SET: %d buffers.\n",
+ bufferCount
+ );
+ }
+#endif
+
+ /* Reset the buffer index. */
+ bufferIndex = 0;
+
+ /* Set the initial buffer. */
+ buffer = entry->commandBuffer;
+
+ /* Loop through all subbuffers. */
+ while (buffer)
+ {
+ /* Determine the size of the buffer. */
+ size = buffer->dataCount * Command->info.commandAlignment;
+
+#if !defined(gcvCOMMAND_BUFFER_NAME)
+ /* A single buffer? */
+ if (bufferCount == 1)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO,
+ gcvZONE_COMMAND,
+ " COMMAND BUFFER: count=%d (0x%X), size=%d bytes @ %08X.\n",
+ buffer->dataCount,
+ buffer->dataCount,
+ size,
+ buffer->address
+ );
+ }
+ else
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO,
+ gcvZONE_COMMAND,
+ " COMMAND BUFFER %d: count=%d (0x%X), size=%d bytes @ %08X\n",
+ bufferIndex,
+ buffer->dataCount,
+ buffer->dataCount,
+ size,
+ buffer->address
+ );
+ }
+#endif
+
+ /* Determine the number of double words to print. */
+ count = size / 4;
+
+ /* Determine the buffer location. */
+ data = (gctUINT32_PTR)
+ (
+ (gctUINT8_PTR) buffer + buffer->bufferOffset
+ );
+
+#if defined(gcvCOMMAND_BUFFER_NAME)
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO,
+ gcvZONE_COMMAND,
+ "unsigned int _" gcvCOMMAND_BUFFER_NAME "_%d[] =\n",
+ arrayCount
+ );
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO,
+ gcvZONE_COMMAND,
+ "{\n"
+ );
+
+ arrayCount += 1;
+#endif
+
+#if gcvDUMP_COMMAND_LINES
+ /* Reset the line number. */
+ lineNumber = 0;
+#endif
+
+#if defined(gcvCOMMAND_BUFFER_NAME)
+ count -= 2;
+#endif
+
+ for (i = 0; i < count; i += 1)
+ {
+ if ((i % 8) == 0)
+ {
+#if defined(gcvCOMMAND_BUFFER_NAME)
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "\t");
+#else
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, " ");
+#endif
+ }
+
+#if gcvDUMP_COMMAND_LINES
+ if (lineNumber == gcvDUMP_COMMAND_LINES)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, " . . . . . . . . .\n");
+ break;
+ }
+#endif
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "0x%08X", data[i]);
+
+ if (i + 1 == count)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "\n");
+
+#if gcvDUMP_COMMAND_LINES
+ lineNumber += 1;
+#endif
+ }
+ else
+ {
+ if (((i + 1) % 8) == 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, ",\n");
+
+#if gcvDUMP_COMMAND_LINES
+ lineNumber += 1;
+#endif
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, ", ");
+ }
+ }
+ }
+
+#if defined(gcvCOMMAND_BUFFER_NAME)
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO,
+ gcvZONE_COMMAND,
+ "};\n\n"
+ );
+#endif
+
+ /* Advance to the next subbuffer. */
+ buffer = buffer->nextSubBuffer;
+ bufferIndex += 1;
+ }
+
+ /* Advance to the next entry. */
+ entry += 1;
+ }
+}
+#endif
+
+static gceSTATUS
+_LockCurrentQueue(
+ IN gckVGCOMMAND Command,
+ OUT gcsKERNEL_CMDQUEUE_PTR * Entries,
+ OUT gctUINT_PTR EntryCount
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ gcsKERNEL_QUEUE_HEADER_PTR queueHead;
+
+ /* Get a shortcut to the head of the queue. */
+ queueHead = Command->queueHead;
+
+ /* Is the head buffer still being worked on? */
+ if (queueHead->pending)
+ {
+ /* Increment overflow count. */
+ Command->queueOverflow += 1;
+
+ /* Wait until the head becomes idle. */
+ gcmkERR_BREAK(_WaitForIdle(Command, queueHead));
+ }
+
+ /* Acquire the mutex. */
+ gcmkERR_BREAK(gckOS_AcquireMutex(
+ Command->os,
+ Command->queueMutex,
+ gcvINFINITE
+ ));
+
+ /* Determine the first queue entry. */
+ queueHead->currentEntry = (gcsKERNEL_CMDQUEUE_PTR)
+ (
+ (gctUINT8_PTR) queueHead + gcmSIZEOF(gcsKERNEL_QUEUE_HEADER)
+ );
+
+ /* Set the pointer to the first entry. */
+ * Entries = queueHead->currentEntry;
+
+ /* Determine the number of available entries. */
+ * EntryCount = queueHead->size / gcmSIZEOF(gcsKERNEL_CMDQUEUE);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_UnlockCurrentQueue(
+ IN gckVGCOMMAND Command,
+ IN gctUINT EntryCount
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+#if !gcdENABLE_INFINITE_SPEED_HW
+ gcsKERNEL_QUEUE_HEADER_PTR queueTail;
+ gcsKERNEL_QUEUE_HEADER_PTR queueHead;
+ gcsKERNEL_QUEUE_HEADER_PTR queueNext;
+ gctUINT queueSize;
+ gctUINT newSize;
+ gctUINT unusedSize;
+
+ /* Get shortcut to the head and to the tail of the queue. */
+ queueTail = Command->queueTail;
+ queueHead = Command->queueHead;
+
+ /* Dump the command buffer. */
+#if gcvDUMP_COMMAND_BUFFER
+ _DumpCommandQueue(Command, queueHead, EntryCount);
+#endif
+
+ /* Get a shortcut to the current queue size. */
+ queueSize = queueHead->size;
+
+ /* Determine the new queue size. */
+ newSize = EntryCount * gcmSIZEOF(gcsKERNEL_CMDQUEUE);
+ gcmkASSERT(newSize <= queueSize);
+
+ /* Determine the size of the unused area. */
+ unusedSize = queueSize - newSize;
+
+ /* Is the unused area big enough to become a buffer? */
+ if (unusedSize >= gcvMINUMUM_BUFFER)
+ {
+ gcsKERNEL_QUEUE_HEADER_PTR nextHead;
+
+ /* Place the new header. */
+ nextHead = (gcsKERNEL_QUEUE_HEADER_PTR)
+ (
+ (gctUINT8_PTR) queueHead
+ + gcmSIZEOF(gcsKERNEL_QUEUE_HEADER)
+ + newSize
+ );
+
+ /* Initialize the buffer. */
+ nextHead->size = unusedSize - gcmSIZEOF(gcsKERNEL_QUEUE_HEADER);
+ nextHead->pending = 0;
+
+ /* Link the buffer in. */
+ nextHead->next = queueHead->next;
+ queueHead->next = nextHead;
+ queueNext = nextHead;
+
+ /* Update the size of the current buffer. */
+ queueHead->size = newSize;
+ }
+
+ /* Not big enough. */
+ else
+ {
+ /* Determine the next queue. */
+ queueNext = queueHead->next;
+ }
+
+ /* Mark the buffer as busy. */
+ queueHead->pending = EntryCount;
+
+ /* Advance to the next buffer. */
+ Command->queueHead = queueNext;
+
+ /* Start the command processor if the queue was empty. */
+ if (queueTail == queueHead)
+ {
+ gcsCMDBUFFER_PTR commandBuffer;
+
+ /* The first entry must be a command buffer. */
+ commandBuffer = queueTail->currentEntry->commandBuffer;
+
+ /* Start the command processor. */
+ gcmkERR_BREAK(gckVGHARDWARE_Execute(
+ Command->hardware,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ ));
+ }
+
+ /* The queue was not empty. */
+ else
+ {
+ /* Advance the merge buffer if needed. */
+ if (queueHead == Command->mergeQueue)
+ {
+ Command->mergeQueue = queueNext;
+ }
+ }
+#endif
+
+ /* Release the mutex. */
+ gcmkERR_BREAK(gckOS_ReleaseMutex(
+ Command->os,
+ Command->queueMutex
+ ));
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+
+
+/******************************************************************************\
+****************************** gckVGCOMMAND API Code *****************************
+\******************************************************************************/
+gceSTATUS
+gckVGCOMMAND_Construct(
+ IN gckVGKERNEL Kernel,
+ IN gctUINT TaskGranularity,
+ IN gctUINT QueueSize,
+ OUT gckVGCOMMAND * Command
+ )
+{
+ gceSTATUS status, last;
+ gckVGCOMMAND command = gcvNULL;
+ gcsKERNEL_QUEUE_HEADER_PTR queue;
+ gctUINT i, j;
+
+ gcmkHEADER_ARG("Kernel=0x%x TaskGranularity=0x%x QueueSize=0x%x Command=0x%x",
+ Kernel, TaskGranularity, QueueSize, Command);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(QueueSize >= gcvMINUMUM_BUFFER);
+ gcmkVERIFY_ARGUMENT(Command != gcvNULL);
+
+ do
+ {
+ /***********************************************************************
+ ** Generic object initialization.
+ */
+
+ /* Allocate the gckVGCOMMAND structure. */
+ gcmkERR_BREAK(gckOS_Allocate(
+ Kernel->os,
+ gcmSIZEOF(struct _gckVGCOMMAND),
+ (gctPOINTER *) &command
+ ));
+
+ /* Initialize the object. */
+ command->object.type = gcvOBJ_COMMAND;
+
+ /* Set the object pointers. */
+ command->kernel = Kernel;
+ command->os = Kernel->os;
+ command->hardware = Kernel->hardware;
+
+ /* Reset pointers. */
+ command->queue = gcvNULL;
+ command->queueMutex = gcvNULL;
+ command->taskMutex = gcvNULL;
+ command->commitMutex = gcvNULL;
+
+ command->powerStallBuffer = gcvNULL;
+ command->powerStallSignal = gcvNULL;
+ command->powerSemaphore = gcvNULL;
+
+ /* Reset context states. */
+ command->contextCounter = 0;
+ command->currentContext = 0;
+
+ /* Enable command buffer dumping. */
+ command->enableDumping = gcvTRUE;
+
+ /* Set features. */
+ command->fe20 = Kernel->hardware->fe20;
+ command->vg20 = Kernel->hardware->vg20;
+ command->vg21 = Kernel->hardware->vg21;
+
+ /* Reset task table .*/
+ gcmkVERIFY_OK(gckOS_ZeroMemory(
+ command->taskTable, gcmSIZEOF(command->taskTable)
+ ));
+
+ /* Query command buffer attributes. */
+ gcmkERR_BREAK(gckVGCOMMAND_InitializeInfo(command));
+
+ /* Create the control mutexes. */
+ gcmkERR_BREAK(gckOS_CreateMutex(Kernel->os, &command->queueMutex));
+ gcmkERR_BREAK(gckOS_CreateMutex(Kernel->os, &command->taskMutex));
+ gcmkERR_BREAK(gckOS_CreateMutex(Kernel->os, &command->commitMutex));
+
+ /* Create the power management semaphore. */
+ gcmkERR_BREAK(gckOS_CreateSemaphore(Kernel->os,
+ &command->powerSemaphore));
+
+ gcmkERR_BREAK(gckOS_CreateSignal(Kernel->os,
+ gcvFALSE, &command->powerStallSignal));
+
+ /***********************************************************************
+ ** Command queue initialization.
+ */
+
+ /* Allocate the command queue. */
+ gcmkERR_BREAK(gckOS_Allocate(
+ Kernel->os,
+ QueueSize,
+ (gctPOINTER *) &command->queue
+ ));
+
+ /* Initialize the command queue. */
+ queue = command->queue;
+
+ queue->size = QueueSize - gcmSIZEOF(gcsKERNEL_QUEUE_HEADER);
+ queue->pending = 0;
+ queue->next = queue;
+
+ command->queueHead =
+ command->queueTail =
+ command->mergeQueue = command->queue;
+
+ command->queueOverflow = 0;
+
+
+ /***********************************************************************
+ ** Enable TS overflow interrupt.
+ */
+
+ command->info.tsOverflowInt = 0;
+ gcmkERR_BREAK(gckVGINTERRUPT_Enable(
+ Kernel->interrupt,
+ &command->info.tsOverflowInt,
+ _EventHandler_TSOverflow
+ ));
+
+ /* Mask out the interrupt. */
+ Kernel->hardware->eventMask &= ~(1 << command->info.tsOverflowInt);
+
+
+ /***********************************************************************
+ ** Enable Bus Error interrupt.
+ */
+
+ /* Hardwired to bit 31. */
+ command->busErrorInt = 31;
+
+ /* Enable the interrupt. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Enable(
+ Kernel->interrupt,
+ &command->busErrorInt,
+ _EventHandler_BusError
+ ));
+
+
+ command->powerStallInt = 30;
+ /* Enable the interrupt. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Enable(
+ Kernel->interrupt,
+ &command->powerStallInt,
+ _EventHandler_PowerStall
+ ));
+
+ /***********************************************************************
+ ** Task management initialization.
+ */
+
+ command->taskStorage = gcvNULL;
+ command->taskStorageGranularity = TaskGranularity;
+ command->taskStorageUsable = TaskGranularity - gcmSIZEOF(gcsTASK_STORAGE);
+
+ command->taskFreeHead = gcvNULL;
+ command->taskFreeTail = gcvNULL;
+
+ /* Enable block handlers. */
+ for (i = 0; i < gcmCOUNTOF(_blockHandlers); i += 1)
+ {
+ /* Get the target hardware block. */
+ gceBLOCK block = _blockHandlers[i].block;
+
+ /* Get the interrupt array entry. */
+ gcsBLOCK_TASK_ENTRY_PTR entry = &command->taskTable[block];
+
+ /* Determine the interrupt value index. */
+ gctUINT index = entry->interruptCount;
+
+ /* Create the block semaphore. */
+ if (entry->interruptSemaphore == gcvNULL)
+ {
+ gcmkERR_BREAK(gckOS_CreateSemaphoreVG(
+ command->os, &entry->interruptSemaphore
+ ));
+ }
+
+ /* Enable auto-detection. */
+ entry->interruptArray[index] = -1;
+
+ /* Enable interrupt for the block. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Enable(
+ Kernel->interrupt,
+ &entry->interruptArray[index],
+ _blockHandlers[i].handler
+ ));
+
+ /* Update the number of registered interrupts. */
+ entry->interruptCount += 1;
+
+ /* Inrement the semaphore to allow the usage of the registered
+ interrupt. */
+ gcmkERR_BREAK(gckOS_IncrementSemaphore(
+ command->os, entry->interruptSemaphore
+ ));
+
+ }
+
+ /* Error? */
+ if (gcmkIS_ERROR(status))
+ {
+ break;
+ }
+
+ /* Get the FE interrupt. */
+ command->info.feBufferInt
+ = command->taskTable[gcvBLOCK_COMMAND].interruptArray[0];
+
+ /* Return gckVGCOMMAND object pointer. */
+ *Command = command;
+
+ gcmkFOOTER_ARG("*Command=0x%x",*Command);
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Roll back. */
+ if (command != gcvNULL)
+ {
+ /* Disable block handlers. */
+ for (i = 0; i < gcvBLOCK_COUNT; i += 1)
+ {
+ /* Get the task table entry. */
+ gcsBLOCK_TASK_ENTRY_PTR entry = &command->taskTable[i];
+
+ /* Destroy the semaphore. */
+ if (entry->interruptSemaphore != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_DestroySemaphore(
+ command->os, entry->interruptSemaphore
+ ));
+ }
+
+ /* Disable all enabled interrupts. */
+ for (j = 0; j < entry->interruptCount; j += 1)
+ {
+ /* Must be a valid value. */
+ gcmkASSERT(entry->interruptArray[j] >= 0);
+ gcmkASSERT(entry->interruptArray[j] <= 31);
+
+ /* Disable the interrupt. */
+ gcmkCHECK_STATUS(gckVGINTERRUPT_Disable(
+ Kernel->interrupt,
+ entry->interruptArray[j]
+ ));
+ }
+ }
+
+ /* Disable the bus error interrupt. */
+ gcmkCHECK_STATUS(gckVGINTERRUPT_Disable(
+ Kernel->interrupt,
+ command->busErrorInt
+ ));
+
+ /* Disable TS overflow interrupt. */
+ if (command->info.tsOverflowInt != -1)
+ {
+ gcmkCHECK_STATUS(gckVGINTERRUPT_Disable(
+ Kernel->interrupt,
+ command->info.tsOverflowInt
+ ));
+ }
+
+ /* Delete the commit mutex. */
+ if (command->commitMutex != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_DeleteMutex(
+ Kernel->os, command->commitMutex
+ ));
+ }
+
+ /* Delete the command queue mutex. */
+ if (command->taskMutex != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_DeleteMutex(
+ Kernel->os, command->taskMutex
+ ));
+ }
+
+ /* Delete the command queue mutex. */
+ if (command->queueMutex != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_DeleteMutex(
+ Kernel->os, command->queueMutex
+ ));
+ }
+
+ /* Delete the command queue. */
+ if (command->queue != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_Free(
+ Kernel->os, command->queue
+ ));
+ }
+
+ if (command->powerSemaphore != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySemaphore(
+ Kernel->os, command->powerSemaphore));
+ }
+
+ if (command->powerStallSignal != gcvNULL)
+ {
+ /* Create the power management semaphore. */
+ gcmkVERIFY_OK(gckOS_DestroySignal(
+ Kernel->os,
+ command->powerStallSignal));
+ }
+
+ /* Free the gckVGCOMMAND structure. */
+ gcmkCHECK_STATUS(gckOS_Free(
+ Kernel->os, command
+ ));
+ }
+
+ gcmkFOOTER();
+ /* Return the error. */
+ return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_Destroy(
+ OUT gckVGCOMMAND Command
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ do
+ {
+ gctUINT i;
+ gcsTASK_STORAGE_PTR nextStorage;
+
+ if (Command->queueHead != gcvNULL)
+ {
+ /* Wait until the head becomes idle. */
+ gcmkERR_BREAK(_WaitForIdle(Command, Command->queueHead));
+ }
+
+ /* Disable block handlers. */
+ for (i = 0; i < gcvBLOCK_COUNT; i += 1)
+ {
+ /* Get the interrupt array entry. */
+ gcsBLOCK_TASK_ENTRY_PTR entry = &Command->taskTable[i];
+
+ /* Determine the index of the last interrupt in the array. */
+ gctINT index = entry->interruptCount - 1;
+
+ /* Destroy the semaphore. */
+ if (entry->interruptSemaphore != gcvNULL)
+ {
+ gcmkERR_BREAK(gckOS_DestroySemaphore(
+ Command->os, entry->interruptSemaphore
+ ));
+ }
+
+ /* Disable all enabled interrupts. */
+ while (index >= 0)
+ {
+ /* Must be a valid value. */
+ gcmkASSERT(entry->interruptArray[index] >= 0);
+ gcmkASSERT(entry->interruptArray[index] <= 31);
+
+ /* Disable the interrupt. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Disable(
+ Command->kernel->interrupt,
+ entry->interruptArray[index]
+ ));
+
+ /* Update to the next interrupt. */
+ index -= 1;
+ entry->interruptCount -= 1;
+ }
+
+ /* Error? */
+ if (gcmkIS_ERROR(status))
+ {
+ break;
+ }
+ }
+
+ /* Error? */
+ if (gcmkIS_ERROR(status))
+ {
+ break;
+ }
+
+ /* Disable the bus error interrupt. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Disable(
+ Command->kernel->interrupt,
+ Command->busErrorInt
+ ));
+
+ /* Disable TS overflow interrupt. */
+ if (Command->info.tsOverflowInt != -1)
+ {
+ gcmkERR_BREAK(gckVGINTERRUPT_Disable(
+ Command->kernel->interrupt,
+ Command->info.tsOverflowInt
+ ));
+
+ Command->info.tsOverflowInt = -1;
+ }
+
+ /* Delete the commit mutex. */
+ if (Command->commitMutex != gcvNULL)
+ {
+ gcmkERR_BREAK(gckOS_DeleteMutex(
+ Command->os, Command->commitMutex
+ ));
+
+ Command->commitMutex = gcvNULL;
+ }
+
+ /* Delete the command queue mutex. */
+ if (Command->taskMutex != gcvNULL)
+ {
+ gcmkERR_BREAK(gckOS_DeleteMutex(
+ Command->os, Command->taskMutex
+ ));
+
+ Command->taskMutex = gcvNULL;
+ }
+
+ /* Delete the command queue mutex. */
+ if (Command->queueMutex != gcvNULL)
+ {
+ gcmkERR_BREAK(gckOS_DeleteMutex(
+ Command->os, Command->queueMutex
+ ));
+
+ Command->queueMutex = gcvNULL;
+ }
+
+ if (Command->powerSemaphore != gcvNULL)
+ {
+ /* Destroy the power management semaphore. */
+ gcmkERR_BREAK(gckOS_DestroySemaphore(
+ Command->os, Command->powerSemaphore));
+ }
+
+ if (Command->powerStallSignal != gcvNULL)
+ {
+ /* Create the power management semaphore. */
+ gcmkERR_BREAK(gckOS_DestroySignal(
+ Command->os,
+ Command->powerStallSignal));
+ }
+
+ if (Command->queue != gcvNULL)
+ {
+ /* Delete the command queue. */
+ gcmkERR_BREAK(gckOS_Free(
+ Command->os, Command->queue
+ ));
+ }
+
+ /* Destroy all allocated buffers. */
+ while (Command->taskStorage)
+ {
+ /* Copy the buffer pointer. */
+ nextStorage = Command->taskStorage->next;
+
+ /* Free the current container. */
+ gcmkERR_BREAK(gckOS_Free(
+ Command->os, Command->taskStorage
+ ));
+
+ /* Advance to the next one. */
+ Command->taskStorage = nextStorage;
+ }
+
+ /* Error? */
+ if (gcmkIS_ERROR(status))
+ {
+ break;
+ }
+
+ /* Mark the object as unknown. */
+ Command->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckVGCOMMAND structure. */
+ gcmkERR_BREAK(gckOS_Free(Command->os, Command));
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Restore the object type if failed. */
+ Command->object.type = gcvOBJ_COMMAND;
+
+ gcmkFOOTER();
+ /* Return the error. */
+ return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_QueryCommandBuffer(
+ IN gckVGCOMMAND Command,
+ OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Information=0x%x", Command, Information);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+ gcmkVERIFY_ARGUMENT(Information != gcvNULL);
+
+ /* Copy the information. */
+ gcmkVERIFY_OK(gckOS_MemCopy(
+ Information, &Command->info, sizeof(gcsCOMMAND_BUFFER_INFO)
+ ));
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVGCOMMAND_Allocate(
+ IN gckVGCOMMAND Command,
+ IN gctSIZE_T Size,
+ OUT gcsCMDBUFFER_PTR * CommandBuffer,
+ OUT gctPOINTER * Data
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Command=0x%x Size=0x%x CommandBuffer=0x%x Data=0x%x",
+ Command, Size, CommandBuffer, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+ do
+ {
+ /* Allocate the buffer. */
+ gcmkERR_BREAK(_AllocateCommandBuffer(Command, Size, CommandBuffer));
+
+ /* Determine the data pointer. */
+ * Data = (gctUINT8_PTR) (*CommandBuffer) + (* CommandBuffer)->bufferOffset;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_Free(
+ IN gckVGCOMMAND Command,
+ IN gcsCMDBUFFER_PTR CommandBuffer
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x",
+ Command, CommandBuffer);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+ gcmkVERIFY_ARGUMENT(CommandBuffer != gcvNULL);
+
+ /* Free command buffer. */
+ status = _FreeCommandBuffer(Command->kernel, CommandBuffer);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_Execute(
+ IN gckVGCOMMAND Command,
+ IN gcsCMDBUFFER_PTR CommandBuffer
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x",
+ Command, CommandBuffer);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+ gcmkVERIFY_ARGUMENT(CommandBuffer != gcvNULL);
+
+ do
+ {
+ gctUINT queueLength;
+ gcsKERNEL_CMDQUEUE_PTR kernelEntry;
+
+ /* Lock the current queue. */
+ gcmkERR_BREAK(_LockCurrentQueue(
+ Command, &kernelEntry, &queueLength
+ ));
+
+ /* Set the buffer. */
+ kernelEntry->commandBuffer = CommandBuffer;
+ kernelEntry->handler = _FreeKernelCommandBuffer;
+
+ /* Lock the current queue. */
+ gcmkERR_BREAK(_UnlockCurrentQueue(
+ Command, 1
+ ));
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_Commit(
+ IN gckVGCOMMAND Command,
+ IN gcsVGCONTEXT_PTR Context,
+ IN gcsVGCMDQUEUE_PTR Queue,
+ IN gctUINT EntryCount,
+ IN gcsTASK_MASTER_TABLE_PTR TaskTable
+ )
+{
+ /*
+ The first buffer is executed through a direct gckVGHARDWARE_Execute call,
+ therefore only an update is needed after the execution is over. All
+ consequent buffers need to be executed upon the first update call from
+ the FE interrupt handler.
+ */
+
+ static gcsQUEUE_UPDATE_CONTROL _dynamicBuffer[] =
+ {
+ {
+ _UpdateDynamicCommandBuffer,
+ _UpdateDynamicCommandBuffer,
+ _UpdateLastDynamicCommandBuffer,
+ _UpdateLastDynamicCommandBuffer
+ },
+ {
+ _ExecuteDynamicCommandBuffer,
+ _UpdateDynamicCommandBuffer,
+ _ExecuteLastDynamicCommandBuffer,
+ _UpdateLastDynamicCommandBuffer
+ }
+ };
+
+ static gcsQUEUE_UPDATE_CONTROL _staticBuffer[] =
+ {
+ {
+ _UpdateStaticCommandBuffer,
+ _UpdateStaticCommandBuffer,
+ _UpdateLastStaticCommandBuffer,
+ _UpdateLastStaticCommandBuffer
+ },
+ {
+ _ExecuteStaticCommandBuffer,
+ _UpdateStaticCommandBuffer,
+ _ExecuteLastStaticCommandBuffer,
+ _UpdateLastStaticCommandBuffer
+ }
+ };
+
+ gceSTATUS status, last;
+
+#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);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+ gcmkVERIFY_ARGUMENT(Context != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
+ gcmkVERIFY_ARGUMENT(EntryCount > 1);
+
+ do
+ {
+ gctBOOL haveFETasks;
+ gctUINT queueSize;
+ gcsVGCMDQUEUE_PTR mappedQueue;
+ gcsVGCMDQUEUE_PTR userEntry;
+ gcsKERNEL_CMDQUEUE_PTR kernelEntry;
+ gcsQUEUE_UPDATE_CONTROL_PTR queueControl;
+ gctUINT currentLength;
+ gctUINT queueLength;
+ gctUINT entriesQueued;
+ gctUINT8_PTR previousEnd;
+ gctBOOL previousDynamic;
+ gctBOOL previousExecuted;
+ gctUINT controlIndex;
+
+#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
+ ));
+
+ /* Acquire the power semaphore. */
+ gcmkERR_BREAK(gckOS_AcquireSemaphore(
+ Command->os, Command->powerSemaphore
+ ));
+
+ /* Acquire the mutex. */
+ status = gckOS_AcquireMutex(
+ Command->os,
+ Command->commitMutex,
+ gcvINFINITE
+ );
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(
+ Command->os, Command->powerSemaphore));
+ break;
+ }
+
+ do
+ {
+ gcmkERR_BREAK(_FlushMMU(Command));
+
+ /* Assign a context ID if not yet assigned. */
+ if (Context->id == 0)
+ {
+ /* Assign the next context number. */
+ Context->id = ++ Command->contextCounter;
+
+ /* See if we overflowed. */
+ if (Command->contextCounter == 0)
+ {
+ /* We actually did overflow, wow... */
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ break;
+ }
+ }
+
+ /* The first entry in the queue is always the context buffer.
+ Verify whether the user context is the same as the current
+ context and if that's the case, skip the first entry. */
+ if (Context->id == Command->currentContext)
+ {
+ /* Same context as before, skip the first entry. */
+ EntryCount -= 1;
+ Queue += 1;
+
+ /* Set the signal to avoid user waiting. */
+#ifdef __QNXNTO__
+ gcmkERR_BREAK(gckOS_UserSignal(
+ Command->os,
+ Context->userSignal,
+ Context->rcvid,
+ Context->coid
+ ));
+#else
+ gcmkERR_BREAK(gckOS_UserSignal(
+ Command->os, Context->signal, Context->process
+ ));
+#endif
+ }
+ else
+ {
+ /* Different user context - keep the first entry.
+ Set the user context as the current one. */
+ Command->currentContext = Context->id;
+ }
+
+ /* Reset pointers. */
+ queueControl = gcvNULL;
+ previousEnd = gcvNULL;
+
+ /* Determine whether there are FE tasks to be performed. */
+ haveFETasks = (TaskTable->table[gcvBLOCK_COMMAND].head != gcvNULL);
+
+ /* Determine the size of the queue. */
+ queueSize = EntryCount * gcmSIZEOF(gcsVGCMDQUEUE);
+
+ /* Map the command queue into the kernel space. */
+ gcmkERR_BREAK(gckOS_MapUserPointer(
+ Command->os,
+ Queue,
+ queueSize,
+ (gctPOINTER *) &mappedQueue
+ ));
+
+ /* Set the first entry. */
+ userEntry = mappedQueue;
+
+ /* Process the command queue. */
+ while (EntryCount)
+ {
+ /* Lock the current queue. */
+ gcmkERR_BREAK(_LockCurrentQueue(
+ Command, &kernelEntry, &queueLength
+ ));
+
+ /* Determine the number of entries to process. */
+ currentLength = (queueLength < EntryCount)
+ ? queueLength
+ : EntryCount;
+
+ /* Update the number of the entries left to process. */
+ EntryCount -= currentLength;
+
+ /* Reset previous flags. */
+ previousDynamic = gcvFALSE;
+ previousExecuted = gcvFALSE;
+
+ /* Set the initial control index. */
+ controlIndex = 0;
+
+ /* Process entries. */
+ for (entriesQueued = 0; entriesQueued < currentLength; entriesQueued += 1)
+ {
+ /* Get the kernel pointer to the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer = gcvNULL;
+ gcmkERR_BREAK(_ConvertUserCommandBufferPointer(
+ Command,
+ userEntry->commandBuffer,
+ &commandBuffer
+ ));
+
+ /* Is it a dynamic command buffer? */
+ if (userEntry->dynamic)
+ {
+ /* Select dynamic buffer control functions. */
+ queueControl = &_dynamicBuffer[controlIndex];
+ }
+
+ /* No, a static command buffer. */
+ else
+ {
+ /* Select static buffer control functions. */
+ queueControl = &_staticBuffer[controlIndex];
+ }
+
+ /* Set the command buffer pointer to the entry. */
+ kernelEntry->commandBuffer = commandBuffer;
+
+ /* If the previous entry was a dynamic command buffer,
+ link it to the current. */
+ if (previousDynamic)
+ {
+ gcmkERR_BREAK(gckVGCOMMAND_FetchCommand(
+ Command,
+ previousEnd,
+ commandBuffer->address,
+ commandBuffer->dataCount,
+ gcvNULL
+ ));
+
+ /* The buffer will be auto-executed, only need to
+ update it after it has been executed. */
+ kernelEntry->handler = queueControl->update;
+
+ /* The buffer is only being updated. */
+ previousExecuted = gcvFALSE;
+ }
+ else
+ {
+ /* Set the buffer up for execution. */
+ kernelEntry->handler = queueControl->execute;
+
+ /* The buffer is being updated. */
+ previousExecuted = gcvTRUE;
+ }
+
+ /* The current buffer's END command becomes the last END. */
+ previousEnd
+ = ((gctUINT8_PTR) commandBuffer)
+ + commandBuffer->bufferOffset
+ + commandBuffer->dataCount * Command->info.commandAlignment
+ - Command->info.staticTailSize;
+
+ /* Update the last entry info. */
+ previousDynamic = userEntry->dynamic;
+
+ /* Advance entries. */
+ userEntry += 1;
+ kernelEntry += 1;
+
+ /* Update the control index. */
+ controlIndex = 1;
+ }
+
+ /* If the previous entry was a dynamic command buffer,
+ terminate it with an END. */
+ if (previousDynamic)
+ {
+ gcmkERR_BREAK(gckVGCOMMAND_EndCommand(
+ Command,
+ previousEnd,
+ Command->info.feBufferInt,
+ gcvNULL
+ ));
+ }
+
+ /* Last buffer? */
+ if (EntryCount == 0)
+ {
+ /* Modify the last command buffer's routines to handle
+ tasks if any.*/
+ if (haveFETasks)
+ {
+ if (previousExecuted)
+ {
+ kernelEntry[-1].handler = queueControl->lastExecute;
+ }
+ else
+ {
+ kernelEntry[-1].handler = queueControl->lastUpdate;
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkERR_BREAK(gckOS_ReleaseMutex(
+ Command->os,
+ Command->queueMutex
+ ));
+ /* Schedule tasks. */
+ gcmkERR_BREAK(_ScheduleTasks(Command, TaskTable, previousEnd));
+
+ /* Acquire the mutex. */
+ gcmkERR_BREAK(gckOS_AcquireMutex(
+ Command->os,
+ Command->queueMutex,
+ gcvINFINITE
+ ));
+ }
+
+ /* Unkock and schedule the current queue for execution. */
+ gcmkERR_BREAK(_UnlockCurrentQueue(
+ Command, currentLength
+ ));
+ }
+
+
+ /* Unmap the user command buffer. */
+ gcmkERR_BREAK(gckOS_UnmapUserPointer(
+ Command->os,
+ Queue,
+ queueSize,
+ mappedQueue
+ ));
+ }
+ while (gcvFALSE);
+
+ /* Release the mutex. */
+ gcmkCHECK_STATUS(gckOS_ReleaseMutex(
+ Command->os,
+ Command->commitMutex
+ ));
+
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(
+ Command->os, Command->powerSemaphore));
+ }
+ 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;
+}
+
+#endif /* gcdENABLE_VG */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
new file mode 100644
index 000000000000..be42946e5a2a
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
@@ -0,0 +1,1905 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_DATABASE
+
+/*******************************************************************************
+***** Private fuctions ********************************************************/
+
+#define _GetSlot(database, x) \
+ (gctUINT32)(gcmPTR_TO_UINT64(x) % gcmCOUNTOF(database->list))
+
+/*******************************************************************************
+** gckKERNEL_NewDatabase
+**
+** Create a new database structure and insert it to the head of the hash list.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** ProcessID that identifies the database.
+**
+** OUTPUT:
+**
+** gcsDATABASE_PTR * Database
+** Pointer to a variable receiving the database structure pointer on
+** success.
+*/
+static gceSTATUS
+gckKERNEL_NewDatabase(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ OUT gcsDATABASE_PTR * Database
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gctBOOL acquired = gcvFALSE;
+ gctSIZE_T slot;
+ gcsDATABASE_PTR existingDatabase;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+ /* Acquire the database mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Compute the hash for the database. */
+ slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
+
+ /* Walk the hash list. */
+ for (existingDatabase = Kernel->db->db[slot];
+ existingDatabase != gcvNULL;
+ existingDatabase = existingDatabase->next)
+ {
+ if (existingDatabase->processID == ProcessID)
+ {
+ /* One process can't be added twice. */
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+ }
+
+ if (Kernel->db->freeDatabase != gcvNULL)
+ {
+ /* Allocate a database from the free list. */
+ database = Kernel->db->freeDatabase;
+ Kernel->db->freeDatabase = database->next;
+ }
+ else
+ {
+ gctPOINTER pointer = gcvNULL;
+
+ /* Allocate a new database from the heap. */
+ gcmkONERROR(gckOS_Allocate(Kernel->os,
+ gcmSIZEOF(gcsDATABASE),
+ &pointer));
+
+ gckOS_ZeroMemory(pointer, gcmSIZEOF(gcsDATABASE));
+
+ database = pointer;
+
+ gcmkONERROR(gckOS_CreateMutex(Kernel->os, &database->counterMutex));
+ }
+
+ /* Insert the database into the hash. */
+ database->next = Kernel->db->db[slot];
+ Kernel->db->db[slot] = database;
+
+ /* Save the hash slot. */
+ database->slot = slot;
+
+ /* Release the database mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Return the database. */
+ *Database = database;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Database=0x%x", *Database);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_FindDatabase
+**
+** Find a database identified by a process ID and move it to the head of the
+** hash list.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** ProcessID that identifies the database.
+**
+** gctBOOL LastProcessID
+** gcvTRUE if searching for the last known process ID. gcvFALSE if
+** we need to search for the process ID specified by the ProcessID
+** argument.
+**
+** OUTPUT:
+**
+** gcsDATABASE_PTR * Database
+** Pointer to a variable receiving the database structure pointer on
+** success.
+*/
+gceSTATUS
+gckKERNEL_FindDatabase(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctBOOL LastProcessID,
+ OUT gcsDATABASE_PTR * Database
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database, previous;
+ gctSIZE_T slot;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d LastProcessID=%d",
+ Kernel, ProcessID, LastProcessID);
+
+ /* Compute the hash for the database. */
+ slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
+
+ /* Acquire the database mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Check whether we are getting the last known database. */
+ if (LastProcessID)
+ {
+ /* Use last database. */
+ database = Kernel->db->lastDatabase;
+
+ if (database == gcvNULL)
+ {
+ /* Database not found. */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+ }
+ else
+ {
+ /* Walk the hash list. */
+ for (previous = gcvNULL, database = Kernel->db->db[slot];
+ database != gcvNULL;
+ database = database->next)
+ {
+ if (database->processID == ProcessID)
+ {
+ /* Found it! */
+ break;
+ }
+
+ previous = database;
+ }
+
+ if (database == gcvNULL)
+ {
+ /* Database not found. */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+
+ if (previous != gcvNULL)
+ {
+ /* Move database to the head of the hash list. */
+ previous->next = database->next;
+ database->next = Kernel->db->db[slot];
+ Kernel->db->db[slot] = database;
+ }
+ }
+
+ /* Release the database mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Return the database. */
+ *Database = database;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Database=0x%x", *Database);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_DeleteDatabase
+**
+** Remove a database from the hash list and delete its structure.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gcsDATABASE_PTR Database
+** Pointer to the database structure to remove.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+static gceSTATUS
+gckKERNEL_DeleteDatabase(
+ IN gckKERNEL Kernel,
+ IN gcsDATABASE_PTR Database
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsDATABASE_PTR database;
+
+ gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);
+
+ /* Acquire the database mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Check slot value. */
+ gcmkVERIFY_ARGUMENT(Database->slot < gcmCOUNTOF(Kernel->db->db));
+
+ if (Database->slot < gcmCOUNTOF(Kernel->db->db))
+ {
+ /* Check if database if the head of the hash list. */
+ if (Kernel->db->db[Database->slot] == Database)
+ {
+ /* Remove the database from the hash list. */
+ Kernel->db->db[Database->slot] = Database->next;
+ }
+ else
+ {
+ /* Walk the has list to find the database. */
+ for (database = Kernel->db->db[Database->slot];
+ database != gcvNULL;
+ database = database->next
+ )
+ {
+ /* Check if the next list entry is this database. */
+ if (database->next == Database)
+ {
+ /* Remove the database from the hash list. */
+ database->next = Database->next;
+ break;
+ }
+ }
+
+ if (database == gcvNULL)
+ {
+ /* Ouch! Something got corrupted. */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+ }
+ }
+
+ if (Kernel->db->lastDatabase != gcvNULL)
+ {
+ /* Insert database to the free list. */
+ Kernel->db->lastDatabase->next = Kernel->db->freeDatabase;
+ Kernel->db->freeDatabase = Kernel->db->lastDatabase;
+ }
+
+ /* Keep database as the last database. */
+ Kernel->db->lastDatabase = Database;
+
+ /* 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));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_NewRecord
+**
+** Create a new database record structure and insert it to the head of the
+** database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gcsDATABASE_PTR Database
+** Pointer to a database structure.
+**
+** OUTPUT:
+**
+** gcsDATABASE_RECORD_PTR * Record
+** Pointer to a variable receiving the database record structure
+** pointer on success.
+*/
+static gceSTATUS
+gckKERNEL_NewRecord(
+ IN gckKERNEL Kernel,
+ IN gcsDATABASE_PTR Database,
+ IN gctUINT32 Slot,
+ OUT gcsDATABASE_RECORD_PTR * Record
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsDATABASE_RECORD_PTR record = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);
+
+ /* Acquire the database mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (Kernel->db->freeRecord != gcvNULL)
+ {
+ /* Allocate the record from the free list. */
+ record = Kernel->db->freeRecord;
+ Kernel->db->freeRecord = record->next;
+ }
+ else
+ {
+ gctPOINTER pointer = gcvNULL;
+
+ /* Allocate the record from the heap. */
+ gcmkONERROR(gckOS_Allocate(Kernel->os,
+ gcmSIZEOF(gcsDATABASE_RECORD),
+ &pointer));
+
+ record = pointer;
+ }
+
+ /* Insert the record in the database. */
+ record->next = Database->list[Slot];
+ Database->list[Slot] = record;
+
+ /* Release the database mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Return the record. */
+ *Record = record;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Record=0x%x", *Record);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+ if (record != gcvNULL)
+ {
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, record));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_DeleteRecord
+**
+** Remove a database record from the database and delete its structure.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gcsDATABASE_PTR Database
+** Pointer to a database structure.
+**
+** gceDATABASE_TYPE Type
+** Type of the record to remove.
+**
+** gctPOINTER Data
+** Data of the record to remove.
+**
+** OUTPUT:
+**
+** gctSIZE_T_PTR Bytes
+** Pointer to a variable that receives the size of the record deleted.
+** Can be gcvNULL if the size is not required.
+*/
+static gceSTATUS
+gckKERNEL_DeleteRecord(
+ IN gckKERNEL Kernel,
+ IN gcsDATABASE_PTR Database,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Data,
+ OUT gctSIZE_T_PTR Bytes OPTIONAL
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsDATABASE_RECORD_PTR record, previous;
+ gctUINT32 slot = _GetSlot(Database, Data);
+
+ gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
+ Kernel, Database, Type, Data);
+
+ /* Acquire the database mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Scan the database for this record. */
+ for (record = Database->list[slot], previous = gcvNULL;
+ record != gcvNULL;
+ record = record->next
+ )
+ {
+ if ((record->type == Type)
+ && (record->data == Data)
+ )
+ {
+ /* Found it! */
+ break;
+ }
+
+ previous = record;
+ }
+
+ if (record == gcvNULL)
+ {
+ /* Ouch! This record is not found? */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return size of record. */
+ *Bytes = record->bytes;
+ }
+
+ /* Remove record from database. */
+ if (previous == gcvNULL)
+ {
+ Database->list[slot] = record->next;
+ }
+ else
+ {
+ previous->next = record->next;
+ }
+
+ /* Insert record in free list. */
+ record->next = Kernel->db->freeRecord;
+ Kernel->db->freeRecord = record;
+
+ /* Release the database mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_FindRecord
+**
+** Find a database record from the database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gcsDATABASE_PTR Database
+** Pointer to a database structure.
+**
+** gceDATABASE_TYPE Type
+** Type of the record to remove.
+**
+** gctPOINTER Data
+** Data of the record to remove.
+**
+** OUTPUT:
+**
+** gctSIZE_T_PTR Bytes
+** Pointer to a variable that receives the size of the record deleted.
+** Can be gcvNULL if the size is not required.
+*/
+static gceSTATUS
+gckKERNEL_FindRecord(
+ IN gckKERNEL Kernel,
+ IN gcsDATABASE_PTR Database,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Data,
+ OUT gcsDATABASE_RECORD_PTR Record
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsDATABASE_RECORD_PTR record;
+ gctUINT32 slot = _GetSlot(Database, Data);
+
+ gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
+ Kernel, Database, Type, Data);
+
+ /* Acquire the database mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Scan the database for this record. */
+ for (record = Database->list[slot];
+ record != gcvNULL;
+ record = record->next
+ )
+ {
+ if ((record->type == Type)
+ && (record->data == Data)
+ )
+ {
+ /* Found it! */
+ break;
+ }
+ }
+
+ if (record == gcvNULL)
+ {
+ /* Ouch! This record is not found? */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+
+ if (Record != gcvNULL)
+ {
+ /* Return information of record. */
+ gcmkONERROR(
+ gckOS_MemCopy(Record, record, sizeof(gcsDATABASE_RECORD)));
+ }
+
+ /* Release the database mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Success. */
+ gcmkFOOTER_ARG("Record=0x%x", Record);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+***** Public API **************************************************************/
+
+/*******************************************************************************
+** gckKERNEL_CreateProcessDB
+**
+** Create a new process database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_CreateProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database = gcvNULL;
+ gctUINT32 i;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Create a new database. */
+ gcmkONERROR(gckKERNEL_NewDatabase(Kernel, ProcessID, &database));
+
+ /* Initialize the database. */
+ database->processID = ProcessID;
+ database->vidMem.bytes = 0;
+ database->vidMem.maxBytes = 0;
+ database->vidMem.totalBytes = 0;
+ database->nonPaged.bytes = 0;
+ database->nonPaged.maxBytes = 0;
+ database->nonPaged.totalBytes = 0;
+ database->contiguous.bytes = 0;
+ database->contiguous.maxBytes = 0;
+ database->contiguous.totalBytes = 0;
+ database->mapMemory.bytes = 0;
+ database->mapMemory.maxBytes = 0;
+ database->mapMemory.totalBytes = 0;
+ database->mapUserMemory.bytes = 0;
+ database->mapUserMemory.maxBytes = 0;
+ database->mapUserMemory.totalBytes = 0;
+ database->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;
+ gcskSECURE_CACHE * cache = &database->cache;
+
+ /* Setup the linked list of cache nodes. */
+ for (slot = 1; slot <= gcdSECURE_CACHE_SLOTS; ++slot)
+ {
+ cache->cache[slot].logical = gcvNULL;
+
+#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
+ cache->cache[slot].prev = &cache->cache[slot - 1];
+ cache->cache[slot].next = &cache->cache[slot + 1];
+# endif
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ cache->cache[slot].nextHash = gcvNULL;
+ cache->cache[slot].prevHash = gcvNULL;
+# endif
+ }
+
+#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
+ /* Setup the head and tail of the cache. */
+ cache->cache[0].next = &cache->cache[1];
+ cache->cache[0].prev = &cache->cache[gcdSECURE_CACHE_SLOTS];
+ cache->cache[0].logical = gcvNULL;
+
+ /* Fix up the head and tail pointers. */
+ cache->cache[0].next->prev = &cache->cache[0];
+ cache->cache[0].prev->next = &cache->cache[0];
+# endif
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ /* Zero out the hash table. */
+ for (slot = 0; slot < gcmCOUNTOF(cache->hash); ++slot)
+ {
+ cache->hash[slot].logical = gcvNULL;
+ cache->hash[slot].nextHash = gcvNULL;
+ }
+# endif
+
+ /* Initialize cache index. */
+ cache->cacheIndex = gcvNULL;
+ cache->cacheFree = 1;
+ cache->cacheStamp = 0;
+ }
+#endif
+
+ /* Reset idle timer. */
+ Kernel->db->lastIdle = 0;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_AddProcessDB
+**
+** Add a record to a process database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** gceDATABASE_TYPE TYPE
+** Type of the record to add.
+**
+** gctPOINTER Pointer
+** Data of the record to add.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the record to add.
+**
+** gctSIZE_T Size
+** Size of the record to add.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_AddProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Pointer,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Size
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gcsDATABASE_RECORD_PTR record = gcvNULL;
+ gcsDATABASE_COUNTERS * count;
+ gctUINT32 vidMemType;
+ gcePOOL vidMemPool;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x "
+ "Physical=0x%x Size=%lu",
+ Kernel, ProcessID, Type, Pointer, Physical, Size);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* 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)
+ {
+ gctUINT64 time;
+
+ /* Get the current profile time. */
+ gcmkONERROR(gckOS_GetProfileTick(&time));
+
+ if ((ProcessID == 0) && (Kernel->db->lastIdle != 0))
+ {
+ /* Out of idle, adjust time it was idle. */
+ Kernel->db->idleTime += time - Kernel->db->lastIdle;
+ Kernel->db->lastIdle = 0;
+ }
+ else if (ProcessID == 1)
+ {
+ /* Save current idle time. */
+ Kernel->db->lastIdle = time;
+ }
+
+#if gcdDYNAMIC_SPEED
+ {
+ /* Test for first call. */
+ if (Kernel->db->lastSlowdown == 0)
+ {
+ /* Save milliseconds. */
+ Kernel->db->lastSlowdown = time;
+ Kernel->db->lastSlowdownIdle = Kernel->db->idleTime;
+ }
+ else
+ {
+ /* Compute ellapsed time in milliseconds. */
+ gctUINT delta = gckOS_ProfileToMS(time - Kernel->db->lastSlowdown);
+
+ /* Test for end of period. */
+ if (delta >= gcdDYNAMIC_SPEED)
+ {
+ /* Compute number of idle milliseconds. */
+ gctUINT idle = gckOS_ProfileToMS(
+ Kernel->db->idleTime - Kernel->db->lastSlowdownIdle);
+
+ /* Broadcast to slow down the GPU. */
+ gcmkONERROR(gckOS_BroadcastCalibrateSpeed(Kernel->os,
+ Kernel->hardware,
+ idle,
+ delta));
+
+ /* Save current time. */
+ Kernel->db->lastSlowdown = time;
+ Kernel->db->lastSlowdownIdle = Kernel->db->idleTime;
+ }
+ }
+ }
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+
+ /* Find the database. */
+ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+ /* Create a new record in the database. */
+ gcmkONERROR(gckKERNEL_NewRecord(Kernel, database, _GetSlot(database, Pointer), &record));
+
+ /* Initialize the record. */
+ record->kernel = Kernel;
+ record->type = Type;
+ record->data = Pointer;
+ record->physical = Physical;
+ record->bytes = Size;
+
+ /* Get pointer to counters. */
+ switch (Type)
+ {
+ case gcvDB_VIDEO_MEMORY:
+ count = &database->vidMem;
+ break;
+
+ case gcvDB_NON_PAGED:
+ count = &database->nonPaged;
+ break;
+
+ case gcvDB_CONTIGUOUS:
+ count = &database->contiguous;
+ break;
+
+ case gcvDB_MAP_MEMORY:
+ count = &database->mapMemory;
+ break;
+
+ case gcvDB_MAP_USER_MEMORY:
+ count = &database->mapUserMemory;
+ break;
+
+ case gcvDB_COMMAND_BUFFER:
+ count = &database->virtualCommandBuffer;
+ break;
+
+ default:
+ count = gcvNULL;
+ break;
+ }
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, database->counterMutex, gcvINFINITE));
+
+ if (count != gcvNULL)
+ {
+ /* Adjust counters. */
+ count->totalBytes += Size;
+ count->bytes += Size;
+ count->allocCount++;
+
+ if (count->bytes > count->maxBytes)
+ {
+ count->maxBytes = count->bytes;
+ }
+ }
+
+ if (Type == gcvDB_VIDEO_MEMORY)
+ {
+ count = &database->vidMemType[vidMemType];
+
+ /* Adjust counters. */
+ count->totalBytes += Size;
+ count->bytes += Size;
+ count->allocCount++;
+
+ if (count->bytes > count->maxBytes)
+ {
+ count->maxBytes = count->bytes;
+ }
+
+ count = &database->vidMemPool[vidMemPool];
+
+ /* Adjust counters. */
+ count->totalBytes += Size;
+ count->bytes += Size;
+ count->allocCount++;
+
+ if (count->bytes > count->maxBytes)
+ {
+ count->maxBytes = count->bytes;
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, database->counterMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_RemoveProcessDB
+**
+** Remove a record from a process database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** gceDATABASE_TYPE TYPE
+** Type of the record to remove.
+**
+** gctPOINTER Pointer
+** Data of the record to remove.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_RemoveProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Pointer
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gctSIZE_T bytes = 0;
+ gctUINT32 vidMemType;
+ gcePOOL vidMempool;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
+ Kernel, ProcessID, Type, Pointer);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+
+ /* 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));
+
+ /* Delete the record. */
+ 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->vidMem.freeCount++;
+ database->vidMemType[vidMemType].bytes -= bytes;
+ database->vidMemType[vidMemType].freeCount++;
+ database->vidMemPool[vidMempool].bytes -= bytes;
+ database->vidMemPool[vidMempool].freeCount++;
+ break;
+
+ case gcvDB_NON_PAGED:
+ database->nonPaged.bytes -= bytes;
+ database->nonPaged.freeCount++;
+ break;
+
+ case gcvDB_CONTIGUOUS:
+ database->contiguous.bytes -= bytes;
+ database->contiguous.freeCount++;
+ break;
+
+ case gcvDB_MAP_MEMORY:
+ database->mapMemory.bytes -= bytes;
+ database->mapMemory.freeCount++;
+ break;
+
+ case gcvDB_MAP_USER_MEMORY:
+ database->mapUserMemory.bytes -= bytes;
+ database->mapUserMemory.freeCount++;
+ break;
+
+ case gcvDB_COMMAND_BUFFER:
+ database->virtualCommandBuffer.bytes -= bytes;
+ database->virtualCommandBuffer.freeCount++;
+ break;
+
+ default:
+ break;
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, database->counterMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_FindProcessDB
+**
+** Find a record from a process database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** gceDATABASE_TYPE TYPE
+** Type of the record to remove.
+**
+** gctPOINTER Pointer
+** Data of the record to remove.
+**
+** OUTPUT:
+**
+** gcsDATABASE_RECORD_PTR Record
+** Copy of record.
+*/
+gceSTATUS
+gckKERNEL_FindProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 ThreadID,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Pointer,
+ OUT gcsDATABASE_RECORD_PTR Record
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
+ Kernel, ProcessID, ThreadID, Type, Pointer);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+
+ /* Find the database. */
+ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+ /* Find the record. */
+ gcmkONERROR(
+ gckKERNEL_FindRecord(Kernel, database, Type, Pointer, Record));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_DestroyProcessDB
+**
+** Destroy a process database. If the database contains any records, the data
+** inside those records will be deleted as well. This aids in the cleanup if
+** a process has died unexpectedly or has memory leaks.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_DestroyProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gcsDATABASE_RECORD_PTR record, next;
+ gctBOOL asynchronous = gcvTRUE;
+ gckVIDMEM_NODE nodeObject;
+ gctPHYS_ADDR physical;
+ gckKERNEL kernel = Kernel;
+ gctUINT32 handle;
+ gctUINT32 i;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Find the database. */
+ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+ "DB(%d): VidMem: total=%lu max=%lu",
+ ProcessID, database->vidMem.totalBytes,
+ database->vidMem.maxBytes);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+ "DB(%d): NonPaged: total=%lu max=%lu",
+ ProcessID, database->nonPaged.totalBytes,
+ database->nonPaged.maxBytes);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+ "DB(%d): Contiguous: total=%lu max=%lu",
+ ProcessID, database->contiguous.totalBytes,
+ database->contiguous.maxBytes);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+ "DB(%d): Idle time=%llu",
+ ProcessID, Kernel->db->idleTime);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+ "DB(%d): Map: total=%lu max=%lu",
+ ProcessID, database->mapMemory.totalBytes,
+ database->mapMemory.maxBytes);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+ "DB(%d): Map: total=%lu max=%lu",
+ ProcessID, database->mapUserMemory.totalBytes,
+ database->mapUserMemory.maxBytes);
+
+ if (database->list != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "Process %d has entries in its database:",
+ ProcessID);
+ }
+
+ for(i = 0; i < gcmCOUNTOF(database->list); i++)
+ {
+
+ /* Walk all records. */
+ for (record = database->list[i]; record != gcvNULL; record = next)
+ {
+ /* Next next record. */
+ next = record->next;
+
+ /* Dispatch on record type. */
+ switch (record->type)
+ {
+ case gcvDB_VIDEO_MEMORY:
+ gcmkERR_BREAK(gckVIDMEM_HANDLE_Lookup(record->kernel,
+ ProcessID,
+ gcmPTR2INT32(record->data),
+ &nodeObject));
+
+ /* Free the video memory. */
+ 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)",
+ record->data, status);
+ break;
+
+ case gcvDB_NON_PAGED:
+ physical = gcmNAME_TO_PTR(record->physical);
+ /* Unmap user logical memory first. */
+ status = gckOS_UnmapUserLogical(Kernel->os,
+ physical,
+ record->bytes,
+ record->data);
+
+ /* Free the non paged memory. */
+ status = gckEVENT_FreeNonPagedMemory(Kernel->eventObj,
+ record->bytes,
+ physical,
+ record->data,
+ gcvKERNEL_PIXEL);
+ gcmRELEASE_NAME(record->physical);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: NON_PAGED 0x%x, bytes=%lu (status=%d)",
+ record->data, record->bytes, status);
+ break;
+
+ case gcvDB_COMMAND_BUFFER:
+ /* Free the command buffer. */
+ status = gckEVENT_DestroyVirtualCommandBuffer(record->kernel->eventObj,
+ record->bytes,
+ gcmNAME_TO_PTR(record->physical),
+ record->data,
+ gcvKERNEL_PIXEL);
+ gcmRELEASE_NAME(record->physical);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: COMMAND_BUFFER 0x%x, bytes=%lu (status=%d)",
+ record->data, record->bytes, status);
+ break;
+
+ case gcvDB_CONTIGUOUS:
+ physical = gcmNAME_TO_PTR(record->physical);
+ /* Unmap user logical memory first. */
+ status = gckOS_UnmapUserLogical(Kernel->os,
+ physical,
+ record->bytes,
+ record->data);
+
+ /* Free the contiguous memory. */
+ status = gckEVENT_FreeContiguousMemory(Kernel->eventObj,
+ record->bytes,
+ physical,
+ record->data,
+ gcvKERNEL_PIXEL);
+ gcmRELEASE_NAME(record->physical);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: CONTIGUOUS 0x%x bytes=%lu (status=%d)",
+ record->data, record->bytes, status);
+ break;
+
+ case gcvDB_SIGNAL:
+#if USE_NEW_LINUX_SIGNAL
+ status = gcvSTATUS_NOT_SUPPORTED;
+#else
+ /* Free the user signal. */
+ status = gckOS_DestroyUserSignal(Kernel->os,
+ gcmPTR2INT32(record->data));
+#endif /* USE_NEW_LINUX_SIGNAL */
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: SIGNAL %d (status=%d)",
+ (gctINT)(gctUINTPTR_T)record->data, status);
+ break;
+
+ case gcvDB_VIDEO_MEMORY_LOCKED:
+ handle = gcmPTR2INT32(record->data);
+
+ gcmkERR_BREAK(gckVIDMEM_HANDLE_Lookup(record->kernel,
+ ProcessID,
+ handle,
+ &nodeObject));
+
+ /* Unlock what we still locked */
+ status = gckVIDMEM_Unlock(record->kernel,
+ nodeObject,
+ nodeObject->type,
+ &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
+ {
+ 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)",
+ record->data, status);
+ break;
+
+ case gcvDB_CONTEXT:
+ /* TODO: Free the context */
+ status = gckCOMMAND_Detach(Kernel->command, gcmNAME_TO_PTR(record->data));
+ gcmRELEASE_NAME(record->data);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: CONTEXT 0x%x (status=%d)",
+ record->data, status);
+ break;
+
+ case gcvDB_MAP_MEMORY:
+ /* Unmap memory. */
+ status = gckKERNEL_UnmapMemory(Kernel,
+ record->physical,
+ record->bytes,
+ record->data);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: MAP MEMORY %d (status=%d)",
+ gcmPTR2INT32(record->data), status);
+ break;
+
+ case gcvDB_MAP_USER_MEMORY:
+ /* TODO: Unmap user memory. */
+ status = gckOS_UnmapUserMemory(Kernel->os,
+ Kernel->core,
+ record->physical,
+ record->bytes,
+ gcmNAME_TO_PTR(record->data),
+ 0);
+ gcmRELEASE_NAME(record->data);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: MAP USER MEMORY %d (status=%d)",
+ gcmPTR2INT32(record->data), status);
+ break;
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+ case gcvDB_SYNC_POINT:
+ /* Free the user signal. */
+ status = gckOS_DestroySyncPoint(Kernel->os,
+ (gctSYNC_POINT) record->data);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: SYNC POINT %d (status=%d)",
+ (gctINT)(gctUINTPTR_T)record->data, status);
+ break;
+#endif
+
+ 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,
+ "DB: Correcupted record=0x%08x type=%d",
+ record, record->type);
+ break;
+ }
+
+ /* Delete the record. */
+ gcmkONERROR(gckKERNEL_DeleteRecord(Kernel,
+ database,
+ record->type,
+ record->data,
+ gcvNULL));
+ }
+
+ }
+
+ /* Delete the database. */
+ gcmkONERROR(gckKERNEL_DeleteDatabase(Kernel, database));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_QueryProcessDB
+**
+** Query a process database for the current usage of a particular record type.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** gctBOOL LastProcessID
+** gcvTRUE if searching for the last known process ID. gcvFALSE if
+** we need to search for the process ID specified by the ProcessID
+** argument.
+**
+** gceDATABASE_TYPE Type
+** Type of the record to query.
+**
+** OUTPUT:
+**
+** gcuDATABASE_INFO * Info
+** Pointer to a variable that receives the requested information.
+*/
+gceSTATUS
+gckKERNEL_QueryProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctBOOL LastProcessID,
+ IN gceDATABASE_TYPE Type,
+ OUT gcuDATABASE_INFO * Info
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gcePOOL vidMemPool;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Info=0x%x",
+ Kernel, ProcessID, Type, Info);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+
+ /* Deocde pool. */
+ vidMemPool = (Type & gcdDB_VIDEO_MEMORY_POOL_MASK) >> gcdDB_VIDEO_MEMORY_POOL_SHIFT;
+
+ Type &= gcdDATABASE_TYPE_MASK;
+
+ /* Find the database. */
+ gcmkONERROR(
+ gckKERNEL_FindDatabase(Kernel, ProcessID, LastProcessID, &database));
+
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, database->counterMutex, gcvINFINITE));
+
+ /* 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_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_IDLE:
+ Info->time = Kernel->db->idleTime;
+ Kernel->db->idleTime = 0;
+ 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));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_FindHandleDatbase(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ OUT gctPOINTER * HandleDatabase,
+ OUT gctPOINTER * HandleDatabaseMutex
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+
+ 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));
+
+ *HandleDatabase = database->handleDatabase;
+ *HandleDatabaseMutex = database->handleDatabaseMutex;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ 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
+**
+** Get teh secure cache from a process database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** OUTPUT:
+**
+** gcskSECURE_CACHE_PTR * Cache
+** Pointer to a variable that receives the secure cache pointer.
+*/
+gceSTATUS
+gckKERNEL_GetProcessDBCache(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ OUT gcskSECURE_CACHE_PTR * Cache
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Cache != gcvNULL);
+
+ /* Find the database. */
+ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+ /* Return the pointer to the cache. */
+ *Cache = &database->cache;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Cache=0x%x", *Cache);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+gceSTATUS
+gckKERNEL_DumpProcessDB(
+ IN gckKERNEL Kernel
+ )
+{
+ gcsDATABASE_PTR database;
+ gctINT i, pid;
+ gctUINT8 name[24];
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Acquire the database mutex. */
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+
+ gcmkPRINT("**************************\n");
+ gcmkPRINT("*** PROCESS DB DUMP ***\n");
+ gcmkPRINT("**************************\n");
+
+ gcmkPRINT_N(8, "%-8s%s\n", "PID", "NAME");
+ /* 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));
+
+ gcmkPRINT_N(8, "%-8d%s\n", pid, name);
+ }
+ }
+
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Success. */
+ 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;
+}
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c
new file mode 100644
index 000000000000..7bd0c57c8e55
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c
@@ -0,0 +1,2821 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+#include <gc_hal_kernel_debug.h>
+
+/******************************************************************************\
+******************************** Debug Variables *******************************
+\******************************************************************************/
+
+static gceSTATUS _lastError = gcvSTATUS_OK;
+static gctUINT32 _debugLevel = gcvLEVEL_ERROR;
+/*
+_debugZones config value
+Please Reference define in gc_hal_base.h
+*/
+static gctUINT32 _debugZones = gcvZONE_NONE;
+
+/******************************************************************************\
+********************************* Debug Switches *******************************
+\******************************************************************************/
+
+/*
+ gcdBUFFERED_OUTPUT
+
+ When set to non-zero, all output is collected into a buffer with the
+ specified size. Once the buffer gets full, the debug buffer will be
+ printed to the console. gcdBUFFERED_SIZE determines the size of the buffer.
+*/
+#define gcdBUFFERED_OUTPUT 0
+
+/*
+ gcdBUFFERED_SIZE
+
+ When set to non-zero, all output is collected into a buffer with the
+ specified size. Once the buffer gets full, the debug buffer will be
+ printed to the console.
+*/
+#define gcdBUFFERED_SIZE (1024 * 1024 * 2)
+
+/*
+ gcdDMA_BUFFER_COUNT
+
+ If greater then zero, the debugger will attempt to find the command buffer
+ where DMA is currently executing and then print this buffer and
+ (gcdDMA_BUFFER_COUNT - 1) buffers before the current one. If set to zero
+ or the current buffer is not found, all buffers are printed.
+*/
+#define gcdDMA_BUFFER_COUNT 0
+
+/*
+ gcdTHREAD_BUFFERS
+
+ When greater then one, will accumulate messages from the specified number
+ of threads in separate output buffers.
+*/
+#define gcdTHREAD_BUFFERS 1
+
+/*
+ gcdENABLE_OVERFLOW
+
+ When set to non-zero, and the output buffer gets full, instead of being
+ printed, it will be allowed to overflow removing the oldest messages.
+*/
+#define gcdENABLE_OVERFLOW 1
+
+/*
+ gcdSHOW_LINE_NUMBER
+
+ When enabledm each print statement will be preceeded with the current
+ line number.
+*/
+#define gcdSHOW_LINE_NUMBER 0
+
+/*
+ gcdSHOW_PROCESS_ID
+
+ When enabledm each print statement will be preceeded with the current
+ process ID.
+*/
+#define gcdSHOW_PROCESS_ID 0
+
+/*
+ gcdSHOW_THREAD_ID
+
+ When enabledm each print statement will be preceeded with the current
+ thread ID.
+*/
+#define gcdSHOW_THREAD_ID 0
+
+/*
+ gcdSHOW_TIME
+
+ When enabled each print statement will be preceeded with the current
+ high-resolution time.
+*/
+#define gcdSHOW_TIME 0
+
+
+/******************************************************************************\
+****************************** Miscellaneous Macros ****************************
+\******************************************************************************/
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+# define gcmDBGASSERT(Expression, Format, Value) \
+ if (!(Expression)) \
+ { \
+ _DirectPrint( \
+ "*** gcmDBGASSERT ***************************\n" \
+ " function : %s\n" \
+ " line : %d\n" \
+ " expression : " #Expression "\n" \
+ " actual value : " Format "\n", \
+ __FUNCTION__, __LINE__, Value \
+ ); \
+ }
+#else
+# define gcmDBGASSERT(Expression, Format, Value)
+#endif
+
+#define gcmPTRALIGNMENT(Pointer, Alignemnt) \
+( \
+ gcmALIGN(gcmPTR2INT32(Pointer), Alignemnt) - gcmPTR2INT32(Pointer) \
+)
+
+#if gcdALIGNBYSIZE
+# define gcmISALIGNED(Offset, Alignment) \
+ (((Offset) & ((Alignment) - 1)) == 0)
+
+# define gcmkALIGNPTR(Type, Pointer, Alignment) \
+ Pointer = (Type) gcmINT2PTR(gcmALIGN(gcmPTR2INT32(Pointer), Alignment))
+#else
+# define gcmISALIGNED(Offset, Alignment) \
+ gcvTRUE
+
+# define gcmkALIGNPTR(Type, Pointer, Alignment)
+#endif
+
+#define gcmALIGNSIZE(Offset, Size) \
+ ((Size - Offset) + Size)
+
+#define gcdHAVEPREFIX \
+( \
+ gcdSHOW_TIME \
+ || gcdSHOW_LINE_NUMBER \
+ || gcdSHOW_PROCESS_ID \
+ || gcdSHOW_THREAD_ID \
+)
+
+#if gcdHAVEPREFIX
+
+# define gcdOFFSET 0
+
+#if gcdSHOW_TIME
+#if gcmISALIGNED(gcdOFFSET, 8)
+# define gcdTIMESIZE gcmSIZEOF(gctUINT64)
+# elif gcdOFFSET == 4
+# define gcdTIMESIZE gcmALIGNSIZE(4, gcmSIZEOF(gctUINT64))
+# else
+# error "Unexpected offset value."
+# endif
+# undef gcdOFFSET
+# define gcdOFFSET 8
+#if !defined(gcdPREFIX_LEADER)
+# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT64)
+# define gcdTIMEFORMAT "0x%016llX"
+# else
+# define gcdTIMEFORMAT ", 0x%016llX"
+# endif
+# else
+# define gcdTIMESIZE 0
+# define gcdTIMEFORMAT
+# endif
+
+#if gcdSHOW_LINE_NUMBER
+#if gcmISALIGNED(gcdOFFSET, 8)
+# define gcdNUMSIZE gcmSIZEOF(gctUINT64)
+# elif gcdOFFSET == 4
+# define gcdNUMSIZE gcmALIGNSIZE(4, gcmSIZEOF(gctUINT64))
+# else
+# error "Unexpected offset value."
+# endif
+# undef gcdOFFSET
+# define gcdOFFSET 8
+#if !defined(gcdPREFIX_LEADER)
+# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT64)
+# define gcdNUMFORMAT "%8llu"
+# else
+# define gcdNUMFORMAT ", %8llu"
+# endif
+# else
+# define gcdNUMSIZE 0
+# define gcdNUMFORMAT
+# endif
+
+#if gcdSHOW_PROCESS_ID
+#if gcmISALIGNED(gcdOFFSET, 4)
+# define gcdPIDSIZE gcmSIZEOF(gctUINT32)
+# else
+# error "Unexpected offset value."
+# endif
+# undef gcdOFFSET
+# define gcdOFFSET 4
+#if !defined(gcdPREFIX_LEADER)
+# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32)
+# define gcdPIDFORMAT "pid=%5d"
+# else
+# define gcdPIDFORMAT ", pid=%5d"
+# endif
+# else
+# define gcdPIDSIZE 0
+# define gcdPIDFORMAT
+# endif
+
+#if gcdSHOW_THREAD_ID
+#if gcmISALIGNED(gcdOFFSET, 4)
+# define gcdTIDSIZE gcmSIZEOF(gctUINT32)
+# else
+# error "Unexpected offset value."
+# endif
+# undef gcdOFFSET
+# define gcdOFFSET 4
+#if !defined(gcdPREFIX_LEADER)
+# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32)
+# define gcdTIDFORMAT "tid=%5d"
+# else
+# define gcdTIDFORMAT ", tid=%5d"
+# endif
+# else
+# define gcdTIDSIZE 0
+# define gcdTIDFORMAT
+# endif
+
+# define gcdPREFIX_SIZE \
+ ( \
+ gcdTIMESIZE \
+ + gcdNUMSIZE \
+ + gcdPIDSIZE \
+ + gcdTIDSIZE \
+ )
+
+ static const char * _prefixFormat =
+ "["
+ gcdTIMEFORMAT
+ gcdNUMFORMAT
+ gcdPIDFORMAT
+ gcdTIDFORMAT
+ "] ";
+
+#else
+
+# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32)
+# define gcdPREFIX_SIZE 0
+
+#endif
+
+/* Assumed largest variable argument leader size. */
+#define gcdVARARG_LEADER gcmSIZEOF(gctUINT64)
+
+/* Alignnments. */
+#if gcdALIGNBYSIZE
+# define gcdPREFIX_ALIGNMENT gcdPREFIX_LEADER
+# define gcdVARARG_ALIGNMENT gcdVARARG_LEADER
+#else
+# define gcdPREFIX_ALIGNMENT 0
+# define gcdVARARG_ALIGNMENT 0
+#endif
+
+#if gcdBUFFERED_OUTPUT
+# define gcdOUTPUTPREFIX _AppendPrefix
+# define gcdOUTPUTSTRING _AppendString
+# define gcdOUTPUTCOPY _AppendCopy
+# define gcdOUTPUTBUFFER _AppendBuffer
+#else
+# define gcdOUTPUTPREFIX _PrintPrefix
+# define gcdOUTPUTSTRING _PrintString
+# define gcdOUTPUTCOPY _PrintString
+# define gcdOUTPUTBUFFER _PrintBuffer
+#endif
+
+/******************************************************************************\
+****************************** Private Structures ******************************
+\******************************************************************************/
+
+typedef enum _gceBUFITEM
+{
+ gceBUFITEM_NONE,
+ gcvBUFITEM_PREFIX,
+ gcvBUFITEM_STRING,
+ gcvBUFITEM_COPY,
+ gcvBUFITEM_BUFFER
+}
+gceBUFITEM;
+
+/* Common item head/buffer terminator. */
+typedef struct _gcsBUFITEM_HEAD * gcsBUFITEM_HEAD_PTR;
+typedef struct _gcsBUFITEM_HEAD
+{
+ gceBUFITEM type;
+}
+gcsBUFITEM_HEAD;
+
+/* String prefix (for ex. [ 1,tid=0x019A]) */
+typedef struct _gcsBUFITEM_PREFIX * gcsBUFITEM_PREFIX_PTR;
+typedef struct _gcsBUFITEM_PREFIX
+{
+ gceBUFITEM type;
+#if gcdHAVEPREFIX
+ gctPOINTER prefixData;
+#endif
+}
+gcsBUFITEM_PREFIX;
+
+/* Buffered string. */
+typedef struct _gcsBUFITEM_STRING * gcsBUFITEM_STRING_PTR;
+typedef struct _gcsBUFITEM_STRING
+{
+ gceBUFITEM type;
+ gctINT indent;
+ gctCONST_STRING message;
+ gctPOINTER messageData;
+ gctUINT messageDataSize;
+}
+gcsBUFITEM_STRING;
+
+/* Buffered string (copy of the string is included with the record). */
+typedef struct _gcsBUFITEM_COPY * gcsBUFITEM_COPY_PTR;
+typedef struct _gcsBUFITEM_COPY
+{
+ gceBUFITEM type;
+ gctINT indent;
+ gctPOINTER messageData;
+ gctUINT messageDataSize;
+}
+gcsBUFITEM_COPY;
+
+/* Memory buffer. */
+typedef struct _gcsBUFITEM_BUFFER * gcsBUFITEM_BUFFER_PTR;
+typedef struct _gcsBUFITEM_BUFFER
+{
+ gceBUFITEM type;
+ gctINT indent;
+ gceDUMP_BUFFER bufferType;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+ gctUINT32 dmaAddress;
+#endif
+
+ gctUINT dataSize;
+ gctUINT32 address;
+#if gcdHAVEPREFIX
+ gctPOINTER prefixData;
+#endif
+}
+gcsBUFITEM_BUFFER;
+
+typedef struct _gcsBUFFERED_OUTPUT * gcsBUFFERED_OUTPUT_PTR;
+typedef struct _gcsBUFFERED_OUTPUT
+{
+#if gcdTHREAD_BUFFERS > 1
+ gctUINT32 threadID;
+#endif
+
+#if gcdSHOW_LINE_NUMBER
+ gctUINT64 lineNumber;
+#endif
+
+ gctINT indent;
+
+#if gcdBUFFERED_OUTPUT
+ gctINT start;
+ gctINT index;
+ gctINT count;
+ gctUINT8 buffer[gcdBUFFERED_SIZE];
+#endif
+
+ gcsBUFFERED_OUTPUT_PTR prev;
+ gcsBUFFERED_OUTPUT_PTR next;
+}
+gcsBUFFERED_OUTPUT;
+
+typedef gctUINT (* gcfPRINTSTRING) (
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gcsBUFITEM_HEAD_PTR Item
+ );
+
+typedef gctINT (* gcfGETITEMSIZE) (
+ IN gcsBUFITEM_HEAD_PTR Item
+ );
+
+/******************************************************************************\
+******************************* Private Variables ******************************
+\******************************************************************************/
+
+static gcsBUFFERED_OUTPUT _outputBuffer[gcdTHREAD_BUFFERS];
+static gcsBUFFERED_OUTPUT_PTR _outputBufferHead = gcvNULL;
+static gcsBUFFERED_OUTPUT_PTR _outputBufferTail = gcvNULL;
+
+/******************************************************************************\
+****************************** Item Size Functions *****************************
+\******************************************************************************/
+
+#if gcdBUFFERED_OUTPUT
+static gctINT
+_GetTerminatorItemSize(
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+ return gcmSIZEOF(gcsBUFITEM_HEAD);
+}
+
+static gctINT
+_GetPrefixItemSize(
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+#if gcdHAVEPREFIX
+ gcsBUFITEM_PREFIX_PTR item = (gcsBUFITEM_PREFIX_PTR) Item;
+ gctUINT vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
+ return vlen + gcdPREFIX_SIZE;
+#else
+ return gcmSIZEOF(gcsBUFITEM_PREFIX);
+#endif
+}
+
+static gctINT
+_GetStringItemSize(
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+ gcsBUFITEM_STRING_PTR item = (gcsBUFITEM_STRING_PTR) Item;
+ gctUINT vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
+ return vlen + item->messageDataSize;
+}
+
+static gctINT
+_GetCopyItemSize(
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+ gcsBUFITEM_COPY_PTR item = (gcsBUFITEM_COPY_PTR) Item;
+ gctUINT vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
+ return vlen + item->messageDataSize;
+}
+
+static gctINT
+_GetBufferItemSize(
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+#if gcdHAVEPREFIX
+ gcsBUFITEM_BUFFER_PTR item = (gcsBUFITEM_BUFFER_PTR) Item;
+ gctUINT vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
+ return vlen + gcdPREFIX_SIZE + item->dataSize;
+#else
+ gcsBUFITEM_BUFFER_PTR item = (gcsBUFITEM_BUFFER_PTR) Item;
+ return gcmSIZEOF(gcsBUFITEM_BUFFER) + item->dataSize;
+#endif
+}
+
+static gcfGETITEMSIZE _itemSize[] =
+{
+ _GetTerminatorItemSize,
+ _GetPrefixItemSize,
+ _GetStringItemSize,
+ _GetCopyItemSize,
+ _GetBufferItemSize
+};
+#endif
+
+/******************************************************************************\
+******************************* Printing Functions *****************************
+\******************************************************************************/
+
+#if gcdDEBUG || gcdBUFFERED_OUTPUT
+static void
+_DirectPrint(
+ gctCONST_STRING Message,
+ ...
+ )
+{
+ gctINT len;
+ char buffer[768];
+ gctARGUMENTS arguments;
+
+ gcmkARGUMENTS_START(arguments, Message);
+ len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), Message, &arguments);
+ gcmkARGUMENTS_END(arguments);
+
+ buffer[len] = '\0';
+ gcmkOUTPUT_STRING(buffer);
+}
+#endif
+
+static int
+_AppendIndent(
+ IN gctINT Indent,
+ IN char * Buffer,
+ IN int BufferSize
+ )
+{
+ gctINT i;
+
+ gctINT len = 0;
+ gctINT indent = Indent % 40;
+
+ for (i = 0; i < indent; i += 1)
+ {
+ Buffer[len++] = ' ';
+ }
+
+ if (indent != Indent)
+ {
+ len += gcmkSPRINTF(
+ Buffer + len, BufferSize - len, " <%d> ", Indent
+ );
+
+ Buffer[len] = '\0';
+ }
+
+ return len;
+}
+
+#if gcdHAVEPREFIX
+static void
+_PrintPrefix(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctPOINTER Data
+ )
+{
+ char buffer[768];
+ gctINT len;
+
+ /* Format the string. */
+ len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), _prefixFormat, Data);
+ buffer[len] = '\0';
+
+ /* Print the string. */
+ gcmkOUTPUT_STRING(buffer);
+}
+#endif
+
+static void
+_PrintString(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Indent,
+ IN gctCONST_STRING Message,
+ IN gctUINT ArgumentSize,
+ IN gctPOINTER Data
+ )
+{
+ char buffer[768];
+ gctINT len;
+
+ /* Append the indent string. */
+ len = _AppendIndent(Indent, buffer, gcmSIZEOF(buffer));
+
+ /* Format the string. */
+ len += gcmkVSPRINTF(buffer + len, gcmSIZEOF(buffer) - len, Message, Data);
+ buffer[len] = '\0';
+
+ /* Add end-of-line if missing. */
+ if (buffer[len - 1] != '\n')
+ {
+ buffer[len++] = '\n';
+ buffer[len] = '\0';
+ }
+
+ /* Print the string. */
+ gcmkOUTPUT_STRING(buffer);
+}
+
+static void
+_PrintBuffer(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Indent,
+ IN gctPOINTER PrefixData,
+ IN gctPOINTER Data,
+ IN gctUINT Address,
+ IN gctUINT DataSize,
+ IN gceDUMP_BUFFER Type,
+ IN gctUINT32 DmaAddress
+ )
+{
+ static gctCONST_STRING _titleString[] =
+ {
+ "CONTEXT BUFFER",
+ "USER COMMAND BUFFER",
+ "KERNEL COMMAND BUFFER",
+ "LINK BUFFER",
+ "WAIT LINK BUFFER",
+ ""
+ };
+
+ static const gctINT COLUMN_COUNT = 8;
+
+ gctUINT i, count, column, address;
+ gctUINT32_PTR data;
+ gctCHAR buffer[768];
+ gctUINT indent, len;
+ gctBOOL command;
+
+ /* Append space for the prefix. */
+#if gcdHAVEPREFIX
+ indent = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), _prefixFormat, PrefixData);
+ buffer[indent] = '\0';
+#else
+ indent = 0;
+#endif
+
+ /* Append the indent string. */
+ indent += _AppendIndent(
+ Indent, buffer + indent, gcmSIZEOF(buffer) - indent
+ );
+
+ switch (Type)
+ {
+ case gceDUMP_BUFFER_CONTEXT:
+ case gceDUMP_BUFFER_USER:
+ case gceDUMP_BUFFER_KERNEL:
+ case gceDUMP_BUFFER_LINK:
+ case gceDUMP_BUFFER_WAITLINK:
+ /* Form and print the title string. */
+ gcmkSPRINTF2(
+ buffer + indent, gcmSIZEOF(buffer) - indent,
+ "%s%s\n", _titleString[Type],
+ ((DmaAddress >= Address) && (DmaAddress < Address + DataSize))
+ ? " (CURRENT)" : ""
+ );
+
+ gcmkOUTPUT_STRING(buffer);
+
+ /* Terminate the string. */
+ buffer[indent] = '\0';
+
+ /* This is a command buffer. */
+ command = gcvTRUE;
+ break;
+
+ case gceDUMP_BUFFER_FROM_USER:
+ /* This is not a command buffer. */
+ command = gcvFALSE;
+
+ /* No title. */
+ break;
+
+ default:
+ gcmDBGASSERT(gcvFALSE, "%s", "invalid buffer type");
+
+ /* This is not a command buffer. */
+ command = gcvFALSE;
+ }
+
+ /* Overwrite the prefix with spaces. */
+ for (i = 0; i < indent; i += 1)
+ {
+ buffer[i] = ' ';
+ }
+
+ /* Form and print the opening string. */
+ if (command)
+ {
+ gcmkSPRINTF2(
+ buffer + indent, gcmSIZEOF(buffer) - indent,
+ "@[kernel.command %08X %08X\n", Address, DataSize
+ );
+
+ gcmkOUTPUT_STRING(buffer);
+
+ /* Terminate the string. */
+ buffer[indent] = '\0';
+ }
+
+ /* Get initial address. */
+ address = Address;
+
+ /* Cast the data pointer. */
+ data = (gctUINT32_PTR) Data;
+
+ /* Compute the number of double words. */
+ count = DataSize / gcmSIZEOF(gctUINT32);
+
+ /* Print the buffer. */
+ for (i = 0, len = indent, column = 0; i < count; i += 1)
+ {
+ /* Append the address. */
+ if (column == 0)
+ {
+ len += gcmkSPRINTF(
+ buffer + len, gcmSIZEOF(buffer) - len, "0x%08X:", address
+ );
+ }
+
+ /* Append the data value. */
+ len += gcmkSPRINTF2(
+ buffer + len, gcmSIZEOF(buffer) - len, "%c%08X",
+ (address == DmaAddress)? '>' : ' ', data[i]
+ );
+
+ buffer[len] = '\0';
+
+ /* Update the address. */
+ address += gcmSIZEOF(gctUINT32);
+
+ /* Advance column count. */
+ column += 1;
+
+ /* End of line? */
+ if ((column % COLUMN_COUNT) == 0)
+ {
+ /* Append EOL. */
+ gcmkSTRCAT(buffer + len, gcmSIZEOF(buffer) - len, "\n");
+
+ /* Print the string. */
+ gcmkOUTPUT_STRING(buffer);
+
+ /* Reset. */
+ len = indent;
+ column = 0;
+ }
+ }
+
+ /* Print the last partial string. */
+ if (column != 0)
+ {
+ /* Append EOL. */
+ gcmkSTRCAT(buffer + len, gcmSIZEOF(buffer) - len, "\n");
+
+ /* Print the string. */
+ gcmkOUTPUT_STRING(buffer);
+ }
+
+ /* Form and print the opening string. */
+ if (command)
+ {
+ buffer[indent] = '\0';
+ gcmkSTRCAT(buffer, gcmSIZEOF(buffer), "] -- command\n");
+ gcmkOUTPUT_STRING(buffer);
+ }
+}
+
+#if gcdBUFFERED_OUTPUT
+static gctUINT
+_PrintNone(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+ /* Return the size of the node. */
+ return gcmSIZEOF(gcsBUFITEM_HEAD);
+}
+
+static gctUINT
+_PrintPrefixWrapper(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+#if gcdHAVEPREFIX
+ gcsBUFITEM_PREFIX_PTR item;
+ gctUINT vlen;
+
+ /* Get access to the data. */
+ item = (gcsBUFITEM_PREFIX_PTR) Item;
+
+ /* Print the message. */
+ _PrintPrefix(OutputBuffer, item->prefixData);
+
+ /* Compute the size of the variable portion of the structure. */
+ vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
+
+ /* Return the size of the node. */
+ return vlen + gcdPREFIX_SIZE;
+#else
+ return gcmSIZEOF(gcsBUFITEM_PREFIX);
+#endif
+}
+
+static gctUINT
+_PrintStringWrapper(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+ gcsBUFITEM_STRING_PTR item;
+ gctUINT vlen;
+
+ /* Get access to the data. */
+ item = (gcsBUFITEM_STRING_PTR) Item;
+
+ /* Print the message. */
+ _PrintString(
+ OutputBuffer,
+ item->indent, item->message, item->messageDataSize, item->messageData
+ );
+
+ /* Compute the size of the variable portion of the structure. */
+ vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
+
+ /* Return the size of the node. */
+ return vlen + item->messageDataSize;
+}
+
+static gctUINT
+_PrintCopyWrapper(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+ gcsBUFITEM_COPY_PTR item;
+ gctCONST_STRING message;
+ gctUINT vlen;
+
+ /* Get access to the data. */
+ item = (gcsBUFITEM_COPY_PTR) Item;
+
+ /* Determine the string pointer. */
+ message = (gctCONST_STRING) (item + 1);
+
+ /* Print the message. */
+ _PrintString(
+ OutputBuffer,
+ item->indent, message, item->messageDataSize, item->messageData
+ );
+
+ /* Compute the size of the variable portion of the structure. */
+ vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
+
+ /* Return the size of the node. */
+ return vlen + item->messageDataSize;
+}
+
+static gctUINT
+_PrintBufferWrapper(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+#if gcdHAVEPREFIX
+ gctUINT32 dmaAddress;
+ gcsBUFITEM_BUFFER_PTR item;
+ gctPOINTER data;
+ gctUINT vlen;
+
+ /* Get access to the data. */
+ item = (gcsBUFITEM_BUFFER_PTR) Item;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+ dmaAddress = item->dmaAddress;
+#else
+ dmaAddress = 0xFFFFFFFF;
+#endif
+
+ if (dmaAddress != 0)
+ {
+ /* Compute the data address. */
+ data = ((gctUINT8_PTR) item->prefixData) + gcdPREFIX_SIZE;
+
+ /* Print buffer. */
+ _PrintBuffer(
+ OutputBuffer,
+ item->indent, item->prefixData,
+ data, item->address, item->dataSize,
+ item->bufferType, dmaAddress
+ );
+ }
+
+ /* Compute the size of the variable portion of the structure. */
+ vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
+
+ /* Return the size of the node. */
+ return vlen + gcdPREFIX_SIZE + item->dataSize;
+#else
+ gctUINT32 dmaAddress;
+ gcsBUFITEM_BUFFER_PTR item;
+
+ /* Get access to the data. */
+ item = (gcsBUFITEM_BUFFER_PTR) Item;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+ dmaAddress = item->dmaAddress;
+#else
+ dmaAddress = 0xFFFFFFFF;
+#endif
+
+ if (dmaAddress != 0)
+ {
+ /* Print buffer. */
+ _PrintBuffer(
+ OutputBuffer,
+ item->indent, gcvNULL,
+ item + 1, item->address, item->dataSize,
+ item->bufferType, dmaAddress
+ );
+ }
+
+ /* Return the size of the node. */
+ return gcmSIZEOF(gcsBUFITEM_BUFFER) + item->dataSize;
+#endif
+}
+
+static gcfPRINTSTRING _printArray[] =
+{
+ _PrintNone,
+ _PrintPrefixWrapper,
+ _PrintStringWrapper,
+ _PrintCopyWrapper,
+ _PrintBufferWrapper
+};
+#endif
+
+/******************************************************************************\
+******************************* Private Functions ******************************
+\******************************************************************************/
+
+#if gcdBUFFERED_OUTPUT
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+static gcsBUFITEM_BUFFER_PTR
+_FindCurrentDMABuffer(
+ gctUINT32 DmaAddress
+ )
+{
+ gctINT i, skip;
+ gcsBUFITEM_HEAD_PTR item;
+ gcsBUFITEM_BUFFER_PTR dmaCurrent;
+
+ /* Reset the current buffer. */
+ dmaCurrent = gcvNULL;
+
+ /* Get the first stored item. */
+ item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
+
+ /* Run through all items. */
+ for (i = 0; i < _outputBufferHead->count; i += 1)
+ {
+ /* Buffer item? */
+ if (item->type == gcvBUFITEM_BUFFER)
+ {
+ gcsBUFITEM_BUFFER_PTR buffer = (gcsBUFITEM_BUFFER_PTR) item;
+
+ if ((DmaAddress >= buffer->address) &&
+ (DmaAddress < buffer->address + buffer->dataSize))
+ {
+ dmaCurrent = buffer;
+ }
+ }
+
+ /* Get the item size and skip it. */
+ skip = (* _itemSize[item->type]) (item);
+ item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+ /* End of the buffer? Wrap around. */
+ if (item->type == gceBUFITEM_NONE)
+ {
+ item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
+ }
+ }
+
+ /* Return result. */
+ return dmaCurrent;
+}
+
+static void
+_EnableAllDMABuffers(
+ void
+ )
+{
+ gctINT i, skip;
+ gcsBUFITEM_HEAD_PTR item;
+
+ /* Get the first stored item. */
+ item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
+
+ /* Run through all items. */
+ for (i = 0; i < _outputBufferHead->count; i += 1)
+ {
+ /* Buffer item? */
+ if (item->type == gcvBUFITEM_BUFFER)
+ {
+ gcsBUFITEM_BUFFER_PTR buffer = (gcsBUFITEM_BUFFER_PTR) item;
+
+ /* Enable the buffer. */
+ buffer->dmaAddress = ~0U;
+ }
+
+ /* Get the item size and skip it. */
+ skip = (* _itemSize[item->type]) (item);
+ item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+ /* End of the buffer? Wrap around. */
+ if (item->type == gceBUFITEM_NONE)
+ {
+ item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
+ }
+ }
+}
+
+static void
+_EnableDMABuffers(
+ gctUINT32 DmaAddress,
+ gcsBUFITEM_BUFFER_PTR CurrentDMABuffer
+ )
+{
+ gctINT i, skip, index;
+ gcsBUFITEM_HEAD_PTR item;
+ gcsBUFITEM_BUFFER_PTR buffers[gcdDMA_BUFFER_COUNT];
+
+ /* Reset buffer pointers. */
+ gckOS_ZeroMemory(buffers, gcmSIZEOF(buffers));
+
+ /* Set the current buffer index. */
+ index = -1;
+
+ /* Get the first stored item. */
+ item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
+
+ /* Run through all items until the current DMA buffer is found. */
+ for (i = 0; i < _outputBufferHead->count; i += 1)
+ {
+ /* Buffer item? */
+ if (item->type == gcvBUFITEM_BUFFER)
+ {
+ /* Advance the index. */
+ index = (index + 1) % gcdDMA_BUFFER_COUNT;
+
+ /* Add to the buffer array. */
+ buffers[index] = (gcsBUFITEM_BUFFER_PTR) item;
+
+ /* Stop if this is the current DMA buffer. */
+ if ((gcsBUFITEM_BUFFER_PTR) item == CurrentDMABuffer)
+ {
+ break;
+ }
+ }
+
+ /* Get the item size and skip it. */
+ skip = (* _itemSize[item->type]) (item);
+ item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+ /* End of the buffer? Wrap around. */
+ if (item->type == gceBUFITEM_NONE)
+ {
+ item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
+ }
+ }
+
+ /* Enable the found buffers. */
+ gcmDBGASSERT(index != -1, "%d", index);
+
+ for (i = 0; i < gcdDMA_BUFFER_COUNT; i += 1)
+ {
+ if (buffers[index] == gcvNULL)
+ {
+ break;
+ }
+
+ buffers[index]->dmaAddress = DmaAddress;
+
+ index -= 1;
+
+ if (index == -1)
+ {
+ index = gcdDMA_BUFFER_COUNT - 1;
+ }
+ }
+}
+#endif
+
+static void
+_Flush(
+ gctUINT32 DmaAddress
+ )
+{
+ gctINT i, skip;
+ gcsBUFITEM_HEAD_PTR item;
+
+ gcsBUFFERED_OUTPUT_PTR outputBuffer = _outputBufferHead;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+ if ((outputBuffer != gcvNULL) && (outputBuffer->count != 0))
+ {
+ /* Find the current DMA buffer. */
+ gcsBUFITEM_BUFFER_PTR dmaCurrent = _FindCurrentDMABuffer(DmaAddress);
+
+ /* Was the current buffer found? */
+ if (dmaCurrent == gcvNULL)
+ {
+ /* No, print all buffers. */
+ _EnableAllDMABuffers();
+ }
+ else
+ {
+ /* Yes, enable only specified number of buffers. */
+ _EnableDMABuffers(DmaAddress, dmaCurrent);
+ }
+ }
+#endif
+
+ while (outputBuffer != gcvNULL)
+ {
+ if (outputBuffer->count != 0)
+ {
+ _DirectPrint("********************************************************************************\n");
+ _DirectPrint("FLUSHING DEBUG OUTPUT BUFFER (%d elements).\n", outputBuffer->count);
+ _DirectPrint("********************************************************************************\n");
+
+ item = (gcsBUFITEM_HEAD_PTR) &outputBuffer->buffer[outputBuffer->start];
+
+ for (i = 0; i < outputBuffer->count; i += 1)
+ {
+ skip = (* _printArray[item->type]) (outputBuffer, item);
+
+ item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+ if (item->type == gceBUFITEM_NONE)
+ {
+ item = (gcsBUFITEM_HEAD_PTR) outputBuffer->buffer;
+ }
+ }
+
+ outputBuffer->start = 0;
+ outputBuffer->index = 0;
+ outputBuffer->count = 0;
+ }
+
+ outputBuffer = outputBuffer->next;
+ }
+}
+
+static gcsBUFITEM_HEAD_PTR
+_AllocateItem(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Size
+ )
+{
+ gctINT skip;
+ gcsBUFITEM_HEAD_PTR item, next;
+
+#if gcdENABLE_OVERFLOW
+ if (
+ (OutputBuffer->index + Size >= gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
+ ||
+ (
+ (OutputBuffer->index < OutputBuffer->start) &&
+ (OutputBuffer->index + Size >= OutputBuffer->start)
+ )
+ )
+ {
+ if (OutputBuffer->index + Size >= gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
+ {
+ if (OutputBuffer->index < OutputBuffer->start)
+ {
+ item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->start];
+
+ while (item->type != gceBUFITEM_NONE)
+ {
+ skip = (* _itemSize[item->type]) (item);
+
+ OutputBuffer->start += skip;
+ OutputBuffer->count -= 1;
+
+ item->type = gceBUFITEM_NONE;
+ item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+ }
+
+ OutputBuffer->start = 0;
+ }
+
+ OutputBuffer->index = 0;
+ }
+
+ item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->start];
+
+ while (OutputBuffer->start - OutputBuffer->index <= Size)
+ {
+ skip = (* _itemSize[item->type]) (item);
+
+ OutputBuffer->start += skip;
+ OutputBuffer->count -= 1;
+
+ item->type = gceBUFITEM_NONE;
+ item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+ if (item->type == gceBUFITEM_NONE)
+ {
+ OutputBuffer->start = 0;
+ break;
+ }
+ }
+ }
+#else
+ if (OutputBuffer->index + Size > gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
+ {
+ _DirectPrint("\nMessage buffer full; forcing message flush.\n\n");
+ _Flush(~0U);
+ }
+#endif
+
+ item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->index];
+
+ OutputBuffer->index += Size;
+ OutputBuffer->count += 1;
+
+ next = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + Size);
+ next->type = gceBUFITEM_NONE;
+
+ return item;
+}
+
+#if gcdALIGNBYSIZE
+static void
+_FreeExtraSpace(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctPOINTER Item,
+ IN gctINT ItemSize,
+ IN gctINT FreeSize
+ )
+{
+ gcsBUFITEM_HEAD_PTR next;
+
+ OutputBuffer->index -= FreeSize;
+
+ next = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) Item + ItemSize);
+ next->type = gceBUFITEM_NONE;
+}
+#endif
+
+#if gcdHAVEPREFIX
+static void
+_AppendPrefix(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctPOINTER Data
+ )
+{
+ gctUINT8_PTR prefixData;
+ gcsBUFITEM_PREFIX_PTR item;
+ gctINT allocSize;
+
+#if gcdALIGNBYSIZE
+ gctUINT alignment;
+ gctINT size, freeSize;
+#endif
+
+ gcmDBGASSERT(Data != gcvNULL, "%p", Data);
+
+ /* Determine the maximum item size. */
+ allocSize
+ = gcmSIZEOF(gcsBUFITEM_PREFIX)
+ + gcdPREFIX_SIZE
+ + gcdPREFIX_ALIGNMENT;
+
+ /* Allocate prefix item. */
+ item = (gcsBUFITEM_PREFIX_PTR) _AllocateItem(OutputBuffer, allocSize);
+
+ /* Compute the initial prefix data pointer. */
+ prefixData = (gctUINT8_PTR) (item + 1);
+
+ /* Align the data pointer as necessary. */
+#if gcdALIGNBYSIZE
+ alignment = gcmPTRALIGNMENT(prefixData, gcdPREFIX_ALIGNMENT);
+ prefixData += alignment;
+#endif
+
+ /* Set item data. */
+ item->type = gcvBUFITEM_PREFIX;
+ item->prefixData = prefixData;
+
+ /* Copy argument value. */
+ gcmkMEMCPY(prefixData, Data, gcdPREFIX_SIZE);
+
+#if gcdALIGNBYSIZE
+ /* Compute the actual node size. */
+ size = gcmSIZEOF(gcsBUFITEM_PREFIX) + gcdPREFIX_SIZE + alignment;
+
+ /* Free extra memory if any. */
+ freeSize = allocSize - size;
+ if (freeSize != 0)
+ {
+ _FreeExtraSpace(OutputBuffer, item, size, freeSize);
+ }
+#endif
+}
+#endif
+
+static void
+_AppendString(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Indent,
+ IN gctCONST_STRING Message,
+ IN gctUINT ArgumentSize,
+ IN gctPOINTER Data
+ )
+{
+ gctUINT8_PTR messageData;
+ gcsBUFITEM_STRING_PTR item;
+ gctINT allocSize;
+
+#if gcdALIGNBYSIZE
+ gctUINT alignment;
+ gctINT size, freeSize;
+#endif
+
+ /* Determine the maximum item size. */
+ allocSize
+ = gcmSIZEOF(gcsBUFITEM_STRING)
+ + ArgumentSize
+ + gcdVARARG_ALIGNMENT;
+
+ /* Allocate prefix item. */
+ item = (gcsBUFITEM_STRING_PTR) _AllocateItem(OutputBuffer, allocSize);
+
+ /* Compute the initial message data pointer. */
+ messageData = (gctUINT8_PTR) (item + 1);
+
+ /* Align the data pointer as necessary. */
+#if gcdALIGNBYSIZE
+ alignment = gcmPTRALIGNMENT(messageData, gcdVARARG_ALIGNMENT);
+ messageData += alignment;
+#endif
+
+ /* Set item data. */
+ item->type = gcvBUFITEM_STRING;
+ item->indent = Indent;
+ item->message = Message;
+ item->messageData = messageData;
+ item->messageDataSize = ArgumentSize;
+
+ /* Copy argument value. */
+ if (ArgumentSize != 0)
+ {
+ gcmkMEMCPY(messageData, Data, ArgumentSize);
+ }
+
+#if gcdALIGNBYSIZE
+ /* Compute the actual node size. */
+ size = gcmSIZEOF(gcsBUFITEM_STRING) + ArgumentSize + alignment;
+
+ /* Free extra memory if any. */
+ freeSize = allocSize - size;
+ if (freeSize != 0)
+ {
+ _FreeExtraSpace(OutputBuffer, item, size, freeSize);
+ }
+#endif
+}
+
+static void
+_AppendCopy(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Indent,
+ IN gctCONST_STRING Message,
+ IN gctUINT ArgumentSize,
+ IN gctPOINTER Data
+ )
+{
+ gctUINT8_PTR messageData;
+ gcsBUFITEM_COPY_PTR item;
+ gctINT allocSize;
+ gctINT messageLength;
+ gctCONST_STRING message;
+
+#if gcdALIGNBYSIZE
+ gctUINT alignment;
+ gctINT size, freeSize;
+#endif
+
+ /* Get the length of the string. */
+ messageLength = strlen(Message) + 1;
+
+ /* Determine the maximum item size. */
+ allocSize
+ = gcmSIZEOF(gcsBUFITEM_COPY)
+ + messageLength
+ + ArgumentSize
+ + gcdVARARG_ALIGNMENT;
+
+ /* Allocate prefix item. */
+ item = (gcsBUFITEM_COPY_PTR) _AllocateItem(OutputBuffer, allocSize);
+
+ /* Determine the message placement. */
+ message = (gctCONST_STRING) (item + 1);
+
+ /* Compute the initial message data pointer. */
+ messageData = (gctUINT8_PTR) message + messageLength;
+
+ /* Align the data pointer as necessary. */
+#if gcdALIGNBYSIZE
+ if (ArgumentSize == 0)
+ {
+ alignment = 0;
+ }
+ else
+ {
+ alignment = gcmPTRALIGNMENT(messageData, gcdVARARG_ALIGNMENT);
+ messageData += alignment;
+ }
+#endif
+
+ /* Set item data. */
+ item->type = gcvBUFITEM_COPY;
+ item->indent = Indent;
+ item->messageData = messageData;
+ item->messageDataSize = ArgumentSize;
+
+ /* Copy the message. */
+ gcmkMEMCPY((gctPOINTER) message, Message, messageLength);
+
+ /* Copy argument value. */
+ if (ArgumentSize != 0)
+ {
+ gcmkMEMCPY(messageData, Data, ArgumentSize);
+ }
+
+#if gcdALIGNBYSIZE
+ /* Compute the actual node size. */
+ size
+ = gcmSIZEOF(gcsBUFITEM_COPY)
+ + messageLength
+ + ArgumentSize
+ + alignment;
+
+ /* Free extra memory if any. */
+ freeSize = allocSize - size;
+ if (freeSize != 0)
+ {
+ _FreeExtraSpace(OutputBuffer, item, size, freeSize);
+ }
+#endif
+}
+
+static void
+_AppendBuffer(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Indent,
+ IN gctPOINTER PrefixData,
+ IN gctPOINTER Data,
+ IN gctUINT Address,
+ IN gctUINT DataSize,
+ IN gceDUMP_BUFFER Type,
+ IN gctUINT32 DmaAddress
+ )
+{
+#if gcdHAVEPREFIX
+ gctUINT8_PTR prefixData;
+ gcsBUFITEM_BUFFER_PTR item;
+ gctINT allocSize;
+ gctPOINTER data;
+
+#if gcdALIGNBYSIZE
+ gctUINT alignment;
+ gctINT size, freeSize;
+#endif
+
+ gcmDBGASSERT(DataSize != 0, "%d", DataSize);
+ gcmDBGASSERT(Data != gcvNULL, "%p", Data);
+
+ /* Determine the maximum item size. */
+ allocSize
+ = gcmSIZEOF(gcsBUFITEM_BUFFER)
+ + gcdPREFIX_SIZE
+ + gcdPREFIX_ALIGNMENT
+ + DataSize;
+
+ /* Allocate prefix item. */
+ item = (gcsBUFITEM_BUFFER_PTR) _AllocateItem(OutputBuffer, allocSize);
+
+ /* Compute the initial prefix data pointer. */
+ prefixData = (gctUINT8_PTR) (item + 1);
+
+#if gcdALIGNBYSIZE
+ /* Align the data pointer as necessary. */
+ alignment = gcmPTRALIGNMENT(prefixData, gcdPREFIX_ALIGNMENT);
+ prefixData += alignment;
+#endif
+
+ /* Set item data. */
+ item->type = gcvBUFITEM_BUFFER;
+ item->indent = Indent;
+ item->bufferType = Type;
+ item->dataSize = DataSize;
+ item->address = Address;
+ item->prefixData = prefixData;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+ item->dmaAddress = DmaAddress;
+#endif
+
+ /* Copy prefix data. */
+ gcmkMEMCPY(prefixData, PrefixData, gcdPREFIX_SIZE);
+
+ /* Compute the data pointer. */
+ data = prefixData + gcdPREFIX_SIZE;
+
+ /* Copy argument value. */
+ gcmkMEMCPY(data, Data, DataSize);
+
+#if gcdALIGNBYSIZE
+ /* Compute the actual node size. */
+ size
+ = gcmSIZEOF(gcsBUFITEM_BUFFER)
+ + gcdPREFIX_SIZE
+ + alignment
+ + DataSize;
+
+ /* Free extra memory if any. */
+ freeSize = allocSize - size;
+ if (freeSize != 0)
+ {
+ _FreeExtraSpace(OutputBuffer, item, size, freeSize);
+ }
+#endif
+#else
+ gcsBUFITEM_BUFFER_PTR item;
+ gctINT size;
+
+ gcmDBGASSERT(DataSize != 0, "%d", DataSize);
+ gcmDBGASSERT(Data != gcvNULL, "%p", Data);
+
+ /* Determine the maximum item size. */
+ size = gcmSIZEOF(gcsBUFITEM_BUFFER) + DataSize;
+
+ /* Allocate prefix item. */
+ item = (gcsBUFITEM_BUFFER_PTR) _AllocateItem(OutputBuffer, size);
+
+ /* Set item data. */
+ item->type = gcvBUFITEM_BUFFER;
+ item->indent = Indent;
+ item->dataSize = DataSize;
+ item->address = Address;
+
+ /* Copy argument value. */
+ gcmkMEMCPY(item + 1, Data, DataSize);
+#endif
+}
+#endif
+
+static gcmINLINE void
+_InitBuffers(
+ void
+ )
+{
+ int i;
+
+ if (_outputBufferHead == gcvNULL)
+ {
+ for (i = 0; i < gcdTHREAD_BUFFERS; i += 1)
+ {
+ if (_outputBufferTail == gcvNULL)
+ {
+ _outputBufferHead = &_outputBuffer[i];
+ }
+ else
+ {
+ _outputBufferTail->next = &_outputBuffer[i];
+ }
+
+#if gcdTHREAD_BUFFERS > 1
+ _outputBuffer[i].threadID = ~0U;
+#endif
+
+ _outputBuffer[i].prev = _outputBufferTail;
+ _outputBuffer[i].next = gcvNULL;
+
+ _outputBufferTail = &_outputBuffer[i];
+ }
+ }
+}
+
+static gcmINLINE gcsBUFFERED_OUTPUT_PTR
+_GetOutputBuffer(
+ void
+ )
+{
+ gcsBUFFERED_OUTPUT_PTR outputBuffer;
+
+#if gcdTHREAD_BUFFERS > 1
+ /* Get the current thread ID. */
+ gctUINT32 ThreadID = gcmkGETTHREADID();
+
+ /* Locate the output buffer for the thread. */
+ outputBuffer = _outputBufferHead;
+
+ while (outputBuffer != gcvNULL)
+ {
+ if (outputBuffer->threadID == ThreadID)
+ {
+ break;
+ }
+
+ outputBuffer = outputBuffer->next;
+ }
+
+ /* No matching buffer found? */
+ if (outputBuffer == gcvNULL)
+ {
+ /* Get the tail for the buffer. */
+ outputBuffer = _outputBufferTail;
+
+ /* Move it to the head. */
+ _outputBufferTail = _outputBufferTail->prev;
+ _outputBufferTail->next = gcvNULL;
+
+ outputBuffer->prev = gcvNULL;
+ outputBuffer->next = _outputBufferHead;
+
+ _outputBufferHead->prev = outputBuffer;
+ _outputBufferHead = outputBuffer;
+
+ /* Reset the buffer. */
+ outputBuffer->threadID = ThreadID;
+#if gcdBUFFERED_OUTPUT
+ outputBuffer->start = 0;
+ outputBuffer->index = 0;
+ outputBuffer->count = 0;
+#endif
+#if gcdSHOW_LINE_NUMBER
+ outputBuffer->lineNumber = 0;
+#endif
+ }
+#else
+ outputBuffer = _outputBufferHead;
+#endif
+
+ return outputBuffer;
+}
+
+static gcmINLINE int _GetArgumentSize(
+ IN gctCONST_STRING Message
+ )
+{
+ int i, count;
+
+ gcmDBGASSERT(Message != gcvNULL, "%p", Message);
+
+ for (i = 0, count = 0; Message[i]; i += 1)
+ {
+ if (Message[i] == '%')
+ {
+ count += 1;
+ }
+ }
+
+ return count * gcmSIZEOF(gctUINT32);
+}
+
+#if gcdHAVEPREFIX
+static void
+_InitPrefixData(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctPOINTER Data
+ )
+{
+ gctUINT8_PTR data = (gctUINT8_PTR) Data;
+
+#if gcdSHOW_TIME
+ {
+ gctUINT64 time;
+ gckOS_GetProfileTick(&time);
+ gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT64));
+ * ((gctUINT64_PTR) data) = time;
+ data += gcmSIZEOF(gctUINT64);
+ }
+#endif
+
+#if gcdSHOW_LINE_NUMBER
+ {
+ gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT64));
+ * ((gctUINT64_PTR) data) = OutputBuffer->lineNumber;
+ data += gcmSIZEOF(gctUINT64);
+ }
+#endif
+
+#if gcdSHOW_PROCESS_ID
+ {
+ gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT32));
+ * ((gctUINT32_PTR) data) = gcmkGETPROCESSID();
+ data += gcmSIZEOF(gctUINT32);
+ }
+#endif
+
+#if gcdSHOW_THREAD_ID
+ {
+ gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT32));
+ * ((gctUINT32_PTR) data) = gcmkGETTHREADID();
+ }
+#endif
+}
+#endif
+
+static void
+_Print(
+ IN gctUINT ArgumentSize,
+ IN gctBOOL CopyMessage,
+ IN gctCONST_STRING Message,
+ IN gctARGUMENTS * Arguments
+ )
+{
+ gcsBUFFERED_OUTPUT_PTR outputBuffer;
+ gcmkDECLARE_LOCK(lockHandle);
+
+ gcmkLOCKSECTION(lockHandle);
+
+ /* Initialize output buffer list. */
+ _InitBuffers();
+
+ /* Locate the proper output buffer. */
+ outputBuffer = _GetOutputBuffer();
+
+ /* Update the line number. */
+#if gcdSHOW_LINE_NUMBER
+ outputBuffer->lineNumber += 1;
+#endif
+
+ /* Print prefix. */
+#if gcdHAVEPREFIX
+ {
+ gctUINT8_PTR alignedPrefixData;
+ gctUINT8 prefixData[gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT];
+
+ /* Compute aligned pointer. */
+ alignedPrefixData = prefixData;
+ gcmkALIGNPTR(gctUINT8_PTR, alignedPrefixData, gcdPREFIX_ALIGNMENT);
+
+ /* Initialize the prefix data. */
+ _InitPrefixData(outputBuffer, alignedPrefixData);
+
+ /* Print the prefix. */
+ gcdOUTPUTPREFIX(outputBuffer, alignedPrefixData);
+ }
+#endif
+
+ /* Form the indent string. */
+ if (strncmp(Message, "--", 2) == 0)
+ {
+ outputBuffer->indent -= 2;
+ }
+
+ /* Print the message. */
+ if (CopyMessage)
+ {
+ gcdOUTPUTCOPY(
+ outputBuffer, outputBuffer->indent,
+ Message, ArgumentSize, (gctPOINTER) Arguments
+ );
+ }
+ else
+ {
+ gcdOUTPUTSTRING(
+ outputBuffer, outputBuffer->indent,
+ Message, ArgumentSize, ((gctPOINTER) Arguments)
+ );
+ }
+
+ /* Check increasing indent. */
+ if (strncmp(Message, "++", 2) == 0)
+ {
+ outputBuffer->indent += 2;
+ }
+
+ gcmkUNLOCKSECTION(lockHandle);
+}
+
+
+/******************************************************************************\
+********************************* Debug Macros *********************************
+\******************************************************************************/
+
+#ifdef __QNXNTO__
+
+extern volatile unsigned g_nQnxInIsrs;
+
+#define gcmDEBUGPRINT(ArgumentSize, CopyMessage, Message) \
+{ \
+ if (atomic_add_value(&g_nQnxInIsrs, 1) == 0) \
+ { \
+ gctARGUMENTS __arguments__; \
+ gcmkARGUMENTS_START(__arguments__, Message); \
+ _Print(ArgumentSize, CopyMessage, Message, &__arguments__); \
+ gcmkARGUMENTS_END(__arguments__); \
+ } \
+ atomic_sub(&g_nQnxInIsrs, 1); \
+}
+
+#else
+
+#define gcmDEBUGPRINT(ArgumentSize, CopyMessage, Message) \
+{ \
+ gctARGUMENTS __arguments__; \
+ gcmkARGUMENTS_START(__arguments__, Message); \
+ _Print(ArgumentSize, CopyMessage, Message, &__arguments__); \
+ gcmkARGUMENTS_END(__arguments__); \
+}
+
+#endif
+
+/******************************************************************************\
+********************************** Debug Code **********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_Print
+**
+** Send a message to the debugger.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_PrintN
+**
+** Send a message to the debugger.
+**
+** INPUT:
+**
+** gctUINT ArgumentSize
+** The size of the optional arguments in bytes.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_PrintN(
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_CopyPrint
+**
+** Send a message to the debugger. If in buffered output mode, the entire
+** message will be copied into the buffer instead of using the pointer to
+** the string.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_CopyPrint(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ gcmDEBUGPRINT(_GetArgumentSize(Message), gcvTRUE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DumpBuffer
+**
+** Print the contents of the specified buffer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctPOINTER Buffer
+** Pointer to the buffer to print.
+**
+** gctUINT Size
+** Size of the buffer.
+**
+** gceDUMP_BUFFER Type
+** Buffer type.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DumpBuffer(
+ IN gckOS Os,
+ IN gctPOINTER Buffer,
+ IN gctUINT Size,
+ IN gceDUMP_BUFFER Type,
+ IN gctBOOL CopyMessage
+ )
+{
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address = 0;
+ gcsBUFFERED_OUTPUT_PTR outputBuffer = gcvNULL;
+ static gctBOOL userLocked;
+ gctCHAR *buffer = (gctCHAR*)Buffer;
+
+ gcmkDECLARE_LOCK(lockHandle);
+
+ /* Request lock when not coming from user,
+ or coming from user and not yet locked
+ and message is starting with @[. */
+ if (Type == gceDUMP_BUFFER_FROM_USER)
+ {
+ if ((Size > 2)
+ && (buffer[0] == '@')
+ && (buffer[1] == '['))
+ {
+ /* Beginning of a user dump. */
+ gcmkLOCKSECTION(lockHandle);
+ userLocked = gcvTRUE;
+ }
+ /* Else, let it pass through. */
+ }
+ else
+ {
+ gcmkLOCKSECTION(lockHandle);
+ userLocked = gcvFALSE;
+ }
+
+ if (Buffer != gcvNULL)
+ {
+ /* Initialize output buffer list. */
+ _InitBuffers();
+
+ /* Locate the proper output buffer. */
+ outputBuffer = _GetOutputBuffer();
+
+ /* Update the line number. */
+#if gcdSHOW_LINE_NUMBER
+ outputBuffer->lineNumber += 1;
+#endif
+
+ /* Get the physical address of the buffer. */
+ if (Type != gceDUMP_BUFFER_FROM_USER)
+ {
+ gcmkVERIFY_OK(gckOS_GetPhysicalAddress(Os, Buffer, &physical));
+ gcmkSAFECASTPHYSADDRT(address, physical);
+ }
+ else
+ {
+ address = 0;
+ }
+
+#if gcdHAVEPREFIX
+ {
+ gctUINT8_PTR alignedPrefixData;
+ gctUINT8 prefixData[gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT];
+
+ /* Compute aligned pointer. */
+ alignedPrefixData = prefixData;
+ gcmkALIGNPTR(gctUINT8_PTR, alignedPrefixData, gcdPREFIX_ALIGNMENT);
+
+ /* Initialize the prefix data. */
+ _InitPrefixData(outputBuffer, alignedPrefixData);
+
+ /* Print/schedule the buffer. */
+ gcdOUTPUTBUFFER(
+ outputBuffer, outputBuffer->indent,
+ alignedPrefixData, Buffer, address, Size, Type, 0
+ );
+ }
+#else
+ /* Print/schedule the buffer. */
+ if (Type == gceDUMP_BUFFER_FROM_USER)
+ {
+ gcdOUTPUTSTRING(
+ outputBuffer, outputBuffer->indent,
+ Buffer, 0, gcvNULL
+ );
+ }
+ else
+ {
+ gcdOUTPUTBUFFER(
+ outputBuffer, outputBuffer->indent,
+ gcvNULL, Buffer, address, Size, Type, 0
+ );
+ }
+#endif
+ }
+
+ /* Unlock when not coming from user,
+ or coming from user and not yet locked. */
+ if (userLocked)
+ {
+ if ((Size > 4)
+ && (buffer[0] == ']')
+ && (buffer[1] == ' ')
+ && (buffer[2] == '-')
+ && (buffer[3] == '-'))
+ {
+ /* End of a user dump. */
+ gcmkUNLOCKSECTION(lockHandle);
+ userLocked = gcvFALSE;
+ }
+ /* Else, let it pass through, don't unlock. */
+ }
+ else
+ {
+ gcmkUNLOCKSECTION(lockHandle);
+ }
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTrace
+**
+** Send a leveled message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level of message.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if (Level > _debugLevel)
+ {
+ return;
+ }
+
+ gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTraceN
+**
+** Send a leveled message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level of message.
+**
+** gctUINT ArgumentSize
+** The size of the optional arguments in bytes.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTraceN(
+ IN gctUINT32 Level,
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if (Level > _debugLevel)
+ {
+ return;
+ }
+
+ gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTraceZone
+**
+** Send a leveled and zoned message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level for message.
+**
+** gctUINT32 Zone
+** Debug zone for message.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if ((Level > _debugLevel) || !(Zone & _debugZones))
+ {
+ return;
+ }
+
+ gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTraceZoneN
+**
+** Send a leveled and zoned message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level for message.
+**
+** gctUINT32 Zone
+** Debug zone for message.
+**
+** gctUINT ArgumentSize
+** The size of the optional arguments in bytes.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTraceZoneN(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if ((Level > _debugLevel) || !(Zone & _debugZones))
+ {
+ return;
+ }
+
+ gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugBreak
+**
+** Break into the debugger.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DebugBreak(
+ void
+ )
+{
+ gckOS_DebugTrace(gcvLEVEL_ERROR, "%s(%d)", __FUNCTION__, __LINE__);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugFatal
+**
+** Send a message to the debugger and break into the debugger.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ gcmkPRINT_VERSION();
+ gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
+
+ /* Break into the debugger. */
+ gckOS_DebugBreak();
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugLevel
+**
+** Set the debug level.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** New debug level.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugLevel(
+ IN gctUINT32 Level
+ )
+{
+ _debugLevel = Level;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugZone
+**
+** Set the debug zone.
+**
+** INPUT:
+**
+** gctUINT32 Zone
+** New debug zone.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_SetDebugZone(
+ IN gctUINT32 Zone
+ )
+{
+ _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugLevelZone
+**
+** Set the debug level and zone.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** New debug level.
+**
+** gctUINT32 Zone
+** New debug zone.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ )
+{
+ _debugLevel = Level;
+ _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugZones
+**
+** Enable or disable debug zones.
+**
+** INPUT:
+**
+** gctUINT32 Zones
+** Debug zones to enable or disable.
+**
+** gctBOOL Enable
+** Set to gcvTRUE to enable the zones (or the Zones with the current
+** zones) or gcvFALSE to disable the specified Zones.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ )
+{
+ if (Enable)
+ {
+ /* Enable the zones. */
+ _debugZones |= Zones;
+ }
+ else
+ {
+ /* Disable the zones. */
+ _debugZones &= ~Zones;
+ }
+}
+
+/*******************************************************************************
+**
+** gckOS_Verify
+**
+** Called to verify the result of a function call.
+**
+** INPUT:
+**
+** gceSTATUS Status
+** Function call result.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_Verify(
+ IN gceSTATUS status
+ )
+{
+ _lastError = status;
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugFlush
+**
+** Force messages to be flushed out.
+**
+** INPUT:
+**
+** gctCONST_STRING CallerName
+** Name of the caller function.
+**
+** gctUINT LineNumber
+** Line number of the caller.
+**
+** gctUINT32 DmaAddress
+** The current DMA address or ~0U to ignore.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugFlush(
+ gctCONST_STRING CallerName,
+ gctUINT LineNumber,
+ gctUINT32 DmaAddress
+ )
+{
+#if gcdBUFFERED_OUTPUT
+ _DirectPrint("\nFlush requested by %s(%d).\n\n", CallerName, LineNumber);
+ _Flush(DmaAddress);
+#endif
+}
+gctCONST_STRING
+gckOS_DebugStatus2Name(
+ gceSTATUS status
+ )
+{
+ switch (status)
+ {
+ case gcvSTATUS_OK:
+ return "gcvSTATUS_OK";
+ case gcvSTATUS_TRUE:
+ return "gcvSTATUS_TRUE";
+ case gcvSTATUS_NO_MORE_DATA:
+ return "gcvSTATUS_NO_MORE_DATA";
+ case gcvSTATUS_CACHED:
+ return "gcvSTATUS_CACHED";
+ case gcvSTATUS_MIPMAP_TOO_LARGE:
+ return "gcvSTATUS_MIPMAP_TOO_LARGE";
+ case gcvSTATUS_NAME_NOT_FOUND:
+ return "gcvSTATUS_NAME_NOT_FOUND";
+ case gcvSTATUS_NOT_OUR_INTERRUPT:
+ return "gcvSTATUS_NOT_OUR_INTERRUPT";
+ case gcvSTATUS_MISMATCH:
+ return "gcvSTATUS_MISMATCH";
+ case gcvSTATUS_MIPMAP_TOO_SMALL:
+ return "gcvSTATUS_MIPMAP_TOO_SMALL";
+ case gcvSTATUS_LARGER:
+ return "gcvSTATUS_LARGER";
+ case gcvSTATUS_SMALLER:
+ return "gcvSTATUS_SMALLER";
+ case gcvSTATUS_CHIP_NOT_READY:
+ return "gcvSTATUS_CHIP_NOT_READY";
+ case gcvSTATUS_NEED_CONVERSION:
+ return "gcvSTATUS_NEED_CONVERSION";
+ case gcvSTATUS_SKIP:
+ return "gcvSTATUS_SKIP";
+ case gcvSTATUS_DATA_TOO_LARGE:
+ return "gcvSTATUS_DATA_TOO_LARGE";
+ case gcvSTATUS_INVALID_CONFIG:
+ return "gcvSTATUS_INVALID_CONFIG";
+ case gcvSTATUS_CHANGED:
+ return "gcvSTATUS_CHANGED";
+ case gcvSTATUS_NOT_SUPPORT_DITHER:
+ return "gcvSTATUS_NOT_SUPPORT_DITHER";
+
+ case gcvSTATUS_INVALID_ARGUMENT:
+ return "gcvSTATUS_INVALID_ARGUMENT";
+ case gcvSTATUS_INVALID_OBJECT:
+ return "gcvSTATUS_INVALID_OBJECT";
+ case gcvSTATUS_OUT_OF_MEMORY:
+ return "gcvSTATUS_OUT_OF_MEMORY";
+ case gcvSTATUS_MEMORY_LOCKED:
+ return "gcvSTATUS_MEMORY_LOCKED";
+ case gcvSTATUS_MEMORY_UNLOCKED:
+ return "gcvSTATUS_MEMORY_UNLOCKED";
+ case gcvSTATUS_HEAP_CORRUPTED:
+ return "gcvSTATUS_HEAP_CORRUPTED";
+ case gcvSTATUS_GENERIC_IO:
+ return "gcvSTATUS_GENERIC_IO";
+ case gcvSTATUS_INVALID_ADDRESS:
+ return "gcvSTATUS_INVALID_ADDRESS";
+ case gcvSTATUS_CONTEXT_LOSSED:
+ return "gcvSTATUS_CONTEXT_LOSSED";
+ case gcvSTATUS_TOO_COMPLEX:
+ return "gcvSTATUS_TOO_COMPLEX";
+ case gcvSTATUS_BUFFER_TOO_SMALL:
+ return "gcvSTATUS_BUFFER_TOO_SMALL";
+ case gcvSTATUS_INTERFACE_ERROR:
+ return "gcvSTATUS_INTERFACE_ERROR";
+ case gcvSTATUS_NOT_SUPPORTED:
+ return "gcvSTATUS_NOT_SUPPORTED";
+ case gcvSTATUS_MORE_DATA:
+ return "gcvSTATUS_MORE_DATA";
+ case gcvSTATUS_TIMEOUT:
+ return "gcvSTATUS_TIMEOUT";
+ case gcvSTATUS_OUT_OF_RESOURCES:
+ return "gcvSTATUS_OUT_OF_RESOURCES";
+ case gcvSTATUS_INVALID_DATA:
+ return "gcvSTATUS_INVALID_DATA";
+ case gcvSTATUS_INVALID_MIPMAP:
+ return "gcvSTATUS_INVALID_MIPMAP";
+ case gcvSTATUS_NOT_FOUND:
+ return "gcvSTATUS_NOT_FOUND";
+ case gcvSTATUS_NOT_ALIGNED:
+ return "gcvSTATUS_NOT_ALIGNED";
+ case gcvSTATUS_INVALID_REQUEST:
+ return "gcvSTATUS_INVALID_REQUEST";
+ case gcvSTATUS_GPU_NOT_RESPONDING:
+ return "gcvSTATUS_GPU_NOT_RESPONDING";
+ case gcvSTATUS_TIMER_OVERFLOW:
+ return "gcvSTATUS_TIMER_OVERFLOW";
+ case gcvSTATUS_VERSION_MISMATCH:
+ return "gcvSTATUS_VERSION_MISMATCH";
+ case gcvSTATUS_LOCKED:
+ return "gcvSTATUS_LOCKED";
+ 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_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));
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
new file mode 100644
index 000000000000..b69e156cd847
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
@@ -0,0 +1,3526 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+#include "gc_hal_kernel_buffer.h"
+
+#ifdef __QNXNTO__
+#include <atomic.h>
+#include "gc_hal_kernel_qnx.h"
+#endif
+
+#define _GC_OBJ_ZONE gcvZONE_EVENT
+
+#define gcdEVENT_ALLOCATION_COUNT (4096 / gcmSIZEOF(gcsHAL_INTERFACE))
+#define gcdEVENT_MIN_THRESHOLD 4
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+static gceSTATUS
+gckEVENT_AllocateQueue(
+ IN gckEVENT Event,
+ OUT gcsEVENT_QUEUE_PTR * Queue
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
+
+ /* Do we have free queues? */
+ if (Event->freeList == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Move one free queue from the free list. */
+ * Queue = Event->freeList;
+ Event->freeList = Event->freeList->next;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Queue=0x%x", gcmOPT_POINTER(Queue));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+gckEVENT_FreeQueue(
+ IN gckEVENT Event,
+ OUT gcsEVENT_QUEUE_PTR Queue
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
+
+ /* Move one free queue from the free list. */
+ Queue->next = Event->freeList;
+ Event->freeList = Queue;
+
+ /* Success. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+gckEVENT_FreeRecord(
+ IN gckEVENT Event,
+ IN gcsEVENT_PTR Record
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->freeEventMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Push the record on the free list. */
+ Record->next = Event->freeEventList;
+ Event->freeEventList = Record;
+ Event->freeEventCount += 1;
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+gckEVENT_IsEmpty(
+ IN gckEVENT Event,
+ OUT gctBOOL_PTR IsEmpty
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T i;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(IsEmpty != gcvNULL);
+
+ /* Assume the event queue is empty. */
+ *IsEmpty = gcvTRUE;
+
+ /* Walk the event queue. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ /* Check whether this event is in use. */
+ if (Event->queues[i].head != gcvNULL)
+ {
+ /* The event is in use, hence the queue is not empty. */
+ *IsEmpty = gcvFALSE;
+ break;
+ }
+ }
+
+ /* Try acquiring the mutex. */
+ status = gckOS_AcquireMutex(Event->os, Event->eventQueueMutex, 0);
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ /* Timeout - queue is no longer empty. */
+ *IsEmpty = gcvFALSE;
+ }
+ else
+ {
+ /* Bail out on error. */
+ gcmkONERROR(status);
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*IsEmpty=%d", gcmOPT_VALUE(IsEmpty));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_TryToIdleGPU(
+ IN gckEVENT Event
+)
+{
+ gceSTATUS status;
+ gctBOOL empty = gcvFALSE, idle = gcvFALSE;
+ gctBOOL powerLocked = gcvFALSE;
+ gckHARDWARE hardware;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Grab gckHARDWARE object. */
+ hardware = Event->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Check whether the event queue is empty. */
+ gcmkONERROR(gckEVENT_IsEmpty(Event, &empty));
+
+ if (empty)
+ {
+ status = gckOS_AcquireMutex(hardware->os, hardware->powerMutex, 0);
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ powerLocked = gcvTRUE;
+
+ /* Query whether the hardware is idle. */
+ gcmkONERROR(gckHARDWARE_QueryIdle(Event->kernel->hardware, &idle));
+
+ gcmkONERROR(gckOS_ReleaseMutex(hardware->os, hardware->powerMutex));
+ powerLocked = gcvFALSE;
+
+ if (idle)
+ {
+ /* Inform the system of idle GPU. */
+ gcmkONERROR(gckOS_Broadcast(Event->os,
+ Event->kernel->hardware,
+ gcvBROADCAST_GPU_IDLE));
+ }
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (powerLocked)
+ {
+ gcmkONERROR(gckOS_ReleaseMutex(hardware->os, hardware->powerMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+__RemoveRecordFromProcessDB(
+ IN gckEVENT Event,
+ IN gcsEVENT_PTR Record
+ )
+{
+ gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
+ gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+ while (Record != gcvNULL)
+ {
+ if (Record->info.command == gcvHAL_SIGNAL)
+ {
+ /* TODO: Find a better place to bind signal to hardware.*/
+ gcmkVERIFY_OK(gckOS_SignalSetHardware(Event->os,
+ gcmUINT64_TO_PTR(Record->info.u.Signal.signal),
+ Event->kernel->hardware));
+ }
+
+ if (Record->fromKernel)
+ {
+ /* No need to check db if event is from kernel. */
+ Record = Record->next;
+ continue;
+ }
+
+ switch (Record->info.command)
+ {
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Event->kernel,
+ Record->processID,
+ gcvDB_NON_PAGED,
+ gcmUINT64_TO_PTR(Record->info.u.FreeNonPagedMemory.logical)));
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Event->kernel,
+ Record->processID,
+ gcvDB_CONTIGUOUS,
+ gcmUINT64_TO_PTR(Record->info.u.FreeContiguousMemory.logical)));
+ break;
+
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Event->kernel,
+ Record->processID,
+ gcvDB_VIDEO_MEMORY_LOCKED,
+ gcmUINT64_TO_PTR(Record->info.u.UnlockVideoMemory.node)));
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Event->kernel,
+ Record->processID,
+ gcvDB_MAP_USER_MEMORY,
+ gcmINT2PTR(Record->info.u.UnmapUserMemory.info)));
+ break;
+
+ case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Event->kernel,
+ Record->processID,
+ gcvDB_COMMAND_BUFFER,
+ gcmUINT64_TO_PTR(Record->info.u.FreeVirtualCommandBuffer.logical)));
+ break;
+
+ default:
+ break;
+ }
+
+ Record = Record->next;
+ }
+ gcmkFOOTER_NO();
+ 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
+}
+
+/******************************************************************************\
+******************************* gckEVENT API Code *******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckEVENT_Construct
+**
+** Construct a new gckEVENT object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** gckEVENT * Event
+** Pointer to a variable that receives the gckEVENT object pointer.
+*/
+gceSTATUS
+gckEVENT_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckEVENT * Event
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+ gckEVENT eventObj = gcvNULL;
+ int i;
+ gcsEVENT_PTR record;
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Event != gcvNULL);
+
+ /* Extract the pointer to the gckOS object. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Allocate the gckEVENT object. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckEVENT), &pointer));
+
+ eventObj = pointer;
+
+ /* Reset the object. */
+ gcmkVERIFY_OK(gckOS_ZeroMemory(eventObj, gcmSIZEOF(struct _gckEVENT)));
+
+ /* Initialize the gckEVENT object. */
+ eventObj->object.type = gcvOBJ_EVENT;
+ eventObj->kernel = Kernel;
+ eventObj->os = os;
+
+ /* Create the mutexes. */
+ gcmkONERROR(gckOS_CreateMutex(os, &eventObj->eventQueueMutex));
+ gcmkONERROR(gckOS_CreateMutex(os, &eventObj->freeEventMutex));
+ gcmkONERROR(gckOS_CreateMutex(os, &eventObj->eventListMutex));
+
+ /* Create a bunch of event reccords. */
+ for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; i += 1)
+ {
+ /* Allocate an event record. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsEVENT), &pointer));
+
+ record = pointer;
+
+ /* Push it on the free list. */
+ record->next = eventObj->freeEventList;
+ eventObj->freeEventList = record;
+ eventObj->freeEventCount += 1;
+ }
+
+ /* Initialize the free list of event queues. */
+ for (i = 0; i < gcdREPO_LIST_COUNT; i += 1)
+ {
+ eventObj->repoList[i].next = eventObj->freeList;
+ eventObj->freeList = &eventObj->repoList[i];
+ }
+
+ /* Construct the atom. */
+ gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->freeAtom));
+ gcmkONERROR(gckOS_AtomSet(os,
+ eventObj->freeAtom,
+ gcmCOUNTOF(eventObj->queues)));
+
+#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,
+ _SubmitTimerFunction,
+ (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;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Event=0x%x", *Event);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (eventObj != gcvNULL)
+ {
+ if (eventObj->eventQueueMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->eventQueueMutex));
+ }
+
+ if (eventObj->freeEventMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->freeEventMutex));
+ }
+
+ if (eventObj->eventListMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->eventListMutex));
+ }
+
+ while (eventObj->freeEventList != gcvNULL)
+ {
+ record = eventObj->freeEventList;
+ eventObj->freeEventList = record->next;
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, record));
+ }
+
+ if (eventObj->freeAtom != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->freeAtom));
+ }
+
+#if gcdSMP
+ if (eventObj->pending != gcvNULL)
+ {
+ 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));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Destroy
+**
+** Destroy an gckEVENT object.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Destroy(
+ IN gckEVENT Event
+ )
+{
+ gcsEVENT_PTR record;
+ gcsEVENT_QUEUE_PTR queue;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ if (Event->submitTimer != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_StopTimer(Event->os, Event->submitTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Event->os, Event->submitTimer));
+ }
+
+ /* Delete the queue mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->eventQueueMutex));
+
+ /* Free all free events. */
+ while (Event->freeEventList != gcvNULL)
+ {
+ record = Event->freeEventList;
+ Event->freeEventList = record->next;
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, record));
+ }
+
+ /* Delete the free mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->freeEventMutex));
+
+ /* Free all pending queues. */
+ while (Event->queueHead != gcvNULL)
+ {
+ /* Get the current queue. */
+ queue = Event->queueHead;
+
+ /* Free all pending events. */
+ while (queue->head != gcvNULL)
+ {
+ record = queue->head;
+ queue->head = record->next;
+
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_WARNING, gcvZONE_EVENT,
+ gcmSIZEOF(record) + gcmSIZEOF(queue->source),
+ "Event record 0x%x is still pending for %d.",
+ record, queue->source
+ );
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, record));
+ }
+
+ /* Remove the top queue from the list. */
+ if (Event->queueHead == Event->queueTail)
+ {
+ Event->queueHead =
+ Event->queueTail = gcvNULL;
+ }
+ else
+ {
+ Event->queueHead = Event->queueHead->next;
+ }
+
+ /* Free the queue. */
+ gcmkVERIFY_OK(gckEVENT_FreeQueue(Event, queue));
+ }
+
+ /* Delete the list mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->eventListMutex));
+
+ /* Delete the atom. */
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->freeAtom));
+
+#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. */
+ Event->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckEVENT object. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, Event));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_GetEvent
+**
+** Reserve the next available hardware event.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctBOOL Wait
+** Set to gcvTRUE to force the function to wait if no events are
+** immediately available.
+**
+** gceKERNEL_WHERE Source
+** Source of the event.
+**
+** OUTPUT:
+**
+** gctUINT8 * EventID
+** Reserved event ID.
+*/
+#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,
+ IN gctBOOL Wait,
+ OUT gctUINT8 * EventID,
+ IN gceKERNEL_WHERE Source
+ )
+#endif
+{
+ gctINT i, id;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctINT32 free;
+#if gcdMULTI_GPU
+ gctINT j;
+#endif
+
+ gcmkHEADER_ARG("Event=0x%x Source=%d", Event, Source);
+
+ while (gcvTRUE)
+ {
+ /* Grab the queue mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->eventQueueMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Walk through all events. */
+ id = Event->lastID;
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ gctINT nextID = gckMATH_ModuloInt((id + 1),
+ gcmCOUNTOF(Event->queues));
+
+ if (Event->queues[id].head == gcvNULL)
+ {
+ *EventID = (gctUINT8) id;
+
+ Event->lastID = (gctUINT8) nextID;
+
+ /* Save time stamp of event. */
+ Event->queues[id].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));
+#if gcdDYNAMIC_SPEED
+ if (free <= gcdDYNAMIC_EVENT_THRESHOLD)
+ {
+ gcmkONERROR(gckOS_BroadcastHurry(
+ Event->os,
+ Event->kernel->hardware,
+ gcdDYNAMIC_EVENT_THRESHOLD - free));
+ }
+#endif
+
+ /* Release the queue mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os,
+ Event->eventQueueMutex));
+
+ /* Success. */
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_EVENT,
+ gcmSIZEOF(id),
+ "Using id=%d",
+ id
+ );
+
+ gcmkFOOTER_ARG("*EventID=%u", *EventID);
+ return gcvSTATUS_OK;
+ }
+
+ id = nextID;
+ }
+
+#if gcdDYNAMIC_SPEED
+ /* No free events, speed up the GPU right now! */
+ gcmkONERROR(gckOS_BroadcastHurry(Event->os,
+ Event->kernel->hardware,
+ gcdDYNAMIC_EVENT_THRESHOLD));
+#endif
+
+ /* Release the queue mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ acquired = gcvFALSE;
+
+ /* Fail if wait is not requested. */
+ if (!Wait)
+ {
+ /* Out of resources. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Delay a while. */
+ gcmkONERROR(gckOS_Delay(Event->os, 1));
+ }
+
+OnError:
+ if (acquired)
+ {
+ /* Release the queue mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_AllocateRecord
+**
+** Allocate a record for the new event.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctBOOL AllocateAllowed
+** State for allocation if out of free events.
+**
+** OUTPUT:
+**
+** gcsEVENT_PTR * Record
+** Allocated event record.
+*/
+gceSTATUS
+gckEVENT_AllocateRecord(
+ IN gckEVENT Event,
+ IN gctBOOL AllocateAllowed,
+ OUT gcsEVENT_PTR * Record
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctINT i;
+ gcsEVENT_PTR record;
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG("Event=0x%x AllocateAllowed=%d", Event, AllocateAllowed);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeEventMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Test if we are below the allocation threshold. */
+ if ( (AllocateAllowed && (Event->freeEventCount < gcdEVENT_MIN_THRESHOLD)) ||
+ (Event->freeEventCount == 0) )
+ {
+ /* Allocate a bunch of records. */
+ for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; i += 1)
+ {
+ /* Allocate an event record. */
+ gcmkONERROR(gckOS_Allocate(Event->os,
+ gcmSIZEOF(gcsEVENT),
+ &pointer));
+
+ record = pointer;
+
+ /* Push it on the free list. */
+ record->next = Event->freeEventList;
+ Event->freeEventList = record;
+ Event->freeEventCount += 1;
+ }
+ }
+
+ *Record = Event->freeEventList;
+ Event->freeEventList = Event->freeEventList->next;
+ Event->freeEventCount -= 1;
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Record=0x%x", gcmOPT_POINTER(Record));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_AddList
+**
+** Add a new event to the list of events.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gcsHAL_INTERFACE_PTR Interface
+** Pointer to the interface for the event to be added.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+** gctBOOL AllocateAllowed
+** State for allocation if out of free events.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_AddList(
+ IN gckEVENT Event,
+ IN gcsHAL_INTERFACE_PTR Interface,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gctBOOL AllocateAllowed,
+ IN gctBOOL FromKernel
+ )
+{
+ gceSTATUS status;
+ 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",
+ Event, Interface);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, _GC_OBJ_ZONE,
+ "FromWhere=%d AllocateAllowed=%d",
+ FromWhere, AllocateAllowed);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+ /* Verify the event command. */
+ gcmkASSERT
+ ( (Interface->command == gcvHAL_FREE_NON_PAGED_MEMORY)
+ || (Interface->command == gcvHAL_FREE_CONTIGUOUS_MEMORY)
+ || (Interface->command == gcvHAL_WRITE_DATA)
+ || (Interface->command == gcvHAL_UNLOCK_VIDEO_MEMORY)
+ || (Interface->command == gcvHAL_SIGNAL)
+ || (Interface->command == gcvHAL_UNMAP_USER_MEMORY)
+ || (Interface->command == gcvHAL_TIMESTAMP)
+ || (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. */
+ if ((FromWhere != gcvKERNEL_COMMAND) && (FromWhere != gcvKERNEL_PIXEL))
+ {
+ /* Invalid argument. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Allocate a free record. */
+ gcmkONERROR(gckEVENT_AllocateRecord(Event, AllocateAllowed, &record));
+
+ /* Termninate the record. */
+ record->next = gcvNULL;
+
+ /* Record the committer. */
+ record->fromKernel = FromKernel;
+
+ /* Copy the event interface into the record. */
+ gckOS_MemCopy(&record->info, Interface, gcmSIZEOF(record->info));
+
+ /* 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
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->eventListMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Do we need to allocate a new queue? */
+ if ((Event->queueTail == gcvNULL) || (Event->queueTail->source < FromWhere))
+ {
+ /* Allocate a new queue. */
+ gcmkONERROR(gckEVENT_AllocateQueue(Event, &queue));
+
+ /* Initialize the queue. */
+ queue->source = FromWhere;
+ queue->head = gcvNULL;
+ queue->next = gcvNULL;
+
+ /* Attach it to the list of allocated queues. */
+ if (Event->queueTail == gcvNULL)
+ {
+ Event->queueHead =
+ Event->queueTail = queue;
+ }
+ else
+ {
+ Event->queueTail->next = queue;
+ Event->queueTail = queue;
+ }
+ }
+ else
+ {
+ queue = Event->queueTail;
+ }
+
+ /* Attach the record to the queue. */
+ if (queue->head == gcvNULL)
+ {
+ queue->head = record;
+ queue->tail = record;
+ }
+ else
+ {
+ queue->tail->next = record;
+ queue->tail = record;
+ }
+
+ /* Unmap user space logical address.
+ * Linux kernel does not support unmap the memory of other process any more since 3.5.
+ * Let's unmap memory of self process before submit the event to gpu.
+ * */
+ switch(Interface->command)
+ {
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ gcmkONERROR(gckOS_UnmapUserLogical(
+ Event->os,
+ gcmNAME_TO_PTR(Interface->u.FreeNonPagedMemory.physical),
+ (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
+ gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+ break;
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ gcmkONERROR(gckOS_UnmapUserLogical(
+ Event->os,
+ gcmNAME_TO_PTR(Interface->u.FreeContiguousMemory.physical),
+ (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));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+ }
+
+ if (record != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Unlock
+**
+** Schedule an event to unlock virtual memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union that specifies the virtual memory
+** to unlock.
+**
+** gceSURF_TYPE Type
+** Type of surface to unlock.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Unlock(
+ IN gckEVENT Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gctPOINTER Node,
+ IN gceSURF_TYPE Type
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x FromWhere=%d Node=0x%x Type=%d",
+ Event, FromWhere, Node, Type);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+ /* Mark the event as an unlock. */
+ iface.command = gcvHAL_UNLOCK_VIDEO_MEMORY;
+ iface.u.UnlockVideoMemory.node = gcmPTR_TO_UINT64(Node);
+ iface.u.UnlockVideoMemory.type = Type;
+ iface.u.UnlockVideoMemory.asynchroneous = 0;
+
+ /* 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
+**
+** Schedule an event to free non-paged memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctSIZE_T Bytes
+** Number of bytes of non-paged memory to free.
+**
+** gctPHYS_ADDR Physical
+** Physical address of non-paged memory to free.
+**
+** gctPOINTER Logical
+** Logical address of non-paged memory to free.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+*/
+gceSTATUS
+gckEVENT_FreeNonPagedMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+ gckKERNEL kernel = Event->kernel;
+
+ gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
+ "FromWhere=%d",
+ Event, Bytes, Physical, Logical, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ /* Create an event. */
+ iface.command = gcvHAL_FREE_NON_PAGED_MEMORY;
+ iface.u.FreeNonPagedMemory.bytes = Bytes;
+ iface.u.FreeNonPagedMemory.physical = gcmPTR_TO_NAME(Physical);
+ iface.u.FreeNonPagedMemory.logical = gcmPTR_TO_UINT64(Logical);
+
+ /* 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;
+}
+
+gceSTATUS
+gckEVENT_DestroyVirtualCommandBuffer(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+ gckKERNEL kernel = Event->kernel;
+
+ gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
+ "FromWhere=%d",
+ Event, Bytes, Physical, Logical, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ /* Create an event. */
+ iface.command = gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER;
+ iface.u.FreeVirtualCommandBuffer.bytes = Bytes;
+ iface.u.FreeVirtualCommandBuffer.physical = gcmPTR_TO_NAME(Physical);
+ iface.u.FreeVirtualCommandBuffer.logical = gcmPTR_TO_UINT64(Logical);
+
+ /* 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_FreeContigiuousMemory
+**
+** Schedule an event to free contiguous memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctSIZE_T Bytes
+** Number of bytes of contiguous memory to free.
+**
+** gctPHYS_ADDR Physical
+** Physical address of contiguous memory to free.
+**
+** gctPOINTER Logical
+** Logical address of contiguous memory to free.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+*/
+gceSTATUS
+gckEVENT_FreeContiguousMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+ gckKERNEL kernel = Event->kernel;
+
+ gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
+ "FromWhere=%d",
+ Event, Bytes, Physical, Logical, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ /* Create an event. */
+ iface.command = gcvHAL_FREE_CONTIGUOUS_MEMORY;
+ iface.u.FreeContiguousMemory.bytes = Bytes;
+ iface.u.FreeContiguousMemory.physical = gcmPTR_TO_NAME(Physical);
+ iface.u.FreeContiguousMemory.logical = gcmPTR_TO_UINT64(Logical);
+
+ /* 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_Signal
+**
+** Schedule an event to trigger a signal.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctSIGNAL Signal
+** Pointer to the signal to trigger.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Signal(
+ IN gckEVENT Event,
+ IN gctSIGNAL Signal,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x Signal=0x%x FromWhere=%d",
+ Event, Signal, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ /* Mark the event as a signal. */
+ iface.command = gcvHAL_SIGNAL;
+ iface.u.Signal.signal = gcmPTR_TO_UINT64(Signal);
+ iface.u.Signal.auxSignal = 0;
+ iface.u.Signal.process = 0;
+
+#ifdef __QNXNTO__
+ iface.u.Signal.coid = 0;
+ iface.u.Signal.rcvid = 0;
+
+ gcmkONERROR(gckOS_SignalPending(Event->os, Signal));
+#endif
+
+ /* 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_CommitDone
+**
+** Schedule an event to wake up work thread when commit is done by GPU.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_CommitDone(
+ IN gckEVENT Event,
+ 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_COMMIT_DONE;
+
+ /* 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;
+}
+
+#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
+**
+** Submit the current event queue to the GPU.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctBOOL Wait
+** Submit requires one vacant event; if Wait is set to not zero,
+** and there are no vacant events at this time, the function will
+** wait until an event becomes vacant so that submission of the
+** queue is successful.
+**
+** gctBOOL FromPower
+** Determines whether the call originates from inside the power
+** management or not.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+#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;
+ gcsEVENT_QUEUE_PTR queue;
+ gctBOOL acquired = gcvFALSE;
+ gckCOMMAND command = gcvNULL;
+ gctBOOL commitEntered = gcvFALSE;
+#if !gcdNULL_DRIVER
+ 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;
+ gctUINT64 commitStamp;
+
+ 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)
+ {
+ /* Acquire the command queue. */
+ gcmkONERROR(gckCOMMAND_EnterCommit(command, FromPower));
+ commitEntered = gcvTRUE;
+
+ /* Get current commit stamp. */
+ commitStamp = Event->kernel->command->commitStamp;
+
+ if (commitStamp)
+ {
+ commitStamp -= 1;
+ }
+
+ /* Process all queues. */
+ while (Event->queueHead != gcvNULL)
+ {
+ /* Acquire the list mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->eventListMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Get the current queue. */
+ queue = Event->queueHead;
+
+ /* Allocate an event ID. */
+#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;
+
+ /* Update current commit stamp. */
+ Event->queues[id].commitStamp = commitStamp;
+
+ /* Remove the top queue from the list. */
+ if (Event->queueHead == Event->queueTail)
+ {
+ Event->queueHead = gcvNULL;
+ Event->queueTail = gcvNULL;
+ }
+ else
+ {
+ Event->queueHead = Event->queueHead->next;
+ }
+
+ /* Free the queue. */
+ gcmkONERROR(gckEVENT_FreeQueue(Event, queue));
+
+ /* Release the list mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+ acquired = gcvFALSE;
+
+ /* Determine cache needed to flush. */
+ gcmkVERIFY_OK(_QueryFlush(Event, Event->queues[id].head, &flush));
+
+#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(
+ 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
+ ));
+
+ /* Advance to next command. */
+ buffer = (gctUINT8_PTR)buffer + flushBytes;
+
+ /* Set the hardware event in the command queue. */
+ 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, executeBytes));
+#endif
+#endif
+#if gcdINTERRUPT_STATISTIC
+ gcmkVERIFY_OK(gckOS_AtomIncrement(
+ Event->os,
+ Event->interruptCount,
+ &oldValue
+ ));
+#endif
+
+ }
+
+ /* Release the command queue. */
+ gcmkONERROR(gckCOMMAND_ExitCommit(command, FromPower));
+
+#if !gcdNULL_DRIVER
+ gcmkVERIFY_OK(_TryToIdleGPU(Event));
+#endif
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ 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. */
+ Event->queues[id].head = gcvNULL;
+ }
+
+ if (status == gcvSTATUS_GPU_NOT_RESPONDING)
+ {
+ /* Broadcast GPU stuck. */
+ status = gckOS_Broadcast(Event->os,
+ Event->kernel->hardware,
+ gcvBROADCAST_GPU_STUCK);
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Commit
+**
+** Commit an event queue from the user.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gcsQUEUE_PTR Queue
+** User event queue.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+#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;
+ gctUINT32 processID;
+ gctBOOL needCopy = gcvFALSE;
+
+ gcmkHEADER_ARG("Event=0x%x Queue=0x%x", Event, Queue);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Get the current process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+
+ /* Query if we need to copy the client data. */
+ gcmkONERROR(gckOS_QueryNeedCopy(Event->os, processID, &needCopy));
+
+ /* Loop while there are records in the queue. */
+ while (Queue != gcvNULL)
+ {
+ gcsQUEUE queue;
+
+ if (needCopy)
+ {
+ /* Point to stack record. */
+ record = &queue;
+
+ /* Copy the data from the client. */
+ gcmkONERROR(gckOS_CopyFromUserData(Event->os,
+ record,
+ Queue,
+ gcmSIZEOF(gcsQUEUE)));
+ }
+ else
+ {
+ gctPOINTER pointer = gcvNULL;
+
+ /* Map record into kernel memory. */
+ gcmkONERROR(gckOS_MapUserPointer(Event->os,
+ Queue,
+ gcmSIZEOF(gcsQUEUE),
+ &pointer));
+
+ record = pointer;
+ }
+
+ /* Append event record to event queue. */
+ gcmkONERROR(
+ gckEVENT_AddList(Event, &record->iface, gcvKERNEL_PIXEL, gcvTRUE, gcvFALSE));
+
+ /* Next record in the queue. */
+ next = gcmUINT64_TO_PTR(record->next);
+
+ if (!needCopy)
+ {
+ /* Unmap record from kernel memory. */
+ gcmkONERROR(
+ gckOS_UnmapUserPointer(Event->os,
+ Queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) record));
+ record = gcvNULL;
+ }
+
+ Queue = next;
+ }
+
+ /* Submit the event list. */
+#if gcdMULTI_GPU
+ gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE, ChipEnable));
+#else
+ gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE));
+#endif
+
+ /* Success */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if ((record != gcvNULL) && !needCopy)
+ {
+ /* Roll back. */
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(Event->os,
+ Queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) record));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Compose
+**
+** Schedule a composition event and start a composition.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gcsHAL_COMPOSE_PTR Info
+** Pointer to the composition structure.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Compose(
+ IN gckEVENT Event,
+ IN gcsHAL_COMPOSE_PTR Info
+ )
+{
+ gceSTATUS status;
+ gcsEVENT_PTR headRecord;
+ gcsEVENT_PTR tailRecord;
+ gcsEVENT_PTR tempRecord;
+ gctUINT8 id = 0xFF;
+ gctUINT32 processID;
+
+ gcmkHEADER_ARG("Event=0x%x Info=0x%x", Event, Info);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+
+ /* Allocate an event ID. */
+#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));
+
+ /* Allocate a record. */
+ gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
+ headRecord = tailRecord = tempRecord;
+
+ /* Initialize the record. */
+ tempRecord->info.command = gcvHAL_SIGNAL;
+ tempRecord->info.u.Signal.process = Info->process;
+#ifdef __QNXNTO__
+ tempRecord->info.u.Signal.coid = Info->coid;
+ tempRecord->info.u.Signal.rcvid = Info->rcvid;
+#endif
+ tempRecord->info.u.Signal.signal = Info->signal;
+ tempRecord->info.u.Signal.auxSignal = 0;
+ tempRecord->next = gcvNULL;
+ tempRecord->processID = processID;
+
+ /* Allocate another record for user signal #1. */
+ if (gcmUINT64_TO_PTR(Info->userSignal1) != gcvNULL)
+ {
+ /* Allocate a record. */
+ gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
+ tailRecord->next = tempRecord;
+ tailRecord = tempRecord;
+
+ /* Initialize the record. */
+ tempRecord->info.command = gcvHAL_SIGNAL;
+ tempRecord->info.u.Signal.process = Info->userProcess;
+#ifdef __QNXNTO__
+ tempRecord->info.u.Signal.coid = Info->coid;
+ tempRecord->info.u.Signal.rcvid = Info->rcvid;
+#endif
+ tempRecord->info.u.Signal.signal = Info->userSignal1;
+ tempRecord->info.u.Signal.auxSignal = 0;
+ tempRecord->next = gcvNULL;
+ tempRecord->processID = processID;
+ }
+
+ /* Allocate another record for user signal #2. */
+ if (gcmUINT64_TO_PTR(Info->userSignal2) != gcvNULL)
+ {
+ /* Allocate a record. */
+ gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
+ tailRecord->next = tempRecord;
+
+ /* Initialize the record. */
+ tempRecord->info.command = gcvHAL_SIGNAL;
+ tempRecord->info.u.Signal.process = Info->userProcess;
+#ifdef __QNXNTO__
+ tempRecord->info.u.Signal.coid = Info->coid;
+ tempRecord->info.u.Signal.rcvid = Info->rcvid;
+#endif
+ tempRecord->info.u.Signal.signal = Info->userSignal2;
+ tempRecord->info.u.Signal.auxSignal = 0;
+ tempRecord->next = gcvNULL;
+ tempRecord->processID = processID;
+ }
+
+ /* Set the event list. */
+ Event->queues[id].head = headRecord;
+
+ /* Start composition. */
+ gcmkONERROR(gckHARDWARE_Compose(
+ Event->kernel->hardware, processID,
+ gcmUINT64_TO_PTR(Info->physical), gcmUINT64_TO_PTR(Info->logical), Info->offset, Info->size, id
+ ));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Interrupt
+**
+** Called by the interrupt service routine to store the triggered interrupt
+** mask to be later processed by gckEVENT_Notify.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctUINT32 Data
+** Mask for the 32 interrupts.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Interrupt(
+ IN gckEVENT Event,
+#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 (CoreId == gcvCORE_3D_0_ID)
+#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);
+
+#if gcdMULTI_GPU
+ /* Make sure FE of another GPU is idle. */
+ do
+ {
+ gcmkVERIFY_OK(gckOS_ReadRegisterByCoreId(
+ Event->os,
+ Event->kernel->core,
+ gcvCORE_3D_1_ID,
+ 0x4,
+ &idle));
+ }
+ while (idle != 0x7FFFFFFF);
+#endif
+
+ /* Start Command Parser. */
+ gcmkVERIFY_OK(gckHARDWARE_Execute(
+ Event->kernel->hardware,
+ data->physical,
+ data->bytes
+ ));
+ }
+ }
+
+ /* Combine current interrupt status with pending flags. */
+#if gcdSMP
+#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__)
+#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
+ if (Event->kernel->core == gcvCORE_MAJOR)
+ {
+ Event->pending3D[CoreId] |= Data;
+ }
+ else
+#endif
+#endif
+ {
+ Event->pending |= Data;
+ }
+#endif
+
+#if gcdINTERRUPT_STATISTIC
+#if gcdMULTI_GPU
+ if (CoreId == gcvCORE_3D_0_ID)
+#endif
+ {
+ 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. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Notify
+**
+** Process all triggered interrupts.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Notify(
+ IN gckEVENT Event,
+ IN gctUINT32 IDs
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctINT i;
+ gcsEVENT_QUEUE * queue;
+ gctUINT mask = 0;
+ gctBOOL acquired = gcvFALSE;
+ gctPOINTER info;
+ gctSIGNAL signal;
+ 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
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gctINT eventNumber = 0;
+#endif
+ gctINT32 free;
+#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);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ gcmDEBUG_ONLY(
+ if (IDs != 0)
+ {
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if (Event->queues[i].head != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "Queue(%d): stamp=%llu source=%d",
+ i,
+ Event->queues[i].stamp,
+ Event->queues[i].source);
+ }
+ }
+ }
+ );
+
+#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
+#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;
+
+#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)
+ {
+ gcmkPRINT("[galcore]: AXI BUS ERROR");
+ gckHARDWARE_DumpGPUState(Event->kernel->hardware);
+ pending &= 0x7FFFFFFF;
+ }
+
+ if (pending & 0x40000000)
+ {
+ gckHARDWARE_DumpMMUException(Event->kernel->hardware);
+
+ gckHARDWARE_DumpGPUState(Event->kernel->hardware);
+
+ pending &= 0xBFFFFFFF;
+ }
+
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_EVENT,
+ gcmSIZEOF(pending),
+ "Pending interrupts 0x%x",
+ pending
+ );
+
+ queue = gcvNULL;
+
+ gcmDEBUG_ONLY(
+ if (IDs == 0)
+ {
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if (Event->queues[i].head != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "Queue(%d): stamp=%llu source=%d",
+ i,
+ Event->queues[i].stamp,
+ Event->queues[i].source);
+ }
+ }
+ }
+ );
+
+ /* Find the oldest pending interrupt. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if ((Event->queues[i].head != gcvNULL)
+ && (pending & (1 << i))
+ )
+ {
+ if ((queue == gcvNULL)
+ || (Event->queues[i].stamp < queue->stamp)
+ )
+ {
+ queue = &Event->queues[i];
+ mask = 1 << i;
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ eventNumber = i;
+#endif
+ }
+ }
+ }
+
+ if (queue == gcvNULL)
+ {
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_ERROR, gcvZONE_EVENT,
+ gcmSIZEOF(pending),
+ "Interrupts 0x%x are not pending.",
+ pending
+ );
+
+#if gcdSMP
+#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__)
+#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;
+
+#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;
+ }
+
+ /* Check whether there is a missed interrupt. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if ((Event->queues[i].head != gcvNULL)
+ && (Event->queues[i].stamp < queue->stamp)
+ && (Event->queues[i].source <= queue->source)
+#if gcdMULTI_GPU
+ && (Event->queues[i].chipEnable == queue->chipEnable)
+#endif
+ )
+ {
+ gcmkTRACE_N(
+ gcvLEVEL_ERROR,
+ gcmSIZEOF(i) + gcmSIZEOF(Event->queues[i].stamp),
+ "Event %d lost (stamp %llu)",
+ i, Event->queues[i].stamp
+ );
+
+ /* Use this event instead. */
+ queue = &Event->queues[i];
+ mask = 0;
+ }
+ }
+
+ if (mask != 0)
+ {
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_EVENT,
+ gcmSIZEOF(eventNumber),
+ "Processing interrupt %d",
+ eventNumber
+ );
+#endif
+ }
+
+#if gcdSMP
+#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__)
+#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;
+
+#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
+ /* Write out commit stamp.*/
+ *(gctUINT64 *)(Event->kernel->command->fence->logical) = queue->commitStamp;
+
+ /* Grab the event head. */
+ record = queue->head;
+
+ /* Now quickly clear its event list. */
+ queue->head = gcvNULL;
+
+ /* Release the mutex queue. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ acquired = gcvFALSE;
+
+ /* Increase the number of free events. */
+ gcmkONERROR(gckOS_AtomIncrement(Event->os, Event->freeAtom, &free));
+
+ /* Walk all events for this interrupt. */
+ while (record != gcvNULL)
+ {
+ gcsEVENT_PTR recordNext;
+#ifndef __QNXNTO__
+ gctPOINTER logical;
+#endif
+#if gcdSECURE_USER
+ gctSIZE_T bytes;
+#endif
+
+ /* Grab next record. */
+ recordNext = record->next;
+
+#ifdef __QNXNTO__
+ /* Assign record->processID as the pid for this galcore thread.
+ * Used in OS calls like gckOS_UnlockMemory() which do not take a pid.
+ */
+ drv_thread_specific_key_assign(record->processID, 0, Event->kernel->core);
+#endif
+
+#if gcdSECURE_USER
+ /* Get the cache that belongs to this process. */
+ gcmkONERROR(gckKERNEL_GetProcessDBCache(Event->kernel,
+ record->processID,
+ &cache));
+#endif
+
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_EVENT,
+ gcmSIZEOF(record->info.command),
+ "Processing event type: %d",
+ record->info.command
+ );
+
+ switch (record->info.command)
+ {
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "gcvHAL_FREE_NON_PAGED_MEMORY: 0x%x",
+ gcmNAME_TO_PTR(record->info.u.FreeNonPagedMemory.physical));
+
+ /* Free non-paged memory. */
+ status = gckOS_FreeNonPagedMemory(
+ Event->os,
+ (gctSIZE_T) record->info.u.FreeNonPagedMemory.bytes,
+ gcmNAME_TO_PTR(record->info.u.FreeNonPagedMemory.physical),
+ gcmUINT64_TO_PTR(record->info.u.FreeNonPagedMemory.logical));
+
+ if (gcmIS_SUCCESS(status))
+ {
+#if gcdSECURE_USER
+ gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+ Event->kernel,
+ cache,
+ gcmUINT64_TO_PTR(record->record.u.FreeNonPagedMemory.logical),
+ (gctSIZE_T) record->record.u.FreeNonPagedMemory.bytes));
+#endif
+ }
+ gcmRELEASE_NAME(record->info.u.FreeNonPagedMemory.physical);
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "gcvHAL_FREE_CONTIGUOUS_MEMORY: 0x%x",
+ gcmNAME_TO_PTR(record->info.u.FreeContiguousMemory.physical));
+
+ /* Unmap the user memory. */
+ status = gckOS_FreeContiguous(
+ Event->os,
+ gcmNAME_TO_PTR(record->info.u.FreeContiguousMemory.physical),
+ gcmUINT64_TO_PTR(record->info.u.FreeContiguousMemory.logical),
+ (gctSIZE_T) record->info.u.FreeContiguousMemory.bytes);
+
+ if (gcmIS_SUCCESS(status))
+ {
+#if gcdSECURE_USER
+ gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+ Event->kernel,
+ cache,
+ 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_WRITE_DATA:
+#ifndef __QNXNTO__
+ /* Convert physical into logical address. */
+ gcmkERR_BREAK(
+ gckOS_MapPhysical(Event->os,
+ record->info.u.WriteData.address,
+ gcmSIZEOF(gctUINT32),
+ &logical));
+
+ /* Write data. */
+ gcmkERR_BREAK(
+ gckOS_WriteMemory(Event->os,
+ logical,
+ record->info.u.WriteData.data));
+
+ /* Unmap the physical memory. */
+ gcmkERR_BREAK(
+ gckOS_UnmapPhysical(Event->os,
+ logical,
+ gcmSIZEOF(gctUINT32)));
+#else
+ /* Write data. */
+ gcmkERR_BREAK(
+ gckOS_WriteMemory(Event->os,
+ (gctPOINTER)
+ record->info.u.WriteData.address,
+ record->info.u.WriteData.data));
+#endif
+ break;
+
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "gcvHAL_UNLOCK_VIDEO_MEMORY: 0x%x",
+ record->info.u.UnlockVideoMemory.node);
+
+ 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;
+ bytes = 0;
+ }
+ else
+ {
+ logical = node->Virtual.logical;
+ bytes = node->Virtual.bytes;
+ }
+#endif
+
+ /* Unlock. */
+ status = gckVIDMEM_Unlock(
+ Event->kernel,
+ nodeObject,
+ record->info.u.UnlockVideoMemory.type,
+ gcvNULL);
+
+#if gcdSECURE_USER
+ if (gcmIS_SUCCESS(status) && (logical != gcvNULL))
+ {
+ gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+ Event->kernel,
+ cache,
+ logical,
+ bytes));
+ }
+#endif
+
+#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:
+ signal = gcmUINT64_TO_PTR(record->info.u.Signal.signal);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "gcvHAL_SIGNAL: 0x%x",
+ signal);
+
+#ifdef __QNXNTO__
+ if ((record->info.u.Signal.coid == 0)
+ && (record->info.u.Signal.rcvid == 0)
+ )
+ {
+ /* Kernel signal. */
+ gcmkERR_BREAK(
+ gckOS_SignalPulse(Event->os,
+ signal));
+ }
+ else
+ {
+ /* User signal. */
+ gcmkERR_BREAK(
+ gckOS_UserSignal(Event->os,
+ signal,
+ record->info.u.Signal.rcvid,
+ record->info.u.Signal.coid));
+ }
+#else
+ /* Set signal. */
+ if (gcmUINT64_TO_PTR(record->info.u.Signal.process) == gcvNULL)
+ {
+ /* Kernel signal. */
+ gcmkERR_BREAK(
+ gckOS_Signal(Event->os,
+ signal,
+ gcvTRUE));
+ }
+ else
+ {
+ /* User signal. */
+ gcmkERR_BREAK(
+ gckOS_UserSignal(Event->os,
+ signal,
+ gcmUINT64_TO_PTR(record->info.u.Signal.process)));
+ }
+
+ gcmkASSERT(record->info.u.Signal.auxSignal == 0);
+#endif
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+ info = gcmNAME_TO_PTR(record->info.u.UnmapUserMemory.info);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "gcvHAL_UNMAP_USER_MEMORY: 0x%x",
+ info);
+
+ /* Unmap the user memory. */
+ status = gckOS_UnmapUserMemory(
+ Event->os,
+ Event->kernel->core,
+ gcmUINT64_TO_PTR(record->info.u.UnmapUserMemory.memory),
+ (gctSIZE_T) record->info.u.UnmapUserMemory.size,
+ info,
+ record->info.u.UnmapUserMemory.address);
+
+#if gcdSECURE_USER
+ if (gcmIS_SUCCESS(status))
+ {
+ gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+ Event->kernel,
+ cache,
+ gcmUINT64_TO_PTR(record->info.u.UnmapUserMemory.memory),
+ (gctSIZE_T) record->info.u.UnmapUserMemory.size));
+ }
+#endif
+ gcmRELEASE_NAME(record->info.u.UnmapUserMemory.info);
+ break;
+
+ case gcvHAL_TIMESTAMP:
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "gcvHAL_TIMESTAMP: %d %d",
+ record->info.u.TimeStamp.timer,
+ record->info.u.TimeStamp.request);
+
+ /* Process the timestamp. */
+ switch (record->info.u.TimeStamp.request)
+ {
+ case 0:
+ status = gckOS_GetTime(&Event->kernel->timers[
+ record->info.u.TimeStamp.timer].
+ stopTime);
+ break;
+
+ case 1:
+ status = gckOS_GetTime(&Event->kernel->timers[
+ record->info.u.TimeStamp.timer].
+ startTime);
+ break;
+
+ default:
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_ERROR, gcvZONE_EVENT,
+ gcmSIZEOF(record->info.u.TimeStamp.request),
+ "Invalid timestamp request: %d",
+ record->info.u.TimeStamp.request
+ );
+
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+ break;
+
+ case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
+ gcmkVERIFY_OK(
+ gckKERNEL_DestroyVirtualCommandBuffer(Event->kernel,
+ (gctSIZE_T) record->info.u.FreeVirtualCommandBuffer.bytes,
+ gcmNAME_TO_PTR(record->info.u.FreeVirtualCommandBuffer.physical),
+ gcmUINT64_TO_PTR(record->info.u.FreeVirtualCommandBuffer.logical)
+ ));
+ gcmRELEASE_NAME(record->info.u.FreeVirtualCommandBuffer.physical);
+ break;
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+ case gcvHAL_SYNC_POINT:
+ {
+ gctSYNC_POINT syncPoint;
+
+ syncPoint = gcmUINT64_TO_PTR(record->info.u.SyncPoint.syncPoint);
+ status = gckOS_SignalSyncPoint(Event->os, syncPoint);
+ }
+ 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;
+
+ default:
+ /* Invalid argument. */
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_ERROR, gcvZONE_EVENT,
+ gcmSIZEOF(record->info.command),
+ "Unknown event type: %d",
+ record->info.command
+ );
+
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+
+ /* Make sure there are no errors generated. */
+ if (gcmIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_WARNING, gcvZONE_EVENT,
+ gcmSIZEOF(status),
+ "Event produced status: %d(%s)",
+ status, gckOS_DebugStatus2Name(status));
+ }
+
+ /* Free the event. */
+ gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
+
+ /* Advance to next record. */
+ record = recordNext;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "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));
+ }
+
+#if gcdMULTI_GPU
+OnSuccess:
+#endif
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ }
+
+#if !gcdSMP
+ if (suspended)
+ {
+ /* Resume interrupts. */
+ gcmkVERIFY_OK(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
+ }
+#endif
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckEVENT_FreeProcess
+**
+** Free all events owned by a particular process ID.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctUINT32 ProcessID
+** Process ID of the process to be freed up.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_FreeProcess(
+ IN gckEVENT Event,
+ IN gctUINT32 ProcessID
+ )
+{
+ gctSIZE_T i;
+ gctBOOL acquired = gcvFALSE;
+ gcsEVENT_PTR record, next;
+ gceSTATUS status;
+ gcsEVENT_PTR deleteHead, deleteTail;
+
+ gcmkHEADER_ARG("Event=0x%x ProcessID=%d", Event, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Walk through all queues. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if (Event->queues[i].head != gcvNULL)
+ {
+ /* Grab the event queue mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->eventQueueMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Grab the mutex head. */
+ record = Event->queues[i].head;
+ Event->queues[i].head = gcvNULL;
+ Event->queues[i].tail = gcvNULL;
+ deleteHead = gcvNULL;
+ deleteTail = gcvNULL;
+
+ while (record != gcvNULL)
+ {
+ next = record->next;
+ if (record->processID == ProcessID)
+ {
+ if (deleteHead == gcvNULL)
+ {
+ deleteHead = record;
+ }
+ else
+ {
+ deleteTail->next = record;
+ }
+
+ deleteTail = record;
+ }
+ else
+ {
+ if (Event->queues[i].head == gcvNULL)
+ {
+ Event->queues[i].head = record;
+ }
+ else
+ {
+ Event->queues[i].tail->next = record;
+ }
+
+ Event->queues[i].tail = record;
+ }
+
+ record->next = gcvNULL;
+ record = next;
+ }
+
+ /* Release the mutex queue. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ acquired = gcvFALSE;
+
+ /* Loop through the entire list of events. */
+ for (record = deleteHead; record != gcvNULL; record = next)
+ {
+ /* Get the next event record. */
+ next = record->next;
+
+ /* Free the event record. */
+ gcmkONERROR(gckEVENT_FreeRecord(Event, record));
+ }
+ }
+ }
+
+ gcmkONERROR(_TryToIdleGPU(Event));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Release the event queue mutex. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckEVENT_Stop
+**
+** Stop the hardware using the End event mechanism.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctUINT32 ProcessID
+** Process ID Logical belongs.
+**
+** gctPHYS_ADDR Handle
+** Physical address handle. If gcvNULL it is video memory.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIGNAL Signal
+** Pointer to the signal to trigger.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Stop(
+ IN gckEVENT Event,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle,
+ IN gctPOINTER Logical,
+ IN gctSIGNAL Signal,
+ IN OUT gctUINT32 * waitSize
+ )
+{
+ gceSTATUS status;
+ /* gctSIZE_T waitSize;*/
+ gcsEVENT_PTR record;
+ gctUINT8 id = 0xFF;
+
+ gcmkHEADER_ARG("Event=0x%x ProcessID=%u Handle=0x%x Logical=0x%x "
+ "Signal=0x%x",
+ Event, ProcessID, Handle, Logical, Signal);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Submit the current event queue. */
+#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));
+
+ /* Initialize the record. */
+ record->next = gcvNULL;
+ record->processID = ProcessID;
+ record->info.command = gcvHAL_SIGNAL;
+ record->info.u.Signal.signal = gcmPTR_TO_UINT64(Signal);
+#ifdef __QNXNTO__
+ record->info.u.Signal.coid = 0;
+ record->info.u.Signal.rcvid = 0;
+#endif
+ record->info.u.Signal.auxSignal = 0;
+ record->info.u.Signal.process = 0;
+
+ /* Append the record. */
+ Event->queues[id].head = record;
+
+ /* Replace last WAIT with END. */
+ gcmkONERROR(gckHARDWARE_End(
+ Event->kernel->hardware, Logical, waitSize
+ ));
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache for the END. */
+ gcmkONERROR(gckOS_CacheClean(
+ Event->os,
+ ProcessID,
+ gcvNULL,
+ (gctUINT32)Handle,
+ Logical,
+ *waitSize
+ ));
+#endif
+
+ /* Wait for the signal. */
+ gcmkONERROR(gckOS_WaitSignal(Event->os, Signal, gcvINFINITE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static void
+_PrintRecord(
+ gcsEVENT_PTR record
+ )
+{
+ switch (record->info.command)
+ {
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ gcmkPRINT(" gcvHAL_FREE_NON_PAGED_MEMORY");
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ gcmkPRINT(" gcvHAL_FREE_CONTIGUOUS_MEMORY");
+ break;
+
+ case gcvHAL_WRITE_DATA:
+ gcmkPRINT(" gcvHAL_WRITE_DATA");
+ break;
+
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ gcmkPRINT(" gcvHAL_UNLOCK_VIDEO_MEMORY");
+ break;
+
+ case gcvHAL_SIGNAL:
+ gcmkPRINT(" gcvHAL_SIGNAL process=%d signal=0x%x",
+ record->info.u.Signal.process,
+ record->info.u.Signal.signal);
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+ gcmkPRINT(" gcvHAL_UNMAP_USER_MEMORY");
+ break;
+
+ case gcvHAL_TIMESTAMP:
+ gcmkPRINT(" gcvHAL_TIMESTAMP");
+ break;
+
+ case gcvHAL_COMMIT_DONE:
+ gcmkPRINT(" gcvHAL_COMMIT_DONE");
+ break;
+
+ case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
+ gcmkPRINT(" gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER logical=0x%08x",
+ 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;
+ }
+}
+
+/*******************************************************************************
+** gckEVENT_Dump
+**
+** Dump record in event queue when stuck happens.
+** No protection for the event queue.
+**/
+gceSTATUS
+gckEVENT_Dump(
+ IN gckEVENT Event
+ )
+{
+ gcsEVENT_QUEUE_PTR queueHead = Event->queueHead;
+ gcsEVENT_QUEUE_PTR queue;
+ gcsEVENT_PTR record = gcvNULL;
+ gctINT i;
+#if gcdINTERRUPT_STATISTIC
+ gctINT32 pendingInterrupt;
+ gctUINT32 intrAcknowledge;
+#endif
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ gcmkPRINT("**************************\n");
+ gcmkPRINT("*** EVENT STATE DUMP ***\n");
+ gcmkPRINT("**************************\n");
+
+ gcmkPRINT(" Unsumbitted Event:");
+ while(queueHead)
+ {
+ queue = queueHead;
+ record = queueHead->head;
+
+ gcmkPRINT(" [%x]:", queue);
+ while(record)
+ {
+ _PrintRecord(record);
+ record = record->next;
+ }
+
+ if (queueHead == Event->queueTail)
+ {
+ queueHead = gcvNULL;
+ }
+ else
+ {
+ queueHead = queueHead->next;
+ }
+ }
+
+ gcmkPRINT(" Untriggered Event:");
+ for (i = 0; i < gcmCOUNTOF(Event->queues); i++)
+ {
+ queue = &Event->queues[i];
+ record = queue->head;
+
+ gcmkPRINT(" [%d]:", i);
+ while(record)
+ {
+ _PrintRecord(record);
+ record = record->next;
+ }
+ }
+
+#if gcdINTERRUPT_STATISTIC
+ gckOS_AtomGet(Event->os, Event->interruptCount, &pendingInterrupt);
+ gcmkPRINT(" Number of Pending Interrupt: %d", pendingInterrupt);
+
+ if (Event->kernel->recovery == 0)
+ {
+ gckOS_ReadRegisterEx(
+ Event->os,
+ Event->kernel->core,
+ 0x10,
+ &intrAcknowledge
+ );
+
+ gcmkPRINT(" INTR_ACKNOWLEDGE=0x%x", intrAcknowledge);
+ }
+#endif
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c
new file mode 100644
index 000000000000..3d7da980b84b
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c
@@ -0,0 +1,892 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+/**
+** @file
+** gckHEAP object for kernel HAL layer. The heap implemented here is an arena-
+** based memory allocation. An arena-based memory heap allocates data quickly
+** from specified arenas and reduces memory fragmentation.
+**
+*/
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_HEAP
+
+/*******************************************************************************
+***** Structures ***************************************************************
+*******************************************************************************/
+#define gcdIN_USE ((gcskNODE_PTR)gcvMAXUINTPTR_T)
+
+typedef struct _gcskNODE * gcskNODE_PTR;
+typedef struct _gcskNODE
+{
+ /* Number of byets in node. */
+ gctSIZE_T bytes;
+
+ /* Pointer to next free node, or gcvNULL to mark the node as freed, or
+ ** gcdIN_USE to mark the node as used. */
+ gcskNODE_PTR next;
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Time stamp of allocation. */
+ gctUINT64 timeStamp;
+#endif
+}
+gcskNODE;
+
+typedef struct _gcskHEAP * gcskHEAP_PTR;
+typedef struct _gcskHEAP
+{
+ /* Linked list. */
+ gcskHEAP_PTR next;
+ gcskHEAP_PTR prev;
+
+ /* Heap size. */
+ gctSIZE_T size;
+
+ /* Free list. */
+ gcskNODE_PTR freeList;
+}
+gcskHEAP;
+
+struct _gckHEAP
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to a gckOS object. */
+ gckOS os;
+
+ /* Locking mutex. */
+ gctPOINTER mutex;
+
+ /* Allocation parameters. */
+ gctSIZE_T allocationSize;
+
+ /* Heap list. */
+ gcskHEAP_PTR heap;
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ gctUINT64 timeStamp;
+#endif
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Profile information. */
+ gctUINT32 allocCount;
+ gctUINT64 allocBytes;
+ gctUINT64 allocBytesMax;
+ gctUINT64 allocBytesTotal;
+ gctUINT32 heapCount;
+ gctUINT32 heapCountMax;
+ gctUINT64 heapMemory;
+ gctUINT64 heapMemoryMax;
+#endif
+};
+
+/*******************************************************************************
+***** Static Support Functions *************************************************
+*******************************************************************************/
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+static gctSIZE_T
+_DumpHeap(
+ IN gcskHEAP_PTR Heap
+ )
+{
+ gctPOINTER p;
+ gctSIZE_T leaked = 0;
+
+ /* Start at first node. */
+ for (p = Heap + 1;;)
+ {
+ /* Convert the pointer. */
+ gcskNODE_PTR node = (gcskNODE_PTR) p;
+
+ /* Check if this is a used node. */
+ if (node->next == gcdIN_USE)
+ {
+ /* Print the leaking node. */
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_HEAP,
+ "Detected leaking: node=0x%x bytes=%lu timeStamp=%llu "
+ "(%08X %c%c%c%c)",
+ node, node->bytes, node->timeStamp,
+ ((gctUINT32_PTR) (node + 1))[0],
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[0]),
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[1]),
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[2]),
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[3]));
+
+ /* Add leaking byte count. */
+ leaked += node->bytes;
+ }
+
+ /* Test for end of heap. */
+ if (node->bytes == 0)
+ {
+ break;
+ }
+
+ else
+ {
+ /* Move to next node. */
+ p = (gctUINT8_PTR) node + node->bytes;
+ }
+ }
+
+ /* Return the number of leaked bytes. */
+ return leaked;
+}
+#endif
+
+static gceSTATUS
+_CompactKernelHeap(
+ IN gckHEAP Heap
+ )
+{
+ gcskHEAP_PTR heap, next;
+ gctPOINTER p;
+ gcskHEAP_PTR freeList = gcvNULL;
+
+ gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+ /* Walk all the heaps. */
+ for (heap = Heap->heap; heap != gcvNULL; heap = next)
+ {
+ gcskNODE_PTR lastFree = gcvNULL;
+
+ /* Zero out the free list. */
+ heap->freeList = gcvNULL;
+
+ /* Start at the first node. */
+ for (p = (gctUINT8_PTR) (heap + 1);;)
+ {
+ /* Convert the pointer. */
+ gcskNODE_PTR node = (gcskNODE_PTR) p;
+
+ gcmkASSERT(p <= (gctPOINTER) ((gctUINT8_PTR) (heap + 1) + heap->size));
+
+ /* Test if this node not used. */
+ if (node->next != gcdIN_USE)
+ {
+ /* Test if this is the end of the heap. */
+ if (node->bytes == 0)
+ {
+ break;
+ }
+
+ /* Test of this is the first free node. */
+ else if (lastFree == gcvNULL)
+ {
+ /* Initialzie the free list. */
+ heap->freeList = node;
+ lastFree = node;
+ }
+
+ else
+ {
+ /* Test if this free node is contiguous with the previous
+ ** free node. */
+ if ((gctUINT8_PTR) lastFree + lastFree->bytes == p)
+ {
+ /* Just increase the size of the previous free node. */
+ lastFree->bytes += node->bytes;
+ }
+ else
+ {
+ /* Add to linked list. */
+ lastFree->next = node;
+ lastFree = node;
+ }
+ }
+ }
+
+ /* Move to next node. */
+ p = (gctUINT8_PTR) node + node->bytes;
+ }
+
+ /* Mark the end of the chain. */
+ if (lastFree != gcvNULL)
+ {
+ lastFree->next = gcvNULL;
+ }
+
+ /* Get next heap. */
+ next = heap->next;
+
+ /* Check if the entire heap is free. */
+ if ((heap->freeList != gcvNULL)
+ && (heap->freeList->bytes == heap->size - gcmSIZEOF(gcskNODE))
+ )
+ {
+ /* Remove the heap from the linked list. */
+ if (heap->prev == gcvNULL)
+ {
+ Heap->heap = next;
+ }
+ else
+ {
+ heap->prev->next = next;
+ }
+
+ if (heap->next != gcvNULL)
+ {
+ heap->next->prev = heap->prev;
+ }
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Update profiling. */
+ Heap->heapCount -= 1;
+ Heap->heapMemory -= heap->size + gcmSIZEOF(gcskHEAP);
+#endif
+
+ /* Add this heap to the list of heaps that need to be freed. */
+ heap->next = freeList;
+ freeList = heap;
+ }
+ }
+
+ if (freeList != gcvNULL)
+ {
+ /* Release the mutex, remove any chance for a dead lock. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ /* Free all heaps in the free list. */
+ for (heap = freeList; heap != gcvNULL; heap = next)
+ {
+ /* Get pointer to the next heap. */
+ next = heap->next;
+
+ /* Free the heap. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
+ "Freeing heap 0x%x (%lu bytes)",
+ heap, heap->size + gcmSIZEOF(gcskHEAP));
+ gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
+ }
+
+ /* Acquire the mutex again. */
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+***** gckHEAP API Code *********************************************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** gckHEAP_Construct
+**
+** Construct a new gckHEAP object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctSIZE_T AllocationSize
+** Minimum size per arena.
+**
+** OUTPUT:
+**
+** gckHEAP * Heap
+** Pointer to a variable that will hold the pointer to the gckHEAP
+** object.
+*/
+gceSTATUS
+gckHEAP_Construct(
+ IN gckOS Os,
+ IN gctSIZE_T AllocationSize,
+ OUT gckHEAP * Heap
+ )
+{
+ gceSTATUS status;
+ gckHEAP heap = gcvNULL;
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG("Os=0x%x AllocationSize=%lu", Os, AllocationSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Heap != gcvNULL);
+
+ /* Allocate the gckHEAP object. */
+ gcmkONERROR(gckOS_AllocateMemory(Os,
+ gcmSIZEOF(struct _gckHEAP),
+ &pointer));
+
+ heap = pointer;
+
+ /* Initialize the gckHEAP object. */
+ heap->object.type = gcvOBJ_HEAP;
+ heap->os = Os;
+ heap->allocationSize = AllocationSize;
+ heap->heap = gcvNULL;
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ heap->timeStamp = 0;
+#endif
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Zero the counters. */
+ heap->allocCount = 0;
+ heap->allocBytes = 0;
+ heap->allocBytesMax = 0;
+ heap->allocBytesTotal = 0;
+ heap->heapCount = 0;
+ heap->heapCountMax = 0;
+ heap->heapMemory = 0;
+ heap->heapMemoryMax = 0;
+#endif
+
+ /* Create the mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &heap->mutex));
+
+ /* Return the pointer to the gckHEAP object. */
+ *Heap = heap;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Heap=0x%x", *Heap);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (heap != gcvNULL)
+ {
+ /* Free the heap structure. */
+ gcmkVERIFY_OK(gckOS_FreeMemory(Os, heap));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHEAP_Destroy
+**
+** Destroy a gckHEAP object.
+**
+** INPUT:
+**
+** gckHEAP Heap
+** Pointer to a gckHEAP object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHEAP_Destroy(
+ IN gckHEAP Heap
+ )
+{
+ gcskHEAP_PTR heap;
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ gctSIZE_T leaked = 0;
+#endif
+
+ gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+ for (heap = Heap->heap; heap != gcvNULL; heap = Heap->heap)
+ {
+ /* Unlink heap from linked list. */
+ Heap->heap = heap->next;
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Check for leaked memory. */
+ leaked += _DumpHeap(heap);
+#endif
+
+ /* Free the heap. */
+ gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
+ }
+
+ /* Free the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Heap->os, Heap->mutex));
+
+ /* Free the heap structure. */
+ gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, Heap));
+
+ /* Success. */
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ gcmkFOOTER_ARG("leaked=%lu", leaked);
+#else
+ gcmkFOOTER_NO();
+#endif
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHEAP_Allocate
+**
+** Allocate data from the heap.
+**
+** INPUT:
+**
+** gckHEAP Heap
+** Pointer to a gckHEAP object.
+**
+** IN gctSIZE_T Bytes
+** Number of byte to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the address of the allocated
+** memory.
+*/
+gceSTATUS
+gckHEAP_Allocate(
+ IN gckHEAP Heap,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gctBOOL acquired = gcvFALSE;
+ gcskHEAP_PTR heap;
+ gceSTATUS status;
+ gctSIZE_T bytes;
+ gcskNODE_PTR node, used, prevFree = gcvNULL;
+ gctPOINTER memory = gcvNULL;
+
+ gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Determine number of bytes required for a node. */
+ bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ /* Check if this allocation is bigger than the default allocation size. */
+ if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP) - gcmSIZEOF(gcskNODE))
+ {
+ /* Adjust allocation size. */
+ Heap->allocationSize = bytes * 2;
+ }
+
+ else if (Heap->heap != gcvNULL)
+ {
+ gctINT i;
+
+ /* 2 retries, since we might need to compact. */
+ for (i = 0; i < 2; ++i)
+ {
+ /* Walk all the heaps. */
+ for (heap = Heap->heap; heap != gcvNULL; heap = heap->next)
+ {
+ /* Check if this heap has enough bytes to hold the request. */
+ if (bytes <= heap->size - gcmSIZEOF(gcskNODE))
+ {
+ prevFree = gcvNULL;
+
+ /* Walk the chain of free nodes. */
+ for (node = heap->freeList;
+ node != gcvNULL;
+ node = node->next
+ )
+ {
+ gcmkASSERT(node->next != gcdIN_USE);
+
+ /* Check if this free node has enough bytes. */
+ if (node->bytes >= bytes)
+ {
+ /* Use the node. */
+ goto UseNode;
+ }
+
+ /* Save current free node for linked list management. */
+ prevFree = node;
+ }
+ }
+ }
+
+ if (i == 0)
+ {
+ /* Compact the heap. */
+ gcmkVERIFY_OK(_CompactKernelHeap(Heap));
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "===== KERNEL HEAP =====");
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Number of allocations : %12u",
+ Heap->allocCount);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Number of bytes allocated : %12llu",
+ Heap->allocBytes);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Maximum allocation size : %12llu",
+ Heap->allocBytesMax);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Total number of bytes allocated : %12llu",
+ Heap->allocBytesTotal);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Number of heaps : %12u",
+ Heap->heapCount);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Heap memory in bytes : %12llu",
+ Heap->heapMemory);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Maximum number of heaps : %12u",
+ Heap->heapCountMax);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Maximum heap memory in bytes : %12llu",
+ Heap->heapMemoryMax);
+#endif
+ }
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ acquired = gcvFALSE;
+
+ /* Allocate a new heap. */
+ gcmkONERROR(
+ gckOS_AllocateMemory(Heap->os,
+ Heap->allocationSize,
+ &memory));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
+ "Allocated heap 0x%x (%lu bytes)",
+ memory, Heap->allocationSize);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ /* Use the allocated memory as the heap. */
+ heap = (gcskHEAP_PTR) memory;
+
+ /* Insert this heap to the head of the chain. */
+ heap->next = Heap->heap;
+ heap->prev = gcvNULL;
+ heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP);
+
+ if (heap->next != gcvNULL)
+ {
+ heap->next->prev = heap;
+ }
+ Heap->heap = heap;
+
+ /* Mark the end of the heap. */
+ node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap
+ + Heap->allocationSize
+ - gcmSIZEOF(gcskNODE)
+ );
+ node->bytes = 0;
+ node->next = gcvNULL;
+
+ /* Create a free list. */
+ node = (gcskNODE_PTR) (heap + 1);
+ heap->freeList = node;
+
+ /* Initialize the free list. */
+ node->bytes = heap->size - gcmSIZEOF(gcskNODE);
+ node->next = gcvNULL;
+
+ /* No previous free. */
+ prevFree = gcvNULL;
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Update profiling. */
+ Heap->heapCount += 1;
+ Heap->heapMemory += Heap->allocationSize;
+
+ if (Heap->heapCount > Heap->heapCountMax)
+ {
+ Heap->heapCountMax = Heap->heapCount;
+ }
+ if (Heap->heapMemory > Heap->heapMemoryMax)
+ {
+ Heap->heapMemoryMax = Heap->heapMemory;
+ }
+#endif
+
+UseNode:
+ /* Verify some stuff. */
+ gcmkASSERT(heap != gcvNULL);
+ gcmkASSERT(node != gcvNULL);
+ gcmkASSERT(node->bytes >= bytes);
+
+ if (heap->prev != gcvNULL)
+ {
+ /* Unlink the heap from the linked list. */
+ heap->prev->next = heap->next;
+ if (heap->next != gcvNULL)
+ {
+ heap->next->prev = heap->prev;
+ }
+
+ /* Move the heap to the front of the list. */
+ heap->next = Heap->heap;
+ heap->prev = gcvNULL;
+ Heap->heap = heap;
+ heap->next->prev = heap;
+ }
+
+ /* Check if there is enough free space left after usage for another free
+ ** node. */
+ if (node->bytes - bytes >= gcmSIZEOF(gcskNODE))
+ {
+ /* Allocated used space from the back of the free list. */
+ used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes);
+
+ /* Adjust the number of free bytes. */
+ node->bytes -= bytes;
+ gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE));
+ }
+ else
+ {
+ /* Remove this free list from the chain. */
+ if (prevFree == gcvNULL)
+ {
+ heap->freeList = node->next;
+ }
+ else
+ {
+ prevFree->next = node->next;
+ }
+
+ /* Consume the entire free node. */
+ used = (gcskNODE_PTR) node;
+ bytes = node->bytes;
+ }
+
+ /* Mark node as used. */
+ used->bytes = bytes;
+ used->next = gcdIN_USE;
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ used->timeStamp = ++Heap->timeStamp;
+#endif
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Update profile counters. */
+ Heap->allocCount += 1;
+ Heap->allocBytes += bytes;
+ Heap->allocBytesMax = gcmMAX(Heap->allocBytes, Heap->allocBytesMax);
+ Heap->allocBytesTotal += bytes;
+#endif
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ /* Return pointer to memory. */
+ *Memory = used + 1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+ }
+
+ if (memory != gcvNULL)
+ {
+ /* Free the heap memory. */
+ gckOS_FreeMemory(Heap->os, memory);
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHEAP_Free
+**
+** Free allocated memory from the heap.
+**
+** INPUT:
+**
+** gckHEAP Heap
+** Pointer to a gckHEAP object.
+**
+** IN gctPOINTER Memory
+** Pointer to memory to free.
+**
+** OUTPUT:
+**
+** NOTHING.
+*/
+gceSTATUS
+gckHEAP_Free(
+ IN gckHEAP Heap,
+ IN gctPOINTER Memory
+ )
+{
+ gcskNODE_PTR node;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Heap=0x%x Memory=0x%x", Heap, Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+ /* Pointer to structure. */
+ node = (gcskNODE_PTR) Memory - 1;
+
+ /* Mark the node as freed. */
+ node->next = gcvNULL;
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Update profile counters. */
+ Heap->allocBytes -= node->bytes;
+#endif
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gckHEAP_ProfileStart(
+ IN gckHEAP Heap
+ )
+{
+ gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+
+ /* Zero the counters. */
+ Heap->allocCount = 0;
+ Heap->allocBytes = 0;
+ Heap->allocBytesMax = 0;
+ Heap->allocBytesTotal = 0;
+ Heap->heapCount = 0;
+ Heap->heapCountMax = 0;
+ Heap->heapMemory = 0;
+ Heap->heapMemoryMax = 0;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHEAP_ProfileEnd(
+ IN gckHEAP Heap,
+ IN gctCONST_STRING Title
+ )
+{
+ gcmkHEADER_ARG("Heap=0x%x Title=0x%x", Heap, Title);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+ gcmkVERIFY_ARGUMENT(Title != gcvNULL);
+
+ gcmkPRINT("");
+ gcmkPRINT("=====[ HEAP - %s ]=====", Title);
+ gcmkPRINT("Number of allocations : %12u", Heap->allocCount);
+ gcmkPRINT("Number of bytes allocated : %12llu", Heap->allocBytes);
+ gcmkPRINT("Maximum allocation size : %12llu", Heap->allocBytesMax);
+ gcmkPRINT("Total number of bytes allocated : %12llu", Heap->allocBytesTotal);
+ gcmkPRINT("Number of heaps : %12u", Heap->heapCount);
+ gcmkPRINT("Heap memory in bytes : %12llu", Heap->heapMemory);
+ gcmkPRINT("Maximum number of heaps : %12u", Heap->heapCountMax);
+ gcmkPRINT("Maximum heap memory in bytes : %12llu", Heap->heapMemoryMax);
+ gcmkPRINT("==============================================");
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif /* VIVANTE_PROFILER */
+
+/*******************************************************************************
+***** Test Code ****************************************************************
+*******************************************************************************/
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c
new file mode 100644
index 000000000000..3fed5af91bbd
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c
@@ -0,0 +1,911 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdENABLE_VG
+
+/******************************************************************************\
+*********************** Support Functions and Definitions **********************
+\******************************************************************************/
+
+/* Interruot statistics will be accumulated if not zero. */
+#define gcmENABLE_INTERRUPT_STATISTICS 0
+
+#define _GC_OBJ_ZONE gcvZONE_INTERRUPT
+
+/* Object structure. */
+struct _gckVGINTERRUPT
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* gckVGKERNEL pointer. */
+ gckVGKERNEL kernel;
+
+ /* gckOS pointer. */
+ gckOS os;
+
+ /* Interrupt handlers. */
+ gctINTERRUPT_HANDLER handlers[32];
+
+ /* Main interrupt handler thread. */
+ gctTHREAD handler;
+ gctBOOL terminate;
+
+ /* Interrupt FIFO. */
+ gctSEMAPHORE fifoValid;
+ gctUINT32 fifo[256];
+ gctUINT fifoItems;
+ gctUINT8 head;
+ gctUINT8 tail;
+
+ /* Interrupt statistics. */
+#if gcmENABLE_INTERRUPT_STATISTICS
+ gctUINT maxFifoItems;
+ gctUINT fifoOverflow;
+ gctUINT maxSimultaneous;
+ gctUINT multipleCount;
+#endif
+};
+
+
+/*******************************************************************************
+**
+** _ProcessInterrupt
+**
+** The interrupt processor.
+**
+** INPUT:
+**
+** ThreadParameter
+** Pointer to the gckVGINTERRUPT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+#if gcmENABLE_INTERRUPT_STATISTICS
+static void
+_ProcessInterrupt(
+ gckVGINTERRUPT Interrupt,
+ gctUINT_PTR TriggeredCount
+ )
+#else
+static void
+_ProcessInterrupt(
+ gckVGINTERRUPT Interrupt
+ )
+#endif
+{
+ gceSTATUS status;
+ gctUINT32 triggered;
+ gctUINT i;
+
+ /* Advance to the next entry. */
+ Interrupt->tail += 1;
+ Interrupt->fifoItems -= 1;
+
+ /* Get the interrupt value. */
+ triggered = Interrupt->fifo[Interrupt->tail];
+ gcmkASSERT(triggered != 0);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s: triggered=0x%08X\n",
+ __FUNCTION__,
+ triggered
+ );
+
+ /* Walk through all possible interrupts. */
+ for (i = 0; i < gcmSIZEOF(Interrupt->handlers); i += 1)
+ {
+ /* Test if interrupt happened. */
+ if ((triggered & 1) == 1)
+ {
+#if gcmENABLE_INTERRUPT_STATISTICS
+ if (TriggeredCount != gcvNULL)
+ {
+ (* TriggeredCount) += 1;
+ }
+#endif
+
+ /* Make sure we have valid handler. */
+ if (Interrupt->handlers[i] == gcvNULL)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s: Interrupt %d isn't registered.\n",
+ __FUNCTION__, i
+ );
+ }
+ else
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s: interrupt=%d\n",
+ __FUNCTION__,
+ i
+ );
+
+ /* Call the handler. */
+ status = Interrupt->handlers[i] (Interrupt->kernel);
+
+ if (gcmkIS_ERROR(status))
+ {
+ /* Failed to signal the semaphore. */
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s: Error %d incrementing the semaphore #%d.\n",
+ __FUNCTION__, status, i
+ );
+ }
+ }
+ }
+
+ /* Next interrupt. */
+ triggered >>= 1;
+
+ /* No more interrupts to handle? */
+ if (triggered == 0)
+ {
+ break;
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** _MainInterruptHandler
+**
+** The main interrupt thread serves the interrupt FIFO and calls registered
+** handlers for the interrupts that occured. The handlers are called in the
+** sequence interrupts occured with the exception when multiple interrupts
+** occured at the same time. In that case the handler calls are "sorted" by
+** the interrupt number therefore giving the interrupts with lower numbers
+** higher priority.
+**
+** INPUT:
+**
+** ThreadParameter
+** Pointer to the gckVGINTERRUPT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+static gctTHREADFUNCRESULT gctTHREADFUNCTYPE
+_MainInterruptHandler(
+ gctTHREADFUNCPARAMETER ThreadParameter
+ )
+{
+ gceSTATUS status;
+ gckVGINTERRUPT interrupt;
+
+#if gcmENABLE_INTERRUPT_STATISTICS
+ gctUINT count;
+#endif
+
+ /* Cast the object. */
+ interrupt = (gckVGINTERRUPT) ThreadParameter;
+
+ /* Enter the loop. */
+ while (gcvTRUE)
+ {
+ /* Wait for an interrupt. */
+ status = gckOS_DecrementSemaphore(interrupt->os, interrupt->fifoValid);
+
+ /* Error? */
+ if (gcmkIS_ERROR(status))
+ {
+ break;
+ }
+
+ /* System termination request? */
+ if (status == gcvSTATUS_TERMINATE)
+ {
+ break;
+ }
+
+ /* Driver is shutting down? */
+ if (interrupt->terminate)
+ {
+ break;
+ }
+
+#if gcmENABLE_INTERRUPT_STATISTICS
+ /* Reset triggered count. */
+ count = 0;
+
+ /* Process the interrupt. */
+ _ProcessInterrupt(interrupt, &count);
+
+ /* Update conters. */
+ if (count > interrupt->maxSimultaneous)
+ {
+ interrupt->maxSimultaneous = count;
+ }
+
+ if (count > 1)
+ {
+ interrupt->multipleCount += 1;
+ }
+#else
+ /* Process the interrupt. */
+ _ProcessInterrupt(interrupt);
+#endif
+ }
+
+ return 0;
+}
+
+
+/*******************************************************************************
+**
+** _StartInterruptHandler / _StopInterruptHandler
+**
+** Main interrupt handler routine control.
+**
+** INPUT:
+**
+** ThreadParameter
+** Pointer to the gckVGINTERRUPT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+static gceSTATUS
+_StartInterruptHandler(
+ gckVGINTERRUPT Interrupt
+ )
+{
+ gceSTATUS status, last;
+
+ do
+ {
+ /* Objects must not be already created. */
+ gcmkASSERT(Interrupt->fifoValid == gcvNULL);
+ gcmkASSERT(Interrupt->handler == gcvNULL);
+
+ /* Reset the termination request. */
+ Interrupt->terminate = gcvFALSE;
+
+#if !gcdENABLE_INFINITE_SPEED_HW
+ /* Construct the fifo semaphore. */
+ gcmkERR_BREAK(gckOS_CreateSemaphoreVG(
+ Interrupt->os, &Interrupt->fifoValid
+ ));
+
+ /* Start the interrupt handler thread. */
+ gcmkERR_BREAK(gckOS_StartThread(
+ Interrupt->os,
+ _MainInterruptHandler,
+ Interrupt,
+ &Interrupt->handler
+ ));
+#endif
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Roll back. */
+ if (Interrupt->fifoValid != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_DestroySemaphore(
+ Interrupt->os, Interrupt->fifoValid
+ ));
+
+ Interrupt->fifoValid = gcvNULL;
+ }
+
+ /* Return the status. */
+ return status;
+}
+
+static gceSTATUS
+_StopInterruptHandler(
+ gckVGINTERRUPT Interrupt
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Does the thread exist? */
+ if (Interrupt->handler == gcvNULL)
+ {
+ /* The semaphore must be NULL as well. */
+ gcmkASSERT(Interrupt->fifoValid == gcvNULL);
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ break;
+ }
+
+ /* The semaphore must exist as well. */
+ gcmkASSERT(Interrupt->fifoValid != gcvNULL);
+
+ /* Set the termination request. */
+ Interrupt->terminate = gcvTRUE;
+
+ /* Unlock the thread. */
+ gcmkERR_BREAK(gckOS_IncrementSemaphore(
+ Interrupt->os, Interrupt->fifoValid
+ ));
+
+ /* Wait until the thread quits. */
+ gcmkERR_BREAK(gckOS_StopThread(
+ Interrupt->os,
+ Interrupt->handler
+ ));
+
+ /* Destroy the semaphore. */
+ gcmkERR_BREAK(gckOS_DestroySemaphore(
+ Interrupt->os, Interrupt->fifoValid
+ ));
+
+ /* Reset handles. */
+ Interrupt->handler = gcvNULL;
+ Interrupt->fifoValid = gcvNULL;
+ }
+ while (gcvFALSE);
+
+ /* Return the status. */
+ return status;
+}
+
+
+/******************************************************************************\
+***************************** Interrupt Object API *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckVGINTERRUPT_Construct
+**
+** Construct an interrupt object.
+**
+** INPUT:
+**
+** Kernel
+** Pointer to the gckVGKERNEL object.
+**
+** OUTPUT:
+**
+** Interrupt
+** Pointer to the new gckVGINTERRUPT object.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Construct(
+ IN gckVGKERNEL Kernel,
+ OUT gckVGINTERRUPT * Interrupt
+ )
+{
+ gceSTATUS status;
+ gckVGINTERRUPT interrupt = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%x Interrupt=0x%x", Kernel, Interrupt);
+
+ /* Verify argeuments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interrupt != gcvNULL);
+
+ do
+ {
+ /* Allocate the gckVGINTERRUPT structure. */
+ gcmkERR_BREAK(gckOS_Allocate(
+ Kernel->os,
+ gcmSIZEOF(struct _gckVGINTERRUPT),
+ (gctPOINTER *) &interrupt
+ ));
+
+ /* Reset the object data. */
+ gcmkVERIFY_OK(gckOS_ZeroMemory(
+ interrupt, gcmSIZEOF(struct _gckVGINTERRUPT)
+ ));
+
+ /* Initialize the object. */
+ interrupt->object.type = gcvOBJ_INTERRUPT;
+
+ /* Initialize the object pointers. */
+ interrupt->kernel = Kernel;
+ interrupt->os = Kernel->os;
+
+ /* Initialize the current FIFO position. */
+ interrupt->head = (gctUINT8)~0;
+ interrupt->tail = (gctUINT8)~0;
+
+ /* Start the thread. */
+ gcmkERR_BREAK(_StartInterruptHandler(interrupt));
+
+ /* Return interrupt object. */
+ *Interrupt = interrupt;
+
+ gcmkFOOTER_ARG("*Interrup=0x%x", *Interrupt);
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Roll back. */
+ if (interrupt != gcvNULL)
+ {
+ /* Free the gckVGINTERRUPT structure. */
+ gcmkVERIFY_OK(gckOS_Free(interrupt->os, interrupt));
+ }
+
+ gcmkFOOTER();
+
+ /* Return the status. */
+ return status;
+}
+
+
+/*******************************************************************************
+**
+** gckVGINTERRUPT_Destroy
+**
+** Destroy an interrupt object.
+**
+** INPUT:
+**
+** Interrupt
+** Pointer to the gckVGINTERRUPT object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Destroy(
+ IN gckVGINTERRUPT Interrupt
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+
+ do
+ {
+ /* Stop the interrupt thread. */
+ gcmkERR_BREAK(_StopInterruptHandler(Interrupt));
+
+ /* Mark the object as unknown. */
+ Interrupt->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckVGINTERRUPT structure. */
+ gcmkERR_BREAK(gckOS_Free(Interrupt->os, Interrupt));
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+
+ /* Return the status. */
+ return status;
+}
+
+
+/*******************************************************************************
+**
+** gckVGINTERRUPT_DumpState
+**
+** Print the current state of the interrupt manager.
+**
+** INPUT:
+**
+** Interrupt
+** Pointer to a gckVGINTERRUPT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+#if gcvDEBUG
+gceSTATUS
+gckVGINTERRUPT_DumpState(
+ IN gckVGINTERRUPT Interrupt
+ )
+{
+ gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+
+ /* Print the header. */
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s: INTERRUPT OBJECT STATUS\n",
+ __FUNCTION__
+ );
+
+ /* Print statistics. */
+#if gcmENABLE_INTERRUPT_STATISTICS
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " Maximum number of FIFO items accumulated at a single time: %d\n",
+ Interrupt->maxFifoItems
+ );
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " Interrupt FIFO overflow happened times: %d\n",
+ Interrupt->fifoOverflow
+ );
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " Maximum number of interrupts simultaneously generated: %d\n",
+ Interrupt->maxSimultaneous
+ );
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " Number of times when there were multiple interrupts generated: %d\n",
+ Interrupt->multipleCount
+ );
+#endif
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " The current number of entries in the FIFO: %d\n",
+ Interrupt->fifoItems
+ );
+
+ /* Print the FIFO contents. */
+ if (Interrupt->fifoItems != 0)
+ {
+ gctUINT8 index;
+ gctUINT8 last;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " FIFO current contents:\n"
+ );
+
+ /* Get the current pointers. */
+ index = Interrupt->tail;
+ last = Interrupt->head;
+
+ while (index != last)
+ {
+ /* Advance to the next entry. */
+ index += 1;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " %d: 0x%08X\n",
+ index, Interrupt->fifo[index]
+ );
+ }
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+#endif
+
+
+/*******************************************************************************
+**
+** gckVGINTERRUPT_Enable
+**
+** Enable the specified interrupt.
+**
+** INPUT:
+**
+** Interrupt
+** Pointer to a gckVGINTERRUPT object.
+**
+** Id
+** Pointer to the variable that holds the interrupt number to be
+** registered in range 0..31.
+** If the value is less then 0, gckVGINTERRUPT_Enable will attempt
+** to find an unused interrupt. If such interrupt is found, the number
+** will be assigned to the variable if the functuion call succeedes.
+**
+** Handler
+** Pointer to the handler to register for the interrupt.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Enable(
+ IN gckVGINTERRUPT Interrupt,
+ IN OUT gctINT32_PTR Id,
+ IN gctINTERRUPT_HANDLER Handler
+ )
+{
+ gceSTATUS status;
+ gctINT32 i;
+
+ gcmkHEADER_ARG("Interrupt=0x%x Id=0x%x Handler=0x%x", Interrupt, Id, Handler);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+ gcmkVERIFY_ARGUMENT(Id != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Handler != gcvNULL);
+
+ do
+ {
+ /* See if we need to allocate an ID. */
+ if (*Id < 0)
+ {
+ /* Find the first unused interrupt handler. */
+ for (i = 0; i < gcmCOUNTOF(Interrupt->handlers); ++i)
+ {
+ if (Interrupt->handlers[i] == gcvNULL)
+ {
+ break;
+ }
+ }
+
+ /* No unused innterrupts? */
+ if (i == gcmCOUNTOF(Interrupt->handlers))
+ {
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ break;
+ }
+
+ /* Update the interrupt ID. */
+ *Id = i;
+ }
+
+ /* Make sure the ID is in range. */
+ else if (*Id >= gcmCOUNTOF(Interrupt->handlers))
+ {
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+
+ /* Set interrupt handler. */
+ Interrupt->handlers[*Id] = Handler;
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+
+/*******************************************************************************
+**
+** gckVGINTERRUPT_Disable
+**
+** Disable the specified interrupt.
+**
+** INPUT:
+**
+** Interrupt
+** Pointer to a gckVGINTERRUPT object.
+**
+** Id
+** Interrupt number to be disabled in range 0..31.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Disable(
+ IN gckVGINTERRUPT Interrupt,
+ IN gctINT32 Id
+ )
+{
+ gcmkHEADER_ARG("Interrupt=0x%x Id=0x%x", Interrupt, Id);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+ gcmkVERIFY_ARGUMENT((Id >= 0) && (Id < gcmCOUNTOF(Interrupt->handlers)));
+
+ /* Reset interrupt handler. */
+ Interrupt->handlers[Id] = gcvNULL;
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckVGINTERRUPT_Enque
+**
+** Read the interrupt status register and put the value in the interrupt FIFO.
+**
+** INPUT:
+**
+** Interrupt
+** Pointer to a gckVGINTERRUPT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+#ifndef __QNXNTO__
+gceSTATUS
+gckVGINTERRUPT_Enque(
+ IN gckVGINTERRUPT Interrupt
+ )
+#else
+gceSTATUS
+gckVGINTERRUPT_Enque(
+ IN gckVGINTERRUPT Interrupt,
+ OUT gckOS *Os,
+ OUT gctSEMAPHORE *Semaphore
+ )
+#endif
+{
+ gceSTATUS status;
+ gctUINT32 triggered;
+
+ gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+
+#ifdef __QNXNTO__
+ *Os = gcvNULL;
+ *Semaphore = gcvNULL;
+#endif
+
+ do
+ {
+ /* Read interrupt status register. */
+ gcmkERR_BREAK(gckVGHARDWARE_ReadInterrupt(
+ Interrupt->kernel->hardware, &triggered
+ ));
+
+ /* Mask out TS overflow interrupt */
+ triggered &= 0xfffffffe;
+
+ /* No interrupts to process? */
+ if (triggered == 0)
+ {
+ status = gcvSTATUS_NOT_OUR_INTERRUPT;
+ break;
+ }
+
+ /* FIFO overflow? */
+ if (Interrupt->fifoItems == gcmCOUNTOF(Interrupt->fifo))
+ {
+#if gcmENABLE_INTERRUPT_STATISTICS
+ Interrupt->fifoOverflow += 1;
+#endif
+
+ /* OR the interrupt with the last value in the FIFO. */
+ Interrupt->fifo[Interrupt->head] |= triggered;
+
+ /* Success (kind of). */
+ status = gcvSTATUS_OK;
+ }
+ else
+ {
+ /* Advance to the next entry. */
+ Interrupt->head += 1;
+ Interrupt->fifoItems += 1;
+
+#if gcmENABLE_INTERRUPT_STATISTICS
+ if (Interrupt->fifoItems > Interrupt->maxFifoItems)
+ {
+ Interrupt->maxFifoItems = Interrupt->fifoItems;
+ }
+#endif
+
+ /* Set the new value. */
+ Interrupt->fifo[Interrupt->head] = triggered;
+
+#ifndef __QNXNTO__
+ /* Increment the FIFO semaphore. */
+ gcmkERR_BREAK(gckOS_IncrementSemaphore(
+ Interrupt->os, Interrupt->fifoValid
+ ));
+#else
+ *Os = Interrupt->os;
+ *Semaphore = Interrupt->fifoValid;
+#endif
+
+ /* Windows kills our threads prematurely when the application
+ exists. Verify here that the thread is still alive. */
+ status = gckOS_VerifyThread(Interrupt->os, Interrupt->handler);
+
+ /* Has the thread been prematurely terminated? */
+ if (status != gcvSTATUS_OK)
+ {
+ /* Process all accumulated interrupts. */
+ while (Interrupt->head != Interrupt->tail)
+ {
+#if gcmENABLE_INTERRUPT_STATISTICS
+ /* Process the interrupt. */
+ _ProcessInterrupt(Interrupt, gcvNULL);
+#else
+ /* Process the interrupt. */
+ _ProcessInterrupt(Interrupt);
+#endif
+ }
+
+ /* Set success. */
+ status = gcvSTATUS_OK;
+ }
+ }
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+#endif /* gcdENABLE_VG */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
new file mode 100644
index 000000000000..b6baf0aa0257
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
@@ -0,0 +1,2315 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_MMU
+
+typedef enum _gceMMU_TYPE
+{
+ gcvMMU_USED = (0 << 4),
+ gcvMMU_SINGLE = (1 << 4),
+ gcvMMU_FREE = (2 << 4),
+}
+gceMMU_TYPE;
+
+#define gcmENTRY_TYPE(x) (x & 0xF0)
+
+#define gcdMMU_TABLE_DUMP 0
+
+#define gcdUSE_MMU_EXCEPTION 0
+
+/*
+ gcdMMU_CLEAR_VALUE
+
+ The clear value for the entry of the old MMU.
+*/
+#ifndef gcdMMU_CLEAR_VALUE
+# define gcdMMU_CLEAR_VALUE 0x00000ABC
+#endif
+
+#define gcdVERTEX_START (128 << 10)
+
+typedef struct _gcsMMU_STLB *gcsMMU_STLB_PTR;
+
+typedef struct _gcsMMU_STLB
+{
+ gctPHYS_ADDR physical;
+ gctUINT32_PTR logical;
+ gctSIZE_T size;
+ gctUINT32 physBase;
+ gctSIZE_T pageCount;
+ gctUINT32 mtlbIndex;
+ gctUINT32 mtlbEntryNum;
+ gcsMMU_STLB_PTR next;
+} gcsMMU_STLB;
+
+#if gcdSHARED_PAGETABLE
+typedef struct _gcsSharedPageTable * gcsSharedPageTable_PTR;
+typedef struct _gcsSharedPageTable
+{
+ /* Shared gckMMU object. */
+ gckMMU mmu;
+
+ /* Hardwares which use this shared pagetable. */
+ gckHARDWARE hardwares[gcdMAX_GPU_COUNT];
+
+ /* Number of cores use this shared pagetable. */
+ gctUINT32 reference;
+}
+gcsSharedPageTable;
+
+static gcsSharedPageTable_PTR sharedPageTable = gcvNULL;
+#endif
+
+#if gcdMIRROR_PAGETABLE
+typedef struct _gcsMirrorPageTable * gcsMirrorPageTable_PTR;
+typedef struct _gcsMirrorPageTable
+{
+ /* gckMMU objects. */
+ gckMMU mmus[gcdMAX_GPU_COUNT];
+
+ /* Hardwares which use this shared pagetable. */
+ gckHARDWARE hardwares[gcdMAX_GPU_COUNT];
+
+ /* Number of cores use this shared pagetable. */
+ gctUINT32 reference;
+}
+gcsMirrorPageTable;
+
+static gcsMirrorPageTable_PTR mirrorPageTable = gcvNULL;
+static gctPOINTER mirrorPageTableMutex = gcvNULL;
+#endif
+
+typedef struct _gcsDynamicSpaceNode * gcsDynamicSpaceNode_PTR;
+typedef struct _gcsDynamicSpaceNode
+{
+ gctUINT32 start;
+ gctINT32 entries;
+}
+gcsDynamicSpaceNode;
+
+static void
+_WritePageEntry(
+ IN gctUINT32_PTR PageEntry,
+ IN gctUINT32 EntryValue
+ )
+{
+ static gctUINT16 data = 0xff00;
+
+ if (*(gctUINT8 *)&data == 0xff)
+ {
+ *PageEntry = gcmSWAB32(EntryValue);
+ }
+ else
+ {
+ *PageEntry = EntryValue;
+ }
+}
+
+static gctUINT32
+_ReadPageEntry(
+ IN gctUINT32_PTR PageEntry
+ )
+{
+ static gctUINT16 data = 0xff00;
+ gctUINT32 entryValue;
+
+ if (*(gctUINT8 *)&data == 0xff)
+ {
+ entryValue = *PageEntry;
+ return gcmSWAB32(entryValue);
+ }
+ else
+ {
+ return *PageEntry;
+ }
+}
+
+static gceSTATUS
+_FillPageTable(
+ IN gctUINT32_PTR PageTable,
+ IN gctUINT32 PageCount,
+ IN gctUINT32 EntryValue
+)
+{
+ gctUINT i;
+
+ for (i = 0; i < PageCount; i++)
+ {
+ _WritePageEntry(PageTable + i, EntryValue);
+ }
+
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_Link(
+ IN gckMMU Mmu,
+ IN gctUINT32 Index,
+ IN gctUINT32 Next
+ )
+{
+ if (Index >= Mmu->pageTableEntries)
+ {
+ /* Just move heap pointer. */
+ Mmu->heapList = Next;
+ }
+ else
+ {
+ /* Address page table. */
+ gctUINT32_PTR map = Mmu->mapLogical;
+
+ /* Dispatch on node type. */
+ switch (gcmENTRY_TYPE(_ReadPageEntry(&map[Index])))
+ {
+ case gcvMMU_SINGLE:
+ /* Set single index. */
+ _WritePageEntry(&map[Index], (Next << 8) | gcvMMU_SINGLE);
+ break;
+
+ case gcvMMU_FREE:
+ /* Set index. */
+ _WritePageEntry(&map[Index + 1], Next);
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", Index);
+ return gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_AddFree(
+ IN gckMMU Mmu,
+ IN gctUINT32 Index,
+ IN gctUINT32 Node,
+ IN gctUINT32 Count
+ )
+{
+ gctUINT32_PTR map = Mmu->mapLogical;
+
+ if (Count == 1)
+ {
+ /* Initialize a single page node. */
+ _WritePageEntry(map + Node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
+ }
+ else
+ {
+ /* Initialize the node. */
+ _WritePageEntry(map + Node + 0, (Count << 8) | gcvMMU_FREE);
+ _WritePageEntry(map + Node + 1, ~0U);
+ }
+
+ /* Append the node. */
+ return _Link(Mmu, Index, Node);
+}
+
+static gceSTATUS
+_Collect(
+ IN gckMMU Mmu
+ )
+{
+ gctUINT32_PTR map = Mmu->mapLogical;
+ gceSTATUS status;
+ gctUINT32 i, previous, start = 0, count = 0;
+
+ previous = Mmu->heapList = ~0U;
+ Mmu->freeNodes = gcvFALSE;
+
+ /* Walk the entire page table. */
+ for (i = 0; i < Mmu->pageTableEntries; ++i)
+ {
+ /* Dispatch based on type of page. */
+ switch (gcmENTRY_TYPE(_ReadPageEntry(&map[i])))
+ {
+ case gcvMMU_USED:
+ /* Used page, so close any open node. */
+ if (count > 0)
+ {
+ /* Add the node. */
+ gcmkONERROR(_AddFree(Mmu, previous, start, count));
+
+ /* Reset the node. */
+ previous = start;
+ count = 0;
+ }
+ break;
+
+ case gcvMMU_SINGLE:
+ /* Single free node. */
+ if (count++ == 0)
+ {
+ /* Start a new node. */
+ start = i;
+ }
+ break;
+
+ case gcvMMU_FREE:
+ /* A free node. */
+ if (count == 0)
+ {
+ /* Start a new node. */
+ start = i;
+ }
+
+ /* Advance the count. */
+ count += _ReadPageEntry(&map[i]) >> 8;
+
+ /* Advance the index into the page table. */
+ i += (_ReadPageEntry(&map[i]) >> 8) - 1;
+ break;
+
+ default:
+ gcmkFATAL("MMU page table correcupted at index %u!", i);
+ return gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* See if we have an open node left. */
+ if (count > 0)
+ {
+ /* Add the node to the list. */
+ gcmkONERROR(_AddFree(Mmu, previous, start, count));
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_MMU,
+ "Performed a garbage collection of the MMU heap.");
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the staus. */
+ return status;
+}
+
+static gctUINT32
+_SetPage(gctUINT32 PageAddress, gctUINT32 PageAddressExt)
+{
+ return PageAddress
+ /* AddressExt */
+ | (PageAddressExt << 4)
+ /* writable */
+ | (1 << 2)
+ /* Ignore exception */
+ | (0 << 1)
+ /* Present */
+ | (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,
+ IN gctUINT32 PhysBase,
+ OUT gctSIZE_T Size
+ )
+{
+ gceSTATUS status;
+ gctBOOL mutex = gcvFALSE;
+ gcsMMU_STLB_PTR head = gcvNULL, pre = gcvNULL;
+ gctUINT32 start = PhysBase & (~gcdMMU_PAGE_64K_MASK);
+ gctUINT32 end = (PhysBase + Size - 1) & (~gcdMMU_PAGE_64K_MASK);
+ gctUINT32 mStart = start >> gcdMMU_MTLB_SHIFT;
+ gctUINT32 mEnd = end >> gcdMMU_MTLB_SHIFT;
+ gctUINT32 sStart = (start & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
+ gctUINT32 sEnd = (end & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
+ gctBOOL ace = gckHARDWARE_IsFeatureAvailable(Mmu->hardware, gcvFEATURE_ACE);
+ gctPHYS_ADDR_T physical;
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+ mutex = gcvTRUE;
+
+ while (mStart <= mEnd)
+ {
+ gcmkASSERT(mStart < gcdMMU_MTLB_ENTRY_NUM);
+ if (*(Mmu->mtlbLogical + mStart) == 0)
+ {
+ 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;
+
+ stlb->mtlbEntryNum = 0;
+ stlb->next = gcvNULL;
+ stlb->physical = gcvNULL;
+ stlb->logical = gcvNULL;
+ stlb->size = gcdMMU_STLB_64K_SIZE;
+ stlb->pageCount = 0;
+
+ if (pre == gcvNULL)
+ {
+ pre = head = stlb;
+ }
+ else
+ {
+ gcmkASSERT(pre->next == gcvNULL);
+ pre->next = stlb;
+ pre = stlb;
+ }
+
+ gcmkONERROR(
+ gckOS_AllocateContiguous(Mmu->os,
+ gcvFALSE,
+ &stlb->size,
+ &stlb->physical,
+ (gctPOINTER)&stlb->logical));
+
+ gcmkONERROR(gckOS_ZeroMemory(stlb->logical, stlb->size));
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(
+ Mmu->os,
+ stlb->logical,
+ &physical));
+
+ gcmkSAFECASTPHYSADDRT(stlb->physBase, physical);
+
+ if (stlb->physBase & (gcdMMU_STLB_64K_SIZE - 1))
+ {
+ gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+ }
+
+ 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__,
+ mStart,
+ _ReadPageEntry(Mmu->mtlbLogical + mStart));
+#endif
+
+ stlb->mtlbIndex = mStart;
+ stlb->mtlbEntryNum = 1;
+#if gcdMMU_TABLE_DUMP
+ gckOS_Print("%s(%d): STLB: logical:%08x -> physical:%08x\n",
+ __FUNCTION__, __LINE__,
+ stlb->logical,
+ stlb->physBase);
+#endif
+
+ while (sStart <= last)
+ {
+ gcmkASSERT(!(start & gcdMMU_PAGE_64K_MASK));
+ _WritePageEntry(stlb->logical + sStart, _SetPage(start, 0));
+#if gcdMMU_TABLE_DUMP
+ gckOS_Print("%s(%d): insert STLB[%d]: %08x\n",
+ __FUNCTION__, __LINE__,
+ sStart,
+ _ReadPageEntry(stlb->logical + sStart));
+#endif
+ /* next page. */
+ start += gcdMMU_PAGE_64K_SIZE;
+ sStart++;
+ stlb->pageCount++;
+ }
+
+ sStart = 0;
+ ++mStart;
+ }
+ else
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+ }
+ }
+
+ /* Insert the stlb into staticSTLB. */
+ if (Mmu->staticSTLB == gcvNULL)
+ {
+ Mmu->staticSTLB = head;
+ }
+ else
+ {
+ gcmkASSERT(pre == gcvNULL);
+ gcmkASSERT(pre->next == gcvNULL);
+ pre->next = Mmu->staticSTLB;
+ Mmu->staticSTLB = head;
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Roll back. */
+ while (head != gcvNULL)
+ {
+ pre = head;
+ head = head->next;
+
+ if (pre->physical != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(Mmu->os,
+ pre->physical,
+ pre->logical,
+ pre->size));
+ }
+
+ if (pre->mtlbEntryNum != 0)
+ {
+ gcmkASSERT(pre->mtlbEntryNum == 1);
+ _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
+ }
+
+ if (mutex)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+ }
+
+ return status;
+}
+
+static gceSTATUS
+_FindDynamicSpace(
+ IN gckMMU Mmu,
+ OUT gcsDynamicSpaceNode_PTR *Array,
+ OUT gctINT * Size
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctPOINTER pointer = gcvNULL;
+ gcsDynamicSpaceNode_PTR array = gcvNULL;
+ gctINT size = 0;
+ gctINT i = 0, nodeStart = -1, nodeEntries = 0;
+
+ /* Allocate memory for the array. */
+ gcmkONERROR(gckOS_Allocate(Mmu->os,
+ gcmSIZEOF(*array) * (gcdMMU_MTLB_ENTRY_NUM / 2),
+ &pointer));
+
+ array = (gcsDynamicSpaceNode_PTR)pointer;
+
+ /* Loop all the entries. */
+ while (i < gcdMMU_MTLB_ENTRY_NUM)
+ {
+ if (!Mmu->mtlbLogical[i])
+ {
+ if (nodeStart < 0)
+ {
+ /* This is the first entry of the dynamic space. */
+ nodeStart = i;
+ nodeEntries = 1;
+ }
+ else
+ {
+ /* Other entries of the dynamic space. */
+ nodeEntries++;
+ }
+ }
+ else if (nodeStart >= 0)
+ {
+ /* Save the previous node. */
+ array[size].start = nodeStart;
+ array[size].entries = nodeEntries;
+ size++;
+
+ /* Reset the start. */
+ nodeStart = -1;
+ nodeEntries = 0;
+ }
+
+ i++;
+ }
+
+ /* Save the previous node. */
+ if (nodeStart >= 0)
+ {
+ array[size].start = nodeStart;
+ array[size].entries = nodeEntries;
+ size++;
+ }
+
+#if gcdMMU_TABLE_DUMP
+ for (i = 0; i < size; i++)
+ {
+ gckOS_Print("%s(%d): [%d]: start=%d, entries=%d.\n",
+ __FUNCTION__, __LINE__,
+ i,
+ array[i].start,
+ array[i].entries);
+ }
+#endif
+
+ *Array = array;
+ *Size = size;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ if (pointer != gcvNULL)
+ {
+ gckOS_Free(Mmu->os, pointer);
+ }
+
+ return status;
+}
+
+static gceSTATUS
+_SetupDynamicSpace(
+ IN gckMMU Mmu
+ )
+{
+ gceSTATUS status;
+ gcsDynamicSpaceNode_PTR nodeArray = gcvNULL;
+ gctINT i, nodeArraySize = 0;
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address;
+ gctINT numEntries = 0;
+ 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));
+
+ /* TODO: We only use the largest one for now. */
+ for (i = 0; i < nodeArraySize; i++)
+ {
+ if (nodeArray[i].entries > numEntries)
+ {
+ Mmu->dynamicMappingStart = nodeArray[i].start;
+ numEntries = nodeArray[i].entries;
+ }
+ }
+
+ gckOS_Free(Mmu->os, (gctPOINTER)nodeArray);
+
+ Mmu->pageTableSize = numEntries * 4096;
+
+ 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,
+ gcvFALSE,
+ &Mmu->pageTableSize,
+ &Mmu->pageTablePhysical,
+ (gctPOINTER)&Mmu->pageTableLogical));
+
+#if gcdUSE_MMU_EXCEPTION
+ gcmkONERROR(_FillPageTable(Mmu->pageTableLogical,
+ Mmu->pageTableEntries,
+ /* Enable exception */
+ 1 << 1));
+#else
+ /* Invalidate all entries. */
+ gcmkONERROR(gckOS_ZeroMemory(Mmu->pageTableLogical,
+ Mmu->pageTableSize));
+#endif
+
+ /* Initilization. */
+ map = Mmu->mapLogical;
+ _WritePageEntry(map, (Mmu->pageTableEntries << 8) | gcvMMU_FREE);
+ _WritePageEntry(map + 1, ~0U);
+ Mmu->heapList = 0;
+ Mmu->freeNodes = gcvFALSE;
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(Mmu->os,
+ Mmu->pageTableLogical,
+ &physical));
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Map to Master TLB. */
+ for (i = (gctINT)Mmu->dynamicMappingStart;
+ i < (gctINT)Mmu->dynamicMappingStart + numEntries;
+ i++)
+ {
+ mtlbEntry = address
+ /* 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__,
+ i,
+ _ReadPageEntry(Mmu->mtlbLogical + i));
+#endif
+ address += gcdMMU_STLB_4K_SIZE;
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+
+ return gcvSTATUS_OK;
+
+OnError:
+ if (Mmu->mapLogical)
+ {
+ gcmkVERIFY_OK(
+ gckOS_Free(Mmu->os, (gctPOINTER) Mmu->mapLogical));
+
+
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(Mmu->os,
+ Mmu->pageTablePhysical,
+ (gctPOINTER) Mmu->pageTableLogical,
+ Mmu->pageTableSize));
+ }
+
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+ }
+
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** _Construct
+**
+** Construct a new gckMMU object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctSIZE_T MmuSize
+** Number of bytes for the page table.
+**
+** OUTPUT:
+**
+** gckMMU * Mmu
+** Pointer to a variable that receives the gckMMU object pointer.
+*/
+gceSTATUS
+_Construct(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T MmuSize,
+ OUT gckMMU * Mmu
+ )
+{
+ gckOS os;
+ gckHARDWARE hardware;
+ gceSTATUS status;
+ gckMMU mmu = gcvNULL;
+ gctUINT32_PTR map;
+ gctPOINTER pointer = gcvNULL;
+#if gcdPROCESS_ADDRESS_SPACE
+ gctUINT32 i;
+ gctUINT32 physical;
+#endif
+ gctUINT32 physBase;
+ gctUINT32 physSize;
+ gctUINT32 gpuAddress;
+ gctPHYS_ADDR_T gpuPhysical;
+
+ gcmkHEADER_ARG("Kernel=0x%x MmuSize=%lu", Kernel, MmuSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(MmuSize > 0);
+ gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Extract the gckHARDWARE object pointer. */
+ hardware = Kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Allocate memory for the gckMMU object. */
+ gcmkONERROR(gckOS_Allocate(os, sizeof(struct _gckMMU), &pointer));
+
+ mmu = pointer;
+
+ /* Initialize the gckMMU object. */
+ mmu->object.type = gcvOBJ_MMU;
+ mmu->os = os;
+ mmu->hardware = hardware;
+ mmu->pageTableMutex = gcvNULL;
+ mmu->pageTableLogical = gcvNULL;
+ mmu->mtlbLogical = gcvNULL;
+ mmu->staticSTLB = gcvNULL;
+ mmu->enabled = gcvFALSE;
+ mmu->mapLogical = gcvNULL;
+
+ /* Create the page table mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &mmu->pageTableMutex));
+
+ if (hardware->mmuVersion == 0)
+ {
+ mmu->pageTableSize = MmuSize;
+
+ /* 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));
+
+
+ /* Compute number of entries in page table. */
+ gcmkSAFECASTSIZET(mmu->pageTableEntries, mmu->pageTableSize / sizeof(gctUINT32));
+
+ /* Mark all pages as free. */
+ map = mmu->mapLogical;
+
+#if gcdMMU_CLEAR_VALUE
+ _FillPageTable(mmu->pageTableLogical, mmu->pageTableEntries, gcdMMU_CLEAR_VALUE);
+#endif
+
+ _WritePageEntry(map, (mmu->pageTableEntries << 8) | gcvMMU_FREE);
+ _WritePageEntry(map + 1, ~0U);
+ mmu->heapList = 0;
+ mmu->freeNodes = gcvFALSE;
+ }
+ else
+ {
+ /* Allocate the 4K mode MTLB table. */
+ mmu->mtlbSize = gcdMMU_MTLB_SIZE + 64;
+
+ gcmkONERROR(
+ gckOS_AllocateContiguous(os,
+ gcvFALSE,
+ &mmu->mtlbSize,
+ &mmu->mtlbPhysical,
+ &pointer));
+
+ 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, &gpuPhysical));
+
+ gcmkSAFECASTPHYSADDRT(gpuAddress, gpuPhysical);
+
+ /* Setup [physBase - physSize) flat mapping. */
+ gcmkONERROR(_FillFlatMapping(
+ mmu,
+ gpuAddress,
+ physSize
+ ));
+
+ gcmkONERROR(_SetupDynamicSpace(mmu));
+#endif
+ }
+
+ /* Return the gckMMU object pointer. */
+ *Mmu = mmu;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Mmu=0x%x", *Mmu);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (mmu != gcvNULL)
+ {
+ if (mmu->mapLogical != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_Free(os, (gctPOINTER) mmu->mapLogical));
+
+
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(os,
+ mmu->pageTablePhysical,
+ (gctPOINTER) mmu->pageTableLogical,
+ mmu->pageTableSize));
+ }
+
+ if (mmu->mtlbLogical != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(os,
+ mmu->mtlbPhysical,
+ (gctPOINTER) mmu->mtlbLogical,
+ mmu->mtlbSize));
+ }
+
+ if (mmu->pageTableMutex != gcvNULL)
+ {
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, mmu->pageTableMutex));
+ }
+
+ /* Mark the gckMMU object as unknown. */
+ mmu->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the allocates memory. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, mmu));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** _Destroy
+**
+** Destroy a gckMMU object.
+**
+** INPUT:
+**
+** gckMMU Mmu
+** Pointer to an gckMMU object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+_Destroy(
+ IN gckMMU Mmu
+ )
+{
+#if gcdPROCESS_ADDRESS_SPACE
+ gctUINT32 i;
+#endif
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+ while (Mmu->staticSTLB != gcvNULL)
+ {
+ gcsMMU_STLB_PTR pre = Mmu->staticSTLB;
+ Mmu->staticSTLB = pre->next;
+
+ if (pre->physical != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(Mmu->os,
+ pre->physical,
+ pre->logical,
+ pre->size));
+ }
+
+ if (pre->mtlbEntryNum != 0)
+ {
+ gcmkASSERT(pre->mtlbEntryNum == 1);
+ _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
+#if gcdMMU_TABLE_DUMP
+ gckOS_Print("%s(%d): clean MTLB[%d]\n",
+ __FUNCTION__, __LINE__,
+ pre->mtlbIndex);
+#endif
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
+ }
+
+ if (Mmu->hardware->mmuVersion != 0)
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(Mmu->os,
+ Mmu->mtlbPhysical,
+ (gctPOINTER) Mmu->mtlbLogical,
+ Mmu->mtlbSize));
+ }
+
+ /* Free address space management table. */
+ if (Mmu->mapLogical != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_Free(Mmu->os, (gctPOINTER) Mmu->mapLogical));
+ }
+
+ 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;
+
+ /* Free the gckMMU object. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, Mmu));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** _AdjstIndex
+**
+** Adjust the index from which we search for a usable node to make sure
+** index allocated is greater than Start.
+*/
+gceSTATUS
+_AdjustIndex(
+ IN gckMMU Mmu,
+ IN gctUINT32 Index,
+ IN gctUINT32 PageCount,
+ IN gctUINT32 Start,
+ OUT gctUINT32 * IndexAdjusted
+ )
+{
+ gceSTATUS status;
+ gctUINT32 index = Index;
+ gctUINT32_PTR map = Mmu->mapLogical;
+
+ gcmkHEADER();
+
+ for (; index < Mmu->pageTableEntries;)
+ {
+ gctUINT32 result = 0;
+ gctUINT32 nodeSize = 0;
+
+ if (index >= Start)
+ {
+ break;
+ }
+
+ switch (gcmENTRY_TYPE(map[index]))
+ {
+ case gcvMMU_SINGLE:
+ nodeSize = 1;
+ break;
+
+ case gcvMMU_FREE:
+ nodeSize = map[index] >> 8;
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", index);
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ if (nodeSize > PageCount)
+ {
+ result = index + (nodeSize - PageCount);
+
+ if (result >= Start)
+ {
+ break;
+ }
+ }
+
+ switch (gcmENTRY_TYPE(map[index]))
+ {
+ case gcvMMU_SINGLE:
+ index = map[index] >> 8;
+ break;
+
+ case gcvMMU_FREE:
+ index = map[index + 1];
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", index);
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+
+ *IndexAdjusted = index;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckMMU_Construct(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T MmuSize,
+ OUT gckMMU * Mmu
+ )
+{
+#if gcdSHARED_PAGETABLE
+ gceSTATUS status;
+ gctPOINTER pointer;
+
+ gcmkHEADER_ARG("Kernel=0x%08x", Kernel);
+
+ if (sharedPageTable == gcvNULL)
+ {
+ gcmkONERROR(
+ gckOS_Allocate(Kernel->os,
+ sizeof(struct _gcsSharedPageTable),
+ &pointer));
+ sharedPageTable = pointer;
+
+ gcmkONERROR(
+ gckOS_ZeroMemory(sharedPageTable,
+ sizeof(struct _gcsSharedPageTable)));
+
+ gcmkONERROR(_Construct(Kernel, MmuSize, &sharedPageTable->mmu));
+ }
+
+ *Mmu = sharedPageTable->mmu;
+
+ sharedPageTable->hardwares[sharedPageTable->reference] = Kernel->hardware;
+
+ sharedPageTable->reference++;
+
+ gcmkFOOTER_ARG("sharedPageTable->reference=%lu", sharedPageTable->reference);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (sharedPageTable)
+ {
+ if (sharedPageTable->mmu)
+ {
+ gcmkVERIFY_OK(gckMMU_Destroy(sharedPageTable->mmu));
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, sharedPageTable));
+ }
+
+ gcmkFOOTER();
+ return status;
+#elif gcdMIRROR_PAGETABLE
+ gceSTATUS status;
+ gctPOINTER pointer;
+
+ gcmkHEADER_ARG("Kernel=0x%08x", Kernel);
+
+ if (mirrorPageTable == gcvNULL)
+ {
+ gcmkONERROR(
+ gckOS_Allocate(Kernel->os,
+ sizeof(struct _gcsMirrorPageTable),
+ &pointer));
+ mirrorPageTable = pointer;
+
+ gcmkONERROR(
+ gckOS_ZeroMemory(mirrorPageTable,
+ sizeof(struct _gcsMirrorPageTable)));
+
+ gcmkONERROR(
+ gckOS_CreateMutex(Kernel->os, &mirrorPageTableMutex));
+ }
+
+ gcmkONERROR(_Construct(Kernel, MmuSize, Mmu));
+
+ mirrorPageTable->mmus[mirrorPageTable->reference] = *Mmu;
+
+ mirrorPageTable->hardwares[mirrorPageTable->reference] = Kernel->hardware;
+
+ mirrorPageTable->reference++;
+
+ gcmkFOOTER_ARG("mirrorPageTable->reference=%lu", mirrorPageTable->reference);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mirrorPageTable && mirrorPageTable->reference == 0)
+ {
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, mirrorPageTable));
+ }
+
+ gcmkFOOTER();
+ return status;
+#else
+ return _Construct(Kernel, MmuSize, Mmu);
+#endif
+}
+
+gceSTATUS
+gckMMU_Destroy(
+ IN gckMMU Mmu
+ )
+{
+#if gcdSHARED_PAGETABLE
+ gckOS os = Mmu->os;
+
+ sharedPageTable->reference--;
+
+ if (sharedPageTable->reference == 0)
+ {
+ if (sharedPageTable->mmu)
+ {
+ gcmkVERIFY_OK(_Destroy(Mmu));
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, sharedPageTable));
+ }
+
+ return gcvSTATUS_OK;
+#elif gcdMIRROR_PAGETABLE
+ mirrorPageTable->reference--;
+
+ if (mirrorPageTable->reference == 0)
+ {
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, mirrorPageTable));
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, mirrorPageTableMutex));
+ }
+
+ return _Destroy(Mmu);
+#else
+ return _Destroy(Mmu);
+#endif
+}
+
+/*******************************************************************************
+**
+** gckMMU_AllocatePages
+**
+** Allocate pages inside the page table.
+**
+** INPUT:
+**
+** gckMMU Mmu
+** Pointer to an gckMMU object.
+**
+** gctSIZE_T PageCount
+** Number of pages to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * PageTable
+** Pointer to a variable that receives the base address of the page
+** table.
+**
+** gctUINT32 * Address
+** Pointer to a variable that receives the hardware specific address.
+*/
+gceSTATUS
+_AllocatePages(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ IN gceSURF_TYPE Type,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ )
+{
+ gceSTATUS status;
+ gctBOOL mutex = gcvFALSE;
+ gctUINT32 index = 0, previous = ~0U, left;
+ gctUINT32_PTR map;
+ gctBOOL gotIt;
+ gctUINT32 address;
+ gctUINT32 pageCount;
+
+ gcmkHEADER_ARG("Mmu=0x%x PageCount=%lu", Mmu, PageCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+
+ if (PageCount > Mmu->pageTableEntries)
+ {
+ /* Not enough pages avaiable. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ gcmkSAFECASTSIZET(pageCount, PageCount);
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+ mutex = gcvTRUE;
+
+ /* Cast pointer to page table. */
+ for (map = Mmu->mapLogical, gotIt = gcvFALSE; !gotIt;)
+ {
+ index = Mmu->heapList;
+
+ if ((Mmu->hardware->mmuVersion == 0) && (Type == gcvSURF_VERTEX))
+ {
+ gcmkONERROR(_AdjustIndex(
+ Mmu,
+ index,
+ pageCount,
+ gcdVERTEX_START / gcmSIZEOF(gctUINT32),
+ &index
+ ));
+ }
+
+ /* Walk the heap list. */
+ for (; !gotIt && (index < Mmu->pageTableEntries);)
+ {
+ /* Check the node type. */
+ switch (gcmENTRY_TYPE(_ReadPageEntry(&map[index])))
+ {
+ case gcvMMU_SINGLE:
+ /* Single odes are valid if we only need 1 page. */
+ if (pageCount == 1)
+ {
+ gotIt = gcvTRUE;
+ }
+ else
+ {
+ /* Move to next node. */
+ previous = index;
+ index = _ReadPageEntry(&map[index]) >> 8;
+ }
+ break;
+
+ case gcvMMU_FREE:
+ /* Test if the node has enough space. */
+ if (pageCount <= (_ReadPageEntry(&map[index]) >> 8))
+ {
+ gotIt = gcvTRUE;
+ }
+ else
+ {
+ /* Move to next node. */
+ previous = index;
+ index = _ReadPageEntry(&map[index + 1]);
+ }
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", index);
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+
+ /* Test if we are out of memory. */
+ if (index >= Mmu->pageTableEntries)
+ {
+ if (Mmu->freeNodes)
+ {
+ /* Time to move out the trash! */
+ gcmkONERROR(_Collect(Mmu));
+
+ /* We are going to search from start, so reset previous to start. */
+ previous = ~0U;
+ }
+ else
+ {
+ /* Out of resources. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+ }
+
+ switch (gcmENTRY_TYPE(_ReadPageEntry(&map[index])))
+ {
+ case gcvMMU_SINGLE:
+ /* Unlink single node from free list. */
+ gcmkONERROR(
+ _Link(Mmu, previous, _ReadPageEntry(&map[index]) >> 8));
+ break;
+
+ case gcvMMU_FREE:
+ /* Check how many pages will be left. */
+ left = (_ReadPageEntry(&map[index]) >> 8) - pageCount;
+ switch (left)
+ {
+ case 0:
+ /* The entire node is consumed, just unlink it. */
+ gcmkONERROR(
+ _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(&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(&map[index], (left << 8) | gcvMMU_FREE);
+ index += left;
+ break;
+ }
+ break;
+ }
+
+ /* Mark node as used. */
+ gcmkONERROR(_FillPageTable(&map[index], pageCount, gcvMMU_USED));
+
+ /* Return pointer to page table. */
+ *PageTable = &Mmu->pageTableLogical[index];
+
+ /* Build virtual address. */
+ if (Mmu->hardware->mmuVersion == 0)
+ {
+ gcmkONERROR(
+ gckHARDWARE_BuildVirtualAddress(Mmu->hardware, index, 0, &address));
+ }
+ else
+ {
+ gctUINT32 masterOffset = index / gcdMMU_STLB_4K_ENTRY_NUM
+ + Mmu->dynamicMappingStart;
+ gctUINT32 slaveOffset = index % gcdMMU_STLB_4K_ENTRY_NUM;
+
+ address = (masterOffset << gcdMMU_MTLB_SHIFT)
+ | (slaveOffset << gcdMMU_STLB_4K_SHIFT);
+ }
+
+ if (Address != gcvNULL)
+ {
+ *Address = address;
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*PageTable=0x%x *Address=%08x",
+ *PageTable, gcmOPT_VALUE(Address));
+ return gcvSTATUS_OK;
+
+OnError:
+
+ if (mutex)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckMMU_FreePages
+**
+** Free pages inside the page table.
+**
+** INPUT:
+**
+** gckMMU Mmu
+** Pointer to an gckMMU object.
+**
+** gctPOINTER PageTable
+** Base address of the page table to free.
+**
+** gctSIZE_T PageCount
+** Number of pages to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+_FreePages(
+ IN gckMMU Mmu,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ )
+{
+ gctUINT32_PTR node;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctUINT32 pageCount;
+
+ gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=%lu",
+ Mmu, PageTable, PageCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+
+ 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;
+
+#if gcdMMU_CLEAR_VALUE
+ if (Mmu->hardware->mmuVersion == 0)
+ {
+ _FillPageTable(PageTable, pageCount, gcdMMU_CLEAR_VALUE);
+ }
+#endif
+
+ if (PageCount == 1)
+ {
+ /* Single page node. */
+ _WritePageEntry(node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
+#if gcdUSE_MMU_EXCEPTION
+ /* Enable exception */
+ _WritePageEntry(PageTable, (1 << 1));
+#endif
+ }
+ else
+ {
+ /* Mark the node as free. */
+ _WritePageEntry(node, (pageCount << 8) | gcvMMU_FREE);
+ _WritePageEntry(node + 1, ~0U);
+
+#if gcdUSE_MMU_EXCEPTION
+ /* Enable exception */
+ gcmkVERIFY_OK(_FillPageTable(PageTable, pageCount, 1 << 1));
+#endif
+ }
+
+ /* We have free nodes. */
+ Mmu->freeNodes = gcvTRUE;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+ acquired = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckMMU_AllocatePages(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ )
+{
+ return gckMMU_AllocatePagesEx(
+ Mmu, PageCount, gcvSURF_TYPE_UNKNOWN, PageTable, Address);
+}
+
+gceSTATUS
+gckMMU_AllocatePagesEx(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ IN gceSURF_TYPE Type,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ )
+{
+#if gcdMIRROR_PAGETABLE
+ gceSTATUS status;
+ gctPOINTER pageTable;
+ gctUINT32 address;
+ gctINT i;
+ gckMMU mmu;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL allocated = gcvFALSE;
+
+ gckOS_AcquireMutex(Mmu->os, mirrorPageTableMutex, gcvINFINITE);
+ acquired = gcvTRUE;
+
+ /* Allocate page table for current MMU. */
+ for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
+ {
+ if (Mmu == mirrorPageTable->mmus[i])
+ {
+ gcmkONERROR(_AllocatePages(Mmu, PageCount, Type, PageTable, Address));
+ allocated = gcvTRUE;
+ }
+ }
+
+ /* Allocate page table for other MMUs. */
+ for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
+ {
+ mmu = mirrorPageTable->mmus[i];
+
+ if (Mmu != mmu)
+ {
+ gcmkONERROR(_AllocatePages(mmu, PageCount, Type, &pageTable, &address));
+ gcmkASSERT(address == *Address);
+ }
+ }
+
+ gckOS_ReleaseMutex(Mmu->os, mirrorPageTableMutex);
+ acquired = gcvFALSE;
+
+ return gcvSTATUS_OK;
+OnError:
+
+ if (allocated)
+ {
+ /* Page tables for multiple GPU always keep the same. So it is impossible
+ * the fist one allocates successfully but others fail.
+ */
+ gcmkASSERT(0);
+ }
+
+ if (acquired)
+ {
+ gckOS_ReleaseMutex(Mmu->os, mirrorPageTableMutex);
+ }
+
+ return status;
+#else
+ return _AllocatePages(Mmu, PageCount, Type, PageTable, Address);
+#endif
+}
+
+gceSTATUS
+gckMMU_FreePages(
+ IN gckMMU Mmu,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ )
+{
+#if gcdMIRROR_PAGETABLE
+ gctINT i;
+ gctUINT32 offset;
+ gckMMU mmu;
+
+ gckOS_AcquireMutex(Mmu->os, mirrorPageTableMutex, gcvINFINITE);
+
+ gcmkVERIFY_OK(_FreePages(Mmu, PageTable, PageCount));
+
+ offset = (gctUINT32)PageTable - (gctUINT32)Mmu->pageTableLogical;
+
+ for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
+ {
+ mmu = mirrorPageTable->mmus[i];
+
+ if (mmu != Mmu)
+ {
+ gcmkVERIFY_OK(_FreePages(mmu, mmu->pageTableLogical + offset/4, PageCount));
+ }
+ }
+
+ gckOS_ReleaseMutex(Mmu->os, mirrorPageTableMutex);
+
+ return gcvSTATUS_OK;
+#else
+ return _FreePages(Mmu, PageTable, PageCount);
+#endif
+}
+
+gceSTATUS
+gckMMU_SetPage(
+ IN gckMMU Mmu,
+ IN gctPHYS_ADDR_T PageAddress,
+ IN gctUINT32 *PageEntry
+ )
+{
+#if gcdMIRROR_PAGETABLE
+ gctUINT32_PTR pageEntry;
+ gctINT i;
+ gckMMU mmu;
+ gctUINT32 offset = (gctUINT32)PageEntry - (gctUINT32)Mmu->pageTableLogical;
+#endif
+ gctUINT32 addressExt;
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
+ gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
+
+ /* [31:0]. */
+ address = (gctUINT32)(PageAddress & 0xFFFFFFFF);
+ /* [39:32]. */
+ addressExt = (gctUINT32)((PageAddress >> 32) & 0xFF);
+
+ if (Mmu->hardware->mmuVersion == 0)
+ {
+ _WritePageEntry(PageEntry, address);
+ }
+ else
+ {
+ _WritePageEntry(PageEntry, _SetPage(address, addressExt));
+ }
+
+#if gcdMIRROR_PAGETABLE
+ for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
+ {
+ mmu = mirrorPageTable->mmus[i];
+
+ if (mmu != Mmu)
+ {
+ pageEntry = mmu->pageTableLogical + offset / 4;
+
+ if (mmu->hardware->mmuVersion == 0)
+ {
+ _WritePageEntry(pageEntry, address);
+ }
+ else
+ {
+ _WritePageEntry(pageEntry, _SetPage(address, addressExt));
+ }
+ }
+
+ }
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+gckMMU_GetPageEntry(
+ IN gckMMU Mmu,
+ IN gctUINT32 Address,
+ IN gctUINT32_PTR *PageTable
+ )
+{
+ gceSTATUS status;
+ 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", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT((Address & 0xFFF) == 0);
+
+ stlb = stlbs[offset];
+
+ if (stlb == gcvNULL)
+ {
+ gcmkONERROR(_AllocateStlb(Mmu->os, &stlb));
+
+ mtlbEntry = stlb->physBase
+ | gcdMMU_MTLB_4K_PAGE
+ | gcdMMU_MTLB_PRESENT
+ ;
+
+ 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:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+_CheckMap(
+ IN gckMMU Mmu
+ )
+{
+ gceSTATUS status;
+ gctUINT32_PTR map = Mmu->mapLogical;
+ gctUINT32 index;
+
+ for (index = Mmu->heapList; index < Mmu->pageTableEntries;)
+ {
+ /* 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);
+ }
+ }
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gckMMU_FlatMapping(
+ IN gckMMU Mmu,
+ IN gctUINT32 Physical
+ )
+{
+ gceSTATUS status;
+ gctUINT32 index = _AddressToIndex(Mmu, Physical);
+ gctUINT32 i;
+ gctBOOL gotIt = gcvFALSE;
+ gctUINT32_PTR map = Mmu->mapLogical;
+ gctUINT32 previous = ~0U;
+ gctUINT32_PTR pageTable;
+
+ gckMMU_GetPageEntry(Mmu, Physical, &pageTable);
+
+ _WritePageEntry(pageTable, _SetPage(Physical));
+
+ if (map)
+ {
+ /* 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])))
+ {
+ 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;
+ }
+ }
+
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Roll back. */
+ return status;
+}
+
+
+
+gceSTATUS
+gckMMU_FreePagesEx(
+ IN gckMMU Mmu,
+ IN gctUINT32 Address,
+ IN gctSIZE_T PageCount
+ )
+{
+ gctUINT32_PTR node;
+ gceSTATUS status;
+
+#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);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+
+ /* Get the node by index. */
+ node = Mmu->mapLogical + _AddressToIndex(Mmu, Address);
+
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+
+ if (PageCount == 1)
+ {
+ /* 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);
+ }
+
+ /* We have free nodes. */
+ Mmu->freeNodes = gcvTRUE;
+
+#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->pageTableMutex));
+
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+gceSTATUS
+gckMMU_Flush(
+ IN gckMMU Mmu,
+ IN gceSURF_TYPE Type
+ )
+{
+ gckHARDWARE hardware;
+ 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++)
+ {
+ hardware = sharedPageTable->hardwares[i];
+ if (hardware)
+ {
+ gcmkVERIFY_OK(gckOS_AtomSetMask(hardware->pageTableDirty, mask));
+ }
+ }
+#elif gcdMIRROR_PAGETABLE
+ for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
+ {
+ hardware = mirrorPageTable->hardwares[i];
+
+ /* Notify cores who use this page table. */
+ gcmkVERIFY_OK(
+ gckOS_AtomSetMask(hardware->pageTableDirty, mask));
+ }
+#else
+ hardware = Mmu->hardware;
+ gcmkVERIFY_OK(
+ gckOS_AtomSetMask(hardware->pageTableDirty, mask));
+#endif
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckMMU_DumpPageTableEntry(
+ IN gckMMU Mmu,
+ 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;
+
+ if (mtlb >= Mmu->dynamicMappingStart)
+ {
+ stlb = (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
+
+ pageTable = Mmu->pageTableLogical;
+
+ index = (mtlb - Mmu->dynamicMappingStart)
+ * gcdMMU_STLB_4K_ENTRY_NUM
+ + stlb;
+
+ 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;
+}
+
+/******************************************************************************
+****************************** T E S T C O D E ******************************
+******************************************************************************/
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c
new file mode 100644
index 000000000000..62f5c8a50499
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c
@@ -0,0 +1,556 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdENABLE_VG
+
+#define _GC_OBJ_ZONE gcvZONE_MMU
+
+/*******************************************************************************
+**
+** gckVGMMU_Construct
+**
+** Construct a new gckVGMMU object.
+**
+** INPUT:
+**
+** gckVGKERNEL Kernel
+** Pointer to an gckVGKERNEL object.
+**
+** gctSIZE_T MmuSize
+** Number of bytes for the page table.
+**
+** OUTPUT:
+**
+** gckVGMMU * Mmu
+** Pointer to a variable that receives the gckVGMMU object pointer.
+*/
+gceSTATUS gckVGMMU_Construct(
+ IN gckVGKERNEL Kernel,
+ IN gctUINT32 MmuSize,
+ OUT gckVGMMU * Mmu
+ )
+{
+ gckOS os;
+ gckVGHARDWARE hardware;
+ gceSTATUS status;
+ gckVGMMU mmu;
+ gctUINT32 * pageTable;
+ gctUINT32 i;
+
+ gcmkHEADER_ARG("Kernel=0x%x MmuSize=0x%x Mmu=0x%x", Kernel, MmuSize, Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(MmuSize > 0);
+ gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Extract the gckVGHARDWARE object pointer. */
+ hardware = Kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Allocate memory for the gckVGMMU object. */
+ status = gckOS_Allocate(os, sizeof(struct _gckVGMMU), (gctPOINTER *) &mmu);
+
+ if (status < 0)
+ {
+ /* Error. */
+ gcmkFATAL(
+ "%s(%d): could not allocate gckVGMMU object.",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER();
+ return status;
+ }
+
+ /* Initialize the gckVGMMU object. */
+ mmu->object.type = gcvOBJ_MMU;
+ mmu->os = os;
+ mmu->hardware = hardware;
+
+ /* Create the mutex. */
+ status = gckOS_CreateMutex(os, &mmu->mutex);
+
+ if (status < 0)
+ {
+ /* Roll back. */
+ mmu->object.type = gcvOBJ_UNKNOWN;
+ gcmkVERIFY_OK(gckOS_Free(os, mmu));
+
+ gcmkFOOTER();
+ /* Error. */
+ return status;
+ }
+
+ /* Allocate the page table. */
+ mmu->pageTableSize = (gctUINT32)MmuSize;
+ status = gckOS_AllocateContiguous(os,
+ gcvFALSE,
+ &mmu->pageTableSize,
+ &mmu->pageTablePhysical,
+ &mmu->pageTableLogical);
+
+ if (status < 0)
+ {
+ /* Roll back. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex));
+
+ mmu->object.type = gcvOBJ_UNKNOWN;
+ gcmkVERIFY_OK(gckOS_Free(os, mmu));
+
+ /* Error. */
+ gcmkFATAL(
+ "%s(%d): could not allocate page table.",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER();
+ return status;
+ }
+
+ /* Compute number of entries in page table. */
+ mmu->entryCount = (gctUINT32)mmu->pageTableSize / sizeof(gctUINT32);
+ mmu->entry = 0;
+
+ /* Mark the entire page table as available. */
+ pageTable = (gctUINT32 *) mmu->pageTableLogical;
+ for (i = 0; i < mmu->entryCount; i++)
+ {
+ pageTable[i] = (gctUINT32)~0;
+ }
+
+ /* Set page table address. */
+ status = gckVGHARDWARE_SetMMU(hardware, mmu->pageTableLogical);
+
+ if (status < 0)
+ {
+ /* Free the page table. */
+ gcmkVERIFY_OK(gckOS_FreeContiguous(mmu->os,
+ mmu->pageTablePhysical,
+ mmu->pageTableLogical,
+ mmu->pageTableSize));
+
+ /* Roll back. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex));
+
+ mmu->object.type = gcvOBJ_UNKNOWN;
+ gcmkVERIFY_OK(gckOS_Free(os, mmu));
+
+ /* Error. */
+ gcmkFATAL(
+ "%s(%d): could not program page table.",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER();
+ return status;
+ }
+
+ /* Return the gckVGMMU object pointer. */
+ *Mmu = mmu;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_MMU,
+ "%s(%d): %u entries at %p.(0x%08X)\n",
+ __FUNCTION__, __LINE__,
+ mmu->entryCount,
+ mmu->pageTableLogical,
+ mmu->pageTablePhysical
+ );
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGMMU_Destroy
+**
+** Destroy a nAQMMU object.
+**
+** INPUT:
+**
+** gckVGMMU Mmu
+** Pointer to an gckVGMMU object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckVGMMU_Destroy(
+ IN gckVGMMU Mmu
+ )
+{
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+ /* Free the page table. */
+ gcmkVERIFY_OK(gckOS_FreeContiguous(Mmu->os,
+ Mmu->pageTablePhysical,
+ Mmu->pageTableLogical,
+ Mmu->pageTableSize));
+
+ /* Roll back. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->mutex));
+
+ /* Mark the gckVGMMU object as unknown. */
+ Mmu->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckVGMMU object. */
+ gcmkVERIFY_OK(gckOS_Free(Mmu->os, Mmu));
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGMMU_AllocatePages
+**
+** Allocate pages inside the page table.
+**
+** INPUT:
+**
+** gckVGMMU Mmu
+** Pointer to an gckVGMMU object.
+**
+** gctSIZE_T PageCount
+** Number of pages to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * PageTable
+** Pointer to a variable that receives the base address of the page
+** table.
+**
+** gctUINT32 * Address
+** Pointer to a variable that receives the hardware specific address.
+*/
+gceSTATUS gckVGMMU_AllocatePages(
+ IN gckVGMMU Mmu,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ )
+{
+ gceSTATUS status;
+ gctUINT32 tail, index, i;
+ gctUINT32 * table;
+ gctBOOL allocated = gcvFALSE;
+
+ gcmkHEADER_ARG("Mmu=0x%x PageCount=0x%x PageTable=0x%x Address=0x%x",
+ Mmu, PageCount, PageTable, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_MMU,
+ "%s(%d): %u pages.\n",
+ __FUNCTION__, __LINE__,
+ PageCount
+ );
+
+ if (PageCount > Mmu->entryCount)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_MMU,
+ "%s(%d): page table too small for %u pages.\n",
+ __FUNCTION__, __LINE__,
+ PageCount
+ );
+
+ gcmkFOOTER_NO();
+ /* Not enough pages avaiable. */
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ /* Grab the mutex. */
+ status = gckOS_AcquireMutex(Mmu->os, Mmu->mutex, gcvINFINITE);
+
+ if (status < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_MMU,
+ "%s(%d): could not acquire mutex.\n"
+ ,__FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER();
+ /* Error. */
+ return status;
+ }
+
+ /* Compute the tail for this allocation. */
+ tail = Mmu->entryCount - (gctUINT32)PageCount;
+
+ /* Walk all entries until we find enough slots. */
+ for (index = Mmu->entry; index <= tail;)
+ {
+ /* Access page table. */
+ table = (gctUINT32 *) Mmu->pageTableLogical + index;
+
+ /* See if all slots are available. */
+ for (i = 0; i < PageCount; i++, table++)
+ {
+ if (*table != ~0)
+ {
+ /* Start from next slot. */
+ index += i + 1;
+ break;
+ }
+ }
+
+ if (i == PageCount)
+ {
+ /* Bail out if we have enough page entries. */
+ allocated = gcvTRUE;
+ break;
+ }
+ }
+
+ if (!allocated)
+ {
+ if (status >= 0)
+ {
+ /* Walk all entries until we find enough slots. */
+ for (index = 0; index <= tail;)
+ {
+ /* Access page table. */
+ table = (gctUINT32 *) Mmu->pageTableLogical + index;
+
+ /* See if all slots are available. */
+ for (i = 0; i < PageCount; i++, table++)
+ {
+ if (*table != ~0)
+ {
+ /* Start from next slot. */
+ index += i + 1;
+ break;
+ }
+ }
+
+ if (i == PageCount)
+ {
+ /* Bail out if we have enough page entries. */
+ allocated = gcvTRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!allocated && (status >= 0))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_MMU,
+ "%s(%d): not enough free pages for %u pages.\n",
+ __FUNCTION__, __LINE__,
+ PageCount
+ );
+
+ /* Not enough empty slots available. */
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ if (status >= 0)
+ {
+ /* Build virtual address. */
+ status = gckVGHARDWARE_BuildVirtualAddress(Mmu->hardware,
+ index,
+ 0,
+ Address);
+
+ if (status >= 0)
+ {
+ /* Update current entry into page table. */
+ Mmu->entry = index + (gctUINT32)PageCount;
+
+ /* Return pointer to page table. */
+ *PageTable = (gctUINT32 *) Mmu->pageTableLogical + index;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_MMU,
+ "%s(%d): allocated %u pages at index %u (0x%08X) @ %p.\n",
+ __FUNCTION__, __LINE__,
+ PageCount,
+ index,
+ *Address,
+ *PageTable
+ );
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->mutex));
+ gcmkFOOTER();
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGMMU_FreePages
+**
+** Free pages inside the page table.
+**
+** INPUT:
+**
+** gckVGMMU Mmu
+** Pointer to an gckVGMMU object.
+**
+** gctPOINTER PageTable
+** Base address of the page table to free.
+**
+** gctSIZE_T PageCount
+** Number of pages to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckVGMMU_FreePages(
+ IN gckVGMMU Mmu,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ )
+{
+ gctUINT32 * table;
+
+ gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=0x%x",
+ Mmu, PageTable, PageCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_MMU,
+ "%s(%d): freeing %u pages at index %u @ %p.\n",
+ __FUNCTION__, __LINE__,
+ PageCount,
+ ((gctUINT32 *) PageTable - (gctUINT32 *) Mmu->pageTableLogical),
+ PageTable
+ );
+
+ /* Convert pointer. */
+ table = (gctUINT32 *) PageTable;
+
+ /* Mark the page table entries as available. */
+ while (PageCount-- > 0)
+ {
+ *table++ = (gctUINT32)~0;
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVGMMU_SetPage(
+ IN gckVGMMU Mmu,
+ IN gctUINT32 PageAddress,
+ IN gctUINT32 *PageEntry
+ )
+{
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
+ gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
+
+ *PageEntry = PageAddress;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVGMMU_Flush(
+ IN gckVGMMU Mmu
+ )
+{
+ gckVGHARDWARE hardware;
+
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ hardware = Mmu->hardware;
+ gcmkVERIFY_OK(
+ gckOS_AtomSet(hardware->os, hardware->pageTableDirty, 1));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#endif /* gcdENABLE_VG */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c
new file mode 100644
index 000000000000..5246cfcab02c
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c
@@ -0,0 +1,381 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_POWER
+
+/******************************************************************************\
+************************ Dynamic Voltage Frequency Setting *********************
+\******************************************************************************/
+#if gcdDVFS
+static gctUINT32
+_GetLoadHistory(
+ IN gckDVFS Dvfs,
+ IN gctUINT32 Select,
+ IN gctUINT32 Index
+)
+{
+ return Dvfs->loads[Index];
+}
+
+static void
+_IncreaseScale(
+ IN gckDVFS Dvfs,
+ IN gctUINT32 Load,
+ OUT gctUINT8 *Scale
+ )
+{
+ if (Dvfs->currentScale < 32)
+ {
+ *Scale = Dvfs->currentScale + 8;
+ }
+ else
+ {
+ *Scale = Dvfs->currentScale + 8;
+ *Scale = gcmMIN(64, *Scale);
+ }
+}
+
+static void
+_RecordFrequencyHistory(
+ gckDVFS Dvfs,
+ gctUINT32 Frequency
+ )
+{
+ gctUINT32 i = 0;
+
+ struct _FrequencyHistory *history = Dvfs->frequencyHistory;
+
+ for (i = 0; i < 16; i++)
+ {
+ if (history->frequency == Frequency)
+ {
+ break;
+ }
+
+ if (history->frequency == 0)
+ {
+ history->frequency = Frequency;
+ break;
+ }
+
+ history++;
+ }
+
+ if (i < 16)
+ {
+ history->count++;
+ }
+}
+
+static gctUINT32
+_GetFrequencyHistory(
+ gckDVFS Dvfs,
+ gctUINT32 Frequency
+ )
+{
+ gctUINT32 i = 0;
+
+ struct _FrequencyHistory * history = Dvfs->frequencyHistory;
+
+ for (i = 0; i < 16; i++)
+ {
+ if (history->frequency == Frequency)
+ {
+ break;
+ }
+
+ history++;
+ }
+
+ if (i < 16)
+ {
+ return history->count;
+ }
+
+ return 0;
+}
+
+static void
+_Policy(
+ IN gckDVFS Dvfs,
+ IN gctUINT32 Load,
+ OUT gctUINT8 *Scale
+ )
+{
+ gctUINT8 load[4], nextLoad;
+ gctUINT8 scale;
+
+ /* Last 4 history. */
+ load[0] = (Load & 0xFF);
+ load[1] = (Load & 0xFF00) >> 8;
+ load[2] = (Load & 0xFF0000) >> 16;
+ load[3] = (Load & 0xFF000000) >> 24;
+
+ /* Determine target scale. */
+ if (load[0] > 54)
+ {
+ _IncreaseScale(Dvfs, Load, &scale);
+ }
+ else
+ {
+ nextLoad = (load[0] + load[1] + load[2] + load[3])/4;
+
+ scale = Dvfs->currentScale * (nextLoad) / 54;
+
+ scale = gcmMAX(1, scale);
+ scale = gcmMIN(64, scale);
+ }
+
+ Dvfs->totalConfig++;
+
+ Dvfs->loads[(load[0]-1)/8]++;
+
+ *Scale = scale;
+
+
+ if (Dvfs->totalConfig % 100 == 0)
+ {
+ gcmkPRINT("=======================================================");
+ gcmkPRINT("GPU Load: %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d",
+ 8, 16, 24, 32, 40, 48, 56, 64);
+ gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d",
+ _GetLoadHistory(Dvfs,2, 0),
+ _GetLoadHistory(Dvfs,2, 1),
+ _GetLoadHistory(Dvfs,2, 2),
+ _GetLoadHistory(Dvfs,2, 3),
+ _GetLoadHistory(Dvfs,2, 4),
+ _GetLoadHistory(Dvfs,2, 5),
+ _GetLoadHistory(Dvfs,2, 6),
+ _GetLoadHistory(Dvfs,2, 7)
+ );
+
+ gcmkPRINT("Frequency(MHz) %-8d %-8d %-8d %-8d %-8d",
+ 58, 120, 240, 360, 480);
+ gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d",
+ _GetFrequencyHistory(Dvfs, 58),
+ _GetFrequencyHistory(Dvfs,120),
+ _GetFrequencyHistory(Dvfs,240),
+ _GetFrequencyHistory(Dvfs,360),
+ _GetFrequencyHistory(Dvfs,480)
+ );
+ }
+}
+
+static void
+_TimerFunction(
+ gctPOINTER Data
+ )
+{
+ gceSTATUS status;
+ gckDVFS dvfs = (gckDVFS) Data;
+ gckHARDWARE hardware = dvfs->hardware;
+ gctUINT32 value;
+ gctUINT32 frequency;
+ gctUINT8 scale;
+ gctUINT32 t1, t2, consumed;
+
+ gckOS_GetTicks(&t1);
+
+ gcmkONERROR(gckHARDWARE_QueryLoad(hardware, &value));
+
+ /* determine target sacle. */
+ _Policy(dvfs, value, &scale);
+
+ /* Set frequency and voltage. */
+ gcmkONERROR(gckOS_SetGPUFrequency(hardware->os, hardware->core, scale));
+
+ /* Query real frequency. */
+ gcmkONERROR(
+ gckOS_QueryGPUFrequency(hardware->os,
+ hardware->core,
+ &frequency,
+ &dvfs->currentScale));
+
+ _RecordFrequencyHistory(dvfs, frequency);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_POWER,
+ "Current frequency = %d",
+ frequency);
+
+ /* Set period. */
+ gcmkONERROR(gckHARDWARE_SetDVFSPeroid(hardware, frequency));
+
+OnError:
+ /* Determine next querying time. */
+ gckOS_GetTicks(&t2);
+
+ consumed = gcmMIN(((long)t2 - (long)t1), 5);
+
+ if (dvfs->stop == gcvFALSE)
+ {
+ gcmkVERIFY_OK(gckOS_StartTimer(hardware->os,
+ dvfs->timer,
+ dvfs->pollingTime - consumed));
+ }
+
+ return;
+}
+
+gceSTATUS
+gckDVFS_Construct(
+ IN gckHARDWARE Hardware,
+ OUT gckDVFS * Dvfs
+ )
+{
+ gceSTATUS status;
+ gctPOINTER pointer;
+ gckDVFS dvfs = gcvNULL;
+ gckOS os = Hardware->os;
+
+ gcmkHEADER_ARG("Hardware=0x%X", Hardware);
+
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
+
+ /* Allocate a gckDVFS manager. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckDVFS), &pointer));
+
+ gckOS_ZeroMemory(pointer, gcmSIZEOF(struct _gckDVFS));
+
+ dvfs = pointer;
+
+ /* Initialization. */
+ dvfs->hardware = Hardware;
+ dvfs->pollingTime = gcdDVFS_POLLING_TIME;
+ dvfs->os = Hardware->os;
+ dvfs->currentScale = 64;
+
+ /* Create a polling timer. */
+ gcmkONERROR(gckOS_CreateTimer(os, _TimerFunction, pointer, &dvfs->timer));
+
+ /* Initialize frequency and voltage adjustment helper. */
+ gcmkONERROR(gckOS_PrepareGPUFrequency(os, Hardware->core));
+
+ /* Return result. */
+ *Dvfs = dvfs;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (dvfs)
+ {
+ if (dvfs->timer)
+ {
+ gcmkVERIFY_OK(gckOS_DestroyTimer(os, dvfs->timer));
+ }
+
+ gcmkOS_SAFE_FREE(os, dvfs);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckDVFS_Destroy(
+ IN gckDVFS Dvfs
+ )
+{
+ gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
+ gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
+
+ /* Deinitialize helper fuunction. */
+ gcmkVERIFY_OK(gckOS_FinishGPUFrequency(Dvfs->os, Dvfs->hardware->core));
+
+ /* DestroyTimer. */
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Dvfs->os, Dvfs->timer));
+
+ gcmkOS_SAFE_FREE(Dvfs->os, Dvfs);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckDVFS_Start(
+ IN gckDVFS Dvfs
+ )
+{
+ gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
+ gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
+
+ gckHARDWARE_InitDVFS(Dvfs->hardware);
+
+ Dvfs->stop = gcvFALSE;
+
+ gckOS_StartTimer(Dvfs->os, Dvfs->timer, Dvfs->pollingTime);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckDVFS_Stop(
+ IN gckDVFS Dvfs
+ )
+{
+ gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
+ gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
+
+ Dvfs->stop = gcvTRUE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h
new file mode 100644
index 000000000000..a2b5e771a15d
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_precomp_h_
+#define __gc_hal_kernel_precomp_h_
+
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel.h"
+
+#endif /* __gc_hal_kernel_precomp_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security.c
new file mode 100644
index 000000000000..8f738f166ef6
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security.c
@@ -0,0 +1,284 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+
+
+
+#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;
+#if defined(LINUX)
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address;
+#endif
+ 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, &physical));
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ iface.u.Execute.command_buffer = (gctUINT32 *)address;
+#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;
+#if defined(LINUX)
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address;
+#endif
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_MAP_MEMORY;
+
+#if defined(LINUX)
+ gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os, PhysicalArray, &physical));
+ gcmkSAFECASTPHYSADDRT(address, physical);
+ iface.u.MapMemory.physicals = (gctUINT32 *)address;
+#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
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
new file mode 100644
index 000000000000..f992faabe9ce
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
@@ -0,0 +1,909 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdENABLE_VG
+
+#define _GC_OBJ_ZONE gcvZONE_VG
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckKERNEL_Construct
+**
+** Construct a new gckKERNEL object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN gctPOINTER Context
+** Pointer to a driver defined context.
+**
+** OUTPUT:
+**
+** gckKERNEL * Kernel
+** Pointer to a variable that will hold the pointer to the gckKERNEL
+** object.
+*/
+gceSTATUS gckVGKERNEL_Construct(
+ IN gckOS Os,
+ IN gctPOINTER Context,
+ IN gckKERNEL inKernel,
+ OUT gckVGKERNEL * Kernel
+ )
+{
+ gceSTATUS status;
+ gckVGKERNEL kernel = gcvNULL;
+
+ gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
+
+ do
+ {
+ /* Allocate the gckKERNEL object. */
+ gcmkERR_BREAK(gckOS_Allocate(
+ Os,
+ sizeof(struct _gckVGKERNEL),
+ (gctPOINTER *) &kernel
+ ));
+
+ /* Initialize the gckKERNEL object. */
+ kernel->object.type = gcvOBJ_KERNEL;
+ kernel->os = Os;
+ kernel->context = Context;
+ kernel->hardware = gcvNULL;
+ kernel->interrupt = gcvNULL;
+ kernel->command = gcvNULL;
+ kernel->mmu = gcvNULL;
+ kernel->kernel = inKernel;
+
+ /* Construct the gckVGHARDWARE object. */
+ gcmkERR_BREAK(gckVGHARDWARE_Construct(
+ Os, &kernel->hardware
+ ));
+
+ /* Set pointer to gckKERNEL object in gckVGHARDWARE object. */
+ kernel->hardware->kernel = kernel;
+
+ /* Construct the gckVGINTERRUPT object. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Construct(
+ kernel, &kernel->interrupt
+ ));
+
+ /* Construct the gckVGCOMMAND object. */
+ gcmkERR_BREAK(gckVGCOMMAND_Construct(
+ kernel, gcmKB2BYTES(8), gcmKB2BYTES(2), &kernel->command
+ ));
+
+ /* Construct the gckVGMMU object. */
+ gcmkERR_BREAK(gckVGMMU_Construct(
+ kernel, gcmMB2BYTES(1), &kernel->mmu
+ ));
+
+ /* Return pointer to the gckKERNEL object. */
+ *Kernel = kernel;
+
+ gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Roll back. */
+ if (kernel != gcvNULL)
+ {
+ if (kernel->mmu != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckVGMMU_Destroy(kernel->mmu));
+ }
+
+ if (kernel->command != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckVGCOMMAND_Destroy(kernel->command));
+ }
+
+ if (kernel->interrupt != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckVGINTERRUPT_Destroy(kernel->interrupt));
+ }
+
+ if (kernel->hardware != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckVGHARDWARE_Destroy(kernel->hardware));
+ }
+
+ gcmkVERIFY_OK(gckOS_Free(Os, kernel));
+ }
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Destroy
+**
+** Destroy an gckKERNEL object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckVGKERNEL_Destroy(
+ IN gckVGKERNEL Kernel
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ do
+ {
+ /* Destroy the gckVGMMU object. */
+ if (Kernel->mmu != gcvNULL)
+ {
+ gcmkERR_BREAK(gckVGMMU_Destroy(Kernel->mmu));
+ Kernel->mmu = gcvNULL;
+ }
+
+ /* Destroy the gckVGCOMMAND object. */
+ if (Kernel->command != gcvNULL)
+ {
+ gcmkERR_BREAK(gckVGCOMMAND_Destroy(Kernel->command));
+ Kernel->command = gcvNULL;
+ }
+
+ /* Destroy the gckVGINTERRUPT object. */
+ if (Kernel->interrupt != gcvNULL)
+ {
+ gcmkERR_BREAK(gckVGINTERRUPT_Destroy(Kernel->interrupt));
+ Kernel->interrupt = gcvNULL;
+ }
+
+ /* Destroy the gckVGHARDWARE object. */
+ if (Kernel->hardware != gcvNULL)
+ {
+ gcmkERR_BREAK(gckVGHARDWARE_Destroy(Kernel->hardware));
+ Kernel->hardware = gcvNULL;
+ }
+
+ /* Mark the gckKERNEL object as unknown. */
+ Kernel->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckKERNEL object. */
+ gcmkERR_BREAK(gckOS_Free(Kernel->os, Kernel));
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_AllocateLinearMemory
+**
+** Function walks all required memory pools and allocates the requested
+** amount of video memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcePOOL * Pool
+** Pointer the desired memory pool.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** gctSIZE_T Alignment
+** Required buffer alignment.
+**
+** gceSURF_TYPE Type
+** Surface type.
+**
+** OUTPUT:
+**
+** gcePOOL * Pool
+** Pointer to the actual pool where the memory was allocated.
+**
+** gcuVIDMEM_NODE_PTR * Node
+** Allocated node.
+*/
+gceSTATUS
+gckVGKERNEL_AllocateLinearMemory(
+ IN gckKERNEL Kernel,
+ IN OUT gcePOOL * Pool,
+ IN gctSIZE_T Bytes,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gcePOOL pool;
+ gceSTATUS status;
+ gckVIDMEM videoMemory;
+
+ /* Get initial pool. */
+ switch (pool = *Pool)
+ {
+ case gcvPOOL_DEFAULT:
+ case gcvPOOL_LOCAL:
+ pool = gcvPOOL_LOCAL_INTERNAL;
+ break;
+
+ case gcvPOOL_UNIFIED:
+ pool = gcvPOOL_SYSTEM;
+ break;
+
+ default:
+ break;
+ }
+
+ do
+ {
+ /* Verify the number of bytes to allocate. */
+ if (Bytes == 0)
+ {
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+
+ if (pool == gcvPOOL_VIRTUAL)
+ {
+ /* Create a gcuVIDMEM_NODE for virtual memory. */
+ gcmkERR_BREAK(gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Node));
+
+ /* Success. */
+ break;
+ }
+
+ else
+ {
+ /* Get pointer to gckVIDMEM object for pool. */
+ status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
+
+ if (status == gcvSTATUS_OK)
+ {
+ /* Allocate memory. */
+ status = gckVIDMEM_AllocateLinear(Kernel,
+ videoMemory,
+ Bytes,
+ Alignment,
+ Type,
+ (*Pool == gcvPOOL_SYSTEM),
+ Node);
+
+ if (status == gcvSTATUS_OK)
+ {
+ /* Memory allocated. */
+ break;
+ }
+ }
+ }
+
+ if (pool == gcvPOOL_LOCAL_INTERNAL)
+ {
+ /* Advance to external memory. */
+ pool = gcvPOOL_LOCAL_EXTERNAL;
+ }
+ else if (pool == gcvPOOL_LOCAL_EXTERNAL)
+ {
+ /* Advance to contiguous system memory. */
+ pool = gcvPOOL_SYSTEM;
+ }
+ else if (pool == gcvPOOL_SYSTEM)
+ {
+ /* Advance to virtual memory. */
+ pool = gcvPOOL_VIRTUAL;
+ }
+ else
+ {
+ /* Out of pools. */
+ break;
+ }
+ }
+ /* Loop only for multiple selection pools. */
+ while ((*Pool == gcvPOOL_DEFAULT)
+ || (*Pool == gcvPOOL_LOCAL)
+ || (*Pool == gcvPOOL_UNIFIED)
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Return pool used for allocation. */
+ *Pool = pool;
+ }
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Dispatch
+**
+** Dispatch a command received from the user HAL layer.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that defines the command to
+** be dispatched.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+** returned.
+*/
+gceSTATUS gckVGKERNEL_Dispatch(
+ IN gckKERNEL Kernel,
+ IN gctBOOL FromUser,
+ IN OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE * kernelInterface = Interface;
+ gctUINT32 processID;
+ gckKERNEL kernel = Kernel;
+ gctPOINTER info = gcvNULL;
+ gctPHYS_ADDR physical = gcvNULL;
+ gctPOINTER logical = gcvNULL;
+ gctSIZE_T bytes = 0;
+
+ gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+
+ /* Dispatch on command. */
+ switch (Interface->command)
+ {
+ case gcvHAL_QUERY_VIDEO_MEMORY:
+ /* Query video memory size. */
+ gcmkERR_BREAK(gckKERNEL_QueryVideoMemory(
+ Kernel, kernelInterface
+ ));
+ break;
+
+ case gcvHAL_QUERY_CHIP_IDENTITY:
+ /* Query chip identity. */
+ gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity(
+ Kernel->vg->hardware,
+ &kernelInterface->u.QueryChipIdentity.chipModel,
+ &kernelInterface->u.QueryChipIdentity.chipRevision,
+ &kernelInterface->u.QueryChipIdentity.chipFeatures,
+ &kernelInterface->u.QueryChipIdentity.chipMinorFeatures,
+ &kernelInterface->u.QueryChipIdentity.chipMinorFeatures2
+ ));
+ break;
+
+ case gcvHAL_QUERY_COMMAND_BUFFER:
+ /* Query command buffer information. */
+ gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer(
+ Kernel,
+ &kernelInterface->u.QueryCommandBuffer.information
+ ));
+ break;
+ case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
+ bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
+ /* Allocate non-paged memory. */
+ gcmkERR_BREAK(gckOS_AllocateNonPagedMemory(
+ Kernel->os,
+ gcvTRUE,
+ &bytes,
+ &physical,
+ &logical
+ ));
+
+ kernelInterface->u.AllocateNonPagedMemory.bytes = bytes;
+ kernelInterface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
+ kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
+ break;
+
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
+
+ /* Unmap user logical out of physical memory first. */
+ gcmkERR_BREAK(gckOS_UnmapUserLogical(
+ Kernel->os,
+ physical,
+ (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
+ gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
+ ));
+
+ /* Free non-paged memory. */
+ gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
+ Kernel->os,
+ (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
+ physical,
+ gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
+ ));
+
+ gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
+ break;
+
+ case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
+ bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
+ /* Allocate contiguous memory. */
+ gcmkERR_BREAK(gckOS_AllocateContiguous(
+ Kernel->os,
+ gcvTRUE,
+ &bytes,
+ &physical,
+ &logical
+ ));
+
+ kernelInterface->u.AllocateNonPagedMemory.bytes = bytes;
+ kernelInterface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
+ kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
+ /* Unmap user logical out of physical memory first. */
+ gcmkERR_BREAK(gckOS_UnmapUserLogical(
+ Kernel->os,
+ physical,
+ (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
+ gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
+ ));
+
+ /* Free contiguous memory. */
+ gcmkERR_BREAK(gckOS_FreeContiguous(
+ Kernel->os,
+ physical,
+ gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical),
+ (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes
+ ));
+
+ gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
+ break;
+
+ case gcvHAL_ALLOCATE_VIDEO_MEMORY:
+ gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED);
+ break;
+
+ case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
+ /* Allocate memory. */
+ gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
+ Kernel, processID,
+ &kernelInterface->u.AllocateLinearVideoMemory.pool,
+ kernelInterface->u.AllocateLinearVideoMemory.bytes,
+ kernelInterface->u.AllocateLinearVideoMemory.alignment,
+ kernelInterface->u.AllocateLinearVideoMemory.type,
+ kernelInterface->u.AllocateLinearVideoMemory.flag,
+ &kernelInterface->u.AllocateLinearVideoMemory.node
+ ));
+
+ break;
+
+ case gcvHAL_RELEASE_VIDEO_MEMORY:
+ /* Free video memory. */
+ gcmkERR_BREAK(gckKERNEL_ReleaseVideoMemory(
+ Kernel, processID,
+ (gctUINT32)kernelInterface->u.ReleaseVideoMemory.node
+ ));
+ {
+ gckVIDMEM_NODE nodeObject;
+
+ /* Remove record from process db. */
+ gcmkERR_BREAK(
+ gckKERNEL_RemoveProcessDB(Kernel, processID, gcvDB_VIDEO_MEMORY_LOCKED, (gctPOINTER)kernelInterface->u.ReleaseVideoMemory.node));
+
+ gcmkERR_BREAK(
+ gckVIDMEM_HANDLE_Lookup(Kernel, processID, (gctUINT32)kernelInterface->u.ReleaseVideoMemory.node, &nodeObject));
+
+ gckVIDMEM_NODE_Dereference(Kernel, nodeObject);
+ }
+
+ break;
+
+ case gcvHAL_MAP_MEMORY:
+ /* Map memory. */
+ gcmkERR_BREAK(gckKERNEL_MapMemory(
+ Kernel,
+ gcmINT2PTR(kernelInterface->u.MapMemory.physical),
+ (gctSIZE_T) kernelInterface->u.MapMemory.bytes,
+ &logical
+ ));
+ kernelInterface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
+ break;
+
+ case gcvHAL_UNMAP_MEMORY:
+ /* Unmap memory. */
+ gcmkERR_BREAK(gckKERNEL_UnmapMemory(
+ Kernel,
+ gcmINT2PTR(kernelInterface->u.MapMemory.physical),
+ (gctSIZE_T) kernelInterface->u.MapMemory.bytes,
+ gcmUINT64_TO_PTR(kernelInterface->u.MapMemory.logical)
+ ));
+ break;
+
+ case gcvHAL_MAP_USER_MEMORY:
+ /* Map user memory to DMA. */
+ gcmkERR_BREAK(gckOS_MapUserMemory(
+ Kernel->os,
+ gcvCORE_VG,
+ gcmUINT64_TO_PTR(kernelInterface->u.MapUserMemory.memory),
+ kernelInterface->u.MapUserMemory.physical,
+ (gctSIZE_T) kernelInterface->u.MapUserMemory.size,
+ &info,
+ &kernelInterface->u.MapUserMemory.address
+ ));
+
+ kernelInterface->u.MapUserMemory.info = gcmPTR_TO_NAME(info);
+
+ /* Clear temp storage. */
+ info = gcvNULL;
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+ /* Unmap user memory. */
+ gcmkERR_BREAK(gckOS_UnmapUserMemory(
+ Kernel->os,
+ gcvCORE_VG,
+ gcmUINT64_TO_PTR(kernelInterface->u.UnmapUserMemory.memory),
+ (gctSIZE_T) kernelInterface->u.UnmapUserMemory.size,
+ gcmNAME_TO_PTR(kernelInterface->u.UnmapUserMemory.info),
+ kernelInterface->u.UnmapUserMemory.address
+ ));
+
+ gcmRELEASE_NAME(kernelInterface->u.UnmapUserMemory.info);
+ break;
+
+ case gcvHAL_LOCK_VIDEO_MEMORY:
+ gcmkONERROR(gckKERNEL_LockVideoMemory(Kernel, gcvCORE_VG, processID, FromUser, Interface));
+ break;
+
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ gcmkONERROR(gckKERNEL_UnlockVideoMemory(Kernel, processID, Interface));
+ break;
+
+ case gcvHAL_USER_SIGNAL:
+#if !USE_NEW_LINUX_SIGNAL
+ /* Dispatch depends on the user signal subcommands. */
+ switch(Interface->u.UserSignal.command)
+ {
+ case gcvUSER_SIGNAL_CREATE:
+ /* Create a signal used in the user space. */
+ gcmkERR_BREAK(
+ gckOS_CreateUserSignal(Kernel->os,
+ Interface->u.UserSignal.manualReset,
+ &Interface->u.UserSignal.id));
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_SIGNAL,
+ gcmINT2PTR(Interface->u.UserSignal.id),
+ gcvNULL,
+ 0));
+ break;
+
+ case gcvUSER_SIGNAL_DESTROY:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Kernel,
+ processID, gcvDB_SIGNAL,
+ gcmINT2PTR(Interface->u.UserSignal.id)));
+
+ /* Destroy the signal. */
+ gcmkERR_BREAK(
+ gckOS_DestroyUserSignal(Kernel->os,
+ Interface->u.UserSignal.id));
+
+ break;
+
+ case gcvUSER_SIGNAL_SIGNAL:
+ /* Signal the signal. */
+ gcmkERR_BREAK(
+ gckOS_SignalUserSignal(Kernel->os,
+ Interface->u.UserSignal.id,
+ Interface->u.UserSignal.state));
+ break;
+
+ case gcvUSER_SIGNAL_WAIT:
+ /* Wait on the signal. */
+ status = gckOS_WaitUserSignal(Kernel->os,
+ Interface->u.UserSignal.id,
+ Interface->u.UserSignal.wait);
+ break;
+
+ default:
+ /* Invalid user signal command. */
+ gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
+ }
+#endif
+ break;
+
+ case gcvHAL_COMMIT:
+ /* Commit a command and context buffer. */
+ gcmkERR_BREAK(gckVGCOMMAND_Commit(
+ Kernel->vg->command,
+ gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.context),
+ gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.queue),
+ kernelInterface->u.VGCommit.entryCount,
+ gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.taskTable)
+ ));
+ break;
+ case gcvHAL_VERSION:
+ kernelInterface->u.Version.major = gcvVERSION_MAJOR;
+ kernelInterface->u.Version.minor = gcvVERSION_MINOR;
+ kernelInterface->u.Version.patch = gcvVERSION_PATCH;
+ kernelInterface->u.Version.build = gcvVERSION_BUILD;
+ status = gcvSTATUS_OK;
+ break;
+
+ case gcvHAL_GET_BASE_ADDRESS:
+ /* Get base address. */
+ gcmkERR_BREAK(
+ gckOS_GetBaseAddress(Kernel->os,
+ &kernelInterface->u.GetBaseAddress.baseAddress));
+ break;
+ case gcvHAL_IMPORT_VIDEO_MEMORY:
+ gcmkONERROR(gckVIDMEM_NODE_Import(Kernel,
+ Interface->u.ImportVideoMemory.name,
+ &Interface->u.ImportVideoMemory.handle));
+ gcmkONERROR(gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_VIDEO_MEMORY,
+ gcmINT2PTR(Interface->u.ImportVideoMemory.handle),
+ gcvNULL,
+ 0));
+ break;
+
+ case gcvHAL_NAME_VIDEO_MEMORY:
+ gcmkONERROR(gckVIDMEM_NODE_Name(Kernel,
+ Interface->u.NameVideoMemory.handle,
+ &Interface->u.NameVideoMemory.name));
+ break;
+
+ case gcvHAL_DATABASE:
+ gcmkONERROR(gckKERNEL_QueryDatabase(Kernel, processID, Interface));
+ break;
+ case gcvHAL_SHBUF:
+ {
+ gctSHBUF shBuf;
+ gctPOINTER uData;
+ gctUINT32 bytes;
+
+ switch (Interface->u.ShBuf.command)
+ {
+ case gcvSHBUF_CREATE:
+ bytes = Interface->u.ShBuf.bytes;
+
+ /* Create. */
+ gcmkONERROR(gckKERNEL_CreateShBuffer(Kernel, bytes, &shBuf));
+
+ Interface->u.ShBuf.id = gcmPTR_TO_UINT64(shBuf);
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID,
+ gcvDB_SHBUF,
+ shBuf,
+ gcvNULL,
+ 0));
+ break;
+
+ case gcvSHBUF_DESTROY:
+ shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+
+ /* Check db first to avoid illegal destroy in the process. */
+ gcmkONERROR(
+ gckKERNEL_RemoveProcessDB(Kernel,
+ processID,
+ gcvDB_SHBUF,
+ shBuf));
+
+ gcmkONERROR(gckKERNEL_DestroyShBuffer(Kernel, shBuf));
+ break;
+
+ case gcvSHBUF_MAP:
+ shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+
+ /* Map for current process access. */
+ gcmkONERROR(gckKERNEL_MapShBuffer(Kernel, shBuf));
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID,
+ gcvDB_SHBUF,
+ shBuf,
+ gcvNULL,
+ 0));
+ break;
+
+ case gcvSHBUF_WRITE:
+ shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+ uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
+ bytes = Interface->u.ShBuf.bytes;
+
+ /* Write. */
+ gcmkONERROR(
+ gckKERNEL_WriteShBuffer(Kernel, shBuf, uData, bytes));
+ break;
+
+ case gcvSHBUF_READ:
+ shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+ uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
+ bytes = Interface->u.ShBuf.bytes;
+
+ /* Read. */
+ gcmkONERROR(
+ gckKERNEL_ReadShBuffer(Kernel,
+ shBuf,
+ uData,
+ bytes,
+ &bytes));
+
+ /* Return copied size. */
+ Interface->u.ShBuf.bytes = bytes;
+ break;
+
+ default:
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ break;
+ }
+ }
+ break;
+ case gcvHAL_READ_REGISTER:
+#if gcdREGISTER_ACCESS_FROM_USER
+ /* Read a register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(
+ Kernel->os,
+ Kernel->core,
+ Interface->u.ReadRegisterData.address,
+ &Interface->u.ReadRegisterData.data));
+#else
+ /* No access from user land to read registers. */
+ Interface->u.ReadRegisterData.data = 0;
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+
+ case gcvHAL_WRITE_REGISTER:
+#if gcdREGISTER_ACCESS_FROM_USER
+ /* Write a register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Kernel->os,
+ Kernel->core,
+ Interface->u.WriteRegisterData.address,
+ Interface->u.WriteRegisterData.data));
+#else
+ /* No access from user land to write registers. */
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+
+
+ default:
+ /* Invalid command. */
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+OnError:
+ /* Save status. */
+ kernelInterface->status = status;
+
+ gcmkFOOTER();
+
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_QueryCommandBuffer
+**
+** Query command buffer attributes.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckVGHARDWARE object.
+**
+** OUTPUT:
+**
+** gcsCOMMAND_BUFFER_INFO_PTR Information
+** Pointer to the information structure to receive buffer attributes.
+*/
+gceSTATUS
+gckKERNEL_QueryCommandBuffer(
+ IN gckKERNEL Kernel,
+ OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Kernel=0x%x *Pool=0x%x",
+ Kernel, Information);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Get the information. */
+ status = gckVGCOMMAND_QueryCommandBuffer(Kernel->vg->command, Information);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+#endif /* gcdENABLE_VG */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h
new file mode 100644
index 000000000000..2ad509e442c0
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_vg_h_
+#define __gc_hal_kernel_vg_h_
+
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel_hardware.h"
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+/* gckKERNEL object. */
+struct _gckVGKERNEL
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Pointer to gckHARDWARE object. */
+ gckVGHARDWARE hardware;
+
+ /* Pointer to gckINTERRUPT object. */
+ gckVGINTERRUPT interrupt;
+
+ /* Pointer to gckCOMMAND object. */
+ gckVGCOMMAND command;
+
+ /* Pointer to context. */
+ gctPOINTER context;
+
+ /* Pointer to gckMMU object. */
+ gckVGMMU mmu;
+
+ gckKERNEL kernel;
+};
+
+/* gckMMU object. */
+struct _gckVGMMU
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Pointer to gckHARDWARE object. */
+ gckVGHARDWARE hardware;
+
+ /* The page table mutex. */
+ gctPOINTER mutex;
+
+ /* Page table information. */
+ gctSIZE_T pageTableSize;
+ gctPHYS_ADDR pageTablePhysical;
+ gctPOINTER pageTableLogical;
+
+ /* Allocation index. */
+ gctUINT32 entryCount;
+ gctUINT32 entry;
+};
+
+#endif /* __gc_hal_kernel_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
new file mode 100644
index 000000000000..16fd872b312b
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
@@ -0,0 +1,2917 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_VIDMEM
+
+/******************************************************************************\
+******************************* Private Functions ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** _Split
+**
+** Split a node on the required byte boundary.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to the node to split.
+**
+** gctSIZE_T Bytes
+** Number of bytes to keep in the node.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gctBOOL
+** gcvTRUE if the node was split successfully, or gcvFALSE if there is an
+** error.
+**
+*/
+static gctBOOL
+_Split(
+ IN gckOS Os,
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcuVIDMEM_NODE_PTR node;
+ gctPOINTER pointer = gcvNULL;
+
+ /* Make sure the byte boundary makes sense. */
+ if ((Bytes <= 0) || (Bytes > Node->VidMem.bytes))
+ {
+ return gcvFALSE;
+ }
+
+ /* Allocate a new gcuVIDMEM_NODE object. */
+ if (gcmIS_ERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(gcuVIDMEM_NODE),
+ &pointer)))
+ {
+ /* Error. */
+ return gcvFALSE;
+ }
+
+ node = pointer;
+
+ /* Initialize gcuVIDMEM_NODE structure. */
+ node->VidMem.offset = Node->VidMem.offset + Bytes;
+ node->VidMem.bytes = Node->VidMem.bytes - Bytes;
+ node->VidMem.alignment = 0;
+ node->VidMem.locked = 0;
+ node->VidMem.memory = Node->VidMem.memory;
+ node->VidMem.pool = Node->VidMem.pool;
+ node->VidMem.physical = Node->VidMem.physical;
+#ifdef __QNXNTO__
+ node->VidMem.processID = 0;
+ node->VidMem.logical = gcvNULL;
+#endif
+
+ /* Insert node behind specified node. */
+ node->VidMem.next = Node->VidMem.next;
+ node->VidMem.prev = Node;
+ Node->VidMem.next = node->VidMem.next->VidMem.prev = node;
+
+ /* Insert free node behind specified node. */
+ node->VidMem.nextFree = Node->VidMem.nextFree;
+ node->VidMem.prevFree = Node;
+ Node->VidMem.nextFree = node->VidMem.nextFree->VidMem.prevFree = node;
+
+ /* Adjust size of specified node. */
+ Node->VidMem.bytes = Bytes;
+
+ /* Success. */
+ return gcvTRUE;
+}
+
+/*******************************************************************************
+**
+** _Merge
+**
+** Merge two adjacent nodes together.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to the first of the two nodes to merge.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+*/
+static gceSTATUS
+_Merge(
+ IN gckOS Os,
+ IN gcuVIDMEM_NODE_PTR Node
+ )
+{
+ gcuVIDMEM_NODE_PTR node;
+ gceSTATUS status;
+
+ /* Save pointer to next node. */
+ node = Node->VidMem.next;
+
+ /* This is a good time to make sure the heap is not corrupted. */
+ if (Node->VidMem.offset + Node->VidMem.bytes != node->VidMem.offset)
+ {
+ /* Corrupted heap. */
+ gcmkASSERT(
+ Node->VidMem.offset + Node->VidMem.bytes == node->VidMem.offset);
+ return gcvSTATUS_HEAP_CORRUPTED;
+ }
+
+ /* Adjust byte count. */
+ Node->VidMem.bytes += node->VidMem.bytes;
+
+ /* Unlink next node from linked list. */
+ Node->VidMem.next = node->VidMem.next;
+ Node->VidMem.nextFree = node->VidMem.nextFree;
+
+ Node->VidMem.next->VidMem.prev =
+ Node->VidMem.nextFree->VidMem.prevFree = Node;
+
+ /* Free next node. */
+ status = gcmkOS_SAFE_FREE(Os, node);
+ return status;
+}
+
+/******************************************************************************\
+******************************* gckVIDMEM API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckVIDMEM_ConstructVirtual
+**
+** Construct a new gcuVIDMEM_NODE union for virtual memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctSIZE_T Bytes
+** Number of byte to allocate.
+**
+** OUTPUT:
+**
+** gcuVIDMEM_NODE_PTR * Node
+** Pointer to a variable that receives the gcuVIDMEM_NODE union pointer.
+*/
+gceSTATUS
+gckVIDMEM_ConstructVirtual(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Flag,
+ IN gctSIZE_T Bytes,
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+ gctPOINTER pointer = gcvNULL;
+ gctINT i;
+
+ gcmkHEADER_ARG("Kernel=0x%x Flag=%x Bytes=%lu", Kernel, Flag, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Allocate an gcuVIDMEM_NODE union. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
+
+ node = pointer;
+
+ /* Initialize gcuVIDMEM_NODE union for virtual memory. */
+ node->Virtual.kernel = Kernel;
+ node->Virtual.contiguous = Flag & gcvALLOC_FLAG_CONTIGUOUS;
+ node->Virtual.logical = gcvNULL;
+#if gcdENABLE_VG
+ node->Virtual.kernelVirtual = gcvNULL;
+#endif
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ node->Virtual.lockeds[i] = 0;
+ node->Virtual.pageTables[i] = gcvNULL;
+ node->Virtual.lockKernels[i] = gcvNULL;
+ }
+
+ gcmkONERROR(gckOS_GetProcessID(&node->Virtual.processID));
+
+ /* Allocate the virtual memory. */
+ gcmkONERROR(
+ gckOS_AllocatePagedMemoryEx(os,
+ Flag,
+ node->Virtual.bytes = Bytes,
+ &node->Virtual.gid,
+ &node->Virtual.physical));
+
+ /* Return pointer to the gcuVIDMEM_NODE union. */
+ *Node = node;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Created virtual node 0x%x for %u bytes @ 0x%x",
+ node, Bytes, node->Virtual.physical);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Node=0x%x", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (node != gcvNULL)
+ {
+ /* Free the structure. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, node));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_DestroyVirtual
+**
+** Destroy an gcuVIDMEM_NODE union for virtual memory.
+**
+** INPUT:
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_DestroyVirtual(
+ IN gcuVIDMEM_NODE_PTR Node
+ )
+{
+ gckOS os;
+
+ gcmkHEADER_ARG("Node=0x%x", Node);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
+
+ /* Extact the gckOS object pointer. */
+ os = Node->Virtual.kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Delete the gcuVIDMEM_NODE union. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, Node));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Construct
+**
+** Construct a new gckVIDMEM object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 BaseAddress
+** Base address for the video memory heap.
+**
+** gctSIZE_T Bytes
+** Number of bytes in the video memory heap.
+**
+** gctSIZE_T Threshold
+** Minimum number of bytes beyond am allocation before the node is
+** split. Can be used as a minimum alignment requirement.
+**
+** gctSIZE_T BankSize
+** Number of bytes per physical memory bank. Used by bank
+** optimization.
+**
+** OUTPUT:
+**
+** gckVIDMEM * Memory
+** Pointer to a variable that will hold the pointer to the gckVIDMEM
+** object.
+*/
+gceSTATUS
+gckVIDMEM_Construct(
+ IN gckOS Os,
+ IN gctUINT32 BaseAddress,
+ IN gctSIZE_T Bytes,
+ IN gctSIZE_T Threshold,
+ IN gctSIZE_T BankSize,
+ OUT gckVIDMEM * Memory
+ )
+{
+ gckVIDMEM memory = gcvNULL;
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node;
+ gctINT i, banks = 0;
+ gctPOINTER pointer = gcvNULL;
+ gctUINT32 heapBytes;
+ gctUINT32 bankSize;
+
+ gcmkHEADER_ARG("Os=0x%x BaseAddress=%08x Bytes=%lu Threshold=%lu "
+ "BankSize=%lu",
+ Os, BaseAddress, Bytes, Threshold, BankSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ gcmkSAFECASTSIZET(heapBytes, Bytes);
+ gcmkSAFECASTSIZET(bankSize, BankSize);
+
+ /* Allocate the gckVIDMEM object. */
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct _gckVIDMEM), &pointer));
+
+ memory = pointer;
+
+ /* Initialize the gckVIDMEM object. */
+ memory->object.type = gcvOBJ_VIDMEM;
+ memory->os = Os;
+
+ /* Set video memory heap information. */
+ memory->baseAddress = BaseAddress;
+ memory->bytes = heapBytes;
+ memory->freeBytes = heapBytes;
+ memory->threshold = Threshold;
+ memory->mutex = gcvNULL;
+
+ BaseAddress = 0;
+
+ /* Walk all possible banks. */
+ for (i = 0; i < gcmCOUNTOF(memory->sentinel); ++i)
+ {
+ gctUINT32 bytes;
+
+ if (BankSize == 0)
+ {
+ /* Use all bytes for the first bank. */
+ bytes = heapBytes;
+ }
+ else
+ {
+ /* Compute number of bytes for this bank. */
+ bytes = gcmALIGN(BaseAddress + 1, bankSize) - BaseAddress;
+
+ if (bytes > heapBytes)
+ {
+ /* Make sure we don't exceed the total number of bytes. */
+ bytes = heapBytes;
+ }
+ }
+
+ if (bytes == 0)
+ {
+ /* Mark heap is not used. */
+ memory->sentinel[i].VidMem.next =
+ memory->sentinel[i].VidMem.prev =
+ memory->sentinel[i].VidMem.nextFree =
+ memory->sentinel[i].VidMem.prevFree = gcvNULL;
+ continue;
+ }
+
+ /* Allocate one gcuVIDMEM_NODE union. */
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
+
+ node = pointer;
+
+ /* Initialize gcuVIDMEM_NODE union. */
+ node->VidMem.memory = memory;
+
+ node->VidMem.next =
+ node->VidMem.prev =
+ node->VidMem.nextFree =
+ node->VidMem.prevFree = &memory->sentinel[i];
+
+ node->VidMem.offset = BaseAddress;
+ node->VidMem.bytes = bytes;
+ node->VidMem.alignment = 0;
+ node->VidMem.physical = 0;
+ node->VidMem.pool = gcvPOOL_UNKNOWN;
+
+ node->VidMem.locked = 0;
+
+#ifdef __QNXNTO__
+ node->VidMem.processID = 0;
+ node->VidMem.logical = gcvNULL;
+#endif
+
+#if gcdENABLE_VG
+ node->VidMem.kernelVirtual = gcvNULL;
+#endif
+
+ /* Initialize the linked list of nodes. */
+ memory->sentinel[i].VidMem.next =
+ memory->sentinel[i].VidMem.prev =
+ memory->sentinel[i].VidMem.nextFree =
+ memory->sentinel[i].VidMem.prevFree = node;
+
+ /* Mark sentinel. */
+ memory->sentinel[i].VidMem.bytes = 0;
+
+ /* Adjust address for next bank. */
+ BaseAddress += bytes;
+ heapBytes -= bytes;
+ banks ++;
+ }
+
+ /* Assign all the bank mappings. */
+ memory->mapping[gcvSURF_RENDER_TARGET] = banks - 1;
+ memory->mapping[gcvSURF_BITMAP] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_DEPTH] = banks - 1;
+ memory->mapping[gcvSURF_HIERARCHICAL_DEPTH] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_TEXTURE] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_VERTEX] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_INDEX] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_TILE_STATUS] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_TYPE_UNKNOWN] = 0;
+
+#if gcdENABLE_VG
+ memory->mapping[gcvSURF_IMAGE] = 0;
+ memory->mapping[gcvSURF_MASK] = 0;
+ memory->mapping[gcvSURF_SCISSOR] = 0;
+#endif
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] INDEX: bank %d",
+ memory->mapping[gcvSURF_INDEX]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] VERTEX: bank %d",
+ memory->mapping[gcvSURF_VERTEX]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] TEXTURE: bank %d",
+ memory->mapping[gcvSURF_TEXTURE]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] RENDER_TARGET: bank %d",
+ memory->mapping[gcvSURF_RENDER_TARGET]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] DEPTH: bank %d",
+ memory->mapping[gcvSURF_DEPTH]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] TILE_STATUS: bank %d",
+ memory->mapping[gcvSURF_TILE_STATUS]);
+
+ /* Allocate the mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &memory->mutex));
+
+ /* Return pointer to the gckVIDMEM object. */
+ *Memory = memory;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (memory != gcvNULL)
+ {
+ if (memory->mutex != gcvNULL)
+ {
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, memory->mutex));
+ }
+
+ for (i = 0; i < banks; ++i)
+ {
+ /* Free the heap. */
+ gcmkASSERT(memory->sentinel[i].VidMem.next != gcvNULL);
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, memory->sentinel[i].VidMem.next));
+ }
+
+ /* Free the object. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, memory));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Destroy
+**
+** Destroy an gckVIDMEM object.
+**
+** INPUT:
+**
+** gckVIDMEM Memory
+** Pointer to an gckVIDMEM object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_Destroy(
+ IN gckVIDMEM Memory
+ )
+{
+ gcuVIDMEM_NODE_PTR node, next;
+ gctINT i;
+
+ gcmkHEADER_ARG("Memory=0x%x", Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+
+ /* Walk all sentinels. */
+ for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i)
+ {
+ /* Bail out of the heap is not used. */
+ if (Memory->sentinel[i].VidMem.next == gcvNULL)
+ {
+ break;
+ }
+
+ /* Walk all the nodes until we reach the sentinel. */
+ for (node = Memory->sentinel[i].VidMem.next;
+ node->VidMem.bytes != 0;
+ node = next)
+ {
+ /* Save pointer to the next node. */
+ next = node->VidMem.next;
+
+ /* Free the node. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Memory->os, node));
+ }
+ }
+
+ /* Free the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Memory->os, Memory->mutex));
+
+ /* Mark the object as unknown. */
+ Memory->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckVIDMEM object. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Memory->os, Memory));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#if gcdENABLE_BANK_ALIGNMENT
+
+#if !gcdBANK_BIT_START
+#error gcdBANK_BIT_START not defined.
+#endif
+
+#if !gcdBANK_BIT_END
+#error gcdBANK_BIT_END not defined.
+#endif
+/*******************************************************************************
+** _GetSurfaceBankAlignment
+**
+** Return the required offset alignment required to the make BaseAddress
+** aligned properly.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to gcoOS object.
+**
+** gceSURF_TYPE Type
+** Type of allocation.
+**
+** gctUINT32 BaseAddress
+** Base address of current video memory node.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR AlignmentOffset
+** Pointer to a variable that will hold the number of bytes to skip in
+** the current video memory node in order to make the alignment bank
+** aligned.
+*/
+static gceSTATUS
+_GetSurfaceBankAlignment(
+ IN gckKERNEL Kernel,
+ IN gceSURF_TYPE Type,
+ IN gctUINT32 BaseAddress,
+ OUT gctUINT32_PTR AlignmentOffset
+ )
+{
+ gctUINT32 bank;
+ /* To retrieve the bank. */
+ static const gctUINT32 bankMask = (0xFFFFFFFF << gcdBANK_BIT_START)
+ ^ (0xFFFFFFFF << (gcdBANK_BIT_END + 1));
+
+ /* To retrieve the bank and all the lower bytes. */
+ static const gctUINT32 byteMask = ~(0xFFFFFFFF << (gcdBANK_BIT_END + 1));
+
+ gcmkHEADER_ARG("Type=%d BaseAddress=0x%x ", Type, BaseAddress);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(AlignmentOffset != gcvNULL);
+
+ switch (Type)
+ {
+ case gcvSURF_RENDER_TARGET:
+ bank = (BaseAddress & bankMask) >> (gcdBANK_BIT_START);
+
+ /* Align to the first bank. */
+ *AlignmentOffset = (bank == 0) ?
+ 0 :
+ ((1 << (gcdBANK_BIT_END + 1)) + 0) - (BaseAddress & byteMask);
+ break;
+
+ case gcvSURF_DEPTH:
+ bank = (BaseAddress & bankMask) >> (gcdBANK_BIT_START);
+
+ /* Align to the third bank. */
+ *AlignmentOffset = (bank == 2) ?
+ 0 :
+ ((1 << (gcdBANK_BIT_END + 1)) + (2 << gcdBANK_BIT_START)) - (BaseAddress & byteMask);
+
+ /* 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:
+ /* no alignment needed. */
+ *AlignmentOffset = 0;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER_ARG("*AlignmentOffset=%u", *AlignmentOffset);
+ return gcvSTATUS_OK;
+}
+#endif
+
+static gcuVIDMEM_NODE_PTR
+_FindNode(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM Memory,
+ IN gctINT Bank,
+ IN gctSIZE_T Bytes,
+ IN gceSURF_TYPE Type,
+ IN OUT gctUINT32_PTR Alignment
+ )
+{
+ gcuVIDMEM_NODE_PTR node;
+ gctUINT32 alignment;
+
+#if gcdENABLE_BANK_ALIGNMENT
+ gctUINT32 bankAlignment;
+ gceSTATUS status;
+#endif
+
+ if (Memory->sentinel[Bank].VidMem.nextFree == gcvNULL)
+ {
+ /* No free nodes left. */
+ return gcvNULL;
+ }
+
+#if gcdENABLE_BANK_ALIGNMENT
+ /* Walk all free nodes until we have one that is big enough or we have
+ ** reached the sentinel. */
+ for (node = Memory->sentinel[Bank].VidMem.nextFree;
+ node->VidMem.bytes != 0;
+ node = node->VidMem.nextFree)
+ {
+ if (node->VidMem.bytes < Bytes)
+ {
+ continue;
+ }
+
+ gcmkONERROR(_GetSurfaceBankAlignment(
+ Kernel,
+ Type,
+ node->VidMem.memory->baseAddress + node->VidMem.offset,
+ &bankAlignment));
+
+ bankAlignment = gcmALIGN(bankAlignment, *Alignment);
+
+ /* Compute number of bytes to skip for alignment. */
+ alignment = (*Alignment == 0)
+ ? 0
+ : (*Alignment - (node->VidMem.offset % *Alignment));
+
+ if (alignment == *Alignment)
+ {
+ /* Node is already aligned. */
+ alignment = 0;
+ }
+
+ if (node->VidMem.bytes >= Bytes + alignment + bankAlignment)
+ {
+ /* This node is big enough. */
+ *Alignment = alignment + bankAlignment;
+ return node;
+ }
+ }
+#endif
+
+ /* Walk all free nodes until we have one that is big enough or we have
+ reached the sentinel. */
+ for (node = Memory->sentinel[Bank].VidMem.nextFree;
+ node->VidMem.bytes != 0;
+ node = node->VidMem.nextFree)
+ {
+ gctUINT offset;
+
+ 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);
+
+ if (alignment == *Alignment)
+ {
+ /* Node is already aligned. */
+ alignment = 0;
+ }
+
+ if (node->VidMem.bytes >= Bytes + alignment)
+ {
+ /* This node is big enough. */
+ *Alignment = alignment;
+ return node;
+ }
+ }
+
+#if gcdENABLE_BANK_ALIGNMENT
+OnError:
+#endif
+ /* Not enough memory. */
+ return gcvNULL;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_AllocateLinear
+**
+** Allocate linear memory from the gckVIDMEM object.
+**
+** INPUT:
+**
+** gckVIDMEM Memory
+** Pointer to an gckVIDMEM object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** gctUINT32 Alignment
+** Byte alignment for allocation.
+**
+** gceSURF_TYPE Type
+** Type of surface to allocate (use by bank optimization).
+**
+** 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
+** Pointer to a variable that will hold the allocated memory node.
+*/
+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
+ )
+{
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node;
+ gctUINT32 alignment;
+ gctINT bank, i;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Memory=0x%x Bytes=%lu Alignment=%u Type=%d",
+ Memory, Bytes, Alignment, Type);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Type < gcvSURF_NUM_TYPES);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ if (Bytes > Memory->freeBytes)
+ {
+ /* Not enough memory. */
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ goto OnError;
+ }
+
+#if gcdSMALL_BLOCK_SIZE
+ if ((Memory->freeBytes < (Memory->bytes/gcdRATIO_FOR_SMALL_MEMORY))
+ && (Bytes >= gcdSMALL_BLOCK_SIZE)
+ && (Specified == gcvFALSE)
+ )
+ {
+ /* The left memory is for small memory.*/
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ goto OnError;
+ }
+#endif
+
+ /* Find the default bank for this surface type. */
+ gcmkASSERT((gctINT) Type < gcmCOUNTOF(Memory->mapping));
+ bank = Memory->mapping[Type];
+ alignment = Alignment;
+
+ /* Find a free node in the default bank. */
+ node = _FindNode(Kernel, Memory, bank, Bytes, Type, &alignment);
+
+ /* Out of memory? */
+ if (node == gcvNULL)
+ {
+ /* Walk all lower banks. */
+ for (i = bank - 1; i >= 0; --i)
+ {
+ /* Find a free node inside the current bank. */
+ node = _FindNode(Kernel, Memory, i, Bytes, Type, &alignment);
+ if (node != gcvNULL)
+ {
+ break;
+ }
+ }
+ }
+
+ if (node == gcvNULL)
+ {
+ /* Walk all upper banks. */
+ for (i = bank + 1; i < gcmCOUNTOF(Memory->sentinel); ++i)
+ {
+ if (Memory->sentinel[i].VidMem.nextFree == gcvNULL)
+ {
+ /* Abort when we reach unused banks. */
+ break;
+ }
+
+ /* Find a free node inside the current bank. */
+ node = _FindNode(Kernel, Memory, i, Bytes, Type, &alignment);
+ if (node != gcvNULL)
+ {
+ break;
+ }
+ }
+ }
+
+ if (node == gcvNULL)
+ {
+ /* Out of memory. */
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ goto OnError;
+ }
+
+ /* Do we have an alignment? */
+ if (alignment > 0)
+ {
+ /* Split the node so it is aligned. */
+ if (_Split(Memory->os, node, alignment))
+ {
+ /* Successful split, move to aligned node. */
+ node = node->VidMem.next;
+
+ /* Remove alignment. */
+ alignment = 0;
+ }
+ }
+
+ /* Do we have enough memory after the allocation to split it? */
+ if (node->VidMem.bytes - Bytes > Memory->threshold)
+ {
+ /* Adjust the node size. */
+ _Split(Memory->os, node, Bytes);
+ }
+
+ /* Remove the node from the free list. */
+ node->VidMem.prevFree->VidMem.nextFree = node->VidMem.nextFree;
+ node->VidMem.nextFree->VidMem.prevFree = node->VidMem.prevFree;
+ node->VidMem.nextFree =
+ node->VidMem.prevFree = gcvNULL;
+
+ /* Fill in the information. */
+ node->VidMem.alignment = alignment;
+ node->VidMem.memory = Memory;
+#ifdef __QNXNTO__
+ node->VidMem.logical = gcvNULL;
+ gcmkONERROR(gckOS_GetProcessID(&node->VidMem.processID));
+#endif
+
+ /* Adjust the number of free bytes. */
+ Memory->freeBytes -= node->VidMem.bytes;
+
+#if gcdENABLE_VG
+ node->VidMem.kernelVirtual = gcvNULL;
+#endif
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+
+ /* Return the pointer to the node. */
+ *Node = node;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Allocated %u bytes @ 0x%x [0x%08X]",
+ node->VidMem.bytes, node, node->VidMem.offset);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Node=0x%x", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Free
+**
+** Free an allocated video memory node.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_Free(
+ IN gckKERNEL Kernel,
+ IN gcuVIDMEM_NODE_PTR Node
+ )
+{
+ gceSTATUS status;
+ gckKERNEL kernel = gcvNULL;
+ gckVIDMEM memory = gcvNULL;
+ gcuVIDMEM_NODE_PTR node;
+ gctBOOL mutexAcquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Node=0x%x", Node);
+
+ /* Verify the arguments. */
+ if ((Node == gcvNULL)
+ || (Node->VidMem.memory == gcvNULL)
+ )
+ {
+ /* Invalid object. */
+ gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+ }
+
+ /**************************** Video Memory ********************************/
+
+ if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ /* Extract pointer to gckVIDMEM object owning the node. */
+ memory = Node->VidMem.memory;
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(memory->os, memory->mutex, gcvINFINITE));
+
+ mutexAcquired = gcvTRUE;
+
+#ifdef __QNXNTO__
+ /* 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;
+
+ /* Don't try to re-free an already freed node. */
+ if ((Node->VidMem.nextFree == gcvNULL)
+ && (Node->VidMem.prevFree == gcvNULL)
+ )
+#endif
+ {
+#if gcdENABLE_VG
+ if (Node->VidMem.kernelVirtual)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "%s(%d) Unmap %x from kernel space.",
+ __FUNCTION__, __LINE__,
+ Node->VidMem.kernelVirtual);
+
+ gcmkVERIFY_OK(
+ gckOS_UnmapPhysical(memory->os,
+ Node->VidMem.kernelVirtual,
+ Node->VidMem.bytes));
+
+ Node->VidMem.kernelVirtual = gcvNULL;
+ }
+#endif
+
+ /* Check if Node is already freed. */
+ if (Node->VidMem.nextFree)
+ {
+ /* Node is alread freed. */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+
+ /* Update the number of free bytes. */
+ memory->freeBytes += Node->VidMem.bytes;
+
+ /* Find the next free node. */
+ for (node = Node->VidMem.next;
+ node != gcvNULL && node->VidMem.nextFree == gcvNULL;
+ node = node->VidMem.next) ;
+
+ /* Insert this node in the free list. */
+ Node->VidMem.nextFree = node;
+ Node->VidMem.prevFree = node->VidMem.prevFree;
+
+ Node->VidMem.prevFree->VidMem.nextFree =
+ node->VidMem.prevFree = Node;
+
+ /* Is the next node a free node and not the sentinel? */
+ if ((Node->VidMem.next == Node->VidMem.nextFree)
+ && (Node->VidMem.next->VidMem.bytes != 0)
+ )
+ {
+ /* Merge this node with the next node. */
+ gcmkONERROR(_Merge(memory->os, node = Node));
+ gcmkASSERT(node->VidMem.nextFree != node);
+ gcmkASSERT(node->VidMem.prevFree != node);
+ }
+
+ /* Is the previous node a free node and not the sentinel? */
+ if ((Node->VidMem.prev == Node->VidMem.prevFree)
+ && (Node->VidMem.prev->VidMem.bytes != 0)
+ )
+ {
+ /* Merge this node with the previous node. */
+ gcmkONERROR(_Merge(memory->os, node = Node->VidMem.prev));
+ gcmkASSERT(node->VidMem.nextFree != node);
+ gcmkASSERT(node->VidMem.prevFree != node);
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Node 0x%x is freed.",
+ Node);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /*************************** Virtual Memory *******************************/
+
+ /* Get gckKERNEL object. */
+ kernel = Node->Virtual.kernel;
+
+ /* Verify the gckKERNEL object pointer. */
+ gcmkVERIFY_OBJECT(kernel, gcvOBJ_KERNEL);
+
+#if gcdENABLE_VG
+ if (Node->Virtual.kernelVirtual)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "%s(%d) Unmap %x from kernel space.",
+ __FUNCTION__, __LINE__,
+ Node->Virtual.kernelVirtual);
+
+ gcmkVERIFY_OK(
+ gckOS_UnmapPhysical(kernel->os,
+ Node->Virtual.kernelVirtual,
+ Node->Virtual.bytes));
+
+ Node->Virtual.kernelVirtual = gcvNULL;
+ }
+#endif
+
+ /* 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));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mutexAcquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(
+ memory->os, memory->mutex
+ ));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if !gcdPROCESS_ADDRESS_SPACE
+/*******************************************************************************
+**
+** _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
+)
+{
+ gceSTATUS status;
+ gctPHYS_ADDR_T phys;
+ gctUINT32 address;
+ gctUINT32 end;
+ gcePOOL pool;
+ gctUINT32 offset;
+ gctUINT32 baseAddress;
+ gctUINT32 bytes;
+
+ 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);
+
+ if (Node->Virtual.contiguous)
+ {
+#if gcdENABLE_VG
+ if (Core == gcvCORE_VG)
+ {
+ *NeedMapping = gcvFALSE;
+ }
+ else
+#endif
+ {
+ /* Convert logical address into a physical address. */
+ gcmkONERROR(gckOS_UserLogicalToPhysical(
+ Kernel->os, Node->Virtual.logical, &phys
+ ));
+
+ gcmkSAFECASTPHYSADDRT(address, phys);
+
+ gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &baseAddress));
+
+ gcmkASSERT(phys >= baseAddress);
+
+ /* Subtract baseAddress to get a GPU address used for programming. */
+ address -= baseAddress;
+
+ /* If part of region is belong to gcvPOOL_VIRTUAL,
+ ** whole region has to be mapped. */
+
+ gcmkSAFECASTSIZET(bytes, Node->Virtual.bytes);
+
+ end = address + bytes - 1;
+
+ if (!gckHARDWARE_IsFeatureAvailable(Kernel->hardware, gcvFEATURE_MMU))
+ {
+ gcmkONERROR(gckHARDWARE_SplitMemory(
+ Kernel->hardware, end, &pool, &offset
+ ));
+
+ *NeedMapping = (pool == gcvPOOL_VIRTUAL);
+ }
+ else
+ {
+ /* TODO: Check whether physical address in flat mapping. */
+ gctUINT32 dynamicMappingStart = Kernel->mmu->dynamicMappingStart;
+ if( end < (dynamicMappingStart << gcdMMU_MTLB_SHIFT))
+ *NeedMapping = gcvFALSE;
+ else
+ *NeedMapping = gcvTRUE;
+ }
+ }
+ }
+ else
+ {
+ *NeedMapping = gcvTRUE;
+ }
+
+ gcmkFOOTER_ARG("*NeedMapping=%d", *NeedMapping);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+gcsGPU_MAP_PTR
+_FindGPUMap(
+ IN gcsGPU_MAP_PTR Head,
+ IN gctINT ProcessID
+ )
+{
+ gcsGPU_MAP_PTR map = Head;
+
+ while (map)
+ {
+ if (map->pid == ProcessID)
+ {
+ return map;
+ }
+
+ map = map->next;
+ }
+
+ return gcvNULL;
+}
+
+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;
+
+ gckOS_Allocate(Os, sizeof(gcsGPU_MAP), &pointer);
+
+ if (pointer == gcvNULL)
+ {
+ return gcvNULL;
+ }
+
+ gpuMap = pointer;
+
+ gckOS_ZeroMemory(pointer, sizeof(gcsGPU_MAP));
+
+ gpuMap->pid = ProcessID;
+
+ if (!*Head)
+ {
+ *Head = *Tail = gpuMap;
+ }
+ else
+ {
+ gpuMap->prev = *Tail;
+ (*Tail)->next = gpuMap;
+ *Tail = gpuMap;
+ }
+
+ return gpuMap;
+}
+
+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
+
+/*******************************************************************************
+**
+** gckVIDMEM_Lock
+**
+** Lock a video memory node and return its hardware specific address.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Pointer to a variable that will hold the hardware specific address.
+**
+** gctUINT32 * PhysicalAddress
+** Pointer to a variable that will hold the bus address of a contiguous
+** video node.
+*/
+gceSTATUS
+gckVIDMEM_Lock(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ IN gctBOOL Cacheable,
+ OUT gctUINT32 * Address,
+ OUT gctUINT32 * Gid,
+ OUT gctUINT64 * PhysicalAddress
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL locked = gcvFALSE;
+ gckOS os = gcvNULL;
+#if !gcdPROCESS_ADDRESS_SPACE
+ gctBOOL needMapping = gcvFALSE;
+#endif
+ gctUINT32 baseAddress;
+ gctUINT64 physicalAddress;
+ gcuVIDMEM_NODE_PTR node = Node->node;
+ gctPHYS_ADDR_T physical;
+
+ gcmkHEADER_ARG("Node=0x%x", Node);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* 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)
+ {
+ gctUINT32 offset;
+
+ if (Cacheable == gcvTRUE)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+ }
+
+ /* Increment the lock count. */
+ node->VidMem.locked ++;
+
+ /* Return the physical address of the node. */
+ gcmkSAFECASTSIZET(offset, node->VidMem.offset);
+
+ *Address = node->VidMem.memory->baseAddress
+ + offset
+ + node->VidMem.alignment;
+
+ physicalAddress = *Address;
+
+ /* Get hardware specific address. */
+#if gcdENABLE_VG
+ if (Kernel->vg == gcvNULL)
+#endif
+ {
+ if (Kernel->hardware->mmuVersion == 0)
+ {
+ /* Convert physical to GPU address for old mmu. */
+ gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &baseAddress));
+ gcmkASSERT(*Address > baseAddress);
+ *Address -= baseAddress;
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(
+ Kernel->os,
+ *Address,
+ &physical
+ ));
+
+ gcmkSAFECASTSIZET(*Address, physical);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Locked node 0x%x (%d) @ 0x%08X",
+ node,
+ node->VidMem.locked,
+ *Address);
+ }
+
+ /*************************** Virtual Memory *******************************/
+
+ else
+ {
+
+ *Gid = node->Virtual.gid;
+
+#if gcdPAGED_MEMORY_CACHEABLE
+ /* Force video memory cacheable. */
+ Cacheable = gcvTRUE;
+#endif
+
+ gcmkONERROR(
+ gckOS_LockPages(os,
+ node->Virtual.physical,
+ node->Virtual.bytes,
+ Cacheable,
+ &node->Virtual.logical,
+ &node->Virtual.pageCount));
+
+ gcmkONERROR(gckOS_UserLogicalToPhysical(
+ os,
+ node->Virtual.logical,
+ &physicalAddress
+ ));
+
+#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));
+
+ if (needMapping == gcvFALSE)
+ {
+ /* Get hardware specific address. */
+#if gcdENABLE_VG
+ if (Kernel->vg != gcvNULL)
+ {
+ 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,
+ 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]));
+ }
+ else
+#endif
+ {
+ /* 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.lockKernels[Kernel->core] = Kernel;
+
+ /* Map the pages. */
+ gcmkONERROR(
+ gckOS_MapPagesEx(os,
+ Kernel->core,
+ node->Virtual.physical,
+ node->Virtual.pageCount,
+ node->Virtual.addresses[Kernel->core],
+ node->Virtual.pageTables[Kernel->core]));
+
+#if gcdENABLE_VG
+ if (Kernel->core == gcvCORE_VG)
+ {
+ gcmkONERROR(gckVGMMU_Flush(Kernel->vg->mmu));
+ }
+ else
+#endif
+ {
+ 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]);
+ }
+
+ /* Return hardware address. */
+ *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;
+
+OnError:
+ if (locked)
+ {
+ if (node->Virtual.pageTables[Kernel->core] != gcvNULL)
+ {
+#if gcdENABLE_VG
+ if (Kernel->vg != gcvNULL)
+ {
+ /* Free the pages from the MMU. */
+ gcmkVERIFY_OK(
+ gckVGMMU_FreePages(Kernel->vg->mmu,
+ node->Virtual.pageTables[Kernel->core],
+ node->Virtual.pageCount));
+ }
+ else
+#endif
+ {
+ /* Free the pages from the MMU. */
+ gcmkVERIFY_OK(
+ gckMMU_FreePages(Kernel->mmu,
+ node->Virtual.pageTables[Kernel->core],
+ node->Virtual.pageCount));
+ }
+ node->Virtual.pageTables[Kernel->core] = gcvNULL;
+ node->Virtual.lockKernels[Kernel->core] = gcvNULL;
+ }
+
+ /* Unlock the pages. */
+ gcmkVERIFY_OK(
+ gckOS_UnlockPages(os,
+ node->Virtual.physical,
+ node->Virtual.bytes,
+ node->Virtual.logical
+ ));
+
+ node->Virtual.lockeds[Kernel->core]--;
+ }
+
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Unlock
+**
+** Unlock a video memory node.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a locked gcuVIDMEM_NODE union.
+**
+** gceSURF_TYPE Type
+** Type of surface to unlock.
+**
+** gctBOOL * Asynchroneous
+** Pointer to a variable specifying whether the surface should be
+** unlocked asynchroneously or not.
+**
+** OUTPUT:
+**
+** gctBOOL * Asynchroneous
+** Pointer to a variable receiving the number of bytes used in the
+** command buffer specified by 'Commands'. If gcvNULL, there is no
+** command buffer.
+*/
+gceSTATUS
+gckVIDMEM_Unlock(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ IN gceSURF_TYPE Type,
+ IN OUT gctBOOL * Asynchroneous
+ )
+{
+ gceSTATUS status;
+ gckOS os = gcvNULL;
+ gctBOOL acquired = gcvFALSE;
+ 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)
+ )
+ {
+ /* 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.locked <= 0)
+ {
+ /* The surface was not locked. */
+ status = gcvSTATUS_MEMORY_UNLOCKED;
+ goto OnError;
+ }
+
+ if (Asynchroneous != gcvNULL)
+ {
+ /* 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);
+ }
+
+ /*************************** Virtual Memory *******************************/
+
+ else
+ {
+
+
+ if (Asynchroneous == gcvNULL)
+ {
+#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];
+
+ /* See if we can unlock the resources. */
+ 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 gcdENABLE_VG
+ if (Kernel->vg != gcvNULL)
+ {
+ gcmkONERROR(
+ gckVGMMU_FreePages(Kernel->vg->mmu,
+ node->Virtual.pageTables[Kernel->core],
+ node->Virtual.pageCount));
+ }
+ else
+#endif
+ {
+ gcmkONERROR(
+ gckMMU_FreePages(Kernel->mmu,
+ node->Virtual.pageTables[Kernel->core],
+ node->Virtual.pageCount));
+ }
+
+ gcmkONERROR(gckOS_UnmapPages(
+ Kernel->os,
+ node->Virtual.pageCount,
+ node->Virtual.addresses[Kernel->core]
+ ));
+
+ /* 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]);
+#endif
+
+ }
+
+ else
+ {
+ gcmkONERROR(
+ gckOS_UnlockPages(os,
+ node->Virtual.physical,
+ node->Virtual.bytes,
+ node->Virtual.logical));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Scheduled unlock for virtual node 0x%x",
+ node);
+
+ /* Schedule the surface to be unlocked. */
+ *Asynchroneous = gcvTRUE;
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
+ acquired = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Asynchroneous=%d", gcmOPT_VALUE(Asynchroneous));
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
+ }
+
+ /* 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));
+ }
+
+ gcmkONERROR(gckMMU_Flush(mmu));
+ }
+
+ *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;
+ }
+
+ /* 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
+ ));
+
+ _DestroyGPUMap(Kernel->os, &Node->mapHead, &Node->mapTail, gpuMap);
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Node->mapMutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ 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)
+ {
+ 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));
+ }
+
+ 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;
+}
+
+gceSTATUS
+gckVIDMEM_ConstructVirtualFromUserMemory(
+ IN gckKERNEL Kernel,
+ IN gcsUSER_MEMORY_DESC_PTR Desc,
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Allocate an gcuVIDMEM_NODE union. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
+
+ gckOS_ZeroMemory(pointer, gcmSIZEOF(gcuVIDMEM_NODE));
+
+ node = pointer;
+
+ /* Initialize gcuVIDMEM_NODE union for virtual memory. */
+ node->Virtual.kernel = Kernel;
+ node->Virtual.contiguous = gcvFALSE;
+
+ /* Wrap Memory. */
+ gcmkONERROR(gckOS_WrapMemory(
+ os, Desc, &node->Virtual.bytes, &node->Virtual.physical));
+
+ /* Return pointer to the gcuVIDMEM_NODE union. */
+ *Node = node;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Node=0x%x", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (node != gcvNULL)
+ {
+ /* Free the structure. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, node));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
new file mode 100644
index 000000000000..5fcc4ae612b7
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
@@ -0,0 +1,2920 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_h_
+#define __gc_hal_h_
+
+#include "gc_hal_rename.h"
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+#include "gc_hal_base.h"
+#include "gc_hal_profiler.h"
+#include "gc_hal_driver.h"
+#if gcdENABLE_3D
+#include "gc_hal_statistics.h"
+#endif
+
+#if gcdSECURITY
+#include "gc_hal_security_interface.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* 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) \
+)
+
+#define gcmALIGN_BASE(n, align) \
+( \
+ ((n) & ~((align) - 1)) \
+)
+
+/******************************************************************************\
+***************************** Element Count Macro *****************************
+\******************************************************************************/
+
+#define gcmSIZEOF(a) \
+( \
+ (gctSIZE_T) (sizeof(a)) \
+)
+
+#define gcmCOUNTOF(a) \
+( \
+ sizeof(a) / sizeof(a[0]) \
+)
+
+/******************************************************************************\
+********************************* Cast Macro **********************************
+\******************************************************************************/
+#define gcmNAME_TO_PTR(na) \
+ gckKERNEL_QueryPointerFromName(kernel, gcmALL_TO_UINT32(na))
+
+#define gcmPTR_TO_NAME(ptr) \
+ gckKERNEL_AllocateNameFromPointer(kernel, ptr)
+
+#define gcmRELEASE_NAME(na) \
+ gckKERNEL_DeleteName(kernel, gcmALL_TO_UINT32(na))
+
+#define gcmALL_TO_UINT32(t) \
+( \
+ (gctUINT32) (gctUINTPTR_T) (t)\
+)
+
+#define gcmPTR_TO_UINT64(p) \
+( \
+ (gctUINT64) (gctUINTPTR_T) (p)\
+)
+
+#define gcmUINT64_TO_PTR(u) \
+( \
+ (gctPOINTER) (gctUINTPTR_T) (u)\
+)
+
+#define gcmUINT64_TO_TYPE(u, t) \
+( \
+ (t) (gctUINTPTR_T) (u)\
+)
+
+/******************************************************************************\
+******************************** Useful Macro *********************************
+\******************************************************************************/
+
+#define gcvINVALID_ADDRESS ~0U
+
+#define gcmGET_PRE_ROTATION(rotate) \
+ ((rotate) & (~(gcvSURF_POST_FLIP_X | gcvSURF_POST_FLIP_Y)))
+
+#define gcmGET_POST_ROTATION(rotate) \
+ ((rotate) & (gcvSURF_POST_FLIP_X | gcvSURF_POST_FLIP_Y))
+
+/******************************************************************************\
+******************************** gcsOBJECT Object *******************************
+\******************************************************************************/
+
+/* Type of objects. */
+typedef enum _gceOBJECT_TYPE
+{
+ gcvOBJ_UNKNOWN = 0,
+ gcvOBJ_2D = gcmCC('2','D',' ',' '),
+ gcvOBJ_3D = gcmCC('3','D',' ',' '),
+ gcvOBJ_ATTRIBUTE = gcmCC('A','T','T','R'),
+ gcvOBJ_BRUSHCACHE = gcmCC('B','R','U','$'),
+ gcvOBJ_BRUSHNODE = gcmCC('B','R','U','n'),
+ gcvOBJ_BRUSH = gcmCC('B','R','U','o'),
+ gcvOBJ_BUFFER = gcmCC('B','U','F','R'),
+ gcvOBJ_COMMAND = gcmCC('C','M','D',' '),
+ gcvOBJ_COMMANDBUFFER = gcmCC('C','M','D','B'),
+ gcvOBJ_CONTEXT = gcmCC('C','T','X','T'),
+ gcvOBJ_DEVICE = gcmCC('D','E','V',' '),
+ gcvOBJ_DUMP = gcmCC('D','U','M','P'),
+ gcvOBJ_EVENT = gcmCC('E','V','N','T'),
+ gcvOBJ_FUNCTION = gcmCC('F','U','N','C'),
+ gcvOBJ_HAL = gcmCC('H','A','L',' '),
+ gcvOBJ_HARDWARE = gcmCC('H','A','R','D'),
+ gcvOBJ_HEAP = gcmCC('H','E','A','P'),
+ gcvOBJ_INDEX = gcmCC('I','N','D','X'),
+ gcvOBJ_INTERRUPT = gcmCC('I','N','T','R'),
+ gcvOBJ_KERNEL = gcmCC('K','E','R','N'),
+ gcvOBJ_KERNEL_FUNCTION = gcmCC('K','F','C','N'),
+ gcvOBJ_MEMORYBUFFER = gcmCC('M','E','M','B'),
+ gcvOBJ_MMU = gcmCC('M','M','U',' '),
+ gcvOBJ_OS = gcmCC('O','S',' ',' '),
+ gcvOBJ_OUTPUT = gcmCC('O','U','T','P'),
+ gcvOBJ_PAINT = gcmCC('P','N','T',' '),
+ gcvOBJ_PATH = gcmCC('P','A','T','H'),
+ gcvOBJ_QUEUE = gcmCC('Q','U','E',' '),
+ gcvOBJ_SAMPLER = gcmCC('S','A','M','P'),
+ gcvOBJ_SHADER = gcmCC('S','H','D','R'),
+ gcvOBJ_STREAM = gcmCC('S','T','R','M'),
+ gcvOBJ_SURF = gcmCC('S','U','R','F'),
+ gcvOBJ_TEXTURE = gcmCC('T','X','T','R'),
+ gcvOBJ_UNIFORM = gcmCC('U','N','I','F'),
+ gcvOBJ_VARIABLE = gcmCC('V','A','R','I'),
+ gcvOBJ_VERTEX = gcmCC('V','R','T','X'),
+ gcvOBJ_VIDMEM = gcmCC('V','M','E','M'),
+ gcvOBJ_VG = gcmCC('V','G',' ',' '),
+ gcvOBJ_BUFOBJ = gcmCC('B','U','F','O'),
+ gcvOBJ_UNIFORM_BLOCK = gcmCC('U','B','L','K'),
+ gcvOBJ_CL = gcmCC('C','L',' ',' '),
+}
+gceOBJECT_TYPE;
+
+/* gcsOBJECT object defintinon. */
+typedef struct _gcsOBJECT
+{
+ /* Type of an object. */
+ gceOBJECT_TYPE type;
+}
+gcsOBJECT;
+
+typedef struct _gckHARDWARE * gckHARDWARE;
+
+/* CORE flags. */
+typedef enum _gceCORE
+{
+ gcvCORE_MAJOR = 0x0,
+ gcvCORE_2D = 0x1,
+ gcvCORE_VG = 0x2,
+#if gcdMULTI_GPU_AFFINITY
+ gcvCORE_OCL = 0x3,
+#endif
+#if gcdENABLE_DEC_COMPRESSION
+ gcvCORE_DEC = 0x4,
+#endif
+ gcvCORE_COUNT
+}
+gceCORE;
+
+#define gcdMAX_GPU_COUNT gcvCORE_COUNT
+
+#define gcdMAX_SURF_LAYERS 4
+
+#define gcdMAX_DRAW_BUFFERS 8
+
+/*******************************************************************************
+**
+** gcmVERIFY_OBJECT
+**
+** Assert if an object is invalid or is not of the specified type. If the
+** object is invalid or not of the specified type, gcvSTATUS_INVALID_OBJECT
+** will be returned from the current function. In retail mode this macro
+** does nothing.
+**
+** ARGUMENTS:
+**
+** obj Object to test.
+** t Expected type of the object.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+#define _gcmVERIFY_OBJECT(prefix, obj, t) \
+ if ((obj) == gcvNULL) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "VERIFY_OBJECT failed: NULL"); \
+ prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
+ gcmCC_PRINT(t)); \
+ prefix##ASSERT((obj) != gcvNULL); \
+ prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
+ return gcvSTATUS_INVALID_OBJECT; \
+ } \
+ else if (((gcsOBJECT*) (obj))->type != t) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "VERIFY_OBJECT failed: %c%c%c%c", \
+ gcmCC_PRINT(((gcsOBJECT*) (obj))->type)); \
+ prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
+ gcmCC_PRINT(t)); \
+ prefix##ASSERT(((gcsOBJECT*)(obj))->type == t); \
+ prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
+ return gcvSTATUS_INVALID_OBJECT; \
+ }
+
+# define gcmVERIFY_OBJECT(obj, t) _gcmVERIFY_OBJECT(gcm, obj, t)
+# define gcmkVERIFY_OBJECT(obj, t) _gcmVERIFY_OBJECT(gcmk, obj, t)
+#else
+# define gcmVERIFY_OBJECT(obj, t) do {} while (gcvFALSE)
+# define gcmkVERIFY_OBJECT(obj, t) do {} while (gcvFALSE)
+#endif
+
+/******************************************************************************/
+/*VERIFY_OBJECT if special return expected*/
+/******************************************************************************/
+#ifndef EGL_API_ANDROID
+# define _gcmVERIFY_OBJECT_RETURN(prefix, obj, t, retVal) \
+ do \
+ { \
+ if ((obj) == gcvNULL) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "VERIFY_OBJECT_RETURN failed: NULL"); \
+ prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
+ gcmCC_PRINT(t)); \
+ prefix##ASSERT((obj) != gcvNULL); \
+ prefix##FOOTER_ARG("retVal=%d", retVal); \
+ return retVal; \
+ } \
+ else if (((gcsOBJECT*) (obj))->type != t) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "VERIFY_OBJECT_RETURN failed: %c%c%c%c", \
+ gcmCC_PRINT(((gcsOBJECT*) (obj))->type)); \
+ prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
+ gcmCC_PRINT(t)); \
+ prefix##ASSERT(((gcsOBJECT*)(obj))->type == t); \
+ prefix##FOOTER_ARG("retVal=%d", retVal); \
+ return retVal; \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmVERIFY_OBJECT_RETURN(obj, t, retVal) \
+ _gcmVERIFY_OBJECT_RETURN(gcm, obj, t, retVal)
+# define gcmkVERIFY_OBJECT_RETURN(obj, t, retVal) \
+ _gcmVERIFY_OBJECT_RETURN(gcmk, obj, t, retVal)
+#else
+# define gcmVERIFY_OBJECT_RETURN(obj, t) do {} while (gcvFALSE)
+# define gcmVERIFY_OBJECT_RETURN(obj, t) do {} while (gcvFALSE)
+#endif
+
+/******************************************************************************\
+********************************** gckOS Object *********************************
+\******************************************************************************/
+
+/* Construct a new gckOS object. */
+gceSTATUS
+gckOS_Construct(
+ IN gctPOINTER Context,
+ OUT gckOS * Os
+ );
+
+/* Destroy an gckOS object. */
+gceSTATUS
+gckOS_Destroy(
+ IN gckOS Os
+ );
+
+/* Query the video memory. */
+gceSTATUS
+gckOS_QueryVideoMemory(
+ IN gckOS Os,
+ OUT gctPHYS_ADDR * InternalAddress,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctPHYS_ADDR * ExternalAddress,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctPHYS_ADDR * ContiguousAddress,
+ OUT gctSIZE_T * ContiguousSize
+ );
+
+/* Allocate memory from the heap. */
+gceSTATUS
+gckOS_Allocate(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Free allocated memory. */
+gceSTATUS
+gckOS_Free(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Wrapper for allocation memory.. */
+gceSTATUS
+gckOS_AllocateMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Wrapper for freeing memory. */
+gceSTATUS
+gckOS_FreeMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Allocate paged memory. */
+gceSTATUS
+gckOS_AllocatePagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ );
+
+/* Allocate paged memory. */
+gceSTATUS
+gckOS_AllocatePagedMemoryEx(
+ IN gckOS Os,
+ IN gctUINT32 Flag,
+ IN gctSIZE_T Bytes,
+ OUT gctUINT32 * Gid,
+ OUT gctPHYS_ADDR * Physical
+ );
+
+/* Lock pages. */
+gceSTATUS
+gckOS_LockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL Cacheable,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ );
+
+/* Map pages. */
+gceSTATUS
+gckOS_MapPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T PageCount,
+ IN gctPOINTER PageTable
+ );
+
+/* Map pages. */
+gceSTATUS
+gckOS_MapPagesEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPHYS_ADDR Physical,
+ 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(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Free paged memory. */
+gceSTATUS
+gckOS_FreePagedMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Allocate non-paged memory. */
+gceSTATUS
+gckOS_AllocateNonPagedMemory(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free non-paged memory. */
+gceSTATUS
+gckOS_FreeNonPagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ );
+
+/* Allocate contiguous memory. */
+gceSTATUS
+gckOS_AllocateContiguous(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free contiguous memory. */
+gceSTATUS
+gckOS_FreeContiguous(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Get the number fo bytes per page. */
+gceSTATUS
+gckOS_GetPageSize(
+ IN gckOS Os,
+ OUT gctSIZE_T * PageSize
+ );
+
+/* Get the physical address of a corresponding logical address. */
+gceSTATUS
+gckOS_GetPhysicalAddress(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ OUT gctPHYS_ADDR_T * Address
+ );
+
+/* Get the physical address of a corresponding user logical address. */
+gceSTATUS
+gckOS_UserLogicalToPhysical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ OUT gctUINT64 * Address
+ );
+
+/* Map physical memory. */
+gceSTATUS
+gckOS_MapPhysical(
+ IN gckOS Os,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap previously mapped physical memory. */
+gceSTATUS
+gckOS_UnmapPhysical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Get real physical address from descriptor. */
+gceSTATUS
+gckOS_PhysicalToPhysicalAddress(
+ IN gckOS Os,
+ IN gctPOINTER Physical,
+ OUT gctPHYS_ADDR_T * PhysicalAddress
+ );
+
+/* Read data from a hardware register. */
+gceSTATUS
+gckOS_ReadRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ );
+
+/* Read data from a hardware register. */
+gceSTATUS
+gckOS_ReadRegisterEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ );
+
+/* Write data to a hardware register. */
+gceSTATUS
+gckOS_WriteRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ );
+
+/* Write data to a hardware register. */
+gceSTATUS
+gckOS_WriteRegisterEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ );
+
+#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(
+ IN gckOS Os,
+ IN gctPOINTER Address,
+ IN gctUINT32 Data
+ );
+
+/* Map physical memory into the process space. */
+gceSTATUS
+gckOS_MapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap physical memory from the specified process space. */
+gceSTATUS
+gckOS_UnmapMemoryEx(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical,
+ IN gctUINT32 PID
+ );
+
+/* Unmap physical memory from the process space. */
+gceSTATUS
+gckOS_UnmapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Unmap user logical memory out of physical memory.
+ * This function is only supported in Linux currently.
+ */
+gceSTATUS
+gckOS_UnmapUserLogical(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Delete a mutex. */
+gceSTATUS
+gckOS_DeleteMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/* Acquire a mutex. */
+gceSTATUS
+gckOS_AcquireMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ );
+
+/* Release a mutex. */
+gceSTATUS
+gckOS_ReleaseMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/* Atomically exchange a pair of 32-bit values. */
+gceSTATUS
+gckOS_AtomicExchange(
+ IN gckOS Os,
+ IN OUT gctUINT32_PTR Target,
+ IN gctUINT32 NewValue,
+ OUT gctUINT32_PTR OldValue
+ );
+
+/* Atomically exchange a pair of pointers. */
+gceSTATUS
+gckOS_AtomicExchangePtr(
+ IN gckOS Os,
+ IN OUT gctPOINTER * Target,
+ IN gctPOINTER NewValue,
+ OUT gctPOINTER * OldValue
+ );
+
+gceSTATUS
+gckOS_AtomSetMask(
+ IN gctPOINTER Atom,
+ IN gctUINT32 Mask
+ );
+
+gceSTATUS
+gckOS_AtomClearMask(
+ IN gctPOINTER Atom,
+ IN gctUINT32 Mask
+ );
+
+gceSTATUS
+gckOS_DumpCallStack(
+ IN gckOS Os
+ );
+
+gceSTATUS
+gckOS_GetProcessNameByPid(
+ IN gctINT Pid,
+ IN gctSIZE_T Length,
+ OUT gctUINT8_PTR String
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomConstruct
+**
+** Create an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Atom
+** Pointer to a variable receiving the constructed atom.
+*/
+gceSTATUS
+gckOS_AtomConstruct(
+ IN gckOS Os,
+ OUT gctPOINTER * Atom
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomDestroy
+**
+** Destroy an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomDestroy(
+ IN gckOS Os,
+ OUT gctPOINTER Atom
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomGet
+**
+** Get the 32-bit value protected by an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the value of the atom.
+*/
+gceSTATUS
+gckOS_AtomGet(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomSet
+**
+** Set the 32-bit value protected by an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** gctINT32 Value
+** The value of the atom.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomSet(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ IN gctINT32 Value
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomIncrement
+**
+** Atomically increment the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomIncrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomDecrement
+**
+** Atomically decrement the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomDecrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/* Delay a number of microseconds. */
+gceSTATUS
+gckOS_Delay(
+ IN gckOS Os,
+ IN gctUINT32 Delay
+ );
+
+/* Get time in milliseconds. */
+gceSTATUS
+gckOS_GetTicks(
+ OUT gctUINT32_PTR Time
+ );
+
+/* Compare time value. */
+gceSTATUS
+gckOS_TicksAfter(
+ IN gctUINT32 Time1,
+ IN gctUINT32 Time2,
+ OUT gctBOOL_PTR IsAfter
+ );
+
+/* Get time in microseconds. */
+gceSTATUS
+gckOS_GetTime(
+ OUT gctUINT64_PTR Time
+ );
+
+/* Memory barrier. */
+gceSTATUS
+gckOS_MemoryBarrier(
+ IN gckOS Os,
+ IN gctPOINTER Address
+ );
+
+/* Map user pointer. */
+gceSTATUS
+gckOS_MapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ );
+
+/* Unmap user pointer. */
+gceSTATUS
+gckOS_UnmapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ IN gctPOINTER KernelPointer
+ );
+
+/*******************************************************************************
+**
+** gckOS_QueryNeedCopy
+**
+** Query whether the memory can be accessed or mapped directly or it has to be
+** copied.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 ProcessID
+** Process ID of the current process.
+**
+** OUTPUT:
+**
+** gctBOOL_PTR NeedCopy
+** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
+** gcvFALSE if the memory can be accessed or mapped dircetly.
+*/
+gceSTATUS
+gckOS_QueryNeedCopy(
+ IN gckOS Os,
+ IN gctUINT32 ProcessID,
+ OUT gctBOOL_PTR NeedCopy
+ );
+
+/*******************************************************************************
+**
+** gckOS_CopyFromUserData
+**
+** Copy data from user to kernel memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER KernelPointer
+** Pointer to kernel memory.
+**
+** gctPOINTER Pointer
+** Pointer to user memory.
+**
+** gctSIZE_T Size
+** Number of bytes to copy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_CopyFromUserData(
+ IN gckOS Os,
+ IN gctPOINTER KernelPointer,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size
+ );
+
+/*******************************************************************************
+**
+** gckOS_CopyToUserData
+**
+** Copy data from kernel to user memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER KernelPointer
+** Pointer to kernel memory.
+**
+** gctPOINTER Pointer
+** Pointer to user memory.
+**
+** gctSIZE_T Size
+** Number of bytes to copy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_CopyToUserData(
+ IN gckOS Os,
+ IN gctPOINTER KernelPointer,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size
+ );
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+ IN gckOS Os
+ );
+
+gceSTATUS
+gckOS_SuspendInterruptEx(
+ IN gckOS Os,
+ IN gceCORE Core
+ );
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+ IN gckOS Os
+ );
+
+gceSTATUS
+gckOS_ResumeInterruptEx(
+ IN gckOS Os,
+ IN gceCORE Core
+ );
+
+/* Get the base address for the physical memory. */
+gceSTATUS
+gckOS_GetBaseAddress(
+ IN gckOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ );
+
+/* Perform a memory copy. */
+gceSTATUS
+gckOS_MemCopy(
+ IN gctPOINTER Destination,
+ IN gctCONST_POINTER Source,
+ IN gctSIZE_T Bytes
+ );
+
+/* Zero memory. */
+gceSTATUS
+gckOS_ZeroMemory(
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Bytes
+ );
+
+/* Device I/O control to the kernel HAL layer. */
+gceSTATUS
+gckOS_DeviceControl(
+ IN gckOS Os,
+ IN gctBOOL FromUser,
+ IN gctUINT32 IoControlCode,
+ IN gctPOINTER InputBuffer,
+ IN gctSIZE_T InputBufferSize,
+ OUT gctPOINTER OutputBuffer,
+ IN gctSIZE_T OutputBufferSize
+ );
+
+/*******************************************************************************
+**
+** gckOS_GetProcessID
+**
+** Get current process ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ProcessID
+** Pointer to the variable that receives the process ID.
+*/
+gceSTATUS
+gckOS_GetProcessID(
+ OUT gctUINT32_PTR ProcessID
+ );
+
+gceSTATUS
+gckOS_GetCurrentProcessID(
+ OUT gctUINT32_PTR ProcessID
+ );
+
+/*******************************************************************************
+**
+** gckOS_GetThreadID
+**
+** Get current thread ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ThreadID
+** Pointer to the variable that receives the thread ID.
+*/
+gceSTATUS
+gckOS_GetThreadID(
+ OUT gctUINT32_PTR ThreadID
+ );
+
+#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 *********************************
+\******************************************************************************/
+
+/* Create a signal. */
+gceSTATUS
+gckOS_CreateSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctSIGNAL * Signal
+ );
+
+/* Destroy a signal. */
+gceSTATUS
+gckOS_DestroySignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ );
+
+/* Signal a signal. */
+gceSTATUS
+gckOS_Signal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ );
+
+/* Wait for a signal. */
+gceSTATUS
+gckOS_WaitSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ );
+
+#ifdef __QNXNTO__
+gceSTATUS
+gckOS_SignalPulse(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ );
+
+gceSTATUS
+gckOS_SignalPending(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ );
+#endif
+
+/* Map a user signal to the kernel space. */
+gceSTATUS
+gckOS_MapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process,
+ OUT gctSIGNAL * MappedSignal
+ );
+
+/* Unmap a user signal */
+gceSTATUS
+gckOS_UnmapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ );
+
+/* Map user memory. */
+gceSTATUS
+gckOS_MapUserMemory(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPOINTER Memory,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ );
+
+/* Unmap user memory. */
+gceSTATUS
+gckOS_UnmapUserMemory(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ );
+
+/* Wrap a user memory to gctPHYS_ADDR. */
+gceSTATUS
+gckOS_WrapMemory(
+ IN gckOS Os,
+ IN gcsUSER_MEMORY_DESC_PTR Desc,
+ OUT gctSIZE_T *Bytes,
+ OUT gctPHYS_ADDR * Physical
+ );
+
+/******************************************************************************\
+************************** Android Native Fence Sync ***************************
+\******************************************************************************/
+gceSTATUS
+gckOS_CreateSyncTimeline(
+ IN gckOS Os,
+ OUT gctHANDLE * Timeline
+ );
+
+gceSTATUS
+gckOS_DestroySyncTimeline(
+ IN gckOS Os,
+ IN gctHANDLE Timeline
+ );
+
+gceSTATUS
+gckOS_CreateSyncPoint(
+ IN gckOS Os,
+ OUT gctSYNC_POINT * SyncPoint
+ );
+
+gceSTATUS
+gckOS_ReferenceSyncPoint(
+ IN gckOS Os,
+ IN gctSYNC_POINT SyncPoint
+ );
+
+gceSTATUS
+gckOS_DestroySyncPoint(
+ IN gckOS Os,
+ IN gctSYNC_POINT SyncPoint
+ );
+
+gceSTATUS
+gckOS_SignalSyncPoint(
+ IN gckOS Os,
+ IN gctSYNC_POINT SyncPoint
+ );
+
+gceSTATUS
+gckOS_QuerySyncPoint(
+ IN gckOS Os,
+ IN gctSYNC_POINT SyncPoint,
+ OUT gctBOOL_PTR State
+ );
+
+gceSTATUS
+gckOS_CreateNativeFence(
+ IN gckOS Os,
+ IN gctHANDLE Timeline,
+ IN gctSYNC_POINT SyncPoint,
+ OUT gctINT * FenceFD
+ );
+
+gceSTATUS
+gckOS_WaitNativeFence(
+ IN gckOS Os,
+ IN gctHANDLE Timeline,
+ IN gctINT FenceFD,
+ IN gctUINT32 Timeout
+ );
+
+#if !USE_NEW_LINUX_SIGNAL
+/* Create signal to be used in the user space. */
+gceSTATUS
+gckOS_CreateUserSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctINT * SignalID
+ );
+
+/* Destroy signal used in the user space. */
+gceSTATUS
+gckOS_DestroyUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID
+ );
+
+/* Wait for signal used in the user space. */
+gceSTATUS
+gckOS_WaitUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctUINT32 Wait
+ );
+
+/* Signal a signal used in the user space. */
+gceSTATUS
+gckOS_SignalUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctBOOL State
+ );
+#endif /* USE_NEW_LINUX_SIGNAL */
+
+/* Set a signal owned by a process. */
+#if defined(__QNXNTO__)
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctINT Recvid,
+ IN gctINT Coid
+ );
+#else
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process
+ );
+#endif
+
+/******************************************************************************\
+** Cache Support
+*/
+
+gceSTATUS
+gckOS_CacheClean(
+ gckOS Os,
+ gctUINT32 ProcessID,
+ gctPHYS_ADDR Handle,
+ gctPHYS_ADDR_T Physical,
+ gctPOINTER Logical,
+ gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gckOS_CacheFlush(
+ gckOS Os,
+ gctUINT32 ProcessID,
+ gctPHYS_ADDR Handle,
+ gctPHYS_ADDR_T Physical,
+ gctPOINTER Logical,
+ gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gckOS_CacheInvalidate(
+ gckOS Os,
+ gctUINT32 ProcessID,
+ gctPHYS_ADDR Handle,
+ gctPHYS_ADDR_T Physical,
+ gctPOINTER Logical,
+ gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gckOS_CPUPhysicalToGPUPhysical(
+ IN gckOS Os,
+ IN gctPHYS_ADDR_T CPUPhysical,
+ IN gctPHYS_ADDR_T * 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
+*/
+
+void
+gckOS_SetDebugLevel(
+ IN gctUINT32 Level
+ );
+
+void
+gckOS_SetDebugZone(
+ IN gctUINT32 Zone
+ );
+
+void
+gckOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ );
+
+void
+gckOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ );
+
+void
+gckOS_SetDebugFile(
+ IN gctCONST_STRING FileName
+ );
+
+/*******************************************************************************
+** Broadcast interface.
+*/
+
+typedef enum _gceBROADCAST
+{
+ /* GPU might be idle. */
+ gcvBROADCAST_GPU_IDLE,
+
+ /* A commit is going to happen. */
+ gcvBROADCAST_GPU_COMMIT,
+
+ /* GPU seems to be stuck. */
+ gcvBROADCAST_GPU_STUCK,
+
+ /* First process gets attached. */
+ gcvBROADCAST_FIRST_PROCESS,
+
+ /* Last process gets detached. */
+ gcvBROADCAST_LAST_PROCESS,
+
+ /* AXI bus error. */
+ gcvBROADCAST_AXI_BUS_ERROR,
+
+ /* Out of memory. */
+ gcvBROADCAST_OUT_OF_MEMORY,
+}
+gceBROADCAST;
+
+gceSTATUS
+gckOS_Broadcast(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gceBROADCAST Reason
+ );
+
+gceSTATUS
+gckOS_BroadcastHurry(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gctUINT Urgency
+ );
+
+gceSTATUS
+gckOS_BroadcastCalibrateSpeed(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gctUINT Idle,
+ IN gctUINT Time
+ );
+
+/*******************************************************************************
+**
+** gckOS_SetGPUPower
+**
+** Set the power of the GPU on or off.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gceCORE Core
+** GPU whose power is set.
+**
+** gctBOOL Clock
+** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
+**
+** gctBOOL Power
+** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SetGPUPower(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctBOOL Clock,
+ IN gctBOOL Power
+ );
+
+gceSTATUS
+gckOS_ResetGPU(
+ IN gckOS Os,
+ IN gceCORE Core
+ );
+
+gceSTATUS
+gckOS_PrepareGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core
+ );
+
+gceSTATUS
+gckOS_FinishGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core
+ );
+
+gceSTATUS
+gckOS_QueryGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gctUINT32 * Frequency,
+ OUT gctUINT8 * Scale
+ );
+
+gceSTATUS
+gckOS_SetGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT8 Scale
+ );
+
+/*******************************************************************************
+** Semaphores.
+*/
+
+/* Create a new semaphore. */
+gceSTATUS
+gckOS_CreateSemaphore(
+ IN gckOS Os,
+ OUT gctPOINTER * Semaphore
+ );
+
+#if gcdENABLE_VG
+gceSTATUS
+gckOS_CreateSemaphoreVG(
+ IN gckOS Os,
+ OUT gctPOINTER * Semaphore
+ );
+#endif
+
+/* Delete a semahore. */
+gceSTATUS
+gckOS_DestroySemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/* Acquire a semahore. */
+gceSTATUS
+gckOS_AcquireSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/* Try to acquire a semahore. */
+gceSTATUS
+gckOS_TryAcquireSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/* Release a semahore. */
+gceSTATUS
+gckOS_ReleaseSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/*******************************************************************************
+** Timer API.
+*/
+
+typedef void (*gctTIMERFUNCTION)(gctPOINTER);
+
+/* Create a timer. */
+gceSTATUS
+gckOS_CreateTimer(
+ IN gckOS Os,
+ IN gctTIMERFUNCTION Function,
+ IN gctPOINTER Data,
+ OUT gctPOINTER * Timer
+ );
+
+/* Destory a timer. */
+gceSTATUS
+gckOS_DestroyTimer(
+ IN gckOS Os,
+ IN gctPOINTER Timer
+ );
+
+/* Start a timer. */
+gceSTATUS
+gckOS_StartTimer(
+ IN gckOS Os,
+ IN gctPOINTER Timer,
+ IN gctUINT32 Delay
+ );
+
+/* Stop a timer. */
+gceSTATUS
+gckOS_StopTimer(
+ IN gckOS Os,
+ IN gctPOINTER Timer
+ );
+
+/******************************************************************************\
+********************************* gckHEAP Object ********************************
+\******************************************************************************/
+
+typedef struct _gckHEAP * gckHEAP;
+
+/* Construct a new gckHEAP object. */
+gceSTATUS
+gckHEAP_Construct(
+ IN gckOS Os,
+ IN gctSIZE_T AllocationSize,
+ OUT gckHEAP * Heap
+ );
+
+/* Destroy an gckHEAP object. */
+gceSTATUS
+gckHEAP_Destroy(
+ IN gckHEAP Heap
+ );
+
+/* Allocate memory. */
+gceSTATUS
+gckHEAP_Allocate(
+ IN gckHEAP Heap,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Node
+ );
+
+/* Free memory. */
+gceSTATUS
+gckHEAP_Free(
+ IN gckHEAP Heap,
+ IN gctPOINTER Node
+ );
+
+/* Profile the heap. */
+gceSTATUS
+gckHEAP_ProfileStart(
+ IN gckHEAP Heap
+ );
+
+gceSTATUS
+gckHEAP_ProfileEnd(
+ IN gckHEAP Heap,
+ IN gctCONST_STRING Title
+ );
+
+
+/******************************************************************************\
+******************************** gckVIDMEM Object ******************************
+\******************************************************************************/
+
+typedef struct _gckVIDMEM * gckVIDMEM;
+typedef struct _gckKERNEL * gckKERNEL;
+typedef struct _gckDB * gckDB;
+typedef struct _gckDVFS * gckDVFS;
+
+/* Construct a new gckVIDMEM object. */
+gceSTATUS
+gckVIDMEM_Construct(
+ IN gckOS Os,
+ IN gctUINT32 BaseAddress,
+ IN gctSIZE_T Bytes,
+ IN gctSIZE_T Threshold,
+ IN gctSIZE_T Banking,
+ OUT gckVIDMEM * Memory
+ );
+
+/* Destroy an gckVDIMEM object. */
+gceSTATUS
+gckVIDMEM_Destroy(
+ IN gckVIDMEM Memory
+ );
+
+/* Allocate 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
+ );
+
+/* Lock memory. */
+gceSTATUS
+gckVIDMEM_Lock(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ IN gctBOOL Cacheable,
+ OUT gctUINT32 * Address,
+ OUT gctUINT32 * Gid,
+ OUT gctUINT64 * PhysicalAddress
+ );
+
+/* Unlock memory. */
+gceSTATUS
+gckVIDMEM_Unlock(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ IN gceSURF_TYPE Type,
+ IN OUT gctBOOL * Asynchroneous
+ );
+
+/* Construct a gcuVIDMEM_NODE union for virtual memory. */
+gceSTATUS
+gckVIDMEM_ConstructVirtual(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Flag,
+ IN gctSIZE_T Bytes,
+ OUT gcuVIDMEM_NODE_PTR * Node
+ );
+
+/* Destroy a gcuVIDMEM_NODE union for virtual memory. */
+gceSTATUS
+gckVIDMEM_DestroyVirtual(
+ IN gcuVIDMEM_NODE_PTR Node
+ );
+
+/******************************************************************************\
+******************************** gckKERNEL Object ******************************
+\******************************************************************************/
+
+struct _gcsHAL_INTERFACE;
+
+/* Notifications. */
+typedef enum _gceNOTIFY
+{
+ gcvNOTIFY_INTERRUPT,
+ gcvNOTIFY_COMMAND_QUEUE,
+}
+gceNOTIFY;
+
+/* Flush flags. */
+typedef enum _gceKERNEL_FLUSH
+{
+ gcvFLUSH_COLOR = 0x01,
+ gcvFLUSH_DEPTH = 0x02,
+ gcvFLUSH_TEXTURE = 0x04,
+ gcvFLUSH_2D = 0x08,
+#if gcdMULTI_GPU
+ gcvFLUSH_L2 = 0x10,
+#endif
+ gcvFLUSH_TILE_STATUS = 0x20,
+ gcvFLUSH_ALL = gcvFLUSH_COLOR
+ | gcvFLUSH_DEPTH
+ | gcvFLUSH_TEXTURE
+ | gcvFLUSH_2D
+#if gcdMULTI_GPU
+ | gcvFLUSH_L2
+#endif
+ | gcvFLUSH_TILE_STATUS
+}
+gceKERNEL_FLUSH;
+
+/* Construct a new gckKERNEL object. */
+gceSTATUS
+gckKERNEL_Construct(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPOINTER Context,
+ IN gckDB SharedDB,
+ OUT gckKERNEL * Kernel
+ );
+
+/* Destroy an gckKERNEL object. */
+gceSTATUS
+gckKERNEL_Destroy(
+ IN gckKERNEL Kernel
+ );
+
+/* Dispatch a user-level command. */
+gceSTATUS
+gckKERNEL_Dispatch(
+ IN gckKERNEL Kernel,
+ IN gctBOOL FromUser,
+ IN OUT struct _gcsHAL_INTERFACE * Interface
+ );
+
+/* Query Database requirements. */
+gceSTATUS
+ gckKERNEL_QueryDatabase(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN OUT gcsHAL_INTERFACE * Interface
+ );
+
+/* Query the video memory. */
+gceSTATUS
+gckKERNEL_QueryVideoMemory(
+ IN gckKERNEL Kernel,
+ OUT struct _gcsHAL_INTERFACE * Interface
+ );
+
+/* Lookup the gckVIDMEM object for a pool. */
+gceSTATUS
+gckKERNEL_GetVideoMemoryPool(
+ IN gckKERNEL Kernel,
+ IN gcePOOL Pool,
+ OUT gckVIDMEM * VideoMemory
+ );
+
+gceSTATUS
+gckKERNEL_AllocateLinearMemory(
+ IN gckKERNEL Kernel,
+ 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_ReleaseVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle
+ );
+
+gceSTATUS
+gckKERNEL_LockVideoMemory(
+ IN gckKERNEL Kernel,
+ 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
+ );
+
+/* Map video memory. */
+gceSTATUS
+gckKERNEL_MapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+#ifdef __QNXNTO__
+ IN gctUINT32 Pid,
+ IN gctUINT32 Bytes,
+#endif
+ OUT gctPOINTER * Logical
+ );
+
+/* Map video memory. */
+gceSTATUS
+gckKERNEL_MapVideoMemoryEx(
+ IN gckKERNEL Kernel,
+ IN gceCORE Core,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+#ifdef __QNXNTO__
+ IN gctUINT32 Pid,
+ IN gctUINT32 Bytes,
+#endif
+ OUT gctPOINTER * Logical
+ );
+
+#ifdef __QNXNTO__
+/* Unmap video memory. */
+gceSTATUS
+gckKERNEL_UnmapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Pid,
+ IN gctUINT32 Bytes
+ );
+#endif
+
+/* Map memory. */
+gceSTATUS
+gckKERNEL_MapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap memory. */
+gceSTATUS
+gckKERNEL_UnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Notification of events. */
+gceSTATUS
+gckKERNEL_Notify(
+ IN gckKERNEL Kernel,
+#if gcdMULTI_GPU
+ IN gctUINT CoreId,
+#endif
+ IN gceNOTIFY Notifcation,
+ IN gctBOOL Data
+ );
+
+gceSTATUS
+gckKERNEL_QuerySettings(
+ IN gckKERNEL Kernel,
+ OUT gcsKERNEL_SETTINGS * Settings
+ );
+
+/*******************************************************************************
+**
+** gckKERNEL_Recovery
+**
+** Try to recover the GPU from a fatal error.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Recovery(
+ IN gckKERNEL Kernel
+ );
+
+/* Set the value of timeout on HW operation. */
+void
+gckKERNEL_SetTimeOut(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 timeOut
+ );
+
+/* Get access to the user data. */
+gceSTATUS
+gckKERNEL_OpenUserData(
+ IN gckKERNEL Kernel,
+ IN gctBOOL NeedCopy,
+ IN gctPOINTER StaticStorage,
+ IN gctPOINTER UserPointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ );
+
+/* Release resources associated with the user data connection. */
+gceSTATUS
+gckKERNEL_CloseUserData(
+ IN gckKERNEL Kernel,
+ IN gctBOOL NeedCopy,
+ IN gctBOOL FlushData,
+ IN gctPOINTER UserPointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ );
+
+gceSTATUS
+gckDVFS_Construct(
+ IN gckHARDWARE Hardware,
+ OUT gckDVFS * Frequency
+ );
+
+gceSTATUS
+gckDVFS_Destroy(
+ IN gckDVFS Dvfs
+ );
+
+gceSTATUS
+gckDVFS_Start(
+ IN gckDVFS Dvfs
+ );
+
+gceSTATUS
+gckDVFS_Stop(
+ IN gckDVFS Dvfs
+ );
+
+/******************************************************************************\
+******************************* gckHARDWARE Object *****************************
+\******************************************************************************/
+
+/* Construct a new gckHARDWARE object. */
+gceSTATUS
+gckHARDWARE_Construct(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gckHARDWARE * Hardware
+ );
+
+/* Destroy an gckHARDWARE object. */
+gceSTATUS
+gckHARDWARE_Destroy(
+ IN gckHARDWARE Hardware
+ );
+
+/* Get hardware type. */
+gceSTATUS
+gckHARDWARE_GetType(
+ IN gckHARDWARE Hardware,
+ OUT gceHARDWARE_TYPE * Type
+ );
+
+/* Query system memory requirements. */
+gceSTATUS
+gckHARDWARE_QuerySystemMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * SystemSize,
+ OUT gctUINT32 * SystemBaseAddress
+ );
+
+/* Build virtual address. */
+gceSTATUS
+gckHARDWARE_BuildVirtualAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Index,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ );
+
+/* Query command buffer requirements. */
+gceSTATUS
+gckHARDWARE_QueryCommandBuffer(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32 * Alignment,
+ OUT gctUINT32 * ReservedHead,
+ OUT gctUINT32 * ReservedTail
+ );
+
+/* Add a WAIT/LINK pair in the command queue. */
+gceSTATUS
+gckHARDWARE_WaitLink(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN OUT gctUINT32 * Bytes,
+ OUT gctUINT32 * WaitOffset,
+ OUT gctUINT32 * WaitBytes
+ );
+
+/* Kickstart the command processor. */
+gceSTATUS
+gckHARDWARE_Execute(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ IN gctSIZE_T Bytes
+ );
+
+/* Add an END command in the command queue. */
+gceSTATUS
+gckHARDWARE_End(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ );
+
+#if gcdMULTI_GPU
+gceSTATUS
+gckHARDWARE_ChipEnable(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gceCORE_3D_MASK ChipEnable,
+ IN OUT gctSIZE_T * Bytes
+ );
+#endif
+
+/* Add a NOP command in the command queue. */
+gceSTATUS
+gckHARDWARE_Nop(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add a PIPESELECT command in the command queue. */
+gceSTATUS
+gckHARDWARE_PipeSelect(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gcePIPE_SELECT Pipe,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Add a LINK command in the command queue. */
+gceSTATUS
+gckHARDWARE_Link(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT32 FetchSize,
+ IN OUT gctUINT32 * Bytes,
+ OUT gctUINT32 * Low,
+ OUT gctUINT32 * High
+ );
+
+/* Add an EVENT command in the command queue. */
+gceSTATUS
+gckHARDWARE_Event(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT8 Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Query the available memory. */
+gceSTATUS
+gckHARDWARE_QueryMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctUINT32 * InternalBaseAddress,
+ OUT gctUINT32 * InternalAlignment,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctUINT32 * ExternalBaseAddress,
+ OUT gctUINT32 * ExternalAlignment,
+ OUT gctUINT32 * HorizontalTileSize,
+ OUT gctUINT32 * VerticalTileSize
+ );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gckHARDWARE_QueryChipIdentity(
+ IN gckHARDWARE Hardware,
+ OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
+ );
+
+/* Query the shader uniforms support. */
+gceSTATUS
+gckHARDWARE_QueryShaderCaps(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT * VertexUniforms,
+ OUT gctUINT * FragmentUniforms,
+ OUT gctBOOL * UnifiedUnforms
+ );
+
+/* Split a harwdare specific address into API stuff. */
+gceSTATUS
+gckHARDWARE_SplitMemory(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ );
+
+/* Update command queue tail pointer. */
+gceSTATUS
+gckHARDWARE_UpdateQueueTail(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset
+ );
+
+/* Convert logical address to hardware specific address. */
+gceSTATUS
+gckHARDWARE_ConvertLogical(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctBOOL InUserSpace,
+ OUT gctUINT32 * Address
+ );
+
+/* Interrupt manager. */
+gceSTATUS
+gckHARDWARE_Interrupt(
+ IN gckHARDWARE Hardware,
+#if gcdMULTI_GPU
+ IN gctUINT CoreId,
+#endif
+ IN gctBOOL InterruptValid
+ );
+
+/* Program MMU. */
+gceSTATUS
+gckHARDWARE_SetMMU(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical
+ );
+
+/* Flush the MMU. */
+gceSTATUS
+gckHARDWARE_FlushMMU(
+ IN gckHARDWARE Hardware
+ );
+
+/* Set the page table base address. */
+gceSTATUS
+gckHARDWARE_SetMMUv2(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Enable,
+ IN gctPOINTER MtlbAddress,
+ IN gceMMU_MODE Mode,
+ IN gctPOINTER SafeAddress,
+ 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(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Wait,
+ OUT gctUINT32 * Data
+ );
+
+/* Flush the caches. */
+gceSTATUS
+gckHARDWARE_Flush(
+ IN gckHARDWARE Hardware,
+ IN gceKERNEL_FLUSH Flush,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Enable/disable fast clear. */
+gceSTATUS
+gckHARDWARE_SetFastClear(
+ IN gckHARDWARE Hardware,
+ IN gctINT Enable,
+ IN gctINT Compression
+ );
+
+gceSTATUS
+gckHARDWARE_ReadInterrupt(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR IDs
+ );
+
+/* Power management. */
+gceSTATUS
+gckHARDWARE_SetPowerManagementState(
+ IN gckHARDWARE Hardware,
+ IN gceCHIPPOWERSTATE State
+ );
+
+gceSTATUS
+gckHARDWARE_QueryPowerManagementState(
+ IN gckHARDWARE Hardware,
+ OUT gceCHIPPOWERSTATE* State
+ );
+
+gceSTATUS
+gckHARDWARE_SetPowerManagement(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL PowerManagement
+ );
+
+gceSTATUS
+gckHARDWARE_SetPowerManagementLock(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Lock
+ );
+
+gceSTATUS
+gckHARDWARE_SetGpuProfiler(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL GpuProfiler
+ );
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+gceSTATUS
+gckHARDWARE_SetFscaleValue(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 FscaleValue
+ );
+
+gceSTATUS
+gckHARDWARE_GetFscaleValue(
+ IN gckHARDWARE Hardware,
+ IN gctUINT * FscaleValue,
+ IN gctUINT * MinFscaleValue,
+ IN gctUINT * MaxFscaleValue
+ );
+
+gceSTATUS
+gckHARDWARE_SetMinFscaleValue(
+ IN gckHARDWARE Hardware,
+ IN gctUINT MinFscaleValue
+ );
+#endif
+
+#if gcdPOWEROFF_TIMEOUT
+gceSTATUS
+gckHARDWARE_SetPowerOffTimeout(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Timeout
+);
+
+gceSTATUS
+gckHARDWARE_QueryPowerOffTimeout(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32* Timeout
+);
+#endif
+
+/* Profile 2D Engine. */
+gceSTATUS
+gckHARDWARE_ProfileEngine2D(
+ IN gckHARDWARE Hardware,
+ OUT gcs2D_PROFILE_PTR Profile
+ );
+
+gceSTATUS
+gckHARDWARE_InitializeHardware(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_Reset(
+ IN gckHARDWARE Hardware
+ );
+
+typedef gceSTATUS (*gctISRMANAGERFUNC)(gctPOINTER Context);
+
+gceSTATUS
+gckHARDWARE_SetIsrManager(
+ IN gckHARDWARE Hardware,
+ IN gctISRMANAGERFUNC StartIsr,
+ IN gctISRMANAGERFUNC StopIsr,
+ IN gctPOINTER Context
+ );
+
+/* Start a composition. */
+gceSTATUS
+gckHARDWARE_Compose(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 ProcessID,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Offset,
+ IN gctSIZE_T Size,
+ IN gctUINT8 EventID
+ );
+
+/* Check for Hardware features. */
+gceSTATUS
+gckHARDWARE_IsFeatureAvailable(
+ IN gckHARDWARE Hardware,
+ IN gceFEATURE Feature
+ );
+
+gceSTATUS
+gckHARDWARE_DumpMMUException(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_DumpGPUState(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_InitDVFS(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_QueryLoad(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32 * Load
+ );
+
+gceSTATUS
+gckHARDWARE_SetDVFSPeroid(
+ IN gckHARDWARE Hardware,
+ 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
+ );
+
+gceSTATUS
+gckHARDWARE_QueryStateTimer(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT64_PTR Start,
+ OUT gctUINT64_PTR End,
+ OUT gctUINT64_PTR On,
+ OUT gctUINT64_PTR Off,
+ OUT gctUINT64_PTR Idle,
+ OUT gctUINT64_PTR Suspend
+ );
+
+#if !gcdENABLE_VG
+/******************************************************************************\
+***************************** gckINTERRUPT Object ******************************
+\******************************************************************************/
+
+typedef struct _gckINTERRUPT * gckINTERRUPT;
+
+typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
+ IN gckKERNEL Kernel
+ );
+
+gceSTATUS
+gckINTERRUPT_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckINTERRUPT * Interrupt
+ );
+
+gceSTATUS
+gckINTERRUPT_Destroy(
+ IN gckINTERRUPT Interrupt
+ );
+
+gceSTATUS
+gckINTERRUPT_SetHandler(
+ IN gckINTERRUPT Interrupt,
+ IN OUT gctINT32_PTR Id,
+ IN gctINTERRUPT_HANDLER Handler
+ );
+
+gceSTATUS
+gckINTERRUPT_Notify(
+ IN gckINTERRUPT Interrupt,
+ IN gctBOOL Valid
+ );
+#endif
+/******************************************************************************\
+******************************** gckEVENT Object *******************************
+\******************************************************************************/
+
+typedef struct _gckEVENT * gckEVENT;
+
+/* Construct a new gckEVENT object. */
+gceSTATUS
+gckEVENT_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckEVENT * Event
+ );
+
+/* Destroy an gckEVENT object. */
+gceSTATUS
+gckEVENT_Destroy(
+ IN gckEVENT Event
+ );
+
+/* Reserve the next available hardware event. */
+#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,
+ IN gctBOOL Wait,
+ OUT gctUINT8 * EventID,
+ IN gceKERNEL_WHERE Source
+ );
+#endif
+
+/* Add a new event to the list of events. */
+gceSTATUS
+gckEVENT_AddList(
+ IN gckEVENT Event,
+ IN gcsHAL_INTERFACE_PTR Interface,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gctBOOL AllocateAllowed,
+ IN gctBOOL FromKernel
+ );
+
+/* Schedule a FreeNonPagedMemory event. */
+gceSTATUS
+gckEVENT_FreeNonPagedMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a FreeContiguousMemory event. */
+gceSTATUS
+gckEVENT_FreeContiguousMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a FreeVideoMemory event. */
+gceSTATUS
+gckEVENT_FreeVideoMemory(
+ IN gckEVENT Event,
+ IN gcuVIDMEM_NODE_PTR VideoMemory,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a signal event. */
+gceSTATUS
+gckEVENT_Signal(
+ IN gckEVENT Event,
+ IN gctSIGNAL Signal,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule an Unlock event. */
+gceSTATUS
+gckEVENT_Unlock(
+ IN gckEVENT Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gctPOINTER Node,
+ IN gceSURF_TYPE Type
+ );
+
+gceSTATUS
+gckEVENT_CommitDone(
+ IN gckEVENT Event,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a FreeVirtualCommandBuffer event. */
+gceSTATUS
+gckEVENT_DestroyVirtualCommandBuffer(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+#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
+
+#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
+gckEVENT_Compose(
+ IN gckEVENT Event,
+ IN gcsHAL_COMPOSE_PTR Info
+ );
+
+/* Event callback routine. */
+gceSTATUS
+gckEVENT_Notify(
+ IN gckEVENT Event,
+ IN gctUINT32 IDs
+ );
+
+/* Event callback routine. */
+gceSTATUS
+gckEVENT_Interrupt(
+ IN gckEVENT Event,
+#if gcdMULTI_GPU
+ IN gctUINT CoreId,
+#endif
+ IN gctUINT32 IDs
+ );
+
+gceSTATUS
+gckEVENT_Dump(
+ IN gckEVENT Event
+ );
+/******************************************************************************\
+******************************* gckCOMMAND Object ******************************
+\******************************************************************************/
+
+typedef struct _gckCOMMAND * gckCOMMAND;
+
+/* Construct a new gckCOMMAND object. */
+gceSTATUS
+gckCOMMAND_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckCOMMAND * Command
+ );
+
+/* Destroy an gckCOMMAND object. */
+gceSTATUS
+gckCOMMAND_Destroy(
+ IN gckCOMMAND Command
+ );
+
+/* Acquire command queue synchronization objects. */
+gceSTATUS
+gckCOMMAND_EnterCommit(
+ IN gckCOMMAND Command,
+ IN gctBOOL FromPower
+ );
+
+/* Release command queue synchronization objects. */
+gceSTATUS
+gckCOMMAND_ExitCommit(
+ IN gckCOMMAND Command,
+ IN gctBOOL FromPower
+ );
+
+/* Start the command queue. */
+gceSTATUS
+gckCOMMAND_Start(
+ IN gckCOMMAND Command
+ );
+
+/* Stop the command queue. */
+gceSTATUS
+gckCOMMAND_Stop(
+ IN gckCOMMAND Command,
+ 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,
+ IN gcoCMDBUF CommandBuffer,
+ IN gcsSTATE_DELTA_PTR StateDelta,
+ IN gcsQUEUE_PTR EventQueue,
+ IN gctUINT32 ProcessID
+ );
+#endif
+
+/* Reserve space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Reserve(
+ IN gckCOMMAND Command,
+ IN gctUINT32 RequestedBytes,
+ OUT gctPOINTER * Buffer,
+ OUT gctUINT32 * BufferSize
+ );
+
+/* Execute reserved space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Execute(
+ IN gckCOMMAND Command,
+ 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
+gckCOMMAND_Attach(
+ IN gckCOMMAND Command,
+ OUT gckCONTEXT * Context,
+ OUT gctSIZE_T * MaxState,
+ OUT gctUINT32 * NumStates,
+ IN gctUINT32 ProcessID
+ );
+
+/* Detach user process. */
+gceSTATUS
+gckCOMMAND_Detach(
+ IN gckCOMMAND Command,
+ IN gckCONTEXT Context
+ );
+
+/* Dump command buffer being executed by GPU. */
+gceSTATUS
+gckCOMMAND_DumpExecutingBuffer(
+ IN gckCOMMAND Command
+ );
+
+/* Whether a kernel command buffer address. */
+gceSTATUS
+gckCOMMAND_AddressInKernelCommandBuffer(
+ IN gckCOMMAND Command,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * Pointer
+ );
+
+/******************************************************************************\
+********************************* gckMMU Object ********************************
+\******************************************************************************/
+
+typedef struct _gckMMU * gckMMU;
+
+/* Construct a new gckMMU object. */
+gceSTATUS
+gckMMU_Construct(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T MmuSize,
+ OUT gckMMU * Mmu
+ );
+
+/* Destroy an gckMMU object. */
+gceSTATUS
+gckMMU_Destroy(
+ IN gckMMU Mmu
+ );
+
+/* Allocate pages inside the MMU. */
+gceSTATUS
+gckMMU_AllocatePages(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ );
+
+gceSTATUS
+gckMMU_AllocatePagesEx(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ IN gceSURF_TYPE Type,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ );
+
+/* Remove a page table from the MMU. */
+gceSTATUS
+gckMMU_FreePages(
+ IN gckMMU Mmu,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ );
+
+/* Set the MMU page with info. */
+gceSTATUS
+gckMMU_SetPage(
+ IN gckMMU Mmu,
+ IN gctPHYS_ADDR_T PageAddress,
+ IN gctUINT32 *PageEntry
+ );
+
+gceSTATUS
+gckMMU_Flush(
+ IN gckMMU Mmu,
+ IN gceSURF_TYPE Type
+ );
+
+gceSTATUS
+gckMMU_DumpPageTableEntry(
+ IN gckMMU Mmu,
+ IN gctUINT32 Address
+ );
+
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gckHARDWARE_QueryProfileRegisters(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Reset,
+ OUT gcsPROFILER_COUNTERS * Counters
+ );
+#endif
+
+#if VIVANTE_PROFILER_CONTEXT
+gceSTATUS
+gckHARDWARE_QueryContextProfile(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Reset,
+ IN gckCONTEXT Context,
+ OUT gcsPROFILER_COUNTERS * Counters
+ );
+
+gceSTATUS
+gckHARDWARE_UpdateContextProfile(
+ IN gckHARDWARE Hardware,
+ IN gckCONTEXT Context
+ );
+#endif
+
+gceSTATUS
+gckHARDWARE_InitProfiler(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckOS_SignalQueryHardware(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ OUT gckHARDWARE * Hardware
+ );
+
+gceSTATUS
+gckOS_SignalSetHardware(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckOS_DetectProcessByName(
+ IN gctCONST_POINTER Name
+ );
+
+void
+gckOS_DumpParam(
+ void
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#if gcdENABLE_VG
+#include "gc_hal_vg.h"
+#endif
+
+#endif /* __gc_hal_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
new file mode 100644
index 000000000000..7a5cb12b5d18
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
@@ -0,0 +1,5737 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_base_h_
+#define __gc_hal_base_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+#include "gc_hal_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gckOS * gckOS;
+typedef struct _gcoHAL * gcoHAL;
+typedef struct _gcoOS * gcoOS;
+typedef struct _gco2D * gco2D;
+typedef struct gcsATOM * gcsATOM_PTR;
+
+#if gcdENABLE_3D
+typedef struct _gco3D * gco3D;
+typedef struct _gcoCL * gcoCL;
+typedef struct _gcsFAST_FLUSH * gcsFAST_FLUSH_PTR;
+#endif
+
+typedef struct _gcoSURF * gcoSURF;
+typedef struct _gcsSURF_INFO * gcsSURF_INFO_PTR;
+typedef struct _gcsSURF_NODE * gcsSURF_NODE_PTR;
+typedef struct _gcsSURF_FORMAT_INFO * gcsSURF_FORMAT_INFO_PTR;
+typedef struct _gcsPOINT * gcsPOINT_PTR;
+typedef struct _gcsSIZE * gcsSIZE_PTR;
+typedef struct _gcsRECT * gcsRECT_PTR;
+typedef struct _gcsBOUNDARY * gcsBOUNDARY_PTR;
+typedef struct _gcoDUMP * gcoDUMP;
+typedef struct _gcoHARDWARE * gcoHARDWARE;
+typedef union _gcuVIDMEM_NODE * gcuVIDMEM_NODE_PTR;
+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;
+#else
+typedef void * gcoVG;
+#endif
+
+#if gcdGC355_PROFILER
+typedef struct _gcsPROFILERFUNCData * gcsPROFILERFUNCData_PTR;
+typedef struct _gcsPROFILERFUNCNODE * gcsPROFILERFUNCNODE_PTR;
+#endif
+
+#if gcdSYNC
+typedef struct _gcoFENCE * gcoFENCE;
+typedef struct _gcsSYNC_CONTEXT * gcsSYNC_CONTEXT_PTR;
+#endif
+
+typedef struct _gcsUSER_MEMORY_DESC * gcsUSER_MEMORY_DESC_PTR;
+
+/******************************************************************************\
+********************* Share obj lock/unlock macros. ****************************
+\******************************************************************************/
+#define gcmLOCK_SHARE_OBJ(Obj) \
+{ \
+ if(Obj->sharedLock != gcvNULL)\
+ {\
+ (gcoOS_AcquireMutex( \
+ gcvNULL, Obj->sharedLock, gcvINFINITE));\
+ }\
+}
+
+
+#define gcmUNLOCK_SHARE_OBJ(Obj)\
+{\
+ if(Obj->sharedLock != gcvNULL)\
+ {\
+ (gcoOS_ReleaseMutex(gcvNULL, Obj->sharedLock));\
+ }\
+}
+
+#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_OES20SFT,
+ gcvPATCH_OES30SFT,
+ gcvPATCH_BASEMARKOSIICN,
+ gcvPATCH_FRUITNINJA,
+ gcvPATCH_ANDROID_WEBGL,
+#if defined(ANDROID)
+ gcePATCH_ANDROID_CTS_MEDIA_PRESENTATIONTIME,
+#endif
+ gcvPATCH_ANDROID_COMPOSITOR,
+ gcvPATCH_CTS_TEXTUREVIEW,
+ gcvPATCH_WATER2_CHUKONG,
+ gcvPATCH_GOOGLEEARTH,
+ gcvPATCH_LEANBACK,
+ gcvPATCH_ANGRYBIRDS,
+ gcvPATCH_REALRACING,
+ gcvPATCH_CLASHOFCLAN,
+ gcvPATCH_TEMPLERUN,
+ gcvPATCH_SBROWSER,
+
+ gcvPATCH_COUNT
+} gcePATCH_ID;
+#endif /* gcdENABLE_3D */
+
+#if gcdENABLE_3D
+#define gcdPROC_IS_WEBGL(patchId) ((patchId) == gcvPATCH_CHROME || (patchId) == gcvPATCH_FIREFOX || (patchId) == gcvPATCH_ANDROID_WEBGL)
+#endif /* gcdENABLE_3D */
+
+typedef void (* gctPLS_DESTRUCTOR) (
+ gcsPLS_PTR
+ );
+
+typedef struct _gcsPLS
+{
+ /* Global objects. */
+ gcoOS os;
+ gcoHAL hal;
+
+ /* Internal memory pool. */
+ gctSIZE_T internalSize;
+ gctPHYS_ADDR internalPhysical;
+ gctPOINTER internalLogical;
+
+ /* External memory pool. */
+ gctSIZE_T externalSize;
+ gctPHYS_ADDR externalPhysical;
+ gctPOINTER externalLogical;
+
+ /* Contiguous memory pool. */
+ gctSIZE_T contiguousSize;
+ gctPHYS_ADDR contiguousPhysical;
+ gctPOINTER contiguousLogical;
+
+ /* EGL-specific process-wide objects. */
+ gctPOINTER eglDisplayInfo;
+ gctPOINTER eglSurfaceInfo;
+ gceSURF_FORMAT eglConfigFormat;
+
+ /* PLS reference count */
+ gcsATOM_PTR reference;
+
+ /* PorcessID of the constrcutor process */
+ gctUINT32 processID;
+
+ /* ThreadID of the constrcutor process. */
+ gctSIZE_T threadID;
+ /* Flag for calling module destructor. */
+ gctBOOL exiting;
+
+ gctBOOL bNeedSupportNP2Texture;
+
+ 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 *************************
+\******************************************************************************/
+
+typedef struct _gcsTLS * gcsTLS_PTR;
+
+typedef void (* gctTLS_DESTRUCTOR) (
+ gcsTLS_PTR
+ );
+
+typedef struct _gcsTLS
+{
+ gceHARDWARE_TYPE currentType;
+
+ /* 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 copied;
+
+ /* libGAL.so handle */
+ gctHANDLE handle;
+
+ /* If true, do not releas 2d engine and hardware in hal layer */
+ gctBOOL release2DUpper;
+}
+gcsTLS;
+
+/******************************************************************************\
+********************************* Enumerations *********************************
+\******************************************************************************/
+
+typedef enum _gcePLS_VALUE
+{
+ gcePLS_VALUE_EGL_DISPLAY_INFO,
+ gcePLS_VALUE_EGL_SURFACE_INFO,
+ gcePLS_VALUE_EGL_CONFIG_FORMAT_INFO,
+ gcePLS_VALUE_EGL_DESTRUCTOR_INFO,
+}
+gcePLS_VALUE;
+
+/* Video memory pool type. */
+typedef enum _gcePOOL
+{
+ gcvPOOL_UNKNOWN = 0,
+ gcvPOOL_DEFAULT,
+ gcvPOOL_LOCAL,
+ gcvPOOL_LOCAL_INTERNAL,
+ gcvPOOL_LOCAL_EXTERNAL,
+ gcvPOOL_UNIFIED,
+ gcvPOOL_SYSTEM,
+ gcvPOOL_VIRTUAL,
+ gcvPOOL_USER,
+ gcvPOOL_CONTIGUOUS,
+
+ gcvPOOL_NUMBER_OF_POOLS
+}
+gcePOOL;
+
+#if gcdENABLE_3D
+/* Blending functions. */
+typedef enum _gceBLEND_FUNCTION
+{
+ gcvBLEND_ZERO,
+ gcvBLEND_ONE,
+ gcvBLEND_SOURCE_COLOR,
+ gcvBLEND_INV_SOURCE_COLOR,
+ gcvBLEND_SOURCE_ALPHA,
+ gcvBLEND_INV_SOURCE_ALPHA,
+ gcvBLEND_TARGET_COLOR,
+ gcvBLEND_INV_TARGET_COLOR,
+ gcvBLEND_TARGET_ALPHA,
+ gcvBLEND_INV_TARGET_ALPHA,
+ gcvBLEND_SOURCE_ALPHA_SATURATE,
+ gcvBLEND_CONST_COLOR,
+ gcvBLEND_INV_CONST_COLOR,
+ gcvBLEND_CONST_ALPHA,
+ gcvBLEND_INV_CONST_ALPHA,
+}
+gceBLEND_FUNCTION;
+
+/* Blending modes. */
+typedef enum _gceBLEND_MODE
+{
+ gcvBLEND_ADD,
+ gcvBLEND_SUBTRACT,
+ gcvBLEND_REVERSE_SUBTRACT,
+ gcvBLEND_MIN,
+ gcvBLEND_MAX,
+}
+gceBLEND_MODE;
+
+/* Depth modes. */
+typedef enum _gceDEPTH_MODE
+{
+ gcvDEPTH_NONE,
+ gcvDEPTH_Z,
+ gcvDEPTH_W,
+}
+gceDEPTH_MODE;
+#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
+{
+ gcvWHERE_COMMAND,
+ gcvWHERE_RASTER,
+ gcvWHERE_PIXEL,
+}
+gceWHERE;
+
+typedef enum _gceHOW
+{
+ gcvHOW_SEMAPHORE = 0x1,
+ gcvHOW_STALL = 0x2,
+ gcvHOW_SEMAPHORE_STALL = 0x3,
+}
+gceHOW;
+
+typedef enum _gceSignalHandlerType
+{
+ gcvHANDLE_SIGFPE_WHEN_SIGNAL_CODE_IS_0 = 0x1,
+}
+gceSignalHandlerType;
+
+/* gcsHAL_Limits*/
+typedef struct _gcsHAL_LIMITS
+{
+ /* chip info */
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 featureCount;
+ gctUINT32 *chipFeatures;
+
+ /* target caps */
+ gctUINT32 maxWidth;
+ gctUINT32 maxHeight;
+ gctUINT32 multiTargetCount;
+ gctUINT32 maxSamples;
+
+}gcsHAL_LIMITS;
+
+/******************************************************************************\
+*********** Generic Memory Allocation Optimization Using Containers ************
+\******************************************************************************/
+
+/* Generic container definition. */
+typedef struct _gcsCONTAINER_LINK * gcsCONTAINER_LINK_PTR;
+typedef struct _gcsCONTAINER_LINK
+{
+ /* Points to the next container. */
+ gcsCONTAINER_LINK_PTR next;
+}
+gcsCONTAINER_LINK;
+
+typedef struct _gcsCONTAINER_RECORD * gcsCONTAINER_RECORD_PTR;
+typedef struct _gcsCONTAINER_RECORD
+{
+ gcsCONTAINER_RECORD_PTR prev;
+ gcsCONTAINER_RECORD_PTR next;
+}
+gcsCONTAINER_RECORD;
+
+typedef struct _gcsCONTAINER * gcsCONTAINER_PTR;
+typedef struct _gcsCONTAINER
+{
+ gctUINT containerSize;
+ gctUINT recordSize;
+ gctUINT recordCount;
+ gcsCONTAINER_LINK_PTR containers;
+ gcsCONTAINER_RECORD freeList;
+ gcsCONTAINER_RECORD allocList;
+}
+gcsCONTAINER;
+
+#if gcdGC355_PROFILER
+/*------------------------GC355_PROFILER function node structure--------------*/
+typedef struct _gcsPROFILERFUNCData
+{
+ gctSTRING funcName;
+ gctSTRING Tag;
+ gctUINT TreeDepth;
+ gctUINT saveLayerTreeDepth;
+ gctUINT varTreeDepth;
+ gctUINT64 elapsedTime;
+ gctUINT64 cpuTime;
+ gctUINT64 gpuTime;
+}gcsPROFILERFUNCData;
+
+
+typedef struct _gcsPROFILERFUNCNODE
+{
+ gcsPROFILERFUNCData_PTR data;
+ gcsPROFILERFUNCNODE_PTR pre;
+ gcsPROFILERFUNCNODE_PTR next;
+}gcsPROFILERFUNCNODE;
+/*----------------------------------------------------------------------------*/
+#endif
+
+
+gceSTATUS
+gcsCONTAINER_Construct(
+ IN gcsCONTAINER_PTR Container,
+ gctUINT RecordsPerContainer,
+ gctUINT RecordSize
+ );
+
+gceSTATUS
+gcsCONTAINER_Destroy(
+ IN gcsCONTAINER_PTR Container
+ );
+
+gceSTATUS
+gcsCONTAINER_AllocateRecord(
+ IN gcsCONTAINER_PTR Container,
+ OUT gctPOINTER * Record
+ );
+
+gceSTATUS
+gcsCONTAINER_FreeRecord(
+ IN gcsCONTAINER_PTR Container,
+ IN gctPOINTER Record
+ );
+
+gceSTATUS
+gcsCONTAINER_FreeAll(
+ IN gcsCONTAINER_PTR Container
+ );
+
+/******************************************************************************\
+********************************* gcoHAL Object *********************************
+\******************************************************************************/
+
+/* Construct a new gcoHAL object. */
+gceSTATUS
+gcoHAL_ConstructEx(
+ IN gctPOINTER Context,
+ IN gcoOS Os,
+ OUT gcoHAL * Hal
+ );
+
+/* 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(
+ IN gctUINT FscaleValue
+ );
+
+gceSTATUS
+gcoHAL_GetFscaleValue(
+ OUT gctUINT * FscaleValue,
+ OUT gctUINT * MinFscaleValue,
+ OUT gctUINT * MaxFscaleValue
+ );
+
+gceSTATUS
+gcoHAL_SetBltNP2Texture(
+ gctBOOL enable
+ );
+
+gceSTATUS
+gcoHAL_NameVideoMemory(
+ IN gctUINT32 Handle,
+ OUT gctUINT32 * Name
+ );
+
+gceSTATUS
+gcoHAL_ImportVideoMemory(
+ IN gctUINT32 Name,
+ OUT gctUINT32 * Handle
+ );
+
+gceSTATUS
+gcoHAL_GetVideoMemoryFd(
+ IN gctUINT32 Handle,
+ OUT gctINT * Fd
+ );
+
+/* Verify whether the specified feature is available in hardware. */
+gceSTATUS
+gcoHAL_IsFeatureAvailable(
+ IN gcoHAL Hal,
+ IN gceFEATURE Feature
+ );
+
+gceSTATUS
+gcoHAL_IsSwwaNeeded(
+ IN gcoHAL Hal,
+ IN gceSWWA Swwa
+ );
+
+gceSTATUS
+gcoHAL_IsFeatureAvailable1(
+ IN gcoHAL Hal,
+ IN gceFEATURE Feature
+ );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gcoHAL_QueryChipIdentity(
+ IN gcoHAL Hal,
+ OUT gceCHIPMODEL* ChipModel,
+ OUT gctUINT32* ChipRevision,
+ OUT gctUINT32* ChipFeatures,
+ OUT gctUINT32* ChipMinorFeatures
+ );
+
+/* Query the minor features of the hardware. */
+gceSTATUS gcoHAL_QueryChipMinorFeatures(
+ IN gcoHAL Hal,
+ OUT gctUINT32* NumFeatures,
+ OUT gctUINT32* ChipMinorFeatures
+ );
+
+gctINT32
+gcoOS_EndRecordAllocation(void);
+void
+gcoOS_RecordAllocation(void);
+void
+gcoOS_AddRecordAllocation(gctSIZE_T Size);
+
+/* Query the amount of video memory. */
+gceSTATUS
+gcoHAL_QueryVideoMemory(
+ IN gcoHAL Hal,
+ OUT gctPHYS_ADDR * InternalAddress,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctPHYS_ADDR * ExternalAddress,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctPHYS_ADDR * ContiguousAddress,
+ OUT gctSIZE_T * ContiguousSize
+ );
+
+/* Map video memory. */
+gceSTATUS
+gcoHAL_MapMemory(
+ IN gcoHAL Hal,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T NumberOfBytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap video memory. */
+gceSTATUS
+gcoHAL_UnmapMemory(
+ IN gcoHAL Hal,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T NumberOfBytes,
+ IN gctPOINTER Logical
+ );
+
+/* Schedule an unmap of a buffer mapped through its physical address. */
+gceSTATUS
+gcoHAL_ScheduleUnmapMemory(
+ IN gcoHAL Hal,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T NumberOfBytes,
+ IN gctPOINTER Logical
+ );
+
+/* 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(
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR GPUAddress
+ );
+
+/* Unmap user memory. */
+gceSTATUS
+gcoHAL_UnmapUserMemory(
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 GPUAddress
+ );
+
+/* Schedule an unmap of a user buffer using event mechanism. */
+gceSTATUS
+gcoHAL_ScheduleUnmapUserMemory(
+ IN gcoHAL Hal,
+ IN gctPOINTER Info,
+ IN gctSIZE_T Size,
+ IN gctUINT32 Address,
+ IN gctPOINTER Memory
+ );
+
+/* Commit the current command buffer. */
+gceSTATUS
+gcoHAL_Commit(
+ IN gcoHAL Hal,
+ IN gctBOOL Stall
+ );
+
+#if gcdENABLE_3D
+/* Sencd fence command. */
+gceSTATUS
+gcoHAL_SendFence(
+ IN gcoHAL Hal
+ );
+#endif /* gcdENABLE_3D */
+
+/* Query the tile capabilities. */
+gceSTATUS
+gcoHAL_QueryTiled(
+ IN gcoHAL Hal,
+ OUT gctINT32 * TileWidth2D,
+ OUT gctINT32 * TileHeight2D,
+ OUT gctINT32 * TileWidth3D,
+ OUT gctINT32 * TileHeight3D
+ );
+
+gceSTATUS
+gcoHAL_Compact(
+ IN gcoHAL Hal
+ );
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gcoHAL_ProfileStart(
+ IN gcoHAL Hal
+ );
+
+gceSTATUS
+gcoHAL_ProfileEnd(
+ IN gcoHAL Hal,
+ IN gctCONST_STRING Title
+ );
+#endif
+
+/* Power Management */
+gceSTATUS
+gcoHAL_SetPowerManagementState(
+ IN gcoHAL Hal,
+ IN gceCHIPPOWERSTATE State
+ );
+
+gceSTATUS
+gcoHAL_QueryPowerManagementState(
+ IN gcoHAL Hal,
+ OUT gceCHIPPOWERSTATE *State
+ );
+
+/* Set the filter type for filter blit. */
+gceSTATUS
+gcoHAL_SetFilterType(
+ IN gcoHAL Hal,
+ IN gceFILTER_TYPE FilterType
+ );
+
+gceSTATUS
+gcoHAL_GetDump(
+ IN gcoHAL Hal,
+ OUT gcoDUMP * Dump
+ );
+
+#if gcdENABLE_3D
+gceSTATUS
+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(
+ IN gcoHAL Hal,
+ IN OUT gcsHAL_INTERFACE_PTR Interface
+ );
+
+/* Destroy a surface. */
+gceSTATUS
+gcoHAL_DestroySurface(
+ IN gcoHAL Hal,
+ IN gcoSURF Surface
+ );
+
+/* Request a start/stop timestamp. */
+gceSTATUS
+gcoHAL_SetTimer(
+ IN gcoHAL Hal,
+ IN gctUINT32 Index,
+ IN gctBOOL Start
+ );
+
+/* Get Time delta from a Timer in microseconds. */
+gceSTATUS
+gcoHAL_GetTimerTime(
+ IN gcoHAL Hal,
+ IN gctUINT32 Timer,
+ OUT gctINT32_PTR TimeDelta
+ );
+
+/* set timeout value. */
+gceSTATUS
+gcoHAL_SetTimeOut(
+ IN gcoHAL Hal,
+ IN gctUINT32 timeOut
+ );
+
+gceSTATUS
+gcoHAL_SetHardwareType(
+ IN gcoHAL Hal,
+ IN gceHARDWARE_TYPE HardwardType
+ );
+
+gceSTATUS
+gcoHAL_GetHardwareType(
+ IN gcoHAL Hal,
+ OUT gceHARDWARE_TYPE * HardwardType
+ );
+
+gceSTATUS
+gcoHAL_QueryChipCount(
+ IN gcoHAL Hal,
+ OUT gctINT32 * Count
+ );
+
+gceSTATUS
+gcoHAL_Query3DCoreCount(
+ IN gcoHAL Hal,
+ OUT gctUINT32 *Count
+ );
+
+gceSTATUS
+gcoHAL_QuerySeparated2D(
+ IN gcoHAL Hal
+ );
+
+gceSTATUS
+gcoHAL_Is3DAvailable(
+ IN gcoHAL Hal
+ );
+
+/* Get pointer to gcoVG object. */
+gceSTATUS
+gcoHAL_GetVGEngine(
+ IN gcoHAL Hal,
+ OUT gcoVG * Engine
+ );
+
+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
+ );
+
+gceSTATUS
+gcoHAL_AllocateVideoMemory(
+ IN gctUINT Alignment,
+ IN gceSURF_TYPE Type,
+ IN gctUINT32 Flag,
+ IN gcePOOL Pool,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctUINT32_PTR Node
+ );
+
+gceSTATUS
+gcoHAL_LockVideoMemory(
+ IN gctUINT32 Node,
+ IN gctBOOL Cacheable,
+ OUT gctUINT32 * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+gceSTATUS
+gcoHAL_UnlockVideoMemory(
+ IN gctUINT32 Node,
+ IN gceSURF_TYPE Type
+ );
+
+gceSTATUS
+ gcoHAL_ReleaseVideoMemory(
+ IN gctUINT32 Node
+ );
+
+#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
+
+gceSTATUS
+gcoHAL_WrapUserMemory(
+ IN gcsUSER_MEMORY_DESC_PTR UserMemoryDesc,
+ OUT gctUINT32_PTR Node
+ );
+
+/******************************************************************************\
+********************************** gcoOS Object *********************************
+\******************************************************************************/
+/* Lock PLS access */
+gceSTATUS
+gcoOS_LockPLS(
+ void
+ );
+
+/* Unlock PLS access */
+gceSTATUS
+gcoOS_UnLockPLS(
+ void
+ );
+
+/* Get PLS value for given key */
+gctPOINTER
+gcoOS_GetPLSValue(
+ IN gcePLS_VALUE key
+ );
+
+/* Set PLS value of a given key */
+void
+gcoOS_SetPLSValue(
+ IN gcePLS_VALUE key,
+ OUT gctPOINTER value
+ );
+
+/* Get access to the thread local storage. */
+gceSTATUS
+gcoOS_GetTLS(
+ OUT gcsTLS_PTR * TLS
+ );
+
+ /* Copy the TLS from a source thread. */
+ gceSTATUS gcoOS_CopyTLS(IN gcsTLS_PTR Source);
+
+/* Destroy the objects associated with the current thread. */
+void
+gcoOS_FreeThreadData(
+ void
+ );
+
+/* Empty function for compatibility. */
+gceSTATUS
+gcoOS_Construct(
+ IN gctPOINTER Context,
+ OUT gcoOS * Os
+ );
+
+/* Empty function for compatibility. */
+gceSTATUS
+gcoOS_Destroy(
+ IN gcoOS Os
+ );
+
+/* Get the base address for the physical memory. */
+gceSTATUS
+gcoOS_GetBaseAddress(
+ IN gcoOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ );
+
+/* Allocate memory from the heap. */
+gceSTATUS
+gcoOS_Allocate(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Get allocated memory size. */
+gceSTATUS
+gcoOS_GetMemorySize(
+ IN gcoOS Os,
+ IN gctPOINTER Memory,
+ OUT gctSIZE_T_PTR MemorySize
+ );
+
+/* Free allocated memory. */
+gceSTATUS
+gcoOS_Free(
+ IN gcoOS Os,
+ 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(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Free memory. */
+gceSTATUS
+gcoOS_FreeMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Allocate contiguous memory. */
+gceSTATUS
+gcoOS_AllocateContiguous(
+ IN gcoOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free contiguous memory. */
+gceSTATUS
+gcoOS_FreeContiguous(
+ IN gcoOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Map user memory. */
+gceSTATUS
+gcoOS_MapUserMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ );
+
+/* Map user memory. */
+gceSTATUS
+gcoOS_MapUserMemoryEx(
+ IN gcoOS Os,
+ IN gctPOINTER Memory,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ );
+
+/* Unmap user memory. */
+gceSTATUS
+gcoOS_UnmapUserMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ );
+
+/* Device I/O Control call to the kernel HAL layer. */
+gceSTATUS
+gcoOS_DeviceControl(
+ IN gcoOS Os,
+ IN gctUINT32 IoControlCode,
+ IN gctPOINTER InputBuffer,
+ IN gctSIZE_T InputBufferSize,
+ IN gctPOINTER OutputBuffer,
+ IN gctSIZE_T OutputBufferSize
+ );
+
+/* Allocate non paged memory. */
+gceSTATUS
+gcoOS_AllocateNonPagedMemory(
+ IN gcoOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free non paged memory. */
+gceSTATUS
+gcoOS_FreeNonPagedMemory(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ );
+
+#define gcmOS_SAFE_FREE(os, mem) \
+ gcoOS_Free(os, mem); \
+ mem = gcvNULL
+
+#define 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
+
+#define gcdMAX_PATH 512
+
+typedef enum _gceFILE_MODE
+{
+ gcvFILE_CREATE = 0,
+ gcvFILE_APPEND,
+ gcvFILE_READ,
+ gcvFILE_CREATETEXT,
+ gcvFILE_APPENDTEXT,
+ gcvFILE_READTEXT,
+}
+gceFILE_MODE;
+
+/* Open a file. */
+gceSTATUS
+gcoOS_Open(
+ IN gcoOS Os,
+ IN gctCONST_STRING FileName,
+ IN gceFILE_MODE Mode,
+ OUT gctFILE * File
+ );
+
+/* Close a file. */
+gceSTATUS
+gcoOS_Close(
+ IN gcoOS Os,
+ IN gctFILE File
+ );
+
+/* Read data from a file. */
+gceSTATUS
+gcoOS_Read(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctSIZE_T ByteCount,
+ IN gctPOINTER Data,
+ OUT gctSIZE_T * ByteRead
+ );
+
+/* Write data to a file. */
+gceSTATUS
+gcoOS_Write(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data
+ );
+
+/* Flush data to a file. */
+gceSTATUS
+gcoOS_Flush(
+ IN gcoOS Os,
+ IN gctFILE File
+ );
+
+/* Close a file descriptor. */
+gceSTATUS
+gcoOS_CloseFD(
+ IN gcoOS Os,
+ IN gctINT FD
+ );
+
+/* Scan a file. */
+gceSTATUS
+gcoOS_FscanfI(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctCONST_STRING Format,
+ OUT gctUINT *result
+ );
+
+/* Dup file descriptor to another. */
+gceSTATUS
+gcoOS_DupFD(
+ IN gcoOS Os,
+ IN gctINT FD,
+ OUT gctINT * FD2
+ );
+
+/* Create an endpoint for communication. */
+gceSTATUS
+gcoOS_Socket(
+ IN gcoOS Os,
+ IN gctINT Domain,
+ IN gctINT Type,
+ IN gctINT Protocol,
+ OUT gctINT *SockFd
+ );
+
+/* Close a socket. */
+gceSTATUS
+gcoOS_CloseSocket(
+ IN gcoOS Os,
+ IN gctINT SockFd
+ );
+
+/* Initiate a connection on a socket. */
+gceSTATUS
+gcoOS_Connect(
+ IN gcoOS Os,
+ IN gctINT SockFd,
+ IN gctCONST_POINTER HostName,
+ IN gctUINT Port);
+
+/* Shut down part of connection on a socket. */
+gceSTATUS
+gcoOS_Shutdown(
+ IN gcoOS Os,
+ IN gctINT SockFd,
+ IN gctINT How
+ );
+
+/* Send a message on a socket. */
+gceSTATUS
+gcoOS_Send(
+ IN gcoOS Os,
+ IN gctINT SockFd,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data,
+ IN gctINT Flags
+ );
+
+/* Initiate a connection on a socket. */
+gceSTATUS
+gcoOS_WaitForSend(
+ IN gcoOS Os,
+ IN gctINT SockFd,
+ IN gctINT Seconds,
+ IN gctINT MicroSeconds);
+
+/* Get environment variable value. */
+gceSTATUS
+gcoOS_GetEnv(
+ IN gcoOS Os,
+ IN gctCONST_STRING VarName,
+ OUT gctSTRING * Value
+ );
+
+/* Set environment variable value. */
+gceSTATUS
+gcoOS_SetEnv(
+ IN gcoOS Os,
+ IN gctCONST_STRING VarName,
+ IN gctSTRING Value
+ );
+
+/* Get current working directory. */
+gceSTATUS
+gcoOS_GetCwd(
+ IN gcoOS Os,
+ IN gctINT SizeInBytes,
+ OUT gctSTRING Buffer
+ );
+
+/* Get file status info. */
+gceSTATUS
+gcoOS_Stat(
+ IN gcoOS Os,
+ IN gctCONST_STRING FileName,
+ OUT gctPOINTER Buffer
+ );
+
+typedef enum _gceFILE_WHENCE
+{
+ gcvFILE_SEEK_SET,
+ gcvFILE_SEEK_CUR,
+ gcvFILE_SEEK_END
+}
+gceFILE_WHENCE;
+
+/* Set the current position of a file. */
+gceSTATUS
+gcoOS_Seek(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctUINT32 Offset,
+ IN gceFILE_WHENCE Whence
+ );
+
+/* Set the current position of a file. */
+gceSTATUS
+gcoOS_SetPos(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctUINT32 Position
+ );
+
+/* Get the current position of a file. */
+gceSTATUS
+gcoOS_GetPos(
+ IN gcoOS Os,
+ IN gctFILE File,
+ OUT gctUINT32 * Position
+ );
+
+/* Same as strstr. */
+gceSTATUS
+gcoOS_StrStr(
+ IN gctCONST_STRING String,
+ IN gctCONST_STRING SubString,
+ OUT gctSTRING * Output
+ );
+
+/* Find the last occurance of a character inside a string. */
+gceSTATUS
+gcoOS_StrFindReverse(
+ IN gctCONST_STRING String,
+ IN gctINT8 Character,
+ OUT gctSTRING * Output
+ );
+
+gceSTATUS
+gcoOS_StrDup(
+ IN gcoOS Os,
+ IN gctCONST_STRING String,
+ OUT gctSTRING * Target
+ );
+
+/* Copy a string. */
+gceSTATUS
+gcoOS_StrCopySafe(
+ IN gctSTRING Destination,
+ IN gctSIZE_T DestinationSize,
+ IN gctCONST_STRING Source
+ );
+
+/* Append a string. */
+gceSTATUS
+gcoOS_StrCatSafe(
+ IN gctSTRING Destination,
+ IN gctSIZE_T DestinationSize,
+ IN gctCONST_STRING Source
+ );
+
+/* Compare two strings. */
+gceSTATUS
+gcoOS_StrCmp(
+ IN gctCONST_STRING String1,
+ IN gctCONST_STRING String2
+ );
+
+/* Compare characters of two strings. */
+gceSTATUS
+gcoOS_StrNCmp(
+ IN gctCONST_STRING String1,
+ IN gctCONST_STRING String2,
+ IN gctSIZE_T Count
+ );
+
+/* Convert string to float. */
+gceSTATUS
+gcoOS_StrToFloat(
+ IN gctCONST_STRING String,
+ OUT gctFLOAT * Float
+ );
+
+/* Convert hex string to integer. */
+gceSTATUS gcoOS_HexStrToInt(
+ IN gctCONST_STRING String,
+ OUT gctINT * Int
+ );
+
+/* Convert hex string to float. */
+gceSTATUS
+gcoOS_HexStrToFloat(
+ IN gctCONST_STRING String,
+ OUT gctFLOAT * Float
+ );
+
+/* Convert string to integer. */
+gceSTATUS
+gcoOS_StrToInt(
+ IN gctCONST_STRING String,
+ OUT gctINT * Int
+ );
+
+gceSTATUS
+gcoOS_MemCmp(
+ IN gctCONST_POINTER Memory1,
+ IN gctCONST_POINTER Memory2,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoOS_PrintStrSafe(
+ OUT gctSTRING String,
+ IN gctSIZE_T StringSize,
+ IN OUT gctUINT * Offset,
+ IN gctCONST_STRING Format,
+ ...
+ );
+
+gceSTATUS
+gcoOS_LoadLibrary(
+ IN gcoOS Os,
+ IN gctCONST_STRING Library,
+ OUT gctHANDLE * Handle
+ );
+
+gceSTATUS
+gcoOS_FreeLibrary(
+ IN gcoOS Os,
+ IN gctHANDLE Handle
+ );
+
+gceSTATUS
+gcoOS_GetProcAddress(
+ IN gcoOS Os,
+ IN gctHANDLE Handle,
+ IN gctCONST_STRING Name,
+ OUT gctPOINTER * Function
+ );
+
+gceSTATUS
+gcoOS_Compact(
+ IN gcoOS Os
+ );
+
+gceSTATUS
+gcoOS_AddSignalHandler (
+ IN gceSignalHandlerType SignalHandlerType
+ );
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gcoOS_ProfileStart(
+ IN gcoOS Os
+ );
+
+gceSTATUS
+gcoOS_ProfileEnd(
+ IN gcoOS Os,
+ IN gctCONST_STRING Title
+ );
+
+gceSTATUS
+gcoOS_SetProfileSetting(
+ IN gcoOS Os,
+ IN gctBOOL Enable,
+ IN gctCONST_STRING FileName
+ );
+#endif
+
+/* Query the video memory. */
+gceSTATUS
+gcoOS_QueryVideoMemory(
+ IN gcoOS Os,
+ OUT gctPHYS_ADDR * InternalAddress,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctPHYS_ADDR * ExternalAddress,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctPHYS_ADDR * ContiguousAddress,
+ OUT gctSIZE_T * ContiguousSize
+ );
+
+gceSTATUS
+gcoOS_QueryCurrentProcessName(
+ OUT gctSTRING Name,
+ IN gctSIZE_T Size
+ );
+
+/* Detect if the current process is the executable specified. */
+gceSTATUS
+gcoOS_DetectProcessByName(
+ IN gctCONST_STRING Name
+ );
+
+gceSTATUS
+gcoOS_DetectProcessByEncryptedName(
+ IN gctCONST_STRING Name
+ );
+
+#if defined(ANDROID)
+gceSTATUS
+gcoOS_DetectProgrameByEncryptedSymbols(
+ IN gcoOS_SymbolsList Symbols
+ );
+#endif
+
+/*----------------------------------------------------------------------------*/
+/*----- Atoms ----------------------------------------------------------------*/
+
+/* Construct an atom. */
+gceSTATUS
+gcoOS_AtomConstruct(
+ IN gcoOS Os,
+ OUT gcsATOM_PTR * Atom
+ );
+
+/* Destroy an atom. */
+gceSTATUS
+gcoOS_AtomDestroy(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom
+ );
+
+/* 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(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom,
+ OUT gctINT32_PTR OldValue
+ );
+
+/* Decrement an atom. */
+gceSTATUS
+gcoOS_AtomDecrement(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom,
+ OUT gctINT32_PTR OldValue
+ );
+
+gctHANDLE
+gcoOS_GetCurrentProcessID(
+ void
+ );
+
+gctHANDLE
+gcoOS_GetCurrentThreadID(
+ void
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Time -----------------------------------------------------------------*/
+
+/* Get the number of milliseconds since the system started. */
+gctUINT32
+gcoOS_GetTicks(
+ void
+ );
+
+/* Get time in microseconds. */
+gceSTATUS
+gcoOS_GetTime(
+ gctUINT64_PTR Time
+ );
+
+/* Get CPU usage in microseconds. */
+gceSTATUS
+gcoOS_GetCPUTime(
+ gctUINT64_PTR CPUTime
+ );
+
+/* Get memory usage. */
+gceSTATUS
+gcoOS_GetMemoryUsage(
+ gctUINT32_PTR MaxRSS,
+ gctUINT32_PTR IxRSS,
+ gctUINT32_PTR IdRSS,
+ gctUINT32_PTR IsRSS
+ );
+
+/* Delay a number of microseconds. */
+gceSTATUS
+gcoOS_Delay(
+ IN gcoOS Os,
+ IN gctUINT32 Delay
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Threads --------------------------------------------------------------*/
+
+#ifdef _WIN32
+/* Cannot include windows.h here becuase "near" and "far"
+ * which are used in gcsDEPTH_INFO, are defined to nothing in WinDef.h.
+ * So, use the real value of DWORD and WINAPI, instead.
+ * DWORD is unsigned long, and WINAPI is __stdcall.
+ * If these two are change in WinDef.h, the following two typdefs
+ * need to be changed, too.
+ */
+typedef unsigned long gctTHREAD_RETURN;
+typedef unsigned long (__stdcall * gcTHREAD_ROUTINE)(void * Argument);
+#else
+typedef void * gctTHREAD_RETURN;
+typedef void * (* gcTHREAD_ROUTINE)(void *);
+#endif
+
+/* Create a new thread. */
+gceSTATUS
+gcoOS_CreateThread(
+ IN gcoOS Os,
+ IN gcTHREAD_ROUTINE Worker,
+ IN gctPOINTER Argument,
+ OUT gctPOINTER * Thread
+ );
+
+/* Close a thread. */
+gceSTATUS
+gcoOS_CloseThread(
+ IN gcoOS Os,
+ IN gctPOINTER Thread
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Mutexes --------------------------------------------------------------*/
+
+/* Create a new mutex. */
+gceSTATUS
+gcoOS_CreateMutex(
+ IN gcoOS Os,
+ OUT gctPOINTER * Mutex
+ );
+
+/* Delete a mutex. */
+gceSTATUS
+gcoOS_DeleteMutex(
+ IN gcoOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/* Acquire a mutex. */
+gceSTATUS
+gcoOS_AcquireMutex(
+ IN gcoOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ );
+
+/* Release a mutex. */
+gceSTATUS
+gcoOS_ReleaseMutex(
+ IN gcoOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Signals --------------------------------------------------------------*/
+
+/* Create a signal. */
+gceSTATUS
+gcoOS_CreateSignal(
+ IN gcoOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctSIGNAL * Signal
+ );
+
+/* Destroy a signal. */
+gceSTATUS
+gcoOS_DestroySignal(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal
+ );
+
+/* Signal a signal. */
+gceSTATUS
+gcoOS_Signal(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ );
+
+/* Wait for a signal. */
+gceSTATUS
+gcoOS_WaitSignal(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ );
+
+/* Map a signal from another process */
+gceSTATUS
+gcoOS_MapSignal(
+ IN gctSIGNAL RemoteSignal,
+ OUT gctSIGNAL * LocalSignal
+ );
+
+/* Unmap a signal mapped from another process */
+gceSTATUS
+gcoOS_UnmapSignal(
+ IN gctSIGNAL Signal
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Android Native Fence -------------------------------------------------*/
+
+/* Create sync point. */
+gceSTATUS
+gcoOS_CreateSyncPoint(
+ IN gcoOS Os,
+ OUT gctSYNC_POINT * SyncPoint
+ );
+
+/* Destroy sync point. */
+gceSTATUS
+gcoOS_DestroySyncPoint(
+ IN gcoOS Os,
+ IN gctSYNC_POINT SyncPoint
+ );
+
+/* Create native fence. */
+gceSTATUS
+gcoOS_CreateNativeFence(
+ IN gcoOS Os,
+ IN gctSYNC_POINT SyncPoint,
+ OUT gctINT * FenceFD
+ );
+
+/* (CPU) Wait on native fence. */
+gceSTATUS
+gcoOS_ClientWaitNativeFence(
+ IN gcoOS Os,
+ IN gctINT FenceFD,
+ IN gctUINT32 Timeout
+ );
+
+/* (GPU) Wait on native fence. */
+gceSTATUS
+gcoOS_WaitNativeFence(
+ IN gcoOS Os,
+ IN gctINT FenceFD,
+ IN gctUINT32 Timeout
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Memory Access and Cache ----------------------------------------------*/
+
+/* Write a register. */
+gceSTATUS
+gcoOS_WriteRegister(
+ IN gcoOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ );
+
+/* Read a register. */
+gceSTATUS
+gcoOS_ReadRegister(
+ IN gcoOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ );
+
+gceSTATUS
+gcoOS_CacheClean(
+ IN gcoOS Os,
+ IN gctUINT32 Node,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoOS_CacheFlush(
+ IN gcoOS Os,
+ IN gctUINT32 Node,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoOS_CacheInvalidate(
+ IN gcoOS Os,
+ IN gctUINT32 Node,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoOS_MemoryBarrier(
+ IN gcoOS Os,
+ IN gctPOINTER Logical
+ );
+
+gceSTATUS
+gcoOS_CPUPhysicalToGPUPhysical(
+ IN gctUINT32 CPUPhysical,
+ OUT gctUINT32_PTR GPUPhysical
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Profile --------------------------------------------------------------*/
+
+gceSTATUS
+gckOS_GetProfileTick(
+ OUT gctUINT64_PTR Tick
+ );
+
+gceSTATUS
+gckOS_QueryProfileTickRate(
+ OUT gctUINT64_PTR TickRate
+ );
+
+gctUINT32
+gckOS_ProfileToMS(
+ IN gctUINT64 Ticks
+ );
+
+gceSTATUS
+gcoOS_GetProfileTick(
+ OUT gctUINT64_PTR Tick
+ );
+
+gceSTATUS
+gcoOS_QueryProfileTickRate(
+ OUT gctUINT64_PTR TickRate
+ );
+
+#define _gcmPROFILE_INIT(prefix, freq, start) \
+ do { \
+ prefix ## OS_QueryProfileTickRate(&(freq)); \
+ prefix ## OS_GetProfileTick(&(start)); \
+ } while (gcvFALSE)
+
+#define _gcmPROFILE_QUERY(prefix, start, ticks) \
+ do { \
+ prefix ## OS_GetProfileTick(&(ticks)); \
+ (ticks) = ((ticks) > (start)) ? ((ticks) - (start)) \
+ : (~0ull - (start) + (ticks) + 1); \
+ } while (gcvFALSE)
+
+#if gcdENABLE_PROFILING
+# define gcmkPROFILE_INIT(freq, start) _gcmPROFILE_INIT(gck, freq, start)
+# define gcmkPROFILE_QUERY(start, ticks) _gcmPROFILE_QUERY(gck, start, ticks)
+# define gcmPROFILE_INIT(freq, start) _gcmPROFILE_INIT(gco, freq, start)
+# define gcmPROFILE_QUERY(start, ticks) _gcmPROFILE_QUERY(gco, start, ticks)
+# define gcmPROFILE_ONLY(x) x
+# define gcmPROFILE_ELSE(x) do { } while (gcvFALSE)
+# define gcmPROFILE_DECLARE_ONLY(x) x
+# define gcmPROFILE_DECLARE_ELSE(x) typedef x
+#else
+# define gcmkPROFILE_INIT(start, freq) do { } while (gcvFALSE)
+# define gcmkPROFILE_QUERY(start, ticks) do { } while (gcvFALSE)
+# define gcmPROFILE_INIT(start, freq) do { } while (gcvFALSE)
+# define gcmPROFILE_QUERY(start, ticks) do { } while (gcvFALSE)
+# define gcmPROFILE_ONLY(x) do { } while (gcvFALSE)
+# define gcmPROFILE_ELSE(x) x
+# define gcmPROFILE_DECLARE_ONLY(x) do { } while (gcvFALSE)
+# define gcmPROFILE_DECLARE_ELSE(x) x
+#endif
+
+/*******************************************************************************
+** gcoMATH object
+*/
+
+#define gcdPI 3.14159265358979323846f
+
+/* Kernel. */
+gctINT
+gckMATH_ModuloInt(
+ IN gctINT X,
+ IN gctINT Y
+ );
+
+/* User. */
+gctUINT32
+gcoMATH_Log2in5dot5(
+ IN gctINT X
+ );
+
+
+gctFLOAT
+gcoMATH_UIntAsFloat(
+ IN gctUINT32 X
+ );
+
+gctUINT32
+gcoMATH_FloatAsUInt(
+ IN gctFLOAT X
+ );
+
+gctBOOL
+gcoMATH_CompareEqualF(
+ IN gctFLOAT X,
+ IN gctFLOAT Y
+ );
+
+gctUINT16
+gcoMATH_UInt8AsFloat16(
+ IN gctUINT8 X
+ );
+
+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 *****************************
+\******************************************************************************/
+
+typedef struct _gcsPOINT
+{
+ gctINT32 x;
+ gctINT32 y;
+}
+gcsPOINT;
+
+typedef struct _gcsSIZE
+{
+ gctINT32 width;
+ gctINT32 height;
+}
+gcsSIZE;
+
+typedef struct _gcsRECT
+{
+ gctINT32 left;
+ gctINT32 top;
+ gctINT32 right;
+ gctINT32 bottom;
+}
+gcsRECT;
+
+typedef union _gcsPIXEL
+{
+ struct
+ {
+ gctFLOAT r, g, b, a;
+ gctFLOAT d, s;
+ } pf;
+
+ struct
+ {
+ gctINT32 r, g, b, a;
+ gctINT32 d, s;
+ } pi;
+
+ struct
+ {
+ gctUINT32 r, g, b, a;
+ gctUINT32 d, s;
+ } pui;
+
+} gcsPIXEL;
+
+/******************************************************************************\
+********************************* gcoSURF Object ********************************
+\******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/*------------------------------- gcoSURF Common ------------------------------*/
+
+/* Color format classes. */
+typedef enum _gceFORMAT_CLASS
+{
+ gcvFORMAT_CLASS_RGBA = 4500,
+ gcvFORMAT_CLASS_YUV,
+ gcvFORMAT_CLASS_INDEX,
+ gcvFORMAT_CLASS_LUMINANCE,
+ gcvFORMAT_CLASS_BUMP,
+ gcvFORMAT_CLASS_DEPTH,
+ 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
+{
+ gcvCOMPONENT_NOTPRESENT = 0x00,
+ gcvCOMPONENT_DONTCARE = 0x80,
+ gcvCOMPONENT_WIDTHMASK = 0x7F,
+ gcvCOMPONENT_ODD = 0x80
+}
+gceCOMPONENT_CONTROL;
+
+/* Color format component parameters. */
+typedef struct _gcsFORMAT_COMPONENT
+{
+ gctUINT8 start;
+ gctUINT8 width;
+}
+gcsFORMAT_COMPONENT;
+
+/* RGBA color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_RGBA
+{
+ gcsFORMAT_COMPONENT alpha;
+ gcsFORMAT_COMPONENT red;
+ gcsFORMAT_COMPONENT green;
+ gcsFORMAT_COMPONENT blue;
+}
+gcsFORMAT_CLASS_TYPE_RGBA;
+
+/* YUV color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_YUV
+{
+ gcsFORMAT_COMPONENT y;
+ gcsFORMAT_COMPONENT u;
+ gcsFORMAT_COMPONENT v;
+}
+gcsFORMAT_CLASS_TYPE_YUV;
+
+/* Index color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_INDEX
+{
+ gcsFORMAT_COMPONENT value;
+}
+gcsFORMAT_CLASS_TYPE_INDEX;
+
+/* Luminance color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_LUMINANCE
+{
+ gcsFORMAT_COMPONENT alpha;
+ gcsFORMAT_COMPONENT value;
+}
+gcsFORMAT_CLASS_TYPE_LUMINANCE;
+
+/* Bump map color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_BUMP
+{
+ gcsFORMAT_COMPONENT alpha;
+ gcsFORMAT_COMPONENT l;
+ gcsFORMAT_COMPONENT v;
+ gcsFORMAT_COMPONENT u;
+ gcsFORMAT_COMPONENT q;
+ gcsFORMAT_COMPONENT w;
+}
+gcsFORMAT_CLASS_TYPE_BUMP;
+
+/* Depth and stencil format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_DEPTH
+{
+ gcsFORMAT_COMPONENT depth;
+ gcsFORMAT_COMPONENT stencil;
+}
+gcsFORMAT_CLASS_TYPE_DEPTH;
+
+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;
+
+ /* 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. */
+ gctBOOL interleaved;
+
+ /* sRGB format. */
+ gctBOOL sRGB;
+
+ /* Format components. */
+ 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;
+
+/* Frame buffer information. */
+typedef struct _gcsSURF_FRAMEBUFFER
+{
+ gctPOINTER logical;
+ gctUINT width, height;
+ gctINT stride;
+ gceSURF_FORMAT format;
+}
+gcsSURF_FRAMEBUFFER;
+
+/* Generic pixel component descriptors. */
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XXX8;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XX8X;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_X8XX;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_8XXX;
+
+typedef enum _gceORIENTATION
+{
+ gcvORIENTATION_TOP_BOTTOM,
+ gcvORIENTATION_BOTTOM_TOP,
+}
+gceORIENTATION;
+
+
+/* Construct a new gcoSURF object. */
+gceSTATUS
+gcoSURF_Construct(
+ IN gcoHAL Hal,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gcePOOL Pool,
+ OUT gcoSURF * Surface
+ );
+
+/* Destroy an gcoSURF object. */
+gceSTATUS
+gcoSURF_Destroy(
+ IN gcoSURF Surface
+ );
+
+/* Map user-allocated surface. */
+gceSTATUS
+gcoSURF_MapUserSurface(
+ IN gcoSURF Surface,
+ IN gctUINT Alignment,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical
+ );
+
+/* 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 gctUINT32 * Node,
+ OUT gcePOOL * Pool,
+ OUT gctSIZE_T_PTR Bytes
+ );
+
+/* Set the color type of the surface. */
+gceSTATUS
+gcoSURF_SetColorType(
+ IN gcoSURF Surface,
+ IN gceSURF_COLOR_TYPE ColorType
+ );
+
+/* Get the color type of the surface. */
+gceSTATUS
+gcoSURF_GetColorType(
+ IN gcoSURF Surface,
+ OUT gceSURF_COLOR_TYPE *ColorType
+ );
+
+/* Set the color space of the surface. */
+gceSTATUS
+gcoSURF_SetColorSpace(
+ IN gcoSURF Surface,
+ IN gceSURF_COLOR_SPACE ColorSpace
+ );
+
+/* Get the color space of the surface. */
+gceSTATUS
+gcoSURF_GetColorSpace(
+ IN gcoSURF Surface,
+ OUT gceSURF_COLOR_SPACE *ColorSpace
+ );
+
+
+/* Set the surface ration angle. */
+gceSTATUS
+gcoSURF_SetRotation(
+ IN gcoSURF Surface,
+ IN gceSURF_ROTATION Rotation
+ );
+
+gceSTATUS
+gcoSURF_IsValid(
+ IN gcoSURF Surface
+ );
+
+#if gcdENABLE_3D
+/* Verify and return the state of the tile status mechanism. */
+gceSTATUS
+gcoSURF_IsTileStatusSupported(
+ IN gcoSURF Surface
+ );
+
+/* Verify if surface has tile status enabled. */
+gceSTATUS
+gcoSURF_IsTileStatusEnabled(
+ IN gcoSURF Surface
+ );
+
+/* Verify if surface is compressed. */
+gceSTATUS
+gcoSURF_IsCompressed(
+ IN gcoSURF 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(
+ IN gcoSURF Surface,
+ IN gctBOOL Decompress
+ );
+
+/* Flush tile status cache for the specified surface. */
+gceSTATUS
+gcoSURF_FlushTileStatus(
+ IN gcoSURF Surface,
+ IN gctBOOL Decompress
+ );
+#endif /* gcdENABLE_3D */
+
+/* Get surface size. */
+gceSTATUS
+gcoSURF_GetSize(
+ IN gcoSURF Surface,
+ OUT gctUINT * Width,
+ OUT gctUINT * Height,
+ OUT gctUINT * Depth
+ );
+
+/* Get surface aligned sizes. */
+gceSTATUS
+gcoSURF_GetAlignedSize(
+ IN gcoSURF Surface,
+ OUT gctUINT * Width,
+ OUT gctUINT * Height,
+ OUT gctINT * Stride
+ );
+
+/* Get alignments. */
+gceSTATUS
+gcoSURF_GetAlignment(
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ OUT gctUINT * AddressAlignment,
+ OUT gctUINT * XAlignment,
+ OUT gctUINT * YAlignment
+ );
+
+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 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
+ );
+
+/* Get surface tiling. */
+gceSTATUS
+gcoSURF_GetTiling(
+ IN gcoSURF Surface,
+ 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(
+ IN gcoSURF Surface,
+ IN OUT gctUINT32 * Address,
+ IN OUT gctPOINTER * Memory
+ );
+
+/* Unlock the surface. */
+gceSTATUS
+gcoSURF_Unlock(
+ IN gcoSURF Surface,
+ IN gctPOINTER Memory
+ );
+
+/*. 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,
+ OUT gcsSURF_FORMAT_INFO_PTR * Info
+ );
+
+/* Compute the color pixel mask. */
+gceSTATUS
+gcoSURF_ComputeColorMask(
+ IN gcsSURF_FORMAT_INFO_PTR Format,
+ OUT gctUINT32_PTR ColorMask
+ );
+
+/* Flush the surface. */
+gceSTATUS
+gcoSURF_Flush(
+ IN gcoSURF Surface
+ );
+
+/* Fill surface from it's tile status buffer. */
+gceSTATUS
+gcoSURF_FillFromTile(
+ IN gcoSURF Surface
+ );
+
+/* Fill surface with a value. */
+gceSTATUS
+gcoSURF_Fill(
+ IN gcoSURF Surface,
+ IN gcsPOINT_PTR Origin,
+ IN gcsSIZE_PTR Size,
+ IN gctUINT32 Value,
+ IN gctUINT32 Mask
+ );
+
+/* Alpha blend two surfaces together. */
+gceSTATUS
+gcoSURF_Blend(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gcsPOINT_PTR SrcOrig,
+ IN gcsPOINT_PTR DestOrigin,
+ IN gcsSIZE_PTR Size,
+ IN gceSURF_BLEND_MODE Mode
+ );
+
+/* Create a new gcoSURF wrapper object. */
+gceSTATUS
+gcoSURF_ConstructWrapper(
+ IN gcoHAL Hal,
+ OUT gcoSURF * Surface
+ );
+
+/* Set 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(
+ IN gcoSURF Surface,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Stride,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical
+ );
+
+/* Set the underlying video buffer for the surface wrapper. */
+gceSTATUS
+gcoSURF_SetVideoBuffer(
+ IN gcoSURF Surface,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Stride,
+ IN gctPOINTER *LogicalPlane1,
+ IN gctUINT32 *PhysicalPlane1
+ );
+
+/* Set the size of the surface in pixels and map the underlying buffer. */
+gceSTATUS
+gcoSURF_SetWindow(
+ IN gcoSURF Surface,
+ IN gctUINT X,
+ IN gctUINT Y,
+ IN gctUINT Width,
+ IN gctUINT Height
+ );
+
+/* Set width/height alignment of the surface directly and calculate stride/size. This is only for dri backend now. Please be careful before use. */
+gceSTATUS
+gcoSURF_SetAlignment(
+ IN gcoSURF Surface,
+ IN gctUINT Width,
+ IN gctUINT Height
+ );
+
+/* Increase reference count of the surface. */
+gceSTATUS
+gcoSURF_ReferenceSurface(
+ IN gcoSURF Surface
+ );
+
+/* Get surface reference count. */
+gceSTATUS
+gcoSURF_QueryReferenceCount(
+ IN gcoSURF Surface,
+ OUT gctINT32 * ReferenceCount
+ );
+
+/* Set surface orientation. */
+gceSTATUS
+gcoSURF_SetOrientation(
+ IN gcoSURF Surface,
+ IN gceORIENTATION Orientation
+ );
+
+/* Query surface orientation. */
+gceSTATUS
+gcoSURF_QueryOrientation(
+ IN gcoSURF Surface,
+ OUT gceORIENTATION * Orientation
+ );
+
+gceSTATUS
+gcoSURF_SetOffset(
+ IN gcoSURF Surface,
+ IN gctSIZE_T Offset
+ );
+
+gceSTATUS
+gcoSURF_NODE_Cache(
+ IN gcsSURF_NODE_PTR Node,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes,
+ 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(
+ IN gcoSURF Surface,
+ IN gceCACHEOPERATION Operation
+ );
+
+gceSTATUS
+gcoSURF_WrapUserMultiBuffer(
+ IN gcoHAL Hal,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Stride[3],
+ IN gctUINT32 Handle[3],
+ IN gctUINT BufferOffset[3],
+ IN gctUINT32 Flag,
+ OUT gcoSURF * Surface
+ );
+
+gceSTATUS
+gcoSURF_Swap(
+ IN gcoSURF Surface1,
+ IN gcoSURF Surface2
+ );
+
+gceSTATUS
+gcoSURF_ResetSurWH(
+ IN gcoSURF Surface,
+ 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
+ );
+
+/* 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
+ );
+
+/* Append tile status buffer. */
+gceSTATUS
+gcoSURF_AttachTileStatus(
+ IN gcoSURF Surface
+ );
+#endif
+
+gceSTATUS
+gcoSURF_WrapUserMemory(
+ IN gcoHAL Hal,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Stride,
+ IN gctUINT Depth,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT32 Handle,
+ IN gctUINT32 Flag,
+ OUT gcoSURF * Surface
+ );
+
+/******************************************************************************\
+********************************* gcoDUMP Object ********************************
+\******************************************************************************/
+
+/* Construct a new gcoDUMP object. */
+gceSTATUS
+gcoDUMP_Construct(
+ IN gcoOS Os,
+ IN gcoHAL Hal,
+ OUT gcoDUMP * Dump
+ );
+
+/* Destroy a gcoDUMP object. */
+gceSTATUS
+gcoDUMP_Destroy(
+ IN gcoDUMP Dump
+ );
+
+/* Enable/disable dumping. */
+gceSTATUS
+gcoDUMP_Control(
+ IN gcoDUMP Dump,
+ IN gctSTRING FileName
+ );
+
+gceSTATUS
+gcoDUMP_IsEnabled(
+ IN gcoDUMP Dump,
+ OUT gctBOOL * Enabled
+ );
+
+/* Add surface. */
+gceSTATUS
+gcoDUMP_AddSurface(
+ IN gcoDUMP Dump,
+ IN gctINT32 Width,
+ IN gctINT32 Height,
+ IN gceSURF_FORMAT PixelFormat,
+ IN gctUINT32 Address,
+ IN gctSIZE_T ByteCount
+ );
+
+/* Mark the beginning of a frame. */
+gceSTATUS
+gcoDUMP_FrameBegin(
+ IN gcoDUMP Dump
+ );
+
+/* Mark the end of a frame. */
+gceSTATUS
+gcoDUMP_FrameEnd(
+ IN gcoDUMP Dump
+ );
+
+/* Dump data. */
+gceSTATUS
+gcoDUMP_DumpData(
+ IN gcoDUMP Dump,
+ IN gceDUMP_TAG Type,
+ IN gctUINT32 Address,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data
+ );
+
+/* Delete an address. */
+gceSTATUS
+gcoDUMP_Delete(
+ IN gcoDUMP Dump,
+ IN gctUINT32 Address
+ );
+
+/* Enable dump or not. */
+gceSTATUS
+gcoDUMP_SetDumpFlag(
+ IN gctBOOL DumpState
+ );
+
+/******************************************************************************\
+******************************* gcsRECT Structure ******************************
+\******************************************************************************/
+
+/* Initialize rectangle structure. */
+gceSTATUS
+gcsRECT_Set(
+ OUT gcsRECT_PTR Rect,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom
+ );
+
+/* Return the width of the rectangle. */
+gceSTATUS
+gcsRECT_Width(
+ IN gcsRECT_PTR Rect,
+ OUT gctINT32 * Width
+ );
+
+/* Return the height of the rectangle. */
+gceSTATUS
+gcsRECT_Height(
+ IN gcsRECT_PTR Rect,
+ OUT gctINT32 * Height
+ );
+
+/* Ensure that top left corner is to the left and above the right bottom. */
+gceSTATUS
+gcsRECT_Normalize(
+ IN OUT gcsRECT_PTR Rect
+ );
+
+/* Compare two rectangles. */
+gceSTATUS
+gcsRECT_IsEqual(
+ IN gcsRECT_PTR Rect1,
+ IN gcsRECT_PTR Rect2,
+ OUT gctBOOL * Equal
+ );
+
+/* Compare the sizes of two rectangles. */
+gceSTATUS
+gcsRECT_IsOfEqualSize(
+ IN gcsRECT_PTR Rect1,
+ IN gcsRECT_PTR Rect2,
+ OUT gctBOOL * EqualSize
+ );
+
+gceSTATUS
+gcsRECT_RelativeRotation(
+ IN gceSURF_ROTATION Orientation,
+ IN OUT gceSURF_ROTATION *Relation);
+
+gceSTATUS
+
+gcsRECT_Rotate(
+
+ IN OUT gcsRECT_PTR Rect,
+
+ IN gceSURF_ROTATION Rotation,
+
+ IN gceSURF_ROTATION toRotation,
+
+ IN gctINT32 SurfaceWidth,
+
+ IN gctINT32 SurfaceHeight
+
+ );
+
+/******************************************************************************\
+**************************** gcsBOUNDARY Structure *****************************
+\******************************************************************************/
+
+typedef struct _gcsBOUNDARY
+{
+ gctINT x;
+ gctINT y;
+ gctINT width;
+ gctINT height;
+}
+gcsBOUNDARY;
+
+/******************************************************************************\
+********************************* gcoHEAP Object ********************************
+\******************************************************************************/
+
+typedef struct _gcoHEAP * gcoHEAP;
+
+/* Construct a new gcoHEAP object. */
+gceSTATUS
+gcoHEAP_Construct(
+ IN gcoOS Os,
+ IN gctSIZE_T AllocationSize,
+ OUT gcoHEAP * Heap
+ );
+
+/* Destroy an gcoHEAP object. */
+gceSTATUS
+gcoHEAP_Destroy(
+ IN gcoHEAP Heap
+ );
+
+/* Allocate memory. */
+gceSTATUS
+gcoHEAP_Allocate(
+ IN gcoHEAP Heap,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcoHEAP_GetMemorySize(
+ IN gcoHEAP Heap,
+ IN gctPOINTER Memory,
+ OUT gctSIZE_T_PTR MemorySize
+ );
+
+/* Free memory. */
+gceSTATUS
+gcoHEAP_Free(
+ IN gcoHEAP Heap,
+ IN gctPOINTER Node
+ );
+
+#if (VIVANTE_PROFILER || gcdDEBUG)
+/* Profile the heap. */
+gceSTATUS
+gcoHEAP_ProfileStart(
+ IN gcoHEAP Heap
+ );
+
+gceSTATUS
+gcoHEAP_ProfileEnd(
+ IN gcoHEAP Heap,
+ IN gctCONST_STRING Title
+ );
+#endif
+
+
+/******************************************************************************\
+******************************* Debugging Macros *******************************
+\******************************************************************************/
+
+void
+gcoOS_SetDebugLevel(
+ IN gctUINT32 Level
+ );
+
+void
+gcoOS_GetDebugLevel(
+ OUT gctUINT32_PTR DebugLevel
+ );
+
+void
+gcoOS_SetDebugZone(
+ IN gctUINT32 Zone
+ );
+
+void
+gcoOS_GetDebugZone(
+ IN gctUINT32 Zone,
+ OUT gctUINT32_PTR DebugZone
+ );
+
+void
+gcoOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ );
+
+void
+gcoOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ );
+
+void
+gcoOS_SetDebugFile(
+ IN gctCONST_STRING FileName
+ );
+
+gctFILE
+gcoOS_ReplaceDebugFile(
+ IN gctFILE fp
+ );
+
+void
+gcoOS_SysTraceBegin(
+ IN gctCONST_STRING FuncName
+ );
+
+void
+gcoOS_SysTraceEnd(
+ IN void);
+
+/*******************************************************************************
+**
+** gcmFATAL
+**
+** Print a message to the debugger and execute a break point.
+**
+** ARGUMENTS:
+**
+** message Message.
+** ... Optional arguments.
+*/
+
+void
+gckOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#if gcmIS_DEBUG(gcdDEBUG_FATAL)
+# define gcmFATAL gcoOS_DebugFatal
+# define gcmkFATAL gckOS_DebugFatal
+#elif gcdHAS_ELLIPSIS
+# define gcmFATAL(...)
+# define gcmkFATAL(...)
+#else
+ gcmINLINE static void
+ __dummy_fatal(
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmFATAL __dummy_fatal
+# define gcmkFATAL __dummy_fatal
+#endif
+
+#define gcmENUM2TEXT(e) case e: return #e
+
+/*******************************************************************************
+**
+** gcmTRACE
+**
+** Print a message to the debugfer if the correct level has been set. In
+** retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** level Level of message.
+** message Message.
+** ... Optional arguments.
+*/
+#define gcvLEVEL_NONE -1
+#define gcvLEVEL_ERROR 0
+#define gcvLEVEL_WARNING 1
+#define gcvLEVEL_INFO 2
+#define gcvLEVEL_VERBOSE 3
+
+void
+gckOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gckOS_DebugTraceN(
+ IN gctUINT32 Level,
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+# define gcmTRACE gcoOS_DebugTrace
+# define gcmkTRACE gckOS_DebugTrace
+# define gcmkTRACE_N gckOS_DebugTraceN
+#elif gcdHAS_ELLIPSIS
+# define gcmTRACE(...)
+# define gcmkTRACE(...)
+# define gcmkTRACE_N(...)
+#else
+ gcmINLINE static void
+ __dummy_trace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+
+ gcmINLINE static void
+ __dummy_trace_n(
+ IN gctUINT32 Level,
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+
+# define gcmTRACE __dummy_trace
+# define gcmkTRACE __dummy_trace
+# define gcmkTRACE_N __dummy_trace_n
+#endif
+
+/* Zones common for kernel and user. */
+#define gcvZONE_OS (1 << 0)
+#define gcvZONE_HARDWARE (1 << 1)
+#define gcvZONE_HEAP (1 << 2)
+#define gcvZONE_SIGNAL (1 << 27)
+
+/* Kernel zones. */
+#define gcvZONE_KERNEL (1 << 3)
+#define gcvZONE_VIDMEM (1 << 4)
+#define gcvZONE_COMMAND (1 << 5)
+#define gcvZONE_DRIVER (1 << 6)
+#define gcvZONE_CMODEL (1 << 7)
+#define gcvZONE_MMU (1 << 8)
+#define gcvZONE_EVENT (1 << 9)
+#define gcvZONE_DEVICE (1 << 10)
+#define gcvZONE_DATABASE (1 << 11)
+#define gcvZONE_INTERRUPT (1 << 12)
+#define gcvZONE_POWER (1 << 13)
+#define gcvZONE_ALLOCATOR (1 << 14)
+
+/* User zones. */
+#define gcvZONE_HAL (1 << 3)
+#define gcvZONE_BUFFER (1 << 4)
+#define gcvZONE_CONTEXT (1 << 5)
+#define gcvZONE_SURFACE (1 << 6)
+#define gcvZONE_INDEX (1 << 7)
+#define gcvZONE_STREAM (1 << 8)
+#define gcvZONE_TEXTURE (1 << 9)
+#define gcvZONE_2D (1 << 10)
+#define gcvZONE_3D (1 << 11)
+#define gcvZONE_COMPILER (1 << 12)
+#define gcvZONE_MEMORY (1 << 13)
+#define gcvZONE_STATE (1 << 14)
+#define gcvZONE_AUX (1 << 15)
+#define gcvZONE_VERTEX (1 << 16)
+#define gcvZONE_CL (1 << 17)
+#define gcvZONE_COMPOSITION (1 << 17)
+#define gcvZONE_VG (1 << 18)
+#define gcvZONE_IMAGE (1 << 19)
+#define gcvZONE_UTILITY (1 << 20)
+#define gcvZONE_PARAMETERS (1 << 21)
+#define gcvZONE_BUFOBJ (1 << 22)
+#define gcvZONE_SHADER (1 << 23)
+#define gcvZONE_STREAM_OUT (1 << 24)
+
+/* API definitions. */
+#define gcvZONE_API_HAL (1 << 28)
+#define gcvZONE_API_EGL (2 << 28)
+#define gcvZONE_API_ES11 (3 << 28)
+#define gcvZONE_API_ES20 (4 << 28)
+#define gcvZONE_API_VG11 (5 << 28)
+#define gcvZONE_API_GL (6 << 28)
+#define gcvZONE_API_DFB (7 << 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)
+/*Set gcdZONE_MASE like 0x0 | gcvZONE_API_EGL
+will enable print EGL module debug info*/
+#define gcdZONE_MASK 0x0FFFFFFF
+
+/* Handy zones. */
+#define gcvZONE_NONE 0
+#define gcvZONE_ALL 0x0FFFFFFF
+
+/*Dump API depth set 1 for API, 2 for API and API behavior*/
+#define gcvDUMP_API_DEPTH 1
+
+/*******************************************************************************
+**
+** gcmTRACE_ZONE
+**
+** Print a message to the debugger if the correct level and zone has been
+** set. In retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** Level Level of message.
+** Zone Zone of message.
+** Message Message.
+** ... Optional arguments.
+*/
+
+void
+gckOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gckOS_DebugTraceZoneN(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+# define gcmTRACE_ZONE gcoOS_DebugTraceZone
+# define gcmkTRACE_ZONE gckOS_DebugTraceZone
+# define gcmkTRACE_ZONE_N gckOS_DebugTraceZoneN
+#elif gcdHAS_ELLIPSIS
+# define gcmTRACE_ZONE(...)
+# define gcmkTRACE_ZONE(...)
+# define gcmkTRACE_ZONE_N(...)
+#else
+ gcmINLINE static void
+ __dummy_trace_zone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+
+ gcmINLINE static void
+ __dummy_trace_zone_n(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+
+# define gcmTRACE_ZONE __dummy_trace_zone
+# define gcmkTRACE_ZONE __dummy_trace_zone
+# define gcmkTRACE_ZONE_N __dummy_trace_zone_n
+#endif
+
+/*******************************************************************************
+**
+** gcmDEBUG_ONLY
+**
+** Execute a statement or function only in DEBUG mode.
+**
+** ARGUMENTS:
+**
+** f Statement or function to execute.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+# define gcmDEBUG_ONLY(f) f
+#else
+# define gcmDEBUG_ONLY(f)
+#endif
+
+/*******************************************************************************
+**
+** gcmSTACK_PUSH
+** gcmSTACK_POP
+** gcmSTACK_DUMP
+**
+** Push or pop a function with entry arguments on the trace stack.
+**
+** ARGUMENTS:
+**
+** Function Name of function.
+** Line Line number.
+** Text Optional text.
+** ... Optional arguments for text.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_STACK)
+ void gcoOS_StackPush(IN 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
+# define gcmSTACK_REMOVE gcoOS_StackRemove
+#elif gcdHAS_ELLIPSIS
+# define gcmSTACK_PUSH(...) 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(
+ IN gctCONST_STRING Function,
+ IN gctINT Line,
+ IN gctCONST_STRING Text, ...
+ )
+ {
+ }
+# define gcmSTACK_PUSH __dummy_stack_push
+# 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
+
+/******************************************************************************\
+******************************** Logging Macros ********************************
+\******************************************************************************/
+
+#define gcdHEADER_LEVEL gcvLEVEL_VERBOSE
+
+#ifndef gcdEMPTY_HEADER_FOOTER
+#define gcdEMPTY_HEADER_FOOTER 0
+#endif
+
+#if gcdENABLE_PROFILING
+void
+gcoOS_ProfileDB(
+ IN gctCONST_STRING Function,
+ IN OUT gctBOOL_PTR Initialized
+ );
+
+#define gcmHEADER() \
+ gctINT8 __user__ = 1; \
+ static gctBOOL __profile__initialized__ = gcvFALSE; \
+ 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(&__user__, __FUNCTION__, __LINE__, Text, __VA_ARGS__); \
+ gcoOS_ProfileDB(__FUNCTION__, &__profile__initialized__)
+#define gcmFOOTER() \
+ gcmSTACK_POP(&__user__, __FUNCTION__); \
+ gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
+#define gcmFOOTER_NO() \
+ gcmSTACK_POP(&__user__, __FUNCTION__); \
+ gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
+#define gcmFOOTER_ARG(...) \
+ gcmSTACK_POP(&__user__, __FUNCTION__); \
+ gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
+#define gcmFOOTER_KILL() \
+ gcmSTACK_POP(&__user__, __FUNCTION__); \
+ gcoOS_ProfileDB(gcvNULL, gcvNULL)
+
+#else /* gcdENABLE_PROFILING */
+
+#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(__user_ptr__, __FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+ gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d)", __FUNCTION__, __LINE__)
+#else
+ gcmINLINE static void
+ __dummy_header(void)
+ {
+ }
+# define gcmHEADER __dummy_header
+#endif
+
+#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(__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(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmHEADER_ARG __dummy_header_arg
+#endif
+
+#ifdef gcdFSL_REL_BUILD
+# define gcmFOOTER()
+#elif gcdEMPTY_HEADER_FOOTER
+# define gcmFOOTER()
+#elif gcdHAS_ELLIPSIS
+# define gcmFOOTER() \
+ 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
+ __dummy_footer(void)
+ {
+ }
+# define gcmFOOTER __dummy_footer
+#endif
+
+#ifdef gcdFSL_REL_BUILD
+#define gcmFOOTER_NO()
+#elif gcdEMPTY_HEADER_FOOTER
+# define gcmFOOTER_NO()
+#elif gcdHAS_ELLIPSIS
+#define gcmFOOTER_NO() \
+ 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
+#else
+ gcmINLINE static void
+ __dummy_footer_no(void)
+ {
+ }
+# define gcmFOOTER_NO __dummy_footer_no
+#endif
+
+#ifdef gcdFSL_REL_BUILD
+#define gcmFOOTER_KILL()
+#elif gcdEMPTY_HEADER_FOOTER
+# define gcmFOOTER_KILL()
+#elif gcdHAS_ELLIPSIS
+#define gcmFOOTER_KILL() \
+ 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
+#else
+ gcmINLINE static void
+ __dummy_footer_kill(void)
+ {
+ }
+# define gcmFOOTER_KILL __dummy_footer_kill
+#endif
+
+#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(__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(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmFOOTER_ARG __dummy_footer_arg
+#endif
+
+#endif /* gcdENABLE_PROFILING */
+
+#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
+ gcmINLINE static void
+ __dummy_kheader(void)
+ {
+ }
+# define gcmkHEADER __dummy_kheader
+#endif
+
+#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
+ gcmINLINE static void
+ __dummy_kheader_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmkHEADER_ARG __dummy_kheader_arg
+#endif
+
+#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)); \
+ *__kernel_ptr__ -= 1
+#else
+ gcmINLINE static void
+ __dummy_kfooter(void)
+ {
+ }
+# define gcmkFOOTER __dummy_kfooter
+#endif
+
+#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
+#else
+ gcmINLINE static void
+ __dummy_kfooter_no(void)
+ {
+ }
+# define gcmkFOOTER_NO __dummy_kfooter_no
+#endif
+
+#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__); \
+ *__kernel_ptr__ -= 1
+#else
+ gcmINLINE static void
+ __dummy_kfooter_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmkFOOTER_ARG __dummy_kfooter_arg
+#endif
+
+#define gcmOPT_VALUE(ptr) (((ptr) == gcvNULL) ? 0 : *(ptr))
+#define gcmOPT_VALUE_INDEX(ptr, index) (((ptr) == gcvNULL) ? 0 : ptr[index])
+#define gcmOPT_POINTER(ptr) (((ptr) == gcvNULL) ? gcvNULL : *(ptr))
+#define gcmOPT_STRING(ptr) (((ptr) == gcvNULL) ? "(nil)" : (ptr))
+
+void
+gckOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gckOS_PrintN(
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gckOS_CopyPrint(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#define gcmPRINT gcoOS_Print
+#define gcmkPRINT gckOS_Print
+#define gcmkPRINT_N gckOS_PrintN
+
+#if gcdPRINT_VERSION
+# define gcmPRINT_VERSION() do { \
+ _gcmPRINT_VERSION(gcm); \
+ gcmSTACK_DUMP(); \
+ } while (0)
+# define gcmkPRINT_VERSION() _gcmPRINT_VERSION(gcmk)
+# define _gcmPRINT_VERSION(prefix) \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ "Vivante HAL version %d.%d.%d build %d", \
+ gcvVERSION_MAJOR, gcvVERSION_MINOR, \
+ gcvVERSION_PATCH, gcvVERSION_BUILD)
+#else
+# define gcmPRINT_VERSION() do { gcmSTACK_DUMP(); } while (gcvFALSE)
+# define gcmkPRINT_VERSION() do { } while (gcvFALSE)
+#endif
+
+typedef enum _gceDUMP_BUFFER
+{
+ gceDUMP_BUFFER_CONTEXT,
+ gceDUMP_BUFFER_USER,
+ gceDUMP_BUFFER_KERNEL,
+ gceDUMP_BUFFER_LINK,
+ gceDUMP_BUFFER_WAITLINK,
+ gceDUMP_BUFFER_FROM_USER,
+}
+gceDUMP_BUFFER;
+
+void
+gckOS_DumpBuffer(
+ IN gckOS Os,
+ IN gctPOINTER Buffer,
+ IN gctUINT Size,
+ IN gceDUMP_BUFFER Type,
+ IN gctBOOL CopyMessage
+ );
+
+#define gcmkDUMPBUFFER gckOS_DumpBuffer
+
+#if gcdDUMP_COMMAND
+# define gcmkDUMPCOMMAND(Os, Buffer, Size, Type, CopyMessage) \
+ gcmkDUMPBUFFER(Os, Buffer, Size, Type, CopyMessage)
+#else
+# define gcmkDUMPCOMMAND(Os, Buffer, Size, Type, CopyMessage)
+#endif
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+
+void
+gckOS_DebugFlush(
+ gctCONST_STRING CallerName,
+ gctUINT LineNumber,
+ gctUINT32 DmaAddress
+ );
+
+# define gcmkDEBUGFLUSH(DmaAddress) \
+ gckOS_DebugFlush(__FUNCTION__, __LINE__, DmaAddress)
+#else
+# define gcmkDEBUGFLUSH(DmaAddress)
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_FRAMERATE
+**
+** Print average frame rate
+**
+*/
+#if gcdDUMP_FRAMERATE
+ gceSTATUS
+ gcfDumpFrameRate(
+ void
+ );
+# define gcmDUMP_FRAMERATE gcfDumpFrameRate
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_FRAMERATE(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_frame_rate(
+ void
+ )
+ {
+ }
+# define gcmDUMP_FRAMERATE __dummy_dump_frame_rate
+#endif
+
+
+/*******************************************************************************
+**
+** gcmDUMP
+**
+** Print a dump message.
+**
+** ARGUMENTS:
+**
+** gctSTRING Message.
+**
+** ... Optional arguments.
+*/
+#if gcdDUMP
+ gceSTATUS
+ gcfDump(
+ IN gcoOS Os,
+ IN gctCONST_STRING String,
+ ...
+ );
+# define gcmDUMP gcfDump
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP(...)
+#else
+ gcmINLINE static void
+ __dummy_dump(
+ IN gcoOS Os,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmDUMP __dummy_dump
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_DATA
+**
+** Add data to the dump.
+**
+** ARGUMENTS:
+**
+** gctSTRING Tag
+** Tag for dump.
+**
+** gctPOINTER Logical
+** Logical address of buffer.
+**
+** gctSIZE_T Bytes
+** Number of bytes.
+*/
+
+#if gcdDUMP || gcdDUMP_COMMAND
+ gceSTATUS
+ gcfDumpData(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+# define gcmDUMP_DATA gcfDumpData
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_DATA(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_data(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+ {
+ }
+# define gcmDUMP_DATA __dummy_dump_data
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_BUFFER
+**
+** Print a buffer to the dump.
+**
+** ARGUMENTS:
+**
+** gctSTRING Tag
+** Tag for dump.
+**
+** gctUINT32 Physical
+** Physical address of buffer.
+**
+** gctPOINTER Logical
+** Logical address of buffer.
+**
+** gctUINT32 Offset
+** Offset into buffer.
+**
+** gctSIZE_T Bytes
+** Number of bytes.
+*/
+
+#if gcdDUMP || gcdDUMP_COMMAND
+gceSTATUS
+gcfDumpBuffer(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctUINT32 Physical,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN gctSIZE_T Bytes
+ );
+# define gcmDUMP_BUFFER gcfDumpBuffer
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_BUFFER(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_buffer(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctUINT32 Physical,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN gctSIZE_T Bytes
+ )
+ {
+ }
+# define gcmDUMP_BUFFER __dummy_dump_buffer
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API
+**
+** Print a dump message for a high level API prefixed by the function name.
+**
+** ARGUMENTS:
+**
+** gctSTRING Message.
+**
+** ... Optional arguments.
+*/
+gceSTATUS gcfDumpApi(IN gctCONST_STRING String, ...);
+#if gcdDUMP_API
+# define gcmDUMP_API gcfDumpApi
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_API(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api(
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmDUMP_API __dummy_dump_api
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API_ARRAY
+**
+** Print an array of data.
+**
+** ARGUMENTS:
+**
+** gctUINT32_PTR Pointer to array.
+** gctUINT32 Size.
+*/
+gceSTATUS gcfDumpArray(IN gctCONST_POINTER Data, IN gctUINT32 Size);
+#if gcdDUMP_API
+# define gcmDUMP_API_ARRAY gcfDumpArray
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_API_ARRAY(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api_array(
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 Size
+ )
+ {
+ }
+# define gcmDUMP_API_ARRAY __dummy_dump_api_array
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API_ARRAY_TOKEN
+**
+** Print an array of data terminated by a token.
+**
+** ARGUMENTS:
+**
+** gctUINT32_PTR Pointer to array.
+** gctUINT32 Termination.
+*/
+gceSTATUS gcfDumpArrayToken(IN gctCONST_POINTER Data, IN gctUINT32 Termination);
+#if gcdDUMP_API
+# define gcmDUMP_API_ARRAY_TOKEN gcfDumpArrayToken
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_API_ARRAY_TOKEN(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api_array_token(
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 Termination
+ )
+ {
+ }
+# define gcmDUMP_API_ARRAY_TOKEN __dummy_dump_api_array_token
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API_DATA
+**
+** Print an array of bytes.
+**
+** ARGUMENTS:
+**
+** gctCONST_POINTER Pointer to array.
+** gctSIZE_T Size.
+*/
+gceSTATUS gcfDumpApiData(IN gctCONST_POINTER Data, IN gctSIZE_T Size);
+#if gcdDUMP_API
+# define gcmDUMP_API_DATA gcfDumpApiData
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_API_DATA(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api_data(
+ IN gctCONST_POINTER Data,
+ IN gctSIZE_T Size
+ )
+ {
+ }
+# define gcmDUMP_API_DATA __dummy_dump_api_data
+#endif
+
+/*******************************************************************************
+** 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
+**
+** Print a message to the shader debugger.
+**
+** ARGUMENTS:
+**
+** message Message.
+** ... Optional arguments.
+*/
+
+#define gcmTRACE_RELEASE gcoOS_DebugShaderTrace
+
+void
+gcoOS_DebugShaderTrace(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_SetDebugShaderFiles(
+ IN gctCONST_STRING VSFileName,
+ IN gctCONST_STRING FSFileName
+ );
+
+void
+gcoOS_SetDebugShaderFileType(
+ IN gctUINT32 ShaderType
+ );
+
+void
+gcoOS_EnableDebugBuffer(
+ IN gctBOOL Enable
+ );
+
+/*******************************************************************************
+**
+** gcmBREAK
+**
+** Break into the debugger. In retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** None.
+*/
+
+void
+gcoOS_DebugBreak(
+ void
+ );
+
+void
+gckOS_DebugBreak(
+ void
+ );
+
+#if gcmIS_DEBUG(gcdDEBUG_BREAK)
+# define gcmBREAK gcoOS_DebugBreak
+# define gcmkBREAK gckOS_DebugBreak
+#else
+# define gcmBREAK()
+# define gcmkBREAK()
+#endif
+
+/*******************************************************************************
+**
+** gcmASSERT
+**
+** Evaluate an expression and break into the debugger if the expression
+** evaluates to false. In retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** exp Expression to evaluate.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
+# define _gcmASSERT(prefix, exp) \
+ do \
+ { \
+ if (!(exp)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ASSERT at %s(%d)", \
+ __FUNCTION__, __LINE__); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ "(%s)", #exp); \
+ prefix##BREAK(); \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmASSERT(exp) _gcmASSERT(gcm, exp)
+# define gcmkASSERT(exp) _gcmASSERT(gcmk, exp)
+#else
+# define gcmASSERT(exp)
+# define gcmkASSERT(exp)
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFY
+**
+** Verify if an expression returns true. If the expression does not
+** evaluates to true, an assertion will happen in debug mode.
+**
+** ARGUMENTS:
+**
+** exp Expression to evaluate.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
+# define gcmVERIFY(exp) gcmASSERT(exp)
+# define gcmkVERIFY(exp) gcmkASSERT(exp)
+#else
+# define gcmVERIFY(exp) exp
+# define gcmkVERIFY(exp) exp
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFY_OK
+**
+** Verify a fucntion returns gcvSTATUS_OK. If the function does not return
+** gcvSTATUS_OK, an assertion will happen in debug mode.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+
+void
+gcoOS_Verify(
+ IN gceSTATUS status
+ );
+
+void
+gckOS_Verify(
+ IN gceSTATUS status
+ );
+
+#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
+# define gcmVERIFY_OK(func) \
+ do \
+ { \
+ gceSTATUS verifyStatus = func; \
+ gcoOS_Verify(verifyStatus); \
+ if (verifyStatus != gcvSTATUS_OK) \
+ { \
+ gcmTRACE( \
+ gcvLEVEL_ERROR, \
+ "gcmVERIFY_OK(%d): function returned %d", \
+ __LINE__, verifyStatus \
+ ); \
+ } \
+ gcmASSERT(verifyStatus == gcvSTATUS_OK); \
+ } \
+ while (gcvFALSE)
+# define gcmkVERIFY_OK(func) \
+ do \
+ { \
+ gceSTATUS verifyStatus = func; \
+ if (verifyStatus != gcvSTATUS_OK) \
+ { \
+ gcmkTRACE( \
+ gcvLEVEL_ERROR, \
+ "gcmkVERIFY_OK(%d): function returned %d", \
+ __LINE__, verifyStatus \
+ ); \
+ } \
+ gckOS_Verify(verifyStatus); \
+ gcmkASSERT(verifyStatus == gcvSTATUS_OK); \
+ } \
+ while (gcvFALSE)
+#else
+# define gcmVERIFY_OK(func) func
+# define gcmkVERIFY_OK(func) func
+#endif
+
+gctCONST_STRING
+gcoOS_DebugStatus2Name(
+ gceSTATUS status
+ );
+
+gctCONST_STRING
+gckOS_DebugStatus2Name(
+ gceSTATUS status
+ );
+
+/*******************************************************************************
+**
+** gcmERR_BREAK
+**
+** Executes a break statement on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmERR_BREAK(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_BREAK: status=%d(%s) @ %s(%d)", \
+ status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+#define _gcmkERR_BREAK(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_BREAK: status=%d(%s) @ %s(%d)", \
+ status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+#define gcmERR_BREAK(func) _gcmERR_BREAK(gcm, func)
+#define gcmkERR_BREAK(func) _gcmkERR_BREAK(gcmk, func)
+
+/*******************************************************************************
+**
+** gcmERR_RETURN
+**
+** Executes a return on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmERR_RETURN(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
+ status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+ prefix##FOOTER(); \
+ return status; \
+ } \
+ do { } while (gcvFALSE)
+#define _gcmkERR_RETURN(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
+ status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+ prefix##FOOTER(); \
+ return status; \
+ } \
+ do { } while (gcvFALSE)
+#define gcmERR_RETURN(func) _gcmERR_RETURN(gcm, func)
+#define gcmkERR_RETURN(func) _gcmkERR_RETURN(gcmk, func)
+
+
+/*******************************************************************************
+**
+** gcmONERROR
+**
+** Jump to the error handler in case there is an error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmONERROR(prefix, func) \
+ do \
+ { \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ONERROR: status=%d(%s) @ %s(%d)", \
+ status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+ goto OnError; \
+ } \
+ } \
+ while (gcvFALSE)
+#define _gcmkONERROR(prefix, func) \
+ do \
+ { \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ONERROR: status=%d(%s) @ %s(%d)", \
+ status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+ goto OnError; \
+ } \
+ } \
+ while (gcvFALSE)
+#define gcmONERROR(func) _gcmONERROR(gcm, func)
+#define gcmkONERROR(func) _gcmkONERROR(gcmk, func)
+
+/*******************************************************************************
+**
+** 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)
+
+/*******************************************************************************
+**
+** gcmkSAFECASTPHYSADDRT
+**
+** Check whether value of a gctPHYS_ADDR_T variable beyond the capability
+** of 32bits GPU hardware.
+**
+** ASSUMPTIONS:
+**
+**
+**
+** ARGUMENTS:
+**
+** x A gctUINT32 variable
+** y A gctSIZE_T variable
+*/
+#define gcmkSAFECASTPHYSADDRT(x, y) \
+ do \
+ { \
+ gctUINT32 tmp = (gctUINT32)(y); \
+ if (gcmSIZEOF(gctPHYS_ADDR_T) > gcmSIZEOF(gctUINT32)) \
+ { \
+ gcmkASSERT(tmp <= gcvMAXUINT32); \
+ } \
+ (x) = tmp; \
+ } \
+ while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmVERIFY_LOCK
+**
+** Verifies whether the surface is locked.
+**
+** ARGUMENTS:
+**
+** surfaceInfo Pointer to the surface iniformational structure.
+*/
+#define gcmVERIFY_LOCK(surfaceInfo) \
+ if (!surfaceInfo->node.valid) \
+ { \
+ gcmONERROR(gcvSTATUS_MEMORY_UNLOCKED); \
+ } \
+
+/*******************************************************************************
+**
+** gcmVERIFY_NODE_LOCK
+**
+** Verifies whether the surface node is locked.
+**
+** ARGUMENTS:
+**
+** surfaceInfo Pointer to the surface iniformational structure.
+*/
+#define gcmVERIFY_NODE_LOCK(surfaceNode) \
+ if (!(surfaceNode)->valid) \
+ { \
+ status = gcvSTATUS_MEMORY_UNLOCKED; \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmBADOBJECT_BREAK
+**
+** Executes a break statement on bad object.
+**
+** ARGUMENTS:
+**
+** obj Object to test.
+** t Expected type of the object.
+*/
+#define gcmBADOBJECT_BREAK(obj, t) \
+ if ((obj == gcvNULL) \
+ || (((gcsOBJECT *)(obj))->type != t) \
+ ) \
+ { \
+ status = gcvSTATUS_INVALID_OBJECT; \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmCHECK_STATUS
+**
+** Executes a break statement on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmCHECK_STATUS(prefix, func) \
+ do \
+ { \
+ last = func; \
+ if (gcmIS_ERROR(last)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "CHECK_STATUS: status=%d(%s) @ %s(%d)", \
+ last, gcoOS_DebugStatus2Name(last), __FUNCTION__, __LINE__); \
+ status = last; \
+ } \
+ } \
+ while (gcvFALSE)
+#define _gcmkCHECK_STATUS(prefix, func) \
+ do \
+ { \
+ last = func; \
+ if (gcmIS_ERROR(last)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "CHECK_STATUS: status=%d(%s) @ %s(%d)", \
+ last, gckOS_DebugStatus2Name(last), __FUNCTION__, __LINE__); \
+ status = last; \
+ } \
+ } \
+ while (gcvFALSE)
+#define gcmCHECK_STATUS(func) _gcmCHECK_STATUS(gcm, func)
+#define gcmkCHECK_STATUS(func) _gcmkCHECK_STATUS(gcmk, func)
+
+/*******************************************************************************
+**
+** gcmVERIFY_ARGUMENT
+**
+** Assert if an argument does not apply to the specified expression. If
+** the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
+** returned from the current function. In retail mode this macro does
+** nothing.
+**
+** ARGUMENTS:
+**
+** arg Argument to evaluate.
+*/
+# define _gcmVERIFY_ARGUMENT(prefix, arg) \
+ do \
+ { \
+ if (!(arg)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, #prefix "VERIFY_ARGUMENT failed:"); \
+ prefix##ASSERT(arg); \
+ prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT); \
+ return gcvSTATUS_INVALID_ARGUMENT; \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmVERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcm, arg)
+# define gcmkVERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcmk, arg)
+
+/*******************************************************************************
+**
+** gcmDEBUG_VERIFY_ARGUMENT
+**
+** Works just like gcmVERIFY_ARGUMENT, but is only valid in debug mode.
+** Use this to verify arguments inside non-public API functions.
+*/
+#if gcdDEBUG
+# define gcmDEBUG_VERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcm, arg)
+# define gcmkDEBUG_VERIFY_ARGUMENT(arg) _gcmkVERIFY_ARGUMENT(gcm, arg)
+#else
+# define gcmDEBUG_VERIFY_ARGUMENT(arg)
+# define gcmkDEBUG_VERIFY_ARGUMENT(arg)
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFY_ARGUMENT_RETURN
+**
+** Assert if an argument does not apply to the specified expression. If
+** the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
+** returned from the current function. In retail mode this macro does
+** nothing.
+**
+** ARGUMENTS:
+**
+** arg Argument to evaluate.
+*/
+# define _gcmVERIFY_ARGUMENT_RETURN(prefix, arg, value) \
+ do \
+ { \
+ if (!(arg)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "gcmVERIFY_ARGUMENT_RETURN failed:"); \
+ prefix##ASSERT(arg); \
+ prefix##FOOTER_ARG("value=%d", value); \
+ return value; \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmVERIFY_ARGUMENT_RETURN(arg, value) \
+ _gcmVERIFY_ARGUMENT_RETURN(gcm, arg, value)
+# define gcmkVERIFY_ARGUMENT_RETURN(arg, value) \
+ _gcmVERIFY_ARGUMENT_RETURN(gcmk, arg, value)
+
+#define MAX_LOOP_COUNT 0x7FFFFFFF
+
+/******************************************************************************\
+****************************** User Debug Option ******************************
+\******************************************************************************/
+
+/* User option. */
+typedef enum _gceDEBUG_MSG
+{
+ gcvDEBUG_MSG_NONE,
+ gcvDEBUG_MSG_ERROR,
+ gcvDEBUG_MSG_WARNING
+}
+gceDEBUG_MSG;
+
+typedef struct _gcsUSER_DEBUG_OPTION
+{
+ gceDEBUG_MSG debugMsg;
+}
+gcsUSER_DEBUG_OPTION;
+
+gcsUSER_DEBUG_OPTION *
+gcGetUserDebugOption(
+ void
+ );
+
+#if defined(ANDROID)
+struct _gcoOS_SymbolsList
+{
+#if gcdENABLE_3D
+ gcePATCH_ID patchId;
+#endif
+ const char * symList[10];
+};
+#endif
+
+#if gcdHAS_ELLIPSIS
+#define gcmUSER_DEBUG_MSG(level, ...) \
+ do \
+ { \
+ if (level <= gcGetUserDebugOption()->debugMsg) \
+ { \
+ gcoOS_Print(__VA_ARGS__); \
+ } \
+ } while (gcvFALSE)
+
+#define gcmUSER_DEBUG_ERROR_MSG(...) gcmUSER_DEBUG_MSG(gcvDEBUG_MSG_ERROR, "Error: " __VA_ARGS__)
+#define gcmUSER_DEBUG_WARNING_MSG(...) gcmUSER_DEBUG_MSG(gcvDEBUG_MSG_WARNING, "Warring: " __VA_ARGS__)
+#else
+#define gcmUSER_DEBUG_MSG
+#define gcmUSER_DEBUG_ERROR_MSG
+#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; \
+ VsConstMax = gcmMIN(512, NumConstants - 64); \
+ PsConstMax = gcmMIN(512, NumConstants - 64); \
+ ConstMax = NumConstants; \
+ } \
+ 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
+
+#endif /* __gc_hal_base_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h
new file mode 100644
index 000000000000..8a4be08b8404
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h
@@ -0,0 +1,1275 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_driver_h_
+#define __gc_hal_driver_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+
+#if gcdENABLE_VG
+#include "gc_hal_driver_vg.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* I/O Control Codes ******************************
+\******************************************************************************/
+
+#define gcvHAL_CLASS "galcore"
+#define IOCTL_GCHAL_INTERFACE 30000
+#define IOCTL_GCHAL_KERNEL_INTERFACE 30001
+#define IOCTL_GCHAL_TERMINATE 30002
+
+#undef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
+/******************************************************************************\
+********************************* Command Codes ********************************
+\******************************************************************************/
+
+typedef enum _gceHAL_COMMAND_CODES
+{
+ /* Generic query. */
+ gcvHAL_QUERY_VIDEO_MEMORY,
+ gcvHAL_QUERY_CHIP_IDENTITY,
+
+ /* Contiguous memory. */
+ gcvHAL_ALLOCATE_NON_PAGED_MEMORY,
+ gcvHAL_FREE_NON_PAGED_MEMORY,
+ gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY,
+ gcvHAL_FREE_CONTIGUOUS_MEMORY,
+
+ /* Video memory allocation. */
+ gcvHAL_ALLOCATE_VIDEO_MEMORY, /* Enforced alignment. */
+ gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY, /* No alignment. */
+ gcvHAL_RELEASE_VIDEO_MEMORY,
+
+ /* Physical-to-logical mapping. */
+ gcvHAL_MAP_MEMORY,
+ gcvHAL_UNMAP_MEMORY,
+
+ /* Logical-to-physical mapping. */
+ gcvHAL_MAP_USER_MEMORY,
+ gcvHAL_UNMAP_USER_MEMORY,
+
+ /* Surface lock/unlock. */
+ gcvHAL_LOCK_VIDEO_MEMORY,
+ gcvHAL_UNLOCK_VIDEO_MEMORY,
+
+ /* Event queue. */
+ gcvHAL_EVENT_COMMIT,
+
+ gcvHAL_USER_SIGNAL,
+ gcvHAL_SIGNAL,
+ gcvHAL_WRITE_DATA,
+
+ gcvHAL_COMMIT,
+ gcvHAL_STALL,
+
+ gcvHAL_READ_REGISTER,
+ gcvHAL_WRITE_REGISTER,
+
+ gcvHAL_GET_PROFILE_SETTING,
+ gcvHAL_SET_PROFILE_SETTING,
+
+ gcvHAL_READ_ALL_PROFILE_REGISTERS,
+ gcvHAL_PROFILE_REGISTERS_2D,
+#if VIVANTE_PROFILER_PERDRAW
+ gcvHAL_READ_PROFILER_REGISTER_SETTING,
+#endif
+
+ /* Power management. */
+ gcvHAL_SET_POWER_MANAGEMENT_STATE,
+ gcvHAL_QUERY_POWER_MANAGEMENT_STATE,
+
+ gcvHAL_GET_BASE_ADDRESS,
+
+ gcvHAL_SET_IDLE, /* reserved */
+
+ /* Queries. */
+ gcvHAL_QUERY_KERNEL_SETTINGS,
+
+ /* Reset. */
+ gcvHAL_RESET,
+
+ /* Map physical address into handle. */
+ gcvHAL_MAP_PHYSICAL,
+
+ /* Debugger stuff. */
+ gcvHAL_DEBUG,
+
+ /* Cache stuff. */
+ gcvHAL_CACHE,
+
+ /* TimeStamp */
+ gcvHAL_TIMESTAMP,
+
+ /* Database. */
+ gcvHAL_DATABASE,
+
+ /* Version. */
+ gcvHAL_VERSION,
+
+ /* Chip info */
+ gcvHAL_CHIP_INFO,
+
+ /* Process attaching/detaching. */
+ gcvHAL_ATTACH,
+ gcvHAL_DETACH,
+
+ /* Composition. */
+ gcvHAL_COMPOSE,
+
+ /* Set timeOut value */
+ gcvHAL_SET_TIMEOUT,
+
+ /* Frame database. */
+ gcvHAL_GET_FRAME_INFO,
+
+ gcvHAL_QUERY_COMMAND_BUFFER,
+
+ gcvHAL_COMMIT_DONE,
+
+ /* GPU and event dump */
+ gcvHAL_DUMP_GPU_STATE,
+ gcvHAL_DUMP_EVENT,
+
+ /* Virtual command buffer. */
+ gcvHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER,
+ gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER,
+
+ /* FSCALE_VAL. */
+ 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,
+
+ /* Wait native fence for GPU. */
+ gcvHAL_WAIT_NATIVE_FENCE,
+
+ /* 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,
+
+ /* Wrap a user memory into a video memory node. */
+ gcvHAL_WRAP_USER_MEMORY,
+
+#if gcdENABLE_DEC_COMPRESSION && gcdDEC_ENABLE_AHB
+ gcvHAL_DEC300_READ,
+ gcvHAL_DEC300_WRITE,
+ gcvHAL_DEC300_FLUSH,
+ gcvHAL_DEC300_FLUSH_WAIT,
+#endif
+}
+gceHAL_COMMAND_CODES;
+
+/******************************************************************************\
+****************************** Interface Structure *****************************
+\******************************************************************************/
+
+#define gcdMAX_PROFILE_FILE_NAME 128
+
+/* Kernel settings. */
+typedef struct _gcsKERNEL_SETTINGS
+{
+ /* Used RealTime signal between kernel and user. */
+ gctINT signal;
+}
+gcsKERNEL_SETTINGS;
+
+typedef struct _gcsUSER_MEMORY_DESC
+{
+ /* Import flag. */
+ gctUINT32 flag;
+
+ /* gcvALLOC_FLAG_DMABUF */
+ gctUINT32 handle;
+
+ /* gcvALLOC_FLAG_USERMEMORY */
+ gctUINT64 logical;
+ gctUINT32 physical;
+ gctUINT32 size;
+}
+gcsUSER_MEMORY_DESC;
+
+
+/* gcvHAL_QUERY_CHIP_IDENTITY */
+typedef struct _gcsHAL_QUERY_CHIP_IDENTITY * gcsHAL_QUERY_CHIP_IDENTITY_PTR;
+typedef struct _gcsHAL_QUERY_CHIP_IDENTITY
+{
+
+ /* Chip model. */
+ gceCHIPMODEL chipModel;
+
+ /* Revision value.*/
+ gctUINT32 chipRevision;
+
+ /* Supported feature fields. */
+ gctUINT32 chipFeatures;
+
+ /* Supported minor feature fields. */
+ gctUINT32 chipMinorFeatures;
+
+ /* Supported minor feature 1 fields. */
+ gctUINT32 chipMinorFeatures1;
+
+ /* Supported minor feature 2 fields. */
+ gctUINT32 chipMinorFeatures2;
+
+ /* Supported minor feature 3 fields. */
+ gctUINT32 chipMinorFeatures3;
+
+ /* Supported minor feature 4 fields. */
+ gctUINT32 chipMinorFeatures4;
+
+ /* Supported minor feature 5 fields. */
+ gctUINT32 chipMinorFeatures5;
+
+ /* Supported minor feature 5 fields. */
+ gctUINT32 chipMinorFeatures6;
+
+ /* Number of streams supported. */
+ gctUINT32 streamCount;
+
+ /* Total number of temporary registers per thread. */
+ gctUINT32 registerMax;
+
+ /* Maximum number of threads. */
+ gctUINT32 threadCount;
+
+ /* Number of shader cores. */
+ gctUINT32 shaderCoreCount;
+
+ /* Size of the vertex cache. */
+ gctUINT32 vertexCacheSize;
+
+ /* Number of entries in the vertex output buffer. */
+ gctUINT32 vertexOutputBufferSize;
+
+ /* Number of pixel pipes. */
+ gctUINT32 pixelPipes;
+
+ /* Number of instructions. */
+ gctUINT32 instructionCount;
+
+ /* Number of constants. */
+ gctUINT32 numConstants;
+
+ /* Buffer size */
+ gctUINT32 bufferSize;
+
+ /* Number of varyings */
+ gctUINT32 varyingsCount;
+
+ /* 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;
+
+ /* Special chip flag bits */
+ gceCHIP_FLAG chipFlags;
+}
+gcsHAL_QUERY_CHIP_IDENTITY;
+
+/* gcvHAL_COMPOSE. */
+typedef struct _gcsHAL_COMPOSE * gcsHAL_COMPOSE_PTR;
+typedef struct _gcsHAL_COMPOSE
+{
+ /* Composition state buffer. */
+ gctUINT64 physical;
+ gctUINT64 logical;
+ gctUINT offset;
+ gctUINT size;
+
+ /* Composition end signal. */
+ gctUINT64 process;
+ gctUINT64 signal;
+
+ /* User signals. */
+ gctUINT64 userProcess;
+ gctUINT64 userSignal1;
+ gctUINT64 userSignal2;
+
+#if defined(__QNXNTO__)
+ /* Client pulse side-channel connection ID. */
+ gctINT32 coid;
+
+ /* Set by server. */
+ gctINT32 rcvid;
+#endif
+}
+gcsHAL_COMPOSE;
+
+
+typedef struct _gcsHAL_INTERFACE
+{
+ /* Command code. */
+ gceHAL_COMMAND_CODES command;
+
+ /* Hardware type. */
+ gceHARDWARE_TYPE hardwareType;
+
+ /* Status value. */
+ gceSTATUS status;
+
+ /* Handle to this interface channel. */
+ gctUINT64 handle;
+
+ /* Pid of the client. */
+ gctUINT32 pid;
+
+ /* Union of command structures. */
+ union _u
+ {
+ /* gcvHAL_GET_BASE_ADDRESS */
+ struct _gcsHAL_GET_BASE_ADDRESS
+ {
+ /* Physical memory address of internal memory. */
+ OUT gctUINT32 baseAddress;
+ }
+ GetBaseAddress;
+
+ /* gcvHAL_QUERY_VIDEO_MEMORY */
+ struct _gcsHAL_QUERY_VIDEO_MEMORY
+ {
+ /* Physical memory address of internal memory. Just a name. */
+ OUT gctUINT32 internalPhysical;
+
+ /* Size in bytes of internal memory. */
+ OUT gctUINT64 internalSize;
+
+ /* Physical memory address of external memory. Just a name. */
+ OUT gctUINT32 externalPhysical;
+
+ /* Size in bytes of external memory.*/
+ OUT gctUINT64 externalSize;
+
+ /* Physical memory address of contiguous memory. Just a name. */
+ OUT gctUINT32 contiguousPhysical;
+
+ /* Size in bytes of contiguous memory.*/
+ OUT gctUINT64 contiguousSize;
+ }
+ QueryVideoMemory;
+
+ /* gcvHAL_QUERY_CHIP_IDENTITY */
+ gcsHAL_QUERY_CHIP_IDENTITY QueryChipIdentity;
+
+ /* gcvHAL_MAP_MEMORY */
+ struct _gcsHAL_MAP_MEMORY
+ {
+ /* Physical memory address to map. Just a name on Linux/Qnx. */
+ IN gctUINT32 physical;
+
+ /* Number of bytes in physical memory to map. */
+ IN gctUINT64 bytes;
+
+ /* Address of mapped memory. */
+ OUT gctUINT64 logical;
+ }
+ MapMemory;
+
+ /* gcvHAL_UNMAP_MEMORY */
+ struct _gcsHAL_UNMAP_MEMORY
+ {
+ /* Physical memory address to unmap. Just a name on Linux/Qnx. */
+ IN gctUINT32 physical;
+
+ /* Number of bytes in physical memory to unmap. */
+ IN gctUINT64 bytes;
+
+ /* Address of mapped memory to unmap. */
+ IN gctUINT64 logical;
+ }
+ UnmapMemory;
+
+ /* gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY */
+ struct _gcsHAL_ALLOCATE_LINEAR_VIDEO_MEMORY
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctUINT bytes;
+
+ /* Buffer alignment. */
+ IN gctUINT alignment;
+
+ /* Type of allocation. */
+ IN gceSURF_TYPE type;
+
+ /* Flag of allocation. */
+ IN gctUINT32 flag;
+
+ /* Memory pool to allocate from. */
+ IN OUT gcePOOL pool;
+
+ /* Allocated video memory. */
+ OUT gctUINT32 node;
+ }
+ AllocateLinearVideoMemory;
+
+ /* gcvHAL_ALLOCATE_VIDEO_MEMORY */
+ struct _gcsHAL_ALLOCATE_VIDEO_MEMORY
+ {
+ /* Width of rectangle to allocate. */
+ IN OUT gctUINT width;
+
+ /* Height of rectangle to allocate. */
+ IN OUT gctUINT height;
+
+ /* Depth of rectangle to allocate. */
+ IN gctUINT depth;
+
+ /* Format rectangle to allocate in gceSURF_FORMAT. */
+ IN gceSURF_FORMAT format;
+
+ /* Type of allocation. */
+ IN gceSURF_TYPE type;
+
+ /* Memory pool to allocate from. */
+ IN OUT gcePOOL pool;
+
+ /* Allocated video memory. */
+ OUT gctUINT32 node;
+ }
+ AllocateVideoMemory;
+
+ /* gcvHAL_RELEASE_VIDEO_MEMORY */
+ struct _gcsHAL_RELEASE_VIDEO_MEMORY
+ {
+ /* 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;
+
+ /* Number of bytes to allocated. */
+ OUT gctUINT64 bytes;
+#endif
+ }
+ ReleaseVideoMemory;
+
+ /* gcvHAL_LOCK_VIDEO_MEMORY */
+ struct _gcsHAL_LOCK_VIDEO_MEMORY
+ {
+ /* Allocated video memory. */
+ IN gctUINT32 node;
+
+ /* Cache configuration. */
+ /* Only gcvPOOL_CONTIGUOUS and gcvPOOL_VIRUTAL
+ ** can be configured */
+ IN gctBOOL cacheable;
+
+ /* Hardware specific address. */
+ OUT gctUINT32 address;
+
+ /* Mapped logical address. */
+ OUT 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 gctUINT64 node;
+
+ /* Type of surface. */
+ IN gceSURF_TYPE type;
+
+ /* Flag to unlock surface asynchroneously. */
+ IN OUT gctBOOL asynchroneous;
+ }
+ UnlockVideoMemory;
+
+ /* gcvHAL_ALLOCATE_NON_PAGED_MEMORY */
+ struct _gcsHAL_ALLOCATE_NON_PAGED_MEMORY
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctUINT64 bytes;
+
+ /* Physical address of allocation. Just a name. */
+ OUT gctUINT32 physical;
+
+ /* Logical address of allocation. */
+ OUT gctUINT64 logical;
+ }
+ AllocateNonPagedMemory;
+
+ /* gcvHAL_FREE_NON_PAGED_MEMORY */
+ struct _gcsHAL_FREE_NON_PAGED_MEMORY
+ {
+ /* Number of bytes allocated. */
+ IN gctUINT64 bytes;
+
+ /* Physical address of allocation. Just a name. */
+ IN gctUINT32 physical;
+
+ /* Logical address of allocation. */
+ IN gctUINT64 logical;
+ }
+ FreeNonPagedMemory;
+
+ /* gcvHAL_ALLOCATE_NON_PAGED_MEMORY */
+ struct _gcsHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctUINT64 bytes;
+
+ /* Physical address of allocation. Just a name. */
+ OUT gctUINT32 physical;
+
+ /* Logical address of allocation. */
+ OUT gctUINT64 logical;
+ }
+ AllocateVirtualCommandBuffer;
+
+ /* gcvHAL_FREE_NON_PAGED_MEMORY */
+ struct _gcsHAL_FREE_VIRTUAL_COMMAND_BUFFER
+ {
+ /* Number of bytes allocated. */
+ IN gctUINT64 bytes;
+
+ /* Physical address of allocation. Just a name. */
+ IN gctUINT32 physical;
+
+ /* Logical address of allocation. */
+ IN gctUINT64 logical;
+ }
+ FreeVirtualCommandBuffer;
+
+ /* gcvHAL_EVENT_COMMIT. */
+ struct _gcsHAL_EVENT_COMMIT
+ {
+ /* Event queue in gcsQUEUE. */
+ IN gctUINT64 queue;
+
+#if gcdMULTI_GPU
+ IN gceCORE_3D_MASK chipEnable;
+
+ IN gceMULTI_GPU_MODE gpuMode;
+#endif
+ }
+ Event;
+
+ /* gcvHAL_COMMIT */
+ struct _gcsHAL_COMMIT
+ {
+ /* Context buffer object gckCONTEXT. */
+ IN gctUINT64 context;
+
+ /* Command buffer gcoCMDBUF. */
+ IN gctUINT64 commandBuffer;
+
+ /* State delta buffer in gcsSTATE_DELTA. */
+ gctUINT64 delta;
+
+ /* Event queue in gcsQUEUE. */
+ IN gctUINT64 queue;
+
+#if gcdMULTI_GPU
+ IN gceCORE_3D_MASK chipEnable;
+
+ IN gceMULTI_GPU_MODE gpuMode;
+#endif
+ }
+ Commit;
+
+ /* gcvHAL_MAP_USER_MEMORY */
+ struct _gcsHAL_MAP_USER_MEMORY
+ {
+ /* Base address of user memory to map. */
+ IN gctUINT64 memory;
+
+ /* Physical address of user memory to map. */
+ IN gctUINT32 physical;
+
+ /* Size of user memory in bytes to map. */
+ IN gctUINT64 size;
+
+ /* Info record required by gcvHAL_UNMAP_USER_MEMORY. Just a name. */
+ OUT gctUINT32 info;
+
+ /* Physical address of mapped memory. */
+ OUT gctUINT32 address;
+ }
+ MapUserMemory;
+
+ /* gcvHAL_UNMAP_USER_MEMORY */
+ struct _gcsHAL_UNMAP_USER_MEMORY
+ {
+ /* Base address of user memory to unmap. */
+ IN gctUINT64 memory;
+
+ /* Size of user memory in bytes to unmap. */
+ IN gctUINT64 size;
+
+ /* Info record returned by gcvHAL_MAP_USER_MEMORY. Just a name. */
+ IN gctUINT32 info;
+
+ /* Physical address of mapped memory as returned by
+ gcvHAL_MAP_USER_MEMORY. */
+ IN gctUINT32 address;
+ }
+ UnmapUserMemory;
+#if !USE_NEW_LINUX_SIGNAL
+ /* gcsHAL_USER_SIGNAL */
+ struct _gcsHAL_USER_SIGNAL
+ {
+ /* Command. */
+ gceUSER_SIGNAL_COMMAND_CODES command;
+
+ /* Signal ID. */
+ IN OUT gctINT id;
+
+ /* Reset mode. */
+ IN gctBOOL manualReset;
+
+ /* Wait timedout. */
+ IN gctUINT32 wait;
+
+ /* State. */
+ IN gctBOOL state;
+ }
+ UserSignal;
+#endif
+
+ /* gcvHAL_SIGNAL. */
+ struct _gcsHAL_SIGNAL
+ {
+ /* Signal handle to signal gctSIGNAL. */
+ IN gctUINT64 signal;
+
+ /* Reserved gctSIGNAL. */
+ IN gctUINT64 auxSignal;
+
+ /* Process owning the signal gctHANDLE. */
+ IN gctUINT64 process;
+
+#if defined(__QNXNTO__)
+ /* Client pulse side-channel connection ID. Set by client in gcoOS_CreateSignal. */
+ IN gctINT32 coid;
+
+ /* Set by server. */
+ IN gctINT32 rcvid;
+#endif
+ /* Event generated from where of pipeline */
+ IN gceKERNEL_WHERE fromWhere;
+ }
+ Signal;
+
+ /* gcvHAL_WRITE_DATA. */
+ struct _gcsHAL_WRITE_DATA
+ {
+ /* Address to write data to. */
+ IN gctUINT32 address;
+
+ /* Data to write. */
+ IN gctUINT32 data;
+ }
+ WriteData;
+
+ /* gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY */
+ struct _gcsHAL_ALLOCATE_CONTIGUOUS_MEMORY
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctUINT64 bytes;
+
+ /* Hardware address of allocation. */
+ OUT gctUINT32 address;
+
+ /* Physical address of allocation. Just a name. */
+ OUT gctUINT32 physical;
+
+ /* Logical address of allocation. */
+ OUT gctUINT64 logical;
+ }
+ AllocateContiguousMemory;
+
+ /* gcvHAL_FREE_CONTIGUOUS_MEMORY */
+ struct _gcsHAL_FREE_CONTIGUOUS_MEMORY
+ {
+ /* Number of bytes allocated. */
+ IN gctUINT64 bytes;
+
+ /* Physical address of allocation. Just a name. */
+ IN gctUINT32 physical;
+
+ /* Logical address of allocation. */
+ IN gctUINT64 logical;
+ }
+ FreeContiguousMemory;
+
+ /* gcvHAL_READ_REGISTER */
+ struct _gcsHAL_READ_REGISTER
+ {
+ /* Logical address of memory to write data to. */
+ IN gctUINT32 address;
+
+ /* Data read. */
+ OUT gctUINT32 data;
+ }
+ ReadRegisterData;
+
+ /* gcvHAL_WRITE_REGISTER */
+ struct _gcsHAL_WRITE_REGISTER
+ {
+ /* Logical address of memory to write data to. */
+ IN gctUINT32 address;
+
+ /* Data read. */
+ IN gctUINT32 data;
+ }
+ WriteRegisterData;
+
+#if 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;
+ }
+ GetProfileSetting;
+
+ /* gcvHAL_SET_PROFILE_SETTING */
+ struct _gcsHAL_SET_PROFILE_SETTING
+ {
+ /* Enable profiling */
+ IN gctBOOL enable;
+ }
+ SetProfileSetting;
+
+#if VIVANTE_PROFILER_PERDRAW
+ /* gcvHAL_READ_PROFILER_REGISTER_SETTING */
+ struct _gcsHAL_READ_PROFILER_REGISTER_SETTING
+ {
+ /*Should Clear Register*/
+ IN gctBOOL bclear;
+ }
+ SetProfilerRegisterClear;
+#endif
+
+ /* gcvHAL_READ_ALL_PROFILE_REGISTERS */
+ struct _gcsHAL_READ_ALL_PROFILE_REGISTERS
+ {
+#if VIVANTE_PROFILER_CONTEXT
+ /* Context buffer object gckCONTEXT. Just a name. */
+ IN gctUINT32 context;
+#endif
+
+ /* Data read. */
+ OUT gcsPROFILER_COUNTERS counters;
+ }
+ RegisterProfileData;
+
+ /* gcvHAL_PROFILE_REGISTERS_2D */
+ struct _gcsHAL_PROFILE_REGISTERS_2D
+ {
+ /* Data read in gcs2D_PROFILE. */
+ OUT gctUINT64 hwProfile2D;
+ }
+ RegisterProfileData2D;
+#endif
+
+ /* Power management. */
+ /* gcvHAL_SET_POWER_MANAGEMENT_STATE */
+ struct _gcsHAL_SET_POWER_MANAGEMENT
+ {
+ /* Data read. */
+ IN gceCHIPPOWERSTATE state;
+ }
+ SetPowerManagement;
+
+ /* gcvHAL_QUERY_POWER_MANAGEMENT_STATE */
+ struct _gcsHAL_QUERY_POWER_MANAGEMENT
+ {
+ /* Data read. */
+ OUT gceCHIPPOWERSTATE state;
+
+ /* Idle query. */
+ OUT gctBOOL isIdle;
+ }
+ QueryPowerManagement;
+
+ /* gcvHAL_QUERY_KERNEL_SETTINGS */
+ struct _gcsHAL_QUERY_KERNEL_SETTINGS
+ {
+ /* Settings.*/
+ OUT gcsKERNEL_SETTINGS settings;
+ }
+ QueryKernelSettings;
+
+ /* gcvHAL_MAP_PHYSICAL */
+ struct _gcsHAL_MAP_PHYSICAL
+ {
+ /* gcvTRUE to map, gcvFALSE to unmap. */
+ IN gctBOOL map;
+
+ /* Physical address. */
+ IN OUT gctUINT64 physical;
+ }
+ MapPhysical;
+
+ /* gcvHAL_DEBUG */
+ struct _gcsHAL_DEBUG
+ {
+ /* If gcvTRUE, set the debug information. */
+ IN gctBOOL set;
+ IN gctUINT32 level;
+ IN gctUINT32 zones;
+ IN gctBOOL enable;
+
+ IN gceDEBUG_MESSAGE_TYPE type;
+ IN gctUINT32 messageSize;
+
+ /* Message to print if not empty. */
+ IN gctCHAR message[80];
+ }
+ Debug;
+
+ /* gcvHAL_CACHE */
+ struct _gcsHAL_CACHE
+ {
+ IN gceCACHEOPERATION operation;
+ IN gctUINT64 process;
+ IN gctUINT64 logical;
+ IN gctUINT64 bytes;
+ IN gctUINT32 node;
+ }
+ Cache;
+
+ /* gcvHAL_TIMESTAMP */
+ struct _gcsHAL_TIMESTAMP
+ {
+ /* Timer select. */
+ IN gctUINT32 timer;
+
+ /* Timer request type (0-stop, 1-start, 2-send delta). */
+ IN gctUINT32 request;
+
+ /* Result of delta time in microseconds. */
+ OUT gctINT32 timeDelta;
+ }
+ TimeStamp;
+
+ /* gcvHAL_DATABASE */
+ struct _gcsHAL_DATABASE
+ {
+ /* Set to gcvTRUE if you want to query a particular process ID.
+ ** Set to gcvFALSE to query the last detached process. */
+ IN gctBOOL validProcessID;
+
+ /* Process ID to query. */
+ IN gctUINT32 processID;
+
+ /* Information. */
+ OUT gcuDATABASE_INFO vidMem;
+ OUT gcuDATABASE_INFO nonPaged;
+ OUT gcuDATABASE_INFO contiguous;
+ OUT gcuDATABASE_INFO gpuIdle;
+
+ /* Detail information about video memory. */
+ OUT gcuDATABASE_INFO vidMemPool[3];
+ }
+ Database;
+
+ /* gcvHAL_VERSION */
+ struct _gcsHAL_VERSION
+ {
+ /* Major version: N.n.n. */
+ OUT gctINT32 major;
+
+ /* Minor version: n.N.n. */
+ OUT gctINT32 minor;
+
+ /* Patch version: n.n.N. */
+ OUT gctINT32 patch;
+
+ /* Build version. */
+ OUT gctUINT32 build;
+ }
+ Version;
+
+ /* gcvHAL_CHIP_INFO */
+ struct _gcsHAL_CHIP_INFO
+ {
+ /* Chip count. */
+ OUT gctINT32 count;
+
+ /* Chip types. */
+ OUT gceHARDWARE_TYPE types[gcdCHIP_COUNT];
+ }
+ ChipInfo;
+
+ /* gcvHAL_ATTACH */
+ struct _gcsHAL_ATTACH
+ {
+ /* Handle of context buffer object. */
+ OUT gctUINT32 context;
+
+ /* Maximum state in the buffer. */
+ OUT gctUINT64 maxState;
+
+ /* Number of states in the buffer. */
+ OUT gctUINT32 numStates;
+
+ /* 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;
+
+ /* gcvHAL_DETACH */
+ struct _gcsHAL_DETACH
+ {
+ /* Context buffer object gckCONTEXT. Just a name. */
+ IN gctUINT32 context;
+ }
+ Detach;
+
+ /* gcvHAL_COMPOSE. */
+ gcsHAL_COMPOSE Compose;
+
+ /* gcvHAL_GET_FRAME_INFO. */
+ struct _gcsHAL_GET_FRAME_INFO
+ {
+ /* gcsHAL_FRAME_INFO* */
+ OUT gctUINT64 frameInfo;
+ }
+ GetFrameInfo;
+
+ /* gcvHAL_SET_TIME_OUT. */
+ struct _gcsHAL_SET_TIMEOUT
+ {
+ gctUINT32 timeOut;
+ }
+ SetTimeOut;
+
+#if gcdENABLE_VG
+ /* gcvHAL_COMMIT */
+ struct _gcsHAL_VGCOMMIT
+ {
+ /* Context buffer. gcsVGCONTEXT_PTR */
+ IN gctUINT64 context;
+
+ /* Command queue. gcsVGCMDQUEUE_PTR */
+ IN gctUINT64 queue;
+
+ /* Number of entries in the queue. */
+ IN gctUINT entryCount;
+
+ /* Task table. gcsTASK_MASTER_TABLE_PTR */
+ 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_SET_FSCALE_VALUE
+ {
+ IN gctUINT value;
+ }
+ SetFscaleValue;
+
+ struct _gcsHAL_GET_FSCALE_VALUE
+ {
+ OUT gctUINT value;
+ OUT gctUINT minValue;
+ OUT gctUINT maxValue;
+ }
+ 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;
+ }
+ QueryResetTimeStamp;
+
+ struct _gcsHAL_SYNC_POINT
+ {
+ /* Command. */
+ gceSYNC_POINT_COMMAND_CODES command;
+
+ /* Sync point. */
+ IN OUT gctUINT64 syncPoint;
+
+ /* From where. */
+ IN gceKERNEL_WHERE fromWhere;
+
+ /* Signaled state. */
+ OUT gctBOOL state;
+ }
+ SyncPoint;
+
+ struct _gcsHAL_CREATE_NATIVE_FENCE
+ {
+ /* Signal id to dup. */
+ IN gctUINT64 syncPoint;
+
+ /* Native fence file descriptor. */
+ OUT gctINT fenceFD;
+
+ }
+ CreateNativeFence;
+
+ struct _gcsHAL_WAIT_NATIVE_FENCE
+ {
+ /* Native fence file descriptor. */
+ IN gctINT fenceFD;
+
+ /* Wait timeout. */
+ IN gctUINT32 timeout;
+ }
+ WaitNativeFence;
+
+ 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;
+
+ struct _gcsHAL_WRAP_USER_MEMORY
+ {
+ /* Handle from other allocators. */
+ IN gctUINT32 handle;
+
+ /* Allocation flag to wrap user memory*/
+ IN gctUINT32 flag;
+
+ /* Video mmory node. */
+ OUT gctUINT32 node;
+
+ /* Description of user memory. */
+ IN gcsUSER_MEMORY_DESC desc;
+ }
+ WrapUserMemory;
+
+#if gcdENABLE_DEC_COMPRESSION && gcdDEC_ENABLE_AHB
+ struct _gcsHAL_DEC300_READ
+ {
+ gctUINT32 enable;
+ gctUINT32 readId;
+ gctUINT32 format;
+ gctUINT32 strides[3];
+ gctUINT32 is3D;
+ gctUINT32 isMSAA;
+ gctUINT32 clearValue;
+ gctUINT32 isTPC;
+ gctUINT32 isTPCCompressed;
+ gctUINT32 surfAddrs[3];
+ gctUINT32 tileAddrs[3];
+ }
+ DEC300Read;
+
+ struct _gcsHAL_DEC300_WRITE
+ {
+ gctUINT32 enable;
+ gctUINT32 readId;
+ gctUINT32 writeId;
+ gctUINT32 format;
+ gctUINT32 surfAddr;
+ gctUINT32 tileAddr;
+ }
+ DEC300Write;
+
+ struct _gcsHAL_DEC300_FLUSH
+ {
+ IN gctUINT8 useless;
+ }
+ DEC300Flush;
+
+ struct _gcsHAL_DEC300_FLUSH_WAIT
+ {
+ IN gctUINT32 done;
+ }
+ DEC300FlushWait;
+#endif
+ }
+ u;
+}
+gcsHAL_INTERFACE;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_driver_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h
new file mode 100644
index 000000000000..f23139ced20f
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h
@@ -0,0 +1,304 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_driver_vg_h_
+#define __gc_hal_driver_vg_h_
+
+
+
+#include "gc_hal_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* I/O Control Codes ******************************
+\******************************************************************************/
+
+#define gcvHAL_CLASS "galcore"
+#define IOCTL_GCHAL_INTERFACE 30000
+
+/******************************************************************************\
+********************************* Command Codes ********************************
+\******************************************************************************/
+
+/******************************************************************************\
+********************* Command buffer information structure. ********************
+\******************************************************************************/
+
+typedef struct _gcsCOMMAND_BUFFER_INFO * gcsCOMMAND_BUFFER_INFO_PTR;
+typedef struct _gcsCOMMAND_BUFFER_INFO
+{
+ /* FE command buffer interrupt ID. */
+ gctINT32 feBufferInt;
+
+ /* TS overflow interrupt ID. */
+ gctINT32 tsOverflowInt;
+
+ /* Alignment and mask for the buffer address. */
+ gctUINT addressMask;
+ gctUINT32 addressAlignment;
+
+ /* Alignment for each command. */
+ gctUINT32 commandAlignment;
+
+ /* Number of bytes required by the STATE command. */
+ gctUINT32 stateCommandSize;
+
+ /* Number of bytes required by the RESTART command. */
+ gctUINT32 restartCommandSize;
+
+ /* Number of bytes required by the FETCH command. */
+ gctUINT32 fetchCommandSize;
+
+ /* Number of bytes required by the CALL command. */
+ gctUINT32 callCommandSize;
+
+ /* Number of bytes required by the RETURN command. */
+ gctUINT32 returnCommandSize;
+
+ /* Number of bytes required by the EVENT command. */
+ gctUINT32 eventCommandSize;
+
+ /* Number of bytes required by the END command. */
+ gctUINT32 endCommandSize;
+
+ /* Number of bytes reserved at the tail of a static command buffer. */
+ gctUINT32 staticTailSize;
+
+ /* Number of bytes reserved at the tail of a dynamic command buffer. */
+ gctUINT32 dynamicTailSize;
+}
+gcsCOMMAND_BUFFER_INFO;
+
+/******************************************************************************\
+******************************** Task Structures *******************************
+\******************************************************************************/
+
+typedef enum _gceTASK
+{
+ gcvTASK_LINK,
+ gcvTASK_CLUSTER,
+ gcvTASK_INCREMENT,
+ gcvTASK_DECREMENT,
+ gcvTASK_SIGNAL,
+ gcvTASK_LOCKDOWN,
+ gcvTASK_UNLOCK_VIDEO_MEMORY,
+ gcvTASK_FREE_VIDEO_MEMORY,
+ gcvTASK_FREE_CONTIGUOUS_MEMORY,
+ gcvTASK_UNMAP_USER_MEMORY
+}
+gceTASK;
+
+typedef struct _gcsTASK_HEADER * gcsTASK_HEADER_PTR;
+typedef struct _gcsTASK_HEADER
+{
+ /* Task ID. */
+ IN gceTASK id;
+}
+gcsTASK_HEADER;
+
+typedef struct _gcsTASK_LINK * gcsTASK_LINK_PTR;
+typedef struct _gcsTASK_LINK
+{
+ /* Task ID (gcvTASK_LINK). */
+ IN gceTASK id;
+
+ /* Pointer to the next task container. */
+ IN gctPOINTER cotainer;
+
+ /* Pointer to the next task from the next task container. */
+ IN gcsTASK_HEADER_PTR task;
+}
+gcsTASK_LINK;
+
+typedef struct _gcsTASK_CLUSTER * gcsTASK_CLUSTER_PTR;
+typedef struct _gcsTASK_CLUSTER
+{
+ /* Task ID (gcvTASK_CLUSTER). */
+ IN gceTASK id;
+
+ /* Number of tasks in the cluster. */
+ IN gctUINT taskCount;
+}
+gcsTASK_CLUSTER;
+
+typedef struct _gcsTASK_INCREMENT * gcsTASK_INCREMENT_PTR;
+typedef struct _gcsTASK_INCREMENT
+{
+ /* Task ID (gcvTASK_INCREMENT). */
+ IN gceTASK id;
+
+ /* Address of the variable to increment. */
+ IN gctUINT32 address;
+}
+gcsTASK_INCREMENT;
+
+typedef struct _gcsTASK_DECREMENT * gcsTASK_DECREMENT_PTR;
+typedef struct _gcsTASK_DECREMENT
+{
+ /* Task ID (gcvTASK_DECREMENT). */
+ IN gceTASK id;
+
+ /* Address of the variable to decrement. */
+ IN gctUINT32 address;
+}
+gcsTASK_DECREMENT;
+
+typedef struct _gcsTASK_SIGNAL * gcsTASK_SIGNAL_PTR;
+typedef struct _gcsTASK_SIGNAL
+{
+ /* Task ID (gcvTASK_SIGNAL). */
+ IN gceTASK id;
+
+ /* Process owning the signal. */
+ IN gctHANDLE process;
+
+ /* Signal handle to signal. */
+ IN gctSIGNAL signal;
+
+#if defined(__QNXNTO__)
+ IN gctINT32 coid;
+ IN gctINT32 rcvid;
+#endif
+}
+gcsTASK_SIGNAL;
+
+typedef struct _gcsTASK_LOCKDOWN * gcsTASK_LOCKDOWN_PTR;
+typedef struct _gcsTASK_LOCKDOWN
+{
+ /* Task ID (gcvTASK_LOCKDOWN). */
+ IN gceTASK id;
+
+ /* Address of the user space counter. */
+ IN gctUINT32 userCounter;
+
+ /* Address of the kernel space counter. */
+ IN gctUINT32 kernelCounter;
+
+ /* Process owning the signal. */
+ IN gctHANDLE process;
+
+ /* Signal handle to signal. */
+ IN gctSIGNAL signal;
+}
+gcsTASK_LOCKDOWN;
+
+typedef struct _gcsTASK_UNLOCK_VIDEO_MEMORY * gcsTASK_UNLOCK_VIDEO_MEMORY_PTR;
+typedef struct _gcsTASK_UNLOCK_VIDEO_MEMORY
+{
+ /* Task ID (gcvTASK_UNLOCK_VIDEO_MEMORY). */
+ IN gceTASK id;
+
+ /* Allocated video memory. */
+ IN gctUINT64 node;
+}
+gcsTASK_UNLOCK_VIDEO_MEMORY;
+
+typedef struct _gcsTASK_FREE_VIDEO_MEMORY * gcsTASK_FREE_VIDEO_MEMORY_PTR;
+typedef struct _gcsTASK_FREE_VIDEO_MEMORY
+{
+ /* Task ID (gcvTASK_FREE_VIDEO_MEMORY). */
+ IN gceTASK id;
+
+ /* Allocated video memory. */
+ IN gctUINT32 node;
+}
+gcsTASK_FREE_VIDEO_MEMORY;
+
+typedef struct _gcsTASK_FREE_CONTIGUOUS_MEMORY * gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR;
+typedef struct _gcsTASK_FREE_CONTIGUOUS_MEMORY
+{
+ /* Task ID (gcvTASK_FREE_CONTIGUOUS_MEMORY). */
+ IN gceTASK id;
+
+ /* Number of bytes allocated. */
+ IN gctSIZE_T bytes;
+
+ /* Physical address of allocation. */
+ IN gctPHYS_ADDR physical;
+
+ /* Logical address of allocation. */
+ IN gctPOINTER logical;
+}
+gcsTASK_FREE_CONTIGUOUS_MEMORY;
+
+typedef struct _gcsTASK_UNMAP_USER_MEMORY * gcsTASK_UNMAP_USER_MEMORY_PTR;
+typedef struct _gcsTASK_UNMAP_USER_MEMORY
+{
+ /* Task ID (gcvTASK_UNMAP_USER_MEMORY). */
+ IN gceTASK id;
+
+ /* Base address of user memory to unmap. */
+ IN gctPOINTER memory;
+
+ /* Size of user memory in bytes to unmap. */
+ IN gctSIZE_T size;
+
+ /* Info record returned by gcvHAL_MAP_USER_MEMORY. */
+ IN gctPOINTER info;
+
+ /* Physical address of mapped memory as returned by
+ gcvHAL_MAP_USER_MEMORY. */
+ IN gctUINT32 address;
+}
+gcsTASK_UNMAP_USER_MEMORY;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_driver_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h
new file mode 100644
index 000000000000..b203f8f7e309
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_dump_h_
+#define __gc_hal_dump_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** FILE LAYOUT:
+**
+** gcsDUMP_FILE structure
+**
+** gcsDUMP_DATA frame
+** gcsDUMP_DATA or gcDUMP_DATA_SIZE records rendingring the frame
+** gctUINT8 data[length]
+*/
+
+#define gcvDUMP_FILE_SIGNATURE gcmCC('g','c','D','B')
+
+typedef struct _gcsDUMP_FILE
+{
+ gctUINT32 signature; /* File signature */
+ gctSIZE_T length; /* Length of file */
+ gctUINT32 frames; /* Number of frames in file */
+}
+gcsDUMP_FILE;
+
+typedef enum _gceDUMP_TAG
+{
+ gcvTAG_SURFACE = gcmCC('s','u','r','f'),
+ gcvTAG_FRAME = gcmCC('f','r','m',' '),
+ gcvTAG_COMMAND = gcmCC('c','m','d',' '),
+ gcvTAG_INDEX = gcmCC('i','n','d','x'),
+ gcvTAG_STREAM = gcmCC('s','t','r','m'),
+ gcvTAG_TEXTURE = gcmCC('t','e','x','t'),
+ gcvTAG_RENDER_TARGET = gcmCC('r','n','d','r'),
+ gcvTAG_DEPTH = gcmCC('z','b','u','f'),
+ gcvTAG_RESOLVE = gcmCC('r','s','l','v'),
+ gcvTAG_DELETE = gcmCC('d','e','l',' '),
+ 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. */
+}
+gcsDUMP_SURFACE;
+
+typedef struct _gcsDUMP_DATA
+{
+ gceDUMP_TAG type; /* Type of record. */
+ gctSIZE_T length; /* Number of bytes of data. */
+ gctUINT32 address; /* Address for the data. */
+}
+gcsDUMP_DATA;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_dump_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h
new file mode 100644
index 000000000000..5fdc54aa4e60
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h
@@ -0,0 +1,717 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_eglplatform_h_
+#define __gc_hal_eglplatform_h_
+
+/* Include VDK types. */
+#include "gc_hal_types.h"
+#include "gc_hal_base.h"
+#include "gc_hal_eglplatform_type.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+/* Win32 and Windows CE platforms. */
+#include <windows.h>
+typedef HDC HALNativeDisplayType;
+typedef HWND HALNativeWindowType;
+typedef HBITMAP HALNativePixmapType;
+
+typedef struct __BITFIELDINFO{
+ BITMAPINFO bmi;
+ RGBQUAD bmiColors[2];
+} BITFIELDINFO;
+
+#elif defined(LINUX) && defined(EGL_API_DFB) && !defined(__APPLE__)
+#include <directfb.h>
+typedef struct _DFBDisplay * HALNativeDisplayType;
+typedef struct _DFBWindow * HALNativeWindowType;
+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-egl.h>
+
+#define WL_COMPOSITOR_SIGNATURE (0x31415926)
+
+typedef struct _gcsWL_VIV_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;
+ struct wl_event_queue *wl_swap_queue;
+ gctINT swapInterval;
+ gctINT file;
+} gcsWL_EGL_DISPLAY;
+
+typedef struct _gcsWL_EGL_BUFFER_INFO
+{
+ gctINT32 width;
+ gctINT32 height;
+ gctINT32 stride;
+ gceSURF_FORMAT format;
+ gceSURF_TYPE type;
+ gcuVIDMEM_NODE_PTR node;
+ gcePOOL pool;
+ gctUINT bytes;
+ gcoSURF surface;
+ gcoSURF attached_surface;
+ gctINT32 invalidate;
+ gctBOOL locked;
+} gcsWL_EGL_BUFFER_INFO;
+
+typedef struct _gcsWL_EGL_BUFFER
+{
+ struct wl_buffer* wl_buffer;
+ gcsWL_EGL_BUFFER_INFO info;
+ struct wl_callback* frame_callback;
+} gcsWL_EGL_BUFFER;
+
+typedef struct _gcsWL_EGL_WINDOW_INFO
+{
+ gctINT32 dx;
+ gctINT32 dy;
+ gctUINT width;
+ gctUINT height;
+ gceSURF_FORMAT format;
+ gctUINT bpp;
+ gctINT bufferCount;
+ gctUINT current;
+} gcsWL_EGL_WINDOW_INFO;
+
+struct wl_egl_window
+{
+ gcsWL_EGL_DISPLAY* display;
+ gcsWL_EGL_BUFFER **backbuffers;
+ gcsWL_EGL_WINDOW_INFO* info;
+ gctINT noResolve;
+ gctINT32 attached_width;
+ gctINT32 attached_height;
+ struct wl_surface* surface;
+};
+
+typedef void* HALNativeDisplayType;
+typedef void* HALNativeWindowType;
+typedef void* HALNativePixmapType;
+#else
+/* Linux platform for FBDEV. */
+typedef struct _FBDisplay * HALNativeDisplayType;
+typedef struct _FBWindow * HALNativeWindowType;
+typedef struct _FBPixmap * HALNativePixmapType;
+#endif
+#elif defined(__ANDROID__) || defined(ANDROID)
+
+struct egl_native_pixmap_t;
+
+#if ANDROID_SDK_VERSION >= 9
+ #include <android/native_window.h>
+
+ typedef struct ANativeWindow* HALNativeWindowType;
+ typedef struct egl_native_pixmap_t* HALNativePixmapType;
+ typedef void* HALNativeDisplayType;
+#else
+ struct android_native_window_t;
+ typedef struct android_native_window_t* HALNativeWindowType;
+ typedef struct egl_native_pixmap_t * HALNativePixmapType;
+ typedef void* HALNativeDisplayType;
+#endif
+
+#elif defined(LINUX) || defined(__APPLE__)
+/* X11 platform. */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef Display * HALNativeDisplayType;
+typedef Window HALNativeWindowType;
+
+#ifdef CUSTOM_PIXMAP
+typedef void * HALNativePixmapType;
+#else
+typedef Pixmap HALNativePixmapType;
+#endif /* CUSTOM_PIXMAP */
+
+/* Rename some badly named X defines. */
+#ifdef Status
+# define XStatus int
+# undef Status
+#endif
+#ifdef Always
+# define XAlways 2
+# undef Always
+#endif
+#ifdef CurrentTime
+# undef CurrentTime
+# define XCurrentTime 0
+#endif
+
+#elif defined(__QNXNTO__)
+#include <screen/screen.h>
+
+/* VOID */
+typedef int HALNativeDisplayType;
+typedef screen_window_t HALNativeWindowType;
+typedef screen_pixmap_t HALNativePixmapType;
+
+#else
+
+#error "Platform not recognized"
+
+/* VOID */
+typedef void * HALNativeDisplayType;
+typedef void * HALNativeWindowType;
+typedef void * HALNativePixmapType;
+
+#endif
+
+/* define DUMMY according to the system */
+#if defined(EGL_API_WL)
+# define WL_DUMMY (31415926)
+# define EGL_DUMMY WL_DUMMY
+#elif defined(__ANDROID__) || defined(ANDROID)
+# define ANDROID_DUMMY (31415926)
+# define EGL_DUMMY ANDROID_DUMMY
+#else
+# define EGL_DUMMY (31415926)
+#endif
+
+/*******************************************************************************
+** Display. ********************************************************************
+*/
+
+gceSTATUS
+gcoOS_GetDisplay(
+ OUT HALNativeDisplayType * Display,
+ IN gctPOINTER Context
+ );
+
+gceSTATUS
+gcoOS_GetDisplayByIndex(
+ IN gctINT DisplayIndex,
+ OUT HALNativeDisplayType * Display,
+ IN gctPOINTER Context
+ );
+
+gceSTATUS
+gcoOS_GetDisplayInfo(
+ IN HALNativeDisplayType Display,
+ OUT gctINT * Width,
+ OUT gctINT * Height,
+ OUT gctSIZE_T * Physical,
+ OUT gctINT * Stride,
+ OUT gctINT * BitsPerPixel
+ );
+
+
+
+gceSTATUS
+gcoOS_GetDisplayInfoEx(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctUINT DisplayInfoSize,
+ OUT halDISPLAY_INFO * DisplayInfo
+ );
+
+gceSTATUS
+gcoOS_GetDisplayVirtual(
+ IN HALNativeDisplayType Display,
+ OUT gctINT * Width,
+ OUT gctINT * Height
+ );
+
+gceSTATUS
+gcoOS_GetDisplayBackbuffer(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ OUT gctPOINTER * context,
+ OUT gcoSURF * surface,
+ OUT gctUINT * Offset,
+ OUT gctINT * X,
+ OUT gctINT * Y
+ );
+
+gceSTATUS
+gcoOS_SetDisplayVirtual(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctUINT Offset,
+ IN gctINT X,
+ IN gctINT Y
+ );
+
+gceSTATUS
+gcoOS_SetDisplayVirtualEx(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctPOINTER Context,
+ IN gcoSURF Surface,
+ IN gctUINT Offset,
+ IN gctINT X,
+ IN gctINT Y
+ );
+
+gceSTATUS
+gcoOS_SetSwapInterval(
+ IN HALNativeDisplayType Display,
+ IN gctINT Interval
+);
+
+gceSTATUS
+gcoOS_SetSwapIntervalEx(
+ IN HALNativeDisplayType Display,
+ IN gctINT Interval,
+ IN gctPOINTER localDisplay);
+
+gceSTATUS
+gcoOS_GetSwapInterval(
+ IN HALNativeDisplayType Display,
+ IN gctINT_PTR Min,
+ IN gctINT_PTR Max
+);
+
+gceSTATUS
+gcoOS_DisplayBufferRegions(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctINT NumRects,
+ IN gctINT_PTR Rects
+ );
+
+gceSTATUS
+gcoOS_DestroyDisplay(
+ IN HALNativeDisplayType Display
+ );
+
+gceSTATUS
+gcoOS_InitLocalDisplayInfo(
+ IN HALNativeDisplayType Display,
+ IN OUT gctPOINTER * localDisplay
+ );
+
+gceSTATUS
+gcoOS_DeinitLocalDisplayInfo(
+ IN HALNativeDisplayType Display,
+ IN OUT gctPOINTER * localDisplay
+ );
+
+gceSTATUS
+gcoOS_GetDisplayInfoEx2(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctPOINTER localDisplay,
+ IN gctUINT DisplayInfoSize,
+ OUT halDISPLAY_INFO * DisplayInfo
+ );
+
+gceSTATUS
+gcoOS_GetDisplayBackbufferEx(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctPOINTER localDisplay,
+ OUT gctPOINTER * context,
+ OUT gcoSURF * surface,
+ OUT gctUINT * Offset,
+ OUT gctINT * X,
+ OUT gctINT * Y
+ );
+
+gceSTATUS
+gcoOS_IsValidDisplay(
+ IN HALNativeDisplayType Display
+ );
+
+gceSTATUS
+gcoOS_GetNativeVisualId(
+ IN HALNativeDisplayType Display,
+ OUT gctINT* nativeVisualId
+ );
+
+gctBOOL
+gcoOS_SynchronousFlip(
+ IN HALNativeDisplayType Display
+ );
+
+/*******************************************************************************
+** Windows. ********************************************************************
+*/
+
+gceSTATUS
+gcoOS_CreateWindow(
+ IN HALNativeDisplayType Display,
+ IN gctINT X,
+ IN gctINT Y,
+ IN gctINT Width,
+ IN gctINT Height,
+ OUT HALNativeWindowType * Window
+ );
+
+gceSTATUS
+gcoOS_GetWindowInfo(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ OUT gctINT * X,
+ OUT gctINT * Y,
+ OUT gctINT * Width,
+ OUT gctINT * Height,
+ OUT gctINT * BitsPerPixel,
+ OUT gctUINT * Offset
+ );
+
+gceSTATUS
+gcoOS_SetWindowFormat(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gceTILING Tiling,
+ IN gceSURF_FORMAT Format
+ );
+
+gceSTATUS
+gcoOS_DestroyWindow(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window
+ );
+
+gceSTATUS
+gcoOS_DrawImage(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctINT Left,
+ IN gctINT Top,
+ IN gctINT Right,
+ IN gctINT Bottom,
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctINT BitsPerPixel,
+ IN gctPOINTER Bits
+ );
+
+gceSTATUS
+gcoOS_GetImage(
+ IN HALNativeWindowType Window,
+ IN gctINT Left,
+ IN gctINT Top,
+ IN gctINT Right,
+ IN gctINT Bottom,
+ OUT gctINT * BitsPerPixel,
+ OUT gctPOINTER * Bits
+ );
+
+gceSTATUS
+gcoOS_GetWindowInfoEx(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ OUT gctINT * X,
+ OUT gctINT * Y,
+ OUT gctINT * Width,
+ OUT gctINT * Height,
+ OUT gctINT * BitsPerPixel,
+ OUT gctUINT * Offset,
+ OUT gceSURF_FORMAT * Format
+ );
+
+gceSTATUS
+gcoOS_DrawImageEx(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctINT Left,
+ IN gctINT Top,
+ IN gctINT Right,
+ IN gctINT Bottom,
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctINT BitsPerPixel,
+ IN gctPOINTER Bits,
+ IN gceSURF_FORMAT Format
+ );
+
+/*******************************************************************************
+** Pixmaps. ********************************************************************
+*/
+
+gceSTATUS
+gcoOS_CreatePixmap(
+ IN HALNativeDisplayType Display,
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctINT BitsPerPixel,
+ OUT HALNativePixmapType * Pixmap
+ );
+
+gceSTATUS
+gcoOS_GetPixmapInfo(
+ IN HALNativeDisplayType Display,
+ IN HALNativePixmapType Pixmap,
+ OUT gctINT * Width,
+ OUT gctINT * Height,
+ OUT gctINT * BitsPerPixel,
+ OUT gctINT * Stride,
+ OUT gctPOINTER * Bits
+ );
+
+gceSTATUS
+gcoOS_DrawPixmap(
+ IN HALNativeDisplayType Display,
+ IN HALNativePixmapType Pixmap,
+ IN gctINT Left,
+ IN gctINT Top,
+ IN gctINT Right,
+ IN gctINT Bottom,
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctINT BitsPerPixel,
+ IN gctPOINTER Bits
+ );
+
+gceSTATUS
+gcoOS_DestroyPixmap(
+ IN HALNativeDisplayType Display,
+ IN HALNativePixmapType Pixmap
+ );
+
+gceSTATUS
+gcoOS_GetPixmapInfoEx(
+ IN HALNativeDisplayType Display,
+ IN HALNativePixmapType Pixmap,
+ OUT gctINT * Width,
+ OUT gctINT * Height,
+ OUT gctINT * BitsPerPixel,
+ OUT gctINT * Stride,
+ OUT gctPOINTER * Bits,
+ OUT gceSURF_FORMAT * Format
+ );
+
+gceSTATUS
+gcoOS_CopyPixmapBits(
+ IN HALNativeDisplayType Display,
+ IN HALNativePixmapType Pixmap,
+ IN gctUINT DstWidth,
+ IN gctUINT DstHeight,
+ IN gctINT DstStride,
+ IN gceSURF_FORMAT DstFormat,
+ OUT gctPOINTER DstBits
+ );
+
+/*******************************************************************************
+** OS relative. ****************************************************************
+*/
+gceSTATUS
+gcoOS_LoadEGLLibrary(
+ OUT gctHANDLE * Handle
+ );
+
+gceSTATUS
+gcoOS_FreeEGLLibrary(
+ IN gctHANDLE Handle
+ );
+
+gceSTATUS
+gcoOS_ShowWindow(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window
+ );
+
+gceSTATUS
+gcoOS_HideWindow(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window
+ );
+
+gceSTATUS
+gcoOS_SetWindowTitle(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctCONST_STRING Title
+ );
+
+gceSTATUS
+gcoOS_CapturePointer(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window
+ );
+
+gceSTATUS
+gcoOS_GetEvent(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ OUT halEvent * Event
+ );
+
+gceSTATUS
+gcoOS_CreateClientBuffer(
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctINT Format,
+ IN gctINT Type,
+ OUT gctPOINTER * ClientBuffer
+ );
+
+gceSTATUS
+gcoOS_GetClientBufferInfo(
+ IN gctPOINTER ClientBuffer,
+ OUT gctINT * Width,
+ OUT gctINT * Height,
+ OUT gctINT * Stride,
+ OUT gctPOINTER * Bits
+ );
+
+gceSTATUS
+gcoOS_DestroyClientBuffer(
+ IN gctPOINTER ClientBuffer
+ );
+
+gceSTATUS
+gcoOS_DestroyContext(
+ IN gctPOINTER Display,
+ IN gctPOINTER Context
+ );
+
+gceSTATUS
+gcoOS_CreateContext(
+ IN gctPOINTER LocalDisplay,
+ IN gctPOINTER Context
+ );
+
+gceSTATUS
+gcoOS_MakeCurrent(
+ IN gctPOINTER LocalDisplay,
+ IN HALNativeWindowType DrawDrawable,
+ IN HALNativeWindowType ReadDrawable,
+ IN gctPOINTER Context,
+ IN gcoSURF ResolveTarget
+ );
+
+gceSTATUS
+gcoOS_CreateDrawable(
+ IN gctPOINTER LocalDisplay,
+ IN HALNativeWindowType Drawable
+ );
+
+gceSTATUS
+gcoOS_DestroyDrawable(
+ IN gctPOINTER LocalDisplay,
+ IN HALNativeWindowType Drawable
+ );
+gceSTATUS
+gcoOS_SwapBuffers(
+ IN gctPOINTER LocalDisplay,
+ IN HALNativeWindowType Drawable,
+ IN gcoSURF RenderTarget,
+ IN gcoSURF ResolveTarget,
+ IN gctPOINTER ResolveBits,
+ 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_CreateDrawableEx(
+ IN gctPOINTER localDisplay,
+ IN HALNativeWindowType Drawable,
+ IN gctBOOL linear);
+
+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,
+ OUT gcoSURF *nextSurf
+ );
+
+gceSTATUS
+gcoOS_DrawSurface(
+ IN gctPOINTER localDisplay,
+ IN HALNativeWindowType Drawable
+ );
+#endif
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_eglplatform_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h
new file mode 100644
index 000000000000..3a79ae4eb713
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h
@@ -0,0 +1,344 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_eglplatform_type_h_
+#define __gc_hal_eglplatform_type_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+** Events. *********************************************************************
+*/
+
+typedef enum _halEventType
+{
+ /* Keyboard event. */
+ HAL_KEYBOARD,
+
+ /* Mouse move event. */
+ HAL_POINTER,
+
+ /* Mouse button event. */
+ HAL_BUTTON,
+
+ /* Application close event. */
+ HAL_CLOSE,
+
+ /* Application window has been updated. */
+ HAL_WINDOW_UPDATE
+}
+halEventType;
+
+/* Scancodes for keyboard. */
+typedef enum _halKeys
+{
+ HAL_UNKNOWN = -1,
+
+ HAL_BACKSPACE = 0x08,
+ HAL_TAB,
+ HAL_ENTER = 0x0D,
+ HAL_ESCAPE = 0x1B,
+
+ HAL_SPACE = 0x20,
+ HAL_SINGLEQUOTE = 0x27,
+ HAL_PAD_ASTERISK = 0x2A,
+ HAL_COMMA = 0x2C,
+ HAL_HYPHEN,
+ HAL_PERIOD,
+ HAL_SLASH,
+ HAL_0,
+ HAL_1,
+ HAL_2,
+ HAL_3,
+ HAL_4,
+ HAL_5,
+ HAL_6,
+ HAL_7,
+ HAL_8,
+ HAL_9,
+ HAL_SEMICOLON = 0x3B,
+ HAL_EQUAL = 0x3D,
+ HAL_A = 0x41,
+ HAL_B,
+ HAL_C,
+ HAL_D,
+ HAL_E,
+ HAL_F,
+ HAL_G,
+ HAL_H,
+ HAL_I,
+ HAL_J,
+ HAL_K,
+ HAL_L,
+ HAL_M,
+ HAL_N,
+ HAL_O,
+ HAL_P,
+ HAL_Q,
+ HAL_R,
+ HAL_S,
+ HAL_T,
+ HAL_U,
+ HAL_V,
+ HAL_W,
+ HAL_X,
+ HAL_Y,
+ HAL_Z,
+ HAL_LBRACKET,
+ HAL_BACKSLASH,
+ HAL_RBRACKET,
+ HAL_BACKQUOTE = 0x60,
+
+ HAL_F1 = 0x80,
+ HAL_F2,
+ HAL_F3,
+ HAL_F4,
+ HAL_F5,
+ HAL_F6,
+ HAL_F7,
+ HAL_F8,
+ HAL_F9,
+ HAL_F10,
+ HAL_F11,
+ HAL_F12,
+
+ HAL_LCTRL,
+ HAL_RCTRL,
+ HAL_LSHIFT,
+ HAL_RSHIFT,
+ HAL_LALT,
+ HAL_RALT,
+ HAL_CAPSLOCK,
+ HAL_NUMLOCK,
+ HAL_SCROLLLOCK,
+ HAL_PAD_0,
+ HAL_PAD_1,
+ HAL_PAD_2,
+ HAL_PAD_3,
+ HAL_PAD_4,
+ HAL_PAD_5,
+ HAL_PAD_6,
+ HAL_PAD_7,
+ HAL_PAD_8,
+ HAL_PAD_9,
+ HAL_PAD_HYPHEN,
+ HAL_PAD_PLUS,
+ HAL_PAD_SLASH,
+ HAL_PAD_PERIOD,
+ HAL_PAD_ENTER,
+ HAL_SYSRQ,
+ HAL_PRNTSCRN,
+ HAL_BREAK,
+ HAL_UP,
+ HAL_LEFT,
+ HAL_RIGHT,
+ HAL_DOWN,
+ HAL_HOME,
+ HAL_END,
+ HAL_PGUP,
+ HAL_PGDN,
+ HAL_INSERT,
+ HAL_DELETE,
+ HAL_LWINDOW,
+ HAL_RWINDOW,
+ HAL_MENU,
+ HAL_POWER,
+ HAL_SLEEP,
+ HAL_WAKE
+}
+halKeys;
+
+/* Structure that defined keyboard mapping. */
+typedef struct _halKeyMap
+{
+ /* Normal key. */
+ halKeys normal;
+
+ /* Extended key. */
+ halKeys extended;
+}
+halKeyMap;
+
+/* Event structure. */
+typedef struct _halEvent
+{
+ /* Event type. */
+ halEventType type;
+
+ /* Event data union. */
+ union _halEventData
+ {
+ /* Event data for keyboard. */
+ struct _halKeyboard
+ {
+ /* Scancode. */
+ halKeys scancode;
+
+ /* ASCII characte of the key pressed. */
+ char key;
+
+ /* Flag whether the key was pressed (1) or released (0). */
+ char pressed;
+ }
+ keyboard;
+
+ /* Event data for pointer. */
+ struct _halPointer
+ {
+ /* Current pointer coordinate. */
+ int x;
+ int y;
+ }
+ pointer;
+
+ /* Event data for mouse buttons. */
+ struct _halButton
+ {
+ /* Left button state. */
+ int left;
+
+ /* Middle button state. */
+ int middle;
+
+ /* Right button state. */
+ int right;
+
+ /* Current pointer coordinate. */
+ int x;
+ int y;
+ }
+ button;
+ }
+ data;
+}
+halEvent;
+
+/* Tiling layouts. */
+typedef enum _halTiling
+{
+ HAL_INVALIDTILED = 0x0, /* Invalid tiling */
+ /* Tiling basic modes enum'ed in power of 2. */
+ HAL_LINEAR = 0x1, /* No tiling. */
+ HAL_TILED = 0x2, /* 4x4 tiling. */
+ HAL_SUPERTILED = 0x4, /* 64x64 tiling. */
+ HAL_MINORTILED = 0x8, /* 2x2 tiling. */
+
+ /* Tiling special layouts. */
+ HAL_TILING_SPLIT_BUFFER = 0x100,
+
+ /* Tiling combination layouts. */
+ HAL_MULTI_TILED = HAL_TILED
+ | HAL_TILING_SPLIT_BUFFER,
+
+ HAL_MULTI_SUPERTILED = HAL_SUPERTILED
+ | HAL_TILING_SPLIT_BUFFER,
+}
+halTiling;
+
+/* VFK_DISPLAY_INFO structure defining information returned by
+ vdkGetDisplayInfoEx. */
+typedef struct _halDISPLAY_INFO
+{
+ /* The size of the display in pixels. */
+ int width;
+ int height;
+
+ /* The stride of the dispay. -1 is returned if the stride is not known
+ ** for the specified display.*/
+ int stride;
+
+ /* The tiling layout of the display. */
+ int tiling;
+
+ /* The color depth of the display in bits per pixel. */
+ int bitsPerPixel;
+
+ /* The logical pointer to the display memory buffer. NULL is returned
+ ** if the pointer is not known for the specified display. */
+ void * logical;
+
+ /* The physical address of the display memory buffer. ~0 is returned
+ ** if the address is not known for the specified display. */
+ unsigned long physical;
+
+ /* True if requires buffer wrapping. */
+ int wrapFB;
+
+ /* FB_MULTI_BUFFER */
+ int multiBuffer;
+ int backBufferY;
+
+ /* The color info of the display. */
+ unsigned int alphaLength;
+ unsigned int alphaOffset;
+ unsigned int redLength;
+ unsigned int redOffset;
+ unsigned int greenLength;
+ unsigned int greenOffset;
+ unsigned int blueLength;
+ unsigned int blueOffset;
+
+ /* Display flip support. */
+ int flip;
+}
+halDISPLAY_INFO;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_eglplatform_type_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
new file mode 100644
index 000000000000..220601a54d90
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
@@ -0,0 +1,2662 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_engine_h_
+#define __gc_hal_engine_h_
+
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+
+#if gcdENABLE_3D
+#if gcdENABLE_VG
+#include "gc_hal_engine_vg.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoSTREAM * gcoSTREAM;
+typedef struct _gcoVERTEX * gcoVERTEX;
+typedef struct _gcoTEXTURE * gcoTEXTURE;
+typedef struct _gcoINDEX * gcoINDEX;
+typedef struct _gcsVERTEX_ATTRIBUTES * gcsVERTEX_ATTRIBUTES_PTR;
+typedef struct _gcoVERTEXARRAY * gcoVERTEXARRAY;
+typedef struct _gcoBUFOBJ * gcoBUFOBJ;
+
+#define gcdATTRIBUTE_COUNT 16
+
+typedef enum _gcePROGRAM_STAGE
+{
+ 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
+}
+gcePROGRAM_STAGE;
+
+typedef enum _gcePROGRAM_STAGE_BIT
+{
+ 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,
+}
+gcePROGRAM_STAGE_BIT;
+
+
+/******************************************************************************\
+********************************* gcoHAL Object *********************************
+\******************************************************************************/
+
+gceSTATUS
+gcoHAL_QueryShaderCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT * UnifiedUniforms,
+ OUT gctUINT * VertUniforms,
+ OUT gctUINT * FragUniforms,
+ OUT gctUINT * Varyings,
+ OUT gctUINT * ShaderCoreCount,
+ OUT gctUINT * ThreadCount,
+ OUT gctUINT * VertInstructionCount,
+ OUT gctUINT * FragInstructionCount
+ );
+
+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,
+ OUT gctUINT * MaxWidth,
+ OUT gctUINT * MaxHeight,
+ OUT gctUINT * MaxDepth,
+ OUT gctBOOL * Cubic,
+ OUT gctBOOL * NonPowerOfTwo,
+ OUT gctUINT * VertexSamplers,
+ OUT gctUINT * PixelSamplers
+ );
+
+gceSTATUS
+gcoHAL_QueryTextureMaxAniso(
+ IN gcoHAL Hal,
+ OUT gctUINT * MaxAnisoValue
+ );
+
+gceSTATUS
+gcoHAL_QueryStreamCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT32 * MaxAttributes,
+ OUT gctUINT32 * MaxStreamSize,
+ OUT gctUINT32 * NumberOfStreams,
+ OUT gctUINT32 * Alignment
+ );
+
+/******************************************************************************\
+********************************* gcoSURF Object ********************************
+\******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/*--------------------------------- gcoSURF 3D --------------------------------*/
+typedef enum _gceBLIT_FLAG
+{
+ gcvBLIT_FLAG_SKIP_DEPTH_WRITE = 0x1,
+ gcvBLIT_FLAG_SKIP_STENCIL_WRITE = 0x2,
+} gceBLIT_FLAG;
+
+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;
+
+
+/* CPU Blit with format (including linear <-> tile) conversion*/
+gceSTATUS
+gcoSURF_BlitCPU(
+ gcsSURF_BLIT_ARGS* args
+ );
+
+
+gceSTATUS
+gcoSURF_BlitDraw(
+ IN gcsSURF_BLITDRAW_ARGS *args
+ );
+#endif /* gcdENABLE_3D */
+
+
+
+#if gcdENABLE_3D
+/* Clear surface function. */
+gceSTATUS
+gcoSURF_Clear(
+ IN gcoSURF Surface,
+ IN gcsSURF_CLEAR_ARGS_PTR clearArg
+ );
+
+/* Preserve pixels from source. */
+gceSTATUS
+gcoSURF_Preserve(
+ IN gcoSURF Source,
+ IN gcoSURF Dest,
+ IN gcsRECT_PTR MaskRect
+ );
+
+
+/* TO BE REMOVED */
+ gceSTATUS
+ depr_gcoSURF_Resolve(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gctUINT32 DestAddress,
+ IN gctPOINTER DestBits,
+ IN gctINT DestStride,
+ IN gceSURF_TYPE DestType,
+ IN gceSURF_FORMAT DestFormat,
+ IN gctUINT DestWidth,
+ IN gctUINT DestHeight
+ );
+
+ gceSTATUS
+ depr_gcoSURF_ResolveRect(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gctUINT32 DestAddress,
+ IN gctPOINTER DestBits,
+ IN gctINT DestStride,
+ IN gceSURF_TYPE DestType,
+ IN gceSURF_FORMAT DestFormat,
+ IN gctUINT DestWidth,
+ IN gctUINT DestHeight,
+ IN gcsPOINT_PTR SrcOrigin,
+ IN gcsPOINT_PTR DestOrigin,
+ IN gcsPOINT_PTR RectSize
+ );
+
+/* Resample surface. */
+gceSTATUS
+gcoSURF_Resample(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface
+ );
+
+/* Resolve surface. */
+gceSTATUS
+gcoSURF_Resolve(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface
+ );
+
+gceSTATUS
+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,
+ IN gcsPOINT_PTR DestOrigin,
+ IN gcsPOINT_PTR RectSize
+ );
+
+/* Resolve rectangular area of a surface. */
+gceSTATUS
+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,
+ IN gcsPOINT_PTR DestOrigin,
+ IN gcsPOINT_PTR RectSize
+ );
+
+/* Set surface resolvability. */
+gceSTATUS
+gcoSURF_SetResolvability(
+ IN gcoSURF Surface,
+ IN gctBOOL Resolvable
+ );
+
+gceSTATUS
+gcoSURF_IsRenderable(
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoSURF_IsFormatRenderableAsRT(
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoSURF_SetSharedLock(
+ IN gcoSURF Surface,
+ IN gctPOINTER sharedLock
+ );
+
+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
+ );
+
+gceSTATUS
+gcoSTREAM_GetFence(
+ IN gcoSTREAM stream
+ );
+
+gceSTATUS
+gcoSTREAM_WaitFence(
+ IN gcoSTREAM stream
+ );
+
+gceSTATUS
+gcoINDEX_GetFence(
+ IN gcoINDEX index
+ );
+
+gceSTATUS
+gcoINDEX_WaitFence(
+ IN gcoINDEX index
+ );
+
+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 *******************************
+\******************************************************************************/
+gceSTATUS
+gcoINDEX_SetSharedLock(
+ IN gcoINDEX Index,
+ IN gctPOINTER sharedLock
+ );
+
+/* Construct a new gcoINDEX object. */
+gceSTATUS
+gcoINDEX_Construct(
+ IN gcoHAL Hal,
+ OUT gcoINDEX * Index
+ );
+
+/* Destroy a gcoINDEX object. */
+gceSTATUS
+gcoINDEX_Destroy(
+ IN gcoINDEX Index
+ );
+
+/* Lock index in memory. */
+gceSTATUS
+gcoINDEX_Lock(
+ IN gcoINDEX Index,
+ OUT gctUINT32 * Address,
+ OUT gctPOINTER * Memory
+ );
+
+/* Unlock index that was previously locked with gcoINDEX_Lock. */
+gceSTATUS
+gcoINDEX_Unlock(
+ IN gcoINDEX Index
+ );
+
+/* Upload index data into the memory. */
+gceSTATUS
+gcoINDEX_Load(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE IndexType,
+ IN gctUINT32 IndexCount,
+ IN gctPOINTER IndexBuffer
+ );
+
+/* Bind an index object to the hardware. */
+gceSTATUS
+gcoINDEX_Bind(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type
+ );
+
+/* Bind an index object to the hardware. */
+gceSTATUS
+gcoINDEX_BindOffset(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type,
+ IN gctUINT32 Offset
+ );
+
+/* Free existing index buffer. */
+gceSTATUS
+gcoINDEX_Free(
+ IN gcoINDEX Index
+ );
+
+/* Upload data into an index buffer. */
+gceSTATUS
+gcoINDEX_Upload(
+ IN gcoINDEX Index,
+ IN gctCONST_POINTER Buffer,
+ IN gctSIZE_T Bytes
+ );
+
+/* Upload data into an index buffer starting at an offset. */
+gceSTATUS
+gcoINDEX_UploadOffset(
+ IN gcoINDEX Index,
+ IN gctSIZE_T Offset,
+ IN gctCONST_POINTER Buffer,
+ IN gctSIZE_T Bytes
+ );
+
+/*Merge index2 to index1 from 0, index2 must subset of inex1*/
+gceSTATUS
+gcoINDEX_Merge(
+ IN gcoINDEX Index1,
+ IN gcoINDEX Index2
+ );
+
+/*check if index buffer is enough for this draw*/
+gctBOOL
+gcoINDEX_CheckRange(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type,
+ IN gctINT Count,
+ IN gctUINT32 Indices
+ );
+
+/* Query the index capabilities. */
+gceSTATUS
+gcoINDEX_QueryCaps(
+ OUT gctBOOL * Index8,
+ OUT gctBOOL * Index16,
+ OUT gctBOOL * Index32,
+ OUT gctUINT * MaxIndex
+ );
+
+/* Determine the index range in the current index buffer. */
+gceSTATUS
+gcoINDEX_GetIndexRange(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type,
+ IN gctUINT32 Offset,
+ IN gctUINT32 Count,
+ OUT gctUINT32 * MinimumIndex,
+ OUT gctUINT32 * MaximumIndex
+ );
+
+/* Dynamic buffer management. */
+gceSTATUS
+gcoINDEX_SetDynamic(
+ IN gcoINDEX Index,
+ IN gctSIZE_T Bytes,
+ IN gctUINT Buffers
+ );
+
+/******************************************************************************\
+********************************** gco3D Object *********************************
+\******************************************************************************/
+
+/* Blending targets. */
+typedef enum _gceBLEND_UNIT
+{
+ gcvBLEND_SOURCE,
+ gcvBLEND_TARGET,
+}
+gceBLEND_UNIT;
+
+/* Construct a new gco3D object. */
+gceSTATUS
+gco3D_Construct(
+ IN gcoHAL Hal,
+ OUT gco3D * Engine
+ );
+
+/* Destroy an gco3D object. */
+gceSTATUS
+gco3D_Destroy(
+ IN gco3D Engine
+ );
+
+/* Set 3D API type. */
+gceSTATUS
+gco3D_SetAPI(
+ IN gco3D Engine,
+ IN gceAPI ApiType
+ );
+
+/* Get 3D API type. */
+gceSTATUS
+gco3D_GetAPI(
+ IN gco3D Engine,
+ OUT gceAPI * ApiType
+ );
+
+/* Set render target. */
+gceSTATUS
+gco3D_SetTarget(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+/* Unset render target. */
+gceSTATUS
+gco3D_UnsetTarget(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+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(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gco3D_SetDepthBufferOffset(
+ IN gco3D Engine,
+ IN gctSIZE_T Offset
+ );
+
+/* Unset depth buffer. */
+gceSTATUS
+gco3D_UnsetDepth(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+/* Set viewport. */
+gceSTATUS
+gco3D_SetViewport(
+ IN gco3D Engine,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom
+ );
+
+/* Set scissors. */
+gceSTATUS
+gco3D_SetScissors(
+ IN gco3D Engine,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom
+ );
+
+/* Set clear color. */
+gceSTATUS
+gco3D_SetClearColor(
+ IN gco3D Engine,
+ IN gctUINT8 Red,
+ IN gctUINT8 Green,
+ IN gctUINT8 Blue,
+ IN gctUINT8 Alpha
+ );
+
+/* Set fixed point clear color. */
+gceSTATUS
+gco3D_SetClearColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+/* Set floating point clear color. */
+gceSTATUS
+gco3D_SetClearColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Set fixed point clear depth. */
+gceSTATUS
+gco3D_SetClearDepthX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Depth
+ );
+
+/* Set floating point clear depth. */
+gceSTATUS
+gco3D_SetClearDepthF(
+ IN gco3D Engine,
+ IN gctFLOAT Depth
+ );
+
+/* Set clear stencil. */
+gceSTATUS
+gco3D_SetClearStencil(
+ IN gco3D Engine,
+ IN gctUINT32 Stencil
+ );
+
+/* Set shading mode. */
+gceSTATUS
+gco3D_SetShading(
+ IN gco3D Engine,
+ IN gceSHADING Shading
+ );
+
+/* Set blending mode. */
+gceSTATUS
+gco3D_EnableBlending(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set blending function. */
+gceSTATUS
+gco3D_SetBlendFunction(
+ IN gco3D Engine,
+ IN gceBLEND_UNIT Unit,
+ IN gceBLEND_FUNCTION FunctionRGB,
+ IN gceBLEND_FUNCTION FunctionAlpha
+ );
+
+/* Set blending mode. */
+gceSTATUS
+gco3D_SetBlendMode(
+ IN gco3D Engine,
+ IN gceBLEND_MODE ModeRGB,
+ IN gceBLEND_MODE ModeAlpha
+ );
+
+/* Set blending color. */
+gceSTATUS
+gco3D_SetBlendColor(
+ IN gco3D Engine,
+ IN gctUINT Red,
+ IN gctUINT Green,
+ IN gctUINT Blue,
+ IN gctUINT Alpha
+ );
+
+/* Set fixed point blending color. */
+gceSTATUS
+gco3D_SetBlendColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+/* Set floating point blending color. */
+gceSTATUS
+gco3D_SetBlendColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Set culling mode. */
+gceSTATUS
+gco3D_SetCulling(
+ IN gco3D Engine,
+ IN gceCULL Mode
+ );
+
+/* Enable point size */
+gceSTATUS
+gco3D_SetPointSizeEnable(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set point sprite */
+gceSTATUS
+gco3D_SetPointSprite(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set fill mode. */
+gceSTATUS
+gco3D_SetFill(
+ IN gco3D Engine,
+ IN gceFILL Mode
+ );
+
+/* Set depth compare mode. */
+gceSTATUS
+gco3D_SetDepthCompare(
+ IN gco3D Engine,
+ IN gceCOMPARE Compare
+ );
+
+/* Enable depth writing. */
+gceSTATUS
+gco3D_EnableDepthWrite(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set depth mode. */
+gceSTATUS
+gco3D_SetDepthMode(
+ IN gco3D Engine,
+ IN gceDEPTH_MODE Mode
+ );
+
+/* Set depth range. */
+gceSTATUS
+gco3D_SetDepthRangeX(
+ IN gco3D Engine,
+ IN gceDEPTH_MODE Mode,
+ IN gctFIXED_POINT Near,
+ IN gctFIXED_POINT Far
+ );
+
+/* Set depth range. */
+gceSTATUS
+gco3D_SetDepthRangeF(
+ IN gco3D Engine,
+ IN gceDEPTH_MODE Mode,
+ IN gctFLOAT Near,
+ IN gctFLOAT Far
+ );
+
+/* Set last pixel enable */
+gceSTATUS
+gco3D_SetLastPixelEnable(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set depth Bias and Scale */
+gceSTATUS
+gco3D_SetDepthScaleBiasX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT DepthScale,
+ IN gctFIXED_POINT DepthBias
+ );
+
+gceSTATUS
+gco3D_SetDepthScaleBiasF(
+ IN gco3D Engine,
+ IN gctFLOAT DepthScale,
+ IN gctFLOAT DepthBias
+ );
+
+/* Set depth near and far clipping plane. */
+gceSTATUS
+gco3D_SetDepthPlaneF(
+ IN gco3D Engine,
+ IN gctFLOAT Near,
+ IN gctFLOAT Far
+ );
+
+/* Enable or disable dithering. */
+gceSTATUS
+gco3D_EnableDither(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set color write enable bits. */
+gceSTATUS
+gco3D_SetColorWrite(
+ IN gco3D Engine,
+ IN gctUINT8 Enable
+ );
+
+/* Enable or disable early depth. */
+gceSTATUS
+gco3D_SetEarlyDepth(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* 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(
+ IN gco3D Engine
+ );
+
+/* Set dynamic early mode */
+gceSTATUS
+gco3D_DisableDynamicEarlyDepthMode(
+ IN gco3D Engine,
+ IN gctBOOL Disable
+ );
+
+/* Enable or disable depth-only mode. */
+gceSTATUS
+gco3D_SetDepthOnly(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+typedef struct _gcsSTENCIL_INFO * gcsSTENCIL_INFO_PTR;
+typedef struct _gcsSTENCIL_INFO
+{
+ gceSTENCIL_MODE mode;
+
+ gctUINT8 maskFront;
+ gctUINT8 maskBack;
+ gctUINT8 writeMaskFront;
+ gctUINT8 writeMaskBack;
+
+ gctUINT8 referenceFront;
+
+ gceCOMPARE compareFront;
+ gceSTENCIL_OPERATION passFront;
+ gceSTENCIL_OPERATION failFront;
+ gceSTENCIL_OPERATION depthFailFront;
+
+ gctUINT8 referenceBack;
+ gceCOMPARE compareBack;
+ gceSTENCIL_OPERATION passBack;
+ gceSTENCIL_OPERATION failBack;
+ gceSTENCIL_OPERATION depthFailBack;
+}
+gcsSTENCIL_INFO;
+
+/* Set stencil mode. */
+gceSTATUS
+gco3D_SetStencilMode(
+ IN gco3D Engine,
+ IN gceSTENCIL_MODE Mode
+ );
+
+/* Set stencil mask. */
+gceSTATUS
+gco3D_SetStencilMask(
+ IN gco3D Engine,
+ IN gctUINT8 Mask
+ );
+
+/* Set stencil back mask. */
+gceSTATUS
+gco3D_SetStencilMaskBack(
+ IN gco3D Engine,
+ IN gctUINT8 Mask
+ );
+
+/* Set stencil write mask. */
+gceSTATUS
+gco3D_SetStencilWriteMask(
+ IN gco3D Engine,
+ IN gctUINT8 Mask
+ );
+
+/* Set stencil back write mask. */
+gceSTATUS
+gco3D_SetStencilWriteMaskBack(
+ IN gco3D Engine,
+ IN gctUINT8 Mask
+ );
+
+/* Set stencil reference. */
+gceSTATUS
+gco3D_SetStencilReference(
+ IN gco3D Engine,
+ IN gctUINT8 Reference,
+ IN gctBOOL Front
+ );
+
+/* Set stencil compare. */
+gceSTATUS
+gco3D_SetStencilCompare(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceCOMPARE Compare
+ );
+
+/* Set stencil operation on pass. */
+gceSTATUS
+gco3D_SetStencilPass(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceSTENCIL_OPERATION Operation
+ );
+
+/* Set stencil operation on fail. */
+gceSTATUS
+gco3D_SetStencilFail(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceSTENCIL_OPERATION Operation
+ );
+
+/* Set stencil operation on depth fail. */
+gceSTATUS
+gco3D_SetStencilDepthFail(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceSTENCIL_OPERATION Operation
+ );
+
+/* Set all stencil states in one blow. */
+gceSTATUS
+gco3D_SetStencilAll(
+ IN gco3D Engine,
+ IN gcsSTENCIL_INFO_PTR Info
+ );
+
+typedef struct _gcsALPHA_INFO * gcsALPHA_INFO_PTR;
+typedef struct _gcsALPHA_INFO
+{
+ /* Alpha test states. */
+ gctBOOL test;
+ gceCOMPARE compare;
+ gctUINT8 reference;
+ gctFLOAT floatReference;
+
+ /* Alpha blending states. */
+ gctBOOL blend;
+
+ gceBLEND_FUNCTION srcFuncColor;
+ gceBLEND_FUNCTION srcFuncAlpha;
+ gceBLEND_FUNCTION trgFuncColor;
+ gceBLEND_FUNCTION trgFuncAlpha;
+
+ gceBLEND_MODE modeColor;
+ gceBLEND_MODE modeAlpha;
+
+ gctUINT32 color;
+}
+gcsALPHA_INFO;
+
+/* Enable or disable alpha test. */
+gceSTATUS
+gco3D_SetAlphaTest(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set alpha test compare. */
+gceSTATUS
+gco3D_SetAlphaCompare(
+ IN gco3D Engine,
+ IN gceCOMPARE Compare
+ );
+
+/* Set alpha test reference in unsigned integer. */
+gceSTATUS
+gco3D_SetAlphaReference(
+ IN gco3D Engine,
+ IN gctUINT8 Reference,
+ IN gctFLOAT FloatReference
+ );
+
+/* Set alpha test reference in fixed point. */
+gceSTATUS
+gco3D_SetAlphaReferenceX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Reference
+ );
+
+/* Set alpha test reference in floating point. */
+gceSTATUS
+gco3D_SetAlphaReferenceF(
+ IN gco3D Engine,
+ IN gctFLOAT Reference
+ );
+
+/* Enable/Disable anti-alias line. */
+gceSTATUS
+gco3D_SetAntiAliasLine(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set texture slot for anti-alias line. */
+gceSTATUS
+gco3D_SetAALineTexSlot(
+ IN gco3D Engine,
+ IN gctUINT TexSlot
+ );
+
+/* Set anti-alias line width scale. */
+gceSTATUS
+gco3D_SetAALineWidth(
+ IN gco3D Engine,
+ IN gctFLOAT Width
+ );
+
+/* Draw a number of primitives. */
+gceSTATUS
+gco3D_DrawPrimitives(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN 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 gctBOOL SpilitDraw,
+ IN gctSIZE_T SpilitCount,
+ IN gcePRIMITIVE SpilitType,
+ IN gctSIZE_T InstanceCount
+ );
+
+gceSTATUS
+gco3D_DrawPrimitivesCount(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT* StartVertex,
+ IN gctSIZE_T* VertexCount,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+
+/* Draw a number of primitives using offsets. */
+gceSTATUS
+gco3D_DrawPrimitivesOffset(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT32 StartOffset,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Draw a number of indexed primitives. */
+gceSTATUS
+gco3D_DrawIndexedPrimitives(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctSIZE_T BaseVertex,
+ IN gctSIZE_T StartIndex,
+ IN gctSIZE_T PrimitiveCount,
+ IN gctBOOL SpilitDraw,
+ IN gctSIZE_T SpilitCount,
+ IN gcePRIMITIVE SpilitType
+ );
+
+/* Draw a number of indexed primitives using offsets. */
+gceSTATUS
+gco3D_DrawIndexedPrimitivesOffset(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT32 BaseOffset,
+ IN gctINT32 StartOffset,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Draw a element from pattern */
+gceSTATUS
+gco3D_DrawPattern(
+ IN gco3D Engine,
+ IN gcsFAST_FLUSH_PTR FastFlushInfo
+ );
+
+/* Enable or disable anti-aliasing. */
+gceSTATUS
+gco3D_SetAntiAlias(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Write data into the command buffer. */
+gceSTATUS
+gco3D_WriteBuffer(
+ IN gco3D Engine,
+ IN gctCONST_POINTER Data,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL Aligned
+ );
+
+/* Send sempahore and stall until sempahore is signalled. */
+gceSTATUS
+gco3D_Semaphore(
+ IN gco3D Engine,
+ IN gceWHERE From,
+ IN gceWHERE To,
+ IN gceHOW How);
+
+/* Explicitly flush shader L1 cache */
+gceSTATUS
+gco3D_FlushSHL1Cache(
+ IN gco3D Engine
+ );
+
+/* Set the subpixels center. */
+gceSTATUS
+gco3D_SetCentroids(
+ IN gco3D Engine,
+ IN gctUINT32 Index,
+ IN gctPOINTER Centroids
+ );
+
+gceSTATUS
+gco3D_SetLogicOp(
+ IN gco3D Engine,
+ IN gctUINT8 Rop
+ );
+
+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
+{
+ gctUINT32 dimensions;
+ gctUINT32 traverseOrder;
+ gctUINT32 enableSwathX;
+ gctUINT32 enableSwathY;
+ gctUINT32 enableSwathZ;
+ gctUINT32 swathSizeX;
+ gctUINT32 swathSizeY;
+ gctUINT32 swathSizeZ;
+ gctUINT32 valueOrder;
+
+ gctUINT32 globalSizeX;
+ gctUINT32 globalOffsetX;
+ gctUINT32 globalSizeY;
+ gctUINT32 globalOffsetY;
+ gctUINT32 globalSizeZ;
+ gctUINT32 globalOffsetZ;
+
+ gctUINT32 workGroupSizeX;
+ gctUINT32 workGroupCountX;
+ gctUINT32 workGroupSizeY;
+ gctUINT32 workGroupCountY;
+ gctUINT32 workGroupSizeZ;
+ gctUINT32 workGroupCountZ;
+
+ gctUINT32 threadAllocation;
+}
+gcsTHREAD_WALKER_INFO;
+
+/* Start OCL thread walker. */
+gceSTATUS
+gco3D_InvokeThreadWalker(
+ IN gco3D Engine,
+ IN gcsTHREAD_WALKER_INFO_PTR Info
+ );
+
+gceSTATUS
+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
+gco3D_GetWClipEnable(
+ IN gco3D Engine,
+ OUT gctBOOL * Enable
+ );
+
+gceSTATUS
+gco3D_SetWPlaneLimitF(
+ IN gco3D Engine,
+ IN gctFLOAT Value
+ );
+
+gceSTATUS
+gco3D_SetWPlaneLimitX(
+ 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 ------------------------*/
+
+/* Set the fragment processor configuration. */
+gceSTATUS
+gco3D_SetFragmentConfiguration(
+ IN gco3D Engine,
+ IN gctBOOL ColorFromStream,
+ IN gctBOOL EnableFog,
+ IN gctBOOL EnableSmoothPoint,
+ IN gctUINT32 ClipPlanes
+ );
+
+/* Enable/disable texture stage operation. */
+gceSTATUS
+gco3D_EnableTextureStage(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctBOOL Enable
+ );
+
+/* Program the channel enable masks for the color texture function. */
+gceSTATUS
+gco3D_SetTextureColorMask(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctBOOL ColorEnabled,
+ IN gctBOOL AlphaEnabled
+ );
+
+/* Program the channel enable masks for the alpha texture function. */
+gceSTATUS
+gco3D_SetTextureAlphaMask(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctBOOL ColorEnabled,
+ IN gctBOOL AlphaEnabled
+ );
+
+/* Program the constant fragment color. */
+gceSTATUS
+gco3D_SetFragmentColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gco3D_SetFragmentColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Program the constant fog color. */
+gceSTATUS
+gco3D_SetFogColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gco3D_SetFogColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Program the constant texture color. */
+gceSTATUS
+gco3D_SetTetxureColorX(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gco3D_SetTetxureColorF(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Configure color texture function. */
+gceSTATUS
+gco3D_SetColorTextureFunction(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gceTEXTURE_FUNCTION Function,
+ IN gceTEXTURE_SOURCE Source0,
+ IN gceTEXTURE_CHANNEL Channel0,
+ IN gceTEXTURE_SOURCE Source1,
+ IN gceTEXTURE_CHANNEL Channel1,
+ IN gceTEXTURE_SOURCE Source2,
+ IN gceTEXTURE_CHANNEL Channel2,
+ IN gctINT Scale
+ );
+
+/* Configure alpha texture function. */
+gceSTATUS
+gco3D_SetAlphaTextureFunction(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gceTEXTURE_FUNCTION Function,
+ IN gceTEXTURE_SOURCE Source0,
+ IN gceTEXTURE_CHANNEL Channel0,
+ IN gceTEXTURE_SOURCE Source1,
+ IN gceTEXTURE_CHANNEL Channel1,
+ IN gceTEXTURE_SOURCE Source2,
+ IN gceTEXTURE_CHANNEL Channel2,
+ IN gctINT Scale
+ );
+
+/******************************************************************************\
+******************************* gcoTEXTURE Object *******************************
+\******************************************************************************/
+
+/* Cube faces. */
+typedef enum _gceTEXTURE_FACE
+{
+ gcvFACE_NONE,
+ gcvFACE_POSITIVE_X,
+ gcvFACE_NEGATIVE_X,
+ gcvFACE_POSITIVE_Y,
+ gcvFACE_NEGATIVE_Y,
+ gcvFACE_POSITIVE_Z,
+ gcvFACE_NEGATIVE_Z,
+}
+gceTEXTURE_FACE;
+
+typedef struct _gcsTEXTURE
+{
+ /* Addressing modes. */
+ gceTEXTURE_ADDRESSING s;
+ gceTEXTURE_ADDRESSING t;
+ gceTEXTURE_ADDRESSING r;
+
+ gceTEXTURE_SWIZZLE swizzle[gcvTEXTURE_COMPONENT_NUM];
+
+ /* Border color. */
+ gctUINT8 border[gcvTEXTURE_COMPONENT_NUM];
+
+ /* Filters. */
+ gceTEXTURE_FILTER minFilter;
+ gceTEXTURE_FILTER magFilter;
+ gceTEXTURE_FILTER mipFilter;
+ gctUINT anisoFilter;
+
+ /* Level of detail. */
+ 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;
+
+/* Construct a new gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Construct(
+ IN gcoHAL Hal,
+ 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(
+ IN gcoHAL Hal,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gctUINT Faces,
+ IN gctUINT MipMapCount,
+ IN gcePOOL Pool,
+ OUT gcoTEXTURE * Texture
+ );
+
+/* Destroy an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Destroy(
+ IN gcoTEXTURE Texture
+ );
+
+/* Upload data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Upload(
+ IN gcoTEXTURE Texture,
+ IN gctINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ IN gctSIZE_T Width,
+ IN gctSIZE_T Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ 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 gctINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ IN gctSIZE_T X,
+ IN gctSIZE_T Y,
+ IN gctSIZE_T Width,
+ IN gctSIZE_T Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ 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(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FACE Face,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Slice,
+ IN gctPOINTER Memory[3],
+ IN gctINT Stride[3],
+ IN gceSURF_FORMAT Format
+ );
+
+/* Upload compressed data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_UploadCompressed(
+ IN gcoTEXTURE Texture,
+ IN gctINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ IN gctSIZE_T Width,
+ IN gctSIZE_T Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctSIZE_T Bytes
+ );
+
+/* Upload compressed sub data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_UploadCompressedSub(
+ IN gcoTEXTURE Texture,
+ IN gctINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ 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
+ );
+
+/* Get gcoSURF object for a mipmap level. */
+gceSTATUS
+gcoTEXTURE_GetMipMap(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ OUT gcoSURF * Surface
+ );
+
+/* Get gcoSURF object for a mipmap level and face offset. */
+gceSTATUS
+gcoTEXTURE_GetMipMapFace(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ OUT gcoSURF * Surface,
+ OUT 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 InternalFormat,
+ IN gceSURF_FORMAT Format,
+ IN gctSIZE_T Width,
+ IN gctSIZE_T Height,
+ IN gctSIZE_T Depth,
+ IN gctUINT Faces,
+ IN gcePOOL Pool,
+ OUT gcoSURF * Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_AddMipMapWithFlag(
+ IN gcoTEXTURE Texture,
+ 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_AddMipMapFromClient(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_AddMipMapFromSurface(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_SetEndianHint(
+ IN gcoTEXTURE Texture,
+ IN gceENDIAN_HINT EndianHint
+ );
+
+gceSTATUS
+gcoTEXTURE_Disable(
+ IN gcoHAL Hal,
+ IN gctINT Sampler
+ );
+
+gceSTATUS
+gcoTEXTURE_Flush(
+ IN gcoTEXTURE Texture
+ );
+
+gceSTATUS
+gcoTEXTURE_FlushVS(
+ IN gcoTEXTURE Texture
+ );
+
+gceSTATUS
+gcoTEXTURE_QueryCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT * MaxWidth,
+ OUT gctUINT * MaxHeight,
+ OUT gctUINT * MaxDepth,
+ OUT gctBOOL * Cubic,
+ OUT gctBOOL * NonPowerOfTwo,
+ OUT gctUINT * VertexSamplers,
+ OUT gctUINT * PixelSamplers
+ );
+
+gceSTATUS
+gcoTEXTURE_GetClosestFormat(
+ IN gcoHAL Hal,
+ IN gceSURF_FORMAT InFormat,
+ OUT gceSURF_FORMAT* OutFormat
+ );
+
+gceSTATUS
+gcoTEXTURE_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,
+ IN gctINT Level
+ );
+
+gceSTATUS
+gcoTEXTURE_RenderIntoMipMap2(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gctBOOL Sync
+ );
+
+gceSTATUS
+gcoTEXTURE_IsRenderable(
+ IN gcoTEXTURE Texture,
+ IN gctUINT Level
+ );
+
+gceSTATUS
+gcoTEXTURE_IsComplete(
+ IN gcoTEXTURE Texture,
+ IN gcsTEXTURE_PTR Info,
+ IN gctINT BaseLevel,
+ IN gctINT MaxLevel
+ );
+
+gceSTATUS
+gcoTEXTURE_BindTexture(
+ IN gcoTEXTURE Texture,
+ IN gctINT Target,
+ IN gctINT Sampler,
+ 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 ******************************
+\******************************************************************************/
+
+typedef enum _gceVERTEX_FORMAT
+{
+ gcvVERTEX_BYTE,
+ gcvVERTEX_UNSIGNED_BYTE,
+ gcvVERTEX_SHORT,
+ gcvVERTEX_UNSIGNED_SHORT,
+ gcvVERTEX_INT,
+ gcvVERTEX_UNSIGNED_INT,
+ gcvVERTEX_FIXED,
+ gcvVERTEX_HALF,
+ gcvVERTEX_FLOAT,
+ gcvVERTEX_UNSIGNED_INT_10_10_10_2,
+ gcvVERTEX_INT_10_10_10_2,
+ 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_SetSharedLock(
+ IN gcoSTREAM Stream,
+ IN gctPOINTER sharedLock
+ );
+
+gceSTATUS
+gcoSTREAM_Construct(
+ IN gcoHAL Hal,
+ OUT gcoSTREAM * Stream
+ );
+
+gceSTATUS
+gcoSTREAM_Destroy(
+ IN gcoSTREAM Stream
+ );
+
+gceSTATUS
+gcoSTREAM_Upload(
+ IN gcoSTREAM Stream,
+ IN gctCONST_POINTER Buffer,
+ IN gctSIZE_T Offset,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL Dynamic
+ );
+
+gceSTATUS
+gcoSTREAM_SetStride(
+ IN gcoSTREAM Stream,
+ 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,
+ OUT gctPOINTER * Logical,
+ OUT gctUINT32 * Physical
+ );
+
+gceSTATUS
+gcoSTREAM_Unlock(
+ IN gcoSTREAM Stream
+ );
+
+gceSTATUS
+gcoSTREAM_Reserve(
+ IN gcoSTREAM Stream,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoSTREAM_Flush(
+ IN gcoSTREAM Stream
+ );
+
+/* Dynamic buffer API. */
+gceSTATUS
+gcoSTREAM_SetDynamic(
+ IN gcoSTREAM Stream,
+ IN gctSIZE_T Bytes,
+ IN gctUINT Buffers
+ );
+
+typedef struct _gcsSTREAM_INFO
+{
+ gctUINT index;
+ gceVERTEX_FORMAT format;
+ gctBOOL normalized;
+ gctUINT components;
+ gctSIZE_T size;
+ gctCONST_POINTER data;
+ gctUINT stride;
+}
+gcsSTREAM_INFO, * gcsSTREAM_INFO_PTR;
+
+gceSTATUS
+gcoSTREAM_UploadDynamic(
+ IN gcoSTREAM Stream,
+ IN gctUINT VertexCount,
+ IN gctUINT InfoCount,
+ IN gcsSTREAM_INFO_PTR Info,
+ IN gcoVERTEX Vertex
+ );
+
+gceSTATUS
+gcoSTREAM_CPUCacheOperation(
+ IN gcoSTREAM Stream,
+ IN gceCACHEOPERATION Operation
+ );
+
+gceSTATUS
+gcoSTREAM_CPUCacheOperation_Range(
+ IN gcoSTREAM Stream,
+ IN gctSIZE_T Offset,
+ IN gctSIZE_T Length,
+ IN gceCACHEOPERATION Operation
+ );
+
+/******************************************************************************\
+******************************** gcoVERTEX Object ******************************
+\******************************************************************************/
+
+typedef struct _gcsVERTEX_ATTRIBUTES
+{
+ gceVERTEX_FORMAT format;
+ gctBOOL normalized;
+ gctUINT32 components;
+ gctSIZE_T size;
+ gctUINT32 stream;
+ gctUINT32 offset;
+ gctUINT32 stride;
+}
+gcsVERTEX_ATTRIBUTES;
+
+gceSTATUS
+gcoVERTEX_Construct(
+ IN gcoHAL Hal,
+ OUT gcoVERTEX * Vertex
+ );
+
+gceSTATUS
+gcoVERTEX_Destroy(
+ IN gcoVERTEX Vertex
+ );
+
+gceSTATUS
+gcoVERTEX_Reset(
+ IN gcoVERTEX Vertex
+ );
+
+gceSTATUS
+gcoVERTEX_EnableAttribute(
+ IN gcoVERTEX Vertex,
+ IN gctUINT32 Index,
+ IN gceVERTEX_FORMAT Format,
+ IN gctBOOL Normalized,
+ IN gctUINT32 Components,
+ IN gcoSTREAM Stream,
+ IN gctUINT32 Offset,
+ IN gctUINT32 Stride
+ );
+
+gceSTATUS
+gcoVERTEX_DisableAttribute(
+ IN gcoVERTEX Vertex,
+ IN gctUINT32 Index
+ );
+
+gceSTATUS
+gcoVERTEX_Bind(
+ IN gcoVERTEX Vertex
+ );
+
+/*******************************************************************************
+***** gcoVERTEXARRAY Object ***************************************************/
+
+typedef struct _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. */
+ gctBOOL enable;
+
+ /* Number of components. */
+ gctINT size;
+
+ /* Attribute format. */
+ gceVERTEX_FORMAT format;
+
+ /* Flag whether the attribute is normalized or not. */
+ gctBOOL normalized;
+
+ /* Stride of the component. */
+ gctUINT stride;
+
+ /* Divisor of the attribute */
+ gctUINT divisor;
+
+ /* Pointer to the attribute data. */
+ gctCONST_POINTER pointer;
+
+ /* Stream object owning the attribute data. */
+ gcoSTREAM stream;
+
+ /* Generic values for attribute. */
+ gctFLOAT genericValue[4];
+
+ /* Generic size for attribute. */
+ gctINT genericSize;
+
+ /* Vertex shader linkage. */
+ gctUINT linkage;
+
+ gctBOOL isPosition;
+}
+gcsVERTEXARRAY,
+* gcsVERTEXARRAY_PTR;
+
+gceSTATUS
+gcoVERTEXARRAY_Construct(
+ IN gcoHAL Hal,
+ OUT gcoVERTEXARRAY * Vertex
+ );
+
+gceSTATUS
+gcoVERTEXARRAY_Destroy(
+ IN gcoVERTEXARRAY Vertex
+ );
+
+gceSTATUS
+gcoVERTEXARRAY_IndexUpdate(
+ IN gctSIZE_T * Count,
+ IN gceINDEX_TYPE IndexType,
+ IN gcoBUFOBJ IndexObject,
+ IN gctPOINTER IndexMemory
+ );
+
+gceSTATUS
+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,
+ IN OUT gcePRIMITIVE * PrimitiveType,
+ IN OUT gctBOOL * SpilitDraw,
+ IN OUT gctSIZE_T * SpilitCount,
+ IN OUT gcePRIMITIVE * SpilitPrimitiveType,
+#if gcdUSE_WCLIP_PATCH
+ IN OUT gctUINT * PrimitiveCount,
+ IN OUT gctFLOAT * wLimitRms,
+ IN OUT gctBOOL * wLimitDirty
+#else
+ IN OUT gctUINT * PrimitiveCount
+#endif
+ );
+
+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 gctBOOL PrimtiveRestart,
+ IN OUT gcePRIMITIVE * PrimitiveType,
+ IN OUT gctBOOL * SpilitDraw,
+ IN OUT gctSIZE_T * SpilitCount,
+ IN OUT gcePRIMITIVE * SpilitPrimitiveType,
+#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_Bind(
+ IN gcoVERTEXARRAY Vertex,
+ IN gctUINT32 EnableBits,
+ IN gcsVERTEXARRAY_PTR VertexArray,
+ IN gctUINT First,
+ IN gctSIZE_T * Count,
+ IN gceINDEX_TYPE IndexType,
+ IN gcoINDEX IndexObject,
+ IN gctPOINTER IndexMemory,
+ IN OUT gcePRIMITIVE * PrimitiveType,
+ IN OUT gctBOOL * SpilitDraw,
+ IN OUT gctSIZE_T * SpilitCount,
+ IN OUT gcePRIMITIVE * SpilitPrimitiveType,
+#if gcdUSE_WCLIP_PATCH
+ IN OUT gctUINT * PrimitiveCount,
+ IN OUT gctFLOAT * wLimitRms,
+ IN OUT gctBOOL * wLimitDirty
+#else
+ IN OUT gctUINT * PrimitiveCount
+#endif
+ );
+
+/*******************************************************************************
+***** Composition *************************************************************/
+
+typedef enum _gceCOMPOSITION
+{
+ gcvCOMPOSE_CLEAR = 1,
+ gcvCOMPOSE_BLUR,
+ gcvCOMPOSE_DIM,
+ gcvCOMPOSE_LAYER
+}
+gceCOMPOSITION;
+
+typedef struct _gcsCOMPOSITION * gcsCOMPOSITION_PTR;
+typedef struct _gcsCOMPOSITION
+{
+ /* Structure size. */
+ gctUINT structSize;
+
+ /* Composition operation. */
+ gceCOMPOSITION operation;
+
+ /* Layer to be composed. */
+ gcoSURF layer;
+
+ /* Source and target coordinates. */
+ gcsRECT srcRect;
+ gcsRECT trgRect;
+
+ /* Target rectangle */
+ gcsPOINT v0;
+ gcsPOINT v1;
+ gcsPOINT v2;
+
+ /* Blending parameters. */
+ gctBOOL enableBlending;
+ gctBOOL premultiplied;
+ gctUINT8 alphaValue;
+
+ /* Clear color. */
+ gctFLOAT r;
+ gctFLOAT g;
+ gctFLOAT b;
+ gctFLOAT a;
+}
+gcsCOMPOSITION;
+
+gceSTATUS
+gco3D_ProbeComposition(
+ IN gcoHARDWARE Hardware,
+ IN gctBOOL ResetIfEmpty
+ );
+
+gceSTATUS
+gco3D_CompositionBegin(
+ 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
+ );
+
+gceSTATUS
+gco3D_CompositionEnd(
+ IN gcoHARDWARE Hardware,
+ IN gcoSURF Target,
+ IN gctBOOL Synchronous
+ );
+
+/* Frame Database */
+gceSTATUS
+gcoHAL_AddFrameDB(
+ void
+ );
+
+gceSTATUS
+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,
+
+ /* special patch for optimaize performance,
+ ** no fence and duplicate stream to ensure data correct
+ */
+ gcvBUFOBJ_USAGE_DISABLE_FENCE_DYNAMIC_STREAM = 256
+} 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
+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,
+ IN gceBUFOBJ_USAGE Usage
+ );
+
+/* Bind an index object to the hardware. */
+gceSTATUS
+gcoBUFOBJ_IndexBind (
+ IN gcoBUFOBJ Index,
+ IN gceINDEX_TYPE Type,
+ IN gctUINT32 Offset,
+ IN gctSIZE_T Count
+ );
+
+/* Find min and max index for the index buffer */
+gceSTATUS
+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
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* gcdENABLE_3D */
+#endif /* __gc_hal_engine_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h
new file mode 100644
index 000000000000..0c23be36cd5b
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h
@@ -0,0 +1,1326 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_engine_vg_h_
+#define __gc_hal_engine_vg_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "gc_hal_types.h"
+
+/******************************************************************************\
+******************************** VG Enumerations *******************************
+\******************************************************************************/
+
+/**
+** @ingroup gcoVG
+**
+** @brief Tiling mode for painting and imagig.
+**
+** This enumeration defines the tiling modes supported by the HAL. This is
+** in fact a one-to-one mapping of the OpenVG 1.1 tile modes.
+*/
+typedef enum _gceTILE_MODE
+{
+ gcvTILE_FILL,
+ gcvTILE_PAD,
+ gcvTILE_REPEAT,
+ gcvTILE_REFLECT
+}
+gceTILE_MODE;
+
+/******************************************************************************/
+/** @ingroup gcoVG
+**
+** @brief The different paint modes.
+**
+** This enumeration lists the available paint modes.
+*/
+typedef enum _gcePAINT_TYPE
+{
+ /** Solid color. */
+ gcvPAINT_MODE_SOLID,
+
+ /** Linear gradient. */
+ gcvPAINT_MODE_LINEAR,
+
+ /** Radial gradient. */
+ gcvPAINT_MODE_RADIAL,
+
+ /** Pattern. */
+ gcvPAINT_MODE_PATTERN,
+
+ /** Mode count. */
+ gcvPAINT_MODE_COUNT
+}
+gcePAINT_TYPE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Types of path data supported by HAL.
+**
+** This enumeration defines the types of path data supported by the HAL.
+** This is in fact a one-to-one mapping of the OpenVG 1.1 path types.
+*/
+typedef enum _gcePATHTYPE
+{
+ gcePATHTYPE_UNKNOWN = -1,
+ gcePATHTYPE_INT8,
+ gcePATHTYPE_INT16,
+ gcePATHTYPE_INT32,
+ gcePATHTYPE_FLOAT
+}
+gcePATHTYPE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Supported path segment commands.
+**
+** This enumeration defines the path segment commands supported by the HAL.
+*/
+typedef enum _gceVGCMD
+{
+ gcvVGCMD_END, /* 0: GCCMD_TS_OPCODE_END */
+ gcvVGCMD_CLOSE, /* 1: GCCMD_TS_OPCODE_CLOSE */
+ gcvVGCMD_MOVE, /* 2: GCCMD_TS_OPCODE_MOVE */
+ gcvVGCMD_MOVE_REL, /* 3: GCCMD_TS_OPCODE_MOVE_REL */
+ gcvVGCMD_LINE, /* 4: GCCMD_TS_OPCODE_LINE */
+ gcvVGCMD_LINE_REL, /* 5: GCCMD_TS_OPCODE_LINE_REL */
+ gcvVGCMD_QUAD, /* 6: GCCMD_TS_OPCODE_QUADRATIC */
+ gcvVGCMD_QUAD_REL, /* 7: GCCMD_TS_OPCODE_QUADRATIC_REL */
+ gcvVGCMD_CUBIC, /* 8: GCCMD_TS_OPCODE_CUBIC */
+ gcvVGCMD_CUBIC_REL, /* 9: GCCMD_TS_OPCODE_CUBIC_REL */
+ gcvVGCMD_BREAK, /* 10: GCCMD_TS_OPCODE_BREAK */
+ gcvVGCMD_HLINE, /* 11: ******* R E S E R V E D *******/
+ gcvVGCMD_HLINE_REL, /* 12: ******* R E S E R V E D *******/
+ gcvVGCMD_VLINE, /* 13: ******* R E S E R V E D *******/
+ gcvVGCMD_VLINE_REL, /* 14: ******* R E S E R V E D *******/
+ gcvVGCMD_SQUAD, /* 15: ******* R E S E R V E D *******/
+ gcvVGCMD_SQUAD_REL, /* 16: ******* R E S E R V E D *******/
+ gcvVGCMD_SCUBIC, /* 17: ******* R E S E R V E D *******/
+ gcvVGCMD_SCUBIC_REL, /* 18: ******* R E S E R V E D *******/
+ gcvVGCMD_SCCWARC, /* 19: ******* R E S E R V E D *******/
+ gcvVGCMD_SCCWARC_REL, /* 20: ******* R E S E R V E D *******/
+ gcvVGCMD_SCWARC, /* 21: ******* R E S E R V E D *******/
+ gcvVGCMD_SCWARC_REL, /* 22: ******* R E S E R V E D *******/
+ gcvVGCMD_LCCWARC, /* 23: ******* R E S E R V E D *******/
+ gcvVGCMD_LCCWARC_REL, /* 24: ******* R E S E R V E D *******/
+ gcvVGCMD_LCWARC, /* 25: ******* R E S E R V E D *******/
+ gcvVGCMD_LCWARC_REL, /* 26: ******* R E S E R V E D *******/
+
+ /* The width of the command recognized by the hardware on bits. */
+ gcvVGCMD_WIDTH = 5,
+
+ /* Hardware command mask. */
+ gcvVGCMD_MASK = (1 << gcvVGCMD_WIDTH) - 1,
+
+ /* Command modifiers. */
+ gcvVGCMD_H_MOD = 1 << gcvVGCMD_WIDTH, /* = 32 */
+ gcvVGCMD_V_MOD = 2 << gcvVGCMD_WIDTH, /* = 64 */
+ gcvVGCMD_S_MOD = 3 << gcvVGCMD_WIDTH, /* = 96 */
+ gcvVGCMD_ARC_MOD = 4 << gcvVGCMD_WIDTH, /* = 128 */
+
+ /* Emulated LINE commands. */
+ gcvVGCMD_HLINE_EMUL = gcvVGCMD_H_MOD | gcvVGCMD_LINE, /* = 36 */
+ gcvVGCMD_HLINE_EMUL_REL = gcvVGCMD_H_MOD | gcvVGCMD_LINE_REL, /* = 37 */
+ gcvVGCMD_VLINE_EMUL = gcvVGCMD_V_MOD | gcvVGCMD_LINE, /* = 68 */
+ gcvVGCMD_VLINE_EMUL_REL = gcvVGCMD_V_MOD | gcvVGCMD_LINE_REL, /* = 69 */
+
+ /* Emulated SMOOTH commands. */
+ gcvVGCMD_SQUAD_EMUL = gcvVGCMD_S_MOD | gcvVGCMD_QUAD, /* = 102 */
+ gcvVGCMD_SQUAD_EMUL_REL = gcvVGCMD_S_MOD | gcvVGCMD_QUAD_REL, /* = 103 */
+ gcvVGCMD_SCUBIC_EMUL = gcvVGCMD_S_MOD | gcvVGCMD_CUBIC, /* = 104 */
+ gcvVGCMD_SCUBIC_EMUL_REL = gcvVGCMD_S_MOD | gcvVGCMD_CUBIC_REL, /* = 105 */
+
+ /* Emulation ARC commands. */
+ gcvVGCMD_ARC_LINE = gcvVGCMD_ARC_MOD | gcvVGCMD_LINE, /* = 132 */
+ gcvVGCMD_ARC_LINE_REL = gcvVGCMD_ARC_MOD | gcvVGCMD_LINE_REL, /* = 133 */
+ gcvVGCMD_ARC_QUAD = gcvVGCMD_ARC_MOD | gcvVGCMD_QUAD, /* = 134 */
+ gcvVGCMD_ARC_QUAD_REL = gcvVGCMD_ARC_MOD | gcvVGCMD_QUAD_REL /* = 135 */
+}
+gceVGCMD;
+typedef enum _gceVGCMD * gceVGCMD_PTR;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Blending modes supported by the HAL.
+**
+** This enumeration defines the blending modes supported by the HAL. This is
+** in fact a one-to-one mapping of the OpenVG 1.1 blending modes.
+*/
+typedef enum _gceVG_BLEND
+{
+ gcvVG_BLEND_SRC,
+ gcvVG_BLEND_SRC_OVER,
+ gcvVG_BLEND_DST_OVER,
+ gcvVG_BLEND_SRC_IN,
+ gcvVG_BLEND_DST_IN,
+ gcvVG_BLEND_MULTIPLY,
+ gcvVG_BLEND_SCREEN,
+ gcvVG_BLEND_DARKEN,
+ gcvVG_BLEND_LIGHTEN,
+ gcvVG_BLEND_ADDITIVE,
+ gcvVG_BLEND_SUBTRACT,
+ gcvVG_BLEND_FILTER
+}
+gceVG_BLEND;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Image modes supported by the HAL.
+**
+** This enumeration defines the image modes supported by the HAL. This is
+** in fact a one-to-one mapping of the OpenVG 1.1 image modes with the addition
+** of NO IMAGE.
+*/
+typedef enum _gceVG_IMAGE
+{
+ gcvVG_IMAGE_NONE,
+ gcvVG_IMAGE_NORMAL,
+ gcvVG_IMAGE_MULTIPLY,
+ gcvVG_IMAGE_STENCIL,
+ gcvVG_IMAGE_FILTER
+}
+gceVG_IMAGE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Filter mode patterns and imaging.
+**
+** This enumeration defines the filter modes supported by the HAL.
+*/
+typedef enum _gceIMAGE_FILTER
+{
+ gcvFILTER_POINT,
+ gcvFILTER_LINEAR,
+ gcvFILTER_BI_LINEAR
+}
+gceIMAGE_FILTER;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Primitive modes supported by the HAL.
+**
+** This enumeration defines the primitive modes supported by the HAL.
+*/
+typedef enum _gceVG_PRIMITIVE
+{
+ gcvVG_SCANLINE,
+ gcvVG_RECTANGLE,
+ gcvVG_TESSELLATED,
+ gcvVG_TESSELLATED_TILED
+}
+gceVG_PRIMITIVE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Rendering quality modes supported by the HAL.
+**
+** This enumeration defines the rendering quality modes supported by the HAL.
+*/
+typedef enum _gceRENDER_QUALITY
+{
+ gcvVG_NONANTIALIASED,
+ gcvVG_2X2_MSAA,
+ gcvVG_2X4_MSAA,
+ gcvVG_4X4_MSAA
+}
+gceRENDER_QUALITY;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Fill rules supported by the HAL.
+**
+** This enumeration defines the fill rules supported by the HAL.
+*/
+typedef enum _gceFILL_RULE
+{
+ gcvVG_EVEN_ODD,
+ gcvVG_NON_ZERO
+}
+gceFILL_RULE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Cap styles supported by the HAL.
+**
+** This enumeration defines the cap styles supported by the HAL.
+*/
+typedef enum _gceCAP_STYLE
+{
+ gcvCAP_BUTT,
+ gcvCAP_ROUND,
+ gcvCAP_SQUARE
+}
+gceCAP_STYLE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Join styles supported by the HAL.
+**
+** This enumeration defines the join styles supported by the HAL.
+*/
+typedef enum _gceJOIN_STYLE
+{
+ gcvJOIN_MITER,
+ gcvJOIN_ROUND,
+ gcvJOIN_BEVEL
+}
+gceJOIN_STYLE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Channel mask values.
+**
+** This enumeration defines the values for channel mask used in image
+** filtering.
+*/
+
+/* Base values for channel mask definitions. */
+#define gcvCHANNEL_X (0)
+#define gcvCHANNEL_R (1 << 0)
+#define gcvCHANNEL_G (1 << 1)
+#define gcvCHANNEL_B (1 << 2)
+#define gcvCHANNEL_A (1 << 3)
+
+typedef enum _gceCHANNEL
+{
+ gcvCHANNEL_XXXX = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X),
+ gcvCHANNEL_XXXA = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_A),
+ gcvCHANNEL_XXBX = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_X),
+ gcvCHANNEL_XXBA = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_A),
+
+ gcvCHANNEL_XGXX = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_X),
+ gcvCHANNEL_XGXA = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_A),
+ gcvCHANNEL_XGBX = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_X),
+ gcvCHANNEL_XGBA = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_A),
+
+ gcvCHANNEL_RXXX = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X),
+ gcvCHANNEL_RXXA = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_A),
+ gcvCHANNEL_RXBX = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_X),
+ gcvCHANNEL_RXBA = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_A),
+
+ gcvCHANNEL_RGXX = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_X),
+ gcvCHANNEL_RGXA = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_A),
+ gcvCHANNEL_RGBX = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_X),
+ gcvCHANNEL_RGBA = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_A),
+}
+gceCHANNEL;
+
+/******************************************************************************\
+******************************** VG Structures *******************************
+\******************************************************************************/
+
+/**
+** @ingroup gcoVG
+**
+** @brief Definition of the color ramp used by the gradient paints.
+**
+** The gcsCOLOR_RAMP structure defines the layout of one single color inside
+** a color ramp which is used by gradient paints.
+*/
+typedef struct _gcsCOLOR_RAMP
+{
+ /** Value for the color stop. */
+ gctFLOAT stop;
+
+ /** Red color channel value for the color stop. */
+ gctFLOAT red;
+
+ /** Green color channel value for the color stop. */
+ gctFLOAT green;
+
+ /** Blue color channel value for the color stop. */
+ gctFLOAT blue;
+
+ /** Alpha color channel value for the color stop. */
+ gctFLOAT alpha;
+}
+gcsCOLOR_RAMP, * gcsCOLOR_RAMP_PTR;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Definition of the color ramp used by the gradient paints in fixed form.
+**
+** The gcsCOLOR_RAMP structure defines the layout of one single color inside
+** a color ramp which is used by gradient paints.
+*/
+typedef struct _gcsFIXED_COLOR_RAMP
+{
+ /** Value for the color stop. */
+ gctFIXED_POINT stop;
+
+ /** Red color channel value for the color stop. */
+ gctFIXED_POINT red;
+
+ /** Green color channel value for the color stop. */
+ gctFIXED_POINT green;
+
+ /** Blue color channel value for the color stop. */
+ gctFIXED_POINT blue;
+
+ /** Alpha color channel value for the color stop. */
+ gctFIXED_POINT alpha;
+}
+gcsFIXED_COLOR_RAMP, * gcsFIXED_COLOR_RAMP_PTR;
+
+
+/**
+** @ingroup gcoVG
+**
+** @brief Rectangle structure used by the gcoVG object.
+**
+** This structure defines the layout of a rectangle. Make sure width and
+** height are larger than 0.
+*/
+typedef struct _gcsVG_RECT * gcsVG_RECT_PTR;
+typedef struct _gcsVG_RECT
+{
+ /** Left location of the rectangle. */
+ gctINT x;
+
+ /** Top location of the rectangle. */
+ gctINT y;
+
+ /** Width of the rectangle. */
+ gctINT width;
+
+ /** Height of the rectangle. */
+ gctINT height;
+}
+gcsVG_RECT;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Path command buffer attribute structure.
+**
+** The gcsPATH_BUFFER_INFO structure contains the specifics about
+** the layout of the path data command buffer.
+*/
+typedef struct _gcsPATH_BUFFER_INFO * gcsPATH_BUFFER_INFO_PTR;
+typedef struct _gcsPATH_BUFFER_INFO
+{
+ gctUINT reservedForHead;
+ gctUINT reservedForTail;
+}
+gcsPATH_BUFFER_INFO;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Definition of the path data container structure.
+**
+** The gcsPATH structure defines the layout of the path data container.
+*/
+typedef struct _gcsPATH_DATA * gcsPATH_DATA_PTR;
+typedef struct _gcsPATH_DATA
+{
+ /* Data container in command buffer format. */
+ gcsCMDBUFFER data;
+
+ /* Path data type. */
+ gcePATHTYPE dataType;
+}
+gcsPATH_DATA;
+
+
+/******************************************************************************\
+********************************* gcoHAL Object ********************************
+\******************************************************************************/
+
+/* Query path data storage attributes. */
+gceSTATUS
+gcoHAL_QueryPathStorage(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ OUT gcsPATH_BUFFER_INFO_PTR Information
+ );
+
+/* Associate a completion signal with the command buffer. */
+gceSTATUS
+gcoHAL_AssociateCompletion(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcsPATH_DATA_PTR PathData
+ );
+
+/* Release the current command buffer completion signal. */
+gceSTATUS
+gcoHAL_DeassociateCompletion(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcsPATH_DATA_PTR PathData
+ );
+
+/* Verify whether the command buffer is still in use. */
+gceSTATUS
+gcoHAL_CheckCompletion(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcsPATH_DATA_PTR PathData
+ );
+
+/* Wait until the command buffer is no longer in use. */
+gceSTATUS
+gcoHAL_WaitCompletion(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcsPATH_DATA_PTR PathData
+ );
+
+/* Flush the pixel cache. */
+gceSTATUS
+gcoHAL_Flush(
+ IN gcoHAL Hal
+#if gcdGC355_PROFILER
+ ,
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ 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 gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ );
+
+/* Combine pool and offset into a harwdare address. */
+gceSTATUS
+gcoHAL_CombineAddress(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcePOOL Pool,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ );
+
+/* Schedule to free linear video memory allocated. */
+gceSTATUS
+gcoHAL_ScheduleVideoMemory(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ 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,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctUINT32 Node
+ );
+
+/* Query command buffer attributes. */
+gceSTATUS
+gcoHAL_QueryCommandBuffer(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ 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 gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctUINT Size,
+ IN gctUINT Alignment,
+ IN gcePOOL Pool,
+ OUT gctUINT32 * Node,
+ OUT gctUINT32 * Address,
+ OUT gctPOINTER * Memory
+ );
+
+/* Align the specified size accordingly to the hardware requirements. */
+gceSTATUS
+gcoHAL_GetAlignedSurfaceSize(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceSURF_TYPE Type,
+ IN OUT gctUINT32_PTR Width,
+ IN OUT gctUINT32_PTR Height
+ );
+
+gceSTATUS
+gcoHAL_ReserveTask(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceBLOCK Block,
+ IN gctUINT TaskCount,
+ IN gctUINT32 Bytes,
+ OUT gctPOINTER * Memory
+ );
+/******************************************************************************\
+********************************** gcoVG Object ********************************
+\******************************************************************************/
+
+/** @defgroup gcoVG gcoVG
+**
+** The gcoVG object abstracts the VG hardware pipe.
+*/
+#if gcdGC355_PROFILER
+void
+gcoVG_ProfilerEnableDisable(
+ IN gcoVG Vg,
+ IN gctUINT64 appStartTime,
+ IN gctBOOL enableGetAPITimes,
+ IN gctFILE apiTimeFile
+ );
+
+void
+gcoVG_ProfilerTreeDepth(
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth
+ );
+
+void
+gcoVG_ProfilerTag(
+ IN gcoVG Vg,
+ IN gctSTRING Tag
+ );
+
+void
+gcoVG_ProfilerSetStates(
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT treeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth
+ );
+#endif
+
+gctBOOL
+gcoVG_IsMaskSupported(
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceSURF_FORMAT Format
+ );
+
+gctBOOL
+gcoVG_IsTargetSupported(
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceSURF_FORMAT Format
+ );
+
+gctBOOL
+gcoVG_IsImageSupported(
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceSURF_FORMAT Format
+ );
+
+gctUINT8 gcoVG_PackColorComponent(
+#if gcdGC355_PROFILER
+ gcoVG Vg,
+ gcsPROFILERFUNCNODE *DList,
+ gctUINT TreeDepth,
+ gctUINT saveLayerTreeDepth,
+ gctUINT varTreeDepth,
+#endif
+ gctFLOAT Value
+ );
+
+gceSTATUS
+gcoVG_Construct(
+ IN gcoHAL Hal,
+ OUT gcoVG * Vg
+ );
+
+gceSTATUS
+gcoVG_Destroy(
+ IN gcoVG Vg
+#if gcdGC355_PROFILER
+ ,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth
+#endif
+ );
+
+gceSTATUS
+gcoVG_SetTarget(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Target
+ );
+
+gceSTATUS
+gcoVG_UnsetTarget(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoVG_SetUserToSurface(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT UserToSurface[9]
+ );
+
+gceSTATUS
+gcoVG_SetSurfaceToImage(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT SurfaceToImage[9]
+ );
+
+gceSTATUS
+gcoVG_EnableMask(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gcoVG_SetMask(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Mask
+ );
+
+gceSTATUS
+gcoVG_UnsetMask(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoVG_FlushMask(
+ IN gcoVG Vg
+#if gcdGC355_PROFILER
+ ,
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth
+#endif
+ );
+
+gceSTATUS
+gcoVG_EnableScissor(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gcoVG_SetScissor(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctSIZE_T RectangleCount,
+ IN gcsVG_RECT_PTR Rectangles
+ );
+
+gceSTATUS
+gcoVG_EnableColorTransform(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gcoVG_SetColorTransform(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT ColorTransform[8]
+ );
+
+gceSTATUS
+gcoVG_SetTileFillColor(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+gceSTATUS
+gcoVG_SetSolidPaint(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctUINT8 Red,
+ IN gctUINT8 Green,
+ IN gctUINT8 Blue,
+ IN gctUINT8 Alpha
+ );
+
+gceSTATUS
+gcoVG_SetLinearPaint(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT Constant,
+ IN gctFLOAT StepX,
+ IN gctFLOAT StepY
+ );
+
+gceSTATUS
+gcoVG_SetRadialPaint(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT LinConstant,
+ IN gctFLOAT LinStepX,
+ IN gctFLOAT LinStepY,
+ IN gctFLOAT RadConstant,
+ IN gctFLOAT RadStepX,
+ IN gctFLOAT RadStepY,
+ IN gctFLOAT RadStepXX,
+ IN gctFLOAT RadStepYY,
+ IN gctFLOAT RadStepXY
+ );
+
+gceSTATUS
+gcoVG_SetPatternPaint(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT UConstant,
+ IN gctFLOAT UStepX,
+ IN gctFLOAT UStepY,
+ IN gctFLOAT VConstant,
+ IN gctFLOAT VStepX,
+ IN gctFLOAT VStepY,
+ IN gctBOOL Linear
+ );
+
+gceSTATUS
+gcoVG_SetColorRamp(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF ColorRamp,
+ IN gceTILE_MODE ColorRampSpreadMode
+ );
+
+gceSTATUS
+gcoVG_SetPattern(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ 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
+ );
+
+gceSTATUS
+gcoVG_SetImageMode(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceVG_IMAGE Mode
+ );
+
+gceSTATUS
+gcoVG_SetBlendMode(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceVG_BLEND Mode
+ );
+
+gceSTATUS
+gcoVG_SetRenderingQuality(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceRENDER_QUALITY Quality
+ );
+
+gceSTATUS
+gcoVG_SetFillRule(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceFILL_RULE FillRule
+ );
+
+gceSTATUS
+gcoVG_FinalizePath(
+ IN gcoVG Vg,
+ IN gcsPATH_DATA_PTR PathData
+ );
+
+gceSTATUS
+gcoVG_Clear(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctINT X,
+ IN gctINT Y,
+ IN gctINT Width,
+ IN gctINT Height
+ );
+
+gceSTATUS
+gcoVG_DrawPath(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ 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 gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Source,
+ IN gcsPOINT_PTR SourceOrigin,
+ IN gcsPOINT_PTR TargetOrigin,
+ IN gcsSIZE_PTR SourceSize,
+ IN gctINT SourceX,
+ IN gctINT SourceY,
+ IN gctINT TargetX,
+ IN gctINT TargetY,
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctBOOL Mask,
+ IN gctBOOL isDrawImage
+ );
+
+gceSTATUS
+gcoVG_TesselateImage(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ 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_DrawSurfaceToImage(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Image,
+ IN const gcsVG_RECT_PTR SrcRectangle,
+ IN const gcsVG_RECT_PTR DstRectangle,
+ IN const gctFLOAT Matrix[9],
+ IN gceIMAGE_FILTER Filter,
+ IN gctBOOL Mask,
+ IN gctBOOL FirstTime
+ );
+
+gceSTATUS
+gcoVG_Blit(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Source,
+ IN gcoSURF Target,
+ IN gcsVG_RECT_PTR SrcRect,
+ IN gcsVG_RECT_PTR TrgRect,
+ IN gceIMAGE_FILTER Filter,
+ IN gceVG_BLEND Mode
+ );
+
+gceSTATUS
+gcoVG_ColorMatrix(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Source,
+ IN gcoSURF Target,
+ IN const gctFLOAT * Matrix,
+ IN gceCHANNEL ColorChannels,
+ IN gctBOOL FilterLinear,
+ IN gctBOOL FilterPremultiplied,
+ IN gcsPOINT_PTR SourceOrigin,
+ IN gcsPOINT_PTR TargetOrigin,
+ IN gctINT Width,
+ IN gctINT Height
+ );
+
+gceSTATUS
+gcoVG_SeparableConvolve(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Source,
+ IN gcoSURF Target,
+ IN gctINT KernelWidth,
+ IN gctINT KernelHeight,
+ IN gctINT ShiftX,
+ IN gctINT ShiftY,
+ IN const gctINT16 * KernelX,
+ IN const gctINT16 * KernelY,
+ IN gctFLOAT Scale,
+ IN gctFLOAT Bias,
+ IN gceTILE_MODE TilingMode,
+ IN gctFLOAT_PTR FillColor,
+ IN gceCHANNEL ColorChannels,
+ IN gctBOOL FilterLinear,
+ IN gctBOOL FilterPremultiplied,
+ IN gcsPOINT_PTR SourceOrigin,
+ IN gcsPOINT_PTR TargetOrigin,
+ IN gcsSIZE_PTR SourceSize,
+ IN gctINT Width,
+ IN gctINT Height
+ );
+
+gceSTATUS
+gcoVG_GaussianBlur(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Source,
+ IN gcoSURF Target,
+ IN gctFLOAT StdDeviationX,
+ IN gctFLOAT StdDeviationY,
+ IN gceTILE_MODE TilingMode,
+ IN gctFLOAT_PTR FillColor,
+ IN gceCHANNEL ColorChannels,
+ IN gctBOOL FilterLinear,
+ IN gctBOOL FilterPremultiplied,
+ IN gcsPOINT_PTR SourceOrigin,
+ IN gcsPOINT_PTR TargetOrigin,
+ IN gcsSIZE_PTR SourceSize,
+ IN gctINT Width,
+ IN gctINT Height
+ );
+
+gceSTATUS
+gcoVG_EnableDither(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctBOOL Enable
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_vg_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
new file mode 100644
index 000000000000..a6062dfb6db7
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
@@ -0,0 +1,1715 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_enum_h_
+#define __gc_hal_enum_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 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,
+ gcv800 = 0x0800,
+ 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;
+
+/* Chip features. */
+typedef enum _gceFEATURE
+{
+ gcvFEATURE_PIPE_2D = 0,
+ gcvFEATURE_PIPE_3D,
+ gcvFEATURE_PIPE_VG,
+ gcvFEATURE_DC,
+ gcvFEATURE_HIGH_DYNAMIC_RANGE,
+ gcvFEATURE_MODULE_CG,
+ gcvFEATURE_MIN_AREA,
+ gcvFEATURE_BUFFER_INTERLEAVING,
+ gcvFEATURE_BYTE_WRITE_2D,
+ gcvFEATURE_ENDIANNESS_CONFIG,
+ gcvFEATURE_DUAL_RETURN_BUS,
+ gcvFEATURE_DEBUG_MODE,
+ gcvFEATURE_YUY2_RENDER_TARGET,
+ gcvFEATURE_FRAGMENT_PROCESSOR,
+ gcvFEATURE_2DPE20,
+ gcvFEATURE_FAST_CLEAR,
+ gcvFEATURE_YUV420_TILER,
+ gcvFEATURE_YUY2_AVERAGING,
+ gcvFEATURE_FLIP_Y,
+ gcvFEATURE_EARLY_Z,
+ gcvFEATURE_COMPRESSION,
+ gcvFEATURE_MSAA,
+ gcvFEATURE_SPECIAL_ANTI_ALIASING,
+ gcvFEATURE_SPECIAL_MSAA_LOD,
+ gcvFEATURE_422_TEXTURE_COMPRESSION,
+ gcvFEATURE_DXT_TEXTURE_COMPRESSION,
+ gcvFEATURE_ETC1_TEXTURE_COMPRESSION,
+ gcvFEATURE_CORRECT_TEXTURE_CONVERTER,
+ gcvFEATURE_TEXTURE_8K,
+ gcvFEATURE_SCALER,
+ gcvFEATURE_YUV420_SCALER,
+ gcvFEATURE_SHADER_HAS_W,
+ gcvFEATURE_SHADER_HAS_SIGN,
+ gcvFEATURE_SHADER_HAS_FLOOR,
+ gcvFEATURE_SHADER_HAS_CEIL,
+ gcvFEATURE_SHADER_HAS_SQRT,
+ gcvFEATURE_SHADER_HAS_TRIG,
+ gcvFEATURE_VAA,
+ gcvFEATURE_HZ,
+ gcvFEATURE_CORRECT_STENCIL,
+ gcvFEATURE_VG20,
+ gcvFEATURE_VG_FILTER,
+ gcvFEATURE_VG21,
+ gcvFEATURE_VG_DOUBLE_BUFFER,
+ gcvFEATURE_MC20,
+ gcvFEATURE_SUPER_TILED,
+ gcvFEATURE_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,
+ gcvFEATURE_FC_FLUSH_STALL,
+ gcvFEATURE_FULL_DIRECTFB,
+ gcvFEATURE_HALF_FLOAT_PIPE,
+ gcvFEATURE_LINE_LOOP,
+ gcvFEATURE_2D_YUV_BLIT,
+ gcvFEATURE_2D_TILING,
+ gcvFEATURE_NON_POWER_OF_TWO,
+ gcvFEATURE_3D_TEXTURE,
+ gcvFEATURE_TEXTURE_ARRAY,
+ gcvFEATURE_TILE_FILLER,
+ gcvFEATURE_LOGIC_OP,
+ gcvFEATURE_COMPOSITION,
+ gcvFEATURE_MIXED_STREAMS,
+ gcvFEATURE_2D_MULTI_SOURCE_BLT,
+ gcvFEATURE_END_EVENT,
+ gcvFEATURE_VERTEX_10_10_10_2,
+ gcvFEATURE_TEXTURE_10_10_10_2,
+ gcvFEATURE_TEXTURE_ANISOTROPIC_FILTERING,
+ gcvFEATURE_TEXTURE_FLOAT_HALF_FLOAT,
+ gcvFEATURE_2D_ROTATION_STALL_FIX,
+ gcvFEATURE_2D_MULTI_SOURCE_BLT_EX,
+ 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_INDEX_FETCH_FIX,
+ gcvFEATURE_TEXTURE_TILE_STATUS_READ,
+ gcvFEATURE_DEPTH_BIAS_FIX,
+ gcvFEATURE_RECT_PRIMITIVE,
+ gcvFEATURE_BUG_FIXES11,
+ gcvFEATURE_SUPERTILED_TEXTURE,
+ gcvFEATURE_2D_NO_COLORBRUSH_INDEX8,
+ gcvFEATURE_RS_YUV_TARGET,
+ gcvFEATURE_2D_FC_SOURCE,
+ 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_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_TEXTURE_ASTC_FIX,
+ gcvFEATURE_2D_SUPER_TILE_V1,
+ gcvFEATURE_2D_SUPER_TILE_V2,
+ gcvFEATURE_2D_SUPER_TILE_V3,
+ gcvFEATURE_2D_MULTI_SOURCE_BLT_EX2,
+ 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_DEC_COMPRESSION,
+ gcvFEATURE_DEC_TPC_COMPRESSION,
+ gcvFEATURE_DEC_COMPRESSION_TILE_NV12_8BIT,
+ gcvFEATURE_DEC_COMPRESSION_TILE_NV12_10BIT,
+ 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_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_SIGNEXT_FIX,
+ 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_FE_RESET_VERTEX_ID,
+ gcvFEATURE_RS_DEPTHSTENCIL_NATIVE_SUPPORT,
+
+ gcvFEATURE_HALTI4,
+ gcvFEATURE_MSAA_FRAGMENT_OPERATION,
+ gcvFEATURE_ZERO_ATTRIB_SUPPORT,
+ gcvFEATURE_TEX_CACHE_FLUSH_FIX,
+
+ /* 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
+{
+ gcvPOWER_ON = 0,
+ gcvPOWER_OFF,
+ gcvPOWER_IDLE,
+ gcvPOWER_SUSPEND,
+ gcvPOWER_SUSPEND_ATPOWERON,
+ gcvPOWER_OFF_ATPOWERON,
+ gcvPOWER_IDLE_BROADCAST,
+ gcvPOWER_SUSPEND_BROADCAST,
+ gcvPOWER_OFF_BROADCAST,
+ gcvPOWER_OFF_RECOVERY,
+ gcvPOWER_OFF_TIMEOUT,
+ gcvPOWER_ON_AUTO
+}
+gceCHIPPOWERSTATE;
+
+/* CPU cache operations */
+typedef enum _gceCACHEOPERATION
+{
+ gcvCACHE_CLEAN = 0x01,
+ gcvCACHE_INVALIDATE = 0x02,
+ gcvCACHE_FLUSH = gcvCACHE_CLEAN | gcvCACHE_INVALIDATE,
+ gcvCACHE_MEMORY_BARRIER = 0x04
+}
+gceCACHEOPERATION;
+
+/* Surface types. */
+typedef enum _gceSURF_TYPE
+{
+ gcvSURF_TYPE_UNKNOWN = 0,
+ gcvSURF_INDEX,
+ gcvSURF_VERTEX,
+ gcvSURF_TEXTURE,
+ gcvSURF_RENDER_TARGET,
+ gcvSURF_DEPTH,
+ gcvSURF_BITMAP,
+ gcvSURF_TILE_STATUS,
+ gcvSURF_IMAGE,
+ gcvSURF_MASK,
+ gcvSURF_SCISSOR,
+ gcvSURF_HIERARCHICAL_DEPTH,
+ gcvSURF_NUM_TYPES, /* Make sure this is the last one! */
+
+ /* Combinations. */
+ gcvSURF_NO_TILE_STATUS = 0x100,
+ gcvSURF_NO_VIDMEM = 0x200, /* Used to allocate surfaces with no underlying vidmem node.
+ In Android, vidmem node is allocated by another process. */
+ gcvSURF_CACHEABLE = 0x400, /* Used to allocate a cacheable surface */
+
+ gcvSURF_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_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,
+
+ gcvSURF_RENDER_TARGET_TS_DIRTY = gcvSURF_RENDER_TARGET
+ | gcvSURF_TILE_STATUS_DIRTY,
+
+ gcvSURF_DEPTH_NO_TILE_STATUS = gcvSURF_DEPTH
+ | gcvSURF_NO_TILE_STATUS,
+
+ gcvSURF_DEPTH_TS_DIRTY = gcvSURF_DEPTH
+ | gcvSURF_TILE_STATUS_DIRTY,
+
+ /* Supported surface types with no vidmem node. */
+ gcvSURF_BITMAP_NO_VIDMEM = gcvSURF_BITMAP
+ | gcvSURF_NO_VIDMEM,
+
+ gcvSURF_TEXTURE_NO_VIDMEM = gcvSURF_TEXTURE
+ | gcvSURF_NO_VIDMEM,
+
+ /* Cacheable surface types with no vidmem node. */
+ gcvSURF_CACHEABLE_BITMAP_NO_VIDMEM = gcvSURF_BITMAP_NO_VIDMEM
+ | gcvSURF_CACHEABLE,
+
+ gcvSURF_CACHEABLE_BITMAP = gcvSURF_BITMAP
+ | gcvSURF_CACHEABLE,
+
+ gcvSURF_FLIP_BITMAP = gcvSURF_BITMAP
+ | gcvSURF_FLIP,
+}
+gceSURF_TYPE;
+
+typedef enum _gceSURF_USAGE
+{
+ gcvSURF_USAGE_UNKNOWN,
+ gcvSURF_USAGE_RESOLVE_AFTER_CPU,
+ gcvSURF_USAGE_RESOLVE_AFTER_3D
+}
+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,
+ gcvSURF_COLOR_LINEAR = 0x01,
+ gcvSURF_COLOR_ALPHA_PRE = 0x02,
+}
+gceSURF_COLOR_TYPE;
+
+/* Rotation. */
+typedef enum _gceSURF_ROTATION
+{
+ gcvSURF_0_DEGREE = 0,
+ gcvSURF_90_DEGREE,
+ gcvSURF_180_DEGREE,
+ gcvSURF_270_DEGREE,
+ gcvSURF_FLIP_X,
+ gcvSURF_FLIP_Y,
+
+ 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),
+ /* surface has multiple nodes */
+ gcvSURF_FLAG_MULTI_NODE = (1 << 5),
+}
+gceSURF_FLAG;
+
+typedef enum _gceMIPMAP_IMAGE_FORMAT
+{
+ gcvUNKNOWN_MIPMAP_IMAGE_FORMAT = -2
+}
+gceMIPMAP_IMAGE_FORMAT;
+
+/* Surface formats. */
+typedef enum _gceSURF_FORMAT
+{
+ /* Unknown format. */
+ gcvSURF_UNKNOWN = 0,
+
+ /* Palettized formats. */
+ gcvSURF_INDEX1 = 100,
+ gcvSURF_INDEX4,
+ gcvSURF_INDEX8,
+
+ /* RGB formats. */
+ gcvSURF_A2R2G2B2 = 200,
+ gcvSURF_R3G3B2,
+ gcvSURF_A8R3G3B2,
+ gcvSURF_X4R4G4B4,
+ gcvSURF_A4R4G4B4,
+ gcvSURF_R4G4B4A4,
+ gcvSURF_X1R5G5B5,
+ gcvSURF_A1R5G5B5,
+ gcvSURF_R5G5B5A1,
+ gcvSURF_R5G6B5,
+ gcvSURF_R8G8B8,
+ gcvSURF_X8R8G8B8,
+ gcvSURF_A8R8G8B8,
+ gcvSURF_R8G8B8A8,
+ gcvSURF_G8R8G8B8,
+ gcvSURF_R8G8B8G8,
+ gcvSURF_X2R10G10B10,
+ gcvSURF_A2R10G10B10,
+ gcvSURF_X12R12G12B12,
+ gcvSURF_A12R12G12B12,
+ gcvSURF_X16R16G16B16,
+ gcvSURF_A16R16G16B16,
+ gcvSURF_A32R32G32B32,
+ gcvSURF_R8G8B8X8,
+ gcvSURF_R5G5B5X1,
+ gcvSURF_R4G4B4X4,
+ gcvSURF_X16R16G16B16_2_A8R8G8B8,
+ gcvSURF_A16R16G16B16_2_A8R8G8B8,
+ gcvSURF_A32R32G32B32_2_G32R32F,
+ gcvSURF_A32R32G32B32_4_A8R8G8B8,
+
+ /* BGR formats. */
+ gcvSURF_A4B4G4R4 = 300,
+ gcvSURF_A1B5G5R5,
+ gcvSURF_B5G6R5,
+ gcvSURF_B8G8R8,
+ gcvSURF_B16G16R16,
+ gcvSURF_X8B8G8R8,
+ gcvSURF_A8B8G8R8,
+ gcvSURF_A2B10G10R10,
+ gcvSURF_X16B16G16R16,
+ gcvSURF_A16B16G16R16,
+ gcvSURF_B32G32R32,
+ gcvSURF_X32B32G32R32,
+ gcvSURF_A32B32G32R32,
+ gcvSURF_B4G4R4A4,
+ gcvSURF_B5G5R5A1,
+ gcvSURF_B8G8R8X8,
+ gcvSURF_B8G8R8A8,
+ gcvSURF_X4B4G4R4,
+ gcvSURF_X1B5G5R5,
+ gcvSURF_B4G4R4X4,
+ gcvSURF_B5G5R5X1,
+ gcvSURF_X2B10G10R10,
+ gcvSURF_B8G8R8_SNORM,
+ gcvSURF_X8B8G8R8_SNORM,
+ gcvSURF_A8B8G8R8_SNORM,
+ gcvSURF_A8B12G12R12_2_A8R8G8B8,
+
+ /* Compressed formats. */
+ gcvSURF_DXT1 = 400,
+ gcvSURF_DXT2,
+ gcvSURF_DXT3,
+ gcvSURF_DXT4,
+ gcvSURF_DXT5,
+ gcvSURF_CXV8U8,
+ gcvSURF_ETC1,
+ gcvSURF_R11_EAC,
+ gcvSURF_SIGNED_R11_EAC,
+ gcvSURF_RG11_EAC,
+ gcvSURF_SIGNED_RG11_EAC,
+ gcvSURF_RGB8_ETC2,
+ gcvSURF_SRGB8_ETC2,
+ gcvSURF_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ gcvSURF_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ gcvSURF_RGBA8_ETC2_EAC,
+ gcvSURF_SRGB8_ALPHA8_ETC2_EAC,
+
+ /* YUV formats. */
+ gcvSURF_YUY2 = 500,
+ gcvSURF_UYVY,
+ gcvSURF_YV12,
+ gcvSURF_I420,
+ gcvSURF_NV12,
+ gcvSURF_NV21,
+ gcvSURF_NV16,
+ gcvSURF_NV61,
+ gcvSURF_YVYU,
+ gcvSURF_VYUY,
+
+ /* Depth formats. */
+ gcvSURF_D16 = 600,
+ gcvSURF_D24S8,
+ gcvSURF_D32,
+ gcvSURF_D24X8,
+ gcvSURF_D32F,
+ gcvSURF_S8D32F,
+ gcvSURF_S8D32F_1_G32R32F,
+ gcvSURF_S8D32F_2_A8R8G8B8,
+ gcvSURF_D24S8_1_A8R8G8B8,
+ gcvSURF_S8,
+
+ /* Alpha formats. */
+ gcvSURF_A4 = 700,
+ gcvSURF_A8,
+ gcvSURF_A12,
+ gcvSURF_A16,
+ gcvSURF_A32,
+ gcvSURF_A1,
+
+ /* Luminance formats. */
+ gcvSURF_L4 = 800,
+ gcvSURF_L8,
+ gcvSURF_L12,
+ gcvSURF_L16,
+ gcvSURF_L32,
+ gcvSURF_L1,
+
+ /* Alpha/Luminance formats. */
+ gcvSURF_A4L4 = 900,
+ gcvSURF_A2L6,
+ gcvSURF_A8L8,
+ gcvSURF_A4L12,
+ gcvSURF_A12L12,
+ gcvSURF_A16L16,
+
+ /* Bump formats. */
+ gcvSURF_L6V5U5 = 1000,
+ gcvSURF_V8U8,
+ gcvSURF_X8L8V8U8,
+ gcvSURF_Q8W8V8U8,
+ gcvSURF_A2W10V10U10,
+ gcvSURF_V16U16,
+ gcvSURF_Q16W16V16U16,
+
+ /* R/RG/RA formats. */
+ gcvSURF_R8 = 1100,
+ gcvSURF_X8R8,
+ gcvSURF_G8R8,
+ gcvSURF_X8G8R8,
+ gcvSURF_A8R8,
+ gcvSURF_R16,
+ gcvSURF_X16R16,
+ gcvSURF_G16R16,
+ gcvSURF_X16G16R16,
+ gcvSURF_A16R16,
+ gcvSURF_R32,
+ gcvSURF_X32R32,
+ gcvSURF_G32R32,
+ gcvSURF_X32G32R32,
+ gcvSURF_A32R32,
+ gcvSURF_RG16,
+ gcvSURF_R8_SNORM,
+ gcvSURF_G8R8_SNORM,
+
+ gcvSURF_R8_1_X8R8G8B8,
+ gcvSURF_G8R8_1_X8R8G8B8,
+
+ /* Floating point formats. */
+ gcvSURF_R16F = 1200,
+ gcvSURF_X16R16F,
+ gcvSURF_G16R16F,
+ gcvSURF_X16G16R16F,
+ gcvSURF_B16G16R16F,
+ gcvSURF_X16B16G16R16F,
+ gcvSURF_A16B16G16R16F,
+ gcvSURF_R32F,
+ gcvSURF_X32R32F,
+ gcvSURF_G32R32F,
+ gcvSURF_X32G32R32F,
+ gcvSURF_B32G32R32F,
+ gcvSURF_X32B32G32R32F,
+ gcvSURF_A32B32G32R32F,
+ gcvSURF_A16F,
+ gcvSURF_L16F,
+ gcvSURF_A16L16F,
+ gcvSURF_A16R16F,
+ gcvSURF_A32F,
+ gcvSURF_L32F,
+ gcvSURF_A32L32F,
+ gcvSURF_A32R32F,
+ 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;
+
+typedef enum _gceSURF_YUV_COLOR_SPACE
+{
+ gcvSURF_ITU_REC601,
+ gcvSURF_ITU_REC709,
+ gcvSURF_ITU_REC2020,
+}
+gceSURF_YUV_COLOR_SPACE;
+
+typedef enum _gceSURF_YUV_CHROMA_SITING
+{
+ gcvSURF_YUV_CHROMA_SITING_0,
+ gcvSURF_YUV_CHROMA_SITING_0_5,
+}
+gceSURF_YUV_CHROMA_SITING;
+
+typedef enum _gceSURF_YUV_SAMPLE_RANGE
+{
+ gcvSURF_YUV_FULL_RANGE,
+ gcvSURF_YUV_NARROW_RANGE,
+}
+gceSURF_YUV_SAMPLE_RANGE;
+
+/* Format modifiers. */
+typedef enum _gceSURF_FORMAT_MODE
+{
+ gcvSURF_FORMAT_OCL = 0x80000000
+}
+gceSURF_FORMAT_MODE;
+
+/* Pixel swizzle modes. */
+typedef enum _gceSURF_SWIZZLE
+{
+ gcvSURF_NOSWIZZLE = 0,
+ gcvSURF_ARGB,
+ gcvSURF_ABGR,
+ gcvSURF_RGBA,
+ gcvSURF_BGRA
+}
+gceSURF_SWIZZLE;
+
+/* Transparency modes. */
+typedef enum _gceSURF_TRANSPARENCY
+{
+ /* Valid only for PE 1.0 */
+ gcvSURF_OPAQUE = 0,
+ gcvSURF_SOURCE_MATCH,
+ gcvSURF_SOURCE_MASK,
+ gcvSURF_PATTERN_MASK,
+}
+gceSURF_TRANSPARENCY;
+
+/* Surface Alignment. */
+typedef enum _gceSURF_ALIGNMENT
+{
+ gcvSURF_FOUR = 0,
+ gcvSURF_SIXTEEN,
+ gcvSURF_SUPER_TILED,
+ gcvSURF_SPLIT_TILED,
+ gcvSURF_SPLIT_SUPER_TILED
+}
+gceSURF_ALIGNMENT;
+
+/* Surface Addressing. */
+typedef enum _gceSURF_ADDRESSING
+{
+ gcvSURF_NO_STRIDE_TILED = 0,
+ gcvSURF_NO_STRIDE_LINEAR,
+ gcvSURF_STRIDE_TILED,
+ gcvSURF_STRIDE_LINEAR
+}
+gceSURF_ADDRESSING;
+
+/* Transparency modes. */
+typedef enum _gce2D_TRANSPARENCY
+{
+ /* Valid only for PE 2.0 */
+ gcv2D_OPAQUE = 0,
+ gcv2D_KEYED,
+ gcv2D_MASKED
+}
+gce2D_TRANSPARENCY;
+
+/* Mono packing modes. */
+typedef enum _gceSURF_MONOPACK
+{
+ gcvSURF_PACKED8 = 0,
+ gcvSURF_PACKED16,
+ gcvSURF_PACKED32,
+ gcvSURF_UNPACKED,
+}
+gceSURF_MONOPACK;
+
+/* Blending modes. */
+typedef enum _gceSURF_BLEND_MODE
+{
+ /* Porter-Duff blending modes. */
+ /* Fsrc Fdst */
+ gcvBLEND_CLEAR = 0, /* 0 0 */
+ gcvBLEND_SRC, /* 1 0 */
+ gcvBLEND_DST, /* 0 1 */
+ gcvBLEND_SRC_OVER_DST, /* 1 1 - Asrc */
+ gcvBLEND_DST_OVER_SRC, /* 1 - Adst 1 */
+ gcvBLEND_SRC_IN_DST, /* Adst 0 */
+ gcvBLEND_DST_IN_SRC, /* 0 Asrc */
+ gcvBLEND_SRC_OUT_DST, /* 1 - Adst 0 */
+ gcvBLEND_DST_OUT_SRC, /* 0 1 - Asrc */
+ gcvBLEND_SRC_ATOP_DST, /* Adst 1 - Asrc */
+ gcvBLEND_DST_ATOP_SRC, /* 1 - Adst Asrc */
+ gcvBLEND_SRC_XOR_DST, /* 1 - Adst 1 - Asrc */
+
+ /* Special blending modes. */
+ gcvBLEND_SET, /* DST = 1 */
+ gcvBLEND_SUB /* DST = DST * (1 - SRC) */
+}
+gceSURF_BLEND_MODE;
+
+/* Per-pixel alpha modes. */
+typedef enum _gceSURF_PIXEL_ALPHA_MODE
+{
+ gcvSURF_PIXEL_ALPHA_STRAIGHT = 0,
+ gcvSURF_PIXEL_ALPHA_INVERSED
+}
+gceSURF_PIXEL_ALPHA_MODE;
+
+/* Global alpha modes. */
+typedef enum _gceSURF_GLOBAL_ALPHA_MODE
+{
+ gcvSURF_GLOBAL_ALPHA_OFF = 0,
+ gcvSURF_GLOBAL_ALPHA_ON,
+ gcvSURF_GLOBAL_ALPHA_SCALE
+}
+gceSURF_GLOBAL_ALPHA_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gceSURF_PIXEL_COLOR_MODE
+{
+ gcvSURF_COLOR_STRAIGHT = 0,
+ gcvSURF_COLOR_MULTIPLY
+}
+gceSURF_PIXEL_COLOR_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gce2D_PIXEL_COLOR_MULTIPLY_MODE
+{
+ gcv2D_COLOR_MULTIPLY_DISABLE = 0,
+ gcv2D_COLOR_MULTIPLY_ENABLE
+}
+gce2D_PIXEL_COLOR_MULTIPLY_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gce2D_GLOBAL_COLOR_MULTIPLY_MODE
+{
+ gcv2D_GLOBAL_COLOR_MULTIPLY_DISABLE = 0,
+ gcv2D_GLOBAL_COLOR_MULTIPLY_ALPHA,
+ gcv2D_GLOBAL_COLOR_MULTIPLY_COLOR
+}
+gce2D_GLOBAL_COLOR_MULTIPLY_MODE;
+
+/* Alpha blending factor modes. */
+typedef enum _gceSURF_BLEND_FACTOR_MODE
+{
+ gcvSURF_BLEND_ZERO = 0,
+ gcvSURF_BLEND_ONE,
+ gcvSURF_BLEND_STRAIGHT,
+ gcvSURF_BLEND_INVERSED,
+ gcvSURF_BLEND_COLOR,
+ gcvSURF_BLEND_COLOR_INVERSED,
+ gcvSURF_BLEND_SRC_ALPHA_SATURATED,
+ gcvSURF_BLEND_STRAIGHT_NO_CROSS,
+ gcvSURF_BLEND_INVERSED_NO_CROSS,
+ gcvSURF_BLEND_COLOR_NO_CROSS,
+ gcvSURF_BLEND_COLOR_INVERSED_NO_CROSS,
+ gcvSURF_BLEND_SRC_ALPHA_SATURATED_CROSS
+}
+gceSURF_BLEND_FACTOR_MODE;
+
+/* Alpha blending porter duff rules. */
+typedef enum _gce2D_PORTER_DUFF_RULE
+{
+ gcvPD_CLEAR = 0,
+ gcvPD_SRC,
+ gcvPD_SRC_OVER,
+ gcvPD_DST_OVER,
+ gcvPD_SRC_IN,
+ gcvPD_DST_IN,
+ gcvPD_SRC_OUT,
+ gcvPD_DST_OUT,
+ gcvPD_SRC_ATOP,
+ gcvPD_DST_ATOP,
+ gcvPD_ADD,
+ gcvPD_XOR,
+ gcvPD_DST
+}
+gce2D_PORTER_DUFF_RULE;
+
+/* Alpha blending factor modes. */
+typedef enum _gce2D_YUV_COLOR_MODE
+{
+ gcv2D_YUV_601= 0,
+ gcv2D_YUV_709,
+ gcv2D_YUV_USER_DEFINED,
+ gcv2D_YUV_USER_DEFINED_CLAMP,
+
+ /* Default setting is for src. gcv2D_YUV_DST
+ can be ORed to set dst.
+ */
+ gcv2D_YUV_DST = 0x80000000,
+}
+gce2D_YUV_COLOR_MODE;
+
+typedef enum _gce2D_COMMAND
+{
+ gcv2D_CLEAR = 0,
+ gcv2D_LINE,
+ gcv2D_BLT,
+ gcv2D_STRETCH,
+ gcv2D_HOR_FILTER,
+ gcv2D_VER_FILTER,
+ gcv2D_MULTI_SOURCE_BLT,
+ gcv2D_FILTER_BLT,
+}
+gce2D_COMMAND;
+
+typedef enum _gce2D_TILE_STATUS_CONFIG
+{
+ gcv2D_TSC_DISABLE = 0,
+ gcv2D_TSC_ENABLE = 0x00000001,
+ gcv2D_TSC_COMPRESSED = 0x00000002,
+ gcv2D_TSC_DOWN_SAMPLER = 0x00000004,
+ gcv2D_TSC_2D_COMPRESSED = 0x00000008,
+ gcv2D_TSC_TPC_COMPRESSED = 0x00000010,
+
+ gcv2D_TSC_DEC_COMPRESSED = 0x00000020,
+ gcv2D_TSC_DEC_TPC = 0x00000040,
+ gcv2D_TSC_DEC_TPC_COMPRESSED = 0x00000080,
+
+ gcv2D_TSC_DEC_TPC_TILED = gcv2D_TSC_DEC_COMPRESSED | gcv2D_TSC_DEC_TPC,
+ gcv2D_TSC_DEC_TPC_TILED_COMPRESSED = gcv2D_TSC_DEC_TPC_TILED | gcv2D_TSC_DEC_TPC_COMPRESSED,
+}
+gce2D_TILE_STATUS_CONFIG;
+
+typedef enum _gce2D_QUERY
+{
+ gcv2D_QUERY_RGB_ADDRESS_MIN_ALIGN = 0,
+ gcv2D_QUERY_RGB_STRIDE_MIN_ALIGN,
+ gcv2D_QUERY_YUV_ADDRESS_MIN_ALIGN,
+ gcv2D_QUERY_YUV_STRIDE_MIN_ALIGN,
+}
+gce2D_QUERY;
+
+typedef enum _gce2D_SUPER_TILE_VERSION
+{
+ gcv2D_SUPER_TILE_VERSION_V1 = 1,
+ gcv2D_SUPER_TILE_VERSION_V2 = 2,
+ gcv2D_SUPER_TILE_VERSION_V3 = 3,
+}
+gce2D_SUPER_TILE_VERSION;
+
+typedef enum _gce2D_STATE
+{
+ gcv2D_STATE_SPECIAL_FILTER_MIRROR_MODE = 1,
+ gcv2D_STATE_SUPER_TILE_VERSION,
+ 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,
+ gcv2D_STATE_ARRAY_CSC_YUV_TO_RGB,
+ gcv2D_STATE_ARRAY_CSC_RGB_TO_YUV,
+
+ gcv2D_STATE_DEC_TPC_NV12_10BIT = 0x20001,
+ gcv2D_STATE_ARRAY_YUV_SRC_TILE_STATUS_ADDR,
+ gcv2D_STATE_ARRAY_YUV_DST_TILE_STATUS_ADDR,
+}
+gce2D_STATE;
+
+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
+{
+ gcvTEXTURE_DUMMY = 0,
+ gcvTEXTURE_REPLACE = 0,
+ gcvTEXTURE_MODULATE,
+ gcvTEXTURE_ADD,
+ gcvTEXTURE_ADD_SIGNED,
+ gcvTEXTURE_INTERPOLATE,
+ gcvTEXTURE_SUBTRACT,
+ gcvTEXTURE_DOT3
+}
+gceTEXTURE_FUNCTION;
+
+/* Texture sources. */
+typedef enum _gceTEXTURE_SOURCE
+{
+ gcvCOLOR_FROM_TEXTURE = 0,
+ gcvCOLOR_FROM_CONSTANT_COLOR,
+ gcvCOLOR_FROM_PRIMARY_COLOR,
+ gcvCOLOR_FROM_PREVIOUS_COLOR
+}
+gceTEXTURE_SOURCE;
+
+/* Texture source channels. */
+typedef enum _gceTEXTURE_CHANNEL
+{
+ gcvFROM_COLOR = 0,
+ gcvFROM_ONE_MINUS_COLOR,
+ gcvFROM_ALPHA,
+ gcvFROM_ONE_MINUS_ALPHA
+}
+gceTEXTURE_CHANNEL;
+#endif /* gcdENABLE_3D */
+
+/* Filter types. */
+typedef enum _gceFILTER_TYPE
+{
+ gcvFILTER_SYNC = 0,
+ gcvFILTER_BLUR,
+ gcvFILTER_USER
+}
+gceFILTER_TYPE;
+
+/* Filter pass types. */
+typedef enum _gceFILTER_PASS_TYPE
+{
+ gcvFILTER_HOR_PASS = 0,
+ gcvFILTER_VER_PASS
+}
+gceFILTER_PASS_TYPE;
+
+/* Endian hints. */
+typedef enum _gceENDIAN_HINT
+{
+ gcvENDIAN_NO_SWAP = 0,
+ gcvENDIAN_SWAP_WORD,
+ gcvENDIAN_SWAP_DWORD
+}
+gceENDIAN_HINT;
+
+/* Tiling modes. */
+typedef enum _gceTILING
+{
+ 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;
+
+/* 2D pattern type. */
+typedef enum _gce2D_PATTERN
+{
+ gcv2D_PATTERN_SOLID = 0,
+ gcv2D_PATTERN_MONO,
+ gcv2D_PATTERN_COLOR,
+ gcv2D_PATTERN_INVALID
+}
+gce2D_PATTERN;
+
+/* 2D source type. */
+typedef enum _gce2D_SOURCE
+{
+ gcv2D_SOURCE_MASKED = 0,
+ gcv2D_SOURCE_MONO,
+ gcv2D_SOURCE_COLOR,
+ gcv2D_SOURCE_INVALID
+}
+gce2D_SOURCE;
+
+/* Pipes. */
+typedef enum _gcePIPE_SELECT
+{
+ gcvPIPE_INVALID = ~0,
+ gcvPIPE_3D = 0,
+ gcvPIPE_2D
+}
+gcePIPE_SELECT;
+
+/* Hardware type. */
+typedef enum _gceHARDWARE_TYPE
+{
+ gcvHARDWARE_INVALID = 0x00,
+ gcvHARDWARE_3D = 0x01,
+ gcvHARDWARE_2D = 0x02,
+ gcvHARDWARE_VG = 0x04,
+#if gcdMULTI_GPU_AFFINITY
+ gcvHARDWARE_OCL = 0x05,
+#endif
+ gcvHARDWARE_3D2D = gcvHARDWARE_3D | gcvHARDWARE_2D,
+}
+gceHARDWARE_TYPE;
+
+#define gcdCHIP_COUNT 3
+
+typedef enum _gceMMU_MODE
+{
+ gcvMMU_MODE_1K,
+ gcvMMU_MODE_4K,
+} gceMMU_MODE;
+
+/* User signal command codes. */
+typedef enum _gceUSER_SIGNAL_COMMAND_CODES
+{
+ gcvUSER_SIGNAL_CREATE,
+ gcvUSER_SIGNAL_DESTROY,
+ gcvUSER_SIGNAL_SIGNAL,
+ gcvUSER_SIGNAL_WAIT,
+ gcvUSER_SIGNAL_MAP,
+ gcvUSER_SIGNAL_UNMAP,
+}
+gceUSER_SIGNAL_COMMAND_CODES;
+
+/* Sync point command codes. */
+typedef enum _gceSYNC_POINT_COMMAND_CODES
+{
+ gcvSYNC_POINT_CREATE,
+ gcvSYNC_POINT_DESTROY,
+ gcvSYNC_POINT_SIGNAL,
+}
+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
+{
+ gcvKERNEL_COMMAND,
+ gcvKERNEL_VERTEX,
+ gcvKERNEL_TRIANGLE,
+ gcvKERNEL_TEXTURE,
+ gcvKERNEL_PIXEL,
+}
+gceKERNEL_WHERE;
+
+#if gcdENABLE_VG
+/* Hardware blocks. */
+typedef enum _gceBLOCK
+{
+ gcvBLOCK_COMMAND,
+ gcvBLOCK_TESSELLATOR,
+ gcvBLOCK_TESSELLATOR2,
+ gcvBLOCK_TESSELLATOR3,
+ gcvBLOCK_RASTER,
+ gcvBLOCK_VG,
+ gcvBLOCK_VG2,
+ gcvBLOCK_VG3,
+ gcvBLOCK_PIXEL,
+
+ /* Number of defined blocks. */
+ gcvBLOCK_COUNT
+}
+gceBLOCK;
+#endif
+
+/* gcdDUMP message type. */
+typedef enum _gceDEBUG_MESSAGE_TYPE
+{
+ gcvMESSAGE_TEXT,
+ gcvMESSAGE_DUMP
+}
+gceDEBUG_MESSAGE_TYPE;
+
+/* 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_INVALID = 0,
+ gcvCOMPARE_NEVER,
+ gcvCOMPARE_NOT_EQUAL,
+ gcvCOMPARE_LESS,
+ gcvCOMPARE_LESS_OR_EQUAL,
+ gcvCOMPARE_EQUAL,
+ gcvCOMPARE_GREATER,
+ gcvCOMPARE_GREATER_OR_EQUAL,
+ gcvCOMPARE_ALWAYS,
+}
+gceCOMPARE;
+
+/* Stencil modes. */
+typedef enum _gceSTENCIL_MODE
+{
+ gcvSTENCIL_NONE,
+ gcvSTENCIL_SINGLE_SIDED,
+ gcvSTENCIL_DOUBLE_SIDED,
+}
+gceSTENCIL_MODE;
+
+/* Stencil operations. */
+typedef enum _gceSTENCIL_OPERATION
+{
+ gcvSTENCIL_KEEP,
+ gcvSTENCIL_REPLACE,
+ gcvSTENCIL_ZERO,
+ gcvSTENCIL_INVERT,
+ gcvSTENCIL_INCREMENT,
+ gcvSTENCIL_DECREMENT,
+ gcvSTENCIL_INCREMENT_SATURATE,
+ gcvSTENCIL_DECREMENT_SATURATE,
+ 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;
+
+/* 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,
+
+ 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;
+
+
+typedef enum _gceCMDBUF_TYPE
+{
+ /* Contiguous command buffer. */
+ gcvCMDBUF_CONTIGUOUS,
+ /* Virtual command buffer. */
+ gcvCMDBUF_VIRTUAL,
+ /* Command buffer allocated from reserved memory. */
+ gcvCMDBUF_RESERVED,
+}
+gceCMDBUF_SOURCE;
+
+typedef enum _gceCHIP_FALG
+{
+ gcvCHIP_FLAG_MSAA_COHERENCEY_ECO_FIX = 1 << 0,
+ gcvCHIP_FLAG_GC2000_R2 = 1 << 1,
+}
+gceCHIP_FLAG;
+
+/*
+* 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
+#define gcvALLOC_FLAG_DMABUF_BIT 5
+#define gcvALLOC_FLAG_USERMEMORY_BIT 6
+
+/* 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)
+
+/* Import DMABUF. */
+#define gcvALLOC_FLAG_DMABUF (1 << gcvALLOC_FLAG_DMABUF_BIT)
+/* Import USERMEMORY. */
+#define gcvALLOC_FLAG_USERMEMORY (1 << gcvALLOC_FLAG_USERMEMORY_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 *****************************
+\******************************************************************************/
+
+typedef struct _gckCONTEXT * gckCONTEXT;
+typedef struct _gcoCMDBUF * gcoCMDBUF;
+
+typedef struct _gcsSTATE_DELTA * gcsSTATE_DELTA_PTR;
+typedef struct _gcsQUEUE * gcsQUEUE_PTR;
+typedef struct _gcoQUEUE * gcoQUEUE;
+typedef struct _gcsHAL_INTERFACE * gcsHAL_INTERFACE_PTR;
+typedef struct _gcs2D_PROFILE * gcs2D_PROFILE_PTR;
+
+#if gcdENABLE_VG
+typedef struct _gcoVGHARDWARE * gcoVGHARDWARE;
+typedef struct _gcoVGBUFFER * gcoVGBUFFER;
+typedef struct _gckVGHARDWARE * gckVGHARDWARE;
+typedef struct _gcsVGCONTEXT * gcsVGCONTEXT_PTR;
+typedef struct _gcsVGCONTEXT_MAP * gcsVGCONTEXT_MAP_PTR;
+typedef struct _gcsVGCMDQUEUE * gcsVGCMDQUEUE_PTR;
+typedef struct _gcsTASK_MASTER_TABLE * gcsTASK_MASTER_TABLE_PTR;
+typedef struct _gckVGKERNEL * gckVGKERNEL;
+typedef void * gctTHREAD;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_enum_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h
new file mode 100644
index 000000000000..8b71fc13e5cd
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h
@@ -0,0 +1,259 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_buffer_h_
+#define __gc_hal_kernel_buffer_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+************************ Command Buffer and Event Objects **********************
+\******************************************************************************/
+
+/* The number of context buffers per user. */
+#define gcdCONTEXT_BUFFER_COUNT 2
+
+/* State delta record. */
+typedef struct _gcsSTATE_DELTA_RECORD * gcsSTATE_DELTA_RECORD_PTR;
+typedef struct _gcsSTATE_DELTA_RECORD
+{
+ /* State address. */
+ gctUINT address;
+
+ /* State mask. */
+ gctUINT32 mask;
+
+ /* State data. */
+ gctUINT32 data;
+}
+gcsSTATE_DELTA_RECORD;
+
+/* State delta. */
+typedef struct _gcsSTATE_DELTA
+{
+ /* For debugging: the number of delta in the order of creation. */
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ gctUINT num;
+#endif
+
+ /* Main state delta ID. Every time state delta structure gets reinitialized,
+ main ID is incremented. If main state ID overflows, all map entry IDs get
+ reinitialized to make sure there is no potential erroneous match after
+ the overflow.*/
+ gctUINT id;
+
+ /* The number of contexts pending modification by the delta. */
+ gctINT refCount;
+
+ /* Vertex element count for the delta buffer. */
+ gctUINT elementCount;
+
+ /* Number of states currently stored in the record array. */
+ gctUINT recordCount;
+
+ /* Record array; holds all modified states in gcsSTATE_DELTA_RECORD. */
+ gctUINT64 recordArray;
+
+ /* Map entry ID is used for map entry validation. If map entry ID does not
+ match the main state delta ID, the entry and the corresponding state are
+ considered not in use. */
+ gctUINT64 mapEntryID;
+ gctUINT mapEntryIDSize;
+
+ /* If the map entry ID matches the main state delta ID, index points to
+ the state record in the record array. */
+ gctUINT64 mapEntryIndex;
+
+ /* Previous and next state deltas in gcsSTATE_DELTA. */
+ gctUINT64 prev;
+ gctUINT64 next;
+}
+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. */
+ gctUINT64 commitCount;
+
+ /* Command buffer entry and exit pipes. */
+ gcePIPE_SELECT entryPipe;
+ gcePIPE_SELECT exitPipe;
+
+ /* Feature usage flags. */
+ gctBOOL using2D;
+ gctBOOL using3D;
+ gctBOOL usingFilterBlit;
+ gctBOOL usingPalette;
+
+ /* Physical address of command buffer. Just a name. */
+ gctUINT32 physical;
+
+ /* Logical address of command buffer. */
+ gctUINT64 logical;
+
+ /* Number of bytes in command buffer. */
+ gctUINT32 bytes;
+
+ /* Start offset into the command buffer. */
+ gctUINT32 startOffset;
+
+ /* Current offset into the command buffer. */
+ gctUINT32 offset;
+
+ /* Number of free bytes in command buffer. */
+ gctUINT32 free;
+
+ /* Location of the last reserved area. */
+ gctUINT64 lastReserve;
+ gctUINT32 lastOffset;
+
+#if gcdSECURE_USER
+ /* Hint array for the current command buffer. */
+ gctUINT hintArraySize;
+ gctUINT64 hintArray;
+ gctUINT64 hintArrayTail;
+#endif
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Last load state command location and hardware address. */
+ gctUINT64 lastLoadStatePtr;
+ 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
+{
+ /* Pointer to next gcsQUEUE structure in gcsQUEUE. */
+ gctUINT64 next;
+
+ /* Event information. */
+ gcsHAL_INTERFACE iface;
+}
+gcsQUEUE;
+
+/* Event queue. */
+struct _gcoQUEUE
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to current event queue. */
+ gcsQUEUE_PTR head;
+ gcsQUEUE_PTR tail;
+
+ /* chunks of the records. */
+ gctPOINTER chunks;
+
+ /* List of free records. */
+ gcsQUEUE_PTR freeList;
+
+ #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
+
+#endif /* __gc_hal_kernel_buffer_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h
new file mode 100644
index 000000000000..ec6d0f3bf501
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h
@@ -0,0 +1,564 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+/*
+** Include file for the local memory management.
+*/
+
+#ifndef __gc_hal_mem_h_
+#define __gc_hal_mem_h_
+#if (gcdENABLE_3D || gcdENABLE_VG)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+** Usage:
+
+ The macros to declare MemPool type and functions are
+ gcmMEM_DeclareFSMemPool (Type, TypeName, Prefix)
+ gcmMEM_DeclareVSMemPool (Type, TypeName, Prefix)
+ gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix)
+
+ The data structures for MemPool are
+ typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
+ typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
+ typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
+
+ The MemPool constructor and destructor functions are
+ gcfMEM_InitFSMemPool(gcsMEM_FS_MEM_POOL *, gcoOS, gctUINT, gctUINT);
+ gcfMEM_FreeFSMemPool(gcsMEM_FS_MEM_POOL *);
+ gcfMEM_InitVSMemPool(gcsMEM_VS_MEM_POOL *, gcoOS, gctUINT, gctBOOL);
+ gcfMEM_FreeVSMemPool(gcsMEM_VS_MEM_POOL *);
+ gcfMEM_InitAFSMemPool(gcsMEM_AFS_MEM_POOL *, gcoOS, gctUINT);
+ gcfMEM_FreeAFSMemPool(gcsMEM_AFS_MEM_POOL *);
+
+ FS: for Fixed-Size data structures
+ VS: for Variable-size data structures
+ AFS: for Array of Fixed-Size data structures
+
+
+ // Example 1: For a fixed-size data structure, struct gcsNode.
+ // It is used locally in a file, so the functions are static without prefix.
+ // At top level, declear allocate and free functions.
+ // The first argument is the data type.
+ // The second armument is the short name used in the fuctions.
+ gcmMEM_DeclareFSMemPool(struct gcsNode, Node, );
+
+ // The previous macro creates two inline functions,
+ // _AllocateNode and _FreeNode.
+
+ // In function or struct
+ gcsMEM_FS_MEM_POOL nodeMemPool;
+
+ // In function,
+ struct gcsNode * node;
+ gceSTATUS status;
+
+ // Before using the memory pool, initialize it.
+ // The second argument is the gcoOS object.
+ // The third argument is the number of data structures to allocate for each chunk.
+ status = gcfMEM_InitFSMemPool(&nodeMemPool, os, 100, sizeof(struct gcsNode));
+ ...
+
+ // Allocate a node.
+ status = _AllocateNode(nodeMemPool, &node);
+ ...
+ // Free a node.
+ _FreeNode(nodeMemPool, node);
+
+ // After using the memory pool, free it.
+ gcfMEM_FreeFSMemPool(&nodeMemPool);
+
+
+ // Example 2: For array of fixed-size data structures, struct gcsNode.
+ // It is used in several files, so the functions are extern with prefix.
+ // At top level, declear allocate and free functions.
+ // The first argument is the data type, and the second one is the short name
+ // used in the fuctions.
+ gcmMEM_DeclareAFSMemPool(struct gcsNode, NodeArray, gcfOpt);
+
+ // The previous macro creates two inline functions,
+ // gcfOpt_AllocateNodeArray and gcfOpt_FreeNodeArray.
+
+ // In function or struct
+ gcsMEM_AFS_MEM_POOL nodeArrayMemPool;
+
+ // In function,
+ struct gcsNode * nodeArray;
+ gceSTATUS status;
+
+ // Before using the array memory pool, initialize it.
+ // The second argument is the gcoOS object, the third is the number of data
+ // structures to allocate for each chunk.
+ status = gcfMEM_InitAFSMemPool(&nodeArrayMemPool, os, sizeof(struct gcsNode));
+ ...
+
+ // Allocate a node array of size 100.
+ status = gcfOpt_AllocateNodeArray(nodeArrayMemPool, &nodeArray, 100);
+ ...
+ // Free a node array.
+ gcfOpt_FreeNodeArray(&nodeArrayMemPool, nodeArray);
+
+ // After using the array memory pool, free it.
+ gcfMEM_FreeAFSMemPool(&nodeArrayMemPool);
+
+*******************************************************************************/
+
+/*******************************************************************************
+** To switch back to use gcoOS_Allocate and gcoOS_Free, add
+** #define USE_LOCAL_MEMORY_POOL 0
+** before including this file.
+*******************************************************************************/
+#ifndef USE_LOCAL_MEMORY_POOL
+/*
+ USE_LOCAL_MEMORY_POOL
+
+ This define enables the local memory management to improve performance.
+*/
+#define USE_LOCAL_MEMORY_POOL 1
+#endif
+
+/*******************************************************************************
+** Memory Pool Data Structures
+*******************************************************************************/
+#if USE_LOCAL_MEMORY_POOL
+ typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
+ typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
+ typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
+#else
+ typedef gcoOS gcsMEM_FS_MEM_POOL;
+ typedef gcoOS gcsMEM_VS_MEM_POOL;
+ typedef gcoOS gcsMEM_AFS_MEM_POOL;
+#endif
+
+/*******************************************************************************
+** Memory Pool Macros
+*******************************************************************************/
+#if USE_LOCAL_MEMORY_POOL
+#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ return(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ gcmERR_RETURN(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+ gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
+ gcmFOOTER(); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ status = gcfMEM_FSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName##List( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * FirstPointer, \
+ Type * LastPointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x FirstPointer=0x%x LastPointer=0x%x", MemPool, FirstPointer, LastPointer); \
+ status = gcfMEM_FSMemPoolFreeAList(MemPool, (gctPOINTER) FirstPointer, (gctPOINTER) LastPointer); \
+ gcmFOOTER(); \
+ return status; \
+}
+
+#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ gceSTATUS status;\
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
+ status = gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+} \
+ \
+gceSTATUS \
+ Prefix##_CAllocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
+ gcmERR_RETURN(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
+ gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, size); \
+ gcmFOOTER(); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pinter); \
+ status = gcfMEM_VSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+}
+
+#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
+ status = gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
+ gcmERR_RETURN(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
+ gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
+ gcmFOOTER(); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ status = gcfMEM_AFSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+}
+
+#else
+
+#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ status = gcoOS_Allocate(MemPool, \
+ gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+ gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer)); \
+ gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
+ gcmFOOTER(); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ status = gcmOS_SAFE_FREE(MemPool, Pointer); \
+ gcmFOOTER(); \
+ return status; \
+}
+
+#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_VS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
+ status = gcoOS_Allocate(MemPool, \
+ Size, \
+ (gctPOINTER *) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_VS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
+ gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+ Size, \
+ (gctPOINTER *) Pointer)); \
+ gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Size); \
+ gcmFOOTER(); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_VS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ status = gcmOS_SAFE_FREE(MemPool, Pointer); \
+ gcmFOOTER(); \
+ return status; \
+}
+
+#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
+ status = gcoOS_Allocate(MemPool, \
+ Count * gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
+ gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+ Count * gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer)); \
+ gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
+ gcmFOOTER(); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ status = gcmOS_SAFE_FREE(MemPool, Pointer); \
+ gcmFOOTER(); \
+ return status; \
+}
+#endif
+
+/*******************************************************************************
+** Memory Pool Data Functions
+*******************************************************************************/
+gceSTATUS
+gcfMEM_InitFSMemPool(
+ IN gcsMEM_FS_MEM_POOL * MemPool,
+ IN gcoOS OS,
+ IN gctUINT NodeCount,
+ IN gctUINT NodeSize
+ );
+
+gceSTATUS
+gcfMEM_FreeFSMemPool(
+ IN gcsMEM_FS_MEM_POOL * MemPool
+ );
+
+gceSTATUS
+gcfMEM_FSMemPoolGetANode(
+ IN gcsMEM_FS_MEM_POOL MemPool,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcfMEM_FSMemPoolFreeANode(
+ IN gcsMEM_FS_MEM_POOL MemPool,
+ IN gctPOINTER Node
+ );
+
+gceSTATUS
+gcfMEM_FSMemPoolFreeAList(
+ IN gcsMEM_FS_MEM_POOL MemPool,
+ IN gctPOINTER FirstNode,
+ IN gctPOINTER LastNode
+ );
+
+gceSTATUS
+gcfMEM_InitVSMemPool(
+ IN gcsMEM_VS_MEM_POOL * MemPool,
+ IN gcoOS OS,
+ IN gctUINT BlockSize,
+ IN gctBOOL RecycleFreeNode
+ );
+
+gceSTATUS
+gcfMEM_FreeVSMemPool(
+ IN gcsMEM_VS_MEM_POOL * MemPool
+ );
+
+gceSTATUS
+gcfMEM_VSMemPoolGetANode(
+ IN gcsMEM_VS_MEM_POOL MemPool,
+ IN gctUINT Size,
+ IN gctUINT Alignment,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcfMEM_VSMemPoolFreeANode(
+ IN gcsMEM_VS_MEM_POOL MemPool,
+ IN gctPOINTER Node
+ );
+
+gceSTATUS
+gcfMEM_InitAFSMemPool(
+ IN gcsMEM_AFS_MEM_POOL *MemPool,
+ IN gcoOS OS,
+ IN gctUINT NodeCount,
+ IN gctUINT NodeSize
+ );
+
+gceSTATUS
+gcfMEM_FreeAFSMemPool(
+ IN gcsMEM_AFS_MEM_POOL *MemPool
+ );
+
+gceSTATUS
+gcfMEM_AFSMemPoolGetANode(
+ IN gcsMEM_AFS_MEM_POOL MemPool,
+ IN gctUINT Count,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcfMEM_AFSMemPoolFreeANode(
+ IN gcsMEM_AFS_MEM_POOL MemPool,
+ IN gctPOINTER Node
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* (gcdENABLE_3D || gcdENABLE_VG) */
+#endif /* __gc_hal_mem_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
new file mode 100644
index 000000000000..a653d7d7042f
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
@@ -0,0 +1,1326 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_options_h_
+#define __gc_hal_options_h_
+
+/*
+ gcdSECURITY
+
+*/
+#ifndef gcdSECURITY
+# define gcdSECURITY 0
+#endif
+
+/*
+ gcdPRINT_VERSION
+
+ Print HAL version.
+*/
+#ifndef gcdPRINT_VERSION
+# define gcdPRINT_VERSION 0
+#endif
+
+/*
+ USE_NEW_LINUX_SIGNAL
+
+ This define enables the Linux kernel signaling between kernel and user.
+*/
+#ifndef USE_NEW_LINUX_SIGNAL
+# define USE_NEW_LINUX_SIGNAL 0
+#endif
+
+/*
+ VIVANTE_PROFILER
+
+ This define enables the profiler.
+*/
+#ifndef VIVANTE_PROFILER
+# define VIVANTE_PROFILER 1
+#endif
+
+/*
+ VIVANTE_PROFILER_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
+
+ Enable VG HAL layer (only for GC350).
+*/
+#ifndef gcdUSE_VG
+# define gcdUSE_VG 0
+#endif
+
+/*
+ USE_SW_FB
+
+ Set to 1 if the frame buffer memory cannot be accessed by the GPU.
+*/
+#ifndef USE_SW_FB
+# define USE_SW_FB 0
+#endif
+
+/*
+ PROFILE_HAL_COUNTERS
+
+ This define enables HAL counter profiling support. HW and SHADER
+ counter profiling depends on this.
+*/
+#ifndef PROFILE_HAL_COUNTERS
+# define PROFILE_HAL_COUNTERS 1
+#endif
+
+/*
+ PROFILE_HW_COUNTERS
+
+ This define enables HW counter profiling support.
+*/
+#ifndef PROFILE_HW_COUNTERS
+# define PROFILE_HW_COUNTERS 1
+#endif
+
+/*
+ PROFILE_SHADER_COUNTERS
+
+ This define enables SHADER counter profiling support.
+*/
+#ifndef PROFILE_SHADER_COUNTERS
+# define PROFILE_SHADER_COUNTERS 1
+#endif
+
+/*
+ COMMAND_PROCESSOR_VERSION
+
+ The version of the command buffer and task manager.
+*/
+#define COMMAND_PROCESSOR_VERSION 1
+
+/*
+ gcdDUMP_KEY
+
+ Set this to a string that appears in 'cat /proc/<pid>/cmdline'. E.g. 'camera'.
+ HAL will create dumps for the processes matching this key.
+*/
+#ifndef gcdDUMP_KEY
+# define gcdDUMP_KEY "process"
+#endif
+
+/*
+ gcdDUMP_PATH
+
+ The dump file location. Some processes cannot write to the sdcard.
+ Try apps' data dir, e.g. /data/data/com.android.launcher
+*/
+#ifndef gcdDUMP_PATH
+#if defined(ANDROID)
+# define gcdDUMP_PATH "/mnt/sdcard/"
+#else
+# define gcdDUMP_PATH "./"
+#endif
+#endif
+
+/*
+ gcdDUMP
+
+ When set to 1, a dump of all states and memory uploads, as well as other
+ hardware related execution will be printed to the debug console. This
+ data can be used for playing back applications.
+*/
+#ifndef gcdDUMP
+# define gcdDUMP 0
+#endif
+
+/*
+ gcdDUMP_API
+
+ When set to 1, a high level dump of the EGL and GL/VG APs's are
+ captured.
+*/
+#ifndef gcdDUMP_API
+# define gcdDUMP_API 0
+#endif
+
+
+
+/*
+ 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.
+ The value set is the starting frame that the average will be calculated.
+ This is needed because sometimes first few frames are too slow to be included
+ in the average. Frame count starts from 1.
+*/
+#ifndef gcdDUMP_FRAMERATE
+# define gcdDUMP_FRAMERATE 0
+#endif
+
+/*
+ gcdENABLE_FSCALE_VAL_ADJUST
+ When non-zero, FSCALE_VAL when gcvPOWER_ON can be adjusted externally.
+ */
+#ifndef gcdENABLE_FSCALE_VAL_ADJUST
+# define gcdENABLE_FSCALE_VAL_ADJUST 1
+#endif
+
+/*
+ gcdDUMP_IN_KERNEL
+
+ When set to 1, all dumps will happen in the kernel. This is handy if
+ you want the kernel to dump its command buffers as well and the data
+ needs to be in sync.
+*/
+#ifndef gcdDUMP_IN_KERNEL
+# define gcdDUMP_IN_KERNEL 0
+#endif
+
+/*
+ gcdDUMP_COMMAND
+
+ When set to non-zero, the command queue will dump all incoming command
+ and context buffers as well as all other modifications to the command
+ queue.
+*/
+#ifndef gcdDUMP_COMMAND
+# define gcdDUMP_COMMAND 0
+#endif
+
+/*
+ gcdDUMP_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
+
+ When set to a value other than 0, a dump of the frame specified by the value,
+ will be done into frame.tga. Frame count starts from 1.
+ */
+#ifndef gcdDUMP_FRAME_TGA
+# define gcdDUMP_FRAME_TGA 0
+#endif
+/*
+ gcdNULL_DRIVER
+
+ Set to 1 for infinite speed hardware.
+ Set to 2 for bypassing the HAL.
+ Set to 3 for bypassing the drivers.
+*/
+#ifndef gcdNULL_DRIVER
+# define gcdNULL_DRIVER 0
+#endif
+
+/*
+ gcdENABLE_TIMEOUT_DETECTION
+
+ Enable timeout detection.
+*/
+#ifndef gcdENABLE_TIMEOUT_DETECTION
+# define gcdENABLE_TIMEOUT_DETECTION 0
+#endif
+
+/*
+ gcdCMD_BUFFER_SIZE
+
+ Number of bytes in a command buffer.
+*/
+#ifndef gcdCMD_BUFFER_SIZE
+# define gcdCMD_BUFFER_SIZE (128 << 10)
+#endif
+
+/*
+ gcdCMD_BUFFERS
+
+ Number of command buffers to use per client.
+*/
+#ifndef gcdCMD_BUFFERS
+# define gcdCMD_BUFFERS 2
+#endif
+
+/*
+ gcdMAX_CMD_BUFFERS
+
+ Maximum number of command buffers to use per client.
+*/
+#ifndef gcdMAX_CMD_BUFFERS
+# define gcdMAX_CMD_BUFFERS 8
+#endif
+
+/*
+ gcdCOMMAND_QUEUES
+
+ Number of command queues in the kernel.
+*/
+#ifndef gcdCOMMAND_QUEUES
+# define gcdCOMMAND_QUEUES 2
+#endif
+
+/*
+ gcdPOWER_CONTROL_DELAY
+
+ The delay in milliseconds required to wait until the GPU has woke up
+ from a suspend or power-down state. This is system dependent because
+ the bus clock also needs to stabalize.
+*/
+#ifndef gcdPOWER_CONTROL_DELAY
+# define gcdPOWER_CONTROL_DELAY 0
+#endif
+
+/*
+ gcdMIRROR_PAGETABLE
+
+ Enable it when GPUs with old MMU and new MMU exist at same SoC. It makes
+ each GPU use same virtual address to access same physical memory.
+*/
+#ifndef gcdMIRROR_PAGETABLE
+# define gcdMIRROR_PAGETABLE 0
+#endif
+
+/*
+ gcdMMU_SIZE
+
+ Size of the MMU page table in bytes. Each 4 bytes can hold 4kB worth of
+ virtual data.
+*/
+#ifndef gcdMMU_SIZE
+#if gcdMIRROR_PAGETABLE
+# define gcdMMU_SIZE 0x200000
+#else
+# define gcdMMU_SIZE (2048 << 10)
+#endif
+#endif
+
+/*
+ gcdSECURE_USER
+
+ Use logical addresses instead of physical addresses in user land. In
+ this case a hint table is created for both command buffers and context
+ buffers, and that hint table will be used to patch up those buffers in
+ the kernel when they are ready to submit.
+*/
+#ifndef gcdSECURE_USER
+# define gcdSECURE_USER 0
+#endif
+
+/*
+ gcdSECURE_CACHE_SLOTS
+
+ Number of slots in the logical to DMA address cache table. Each time a
+ logical address needs to be translated into a DMA address for the GPU,
+ this cache will be walked. The replacement scheme is LRU.
+*/
+#ifndef gcdSECURE_CACHE_SLOTS
+# define gcdSECURE_CACHE_SLOTS 1024
+#endif
+
+/*
+ gcdSECURE_CACHE_METHOD
+
+ Replacement scheme used for Secure Cache. The following options are
+ available:
+
+ gcdSECURE_CACHE_LRU
+ A standard LRU cache.
+
+ gcdSECURE_CACHE_LINEAR
+ A linear walker with the idea that an application will always
+ render the scene in a similar way, so the next entry in the
+ cache should be a hit most of the time.
+
+ gcdSECURE_CACHE_HASH
+ A 256-entry hash table.
+
+ gcdSECURE_CACHE_TABLE
+ A simple cache but with potential of a lot of cache replacement.
+*/
+#ifndef gcdSECURE_CACHE_METHOD
+# define gcdSECURE_CACHE_METHOD gcdSECURE_CACHE_HASH
+#endif
+
+/*
+ gcdREGISTER_ACCESS_FROM_USER
+
+ Set to 1 to allow IOCTL calls to get through from user land. This
+ should only be in debug or development drops.
+*/
+#ifndef gcdREGISTER_ACCESS_FROM_USER
+# define gcdREGISTER_ACCESS_FROM_USER 1
+#endif
+
+/*
+ gcdHEAP_SIZE
+
+ Set the allocation size for the internal heaps. Each time a heap is
+ full, a new heap will be allocated with this minmimum amount of bytes.
+ The bigger this size, the fewer heaps there are to allocate, the better
+ the performance. However, heaps won't be freed until they are
+ completely free, so there might be some more memory waste if the size is
+ too big.
+*/
+#ifndef gcdHEAP_SIZE
+# define gcdHEAP_SIZE (64 << 10)
+#endif
+
+/*
+ gcdPOWER_SUSPEND_WHEN_IDLE
+
+ Set to 1 to make GPU enter gcvPOWER_SUSPEND when idle detected,
+ otherwise GPU will enter gcvPOWER_IDLE.
+*/
+#ifndef gcdPOWER_SUSPEND_WHEN_IDLE
+# define gcdPOWER_SUSPEND_WHEN_IDLE 1
+#endif
+
+#ifndef gcdFPGA_BUILD
+# define gcdFPGA_BUILD 0
+#endif
+
+/*
+ gcdGPU_TIMEOUT
+
+ This define specified the number of milliseconds the system will wait
+ before it broadcasts the GPU is stuck. In other words, it will define
+ the timeout of any operation that needs to wait for the GPU.
+
+ If the value is 0, no timeout will be checked for.
+*/
+#ifndef gcdGPU_TIMEOUT
+#if gcdFPGA_BUILD
+# define gcdGPU_TIMEOUT 0
+# define gcdGPU_2D_TIMEOUT 0
+# else
+# define gcdGPU_TIMEOUT 20000
+# define gcdGPU_2D_TIMEOUT 20000
+# endif
+#endif
+
+/*
+ gcdGPU_ADVANCETIMER
+
+ it is advance timer.
+*/
+#ifndef gcdGPU_ADVANCETIMER
+# define gcdGPU_ADVANCETIMER 250
+#endif
+
+/*
+ gcdSTATIC_LINK
+
+ This define disalbes static linking;
+*/
+#ifndef gcdSTATIC_LINK
+# define gcdSTATIC_LINK 0
+#endif
+
+/*
+ gcdUSE_NEW_HEAP
+
+ Setting this define to 1 enables new heap.
+*/
+#ifndef gcdUSE_NEW_HEAP
+# define gcdUSE_NEW_HEAP 0
+#endif
+
+/*
+ gcdCMD_NO_2D_CONTEXT
+
+ This define enables no-context 2D command buffer.
+*/
+#ifndef gcdCMD_NO_2D_CONTEXT
+# define gcdCMD_NO_2D_CONTEXT 1
+#endif
+
+/*
+ gcdENABLE_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 _GetBankOffsetBytes() to define how
+ different types of allocations are bank and channel aligned.
+ When disabled (default), no bank alignment is done.
+*/
+#ifndef gcdENABLE_BANK_ALIGNMENT
+# define gcdENABLE_BANK_ALIGNMENT 0
+#endif
+
+/*
+ gcdBANK_BIT_START
+
+ Specifies the start bit of the bank (inclusive).
+*/
+#ifndef gcdBANK_BIT_START
+# define gcdBANK_BIT_START 12
+#endif
+
+/*
+ gcdBANK_BIT_END
+
+ Specifies the end bit of the bank (inclusive).
+*/
+#ifndef gcdBANK_BIT_END
+# define gcdBANK_BIT_END 14
+#endif
+
+/*
+ gcdBANK_CHANNEL_BIT
+
+ When set, video memory when allocated bank aligned is allocated such that
+ render and depth buffer addresses alternate on the channel bit specified.
+ This option has an effect only when gcdENABLE_BANK_ALIGNMENT is enabled.
+ When disabled (default), no alteration is done.
+*/
+#ifndef gcdBANK_CHANNEL_BIT
+# define gcdBANK_CHANNEL_BIT 7
+#endif
+
+/*
+ gcdDYNAMIC_SPEED
+
+ When non-zero, it informs the kernel driver to use the speed throttling
+ broadcasting functions to inform the system the GPU should be spet up or
+ slowed down. It will send a broadcast for slowdown each "interval"
+ specified by this define in milliseconds
+ (gckOS_BroadcastCalibrateSpeed).
+*/
+#ifndef gcdDYNAMIC_SPEED
+# define gcdDYNAMIC_SPEED 2000
+#endif
+
+/*
+ gcdDYNAMIC_EVENT_THRESHOLD
+
+ When non-zero, it specifies the maximum number of available events at
+ which the kernel driver will issue a broadcast to speed up the GPU
+ (gckOS_BroadcastHurry).
+*/
+#ifndef gcdDYNAMIC_EVENT_THRESHOLD
+# define gcdDYNAMIC_EVENT_THRESHOLD 5
+#endif
+
+/*
+ gcdENABLE_PROFILING
+
+ Enable profiling macros.
+*/
+#ifndef gcdENABLE_PROFILING
+# define gcdENABLE_PROFILING 0
+#endif
+
+/*
+ gcdENABLE_128B_MERGE
+
+ Enable 128B merge for the BUS control.
+*/
+#ifndef gcdENABLE_128B_MERGE
+# define gcdENABLE_128B_MERGE 0
+#endif
+
+/*
+ gcdFRAME_DB
+
+ When non-zero, it specified the number of frames inside the frame
+ database. The frame DB will collect per-frame timestamps and hardware
+ counters.
+*/
+#ifndef gcdFRAME_DB
+# define gcdFRAME_DB 0
+# define gcdFRAME_DB_RESET 0
+# define gcdFRAME_DB_NAME "/var/log/frameDB.log"
+#endif
+
+/*
+ gcdDISABLE_CORES_2D3D
+ disable the 2D3D cores for 2D openVG
+*/
+#ifndef gcdDISABLE_CORES_2D3D
+# define gcdDISABLE_CORES_2D3D 0
+#endif
+
+/*
+ gcdPAGED_MEMORY_CACHEABLE
+
+ When non-zero, paged memory will be cacheable.
+
+ Normally, driver will detemines whether a video memory
+ is cacheable or not. When cacheable is not neccessary,
+ it will be writecombine.
+
+ 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
+
+/*
+ gcdNONPAGED_MEMORY_CACHEABLE
+
+ When non-zero, non paged memory will be cacheable.
+*/
+#ifndef gcdNONPAGED_MEMORY_CACHEABLE
+# define gcdNONPAGED_MEMORY_CACHEABLE 0
+#endif
+
+/*
+ gcdNONPAGED_MEMORY_BUFFERABLE
+
+ When non-zero, non paged memory will be bufferable.
+ gcdNONPAGED_MEMORY_BUFFERABLE and gcdNONPAGED_MEMORY_CACHEABLE
+ can't be set 1 at same time
+*/
+#ifndef gcdNONPAGED_MEMORY_BUFFERABLE
+# define gcdNONPAGED_MEMORY_BUFFERABLE 1
+#endif
+
+/*
+ gcdENABLE_INFINITE_SPEED_HW
+ enable the Infinte HW , this is for 2D openVG
+*/
+#ifndef gcdENABLE_INFINITE_SPEED_HW
+# define gcdENABLE_INFINITE_SPEED_HW 0
+#endif
+
+/*
+ gcdMULTI_GPU
+
+ 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
+
+/*
+ gcdMULTI_GPU_AFFINITY
+
+ Enable/disable the binding of a context to one GPU
+*/
+#ifndef gcdMULTI_GPU_AFFINITY
+# define gcdMULTI_GPU_AFFINITY 0
+#endif
+
+/*
+ gcdPOWEROFF_TIMEOUT
+
+ When non-zero, GPU will power off automatically from
+ idle state, and gcdPOWEROFF_TIMEOUT is also the default
+ timeout in milliseconds.
+ */
+#ifndef gcdPOWEROFF_TIMEOUT
+# define gcdPOWEROFF_TIMEOUT 300
+#endif
+
+/*
+ QNX_SINGLE_THREADED_DEBUGGING
+*/
+#ifndef QNX_SINGLE_THREADED_DEBUGGING
+# define QNX_SINGLE_THREADED_DEBUGGING 0
+#endif
+
+/*
+ gcdRENDER_THREADS
+
+ Number of render threads. Make it zero, and there will be no render
+ threads.
+*/
+#ifndef gcdRENDER_THREADS
+# define gcdRENDER_THREADS 0
+#endif
+
+/*
+ gcdSMP
+
+ This define enables SMP support.
+
+ Currently, it only works on Linux/Android,
+ Kbuild will config it according to whether
+ CONFIG_SMP is set.
+
+*/
+#ifndef gcdSMP
+#ifdef __APPLE__
+# define gcdSMP 1
+#else
+# define gcdSMP 0
+#endif
+#endif
+
+/*
+ gcdSHARED_RESOLVE_BUFFER_ENABLED
+
+ Use shared resolve buffer for all app buffers.
+*/
+#ifndef gcdSHARED_RESOLVE_BUFFER_ENABLED
+# define gcdSHARED_RESOLVE_BUFFER_ENABLED 0
+#endif
+
+/*
+ gcdUSE_TRIANGLE_STRIP_PATCH
+ */
+#ifndef gcdUSE_TRIANGLE_STRIP_PATCH
+# define gcdUSE_TRIANGLE_STRIP_PATCH 1
+#endif
+
+/*
+ gcdENABLE_OUTER_CACHE_PATCH
+
+ Enable the outer cache patch.
+*/
+#ifndef gcdENABLE_OUTER_CACHE_PATCH
+# define gcdENABLE_OUTER_CACHE_PATCH 0
+#endif
+
+/*
+ gcdPROCESS_ADDRESS_SPACE
+
+ 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 !gcdPROCESS_ADDRESS_SPACE
+#endif
+
+#ifndef gcdUSE_PVR
+# define gcdUSE_PVR 1
+#endif
+
+/*
+ gcdSMALL_BLOCK_SIZE
+
+ When non-zero, a part of VIDMEM will be reserved for requests
+ whose requesting size is less than gcdSMALL_BLOCK_SIZE.
+
+ 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
+#endif
+
+/*
+ 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
+
+/*
+ gcdLINK_QUEUE_SIZE
+
+ When non-zero, driver maintains a queue to record information of
+ latest lined context buffer and command buffer. Data in this queue
+ is be used to debug.
+*/
+#ifndef gcdLINK_QUEUE_SIZE
+# define gcdLINK_QUEUE_SIZE 64
+#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.
+*/
+#ifndef gcdALPHA_KILL_IN_SHADER
+# define gcdALPHA_KILL_IN_SHADER 1
+#endif
+
+
+
+/*
+ gcdDVFS
+
+ 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)
+#endif
+
+#ifndef gcdSYNC
+# define gcdSYNC 1
+#endif
+
+#ifndef gcdSHADER_SRC_BY_MACHINECODE
+# define gcdSHADER_SRC_BY_MACHINECODE 1
+#endif
+
+#ifndef gcdGLB27_SHADER_REPLACE_OPTIMIZATION
+# define gcdGLB27_SHADER_REPLACE_OPTIMIZATION 1
+#endif
+
+/*
+ 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
+
+/*
+ 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
+
+/*
+ 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
+
+/*
+ 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
+
+/*
+ gcdENABLE_RENDER_INTO_WINDOW
+
+ Enable Render-Into-Window (ie, No-Resolve or direct rendering) feature.
+ NOTE that even if enabled, it still depends on hardware feature and
+ application behavior. When hardware feature or application
+ behavior can not support render into window mode, it will fail back
+ to normal mode.
+ On android, if Render-Into-Window is finally used, window back buffer
+ of 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
+
+/*
+ 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
+
+/*
+ gcdENABLE_BLIT_BUFFER_PRESERVE
+
+ 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
+
+/*
+ gcdANDROID_NATIVE_FENCE_SYNC
+
+ Enable android native fence sync. It is introduced since jellybean-4.2.
+ Depends on linux kernel option: CONFIG_SYNC.
+
+ 0: Disabled
+ 1: Build framework for native fence sync feature, and EGL extension
+ 2: Enable async swap buffers for client
+ * Native fence sync for client 'queueBuffer' in EGL, which is
+ 'acquireFenceFd' for layer in compositor side.
+ 3. Enable async hwcomposer composition.
+ * 'releaseFenceFd' for layer in compositor side, which is native
+ fence sync when client 'dequeueBuffer'
+ * Native fence sync for compositor 'queueBuffer' in EGL, which is
+ 'acquireFenceFd' for framebuffer target for DC
+ */
+#ifndef gcdANDROID_NATIVE_FENCE_SYNC
+# 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
+#endif
+
+/*
+ gcdFORCE_BILINEAR
+
+ Force bilinear for mipfilter.
+*/
+#ifndef gcdFORCE_BILINEAR
+# define gcdFORCE_BILINEAR 1
+#endif
+
+/*
+ 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
+# define gcdENABLE_TS_DOUBLE_BUFFER 1
+#else
+#if gcdMOVG
+# define gcdENABLE_TS_DOUBLE_BUFFER 0
+#else
+# define gcdENABLE_TS_DOUBLE_BUFFER 1
+#endif
+#endif
+
+/* gcdINTERRUPT_STATISTIC
+ *
+ * Monitor the event send to GPU and interrupt issued by GPU.
+ */
+
+#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 0
+#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.
+ This macro can only be enabled by special customer.
+*/
+#ifndef gcdENABLE_THIRD_PARTY_OPERATION
+# define gcdENABLE_THIRD_PARTY_OPERATION 0
+#endif
+
+/*
+ gcdENABLE_DEC_COMPRESSION
+ Enable DEC TPC compression or not.
+*/
+#ifndef gcdENABLE_DEC_COMPRESSION
+# define gcdENABLE_DEC_COMPRESSION 0
+#ifndef gcdDEC_ENABLE_AHB
+# define gcdDEC_ENABLE_AHB 0
+#endif
+#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_PROFILER
+# define gcdGC355_PROFILER 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
+
+/*
+ gcdALLOC_CMD_FROM_RESERVE
+
+ Provide a way by which location of command buffer can be
+ specified. This is a DEBUG option to limit command buffer
+ to some memory range.
+*/
+#ifndef gcdALLOC_CMD_FROM_RESERVE
+# define gcdALLOC_CMD_FROM_RESERVE 0
+#endif
+
+#endif /* __gc_hal_options_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h
new file mode 100644
index 000000000000..fee3c31b10c0
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h
@@ -0,0 +1,619 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#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
+
+#define GLVERTEX_OBJECT 10
+#define GLVERTEX_OBJECT_BYTES 11
+
+#define GLINDEX_OBJECT 20
+#define GLINDEX_OBJECT_BYTES 21
+
+#define GLTEXTURE_OBJECT 30
+#define GLTEXTURE_OBJECT_BYTES 31
+
+#define GLBUFOBJ_OBJECT 40
+#define GLBUFOBJ_OBJECT_BYTES 41
+
+#if VIVANTE_PROFILER
+#define gcmPROFILE_GC(Enum, Value) gcoPROFILER_Count(gcvNULL, Enum, Value)
+#else
+#define gcmPROFILE_GC(Enum, Value) do { } while (gcvFALSE)
+#endif
+
+#ifndef gcdNEW_PROFILER_FILE
+#define gcdNEW_PROFILER_FILE 1
+#endif
+
+#define ES11_CALLS 151
+#define ES11_DRAWCALLS (ES11_CALLS + 1)
+#define ES11_STATECHANGECALLS (ES11_DRAWCALLS + 1)
+#define ES11_POINTCOUNT (ES11_STATECHANGECALLS + 1)
+#define ES11_LINECOUNT (ES11_POINTCOUNT + 1)
+#define ES11_TRIANGLECOUNT (ES11_LINECOUNT + 1)
+
+#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)
+#define VG11_STATECHANGECALLS (VG11_DRAWCALLS + 1)
+#define VG11_FILLCOUNT (VG11_STATECHANGECALLS + 1)
+#define VG11_STROKECOUNT (VG11_FILLCOUNT + 1)
+/* End of Driver API ID Definitions. */
+
+/* HAL & MISC IDs. */
+#define HAL_VERTBUFNEWBYTEALLOC 1
+#define HAL_VERTBUFTOTALBYTEALLOC (HAL_VERTBUFNEWBYTEALLOC + 1)
+#define HAL_VERTBUFNEWOBJALLOC (HAL_VERTBUFTOTALBYTEALLOC + 1)
+#define HAL_VERTBUFTOTALOBJALLOC (HAL_VERTBUFNEWOBJALLOC + 1)
+#define HAL_INDBUFNEWBYTEALLOC (HAL_VERTBUFTOTALOBJALLOC + 1)
+#define HAL_INDBUFTOTALBYTEALLOC (HAL_INDBUFNEWBYTEALLOC + 1)
+#define HAL_INDBUFNEWOBJALLOC (HAL_INDBUFTOTALBYTEALLOC + 1)
+#define HAL_INDBUFTOTALOBJALLOC (HAL_INDBUFNEWOBJALLOC + 1)
+#define HAL_TEXBUFNEWBYTEALLOC (HAL_INDBUFTOTALOBJALLOC + 1)
+#define HAL_TEXBUFTOTALBYTEALLOC (HAL_TEXBUFNEWBYTEALLOC + 1)
+#define HAL_TEXBUFNEWOBJALLOC (HAL_TEXBUFTOTALBYTEALLOC + 1)
+#define HAL_TEXBUFTOTALOBJALLOC (HAL_TEXBUFNEWOBJALLOC + 1)
+
+#define GPU_CYCLES 1
+#define GPU_READ64BYTE (GPU_CYCLES + 1)
+#define GPU_WRITE64BYTE (GPU_READ64BYTE + 1)
+#define GPU_TOTALCYCLES (GPU_WRITE64BYTE + 1)
+#define GPU_IDLECYCLES (GPU_TOTALCYCLES + 1)
+
+#define VS_INSTCOUNT 1
+#define VS_BRANCHINSTCOUNT (VS_INSTCOUNT + 1)
+#define VS_TEXLDINSTCOUNT (VS_BRANCHINSTCOUNT + 1)
+#define VS_RENDEREDVERTCOUNT (VS_TEXLDINSTCOUNT + 1)
+#define VS_SOURCE (VS_RENDEREDVERTCOUNT + 1)
+
+#define PS_INSTCOUNT 1
+#define PS_BRANCHINSTCOUNT (PS_INSTCOUNT + 1)
+#define PS_TEXLDINSTCOUNT (PS_BRANCHINSTCOUNT + 1)
+#define PS_RENDEREDPIXCOUNT (PS_TEXLDINSTCOUNT + 1)
+#define PS_SOURCE (PS_RENDEREDPIXCOUNT + 1)
+
+#define PA_INVERTCOUNT 1
+#define PA_INPRIMCOUNT (PA_INVERTCOUNT + 1)
+#define PA_OUTPRIMCOUNT (PA_INPRIMCOUNT + 1)
+#define PA_DEPTHCLIPCOUNT (PA_OUTPRIMCOUNT + 1)
+#define PA_TRIVIALREJCOUNT (PA_DEPTHCLIPCOUNT + 1)
+#define PA_CULLCOUNT (PA_TRIVIALREJCOUNT + 1)
+
+#define SE_TRIANGLECOUNT 1
+#define SE_LINECOUNT (SE_TRIANGLECOUNT + 1)
+
+#define RA_VALIDPIXCOUNT 1
+#define RA_TOTALQUADCOUNT (RA_VALIDPIXCOUNT + 1)
+#define RA_VALIDQUADCOUNTEZ (RA_TOTALQUADCOUNT + 1)
+#define RA_TOTALPRIMCOUNT (RA_VALIDQUADCOUNTEZ + 1)
+#define RA_PIPECACHEMISSCOUNT (RA_TOTALPRIMCOUNT + 1)
+#define RA_PREFCACHEMISSCOUNT (RA_PIPECACHEMISSCOUNT + 1)
+#define RA_EEZCULLCOUNT (RA_PREFCACHEMISSCOUNT + 1)
+
+#define TX_TOTBILINEARREQ 1
+#define TX_TOTTRILINEARREQ (TX_TOTBILINEARREQ + 1)
+#define TX_TOTDISCARDTEXREQ (TX_TOTTRILINEARREQ + 1)
+#define TX_TOTTEXREQ (TX_TOTDISCARDTEXREQ + 1)
+#define TX_MEMREADCOUNT (TX_TOTTEXREQ + 1)
+#define TX_MEMREADIN8BCOUNT (TX_MEMREADCOUNT + 1)
+#define TX_CACHEMISSCOUNT (TX_MEMREADIN8BCOUNT + 1)
+#define TX_CACHEHITTEXELCOUNT (TX_CACHEMISSCOUNT + 1)
+#define TX_CACHEMISSTEXELCOUNT (TX_CACHEHITTEXELCOUNT + 1)
+
+#define PE_KILLEDBYCOLOR 1
+#define PE_KILLEDBYDEPTH (PE_KILLEDBYCOLOR + 1)
+#define PE_DRAWNBYCOLOR (PE_KILLEDBYDEPTH + 1)
+#define PE_DRAWNBYDEPTH (PE_DRAWNBYCOLOR + 1)
+
+#define MC_READREQ8BPIPE 1
+#define MC_READREQ8BIP (MC_READREQ8BPIPE + 1)
+#define MC_WRITEREQ8BPIPE (MC_READREQ8BIP + 1)
+
+#define AXI_READREQSTALLED 1
+#define AXI_WRITEREQSTALLED (AXI_READREQSTALLED + 1)
+#define AXI_WRITEDATASTALLED (AXI_WRITEREQSTALLED + 1)
+
+#define PVS_INSTRCOUNT 1
+#define PVS_ALUINSTRCOUNT (PVS_INSTRCOUNT + 1)
+#define PVS_TEXINSTRCOUNT (PVS_ALUINSTRCOUNT + 1)
+#define PVS_ATTRIBCOUNT (PVS_TEXINSTRCOUNT + 1)
+#define PVS_UNIFORMCOUNT (PVS_ATTRIBCOUNT + 1)
+#define PVS_FUNCTIONCOUNT (PVS_UNIFORMCOUNT + 1)
+#define PVS_SOURCE (PVS_FUNCTIONCOUNT + 1)
+
+#define PPS_INSTRCOUNT 1
+#define PPS_ALUINSTRCOUNT (PPS_INSTRCOUNT + 1)
+#define PPS_TEXINSTRCOUNT (PPS_ALUINSTRCOUNT + 1)
+#define PPS_ATTRIBCOUNT (PPS_TEXINSTRCOUNT + 1)
+#define PPS_UNIFORMCOUNT (PPS_ATTRIBCOUNT + 1)
+#define PPS_FUNCTIONCOUNT (PPS_UNIFORMCOUNT + 1)
+#define PPS_SOURCE (PPS_FUNCTIONCOUNT + 1)
+/* End of MISC Counter IDs. */
+
+#ifdef gcdNEW_PROFILER_FILE
+
+/* Category Constants. */
+#define VPHEADER 0x010000
+#define VPG_INFO 0x020000
+#define VPG_TIME 0x030000
+#define VPG_MEM 0x040000
+#define VPG_ES11 0x050000
+#define VPG_ES30 0x060000
+#define VPG_VG11 0x070000
+#define VPG_HAL 0x080000
+#define VPG_HW 0x090000
+#define VPG_GPU 0x0a0000
+#define VPG_VS 0x0b0000
+#define VPG_PS 0x0c0000
+#define VPG_PA 0x0d0000
+#define VPG_SETUP 0x0e0000
+#define VPG_RA 0x0f0000
+#define VPG_TX 0x100000
+#define VPG_PE 0x110000
+#define VPG_MC 0x120000
+#define VPG_AXI 0x130000
+#define VPG_PROG 0x140000
+#define VPG_PVS 0x150000
+#define VPG_PPS 0x160000
+#define VPG_ES11_TIME 0x170000
+#define VPG_ES30_TIME 0x180000
+#define VPG_FRAME 0x190000
+#define VPG_ES11_DRAW 0x200000
+#define VPG_ES30_DRAW 0x210000
+#define VPG_VG11_TIME 0x220000
+#define VPG_END 0xff0000
+
+/* Info. */
+#define VPC_INFOCOMPANY (VPG_INFO + 1)
+#define VPC_INFOVERSION (VPC_INFOCOMPANY + 1)
+#define VPC_INFORENDERER (VPC_INFOVERSION + 1)
+#define VPC_INFOREVISION (VPC_INFORENDERER + 1)
+#define VPC_INFODRIVER (VPC_INFOREVISION + 1)
+#define VPC_INFODRIVERMODE (VPC_INFODRIVER + 1)
+#define VPC_INFOSCREENSIZE (VPC_INFODRIVERMODE + 1)
+
+/* Counter Constants. */
+#define VPC_ELAPSETIME (VPG_TIME + 1)
+#define VPC_CPUTIME (VPC_ELAPSETIME + 1)
+
+#define VPC_MEMMAXRES (VPG_MEM + 1)
+#define VPC_MEMSHARED (VPC_MEMMAXRES + 1)
+#define VPC_MEMUNSHAREDDATA (VPC_MEMSHARED + 1)
+#define VPC_MEMUNSHAREDSTACK (VPC_MEMUNSHAREDDATA + 1)
+
+/* OpenGL ES11 Statics Counter IDs. */
+#define VPC_ES11CALLS (VPG_ES11 + ES11_CALLS)
+#define VPC_ES11DRAWCALLS (VPG_ES11 + ES11_DRAWCALLS)
+#define VPC_ES11STATECHANGECALLS (VPG_ES11 + ES11_STATECHANGECALLS)
+#define VPC_ES11POINTCOUNT (VPG_ES11 + ES11_POINTCOUNT)
+#define VPC_ES11LINECOUNT (VPG_ES11 + ES11_LINECOUNT)
+#define VPC_ES11TRIANGLECOUNT (VPG_ES11 + ES11_TRIANGLECOUNT)
+
+/* 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)
+#define VPC_VG11DRAWCALLS (VPG_VG11 + VG11_DRAWCALLS)
+#define VPC_VG11STATECHANGECALLS (VPG_VG11 + VG11_STATECHANGECALLS)
+#define VPC_VG11FILLCOUNT (VPG_VG11 + VG11_FILLCOUNT)
+#define VPC_VG11STROKECOUNT (VPG_VG11 + VG11_STROKECOUNT)
+
+/* HAL Counters. */
+#define VPC_HALVERTBUFNEWBYTEALLOC (VPG_HAL + HAL_VERTBUFNEWBYTEALLOC)
+#define VPC_HALVERTBUFTOTALBYTEALLOC (VPG_HAL + HAL_VERTBUFTOTALBYTEALLOC)
+#define VPC_HALVERTBUFNEWOBJALLOC (VPG_HAL + HAL_VERTBUFNEWOBJALLOC)
+#define VPC_HALVERTBUFTOTALOBJALLOC (VPG_HAL + HAL_VERTBUFTOTALOBJALLOC)
+#define VPC_HALINDBUFNEWBYTEALLOC (VPG_HAL + HAL_INDBUFNEWBYTEALLOC)
+#define VPC_HALINDBUFTOTALBYTEALLOC (VPG_HAL + HAL_INDBUFTOTALBYTEALLOC)
+#define VPC_HALINDBUFNEWOBJALLOC (VPG_HAL + HAL_INDBUFNEWOBJALLOC)
+#define VPC_HALINDBUFTOTALOBJALLOC (VPG_HAL + HAL_INDBUFTOTALOBJALLOC)
+#define VPC_HALTEXBUFNEWBYTEALLOC (VPG_HAL + HAL_TEXBUFNEWBYTEALLOC)
+#define VPC_HALTEXBUFTOTALBYTEALLOC (VPG_HAL + HAL_TEXBUFTOTALBYTEALLOC)
+#define VPC_HALTEXBUFNEWOBJALLOC (VPG_HAL + HAL_TEXBUFNEWOBJALLOC)
+#define VPC_HALTEXBUFTOTALOBJALLOC (VPG_HAL + HAL_TEXBUFTOTALOBJALLOC)
+
+/* HW: GPU Counters. */
+#define VPC_GPUCYCLES (VPG_GPU + GPU_CYCLES)
+#define VPC_GPUREAD64BYTE (VPG_GPU + GPU_READ64BYTE)
+#define VPC_GPUWRITE64BYTE (VPG_GPU + GPU_WRITE64BYTE)
+#define VPC_GPUTOTALCYCLES (VPG_GPU + GPU_TOTALCYCLES)
+#define VPC_GPUIDLECYCLES (VPG_GPU + GPU_IDLECYCLES)
+
+/* HW: Shader Counters. */
+#define VPC_VSINSTCOUNT (VPG_VS + VS_INSTCOUNT)
+#define VPC_VSBRANCHINSTCOUNT (VPG_VS + VS_BRANCHINSTCOUNT)
+#define VPC_VSTEXLDINSTCOUNT (VPG_VS + VS_TEXLDINSTCOUNT)
+#define VPC_VSRENDEREDVERTCOUNT (VPG_VS + VS_RENDEREDVERTCOUNT)
+/* HW: PS Count. */
+#define VPC_PSINSTCOUNT (VPG_PS + PS_INSTCOUNT)
+#define VPC_PSBRANCHINSTCOUNT (VPG_PS + PS_BRANCHINSTCOUNT)
+#define VPC_PSTEXLDINSTCOUNT (VPG_PS + PS_TEXLDINSTCOUNT)
+#define VPC_PSRENDEREDPIXCOUNT (VPG_PS + PS_RENDEREDPIXCOUNT)
+
+
+/* HW: PA Counters. */
+#define VPC_PAINVERTCOUNT (VPG_PA + PA_INVERTCOUNT)
+#define VPC_PAINPRIMCOUNT (VPG_PA + PA_INPRIMCOUNT)
+#define VPC_PAOUTPRIMCOUNT (VPG_PA + PA_OUTPRIMCOUNT)
+#define VPC_PADEPTHCLIPCOUNT (VPG_PA + PA_DEPTHCLIPCOUNT)
+#define VPC_PATRIVIALREJCOUNT (VPG_PA + PA_TRIVIALREJCOUNT)
+#define VPC_PACULLCOUNT (VPG_PA + PA_CULLCOUNT)
+
+/* HW: Setup Counters. */
+#define VPC_SETRIANGLECOUNT (VPG_SETUP + SE_TRIANGLECOUNT)
+#define VPC_SELINECOUNT (VPG_SETUP + SE_LINECOUNT)
+
+/* HW: RA Counters. */
+#define VPC_RAVALIDPIXCOUNT (VPG_RA + RA_VALIDPIXCOUNT)
+#define VPC_RATOTALQUADCOUNT (VPG_RA + RA_TOTALQUADCOUNT)
+#define VPC_RAVALIDQUADCOUNTEZ (VPG_RA + RA_VALIDQUADCOUNTEZ)
+#define VPC_RATOTALPRIMCOUNT (VPG_RA + RA_TOTALPRIMCOUNT)
+#define VPC_RAPIPECACHEMISSCOUNT (VPG_RA + RA_PIPECACHEMISSCOUNT)
+#define VPC_RAPREFCACHEMISSCOUNT (VPG_RA + RA_PREFCACHEMISSCOUNT)
+#define VPC_RAEEZCULLCOUNT (VPG_RA + RA_EEZCULLCOUNT)
+
+/* HW: TEX Counters. */
+#define VPC_TXTOTBILINEARREQ (VPG_TX + TX_TOTBILINEARREQ)
+#define VPC_TXTOTTRILINEARREQ (VPG_TX + TX_TOTTRILINEARREQ)
+#define VPC_TXTOTDISCARDTEXREQ (VPG_TX + TX_TOTDISCARDTEXREQ)
+#define VPC_TXTOTTEXREQ (VPG_TX + TX_TOTTEXREQ)
+#define VPC_TXMEMREADCOUNT (VPG_TX + TX_MEMREADCOUNT)
+#define VPC_TXMEMREADIN8BCOUNT (VPG_TX + TX_MEMREADIN8BCOUNT)
+#define VPC_TXCACHEMISSCOUNT (VPG_TX + TX_CACHEMISSCOUNT)
+#define VPC_TXCACHEHITTEXELCOUNT (VPG_TX + TX_CACHEHITTEXELCOUNT)
+#define VPC_TXCACHEMISSTEXELCOUNT (VPG_TX + TX_CACHEMISSTEXELCOUNT)
+
+/* HW: PE Counters. */
+#define VPC_PEKILLEDBYCOLOR (VPG_PE + PE_KILLEDBYCOLOR)
+#define VPC_PEKILLEDBYDEPTH (VPG_PE + PE_KILLEDBYDEPTH)
+#define VPC_PEDRAWNBYCOLOR (VPG_PE + PE_DRAWNBYCOLOR)
+#define VPC_PEDRAWNBYDEPTH (VPG_PE + PE_DRAWNBYDEPTH)
+
+/* HW: MC Counters. */
+#define VPC_MCREADREQ8BPIPE (VPG_MC + MC_READREQ8BPIPE)
+#define VPC_MCREADREQ8BIP (VPG_MC + MC_READREQ8BIP)
+#define VPC_MCWRITEREQ8BPIPE (VPG_MC + MC_WRITEREQ8BPIPE)
+
+/* HW: AXI Counters. */
+#define VPC_AXIREADREQSTALLED (VPG_AXI + AXI_READREQSTALLED)
+#define VPC_AXIWRITEREQSTALLED (VPG_AXI + AXI_WRITEREQSTALLED)
+#define VPC_AXIWRITEDATASTALLED (VPG_AXI + AXI_WRITEDATASTALLED)
+
+/* PROGRAM: Shader program counters. */
+#define VPC_PVSINSTRCOUNT (VPG_PVS + PVS_INSTRCOUNT)
+#define VPC_PVSALUINSTRCOUNT (VPG_PVS + PVS_ALUINSTRCOUNT)
+#define VPC_PVSTEXINSTRCOUNT (VPG_PVS + PVS_TEXINSTRCOUNT)
+#define VPC_PVSATTRIBCOUNT (VPG_PVS + PVS_ATTRIBCOUNT)
+#define VPC_PVSUNIFORMCOUNT (VPG_PVS + PVS_UNIFORMCOUNT)
+#define VPC_PVSFUNCTIONCOUNT (VPG_PVS + PVS_FUNCTIONCOUNT)
+#define VPC_PVSSOURCE (VPG_PVS + PVS_SOURCE)
+
+#define VPC_PPSINSTRCOUNT (VPG_PPS + PPS_INSTRCOUNT)
+#define VPC_PPSALUINSTRCOUNT (VPG_PPS + PPS_ALUINSTRCOUNT)
+#define VPC_PPSTEXINSTRCOUNT (VPG_PPS + PPS_TEXINSTRCOUNT)
+#define VPC_PPSATTRIBCOUNT (VPG_PPS + PPS_ATTRIBCOUNT)
+#define VPC_PPSUNIFORMCOUNT (VPG_PPS + PPS_UNIFORMCOUNT)
+#define VPC_PPSFUNCTIONCOUNT (VPG_PPS + PPS_FUNCTIONCOUNT)
+#define VPC_PPSSOURCE (VPG_PPS + PPS_SOURCE)
+
+#define VPC_PROGRAMHANDLE (VPG_PROG + 1)
+
+#define VPC_ES30_DRAW_NO (VPG_ES30_DRAW + 1)
+#define VPC_ES11_DRAW_NO (VPG_ES11_DRAW + 1)
+#endif
+
+
+/* HW profile information. */
+typedef struct _gcsPROFILER_COUNTERS
+{
+ /* HW static counters. */
+ gctUINT32 gpuClock;
+ gctUINT32 axiClock;
+ gctUINT32 shaderClock;
+
+ /* HW vairable counters. */
+ gctUINT32 gpuClockStart;
+ gctUINT32 gpuClockEnd;
+
+ /* HW vairable counters. */
+ gctUINT32 gpuCyclesCounter;
+ gctUINT32 gpuTotalCyclesCounter;
+ gctUINT32 gpuIdleCyclesCounter;
+ gctUINT32 gpuTotalRead64BytesPerFrame;
+ gctUINT32 gpuTotalWrite64BytesPerFrame;
+
+ /* PE */
+ gctUINT32 pe_pixel_count_killed_by_color_pipe;
+ gctUINT32 pe_pixel_count_killed_by_depth_pipe;
+ gctUINT32 pe_pixel_count_drawn_by_color_pipe;
+ gctUINT32 pe_pixel_count_drawn_by_depth_pipe;
+
+ /* SH */
+ gctUINT32 ps_inst_counter;
+ gctUINT32 rendered_pixel_counter;
+ gctUINT32 vs_inst_counter;
+ gctUINT32 rendered_vertice_counter;
+ gctUINT32 vtx_branch_inst_counter;
+ gctUINT32 vtx_texld_inst_counter;
+ gctUINT32 pxl_branch_inst_counter;
+ gctUINT32 pxl_texld_inst_counter;
+
+ /* PA */
+ gctUINT32 pa_input_vtx_counter;
+ gctUINT32 pa_input_prim_counter;
+ gctUINT32 pa_output_prim_counter;
+ gctUINT32 pa_depth_clipped_counter;
+ gctUINT32 pa_trivial_rejected_counter;
+ gctUINT32 pa_culled_counter;
+
+ /* SE */
+ gctUINT32 se_culled_triangle_count;
+ gctUINT32 se_culled_lines_count;
+
+ /* RA */
+ gctUINT32 ra_valid_pixel_count;
+ gctUINT32 ra_total_quad_count;
+ gctUINT32 ra_valid_quad_count_after_early_z;
+ gctUINT32 ra_total_primitive_count;
+ gctUINT32 ra_pipe_cache_miss_counter;
+ gctUINT32 ra_prefetch_cache_miss_counter;
+ gctUINT32 ra_eez_culled_counter;
+
+ /* TX */
+ gctUINT32 tx_total_bilinear_requests;
+ gctUINT32 tx_total_trilinear_requests;
+ gctUINT32 tx_total_discarded_texture_requests;
+ gctUINT32 tx_total_texture_requests;
+ gctUINT32 tx_mem_read_count;
+ gctUINT32 tx_mem_read_in_8B_count;
+ gctUINT32 tx_cache_miss_count;
+ gctUINT32 tx_cache_hit_texel_count;
+ gctUINT32 tx_cache_miss_texel_count;
+
+ /* MC */
+ gctUINT32 mc_total_read_req_8B_from_pipeline;
+ gctUINT32 mc_total_read_req_8B_from_IP;
+ gctUINT32 mc_total_write_req_8B_from_pipeline;
+
+ /* HI */
+ gctUINT32 hi_axi_cycles_read_request_stalled;
+ gctUINT32 hi_axi_cycles_write_request_stalled;
+ gctUINT32 hi_axi_cycles_write_data_stalled;
+}
+gcsPROFILER_COUNTERS;
+
+#if VIVANTE_PROFILER_NEW
+#define NumOfDrawBuf 64
+#endif
+
+/* HAL profile information. */
+typedef struct _gcsPROFILER
+{
+ gctUINT32 enable;
+ gctBOOL enableHal;
+ gctBOOL enableHW;
+ gctBOOL enableSH;
+ gctBOOL isSyncMode;
+ gctBOOL disableOutputCounter;
+
+ gctBOOL useSocket;
+ gctINT sockFd;
+
+ gctFILE file;
+
+ /* Aggregate Information */
+
+ /* Clock Info */
+ gctUINT64 frameStart;
+ gctUINT64 frameEnd;
+
+ /* Current frame information */
+ gctUINT32 frameNumber;
+ gctUINT64 frameStartTimeusec;
+ gctUINT64 frameEndTimeusec;
+ gctUINT64 frameStartCPUTimeusec;
+ gctUINT64 frameEndCPUTimeusec;
+
+#if PROFILE_HAL_COUNTERS
+ gctUINT32 vertexBufferTotalBytesAlloc;
+ gctUINT32 vertexBufferNewBytesAlloc;
+ int vertexBufferTotalObjectsAlloc;
+ int vertexBufferNewObjectsAlloc;
+
+ gctUINT32 indexBufferTotalBytesAlloc;
+ gctUINT32 indexBufferNewBytesAlloc;
+ int indexBufferTotalObjectsAlloc;
+ int indexBufferNewObjectsAlloc;
+
+ gctUINT32 textureBufferTotalBytesAlloc;
+ gctUINT32 textureBufferNewBytesAlloc;
+ int textureBufferTotalObjectsAlloc;
+ int textureBufferNewObjectsAlloc;
+
+ gctUINT32 numCommits;
+ gctUINT32 drawPointCount;
+ gctUINT32 drawLineCount;
+ gctUINT32 drawTriangleCount;
+ gctUINT32 drawVertexCount;
+ gctUINT32 redundantStateChangeCalls;
+#endif
+
+ gctUINT32 prevVSInstCount;
+ gctUINT32 prevVSBranchInstCount;
+ gctUINT32 prevVSTexInstCount;
+ gctUINT32 prevVSVertexCount;
+ gctUINT32 prevPSInstCount;
+ gctUINT32 prevPSBranchInstCount;
+ gctUINT32 prevPSTexInstCount;
+ gctUINT32 prevPSPixelCount;
+
+#if VIVANTE_PROFILER_NEW
+ gcoBUFOBJ newCounterBuf[NumOfDrawBuf];
+ gctUINT32 curBufId;
+#endif
+
+}
+gcsPROFILER;
+
+/* Memory profile information. */
+struct _gcsMemProfile
+{
+ /* Memory Usage */
+ gctUINT32 videoMemUsed;
+ gctUINT32 systemMemUsed;
+ gctUINT32 commitBufferSize;
+ gctUINT32 contextBufferCopyBytes;
+};
+
+/* Shader profile information. */
+struct _gcsSHADER_PROFILER
+{
+ gctUINT32 shaderLength;
+ gctUINT32 shaderALUCycles;
+ gctUINT32 shaderTexLoadCycles;
+ gctUINT32 shaderTempRegCount;
+ gctUINT32 shaderSamplerRegCount;
+ gctUINT32 shaderInputRegCount;
+ gctUINT32 shaderOutputRegCount;
+};
+
+/* Initialize the gcsProfiler. */
+gceSTATUS
+gcoPROFILER_Initialize(
+ IN gcoHAL Hal,
+ IN gctBOOL Enable
+ );
+
+/* Destroy the gcProfiler. */
+gceSTATUS
+gcoPROFILER_Destroy(
+ IN gcoHAL Hal
+ );
+
+/* Write data to profiler. */
+gceSTATUS
+gcoPROFILER_Write(
+ IN gcoHAL Hal,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data
+ );
+
+/* Flush data out. */
+gceSTATUS
+gcoPROFILER_Flush(
+ IN gcoHAL Hal
+ );
+
+/* Call to signal end of frame. */
+gceSTATUS
+gcoPROFILER_EndFrame(
+ IN gcoHAL Hal
+ );
+
+/* Call to signal end of draw. */
+gceSTATUS
+gcoPROFILER_EndDraw(
+ IN gcoHAL Hal,
+ IN gctBOOL FirstDraw
+ );
+
+/* Increase profile counter Enum by Value. */
+gceSTATUS
+gcoPROFILER_Count(
+ IN gcoHAL Hal,
+ IN gctUINT32 Enum,
+ IN gctINT Value
+ );
+
+/* Profile input vertex shader. */
+gceSTATUS
+gcoPROFILER_ShaderVS(
+ IN gcoHAL Hal,
+ IN gctPOINTER Vs
+ );
+
+/* Profile input fragment shader. */
+gceSTATUS
+gcoPROFILER_ShaderFS(
+ IN gcoHAL Hal,
+ IN gctPOINTER Fs
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_profiler_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h
new file mode 100644
index 000000000000..03d170f509fd
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h
@@ -0,0 +1,1078 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_raster_h_
+#define __gc_hal_raster_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoBRUSH * gcoBRUSH;
+typedef struct _gcoBRUSH_CACHE * gcoBRUSH_CACHE;
+
+/******************************************************************************\
+******************************** gcoBRUSH Object *******************************
+\******************************************************************************/
+
+/* Create a new solid color gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructSingleColor(
+ IN gcoHAL Hal,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 Color,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a new monochrome gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructMonochrome(
+ IN gcoHAL Hal,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor,
+ IN gctUINT64 Bits,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a color gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructColor(
+ IN gcoHAL Hal,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctPOINTER Address,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Destroy an gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_Destroy(
+ IN gcoBRUSH Brush
+ );
+
+/******************************************************************************\
+******************************** gcoSURF Object *******************************
+\******************************************************************************/
+
+/* Set cipping rectangle. */
+gceSTATUS
+gcoSURF_SetClipping(
+ IN gcoSURF Surface
+ );
+
+/* Clear one or more rectangular areas. */
+gceSTATUS
+gcoSURF_Clear2D(
+ IN gcoSURF DestSurface,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT32 LoColor,
+ IN gctUINT32 HiColor
+ );
+
+/* Draw one or more Bresenham lines. */
+gceSTATUS
+gcoSURF_Line(
+ IN gcoSURF Surface,
+ IN gctUINT32 LineCount,
+ IN gcsRECT_PTR Position,
+ IN gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop
+ );
+
+/* Generic rectangular blit. */
+gceSTATUS
+gcoSURF_Blit(
+ IN OPTIONAL gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gctUINT32 RectCount,
+ IN OPTIONAL gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect,
+ IN OPTIONAL gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN OPTIONAL gceSURF_TRANSPARENCY Transparency,
+ IN OPTIONAL gctUINT32 TransparencyColor,
+ IN OPTIONAL gctPOINTER Mask,
+ IN OPTIONAL gceSURF_MONOPACK MaskPack
+ );
+
+/* Monochrome blit. */
+gceSTATUS
+gcoSURF_MonoBlit(
+ IN gcoSURF DestSurface,
+ IN gctPOINTER Source,
+ IN gceSURF_MONOPACK SourcePack,
+ IN gcsPOINT_PTR SourceSize,
+ IN gcsPOINT_PTR SourceOrigin,
+ IN gcsRECT_PTR DestRect,
+ IN OPTIONAL gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gctBOOL ColorConvert,
+ IN gctUINT8 MonoTransparency,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor
+ );
+
+/* Filter blit. */
+gceSTATUS
+gcoSURF_FilterBlit(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
+gceSTATUS
+gcoSURF_EnableAlphaBlend(
+ IN gcoSURF Surface,
+ IN gctUINT8 SrcGlobalAlphaValue,
+ IN gctUINT8 DstGlobalAlphaValue,
+ IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+ IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+ IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+ IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
+ IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
+ IN gceSURF_PIXEL_COLOR_MODE DstColorMode
+ );
+
+/* Disable alpha blending engine in the hardware and engage the ROP engine. */
+gceSTATUS
+gcoSURF_DisableAlphaBlend(
+ IN gcoSURF Surface
+ );
+
+/* Copy a rectangular area with format conversion. */
+gceSTATUS
+gcoSURF_CopyPixels(
+ IN gcoSURF Source,
+ IN gcoSURF Target,
+ IN gctINT SourceX,
+ IN gctINT SourceY,
+ IN gctINT TargetX,
+ IN gctINT TargetY,
+ IN gctINT Width,
+ IN gctINT Height
+ );
+
+/* Read surface pixel. */
+gceSTATUS
+gcoSURF_ReadPixel(
+ IN gcoSURF Surface,
+ IN gctPOINTER Memory,
+ IN gctINT X,
+ IN gctINT Y,
+ IN gceSURF_FORMAT Format,
+ OUT gctPOINTER PixelValue
+ );
+
+/* Write surface pixel. */
+gceSTATUS
+gcoSURF_WritePixel(
+ IN gcoSURF Surface,
+ IN gctPOINTER Memory,
+ IN gctINT X,
+ IN gctINT Y,
+ IN gceSURF_FORMAT Format,
+ IN gctPOINTER PixelValue
+ );
+
+gceSTATUS
+gcoSURF_SetDither(
+ IN gcoSURF Surface,
+ IN gctBOOL Dither
+ );
+
+gceSTATUS
+gcoSURF_Set2DSource(
+ gcoSURF Surface,
+ gceSURF_ROTATION Rotation
+ );
+
+gceSTATUS
+gcoSURF_Set2DTarget(
+ gcoSURF Surface,
+ gceSURF_ROTATION Rotation
+ );
+
+/******************************************************************************\
+********************************** gco2D Object *********************************
+\******************************************************************************/
+
+/* Construct a new gco2D object. */
+gceSTATUS
+gco2D_Construct(
+ IN gcoHAL Hal,
+ OUT gco2D * Hardware
+ );
+
+/* Destroy an gco2D object. */
+gceSTATUS
+gco2D_Destroy(
+ IN gco2D Hardware
+ );
+
+/* Sets the maximum number of brushes in the brush cache. */
+gceSTATUS
+gco2D_SetBrushLimit(
+ IN gco2D Hardware,
+ IN gctUINT MaxCount
+ );
+
+/* Flush the brush. */
+gceSTATUS
+gco2D_FlushBrush(
+ IN gco2D Engine,
+ IN gcoBRUSH Brush,
+ IN gceSURF_FORMAT Format
+ );
+
+/* Program the specified solid color brush. */
+gceSTATUS
+gco2D_LoadSolidBrush(
+ IN gco2D Engine,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 Color,
+ IN gctUINT64 Mask
+ );
+
+gceSTATUS
+gco2D_LoadMonochromeBrush(
+ IN gco2D Engine,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor,
+ IN gctUINT64 Bits,
+ IN gctUINT64 Mask
+ );
+
+gceSTATUS
+gco2D_LoadColorBrush(
+ IN gco2D Engine,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctUINT32 Address,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT64 Mask
+ );
+
+/* Configure monochrome source. */
+gceSTATUS
+gco2D_SetMonochromeSource(
+ IN gco2D Engine,
+ IN gctBOOL ColorConvert,
+ IN gctUINT8 MonoTransparency,
+ IN gceSURF_MONOPACK DataPack,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor
+ );
+
+/* Configure color source. */
+gceSTATUS
+gco2D_SetColorSource(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 TransparencyColor
+ );
+
+/* Configure color source extension for full rotation. */
+gceSTATUS
+gco2D_SetColorSourceEx(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 TransparencyColor
+ );
+
+/* Configure color source. */
+gceSTATUS
+gco2D_SetColorSourceAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight,
+ IN gctBOOL CoordRelative
+ );
+
+gceSTATUS
+gco2D_SetColorSourceN(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight,
+ IN gctUINT32 SurfaceNumber
+ );
+
+/* Configure masked color source. */
+gceSTATUS
+gco2D_SetMaskedSource(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_MONOPACK MaskPack
+ );
+
+/* Configure masked color source extension for full rotation. */
+gceSTATUS
+gco2D_SetMaskedSourceEx(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_MONOPACK MaskPack,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight
+ );
+
+/* Setup the source rectangle. */
+gceSTATUS
+gco2D_SetSource(
+ IN gco2D Engine,
+ IN gcsRECT_PTR SrcRect
+ );
+
+/* Set clipping rectangle. */
+gceSTATUS
+gco2D_SetClipping(
+ IN gco2D Engine,
+ IN gcsRECT_PTR Rect
+ );
+
+/* Configure destination. */
+gceSTATUS
+gco2D_SetTarget(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth
+ );
+
+/* Configure destination extension for full rotation. */
+gceSTATUS
+gco2D_SetTargetEx(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight
+ );
+
+/* Calculate and program the stretch factors. */
+gceSTATUS
+gco2D_CalcStretchFactor(
+ IN gco2D Engine,
+ IN gctINT32 SrcSize,
+ IN gctINT32 DestSize,
+ OUT gctUINT32_PTR Factor
+ );
+
+gceSTATUS
+gco2D_SetStretchFactors(
+ IN gco2D Engine,
+ IN gctUINT32 HorFactor,
+ IN gctUINT32 VerFactor
+ );
+
+/* Calculate and program the stretch factors based on the rectangles. */
+gceSTATUS
+gco2D_SetStretchRectFactors(
+ IN gco2D Engine,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect
+ );
+
+/* Create a new solid color gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructSingleColorBrush(
+ IN gco2D Engine,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 Color,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a new monochrome gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructMonochromeBrush(
+ IN gco2D Engine,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor,
+ IN gctUINT64 Bits,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a color gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructColorBrush(
+ IN gco2D Engine,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctPOINTER Address,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Clear one or more rectangular areas. */
+gceSTATUS
+gco2D_Clear(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT32 Color32,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Draw one or more Bresenham lines. */
+gceSTATUS
+gco2D_Line(
+ IN gco2D Engine,
+ IN gctUINT32 LineCount,
+ IN gcsRECT_PTR Position,
+ IN gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Draw one or more Bresenham lines based on the 32-bit color. */
+gceSTATUS
+gco2D_ColorLine(
+ IN gco2D Engine,
+ IN gctUINT32 LineCount,
+ IN gcsRECT_PTR Position,
+ IN gctUINT32 Color32,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Generic blit. */
+gceSTATUS
+gco2D_Blit(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+gceSTATUS
+gco2D_Blend(
+ IN gco2D Engine,
+ IN gctUINT32 SrcCount,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Batch blit. */
+gceSTATUS
+gco2D_BatchBlit(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Stretch blit. */
+gceSTATUS
+gco2D_StretchBlit(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Monochrome blit. */
+gceSTATUS
+gco2D_MonoBlit(
+ IN gco2D Engine,
+ IN gctPOINTER StreamBits,
+ IN gcsPOINT_PTR StreamSize,
+ IN gcsRECT_PTR StreamRect,
+ IN gceSURF_MONOPACK SrcStreamPack,
+ IN gceSURF_MONOPACK DestStreamPack,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT32 FgRop,
+ IN gctUINT32 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+gceSTATUS
+gco2D_MonoBlitEx(
+ IN gco2D Engine,
+ IN gctPOINTER StreamBits,
+ IN gctINT32 StreamStride,
+ IN gctINT32 StreamWidth,
+ IN gctINT32 StreamHeight,
+ IN gctINT32 StreamX,
+ IN gctINT32 StreamY,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DstRect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop
+ );
+
+/* Set kernel size. */
+gceSTATUS
+gco2D_SetKernelSize(
+ IN gco2D Engine,
+ IN gctUINT8 HorKernelSize,
+ IN gctUINT8 VerKernelSize
+ );
+
+/* Set filter type. */
+gceSTATUS
+gco2D_SetFilterType(
+ IN gco2D Engine,
+ IN gceFILTER_TYPE FilterType
+ );
+
+/* Set the filter kernel by user. */
+gceSTATUS
+gco2D_SetUserFilterKernel(
+ IN gco2D Engine,
+ IN gceFILTER_PASS_TYPE PassType,
+ IN gctUINT16_PTR KernelArray
+ );
+
+/* Select the pass(es) to be done for user defined filter. */
+gceSTATUS
+gco2D_EnableUserFilterPasses(
+ IN gco2D Engine,
+ IN gctBOOL HorPass,
+ IN gctBOOL VerPass
+ );
+
+/* Frees the temporary buffer allocated by filter blit operation. */
+gceSTATUS
+gco2D_FreeFilterBuffer(
+ IN gco2D Engine
+ );
+
+/* Filter blit. */
+gceSTATUS
+gco2D_FilterBlit(
+ IN gco2D Engine,
+ IN gctUINT32 SrcAddress,
+ IN gctUINT SrcStride,
+ IN gctUINT32 SrcUAddress,
+ IN gctUINT SrcUStride,
+ IN gctUINT32 SrcVAddress,
+ IN gctUINT SrcVStride,
+ IN gceSURF_FORMAT SrcFormat,
+ IN gceSURF_ROTATION SrcRotation,
+ IN gctUINT32 SrcSurfaceWidth,
+ IN gcsRECT_PTR SrcRect,
+ IN gctUINT32 DestAddress,
+ IN gctUINT DestStride,
+ IN gceSURF_FORMAT DestFormat,
+ IN gceSURF_ROTATION DestRotation,
+ IN gctUINT32 DestSurfaceWidth,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+/* Filter blit extension for full rotation. */
+gceSTATUS
+gco2D_FilterBlitEx(
+ IN gco2D Engine,
+ IN gctUINT32 SrcAddress,
+ IN gctUINT SrcStride,
+ IN gctUINT32 SrcUAddress,
+ IN gctUINT SrcUStride,
+ IN gctUINT32 SrcVAddress,
+ IN gctUINT SrcVStride,
+ IN gceSURF_FORMAT SrcFormat,
+ IN gceSURF_ROTATION SrcRotation,
+ IN gctUINT32 SrcSurfaceWidth,
+ IN gctUINT32 SrcSurfaceHeight,
+ IN gcsRECT_PTR SrcRect,
+ IN gctUINT32 DestAddress,
+ IN gctUINT DestStride,
+ IN gceSURF_FORMAT DestFormat,
+ IN gceSURF_ROTATION DestRotation,
+ IN gctUINT32 DestSurfaceWidth,
+ IN gctUINT32 DestSurfaceHeight,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+gceSTATUS
+gco2D_FilterBlitEx2(
+ IN gco2D Engine,
+ IN gctUINT32_PTR SrcAddresses,
+ IN gctUINT32 SrcAddressNum,
+ IN gctUINT32_PTR SrcStrides,
+ IN gctUINT32 SrcStrideNum,
+ IN gceTILING SrcTiling,
+ IN gceSURF_FORMAT SrcFormat,
+ IN gceSURF_ROTATION SrcRotation,
+ IN gctUINT32 SrcSurfaceWidth,
+ IN gctUINT32 SrcSurfaceHeight,
+ IN gcsRECT_PTR SrcRect,
+ IN gctUINT32_PTR DestAddresses,
+ IN gctUINT32 DestAddressNum,
+ IN gctUINT32_PTR DestStrides,
+ IN gctUINT32 DestStrideNum,
+ IN gceTILING DestTiling,
+ IN gceSURF_FORMAT DestFormat,
+ IN gceSURF_ROTATION DestRotation,
+ IN gctUINT32 DestSurfaceWidth,
+ IN gctUINT32 DestSurfaceHeight,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
+gceSTATUS
+gco2D_EnableAlphaBlend(
+ IN gco2D Engine,
+ IN gctUINT8 SrcGlobalAlphaValue,
+ IN gctUINT8 DstGlobalAlphaValue,
+ IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+ IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+ IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+ IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
+ IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
+ IN gceSURF_PIXEL_COLOR_MODE DstColorMode
+ );
+
+/* Enable alpha blending engine in the hardware. */
+gceSTATUS
+gco2D_EnableAlphaBlendAdvanced(
+ IN gco2D Engine,
+ IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+ IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+ IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+ IN gceSURF_BLEND_FACTOR_MODE DstFactorMode
+ );
+
+/* Enable alpha blending engine with Porter Duff rule. */
+gceSTATUS
+gco2D_SetPorterDuffBlending(
+ IN gco2D Engine,
+ IN gce2D_PORTER_DUFF_RULE Rule
+ );
+
+/* Disable alpha blending engine in the hardware and engage the ROP engine. */
+gceSTATUS
+gco2D_DisableAlphaBlend(
+ IN gco2D Engine
+ );
+
+/* Retrieve the maximum number of 32-bit data chunks for a single DE command. */
+gctUINT32
+gco2D_GetMaximumDataCount(
+ void
+ );
+
+/* Retrieve the maximum number of rectangles, that can be passed in a single DE command. */
+gctUINT32
+gco2D_GetMaximumRectCount(
+ void
+ );
+
+/* Returns the pixel alignment of the surface. */
+gceSTATUS
+gco2D_GetPixelAlignment(
+ gceSURF_FORMAT Format,
+ gcsPOINT_PTR Alignment
+ );
+
+/* Retrieve monochrome stream pack size. */
+gceSTATUS
+gco2D_GetPackSize(
+ IN gceSURF_MONOPACK StreamPack,
+ OUT gctUINT32 * PackWidth,
+ OUT gctUINT32 * PackHeight
+ );
+
+/* Flush the 2D pipeline. */
+gceSTATUS
+gco2D_Flush(
+ IN gco2D Engine
+ );
+
+/* Load 256-entry color table for INDEX8 source surfaces. */
+gceSTATUS
+gco2D_LoadPalette(
+ IN gco2D Engine,
+ IN gctUINT FirstIndex,
+ IN gctUINT IndexCount,
+ IN gctPOINTER ColorTable,
+ IN gctBOOL ColorConvert
+ );
+
+/* Enable/disable 2D BitBlt mirrorring. */
+gceSTATUS
+gco2D_SetBitBlitMirror(
+ IN gco2D Engine,
+ IN gctBOOL HorizontalMirror,
+ IN gctBOOL VerticalMirror
+ );
+
+/*
+ * Set the transparency for source, destination and pattern.
+ * It also enable or disable the DFB color key mode.
+ */
+gceSTATUS
+gco2D_SetTransparencyAdvancedEx(
+ IN gco2D Engine,
+ IN gce2D_TRANSPARENCY SrcTransparency,
+ IN gce2D_TRANSPARENCY DstTransparency,
+ IN gce2D_TRANSPARENCY PatTransparency,
+ IN gctBOOL EnableDFBColorKeyMode
+ );
+
+/* Set the transparency for source, destination and pattern. */
+gceSTATUS
+gco2D_SetTransparencyAdvanced(
+ IN gco2D Engine,
+ IN gce2D_TRANSPARENCY SrcTransparency,
+ IN gce2D_TRANSPARENCY DstTransparency,
+ IN gce2D_TRANSPARENCY PatTransparency
+ );
+
+/* Set the source color key. */
+gceSTATUS
+gco2D_SetSourceColorKeyAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKey
+ );
+
+/* Set the source color key range. */
+gceSTATUS
+gco2D_SetSourceColorKeyRangeAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKeyLow,
+ IN gctUINT32 ColorKeyHigh
+ );
+
+/* Set the target color key. */
+gceSTATUS
+gco2D_SetTargetColorKeyAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKey
+ );
+
+/* Set the target color key range. */
+gceSTATUS
+gco2D_SetTargetColorKeyRangeAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKeyLow,
+ IN gctUINT32 ColorKeyHigh
+ );
+
+/* Set the YUV color space mode. */
+gceSTATUS
+gco2D_SetYUVColorMode(
+ IN gco2D Engine,
+ IN gce2D_YUV_COLOR_MODE Mode
+ );
+
+/* Setup the source global color value in ARGB8 format. */
+gceSTATUS gco2D_SetSourceGlobalColorAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 Color32
+ );
+
+/* Setup the target global color value in ARGB8 format. */
+gceSTATUS gco2D_SetTargetGlobalColorAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 Color32
+ );
+
+/* Setup the source and target pixel multiply modes. */
+gceSTATUS
+gco2D_SetPixelMultiplyModeAdvanced(
+ IN gco2D Engine,
+ IN gce2D_PIXEL_COLOR_MULTIPLY_MODE SrcPremultiplySrcAlpha,
+ IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstPremultiplyDstAlpha,
+ IN gce2D_GLOBAL_COLOR_MULTIPLY_MODE SrcPremultiplyGlobalMode,
+ IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstDemultiplyDstAlpha
+ );
+
+/* Set the GPU clock cycles after which the idle engine will keep auto-flushing. */
+gceSTATUS
+gco2D_SetAutoFlushCycles(
+ IN gco2D Engine,
+ IN gctUINT32 Cycles
+ );
+
+#if VIVANTE_PROFILER
+/* Read the profile registers available in the 2D engine and sets them in the profile.
+ The function will also reset the pixelsRendered counter every time.
+*/
+gceSTATUS
+gco2D_ProfileEngine(
+ IN gco2D Engine,
+ OPTIONAL gcs2D_PROFILE_PTR Profile
+ );
+#endif
+
+/* Enable or disable 2D dithering. */
+gceSTATUS
+gco2D_EnableDither(
+ IN gco2D Engine,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gco2D_SetGenericSource(
+ IN gco2D Engine,
+ IN gctUINT32_PTR Addresses,
+ IN gctUINT32 AddressNum,
+ IN gctUINT32_PTR Strides,
+ IN gctUINT32 StrideNum,
+ IN gceTILING Tiling,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight
+);
+
+gceSTATUS
+gco2D_SetGenericTarget(
+ IN gco2D Engine,
+ IN gctUINT32_PTR Addresses,
+ IN gctUINT32 AddressNum,
+ IN gctUINT32_PTR Strides,
+ IN gctUINT32 StrideNum,
+ IN gceTILING Tiling,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight
+);
+
+gceSTATUS
+gco2D_SetCurrentSourceIndex(
+ IN gco2D Engine,
+ IN gctUINT32 SrcIndex
+ );
+
+gceSTATUS
+gco2D_MultiSourceBlit(
+ IN gco2D Engine,
+ IN gctUINT32 SourceMask,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT32 RectCount
+ );
+
+gceSTATUS
+gco2D_SetROP(
+ IN gco2D Engine,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop
+ );
+
+gceSTATUS
+gco2D_SetGdiStretchMode(
+ IN gco2D Engine,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gco2D_SetSourceTileStatus(
+ IN gco2D Engine,
+ IN gce2D_TILE_STATUS_CONFIG TSControl,
+ IN gceSURF_FORMAT CompressedFormat,
+ IN gctUINT32 ClearValue,
+ IN gctUINT32 GpuAddress
+ );
+
+gceSTATUS
+gco2D_SetTargetTileStatus(
+ IN gco2D Engine,
+ IN gce2D_TILE_STATUS_CONFIG TileStatusConfig,
+ IN gceSURF_FORMAT CompressedFormat,
+ IN gctUINT32 ClearValue,
+ IN gctUINT32 GpuAddress
+ );
+
+gceSTATUS
+gco2D_QueryU32(
+ IN gco2D Engine,
+ IN gce2D_QUERY Item,
+ OUT gctUINT32_PTR Value
+ );
+
+gceSTATUS
+gco2D_SetStateU32(
+ IN gco2D Engine,
+ IN gce2D_STATE State,
+ IN gctUINT32 Value
+ );
+
+gceSTATUS
+gco2D_SetStateArrayI32(
+ IN gco2D Engine,
+ IN gce2D_STATE State,
+ IN gctINT32_PTR Array,
+ IN gctINT32 ArraySize
+ );
+
+gceSTATUS
+gco2D_SetStateArrayU32(
+ IN gco2D Engine,
+ IN gce2D_STATE State,
+ IN gctUINT32_PTR Array,
+ IN gctINT32 ArraySize
+ );
+
+gceSTATUS
+gco2D_SetTargetRect(
+ IN gco2D Engine,
+ IN gcsRECT_PTR Rect
+ );
+
+gceSTATUS
+gco2D_Set2DEngine(
+ IN gco2D Engine
+ );
+
+gceSTATUS
+gco2D_UnSet2DEngine(
+ IN gco2D Engine
+ );
+
+gceSTATUS
+gco2D_Get2DEngine(
+ OUT gco2D * Engine
+ );
+
+gceSTATUS
+gco2D_Commit(
+ IN gco2D Engine,
+ IN gctBOOL Stall
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_raster_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h
new file mode 100644
index 000000000000..75c26589946e
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h
@@ -0,0 +1,277 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_rename_h_
+#define __gc_hal_rename_h_
+
+
+#if defined(_HAL2D_APPENDIX)
+
+#define _HAL2D_RENAME_2(api, appendix) api ## appendix
+#define _HAL2D_RENAME_1(api, appendix) _HAL2D_RENAME_2(api, appendix)
+#define gcmHAL2D(api) _HAL2D_RENAME_1(api, _HAL2D_APPENDIX)
+
+
+#define gckOS_Construct gcmHAL2D(gckOS_Construct)
+#define gckOS_Destroy gcmHAL2D(gckOS_Destroy)
+#define gckOS_QueryVideoMemory gcmHAL2D(gckOS_QueryVideoMemory)
+#define gckOS_Allocate gcmHAL2D(gckOS_Allocate)
+#define gckOS_Free gcmHAL2D(gckOS_Free)
+#define gckOS_AllocateMemory gcmHAL2D(gckOS_AllocateMemory)
+#define gckOS_FreeMemory gcmHAL2D(gckOS_FreeMemory)
+#define gckOS_AllocatePagedMemory gcmHAL2D(gckOS_AllocatePagedMemory)
+#define gckOS_AllocatePagedMemoryEx gcmHAL2D(gckOS_AllocatePagedMemoryEx)
+#define gckOS_LockPages gcmHAL2D(gckOS_LockPages)
+#define gckOS_MapPages gcmHAL2D(gckOS_MapPages)
+#define gckOS_UnlockPages gcmHAL2D(gckOS_UnlockPages)
+#define gckOS_FreePagedMemory gcmHAL2D(gckOS_FreePagedMemory)
+#define gckOS_AllocateNonPagedMemory gcmHAL2D(gckOS_AllocateNonPagedMemory)
+#define gckOS_FreeNonPagedMemory gcmHAL2D(gckOS_FreeNonPagedMemory)
+#define gckOS_AllocateContiguous gcmHAL2D(gckOS_AllocateContiguous)
+#define gckOS_FreeContiguous gcmHAL2D(gckOS_FreeContiguous)
+#define gckOS_GetPageSize gcmHAL2D(gckOS_GetPageSize)
+#define gckOS_GetPhysicalAddress gcmHAL2D(gckOS_GetPhysicalAddress)
+#define gckOS_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)
+#define gckOS_WriteMemory gcmHAL2D(gckOS_WriteMemory)
+#define gckOS_MapMemory gcmHAL2D(gckOS_MapMemory)
+#define gckOS_UnmapMemory gcmHAL2D(gckOS_UnmapMemory)
+#define gckOS_UnmapMemoryEx gcmHAL2D(gckOS_UnmapMemoryEx)
+#define gckOS_CreateMutex gcmHAL2D(gckOS_CreateMutex)
+#define gckOS_DeleteMutex gcmHAL2D(gckOS_DeleteMutex)
+#define gckOS_AcquireMutex gcmHAL2D(gckOS_AcquireMutex)
+#define gckOS_ReleaseMutex gcmHAL2D(gckOS_ReleaseMutex)
+#define gckOS_AtomicExchange gcmHAL2D(gckOS_AtomicExchange)
+#define gckOS_AtomicExchangePtr gcmHAL2D(gckOS_AtomicExchangePtr)
+#define gckOS_AtomConstruct gcmHAL2D(gckOS_AtomConstruct)
+#define gckOS_AtomDestroy gcmHAL2D(gckOS_AtomDestroy)
+#define gckOS_AtomGet gcmHAL2D(gckOS_AtomGet)
+#define gckOS_AtomIncrement gcmHAL2D(gckOS_AtomIncrement)
+#define gckOS_AtomDecrement gcmHAL2D(gckOS_AtomDecrement)
+#define gckOS_Delay gcmHAL2D(gckOS_Delay)
+#define gckOS_GetTime gcmHAL2D(gckOS_GetTime)
+#define gckOS_MemoryBarrier gcmHAL2D(gckOS_MemoryBarrier)
+#define gckOS_MapUserPointer gcmHAL2D(gckOS_MapUserPointer)
+#define gckOS_UnmapUserPointer gcmHAL2D(gckOS_UnmapUserPointer)
+#define gckOS_QueryNeedCopy gcmHAL2D(gckOS_QueryNeedCopy)
+#define gckOS_CopyFromUserData gcmHAL2D(gckOS_CopyFromUserData)
+#define gckOS_CopyToUserData gcmHAL2D(gckOS_CopyToUserData)
+#define gckOS_SuspendInterrupt gcmHAL2D(gckOS_SuspendInterrupt)
+#define gckOS_ResumeInterrupt gcmHAL2D(gckOS_ResumeInterrupt)
+#define gckOS_GetBaseAddress gcmHAL2D(gckOS_GetBaseAddress)
+#define gckOS_MemCopy gcmHAL2D(gckOS_MemCopy)
+#define gckOS_ZeroMemory gcmHAL2D(gckOS_ZeroMemory)
+#define gckOS_DeviceControl gcmHAL2D(gckOS_DeviceControl)
+#define gckOS_GetProcessID gcmHAL2D(gckOS_GetProcessID)
+#define gckOS_GetThreadID gcmHAL2D(gckOS_GetThreadID)
+#define gckOS_CreateSignal gcmHAL2D(gckOS_CreateSignal)
+#define gckOS_DestroySignal gcmHAL2D(gckOS_DestroySignal)
+#define gckOS_Signal gcmHAL2D(gckOS_Signal)
+#define gckOS_WaitSignal gcmHAL2D(gckOS_WaitSignal)
+#define gckOS_MapSignal gcmHAL2D(gckOS_MapSignal)
+#define gckOS_MapUserMemory gcmHAL2D(gckOS_MapUserMemory)
+#define gckOS_UnmapUserMemory gcmHAL2D(gckOS_UnmapUserMemory)
+#define gckOS_CreateUserSignal gcmHAL2D(gckOS_CreateUserSignal)
+#define gckOS_DestroyUserSignal gcmHAL2D(gckOS_DestroyUserSignal)
+#define gckOS_WaitUserSignal gcmHAL2D(gckOS_WaitUserSignal)
+#define gckOS_SignalUserSignal gcmHAL2D(gckOS_SignalUserSignal)
+#define gckOS_UserSignal gcmHAL2D(gckOS_UserSignal)
+#define gckOS_UserSignal gcmHAL2D(gckOS_UserSignal)
+#define gckOS_CacheClean gcmHAL2D(gckOS_CacheClean)
+#define gckOS_CacheFlush gcmHAL2D(gckOS_CacheFlush)
+#define gckOS_SetDebugLevel gcmHAL2D(gckOS_SetDebugLevel)
+#define gckOS_SetDebugZone gcmHAL2D(gckOS_SetDebugZone)
+#define gckOS_SetDebugLevelZone gcmHAL2D(gckOS_SetDebugLevelZone)
+#define gckOS_SetDebugZones gcmHAL2D(gckOS_SetDebugZones)
+#define gckOS_SetDebugFile gcmHAL2D(gckOS_SetDebugFile)
+#define gckOS_Broadcast gcmHAL2D(gckOS_Broadcast)
+#define gckOS_SetGPUPower gcmHAL2D(gckOS_SetGPUPower)
+#define gckOS_CreateSemaphore gcmHAL2D(gckOS_CreateSemaphore)
+#define gckOS_DestroySemaphore gcmHAL2D(gckOS_DestroySemaphore)
+#define gckOS_AcquireSemaphore gcmHAL2D(gckOS_AcquireSemaphore)
+#define gckOS_ReleaseSemaphore gcmHAL2D(gckOS_ReleaseSemaphore)
+#define gckHEAP_Construct gcmHAL2D(gckHEAP_Construct)
+#define gckHEAP_Destroy gcmHAL2D(gckHEAP_Destroy)
+#define gckHEAP_Allocate gcmHAL2D(gckHEAP_Allocate)
+#define gckHEAP_Free gcmHAL2D(gckHEAP_Free)
+#define gckHEAP_ProfileStart gcmHAL2D(gckHEAP_ProfileStart)
+#define gckHEAP_ProfileEnd gcmHAL2D(gckHEAP_ProfileEnd)
+#define gckHEAP_Test gcmHAL2D(gckHEAP_Test)
+#define gckVIDMEM_Construct gcmHAL2D(gckVIDMEM_Construct)
+#define gckVIDMEM_Destroy gcmHAL2D(gckVIDMEM_Destroy)
+#define gckVIDMEM_Allocate gcmHAL2D(gckVIDMEM_Allocate)
+#define gckVIDMEM_AllocateLinear gcmHAL2D(gckVIDMEM_AllocateLinear)
+#define gckVIDMEM_Free gcmHAL2D(gckVIDMEM_Free)
+#define gckVIDMEM_Lock gcmHAL2D(gckVIDMEM_Lock)
+#define gckVIDMEM_Unlock gcmHAL2D(gckVIDMEM_Unlock)
+#define gckVIDMEM_ConstructVirtual gcmHAL2D(gckVIDMEM_ConstructVirtual)
+#define gckVIDMEM_DestroyVirtual gcmHAL2D(gckVIDMEM_DestroyVirtual)
+#define gckKERNEL_Construct gcmHAL2D(gckKERNEL_Construct)
+#define gckKERNEL_Destroy gcmHAL2D(gckKERNEL_Destroy)
+#define gckKERNEL_Dispatch gcmHAL2D(gckKERNEL_Dispatch)
+#define gckKERNEL_QueryVideoMemory gcmHAL2D(gckKERNEL_QueryVideoMemory)
+#define gckKERNEL_GetVideoMemoryPool gcmHAL2D(gckKERNEL_GetVideoMemoryPool)
+#define gckKERNEL_MapVideoMemory gcmHAL2D(gckKERNEL_MapVideoMemory)
+#define gckKERNEL_UnmapVideoMemory gcmHAL2D(gckKERNEL_UnmapVideoMemory)
+#define gckKERNEL_MapMemory gcmHAL2D(gckKERNEL_MapMemory)
+#define gckKERNEL_UnmapMemory gcmHAL2D(gckKERNEL_UnmapMemory)
+#define gckKERNEL_Notify gcmHAL2D(gckKERNEL_Notify)
+#define gckKERNEL_QuerySettings gcmHAL2D(gckKERNEL_QuerySettings)
+#define gckKERNEL_Recovery gcmHAL2D(gckKERNEL_Recovery)
+#define gckKERNEL_OpenUserData gcmHAL2D(gckKERNEL_OpenUserData)
+#define gckKERNEL_CloseUserData gcmHAL2D(gckKERNEL_CloseUserData)
+#define gckHARDWARE_Construct gcmHAL2D(gckHARDWARE_Construct)
+#define gckHARDWARE_Destroy gcmHAL2D(gckHARDWARE_Destroy)
+#define gckHARDWARE_QuerySystemMemory gcmHAL2D(gckHARDWARE_QuerySystemMemory)
+#define gckHARDWARE_BuildVirtualAddress gcmHAL2D(gckHARDWARE_BuildVirtualAddress)
+#define gckHARDWARE_QueryCommandBuffer gcmHAL2D(gckHARDWARE_QueryCommandBuffer)
+#define gckHARDWARE_WaitLink gcmHAL2D(gckHARDWARE_WaitLink)
+#define gckHARDWARE_Execute gcmHAL2D(gckHARDWARE_Execute)
+#define gckHARDWARE_End gcmHAL2D(gckHARDWARE_End)
+#define gckHARDWARE_Nop gcmHAL2D(gckHARDWARE_Nop)
+#define gckHARDWARE_PipeSelect gcmHAL2D(gckHARDWARE_PipeSelect)
+#define gckHARDWARE_Link gcmHAL2D(gckHARDWARE_Link)
+#define gckHARDWARE_Event gcmHAL2D(gckHARDWARE_Event)
+#define gckHARDWARE_QueryMemory gcmHAL2D(gckHARDWARE_QueryMemory)
+#define gckHARDWARE_QueryChipIdentity gcmHAL2D(gckHARDWARE_QueryChipIdentity)
+#define gckHARDWARE_QueryChipSpecs gcmHAL2D(gckHARDWARE_QueryChipSpecs)
+#define gckHARDWARE_QueryShaderCaps gcmHAL2D(gckHARDWARE_QueryShaderCaps)
+#define gckHARDWARE_ConvertFormat gcmHAL2D(gckHARDWARE_ConvertFormat)
+#define gckHARDWARE_SplitMemory gcmHAL2D(gckHARDWARE_SplitMemory)
+#define gckHARDWARE_AlignToTile gcmHAL2D(gckHARDWARE_AlignToTile)
+#define gckHARDWARE_UpdateQueueTail gcmHAL2D(gckHARDWARE_UpdateQueueTail)
+#define gckHARDWARE_ConvertLogical gcmHAL2D(gckHARDWARE_ConvertLogical)
+#define gckHARDWARE_Interrupt gcmHAL2D(gckHARDWARE_Interrupt)
+#define gckHARDWARE_SetMMU gcmHAL2D(gckHARDWARE_SetMMU)
+#define gckHARDWARE_FlushMMU gcmHAL2D(gckHARDWARE_FlushMMU)
+#define gckHARDWARE_GetIdle gcmHAL2D(gckHARDWARE_GetIdle)
+#define gckHARDWARE_Flush gcmHAL2D(gckHARDWARE_Flush)
+#define gckHARDWARE_SetFastClear gcmHAL2D(gckHARDWARE_SetFastClear)
+#define gckHARDWARE_ReadInterrupt gcmHAL2D(gckHARDWARE_ReadInterrupt)
+#define gckHARDWARE_SetPowerManagementState gcmHAL2D(gckHARDWARE_SetPowerManagementState)
+#define gckHARDWARE_QueryPowerManagementState gcmHAL2D(gckHARDWARE_QueryPowerManagementState)
+#define gckHARDWARE_ProfileEngine2D gcmHAL2D(gckHARDWARE_ProfileEngine2D)
+#define gckHARDWARE_InitializeHardware gcmHAL2D(gckHARDWARE_InitializeHardware)
+#define gckHARDWARE_Reset gcmHAL2D(gckHARDWARE_Reset)
+#define gckINTERRUPT_Construct gcmHAL2D(gckINTERRUPT_Construct)
+#define gckINTERRUPT_Destroy gcmHAL2D(gckINTERRUPT_Destroy)
+#define gckINTERRUPT_SetHandler gcmHAL2D(gckINTERRUPT_SetHandler)
+#define gckINTERRUPT_Notify gcmHAL2D(gckINTERRUPT_Notify)
+#define gckEVENT_Construct gcmHAL2D(gckEVENT_Construct)
+#define gckEVENT_Destroy gcmHAL2D(gckEVENT_Destroy)
+#define gckEVENT_AddList gcmHAL2D(gckEVENT_AddList)
+#define gckEVENT_FreeNonPagedMemory gcmHAL2D(gckEVENT_FreeNonPagedMemory)
+#define gckEVENT_FreeContiguousMemory gcmHAL2D(gckEVENT_FreeContiguousMemory)
+#define gckEVENT_FreeVideoMemory gcmHAL2D(gckEVENT_FreeVideoMemory)
+#define gckEVENT_Signal gcmHAL2D(gckEVENT_Signal)
+#define gckEVENT_Unlock gcmHAL2D(gckEVENT_Unlock)
+#define gckEVENT_Submit gcmHAL2D(gckEVENT_Submit)
+#define gckEVENT_Commit gcmHAL2D(gckEVENT_Commit)
+#define gckEVENT_Notify gcmHAL2D(gckEVENT_Notify)
+#define gckEVENT_Interrupt gcmHAL2D(gckEVENT_Interrupt)
+#define gckCOMMAND_Construct gcmHAL2D(gckCOMMAND_Construct)
+#define gckCOMMAND_Destroy gcmHAL2D(gckCOMMAND_Destroy)
+#define gckCOMMAND_EnterCommit gcmHAL2D(gckCOMMAND_EnterCommit)
+#define gckCOMMAND_ExitCommit gcmHAL2D(gckCOMMAND_ExitCommit)
+#define gckCOMMAND_Start gcmHAL2D(gckCOMMAND_Start)
+#define gckCOMMAND_Stop gcmHAL2D(gckCOMMAND_Stop)
+#define gckCOMMAND_Commit gcmHAL2D(gckCOMMAND_Commit)
+#define gckCOMMAND_Reserve gcmHAL2D(gckCOMMAND_Reserve)
+#define gckCOMMAND_Execute gcmHAL2D(gckCOMMAND_Execute)
+#define gckCOMMAND_Stall gcmHAL2D(gckCOMMAND_Stall)
+#define gckCOMMAND_Attach gcmHAL2D(gckCOMMAND_Attach)
+#define gckCOMMAND_Detach gcmHAL2D(gckCOMMAND_Detach)
+#define gckMMU_Construct gcmHAL2D(gckMMU_Construct)
+#define gckMMU_Destroy gcmHAL2D(gckMMU_Destroy)
+#define gckMMU_AllocatePages gcmHAL2D(gckMMU_AllocatePages)
+#define gckMMU_FreePages gcmHAL2D(gckMMU_FreePages)
+#define gckMMU_Test gcmHAL2D(gckMMU_Test)
+#define gckHARDWARE_QueryProfileRegisters gcmHAL2D(gckHARDWARE_QueryProfileRegisters)
+
+
+#define FindMdlMap gcmHAL2D(FindMdlMap)
+#define OnProcessExit gcmHAL2D(OnProcessExit)
+
+#define gckGALDEVICE_Destroy gcmHAL2D(gckGALDEVICE_Destroy)
+#define gckOS_Print gcmHAL2D(gckOS_Print)
+#define gckGALDEVICE_FreeMemory gcmHAL2D(gckGALDEVICE_FreeMemory)
+#define gckGALDEVICE_AllocateMemory gcmHAL2D(gckGALDEVICE_AllocateMemory)
+#define gckOS_DebugBreak gcmHAL2D(gckOS_DebugBreak)
+#define gckGALDEVICE_Release_ISR gcmHAL2D(gckGALDEVICE_Release_ISR)
+#define gckOS_Verify gcmHAL2D(gckOS_Verify)
+#define gckCOMMAND_Release gcmHAL2D(gckCOMMAND_Release)
+#define gckGALDEVICE_Stop gcmHAL2D(gckGALDEVICE_Stop)
+#define gckGALDEVICE_Construct gcmHAL2D(gckGALDEVICE_Construct)
+#define gckOS_DebugFatal gcmHAL2D(gckOS_DebugFatal)
+#define gckOS_DebugTrace gcmHAL2D(gckOS_DebugTrace)
+#define gckHARDWARE_GetBaseAddress gcmHAL2D(gckHARDWARE_GetBaseAddress)
+#define gckGALDEVICE_Setup_ISR gcmHAL2D(gckGALDEVICE_Setup_ISR)
+#define gckKERNEL_AttachProcess gcmHAL2D(gckKERNEL_AttachProcess)
+#define gckKERNEL_AttachProcessEx gcmHAL2D(gckKERNEL_AttachProcessEx)
+#define gckGALDEVICE_Start_Thread gcmHAL2D(gckGALDEVICE_Start_Thread)
+#define gckHARDWARE_QueryIdle gcmHAL2D(gckHARDWARE_QueryIdle)
+#define gckGALDEVICE_Start gcmHAL2D(gckGALDEVICE_Start)
+#define gckOS_GetKernelLogical gcmHAL2D(gckOS_GetKernelLogical)
+#define gckOS_DebugTraceZone gcmHAL2D(gckOS_DebugTraceZone)
+#define gckGALDEVICE_Stop_Thread gcmHAL2D(gckGALDEVICE_Stop_Thread)
+#define gckHARDWARE_NeedBaseAddress gcmHAL2D(gckHARDWARE_NeedBaseAddress)
+
+#endif
+
+#endif /* __gc_hal_rename_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_security_interface.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_security_interface.h
new file mode 100644
index 000000000000..27f91f0aec3a
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_security_interface.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#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
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h
new file mode 100644
index 000000000000..5611a8bc214a
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_statistics_h_
+#define __gc_hal_statistics_h_
+
+
+#define VIV_STAT_ENABLE_STATISTICS 0
+
+/* Toal number of frames for which the frame time is accounted. We have storage
+ to keep frame times for last this many frames.
+*/
+#define VIV_STAT_FRAME_BUFFER_SIZE 30
+
+
+/*
+ Total number of frames sampled for a mode. This means
+
+ # of frames for HZ Current : VIV_STAT_EARLY_Z_SAMPLE_FRAMES
+ # of frames for HZ Switched : VIV_STAT_EARLY_Z_SAMPLE_FRAMES
+ +
+ --------------------------------------------------------
+ : (2 * VIV_STAT_EARLY_Z_SAMPLE_FRAMES) frames needed
+
+ IMPORTANT: This total must be smaller than VIV_STAT_FRAME_BUFFER_SIZE
+*/
+#define VIV_STAT_EARLY_Z_SAMPLE_FRAMES 7
+#define VIV_STAT_EARLY_Z_LATENCY_FRAMES 2
+
+/* Multiplication factor for previous Hz off mode. Make it more than 1.0 to advertise HZ on.*/
+#define VIV_STAT_EARLY_Z_FACTOR (1.05f)
+
+/* Defines the statistical data keys monitored by the statistics module */
+typedef enum _gceSTATISTICS
+{
+ gcvFRAME_FPS = 1,
+}
+gceSTATISTICS;
+
+/* HAL statistics information. */
+typedef struct _gcsSTATISTICS_EARLYZ
+{
+ gctUINT switchBackCount;
+ gctUINT nextCheckPoint;
+ gctBOOL disabled;
+}
+gcsSTATISTICS_EARLYZ;
+
+
+/* HAL statistics information. */
+typedef struct _gcsSTATISTICS
+{
+ gctUINT64 frameTime[VIV_STAT_FRAME_BUFFER_SIZE];
+ gctUINT64 previousFrameTime;
+ gctUINT frame;
+ gcsSTATISTICS_EARLYZ earlyZ;
+}
+gcsSTATISTICS;
+
+
+/* Add a frame based data into current statistics. */
+void
+gcfSTATISTICS_AddData(
+ IN gceSTATISTICS Key,
+ IN gctUINT Value
+ );
+
+/* Marks the frame end and triggers statistical calculations and decisions.*/
+void
+gcfSTATISTICS_MarkFrameEnd (
+ void
+ );
+
+/* Sets whether the dynmaic HZ is disabled or not .*/
+void
+gcfSTATISTICS_DisableDynamicEarlyZ (
+ IN gctBOOL Disabled
+ );
+
+#endif /*__gc_hal_statistics_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h
new file mode 100644
index 000000000000..f79f9ad57bde
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h
@@ -0,0 +1,976 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_types_h_
+#define __gc_hal_types_h_
+
+#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)). */
+#pragma warning(disable:4100) /* Unreferenced formal parameter. */
+#pragma warning(disable:4204) /* Non-constant aggregate initializer (C99). */
+#pragma warning(disable:4131) /* Uses old-style declarator (for Bison and
+ ** Flex generated files). */
+#pragma warning(disable:4206) /* Translation unit is empty. */
+#pragma warning(disable:4214) /* Nonstandard extension used :
+ ** bit field types other than int. */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+** Platform macros.
+*/
+
+#if defined(__GNUC__)
+# define gcdHAS_ELLIPSIS 1 /* GCC always has it. */
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define gcdHAS_ELLIPSIS 1 /* C99 has it. */
+#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
+# define gcdHAS_ELLIPSIS 1 /* MSVC 2007+ has it. */
+#elif defined(UNDER_CE)
+#if UNDER_CE >= 600
+# define gcdHAS_ELLIPSIS 1
+# else
+# define gcdHAS_ELLIPSIS 0
+# endif
+#else
+# error "gcdHAS_ELLIPSIS: Platform could not be determined"
+#endif
+
+/******************************************************************************\
+************************************ Keyword ***********************************
+\******************************************************************************/
+#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. */
+#elif defined(_MSC_VER) || defined(UNDER_CE)
+# define gcmINLINE __inline /* Internal keyword. */
+#else
+# error "gcmINLINE: Platform could not be determined"
+#endif
+
+/* Possible debug flags. */
+#define gcdDEBUG_NONE 0
+#define gcdDEBUG_ALL (1 << 0)
+#define gcdDEBUG_FATAL (1 << 1)
+#define gcdDEBUG_TRACE (1 << 2)
+#define gcdDEBUG_BREAK (1 << 3)
+#define gcdDEBUG_ASSERT (1 << 4)
+#define gcdDEBUG_CODE (1 << 5)
+#define gcdDEBUG_STACK (1 << 6)
+
+#define gcmIS_DEBUG(flag) ( gcdDEBUG & (flag | gcdDEBUG_ALL) )
+
+#ifndef gcdDEBUG
+#if (defined(DBG) && DBG) || defined(DEBUG) || defined(_DEBUG)
+# define gcdDEBUG gcdDEBUG_ALL
+# else
+# define gcdDEBUG gcdDEBUG_NONE
+# endif
+#endif
+
+#ifdef _USRDLL
+#ifdef _MSC_VER
+#ifdef HAL_EXPORTS
+# define HALAPI __declspec(dllexport)
+# else
+# define HALAPI __declspec(dllimport)
+# endif
+# define HALDECL __cdecl
+# else
+#ifdef HAL_EXPORTS
+# define HALAPI
+# else
+# define HALAPI extern
+# endif
+# endif
+#else
+# define HALAPI
+# define HALDECL
+#endif
+
+/******************************************************************************\
+********************************** Common Types ********************************
+\******************************************************************************/
+
+#define gcvFALSE 0
+#define gcvTRUE 1
+
+#define gcvINFINITE ((gctUINT32) ~0U)
+
+#define gcvINVALID_HANDLE ((gctHANDLE) ~0U)
+
+typedef int gctBOOL;
+typedef gctBOOL * gctBOOL_PTR;
+
+typedef int gctINT;
+typedef signed char gctINT8;
+typedef signed short gctINT16;
+typedef signed int gctINT32;
+typedef signed long long gctINT64;
+
+typedef gctINT * gctINT_PTR;
+typedef gctINT8 * gctINT8_PTR;
+typedef gctINT16 * gctINT16_PTR;
+typedef gctINT32 * gctINT32_PTR;
+typedef gctINT64 * gctINT64_PTR;
+
+typedef unsigned int gctUINT;
+typedef unsigned char gctUINT8;
+typedef unsigned short gctUINT16;
+typedef unsigned int gctUINT32;
+typedef unsigned long long gctUINT64;
+typedef uintptr_t gctUINTPTR_T;
+
+typedef gctUINT * gctUINT_PTR;
+typedef gctUINT8 * gctUINT8_PTR;
+typedef gctUINT16 * gctUINT16_PTR;
+typedef gctUINT32 * gctUINT32_PTR;
+typedef gctUINT64 * gctUINT64_PTR;
+
+typedef size_t gctSIZE_T;
+typedef gctSIZE_T * gctSIZE_T_PTR;
+typedef gctUINT32 gctTRACE;
+
+#ifdef __cplusplus
+# define gcvNULL 0
+#else
+# 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;
+
+typedef void * gctPHYS_ADDR;
+typedef void * gctHANDLE;
+typedef void * gctFILE;
+typedef void * gctSIGNAL;
+typedef void * gctWINDOW;
+typedef void * gctIMAGE;
+typedef void * gctSYNC_POINT;
+typedef void * gctSHBUF;
+
+typedef void * gctSEMAPHORE;
+
+typedef void * gctPOINTER;
+typedef const void * gctCONST_POINTER;
+
+typedef char gctCHAR;
+typedef char * gctSTRING;
+typedef const char * gctCONST_STRING;
+
+typedef gctUINT64 gctPHYS_ADDR_T;
+
+typedef struct _gcsCOUNT_STRING
+{
+ gctSIZE_T Length;
+ gctCONST_STRING String;
+}
+gcsCOUNT_STRING;
+
+typedef union _gcuFLOAT_UINT32
+{
+ gctFLOAT f;
+ gctUINT32 u;
+}
+gcuFLOAT_UINT32;
+
+/* Fixed point constants. */
+#define gcvZERO_X ((gctFIXED_POINT) 0x00000000)
+#define gcvHALF_X ((gctFIXED_POINT) 0x00008000)
+#define gcvONE_X ((gctFIXED_POINT) 0x00010000)
+#define gcvNEGONE_X ((gctFIXED_POINT) 0xFFFF0000)
+#define gcvTWO_X ((gctFIXED_POINT) 0x00020000)
+
+
+
+#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
+
+/******************************************************************************\
+******************************* Fixed Point Math *******************************
+\******************************************************************************/
+
+#define gcmXMultiply(x1, x2) gcoMATH_MultiplyFixed(x1, x2)
+#define gcmXDivide(x1, x2) gcoMATH_DivideFixed(x1, x2)
+#define gcmXMultiplyDivide(x1, x2, x3) gcoMATH_MultiplyDivideFixed(x1, x2, x3)
+
+/* 2D Engine profile. */
+typedef struct _gcs2D_PROFILE
+{
+ /* Cycle count.
+ 32bit counter incremented every 2D clock cycle.
+ Wraps back to 0 when the counter overflows.
+ */
+ gctUINT32 cycleCount;
+
+ /* Pixels rendered by the 2D engine.
+ Resets to 0 every time it is read. */
+ gctUINT32 pixelsRendered;
+}
+gcs2D_PROFILE;
+
+/* Macro to combine four characters into a Charcater Code. */
+#define gcmCC(c1, c2, c3, c4) \
+( \
+ (char) (c1) \
+ | \
+ ((char) (c2) << 8) \
+ | \
+ ((char) (c3) << 16) \
+ | \
+ ((char) (c4) << 24) \
+)
+
+#define gcmPRINTABLE(c) ((((c) >= ' ') && ((c) <= '}')) ? ((c) != '%' ? (c) : ' ') : ' ')
+
+#define gcmCC_PRINT(cc) \
+ gcmPRINTABLE((char) ( (cc) & 0xFF)), \
+ gcmPRINTABLE((char) (((cc) >> 8) & 0xFF)), \
+ gcmPRINTABLE((char) (((cc) >> 16) & 0xFF)), \
+ gcmPRINTABLE((char) (((cc) >> 24) & 0xFF))
+
+/******************************************************************************\
+****************************** Function Parameters *****************************
+\******************************************************************************/
+
+#define IN
+#define OUT
+#define INOUT
+#define OPTIONAL
+
+/******************************************************************************\
+********************************* Status Codes *********************************
+\******************************************************************************/
+
+typedef enum _gceSTATUS
+{
+ gcvSTATUS_OK = 0,
+ gcvSTATUS_FALSE = 0,
+ gcvSTATUS_TRUE = 1,
+ gcvSTATUS_NO_MORE_DATA = 2,
+ gcvSTATUS_CACHED = 3,
+ gcvSTATUS_MIPMAP_TOO_LARGE = 4,
+ gcvSTATUS_NAME_NOT_FOUND = 5,
+ gcvSTATUS_NOT_OUR_INTERRUPT = 6,
+ gcvSTATUS_MISMATCH = 7,
+ gcvSTATUS_MIPMAP_TOO_SMALL = 8,
+ gcvSTATUS_LARGER = 9,
+ gcvSTATUS_SMALLER = 10,
+ gcvSTATUS_CHIP_NOT_READY = 11,
+ gcvSTATUS_NEED_CONVERSION = 12,
+ gcvSTATUS_SKIP = 13,
+ gcvSTATUS_DATA_TOO_LARGE = 14,
+ gcvSTATUS_INVALID_CONFIG = 15,
+ gcvSTATUS_CHANGED = 16,
+ gcvSTATUS_NOT_SUPPORT_DITHER = 17,
+ gcvSTATUS_EXECUTED = 18,
+ gcvSTATUS_TERMINATE = 19,
+
+ gcvSTATUS_INVALID_ARGUMENT = -1,
+ gcvSTATUS_INVALID_OBJECT = -2,
+ gcvSTATUS_OUT_OF_MEMORY = -3,
+ gcvSTATUS_MEMORY_LOCKED = -4,
+ gcvSTATUS_MEMORY_UNLOCKED = -5,
+ gcvSTATUS_HEAP_CORRUPTED = -6,
+ gcvSTATUS_GENERIC_IO = -7,
+ gcvSTATUS_INVALID_ADDRESS = -8,
+ gcvSTATUS_CONTEXT_LOSSED = -9,
+ gcvSTATUS_TOO_COMPLEX = -10,
+ gcvSTATUS_BUFFER_TOO_SMALL = -11,
+ gcvSTATUS_INTERFACE_ERROR = -12,
+ gcvSTATUS_NOT_SUPPORTED = -13,
+ gcvSTATUS_MORE_DATA = -14,
+ gcvSTATUS_TIMEOUT = -15,
+ gcvSTATUS_OUT_OF_RESOURCES = -16,
+ gcvSTATUS_INVALID_DATA = -17,
+ gcvSTATUS_INVALID_MIPMAP = -18,
+ gcvSTATUS_NOT_FOUND = -19,
+ gcvSTATUS_NOT_ALIGNED = -20,
+ gcvSTATUS_INVALID_REQUEST = -21,
+ gcvSTATUS_GPU_NOT_RESPONDING = -22,
+ gcvSTATUS_TIMER_OVERFLOW = -23,
+ gcvSTATUS_VERSION_MISMATCH = -24,
+ gcvSTATUS_LOCKED = -25,
+ gcvSTATUS_INTERRUPTED = -26,
+ gcvSTATUS_DEVICE = -27,
+ 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_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,
+
+ /* Recompilation Errors */
+ gcvSTATUS_RECOMPILER_CONVERT_UNIMPLEMENTED = -3000,
+}
+gceSTATUS;
+
+/******************************************************************************\
+********************************* Status Macros ********************************
+\******************************************************************************/
+
+#define gcmIS_ERROR(status) (status < 0)
+#define gcmNO_ERROR(status) (status >= 0)
+#define gcmIS_SUCCESS(status) (status == gcvSTATUS_OK)
+
+/******************************************************************************\
+********************************* Field Macros *********************************
+\******************************************************************************/
+
+#define __gcmSTART(reg_field) \
+ (0 ? reg_field)
+
+#define __gcmEND(reg_field) \
+ (1 ? reg_field)
+
+#define __gcmGETSIZE(reg_field) \
+ (__gcmEND(reg_field) - __gcmSTART(reg_field) + 1)
+
+#define __gcmALIGN(data, reg_field) \
+ (((gctUINT32) (data)) << __gcmSTART(reg_field))
+
+#define __gcmMASK(reg_field) \
+ ((gctUINT32) ((__gcmGETSIZE(reg_field) == 32) \
+ ? ~0 \
+ : (~(~0 << __gcmGETSIZE(reg_field)))))
+
+/*******************************************************************************
+**
+** gcmFIELDMASK
+**
+** Get aligned field mask.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+*/
+#define gcmFIELDMASK(reg, field) \
+( \
+ __gcmALIGN(__gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+** gcmGETFIELD
+**
+** Extract the value of a field from specified data.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+*/
+#define gcmGETFIELD(data, reg, field) \
+( \
+ ((((gctUINT32) (data)) >> __gcmSTART(reg##_##field)) \
+ & __gcmMASK(reg##_##field)) \
+)
+
+/*******************************************************************************
+**
+** gcmSETFIELD
+**
+** Set the value of a field within specified data.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Value for field.
+*/
+#define gcmSETFIELD(data, reg, field, value) \
+( \
+ (((gctUINT32) (data)) \
+ & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
+ | __gcmALIGN((gctUINT32) (value) \
+ & __gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+** gcmSETFIELDVALUE
+**
+** Set the value of a field within specified data with a
+** predefined value.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Name of the value within the field.
+*/
+#define gcmSETFIELDVALUE(data, reg, field, value) \
+( \
+ (((gctUINT32) (data)) \
+ & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
+ | __gcmALIGN(reg##_##field##_##value \
+ & __gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+** gcmGETMASKEDFIELDMASK
+**
+** Determine field mask of a masked field.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+*/
+#define gcmGETMASKEDFIELDMASK(reg, field) \
+( \
+ gcmSETFIELD(0, reg, field, ~0) | \
+ gcmSETFIELD(0, reg, MASK_ ## field, ~0) \
+)
+
+/*******************************************************************************
+**
+** gcmSETMASKEDFIELD
+**
+** Set the value of a masked field with specified data.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+** value Value for field.
+*/
+#define gcmSETMASKEDFIELD(reg, field, value) \
+( \
+ gcmSETFIELD (~0, reg, field, value) & \
+ gcmSETFIELDVALUE(~0, reg, MASK_ ## field, ENABLED) \
+)
+
+/*******************************************************************************
+**
+** gcmSETMASKEDFIELDVALUE
+**
+** Set the value of a masked field with specified data.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+** value Value for field.
+*/
+#define gcmSETMASKEDFIELDVALUE(reg, field, value) \
+( \
+ gcmSETFIELDVALUE(~0, reg, field, value) & \
+ gcmSETFIELDVALUE(~0, reg, MASK_ ## field, ENABLED) \
+)
+
+/*******************************************************************************
+**
+** gcmVERIFYFIELDVALUE
+**
+** Verify if the value of a field within specified data equals a
+** predefined value.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Name of the value within the field.
+*/
+#define gcmVERIFYFIELDVALUE(data, reg, field, value) \
+( \
+ (((gctUINT32) (data)) >> __gcmSTART(reg##_##field) & \
+ __gcmMASK(reg##_##field)) \
+ == \
+ (reg##_##field##_##value & __gcmMASK(reg##_##field)) \
+)
+
+/*******************************************************************************
+** Bit field macros.
+*/
+
+#define __gcmSTARTBIT(Field) \
+ ( 1 ? Field )
+
+#define __gcmBITSIZE(Field) \
+ ( 0 ? Field )
+
+#define __gcmBITMASK(Field) \
+( \
+ (1 << __gcmBITSIZE(Field)) - 1 \
+)
+
+#define gcmGETBITS(Value, Type, Field) \
+( \
+ ( ((Type) (Value)) >> __gcmSTARTBIT(Field) ) \
+ & \
+ __gcmBITMASK(Field) \
+)
+
+#define gcmSETBITS(Value, Type, Field, NewValue) \
+( \
+ ( ((Type) (Value)) \
+ & ~(__gcmBITMASK(Field) << __gcmSTARTBIT(Field)) \
+ ) \
+ | \
+ ( ( ((Type) (NewValue)) \
+ & __gcmBITMASK(Field) \
+ ) << __gcmSTARTBIT(Field) \
+ ) \
+)
+
+/*******************************************************************************
+**
+** gcmISINREGRANGE
+**
+** Verify whether the specified address is in the register range.
+**
+** ARGUMENTS:
+**
+** Address Address to be verified.
+** Name Name of a register.
+*/
+
+#define gcmISINREGRANGE(Address, Name) \
+( \
+ ((Address & (~0U << Name ## _LSB)) == (Name ## _Address >> 2)) \
+)
+
+/******************************************************************************\
+******************************** Ceiling Macro ********************************
+\******************************************************************************/
+#define gcmCEIL(x) ((x - (gctUINT32)x) == 0 ? (gctUINT32)x : (gctUINT32)x + 1)
+
+/******************************************************************************\
+******************************** Min/Max Macros ********************************
+\******************************************************************************/
+
+#define gcmMIN(x, y) (((x) <= (y)) ? (x) : (y))
+#define gcmMAX(x, y) (((x) >= (y)) ? (x) : (y))
+#define gcmCLAMP(x, min, max) (((x) < (min)) ? (min) : \
+ ((x) > (max)) ? (max) : (x))
+#define gcmABS(x) (((x) < 0) ? -(x) : (x))
+#define gcmNEG(x) (((x) < 0) ? (x) : -(x))
+
+/******************************************************************************\
+******************************** Bit Macro ********************************
+\******************************************************************************/
+#define gcmBITSET(x, y) ((x) & (y))
+/*******************************************************************************
+**
+** gcmPTR2INT
+**
+** Convert a pointer to an integer value.
+**
+** ARGUMENTS:
+**
+** p Pointer value.
+*/
+#define gcmPTR2INT(p) \
+( \
+ (gctUINTPTR_T) (p) \
+)
+
+#define gcmPTR2INT32(p) \
+( \
+ (gctUINT32)(gctUINTPTR_T) (p) \
+)
+
+/*******************************************************************************
+**
+** gcmINT2PTR
+**
+** Convert an integer value into a pointer.
+**
+** ARGUMENTS:
+**
+** v Integer value.
+*/
+
+#define gcmINT2PTR(i) \
+( \
+ (gctPOINTER) (gctUINTPTR_T)(i) \
+)
+
+/*******************************************************************************
+**
+** gcmOFFSETOF
+**
+** Compute the byte offset of a field inside a structure.
+**
+** ARGUMENTS:
+**
+** s Structure name.
+** field Field name.
+*/
+#define gcmOFFSETOF(s, 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) | \
+ (((gctUINT32)(x) & (gctUINT32)0x00FF0000UL) >> 8) | \
+ (((gctUINT32)(x) & (gctUINT32)0xFF000000UL) >> 24)))
+
+/*******************************************************************************
+***** Database ****************************************************************/
+
+typedef struct _gcsDATABASE_COUNTERS
+{
+ /* Number of currently allocated bytes. */
+ gctUINT64 bytes;
+
+ /* Maximum number of bytes allocated (memory footprint). */
+ gctUINT64 maxBytes;
+
+ /* Total number of bytes allocated. */
+ gctUINT64 totalBytes;
+
+ /* The numbers of times video memory was allocated. */
+ gctUINT32 allocCount;
+
+ /* The numbers of times video memory was freed. */
+ gctUINT32 freeCount;
+}
+gcsDATABASE_COUNTERS;
+
+typedef struct _gcuDATABASE_INFO
+{
+ /* Counters. */
+ gcsDATABASE_COUNTERS counters;
+
+ /* Time value. */
+ gctUINT64 time;
+}
+gcuDATABASE_INFO;
+
+/*******************************************************************************
+***** Frame database **********************************************************/
+
+/* gcsHAL_FRAME_INFO */
+typedef struct _gcsHAL_FRAME_INFO
+{
+ /* Current timer tick. */
+ OUT gctUINT64 ticks;
+
+ /* Bandwidth counters. */
+ OUT gctUINT readBytes8[8];
+ OUT gctUINT writeBytes8[8];
+
+ /* Counters. */
+ OUT gctUINT cycles[8];
+ OUT gctUINT idleCycles[8];
+ OUT gctUINT mcCycles[8];
+ OUT gctUINT readRequests[8];
+ OUT gctUINT writeRequests[8];
+
+ /* 3D counters. */
+ OUT gctUINT vertexCount;
+ OUT gctUINT primitiveCount;
+ OUT gctUINT rejectedPrimitives;
+ OUT gctUINT culledPrimitives;
+ OUT gctUINT clippedPrimitives;
+ OUT gctUINT outPrimitives;
+ OUT gctUINT inPrimitives;
+ OUT gctUINT culledQuadCount;
+ OUT gctUINT totalQuadCount;
+ OUT gctUINT quadCount;
+ OUT gctUINT totalPixelCount;
+
+ /* PE counters. */
+ OUT gctUINT colorKilled[8];
+ OUT gctUINT colorDrawn[8];
+ OUT gctUINT depthKilled[8];
+ OUT gctUINT depthDrawn[8];
+
+ /* Shader counters. */
+ OUT gctUINT shaderCycles;
+ OUT gctUINT vsInstructionCount;
+ OUT gctUINT vsTextureCount;
+ OUT gctUINT psInstructionCount;
+ OUT gctUINT psTextureCount;
+
+ /* Texture counters. */
+ OUT gctUINT bilinearRequests;
+ OUT gctUINT trilinearRequests;
+ OUT gctUINT txBytes8;
+ OUT gctUINT txHitCount;
+ OUT gctUINT txMissCount;
+}
+gcsHAL_FRAME_INFO;
+
+#if gcdLINK_QUEUE_SIZE
+typedef struct _gckLINKDATA * gckLINKDATA;
+struct _gckLINKDATA
+{
+ gctUINT32 start;
+ gctUINT32 end;
+ gctUINT32 pid;
+ gctUINT32 linkLow;
+ gctUINT32 linkHigh;
+};
+
+typedef struct _gckLINKQUEUE * gckLINKQUEUE;
+struct _gckLINKQUEUE
+{
+ struct _gckLINKDATA data[gcdLINK_QUEUE_SIZE];
+ gctUINT32 rear;
+ gctUINT32 front;
+ gctUINT32 count;
+};
+#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
+
+#endif /* __gc_hal_types_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
new file mode 100644
index 000000000000..ed77d1aa8cde
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_version_h_
+#define __gc_hal_version_h_
+
+#define gcvVERSION_MAJOR 5
+
+#define gcvVERSION_MINOR 0
+
+#define gcvVERSION_PATCH 11
+
+#define gcvVERSION_BUILD 33433
+
+#define gcvVERSION_STRING "5.0.11.p7.33433"
+
+#endif /* __gc_hal_version_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h
new file mode 100644
index 000000000000..e33d895d1ce2
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h
@@ -0,0 +1,931 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_vg_h_
+#define __gc_hal_vg_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include "gc_hal_rename.h"
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+#include "gc_hal_base.h"
+
+#if gcdENABLE_VG
+
+/* Thread routine type. */
+#if defined(LINUX)
+ typedef gctINT gctTHREADFUNCRESULT;
+ typedef gctPOINTER gctTHREADFUNCPARAMETER;
+# define gctTHREADFUNCTYPE
+#elif defined(WIN32)
+ typedef gctUINT gctTHREADFUNCRESULT;
+ typedef gctPOINTER gctTHREADFUNCPARAMETER;
+# define gctTHREADFUNCTYPE __stdcall
+#elif defined(__QNXNTO__)
+ typedef void * gctTHREADFUNCRESULT;
+ typedef gctPOINTER gctTHREADFUNCPARAMETER;
+# define gctTHREADFUNCTYPE
+#endif
+
+typedef gctTHREADFUNCRESULT (gctTHREADFUNCTYPE * gctTHREADFUNC) (
+ gctTHREADFUNCPARAMETER ThreadParameter
+ );
+
+
+#if defined(gcvDEBUG)
+# undef gcvDEBUG
+#endif
+
+#define gcdFORCE_DEBUG 0
+#define gcdFORCE_MESSAGES 0
+
+
+#if DBG || defined(DEBUG) || defined(_DEBUG) || gcdFORCE_DEBUG
+# define gcvDEBUG 1
+#else
+# define gcvDEBUG 0
+#endif
+
+#define _gcmERROR_RETURN(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
+ status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+ return status; \
+ } \
+ do { } while (gcvFALSE)
+
+#define gcmERROR_RETURN(func) _gcmERROR_RETURN(gcm, func)
+
+#define gcmLOG_LOCATION()
+
+#define gcmkIS_ERROR(status) (status < 0)
+
+#define gcmALIGNDOWN(n, align) \
+( \
+ (n) & ~((align) - 1) \
+)
+
+#define gcmIS_VALID_INDEX(Index, Array) \
+ (((gctUINT) (Index)) < gcmCOUNTOF(Array))
+
+
+#define gcmIS_NAN(x) \
+( \
+ ((* (gctUINT32_PTR) &(x)) & 0x7FFFFFFF) == 0x7FFFFFFF \
+)
+
+#define gcmLERP(v1, v2, w) \
+ ((v1) * (w) + (v2) * (1.0f - (w)))
+
+#define gcmINTERSECT(Start1, Start2, Length) \
+ (gcmABS((Start1) - (Start2)) < (Length))
+
+/*******************************************************************************
+**
+** gcmERR_GOTO
+**
+** Prints a message and terminates the current loop on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** Function
+** Function to evaluate.
+*/
+
+#define gcmERR_GOTO(Function) \
+ status = Function; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ gcmTRACE( \
+ gcvLEVEL_ERROR, \
+ "gcmERR_GOTO: status=%d @ line=%d in function %s.\n", \
+ status, __LINE__, __FUNCTION__ \
+ ); \
+ goto ErrorHandler; \
+ }
+
+#if gcvDEBUG || gcdFORCE_MESSAGES
+# define gcmVERIFY_BOOLEAN(Expression) \
+ gcmASSERT( \
+ ( (Expression) == gcvFALSE ) || \
+ ( (Expression) == gcvTRUE ) \
+ )
+#else
+# define gcmVERIFY_BOOLEAN(Expression)
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFYFIELDFIT
+**
+** Verify whether the value fits in the field.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Value for field.
+*/
+#define gcmVERIFYFIELDFIT(reg, field, value) \
+ gcmASSERT( \
+ (value) <= gcmFIELDMAX(reg, field) \
+ )
+/*******************************************************************************
+**
+** gcmFIELDMAX
+**
+** Get field maximum value.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+*/
+#define gcmFIELDMAX(reg, field) \
+( \
+ (gctUINT32) \
+ ( \
+ (__gcmGETSIZE(reg##_##field) == 32) \
+ ? ~0 \
+ : (~(~0 << __gcmGETSIZE(reg##_##field))) \
+ ) \
+)
+
+
+/* ANSI C does not have the 'f' functions, define replacements here. */
+#define gcmSINF(x) ((gctFLOAT) sin(x))
+#define gcmCOSF(x) ((gctFLOAT) cos(x))
+#define gcmASINF(x) ((gctFLOAT) asin(x))
+#define gcmACOSF(x) ((gctFLOAT) acos(x))
+#define gcmSQRTF(x) ((gctFLOAT) sqrt(x))
+#define gcmFABSF(x) ((gctFLOAT) fabs(x))
+#define gcmFMODF(x, y) ((gctFLOAT) fmod((x), (y)))
+#define gcmCEILF(x) ((gctFLOAT) ceil(x))
+#define gcmFLOORF(x) ((gctFLOAT) floor(x))
+
+
+
+/* Fixed point constants. */
+#define gcvZERO_X ((gctFIXED_POINT) 0x00000000)
+#define gcvHALF_X ((gctFIXED_POINT) 0x00008000)
+#define gcvONE_X ((gctFIXED_POINT) 0x00010000)
+#define gcvNEGONE_X ((gctFIXED_POINT) 0xFFFF0000)
+#define gcvTWO_X ((gctFIXED_POINT) 0x00020000)
+
+/* Integer constants. */
+#define gcvMAX_POS_INT ((gctINT) 0x7FFFFFFF)
+#define gcvMAX_NEG_INT ((gctINT) 0x80000000)
+
+/* Float constants. */
+#define gcvMAX_POS_FLOAT ((gctFLOAT) 3.4028235e+038)
+#define gcvMAX_NEG_FLOAT ((gctFLOAT) -3.4028235e+038)
+
+/******************************************************************************\
+***************************** Miscellaneous Macro ******************************
+\******************************************************************************/
+
+#define gcmKB2BYTES(Kilobyte) \
+( \
+ (Kilobyte) << 10 \
+)
+
+#define gcmMB2BYTES(Megabyte) \
+( \
+ (Megabyte) << 20 \
+)
+
+#define gcmMAT(Matrix, Row, Column) \
+( \
+ (Matrix) [(Row) * 3 + (Column)] \
+)
+
+#define gcmMAKE2CHAR(Char1, Char2) \
+( \
+ ((gctUINT16) (gctUINT8) (Char1) << 0) | \
+ ((gctUINT16) (gctUINT8) (Char2) << 8) \
+)
+
+#define gcmMAKE4CHAR(Char1, Char2, Char3, Char4) \
+( \
+ ((gctUINT32)(gctUINT8) (Char1) << 0) | \
+ ((gctUINT32)(gctUINT8) (Char2) << 8) | \
+ ((gctUINT32)(gctUINT8) (Char3) << 16) | \
+ ((gctUINT32)(gctUINT8) (Char4) << 24) \
+)
+
+/* some platforms need to fix the physical address for HW to access*/
+#define gcmFIXADDRESS(address) \
+(\
+ (address)\
+)
+
+#define gcmkFIXADDRESS(address) \
+(\
+ (address)\
+)
+
+/******************************************************************************\
+****************************** Kernel Debug Macro ******************************
+\******************************************************************************/
+
+/* Set signal to signaled state for specified process. */
+gceSTATUS
+gckOS_SetSignal(
+ IN gckOS Os,
+ IN gctHANDLE Process,
+ IN gctSIGNAL Signal
+ );
+
+/* Return the kernel logical pointer for the given physical one. */
+gceSTATUS
+gckOS_GetKernelLogical(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ );
+
+/* Return the kernel logical pointer for the given physical one. */
+gceSTATUS
+gckOS_GetKernelLogicalEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----------------------------- Semaphore Object -----------------------------*/
+
+/* Increment the value of a semaphore. */
+gceSTATUS
+gckOS_IncrementSemaphore(
+ IN gckOS Os,
+ IN gctSEMAPHORE Semaphore
+ );
+
+/* Decrement the value of a semaphore (waiting might occur). */
+gceSTATUS
+gckOS_DecrementSemaphore(
+ IN gckOS Os,
+ IN gctSEMAPHORE Semaphore
+ );
+
+
+/*----------------------------------------------------------------------------*/
+/*------------------------------- Thread Object ------------------------------*/
+
+/* Start a thread. */
+gceSTATUS
+gckOS_StartThread(
+ IN gckOS Os,
+ IN gctTHREADFUNC ThreadFunction,
+ IN gctPOINTER ThreadParameter,
+ OUT gctTHREAD * Thread
+ );
+
+/* Stop a thread. */
+gceSTATUS
+gckOS_StopThread(
+ IN gckOS Os,
+ IN gctTHREAD Thread
+ );
+
+/* Verify whether the thread is still running. */
+gceSTATUS
+gckOS_VerifyThread(
+ IN gckOS Os,
+ IN gctTHREAD Thread
+ );
+
+
+/* Construct a new gckVGKERNEL object. */
+gceSTATUS
+gckVGKERNEL_Construct(
+ IN gckOS Os,
+ IN gctPOINTER Context,
+ IN gckKERNEL inKernel,
+ OUT gckVGKERNEL * Kernel
+ );
+
+/* Destroy an gckVGKERNEL object. */
+gceSTATUS
+gckVGKERNEL_Destroy(
+ IN gckVGKERNEL Kernel
+ );
+
+/* Allocate linear video memory. */
+gceSTATUS
+gckVGKERNEL_AllocateLinearMemory(
+ IN gckKERNEL Kernel,
+ IN OUT gcePOOL * Pool,
+ IN gctSIZE_T Bytes,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+ OUT gcuVIDMEM_NODE_PTR * Node
+ );
+
+/* Unmap memory. */
+gceSTATUS
+gckKERNEL_UnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Dispatch a user-level command. */
+gceSTATUS
+gckVGKERNEL_Dispatch(
+ IN gckKERNEL Kernel,
+ IN gctBOOL FromUser,
+ IN OUT struct _gcsHAL_INTERFACE * Interface
+ );
+
+/* Query command buffer requirements. */
+gceSTATUS
+gckKERNEL_QueryCommandBuffer(
+ IN gckKERNEL Kernel,
+ OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+ );
+
+/******************************************************************************\
+******************************* gckVGHARDWARE Object ******************************
+\******************************************************************************/
+
+/* Construct a new gckVGHARDWARE object. */
+gceSTATUS
+gckVGHARDWARE_Construct(
+ IN gckOS Os,
+ OUT gckVGHARDWARE * Hardware
+ );
+
+/* Destroy an gckVGHARDWARE object. */
+gceSTATUS
+gckVGHARDWARE_Destroy(
+ IN gckVGHARDWARE Hardware
+ );
+
+/* Query system memory requirements. */
+gceSTATUS
+gckVGHARDWARE_QuerySystemMemory(
+ IN gckVGHARDWARE Hardware,
+ OUT gctSIZE_T * SystemSize,
+ OUT gctUINT32 * SystemBaseAddress
+ );
+
+/* Build virtual address. */
+gceSTATUS
+gckVGHARDWARE_BuildVirtualAddress(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Index,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ );
+
+/* Kickstart the command processor. */
+gceSTATUS
+gckVGHARDWARE_Execute(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Address,
+ IN gctUINT32 Count
+ );
+
+/* Query the available memory. */
+gceSTATUS
+gckVGHARDWARE_QueryMemory(
+ IN gckVGHARDWARE Hardware,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctUINT32 * InternalBaseAddress,
+ OUT gctUINT32 * InternalAlignment,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctUINT32 * ExternalBaseAddress,
+ OUT gctUINT32 * ExternalAlignment,
+ OUT gctUINT32 * HorizontalTileSize,
+ OUT gctUINT32 * VerticalTileSize
+ );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gckVGHARDWARE_QueryChipIdentity(
+ IN gckVGHARDWARE Hardware,
+ OUT gceCHIPMODEL* ChipModel,
+ OUT gctUINT32* ChipRevision,
+ OUT gctUINT32* ChipFeatures,
+ OUT gctUINT32* ChipMinorFeatures,
+ OUT gctUINT32* ChipMinorFeatures1
+ );
+
+/* Convert an API format. */
+gceSTATUS
+gckVGHARDWARE_ConvertFormat(
+ IN gckVGHARDWARE Hardware,
+ IN gceSURF_FORMAT Format,
+ OUT gctUINT32 * BitsPerPixel,
+ OUT gctUINT32 * BytesPerTile
+ );
+
+/* Split a harwdare specific address into API stuff. */
+gceSTATUS
+gckVGHARDWARE_SplitMemory(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ );
+
+/* Align size to tile boundary. */
+gceSTATUS
+gckVGHARDWARE_AlignToTile(
+ IN gckVGHARDWARE Hardware,
+ IN gceSURF_TYPE Type,
+ IN OUT gctUINT32_PTR Width,
+ IN OUT gctUINT32_PTR Height
+ );
+
+/* Convert logical address to hardware specific address. */
+gceSTATUS
+gckVGHARDWARE_ConvertLogical(
+ IN gckVGHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctBOOL InUserSpace,
+ OUT gctUINT32 * Address
+ );
+
+/* Program MMU. */
+gceSTATUS
+gckVGHARDWARE_SetMMU(
+ IN gckVGHARDWARE Hardware,
+ IN gctPOINTER Logical
+ );
+
+/* Flush the MMU. */
+gceSTATUS
+gckVGHARDWARE_FlushMMU(
+ IN gckVGHARDWARE Hardware
+ );
+
+/* Get idle register. */
+gceSTATUS
+gckVGHARDWARE_GetIdle(
+ IN gckVGHARDWARE Hardware,
+ OUT gctUINT32 * Data
+ );
+
+/* Flush the caches. */
+gceSTATUS
+gckVGHARDWARE_Flush(
+ IN gckVGHARDWARE Hardware,
+ IN gceKERNEL_FLUSH Flush,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Enable/disable fast clear. */
+gceSTATUS
+gckVGHARDWARE_SetFastClear(
+ IN gckVGHARDWARE Hardware,
+ IN gctINT Enable
+ );
+
+gceSTATUS
+gckVGHARDWARE_ReadInterrupt(
+ IN gckVGHARDWARE Hardware,
+ OUT gctUINT32_PTR IDs
+ );
+
+/* Power management. */
+gceSTATUS
+gckVGHARDWARE_SetPowerManagementState(
+ IN gckVGHARDWARE Hardware,
+ IN gceCHIPPOWERSTATE State
+ );
+
+gceSTATUS
+gckVGHARDWARE_QueryPowerManagementState(
+ IN gckVGHARDWARE Hardware,
+ OUT gceCHIPPOWERSTATE* State
+ );
+
+gceSTATUS
+gckVGHARDWARE_SetPowerManagement(
+ IN gckVGHARDWARE Hardware,
+ IN gctBOOL PowerManagement
+ );
+
+gceSTATUS
+gckVGHARDWARE_SetPowerOffTimeout(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Timeout
+ );
+
+gceSTATUS
+gckVGHARDWARE_QueryPowerOffTimeout(
+ IN gckVGHARDWARE Hardware,
+ OUT gctUINT32* Timeout
+ );
+
+gceSTATUS
+gckVGHARDWARE_QueryIdle(
+ IN gckVGHARDWARE Hardware,
+ OUT gctBOOL_PTR IsIdle
+ );
+/******************************************************************************\
+*************************** Command Buffer Structures **************************
+\******************************************************************************/
+
+/* Vacant command buffer marker. */
+#define gcvVACANT_BUFFER ((gcsCOMPLETION_SIGNAL_PTR) ((gctSIZE_T)1))
+
+/* Command buffer header. */
+typedef struct _gcsCMDBUFFER * gcsCMDBUFFER_PTR;
+typedef struct _gcsCMDBUFFER
+{
+ /* Pointer to the completion signal. */
+ gcsCOMPLETION_SIGNAL_PTR completion;
+
+ /* The user sets this to the node of the container buffer whitin which
+ this particular command buffer resides. The kernel sets this to the
+ node of the internally allocated buffer. */
+ gcuVIDMEM_NODE_PTR node;
+
+ /* Command buffer hardware address. */
+ gctUINT32 address;
+
+ /* The offset of the buffer from the beginning of the header. */
+ gctUINT32 bufferOffset;
+
+ /* Size of the area allocated for the data portion of this particular
+ command buffer (headers and tail reserves are excluded). */
+ gctUINT32 size;
+
+ /* Offset into the buffer [0..size]; reflects exactly how much data has
+ been put into the command buffer. */
+ gctUINT offset;
+
+ /* The number of command units in the buffer for the hardware to
+ execute. */
+ gctUINT32 dataCount;
+
+ /* MANAGED BY : user HAL (gcoBUFFER object).
+ USED BY : user HAL (gcoBUFFER object).
+ Points to the immediate next allocated command buffer. */
+ gcsCMDBUFFER_PTR nextAllocated;
+
+ /* MANAGED BY : user layers (HAL and drivers).
+ USED BY : kernel HAL (gcoBUFFER object).
+ Points to the next subbuffer if any. A family of subbuffers are chained
+ together and are meant to be executed inseparably as a unit. Meaning
+ that context switching cannot occur while a chain of subbuffers is being
+ executed. */
+ gcsCMDBUFFER_PTR nextSubBuffer;
+}
+gcsCMDBUFFER;
+
+/* Command queue element. */
+typedef struct _gcsVGCMDQUEUE
+{
+ /* Pointer to the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer;
+
+ /* Dynamic vs. static command buffer state. */
+ gctBOOL dynamic;
+}
+gcsVGCMDQUEUE;
+
+/* Context map entry. */
+typedef struct _gcsVGCONTEXT_MAP
+{
+ /* State index. */
+ gctUINT32 index;
+
+ /* New state value. */
+ gctUINT32 data;
+
+ /* Points to the next entry in the mod list. */
+ gcsVGCONTEXT_MAP_PTR next;
+}
+gcsVGCONTEXT_MAP;
+
+/* gcsVGCONTEXT structure that holds the current context. */
+typedef struct _gcsVGCONTEXT
+{
+ /* Context ID. */
+ gctUINT64 id;
+
+ /* State caching ebable flag. */
+ gctBOOL stateCachingEnabled;
+
+ /* Current pipe. */
+ gctUINT32 currentPipe;
+
+ /* State map/mod buffer. */
+ 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;
+ gctUINT32_PTR buffer;
+
+ /* Completion signal. */
+ gctHANDLE process;
+ gctSIGNAL signal;
+
+#if defined(__QNXNTO__)
+ gctSIGNAL userSignal;
+ gctINT32 coid;
+ gctINT32 rcvid;
+#endif
+}
+gcsVGCONTEXT;
+
+/* User space task header. */
+typedef struct _gcsTASK * gcsTASK_PTR;
+typedef struct _gcsTASK
+{
+ /* Pointer to the next task for the same interrupt in user space. */
+ gcsTASK_PTR next;
+
+ /* Size of the task data that immediately follows the structure. */
+ gctUINT size;
+
+ /* Task data starts here. */
+ /* ... */
+}
+gcsTASK;
+
+/* User space task master table entry. */
+typedef struct _gcsTASK_MASTER_ENTRY * gcsTASK_MASTER_ENTRY_PTR;
+typedef struct _gcsTASK_MASTER_ENTRY
+{
+ /* Pointers to the head and to the tail of the task chain. */
+ gcsTASK_PTR head;
+ gcsTASK_PTR tail;
+}
+gcsTASK_MASTER_ENTRY;
+
+/* User space task master table entry. */
+typedef struct _gcsTASK_MASTER_TABLE
+{
+ /* Table with one entry per block. */
+ gcsTASK_MASTER_ENTRY table[gcvBLOCK_COUNT];
+
+ /* The total number of tasks sckeduled. */
+ gctUINT count;
+
+ /* The total size of event data in bytes. */
+ gctUINT size;
+
+#if defined(__QNXNTO__)
+ gctINT32 coid;
+ gctINT32 rcvid;
+#endif
+}
+gcsTASK_MASTER_TABLE;
+
+/******************************************************************************\
+***************************** gckVGINTERRUPT Object ******************************
+\******************************************************************************/
+
+typedef struct _gckVGINTERRUPT * gckVGINTERRUPT;
+
+typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
+ IN gckVGKERNEL Kernel
+ );
+
+gceSTATUS
+gckVGINTERRUPT_Construct(
+ IN gckVGKERNEL Kernel,
+ OUT gckVGINTERRUPT * Interrupt
+ );
+
+gceSTATUS
+gckVGINTERRUPT_Destroy(
+ IN gckVGINTERRUPT Interrupt
+ );
+
+gceSTATUS
+gckVGINTERRUPT_Enable(
+ IN gckVGINTERRUPT Interrupt,
+ IN OUT gctINT32_PTR Id,
+ IN gctINTERRUPT_HANDLER Handler
+ );
+
+gceSTATUS
+gckVGINTERRUPT_Disable(
+ IN gckVGINTERRUPT Interrupt,
+ IN gctINT32 Id
+ );
+
+#ifndef __QNXNTO__
+
+gceSTATUS
+gckVGINTERRUPT_Enque(
+ IN gckVGINTERRUPT Interrupt
+ );
+
+#else
+
+gceSTATUS
+gckVGINTERRUPT_Enque(
+ IN gckVGINTERRUPT Interrupt,
+ OUT gckOS *Os,
+ OUT gctSEMAPHORE *Semaphore
+ );
+
+#endif
+
+gceSTATUS
+gckVGINTERRUPT_DumpState(
+ IN gckVGINTERRUPT Interrupt
+ );
+
+
+/******************************************************************************\
+******************************* gckVGCOMMAND Object *******************************
+\******************************************************************************/
+
+typedef struct _gckVGCOMMAND * gckVGCOMMAND;
+
+/* Construct a new gckVGCOMMAND object. */
+gceSTATUS
+gckVGCOMMAND_Construct(
+ IN gckVGKERNEL Kernel,
+ IN gctUINT TaskGranularity,
+ IN gctUINT QueueSize,
+ OUT gckVGCOMMAND * Command
+ );
+
+/* Destroy an gckVGCOMMAND object. */
+gceSTATUS
+gckVGCOMMAND_Destroy(
+ IN gckVGCOMMAND Command
+ );
+
+/* Query command buffer attributes. */
+gceSTATUS
+gckVGCOMMAND_QueryCommandBuffer(
+ IN gckVGCOMMAND Command,
+ OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+ );
+
+/* Allocate a command queue. */
+gceSTATUS
+gckVGCOMMAND_Allocate(
+ IN gckVGCOMMAND Command,
+ IN gctSIZE_T Size,
+ OUT gcsCMDBUFFER_PTR * CommandBuffer,
+ OUT gctPOINTER * Data
+ );
+
+/* Release memory held by the command queue. */
+gceSTATUS
+gckVGCOMMAND_Free(
+ IN gckVGCOMMAND Command,
+ IN gcsCMDBUFFER_PTR CommandBuffer
+ );
+
+/* Schedule the command queue for execution. */
+gceSTATUS
+gckVGCOMMAND_Execute(
+ IN gckVGCOMMAND Command,
+ IN gcsCMDBUFFER_PTR CommandBuffer
+ );
+
+/* Commit a buffer to the command queue. */
+gceSTATUS
+gckVGCOMMAND_Commit(
+ IN gckVGCOMMAND Command,
+ IN gcsVGCONTEXT_PTR Context,
+ IN gcsVGCMDQUEUE_PTR Queue,
+ IN gctUINT EntryCount,
+ IN gcsTASK_MASTER_TABLE_PTR TaskTable
+ );
+
+/******************************************************************************\
+********************************* gckVGMMU Object ********************************
+\******************************************************************************/
+
+typedef struct _gckVGMMU * gckVGMMU;
+
+/* Construct a new gckVGMMU object. */
+gceSTATUS
+gckVGMMU_Construct(
+ IN gckVGKERNEL Kernel,
+ IN gctUINT32 MmuSize,
+ OUT gckVGMMU * Mmu
+ );
+
+/* Destroy an gckVGMMU object. */
+gceSTATUS
+gckVGMMU_Destroy(
+ IN gckVGMMU Mmu
+ );
+
+/* Allocate pages inside the MMU. */
+gceSTATUS
+gckVGMMU_AllocatePages(
+ IN gckVGMMU Mmu,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ );
+
+/* Remove a page table from the MMU. */
+gceSTATUS
+gckVGMMU_FreePages(
+ IN gckVGMMU Mmu,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ );
+
+/* Set the MMU page with info. */
+gceSTATUS
+gckVGMMU_SetPage(
+ IN gckVGMMU Mmu,
+ IN gctUINT32 PageAddress,
+ IN gctUINT32 *PageEntry
+ );
+
+/* Flush MMU */
+gceSTATUS
+gckVGMMU_Flush(
+ IN gckVGMMU Mmu
+ );
+
+#endif /* gcdENABLE_VG */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __gc_hal_h_ */
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
index 000000000000..b1df099e7a34
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_allocator_array_h_
+#define __gc_hal_kernel_allocator_array_h_
+
+extern gceSTATUS
+_DefaultAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+
+#ifdef CONFIG_DMA_SHARED_BUFFER
+extern gceSTATUS
+_DmabufAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+#endif
+
+gcsALLOCATOR_DESC allocatorArray[] =
+{
+ /* Default allocator. */
+ gcmkDEFINE_ALLOCATOR_DESC("default", _DefaultAlloctorInit),
+
+#ifdef CONFIG_DMA_SHARED_BUFFER
+ /* Dmabuf allocator. */
+ gcmkDEFINE_ALLOCATOR_DESC("dmabuf", _DmabufAlloctorInit),
+#endif
+};
+
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c
new file mode 100644
index 000000000000..023ca2e696ac
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c
@@ -0,0 +1,353 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_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/dma-buf.h>
+#include <linux/platform_device.h>
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+/* Descriptor of a dma_buf imported. */
+typedef struct _gcsDMABUF
+{
+ struct dma_buf *dmabuf;
+ struct dma_buf_attachment *attachment;
+ struct sg_table *sgtable;
+ unsigned long *pagearray;
+ int handle;
+ int fd;
+}
+gcsDMABUF;
+
+static gceSTATUS
+_DmabufAttach(
+ IN gckALLOCATOR Allocator,
+ IN gcsATTACH_DESC_PTR Desc,
+ IN PLINUX_MDL Mdl
+ )
+{
+ gceSTATUS status;
+
+ gckOS os = Allocator->os;
+
+ int fd = (int) Desc->handle;
+
+ struct dma_buf *dmabuf = NULL;
+ struct sg_table *sgt = NULL;
+ struct dma_buf_attachment *attachment = NULL;
+ int npages = 0;
+ unsigned long *pagearray = NULL;
+ int i, j, k = 0;
+ struct scatterlist *s;
+ gcsDMABUF *gcdmabuf = NULL;
+
+ gcmkHEADER();
+
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Import dma buf handle. */
+ dmabuf = dma_buf_get(fd);
+
+ if (!dmabuf)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ attachment = dma_buf_attach(dmabuf, &os->device->platform->device->dev);
+
+ if (!attachment)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL);
+
+ if (!sgt)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ /* Prepare page array. */
+ /* Get number of pages. */
+ for_each_sg(sgt->sgl, s, sgt->orig_nents, i)
+ {
+ npages += (sg_dma_len(s) + PAGE_SIZE - 1) / PAGE_SIZE;
+ }
+
+ /* Allocate page arrary. */
+ gcmkONERROR(gckOS_Allocate(os, npages * gcmSIZEOF(*pagearray), (gctPOINTER *)&pagearray));
+
+ /* Fill page arrary. */
+ for_each_sg(sgt->sgl, s, sgt->orig_nents, i)
+ {
+ for (j = 0; j < (sg_dma_len(s) + PAGE_SIZE - 1) / PAGE_SIZE; j++)
+ {
+ pagearray[k++] = sg_dma_address(s) + j * PAGE_SIZE;
+ }
+ }
+
+ /* Prepare descriptor. */
+ gcmkONERROR(gckOS_Allocate(os, sizeof(gcsDMABUF), (gctPOINTER *)&gcdmabuf));
+
+ gcdmabuf->fd = fd;
+ gcdmabuf->dmabuf = dmabuf;
+ gcdmabuf->pagearray = pagearray;
+ gcdmabuf->attachment = attachment;
+ gcdmabuf->sgtable = sgt;
+
+ /* Record page number. */
+ Mdl->numPages = npages;
+
+ Mdl->priv = gcdmabuf;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+
+static void
+_DmabufFree(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl
+ )
+{
+ gcsDMABUF *gcdmabuf = Mdl->priv;
+ gckOS os = Allocator->os;
+
+ dma_buf_unmap_attachment(gcdmabuf->attachment, gcdmabuf->sgtable, DMA_BIDIRECTIONAL);
+
+ dma_buf_detach(gcdmabuf->dmabuf, gcdmabuf->attachment);
+
+ dma_buf_put(gcdmabuf->dmabuf);
+
+ gckOS_Free(os, gcdmabuf->pagearray);
+
+ gckOS_Free(os, gcdmabuf);
+}
+
+static gctINT
+_DmabufMapUser(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN PLINUX_MDL_MAP MdlMap,
+ IN gctBOOL Cacheable
+ )
+{
+ gcsDMABUF *gcdmabuf = Mdl->priv;
+ gceSTATUS status;
+ PLINUX_MDL mdl = Mdl;
+ PLINUX_MDL_MAP mdlMap = MdlMap;
+ struct file * file = gcdmabuf->dmabuf->file;
+
+ mdlMap->vmaAddr = (gctSTRING)vm_mmap(file,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+
+ if (IS_ERR(mdlMap->vmaAddr))
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ down_write(&current->mm->mmap_sem);
+
+ mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+ up_write(&current->mm->mmap_sem);
+
+ if (mdlMap->vma == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ return 0;
+
+OnError:
+ return status;
+}
+
+static void
+_DmabufUnmapUser(
+ IN gckALLOCATOR Allocator,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Size
+ )
+{
+ if (unlikely(current->mm == gcvNULL))
+ {
+ /* Do nothing if process is exiting. */
+ return;
+ }
+
+ vm_munmap((unsigned long)Logical, Size);
+}
+
+static gceSTATUS
+_DmabufMapKernel(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ OUT gctPOINTER *Logical
+ )
+{
+ /* Kernel doesn't acess video memory. */
+ return gcvSTATUS_NOT_SUPPORTED;
+
+}
+
+static gceSTATUS
+_DmabufUnmapKernel(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical
+ )
+{
+ /* Kernel doesn't acess video memory. */
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+static gceSTATUS
+_DmabufLogicalToPhysical(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical,
+ IN gctUINT32 ProcessID,
+ OUT gctPHYS_ADDR_T * Physical
+ )
+{
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+
+static gceSTATUS
+_DmabufCache(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical,
+ IN gctUINT32 Bytes,
+ IN gceCACHEOPERATION Operation
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+
+static gceSTATUS
+_DmabufPhysical(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctUINT32 Offset,
+ OUT gctPHYS_ADDR_T * Physical
+ )
+{
+ gcsDMABUF *gcdmabuf = Mdl->priv;
+
+ *Physical = gcdmabuf->pagearray[Offset];
+
+
+ return gcvSTATUS_OK;
+}
+
+/* Default allocator operations. */
+static gcsALLOCATOR_OPERATIONS DmabufAllocatorOperations =
+{
+ .Attach = _DmabufAttach,
+ .Free = _DmabufFree,
+ .MapUser = _DmabufMapUser,
+ .UnmapUser = _DmabufUnmapUser,
+ .MapKernel = _DmabufMapKernel,
+ .UnmapKernel = _DmabufUnmapKernel,
+ .LogicalToPhysical = _DmabufLogicalToPhysical,
+ .Cache = _DmabufCache,
+ .Physical = _DmabufPhysical,
+};
+
+/* Default allocator entry. */
+gceSTATUS
+_DmabufAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ )
+{
+ gceSTATUS status;
+ gckALLOCATOR allocator;
+
+ gcmkONERROR(
+ gckALLOCATOR_Construct(Os, &DmabufAllocatorOperations, &allocator));
+
+ allocator->capability = gcvALLOC_FLAG_DMABUF;
+
+ *Allocator = allocator;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
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
index 000000000000..94ab3fa10b37
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_array.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_allocator_array_h_
+#define __gc_hal_kernel_allocator_array_h_
+
+extern gceSTATUS
+_DefaultAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+
+#if LINUX_CMA_FSL
+extern gceSTATUS
+_CMAFSLAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+#endif
+
+#ifdef CONFIG_DMA_SHARED_BUFFER
+extern gceSTATUS
+_DmabufAlloctorInit(
+ 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),
+
+#ifdef CONFIG_DMA_SHARED_BUFFER
+ /* Dmabuf allocator. */
+ gcmkDEFINE_ALLOCATOR_DESC("dmabuf", _DmabufAlloctorInit),
+#endif
+};
+
+#endif
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
index 000000000000..ddb24c0ab84c
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c
@@ -0,0 +1,446 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_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 gctPHYS_ADDR_T * 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 gctPHYS_ADDR_T * 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
index 000000000000..11c7add772c4
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c
@@ -0,0 +1,972 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_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 gctPHYS_ADDR_T * 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 gctPHYS_ADDR_T * 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->capability = gcvALLOC_FLAG_CONTIGUOUS
+ | gcvALLOC_FLAG_NON_CONTIGUOUS
+ | gcvALLOC_FLAG_CACHEABLE
+ | gcvALLOC_FLAG_MEMLIMIT
+ ;
+
+ *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->Attach)
+ && (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 = 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
index 000000000000..72f7c40598d6
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h
@@ -0,0 +1,470 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_allocator_h_
+#define __gc_hal_kernel_allocator_h_
+
+#include "gc_hal_kernel_linux.h"
+
+typedef struct _gcsALLOCATOR * gckALLOCATOR;
+typedef struct _gcsATTACH_DESC * gcsATTACH_DESC_PTR;
+
+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 gctPHYS_ADDR_T * 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 gctPHYS_ADDR_T * Physical
+ );
+
+ /**************************************************************************
+ **
+ ** Attach
+ **
+ ** Import memory allocated by an external allocator.
+ **
+ ** INPUT:
+ ** gckALLOCATOR Allocator
+ ** Pointer to an gckALLOCATOER object.
+ **
+ ** gctUINT32 Handle
+ ** Handle of the memory.
+ **
+ ** OUTPUT:
+ ** None.
+ **
+ */
+ gceSTATUS (*Attach)(
+ IN gckALLOCATOR Allocator,
+ IN gcsATTACH_DESC_PTR Desc,
+ OUT PLINUX_MDL Mdl
+ );
+}
+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;
+
+typedef struct _gcsATTACH_DESC
+{
+ /* gcvALLOC_FLAG_DMABUF */
+ gctUINT32 handle;
+
+ /* gcvALLOC_FLAG_USERMEMORY */
+ gctPOINTER memory;
+ gctUINT32 physical;
+ gctSIZE_T size;
+}
+gcsATTACH_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
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h
new file mode 100644
index 000000000000..54782fd8ccc8
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_debug_h_
+#define __gc_hal_kernel_debug_h_
+
+#include <gc_hal_kernel_linux.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** OS-dependent Macros *****************************
+\******************************************************************************/
+
+typedef va_list gctARGUMENTS;
+
+#define gcmkARGUMENTS_START(Arguments, Pointer) \
+ va_start(Arguments, Pointer)
+
+#define gcmkARGUMENTS_END(Arguments) \
+ va_end(Arguments)
+
+#define gcmkARGUMENTS_ARG(Arguments, Type) \
+ va_arg(Arguments, Type)
+
+#define gcmkDECLARE_LOCK(__spinLock__) \
+ static DEFINE_SPINLOCK(__spinLock__); \
+ unsigned long __spinLock__##flags = 0;
+
+#define gcmkLOCKSECTION(__spinLock__) \
+ spin_lock_irqsave(&__spinLock__, __spinLock__##flags)
+
+#define gcmkUNLOCKSECTION(__spinLock__) \
+ spin_unlock_irqrestore(&__spinLock__, __spinLock__##flags)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+# define gcmkGETPROCESSID() \
+ task_tgid_vnr(current)
+#else
+# define gcmkGETPROCESSID() \
+ current->tgid
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+# define gcmkGETTHREADID() \
+ task_pid_vnr(current)
+#else
+# define gcmkGETTHREADID() \
+ current->pid
+#endif
+
+#define gcmkOUTPUT_STRING(String) \
+ if(gckDEBUGFS_IsEnabled()) {\
+ while(-ERESTARTSYS == gckDEBUGFS_Print(String));\
+ }else{\
+ printk(String); \
+ }\
+ touch_softlockup_watchdog()
+
+
+#define gcmkSPRINTF(Destination, Size, Message, Value) \
+ snprintf(Destination, Size, Message, Value)
+
+#define gcmkSPRINTF2(Destination, Size, Message, Value1, Value2) \
+ snprintf(Destination, Size, Message, Value1, Value2)
+
+#define gcmkSPRINTF3(Destination, Size, Message, Value1, Value2, Value3) \
+ snprintf(Destination, Size, Message, Value1, Value2, Value3)
+
+#define gcmkVSPRINTF(Destination, Size, Message, Arguments) \
+ vsnprintf(Destination, Size, Message, *((va_list*)Arguments))
+
+#define gcmkSTRCAT(Destination, Size, String) \
+ strncat(Destination, String, Size)
+
+#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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_debug_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c
new file mode 100644
index 000000000000..4af6527df705
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c
@@ -0,0 +1,1189 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/vmalloc.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#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"
+#include "gc_hal_kernel_debug.h"
+
+/*
+ Prequsite:
+
+ 1) Debugfs feature must be enabled in the kernel.
+ 1.a) You can enable this, in the compilation of the uImage, all you have to do is, In the "make menuconfig" part,
+ you have to enable the debugfs in the kernel hacking part of the menu.
+
+ HOW TO USE:
+ 1) insert the driver with the following option logFileSize, Ex: insmod galcore.ko ...... logFileSize=10240
+ This gives a circular buffer of 10 MB
+
+ 2)Usually after inserting the driver, the debug file system is mounted under /sys/kernel/debug/
+
+ 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/gc/galcore_trace
+
+ 4)To write into the debug file system from user side :
+ Ex: echo "hello" > cat /sys/kernel/debug/gc/galcore_trace
+
+ 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:
+
+ 1) Go to /hal/inc/gc_hal_options.h, and enable the following flags:
+ - # define gcdDUMP 1
+ - # define gcdDUMP_IN_KERNEL 1
+ - # define gcdDUMP_COMMAND 1
+
+ 2) Go to /hal/kernel/gc_hal_kernel_command.c and disable the following flag
+ -#define gcdSIMPLE_COMMAND_DUMP 0
+
+ 3) Compile the driver
+ 4) insmod it with the logFileSize option
+ 5) Run an application
+ 6) You can get the dump by cat /sys/kernel/debug/gpu/galcore_trace
+
+ */
+
+/**/
+typedef va_list gctDBGARGS ;
+#define gcmkARGS_START(argument, pointer) va_start(argument, pointer)
+#define gcmkARGS_END(argument) va_end(argument)
+
+#define gcmkDEBUGFS_PRINT(ArgumentSize, Message) \
+ { \
+ gctDBGARGS __arguments__; \
+ gcmkARGS_START(__arguments__, Message); \
+ _debugfs_res = _DebugFSPrint(ArgumentSize, Message, &__arguments__);\
+ gcmkARGS_END(__arguments__); \
+ }
+
+
+gcmkDECLARE_LOCK(traceLock);
+
+/* Debug File System Node Struct. */
+struct _gcsDEBUGFS_Node
+{
+ /*wait queues for read and write operations*/
+#if defined(DECLARE_WAIT_QUEUE_HEAD)
+ wait_queue_head_t read_q , write_q ;
+#else
+ struct wait_queue *read_q , *write_q ;
+#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' */
+ int refcount ; /* Files that have this buffer open */
+ 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 _gcsDEBUGFS_Node *next ;
+
+ caddr_t temp;
+ int tempSize;
+};
+
+/* amount of data in the queue */
+#define gcmkNODE_QLEN(node) ( (node)->write_point >= (node)->read_point ? \
+ (node)->write_point - (node)->read_point : \
+ (node)->size - (node)->read_point + (node)->write_point)
+
+/* byte number of the last byte in the queue */
+#define gcmkNODE_FIRST_EMPTY_BYTE(node) ((node)->offset + gcmkNODE_QLEN(node))
+
+/*Synchronization primitives*/
+#define gcmkNODE_READQ(node) (&((node)->read_q))
+#define gcmkNODE_WRITEQ(node) (&((node)->write_q))
+#define gcmkNODE_SEM(node) (&((node)->sem))
+
+/*Utilities*/
+#define gcmkMIN(x, y) ((x) < (y) ? (x) : y)
+
+/*Debug File System Struct*/
+typedef struct _gcsDEBUGFS_
+{
+ gcsDEBUGFS_Node* linkedlist ;
+ gcsDEBUGFS_Node* currentNode ;
+ int isInited ;
+} gcsDEBUGFS_ ;
+
+/*debug file system*/
+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)
+ **
+ *******************************************************************************/
+
+/*******************************************************************************
+ **
+ ** _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
+ **
+ *******************************************************************************/
+static caddr_t
+_ReadFromNode (
+ gcsDEBUGFS_Node* Node ,
+ size_t *Length ,
+ loff_t *Offset
+ )
+{
+ caddr_t retval ;
+ int bytes_copied = 0 , n , start_point , remaining ;
+
+ /* find the smaller of the total bytes we have available and what
+ * the user is asking for */
+ *Length = gcmkMIN ( *Length , gcmkNODE_QLEN(Node) ) ;
+
+ remaining = * Length ;
+
+ /* Get start point. */
+ start_point = Node->read_point;
+
+ /* allocate memory to return */
+ if (remaining > Node->tempSize)
+ {
+ kfree(Node->temp);
+
+ if ( ( retval = kmalloc ( sizeof (char ) * remaining , GFP_KERNEL ) ) == NULL )
+ return NULL;
+
+ Node->temp = retval;
+ Node->tempSize = remaining;
+ }
+ else
+ {
+ retval = Node->temp;
+ }
+
+ /* copy the (possibly noncontiguous) data to our buffer */
+ while ( remaining )
+ {
+ n = gcmkMIN ( remaining , Node->size - start_point ) ;
+ memcpy ( retval + bytes_copied , Node->data + start_point , n ) ;
+ bytes_copied += n ;
+ remaining -= n ;
+ start_point = ( start_point + n ) % Node->size ;
+ }
+
+ /* advance user's file pointer */
+ Node->read_point = (Node->read_point + * Length) % Node->size ;
+
+ return retval ;
+}
+
+/*******************************************************************************
+ **
+ ** _WriteToNode
+ **
+ ** 1) writes to a circular buffer with wraparound.
+ ** 2)in case of an overflow, it overwrites the oldest unread data.
+ **
+ *********************************************************************************/
+static void
+_WriteToNode (
+ gcsDEBUGFS_Node* Node ,
+ caddr_t Buf ,
+ int Length
+ )
+{
+ int bytes_copied = 0 ;
+ int overflow = 0 ;
+ int n ;
+
+ if ( Length + gcmkNODE_QLEN ( Node ) >= ( Node->size - 1 ) )
+ {
+ overflow = 1 ;
+ }
+
+ while ( Length )
+ {
+ /* how many contiguous bytes are available from the write point to
+ * the end of the circular buffer? */
+ n = gcmkMIN ( Length , Node->size - Node->write_point ) ;
+ memcpy ( Node->data + Node->write_point , Buf + bytes_copied , n ) ;
+ bytes_copied += n ;
+ Length -= n ;
+ Node->write_point = ( Node->write_point + n ) % Node->size ;
+ }
+
+ /* if there is an overflow, reset the read point to read whatever is
+ * the oldest data that we have, that has not yet been
+ * overwritten. */
+ if ( overflow )
+ {
+ Node->read_point = ( Node->write_point + 1 ) % Node->size ;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** PRINTING UTILITY (START)
+ **
+ *******************************************************************************/
+
+/*******************************************************************************
+ **
+ ** _GetArgumentSize
+ **
+ **
+ *******************************************************************************/
+static gctINT
+_GetArgumentSize (
+ IN gctCONST_STRING Message
+ )
+{
+ gctINT i , count ;
+
+ for ( i = 0 , count = 0 ; Message[i] ; i += 1 )
+ {
+ if ( Message[i] == '%' )
+ {
+ count += 1 ;
+ }
+ }
+ return count * sizeof (unsigned int ) ;
+}
+
+/*******************************************************************************
+ **
+ ** _AppendString
+ **
+ **
+ *******************************************************************************/
+static ssize_t
+_AppendString (
+ IN gcsDEBUGFS_Node* Node ,
+ IN gctCONST_STRING String ,
+ IN int Length
+ )
+{
+ int n ;
+
+ /* if the message is longer than the buffer, just take the beginning
+ * of it, in hopes that the reader (if any) will have time to read
+ * before we wrap around and obliterate it */
+ n = gcmkMIN ( Length , Node->size - 1 ) ;
+
+ gcmkLOCKSECTION(traceLock);
+
+ /* now copy it into the circular buffer and free our temp copy */
+ _WriteToNode ( Node , (caddr_t)String , n ) ;
+
+ gcmkUNLOCKSECTION(traceLock);
+
+ return n ;
+}
+
+/*******************************************************************************
+ **
+ ** _DebugFSPrint
+ **
+ **
+ *******************************************************************************/
+static ssize_t
+_DebugFSPrint (
+ IN unsigned int ArgumentSize ,
+ IN const char* Message ,
+ IN gctDBGARGS * Arguments
+
+ )
+{
+ char buffer[MAX_LINE_SIZE] ;
+ int len ;
+ ssize_t res=0;
+
+ len = vsnprintf ( buffer , sizeof (buffer ) , Message , *( va_list * ) Arguments ) ;
+
+ buffer[len] = '\0' ;
+
+ /* Add end-of-line if missing. */
+ if ( buffer[len - 1] != '\n' )
+ {
+ buffer[len ++] = '\n' ;
+ buffer[len] = '\0' ;
+ }
+
+ res = _AppendString ( gc_dbgfs.currentNode , buffer , len ) ;
+
+ wake_up_interruptible ( gcmkNODE_READQ ( gc_dbgfs.currentNode ) ) ; /* blocked in read*/
+
+ return res;
+}
+
+/*******************************************************************************
+ **
+ ** LINUX SYSTEM FUNCTIONS (START)
+ **
+ *******************************************************************************/
+
+/*******************************************************************************
+ **
+ ** find the vivlog structure associated with an inode.
+ ** returns a pointer to the structure if found, NULL if not found
+ **
+ *******************************************************************************/
+static gcsDEBUGFS_Node*
+_GetNodeInfo (
+ IN struct inode *Inode
+ )
+{
+ gcsDEBUGFS_Node* node ;
+
+ if ( Inode == NULL )
+ return NULL ;
+
+ for ( node = gc_dbgfs.linkedlist ; node != NULL ; node = node->next )
+ if ( node->filen->d_inode->i_ino == Inode->i_ino )
+ return node ;
+
+ return NULL ;
+}
+
+/*******************************************************************************
+ **
+ ** _DebugFSRead
+ **
+ *******************************************************************************/
+static ssize_t
+_DebugFSRead (
+ struct file *file ,
+ char __user * buffer ,
+ size_t length ,
+ loff_t * offset
+ )
+{
+ int retval ;
+ caddr_t data_to_return ;
+ gcsDEBUGFS_Node* node ;
+ /* get the metadata about this emlog */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
+ if ( ( node = _GetNodeInfo ( file->f_dentry->d_inode ) ) == NULL )
+#else
+ if ( ( node = _GetNodeInfo ( file_inode(file) ) ) == NULL )
+#endif
+ {
+ printk ( "debugfs_read: record not found\n" ) ;
+ return - EIO ;
+ }
+
+ gcmkLOCKSECTION(traceLock);
+
+ /* wait until there's data available (unless we do nonblocking reads) */
+ while (!gcmkNODE_QLEN(node))
+ {
+ gcmkUNLOCKSECTION(traceLock);
+
+ if ( file->f_flags & O_NONBLOCK )
+ {
+ return - EAGAIN ;
+ }
+
+ if ( wait_event_interruptible ( ( *( gcmkNODE_READQ ( node ) ) ) , ( *offset < gcmkNODE_FIRST_EMPTY_BYTE ( node ) ) ) )
+ {
+ return - ERESTARTSYS ; /* signal: tell the fs layer to handle it */
+ }
+
+ gcmkLOCKSECTION(traceLock);
+ }
+
+ data_to_return = _ReadFromNode ( node , &length , offset ) ;
+
+ gcmkUNLOCKSECTION(traceLock);
+
+ if ( data_to_return == NULL )
+ {
+ retval = 0 ;
+ goto unlock ;
+ }
+ if ( copy_to_user ( buffer , data_to_return , length ) > 0 )
+ {
+ retval = - EFAULT ;
+ }
+ else
+ {
+ retval = length ;
+ }
+unlock:
+
+ wake_up_interruptible ( gcmkNODE_WRITEQ ( node ) ) ;
+ return retval ;
+}
+
+/*******************************************************************************
+ **
+ **_DebugFSWrite
+ **
+ *******************************************************************************/
+static ssize_t
+_DebugFSWrite (
+ struct file *file ,
+ const char __user * buffer ,
+ size_t length ,
+ loff_t * offset
+ )
+{
+ caddr_t message = NULL ;
+ int n ;
+ gcsDEBUGFS_Node*node ;
+
+ /* get the metadata about this log */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
+ if ( ( node = _GetNodeInfo ( file->f_dentry->d_inode ) ) == NULL )
+#else
+ if ( ( node = _GetNodeInfo ( file_inode(file) ) ) == NULL )
+#endif
+ {
+ return - EIO ;
+ }
+
+ if ( down_interruptible ( gcmkNODE_SEM ( node ) ) )
+ {
+ return - ERESTARTSYS ;
+ }
+
+ /* if the message is longer than the buffer, just take the beginning
+ * of it, in hopes that the reader (if any) will have time to read
+ * before we wrap around and obliterate it */
+ n = gcmkMIN ( length , node->size - 1 ) ;
+
+ /* make sure we have the memory for it */
+ if ( ( message = kmalloc ( n , GFP_KERNEL ) ) == NULL )
+ {
+ up ( gcmkNODE_SEM ( node ) ) ;
+ return - ENOMEM ;
+ }
+
+
+ /* copy into our temp buffer */
+ if ( copy_from_user ( message , buffer , n ) > 0 )
+ {
+ up ( gcmkNODE_SEM ( node ) ) ;
+ kfree ( message ) ;
+ return - EFAULT ;
+ }
+
+ /* now copy it into the circular buffer and free our temp copy */
+ _WriteToNode ( node , message , n ) ;
+
+ kfree ( message ) ;
+ up ( gcmkNODE_SEM ( node ) ) ;
+
+ /* wake up any readers that might be waiting for the data. we call
+ * schedule in the vague hope that a reader will run before the
+ * writer's next write, to avoid losing data. */
+ wake_up_interruptible ( gcmkNODE_READQ ( node ) ) ;
+
+ 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");
+}
+
+static int vidmem_show(struct seq_file *file, void *unused)
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gckGALDEVICE device = file->private;
+
+ gckKERNEL kernel = _GetValidKernel(device);
+
+ /* 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
+ **
+ *******************************************************************************/
+static const struct file_operations debugfs_operations = {
+ .owner = THIS_MODULE ,
+ .read = _DebugFSRead ,
+ .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)
+ **
+ *******************************************************************************/
+
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_IsEnabled
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+
+
+gctINT
+gckDEBUGFS_IsEnabled ( void )
+{
+ return gc_dbgfs.isInited ;
+}
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_Initialize
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+
+gctINT
+gckDEBUGFS_Initialize ( void )
+{
+ if ( ! gc_dbgfs.isInited )
+ {
+ gc_dbgfs.linkedlist = gcvNULL ;
+ gc_dbgfs.currentNode = gcvNULL ;
+ gc_dbgfs.isInited = 1 ;
+ }
+ return gc_dbgfs.isInited ;
+}
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_Terminate
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+
+gctINT
+gckDEBUGFS_Terminate ( void )
+{
+ gcsDEBUGFS_Node * next = gcvNULL ;
+ gcsDEBUGFS_Node * temp = gcvNULL ;
+ if ( gc_dbgfs.isInited )
+ {
+ temp = gc_dbgfs.linkedlist ;
+ while ( temp != gcvNULL )
+ {
+ next = temp->next ;
+ gckDEBUGFS_FreeNode ( temp ) ;
+ kfree ( temp ) ;
+ temp = next ;
+ }
+ gc_dbgfs.isInited = 0 ;
+ }
+ return 0 ;
+}
+
+
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_CreateNode
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ ** gckDEBUGFS_FreeNode * Device
+ ** Pointer to a variable receiving the gcsDEBUGFS_Node object pointer on
+ ** success.
+ *********************************************************************************/
+
+gctINT
+gckDEBUGFS_CreateNode (
+ IN gctPOINTER Device,
+ IN gctINT SizeInKB ,
+ IN struct dentry * Root ,
+ IN gctCONST_STRING NodeName ,
+ OUT gcsDEBUGFS_Node **Node
+ )
+{
+ gcsDEBUGFS_Node*node ;
+ /* allocate space for our metadata and initialize it */
+ if ( ( node = kmalloc ( sizeof (gcsDEBUGFS_Node ) , GFP_KERNEL ) ) == NULL )
+ goto struct_malloc_failed ;
+
+ /*Zero it out*/
+ memset ( node , 0 , sizeof (gcsDEBUGFS_Node ) ) ;
+
+ /*Init the sync primitives*/
+#if defined(DECLARE_WAIT_QUEUE_HEAD)
+ init_waitqueue_head ( gcmkNODE_READQ ( node ) ) ;
+#else
+ init_waitqueue ( gcmkNODE_READQ ( node ) ) ;
+#endif
+
+#if defined(DECLARE_WAIT_QUEUE_HEAD)
+ init_waitqueue_head ( gcmkNODE_WRITEQ ( node ) ) ;
+#else
+ init_waitqueue ( gcmkNODE_WRITEQ ( node ) ) ;
+#endif
+ sema_init ( gcmkNODE_SEM ( node ) , 1 ) ;
+ /*End the sync primitives*/
+
+ /*creating the debug file system*/
+ node->parent = Root;
+
+ 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 ;
+
+ node->tempSize = 0;
+ node->temp = NULL;
+
+ /*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 ;
+
+
+data_malloc_failed:
+ kfree ( node ) ;
+struct_malloc_failed:
+ return - ENOMEM ;
+}
+
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_FreeNode
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+void
+gckDEBUGFS_FreeNode (
+ IN gcsDEBUGFS_Node * Node
+ )
+{
+
+ gcsDEBUGFS_Node **ptr ;
+
+ if ( Node == NULL )
+ {
+ printk ( "null passed to free_vinfo\n" ) ;
+ return ;
+ }
+
+ down ( gcmkNODE_SEM ( Node ) ) ;
+ /*free data*/
+ vfree ( Node->data ) ;
+
+ kfree(Node->temp);
+
+ /*Close Debug fs*/
+ if (Node->vidmem)
+ {
+ debugfs_remove(Node->vidmem);
+ }
+
+ if ( Node->filen )
+ {
+ debugfs_remove ( Node->filen ) ;
+ }
+
+ /* now delete the node from the linked list */
+ ptr = & ( gc_dbgfs.linkedlist ) ;
+ while ( *ptr != Node )
+ {
+ if ( ! *ptr )
+ {
+ printk ( "corrupt info list!\n" ) ;
+ break ;
+ }
+ else
+ ptr = & ( ( **ptr ).next ) ;
+ }
+ *ptr = Node->next ;
+ up ( gcmkNODE_SEM ( Node ) ) ;
+}
+
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_SetCurrentNode
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+void
+gckDEBUGFS_SetCurrentNode (
+ IN gcsDEBUGFS_Node * Node
+ )
+{
+ gc_dbgfs.currentNode = Node ;
+}
+
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_GetCurrentNode
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+void
+gckDEBUGFS_GetCurrentNode (
+ OUT gcsDEBUGFS_Node ** Node
+ )
+{
+ *Node = gc_dbgfs.currentNode ;
+}
+
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_Print
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+ssize_t
+gckDEBUGFS_Print (
+ IN gctCONST_STRING Message ,
+ ...
+ )
+{
+ ssize_t _debugfs_res;
+ gcmkDEBUGFS_PRINT ( _GetArgumentSize ( Message ) , Message ) ;
+ return _debugfs_res;
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h
new file mode 100644
index 000000000000..9a15d77747b8
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include <stdarg.h>
+
+#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 _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
+ );
+
+/*******************************************************************************
+ **
+ ** System Related
+ **
+ *******************************************************************************/
+
+gctINT gckDEBUGFS_IsEnabled(void);
+
+gctINT gckDEBUGFS_Initialize(void);
+
+gctINT gckDEBUGFS_Terminate(void);
+
+
+/*******************************************************************************
+ **
+ ** Node Related
+ **
+ *******************************************************************************/
+
+gctINT
+gckDEBUGFS_CreateNode(
+ IN gctPOINTER Device,
+ IN gctINT SizeInKB,
+ IN struct dentry * Root,
+ IN gctCONST_STRING NodeName,
+ OUT gcsDEBUGFS_Node **Node
+ );
+
+void gckDEBUGFS_FreeNode(
+ IN gcsDEBUGFS_Node * Node
+ );
+
+
+
+void gckDEBUGFS_SetCurrentNode(
+ IN gcsDEBUGFS_Node * Node
+ );
+
+
+
+void gckDEBUGFS_GetCurrentNode(
+ OUT gcsDEBUGFS_Node ** Node
+ );
+
+
+ssize_t gckDEBUGFS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#endif
+
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
new file mode 100644
index 000000000000..aae964e9245b
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
@@ -0,0 +1,2898 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mman.h>
+#include <linux/slab.h>
+
+#define _GC_OBJ_ZONE gcvZONE_DEVICE
+
+#define DEBUG_FILE "galcore_trace"
+#define PARENT_FILE "gpu"
+
+#define gcdDEBUG_FS_WARN "Experimental debug entry, may be removed in future release, do NOT rely on it!\n"
+
+#ifdef FLAREON
+ static struct dove_gpio_irq_handler gc500_handle;
+#endif
+
+/******************************************************************************\
+******************************** 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;
+ static gctUINT64 idleTime = 0;
+
+ /* Acquire the database mutex. */
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+
+ if (Kernel->db->idleTime)
+ {
+ /* Record idle time if DB upated. */
+ idleTime = Kernel->db->idleTime;
+ Kernel->db->idleTime = 0;
+ }
+
+ /* Idle time since last call */
+ seq_printf(file, "GPU Idle: %llu ns\n", idleTime);
+
+ /* 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)
+{
+ gcsINFO_NODE *node = m->private;
+ gckGALDEVICE device = node->device;
+ gcsPLATFORM * platform = device->platform;
+ gctCONST_STRING name;
+
+ seq_printf(m, "%s built at %s\n", gcvVERSION_STRING, HOST);
+
+ if (platform->ops->name)
+ {
+ platform->ops->name(platform, &name);
+ seq_printf(m, "Platform path: %s\n", name);
+ }
+ else
+ {
+ seq_printf(m, "Code path: %s\n", __FILE__);
+ }
+
+ return 0 ;
+}
+
+/*******************************************************************************
+**
+** Show PM state timer.
+**
+** Entry is called as 'idle' for compatible reason, it shows more information
+** than idle actually.
+**
+** Start: Start time of this counting period.
+** End: End time of this counting peroid.
+** On: Time GPU stays in gcvPOWER_0N.
+** Off: Time GPU stays in gcvPOWER_0FF.
+** Idle: Time GPU stays in gcvPOWER_IDLE.
+** Suspend: Time GPU stays in gcvPOWER_SUSPEND.
+*/
+static int
+gc_idle_show(struct seq_file *m, void *data)
+{
+ gcsINFO_NODE *node = m->private;
+ gckGALDEVICE device = node->device;
+ gckKERNEL kernel = _GetValidKernel(device);
+
+ gctUINT64 start;
+ gctUINT64 end;
+ gctUINT64 on;
+ gctUINT64 off;
+ gctUINT64 idle;
+ gctUINT64 suspend;
+
+ gckHARDWARE_QueryStateTimer(kernel->hardware, &start, &end, &on, &off, &idle, &suspend);
+
+ /* Idle time since last call */
+ seq_printf(m, "Start: %llu ns\n", start);
+ seq_printf(m, "End: %llu ns\n", end);
+ seq_printf(m, "On: %llu ns\n", on);
+ seq_printf(m, "Off: %llu ns\n", off);
+ seq_printf(m, "Idle: %llu ns\n", idle);
+ seq_printf(m, "Suspend: %llu ns\n", suspend);
+
+ return 0 ;
+}
+
+extern void
+_DumpState(
+ IN gckKERNEL Kernel
+ );
+
+static int
+gc_dump_trigger_show(struct seq_file *m, void *data)
+{
+#if gcdENABLE_3D || gcdENABLE_2D
+ gcsINFO_NODE *node = m->private;
+ gckGALDEVICE device = node->device;
+ gckKERNEL kernel = _GetValidKernel(device);
+#endif
+
+ seq_printf(m, gcdDEBUG_FS_WARN);
+
+#if gcdENABLE_3D || gcdENABLE_2D
+ seq_printf(m, "Get dump from /proc/kmsg or /sys/kernel/debug/gc/galcore_trace\n");
+
+ if (kernel->hardware->powerManagement == gcvFALSE)
+ {
+ _DumpState(kernel);
+ }
+#endif
+
+ 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},
+ {"dump_trigger", gc_dump_trigger_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 *************************
+\******************************************************************************/
+
+static gceSTATUS
+_AllocateMemory(
+ IN gckGALDEVICE Device,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER *Logical,
+ OUT gctPHYS_ADDR *Physical,
+ OUT gctUINT32 *PhysAddr
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Device=0x%x Bytes=%lu", Device, Bytes);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+ gcmkVERIFY_ARGUMENT(PhysAddr != NULL);
+
+ gcmkONERROR(gckOS_AllocateContiguous(
+ Device->os, gcvFALSE, &Bytes, Physical, Logical
+ ));
+
+ *PhysAddr = ((PLINUX_MDL)*Physical)->dmaHandle;
+
+ /* Success. */
+ gcmkFOOTER_ARG(
+ "*Logical=0x%x *Physical=0x%x *PhysAddr=0x%08x",
+ *Logical, *Physical, *PhysAddr
+ );
+
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_FreeMemory(
+ IN gckGALDEVICE Device,
+ IN gctPOINTER Logical,
+ IN gctPHYS_ADDR Physical)
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Device=0x%x Logical=0x%x Physical=0x%x",
+ Device, Logical, Physical);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ status = gckOS_FreeContiguous(
+ Device->os, Physical, Logical,
+ ((PLINUX_MDL) Physical)->numPages * PAGE_SIZE
+ );
+
+ gcmkFOOTER();
+ return status;
+}
+
+
+
+/******************************************************************************\
+******************************* Interrupt Handler ******************************
+\******************************************************************************/
+#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 int threadRoutine3D1(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_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;
+ }
+
+ gckKERNEL_Notify(device->kernels[gcvCORE_OCL],
+ gcvNOTIFY_INTERRUPT,
+ gcvFALSE);
+ }
+}
+#else
+static irqreturn_t isrRoutine(int irq, void *ctxt)
+{
+ gceSTATUS status;
+ gckGALDEVICE device;
+
+ device = (gckGALDEVICE) ctxt;
+
+ /* Call kernel interrupt notification. */
+ status = gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvTRUE);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ up(&device->semas[gcvCORE_MAJOR]);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int threadRoutine(void *ctxt)
+{
+ gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "Starting isr Thread with extension=%p",
+ device);
+
+ for (;;)
+ {
+ static int down;
+
+ down = down_interruptible(&device->semas[gcvCORE_MAJOR]);
+ 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);
+ }
+}
+#endif
+
+static irqreturn_t isrRoutine2D(int irq, void *ctxt)
+{
+ gceSTATUS status;
+ gckGALDEVICE device;
+
+ device = (gckGALDEVICE) ctxt;
+
+ /* Call kernel interrupt notification. */
+ status = gckKERNEL_Notify(device->kernels[gcvCORE_2D],
+#if gcdMULTI_GPU
+ 0,
+#endif
+ gcvNOTIFY_INTERRUPT,
+ gcvTRUE);
+ if (gcmIS_SUCCESS(status))
+ {
+ up(&device->semas[gcvCORE_2D]);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int threadRoutine2D(void *ctxt)
+{
+ gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "Starting isr Thread with extension=%p",
+ device);
+
+ for (;;)
+ {
+ static int down;
+
+ down = down_interruptible(&device->semas[gcvCORE_2D]);
+ 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_2D],
+#if gcdMULTI_GPU
+ 0,
+#endif
+ gcvNOTIFY_INTERRUPT,
+ gcvFALSE);
+ }
+}
+
+static irqreturn_t isrRoutineVG(int irq, void *ctxt)
+{
+#if gcdENABLE_VG
+ gceSTATUS status;
+ gckGALDEVICE device;
+
+ device = (gckGALDEVICE) ctxt;
+
+ /* Serve the interrupt. */
+ status = gckVGINTERRUPT_Enque(device->kernels[gcvCORE_VG]->vg->interrupt);
+
+ /* Determine the return value. */
+ return (status == gcvSTATUS_NOT_OUR_INTERRUPT)
+ ? IRQ_RETVAL(0)
+ : IRQ_RETVAL(1);
+#else
+ return IRQ_NONE;
+#endif
+}
+
+static int threadRoutineVG(void *ctxt)
+{
+ gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "Starting isr Thread with extension=%p",
+ device);
+
+ for (;;)
+ {
+ static int down;
+
+ down = down_interruptible(&device->semas[gcvCORE_VG]);
+ 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_VG],
+#if gcdMULTI_GPU
+ 0,
+#endif
+ gcvNOTIFY_INTERRUPT,
+ gcvFALSE);
+ }
+}
+
+/******************************************************************************\
+******************************* gckGALDEVICE Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Construct
+**
+** Constructor.
+**
+** INPUT:
+**
+** OUTPUT:
+**
+** gckGALDEVICE * Device
+** Pointer to a variable receiving the gckGALDEVICE object pointer on
+** success.
+*/
+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,
+ IN gctINT IrqLineVG,
+ IN gctUINT32 RegisterMemBaseVG,
+ IN gctSIZE_T RegisterMemSizeVG,
+ IN gctUINT32 ContiguousBase,
+ IN gctSIZE_T ContiguousSize,
+ IN gctSIZE_T BankSize,
+ IN gctINT FastClear,
+ IN gctINT Compression,
+ IN gctUINT32 PhysBaseAddr,
+ IN gctUINT32 PhysSize,
+ IN gctINT Signal,
+ IN gctUINT LogFileSize,
+ IN gctINT PowerManagement,
+ IN gctINT GpuProfiler,
+ IN gcsDEVICE_CONSTRUCT_ARGS * Args,
+ OUT gckGALDEVICE *Device
+ )
+{
+ gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
+ gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
+ gctUINT32 horizontalTileSize, verticalTileSize;
+ struct resource* mem_region;
+ gctUINT32 physAddr;
+ gctUINT32 physical;
+ gckGALDEVICE device;
+ gceSTATUS status;
+ gctINT32 i;
+#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 "
+ "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
+ "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
+ IrqLine, RegisterMemBase, RegisterMemSize,
+ IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
+ IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
+ ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
+ PhysBaseAddr, PhysSize, Signal);
+#endif
+
+#if gcdDISABLE_CORES_2D3D
+ IrqLine = -1;
+ IrqLine2D = -1;
+#endif
+
+ /* Allocate device structure. */
+ device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL | __GFP_NOWARN);
+
+ if (!device)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ memset(device, 0, sizeof(struct _gckGALDEVICE));
+
+ device->dbgNode = gcvNULL;
+
+ device->platform = Args->platform;
+
+ /* set up the contiguous memory */
+ device->contiguousSize = ContiguousSize;
+
+ 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
+ );
+ }
+ 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;
+ }
+#endif
+
+ if (IrqLine2D != -1)
+ {
+ device->requestedRegisterMemBases[gcvCORE_2D] = RegisterMemBase2D;
+ device->requestedRegisterMemSizes[gcvCORE_2D] = RegisterMemSize2D;
+ }
+
+ if (IrqLineVG != -1)
+ {
+ device->requestedRegisterMemBases[gcvCORE_VG] = RegisterMemBaseVG;
+ device->requestedRegisterMemSizes[gcvCORE_VG] = RegisterMemSizeVG;
+ }
+#if gcdENABLE_DEC_COMPRESSION
+ {
+ device->requestedRegisterMemBases[gcvCORE_DEC] = Args->registerMemBaseDEC300;
+ device->requestedRegisterMemSizes[gcvCORE_DEC] = Args->registerMemSizeDEC300;
+ }
+#endif
+
+
+ device->requestedContiguousBase = 0;
+ device->requestedContiguousSize = 0;
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; 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);
+ }
+
+ physical += device->requestedRegisterMemSize3D[j];
+ }
+ else
+ {
+ device->registerBase3D[j] = gcvNULL;
+ }
+ }
+ }
+ else
+#endif
+ {
+ physical = device->requestedRegisterMemBases[i];
+
+ /* Set up register memory region. */
+ if (physical != 0)
+ {
+
+ if ( Args->registerMemMapped )
+ {
+ device->registerBases[i] = Args->registerMemAddress;
+ device->requestedRegisterMemBases[i] = 0;
+
+ } else {
+
+ mem_region = request_mem_region(physical,
+ device->requestedRegisterMemSizes[i],
+ "galcore register region");
+
+ if (mem_region == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
+ __FUNCTION__, __LINE__,
+ physical, device->requestedRegisterMemSizes[i]
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ device->registerBases[i] = (gctPOINTER) ioremap_nocache(
+ physical, device->requestedRegisterMemSizes[i]);
+
+ if (device->registerBases[i] == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
+ __FUNCTION__, __LINE__,
+ physical, device->requestedRegisterMemSizes[i]
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+
+ physical += device->requestedRegisterMemSizes[i];
+
+ }
+ }
+ }
+
+ /* Set the base address */
+ 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(
+ device->os, gcvCORE_MAJOR, device,
+ gcvNULL, &device->kernels[gcvCORE_MAJOR]));
+
+ sharedDB = device->kernels[gcvCORE_MAJOR]->db;
+
+ /* Initialize core mapping */
+ for (i = 0; i < 8; i++)
+ {
+ device->coreMapping[i] = gcvCORE_MAJOR;
+ }
+
+ /* Setup the ISR manager. */
+ gcmkONERROR(gckHARDWARE_SetIsrManager(
+ device->kernels[gcvCORE_MAJOR]->hardware,
+ (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
+ (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
+ device
+ ));
+
+ gcmkONERROR(gckHARDWARE_SetFastClear(
+ device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
+ ));
+
+ if(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));
+#endif
+ }
+ else
+ {
+ 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(
+ device->os, gcvCORE_2D, device,
+ sharedDB, &device->kernels[gcvCORE_2D]));
+
+ if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db;
+
+ /* Verify the hardware type */
+ gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type));
+
+ if (type != gcvHARDWARE_2D)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Unexpected hardware type: %d\n",
+ __FUNCTION__, __LINE__,
+ type
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Initialize core mapping */
+ if (device->kernels[gcvCORE_MAJOR] == gcvNULL
+#if gcdMULTI_GPU_AFFINITY
+ && device->kernels[gcvCORE_OCL] == gcvNULL
+#endif
+ )
+ {
+ for (i = 0; i < 8; i++)
+ {
+ device->coreMapping[i] = gcvCORE_2D;
+ }
+ }
+ else
+ {
+ device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D;
+ }
+
+ /* Setup the ISR manager. */
+ gcmkONERROR(gckHARDWARE_SetIsrManager(
+ device->kernels[gcvCORE_2D]->hardware,
+ (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR_2D,
+ (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR_2D,
+ device
+ ));
+
+ if(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. */
+ gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command));
+#endif
+ }
+ else
+ {
+ device->kernels[gcvCORE_2D] = gcvNULL;
+ }
+
+ if (IrqLineVG != -1)
+ {
+#if gcdENABLE_VG
+ gcmkONERROR(gckKERNEL_Construct(
+ device->os, gcvCORE_VG, device,
+ sharedDB, &device->kernels[gcvCORE_VG]));
+ /* Initialize core mapping */
+ if (device->kernels[gcvCORE_MAJOR] == gcvNULL
+ && device->kernels[gcvCORE_2D] == gcvNULL
+#if gcdMULTI_GPU_AFFINITY
+ && device->kernels[gcvCORE_OCL] == gcvNULL
+#endif
+ )
+ {
+ for (i = 0; i < 8; i++)
+ {
+ device->coreMapping[i] = gcvCORE_VG;
+ }
+ }
+ else
+ {
+ 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
+ ));
+ }
+
+
+#endif
+ }
+ else
+ {
+ device->kernels[gcvCORE_VG] = gcvNULL;
+ }
+
+ /* 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;
+#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 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;
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (device->kernels[i] != gcvNULL) break;
+ }
+
+ if (i == gcdMAX_GPU_COUNT)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+#if gcdENABLE_VG
+ if (i == gcvCORE_VG)
+ {
+ /* Query the ceiling of the system memory. */
+ gcmkONERROR(gckVGHARDWARE_QuerySystemMemory(
+ device->kernels[i]->vg->hardware,
+ &device->systemMemorySize,
+ &device->systemMemoryBaseAddress
+ ));
+ /* query the amount of video memory */
+ gcmkONERROR(gckVGHARDWARE_QueryMemory(
+ device->kernels[i]->vg->hardware,
+ &device->internalSize, &internalBaseAddress, &internalAlignment,
+ &device->externalSize, &externalBaseAddress, &externalAlignment,
+ &horizontalTileSize, &verticalTileSize
+ ));
+ }
+ else
+#endif
+ {
+ /* Query the ceiling of the system memory. */
+ gcmkONERROR(gckHARDWARE_QuerySystemMemory(
+ device->kernels[i]->hardware,
+ &device->systemMemorySize,
+ &device->systemMemoryBaseAddress
+ ));
+
+ /* query the amount of video memory */
+ gcmkONERROR(gckHARDWARE_QueryMemory(
+ device->kernels[i]->hardware,
+ &device->internalSize, &internalBaseAddress, &internalAlignment,
+ &device->externalSize, &externalBaseAddress, &externalAlignment,
+ &horizontalTileSize, &verticalTileSize
+ ));
+ }
+
+
+ /* Grab the first availiable kernel */
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+#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
+ {
+ if (device->irqLines[i] != -1)
+ {
+ kernel = device->kernels[i];
+ break;
+ }
+ }
+ }
+
+ /* Set up the internal memory region. */
+ if (device->internalSize > 0)
+ {
+ status = gckVIDMEM_Construct(
+ device->os,
+ internalBaseAddress, device->internalSize, internalAlignment,
+ 0, &device->internalVidMem
+ );
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Error, disable internal heap. */
+ device->internalSize = 0;
+ }
+ else
+ {
+ /* Map internal memory. */
+ device->internalLogical
+ = (gctPOINTER) ioremap_nocache(physical, device->internalSize);
+
+ if (device->internalLogical == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ device->internalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
+ device->internalPhysicalName = gcmPTR_TO_NAME(device->internalPhysical);
+ physical += device->internalSize;
+ }
+ }
+
+ if (device->externalSize > 0)
+ {
+ /* create the external memory heap */
+ status = gckVIDMEM_Construct(
+ device->os,
+ externalBaseAddress, device->externalSize, externalAlignment,
+ 0, &device->externalVidMem
+ );
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Error, disable internal heap. */
+ device->externalSize = 0;
+ }
+ else
+ {
+ /* Map external memory. */
+ device->externalLogical
+ = (gctPOINTER) ioremap_nocache(physical, device->externalSize);
+
+ if (device->externalLogical == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ device->externalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
+ device->externalPhysicalName = gcmPTR_TO_NAME(device->externalPhysical);
+ physical += device->externalSize;
+ }
+ }
+
+ /* set up the contiguous memory */
+ device->contiguousSize = ContiguousSize;
+
+ if (ContiguousSize > 0)
+ {
+ if (ContiguousBase == 0)
+ {
+ while (device->contiguousSize > 0)
+ {
+ /* Allocate contiguous memory. */
+ status = _AllocateMemory(
+ device,
+ device->contiguousSize,
+ &device->contiguousBase,
+ &device->contiguousPhysical,
+ &physAddr
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ device->contiguousPhysicalName = gcmPTR_TO_NAME(device->contiguousPhysical);
+ status = gckVIDMEM_Construct(
+ device->os,
+ physAddr | device->systemMemoryBaseAddress,
+ device->contiguousSize,
+ 64,
+ BankSize,
+ &device->contiguousVidMem
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ break;
+ }
+
+ gcmkONERROR(_FreeMemory(
+ device,
+ device->contiguousBase,
+ device->contiguousPhysical
+ ));
+
+ gcmRELEASE_NAME(device->contiguousPhysicalName);
+ device->contiguousBase = gcvNULL;
+ device->contiguousPhysical = gcvNULL;
+ }
+
+ if (device->contiguousSize <= (4 << 20))
+ {
+ device->contiguousSize = 0;
+ }
+ else
+ {
+ device->contiguousSize -= (4 << 20);
+ }
+ }
+ }
+ else
+ {
+ /* Create the contiguous memory heap. */
+ status = gckVIDMEM_Construct(
+ device->os,
+ ContiguousBase | device->systemMemoryBaseAddress,
+ ContiguousSize,
+ 64, BankSize,
+ &device->contiguousVidMem
+ );
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Error, disable contiguous memory pool. */
+ device->contiguousVidMem = gcvNULL;
+ device->contiguousSize = 0;
+ }
+ else
+ {
+ if (Args->contiguousRequested == gcvFALSE)
+ {
+ mem_region = request_mem_region(
+ ContiguousBase, ContiguousSize, "galcore managed memory"
+ );
+
+ if (mem_region == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
+ __FUNCTION__, __LINE__,
+ ContiguousSize, ContiguousBase
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+
+ device->requestedContiguousBase = ContiguousBase;
+ device->requestedContiguousSize = ContiguousSize;
+ device->contiguousRequested = Args->contiguousRequested;
+
+ device->contiguousPhysical = gcvNULL;
+ device->contiguousPhysicalName = 0;
+ device->contiguousSize = ContiguousSize;
+ device->contiguousMapped = gcvTRUE;
+ }
+ }
+ }
+
+ /* Return pointer to the device. */
+ *Device = device;
+
+ gcmkFOOTER_ARG("*Device=0x%x", * Device);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Destroy
+**
+** Class destructor.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Destroy(
+ gckGALDEVICE Device)
+{
+ gctINT i;
+#if gcdMULTI_GPU
+ gctINT j;
+#endif
+ gckKERNEL kernel = gcvNULL;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ if (Device != gcvNULL)
+ {
+ /* Grab the first availiable kernel */
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+#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
+ {
+ if (Device->irqLines[i] != -1)
+ {
+ kernel = Device->kernels[i];
+ break;
+ }
+ }
+ }
+
+ if (Device->internalPhysicalName != 0)
+ {
+ gcmRELEASE_NAME(Device->internalPhysicalName);
+ Device->internalPhysicalName = 0;
+ }
+ if (Device->externalPhysicalName != 0)
+ {
+ gcmRELEASE_NAME(Device->externalPhysicalName);
+ Device->externalPhysicalName = 0;
+ }
+ if (Device->contiguousPhysicalName != 0)
+ {
+ gcmRELEASE_NAME(Device->contiguousPhysicalName);
+ Device->contiguousPhysicalName = 0;
+ }
+
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (Device->kernels[i] != gcvNULL)
+ {
+ /* Destroy the gckKERNEL object. */
+ gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernels[i]));
+ Device->kernels[i] = gcvNULL;
+ }
+ }
+
+ if (Device->internalLogical != gcvNULL)
+ {
+ /* Unmap the internal memory. */
+ iounmap(Device->internalLogical);
+ Device->internalLogical = gcvNULL;
+ }
+
+ if (Device->internalVidMem != gcvNULL)
+ {
+ /* Destroy the internal heap. */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
+ Device->internalVidMem = gcvNULL;
+ }
+
+ if (Device->externalLogical != gcvNULL)
+ {
+ /* Unmap the external memory. */
+ iounmap(Device->externalLogical);
+ Device->externalLogical = gcvNULL;
+ }
+
+ if (Device->externalVidMem != gcvNULL)
+ {
+ /* destroy the external heap */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
+ Device->externalVidMem = gcvNULL;
+ }
+
+ if (Device->contiguousBase != gcvNULL)
+ {
+ if (Device->contiguousMapped == gcvFALSE)
+ {
+ gcmkVERIFY_OK(_FreeMemory(
+ Device,
+ Device->contiguousBase,
+ Device->contiguousPhysical
+ ));
+ }
+
+ Device->contiguousBase = gcvNULL;
+ Device->contiguousPhysical = gcvNULL;
+ }
+
+ if (Device->requestedContiguousBase != 0
+ && Device->contiguousRequested == gcvFALSE
+ )
+ {
+ release_mem_region(Device->requestedContiguousBase, Device->requestedContiguousSize);
+ Device->requestedContiguousBase = 0;
+ Device->requestedContiguousSize = 0;
+ }
+
+ if (Device->contiguousVidMem != gcvNULL)
+ {
+ /* Destroy the contiguous heap. */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
+ Device->contiguousVidMem = gcvNULL;
+ }
+
+ if (Device->dbgNode)
+ {
+ gckDEBUGFS_FreeNode(Device->dbgNode);
+
+ if(Device->dbgNode != gcvNULL)
+ {
+ kfree(Device->dbgNode);
+ Device->dbgNode = gcvNULL;
+ }
+ }
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+#if gcdMULTI_GPU
+ if (i == gcvCORE_MAJOR)
+ {
+ 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;
+ }
+ }
+ }
+ else
+#endif
+ {
+ if (Device->registerBases[i] != gcvNULL)
+ {
+ /* Unmap register memory. */
+ if (Device->requestedRegisterMemBases[i] != 0)
+ iounmap(Device->registerBases[i]);
+
+ if (Device->requestedRegisterMemBases[i] != 0)
+ {
+ release_mem_region(Device->requestedRegisterMemBases[i],
+ Device->requestedRegisterMemSizes[i]);
+ }
+
+ Device->registerBases[i] = gcvNULL;
+ Device->requestedRegisterMemBases[i] = 0;
+ Device->requestedRegisterMemSizes[i] = 0;
+ }
+ }
+ }
+
+ /* Destroy the gckOS object. */
+ if (Device->os != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_Destroy(Device->os));
+ Device->os = gcvNULL;
+ }
+
+ _DebugfsCleanup(Device);
+
+ /* Free the device. */
+ kfree(Device);
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Setup_ISR
+**
+** Start the ISR routine.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Setup successfully.
+** gcvSTATUS_GENERIC_IO
+** Setup failed.
+*/
+gceSTATUS
+gckGALDEVICE_Setup_ISR(
+ IN gckGALDEVICE Device
+ )
+{
+ gceSTATUS status;
+ gctINT ret = 0;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ if (Device->irqLines[gcvCORE_MAJOR] < 0)
+ {
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ /* Hook up the isr based on the irq line. */
+#ifdef FLAREON
+ gc500_handle.dev_name = "galcore interrupt service";
+ gc500_handle.dev_id = Device;
+ gc500_handle.handler = isrRoutine;
+ gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
+ gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
+
+ ret = dove_gpio_request(
+ DOVE_GPIO0_7, &gc500_handle
+ );
+#else
+#if gcdMULTI_GPU
+ ret = request_irq(
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+ Device->irqLine3D[gcvCORE_3D_0_ID], isrRoutine3D0, IRQF_DISABLED,
+#else
+ Device->irqLine3D[gcvCORE_3D_0_ID], isrRoutine3D0, 0x0,
+#endif
+ "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(
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+ Device->irqLine3D[gcvCORE_3D_1_ID], isrRoutine3D1, IRQF_DISABLED,
+#else
+ Device->irqLine3D[gcvCORE_3D_1_ID], isrRoutine3D1, 0x0,
+#endif
+ "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(
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+ Device->irqLines[gcvCORE_MAJOR], isrRoutine3D0, IRQF_DISABLED,
+#else
+ Device->irqLines[gcvCORE_MAJOR], isrRoutine3D0, 0x0,
+#endif
+ "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(
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+ Device->irqLines[gcvCORE_OCL], isrRoutine3D1, IRQF_DISABLED,
+#else
+ Device->irqLines[gcvCORE_OCL], isrRoutine3D1, 0x0,
+#endif
+ "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(
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+ Device->irqLines[gcvCORE_MAJOR], isrRoutine, IRQF_DISABLED,
+#else
+ Device->irqLines[gcvCORE_MAJOR], isrRoutine, 0x0,
+#endif
+ "galcore interrupt service", 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;
+#endif
+#endif
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckGALDEVICE_Setup_ISR_2D(
+ IN gckGALDEVICE Device
+ )
+{
+ gceSTATUS status;
+ gctINT ret;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ if (Device->irqLines[gcvCORE_2D] < 0)
+ {
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ /* Hook up the isr based on the irq line. */
+#ifdef FLAREON
+ gc500_handle.dev_name = "galcore interrupt service";
+ gc500_handle.dev_id = Device;
+ gc500_handle.handler = isrRoutine2D;
+ gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
+ gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
+
+ ret = dove_gpio_request(
+ DOVE_GPIO0_7, &gc500_handle
+ );
+#else
+ ret = request_irq(
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+ Device->irqLines[gcvCORE_2D], isrRoutine2D, IRQF_DISABLED,
+#else
+ Device->irqLines[gcvCORE_2D], isrRoutine2D, 0x0,
+#endif
+ "galcore interrupt service for 2D", Device
+ );
+#endif
+
+ if (ret != 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Could not register irq line %d (error=%d)\n",
+ __FUNCTION__, __LINE__,
+ Device->irqLines[gcvCORE_2D], ret
+ );
+
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ /* Mark ISR as initialized. */
+ Device->isrInitializeds[gcvCORE_2D] = gcvTRUE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckGALDEVICE_Setup_ISR_VG(
+ IN gckGALDEVICE Device
+ )
+{
+ gceSTATUS status;
+ gctINT ret;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ if (Device->irqLines[gcvCORE_VG] < 0)
+ {
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ /* Hook up the isr based on the irq line. */
+#ifdef FLAREON
+ gc500_handle.dev_name = "galcore interrupt service";
+ gc500_handle.dev_id = Device;
+ gc500_handle.handler = isrRoutineVG;
+ gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
+ gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
+
+ ret = dove_gpio_request(
+ DOVE_GPIO0_7, &gc500_handle
+ );
+#else
+ ret = request_irq(
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+ Device->irqLines[gcvCORE_VG], isrRoutineVG, IRQF_DISABLED,
+#else
+ Device->irqLines[gcvCORE_VG], isrRoutineVG, 0x0,
+#endif
+ "galcore interrupt service for 2D", Device
+ );
+#endif
+
+ if (ret != 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Could not register irq line %d (error=%d)\n",
+ __FUNCTION__, __LINE__,
+ Device->irqLines[gcvCORE_VG], ret
+ );
+
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ /* Mark ISR as initialized. */
+ Device->isrInitializeds[gcvCORE_VG] = gcvTRUE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Release_ISR
+**
+** Release the irq line.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Release_ISR(
+ IN gckGALDEVICE Device
+ )
+{
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+#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])
+ {
+#ifdef FLAREON
+ dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
+#else
+ free_irq(Device->irqLines[gcvCORE_MAJOR], Device);
+#endif
+ Device->isrInitializeds[gcvCORE_MAJOR] = gcvFALSE;
+ }
+#endif
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckGALDEVICE_Release_ISR_2D(
+ IN gckGALDEVICE Device
+ )
+{
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ /* release the irq */
+ if (Device->isrInitializeds[gcvCORE_2D])
+ {
+#ifdef FLAREON
+ dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
+#else
+ free_irq(Device->irqLines[gcvCORE_2D], Device);
+#endif
+
+ Device->isrInitializeds[gcvCORE_2D] = gcvFALSE;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckGALDEVICE_Release_ISR_VG(
+ IN gckGALDEVICE Device
+ )
+{
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ /* release the irq */
+ if (Device->isrInitializeds[gcvCORE_VG])
+ {
+#ifdef FLAREON
+ dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
+#else
+ free_irq(Device->irqLines[gcvCORE_VG], Device);
+#endif
+
+ Device->isrInitializeds[gcvCORE_VG] = gcvFALSE;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Start_Threads
+**
+** Start the daemon threads.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Start successfully.
+** gcvSTATUS_GENERIC_IO
+** Start failed.
+*/
+gceSTATUS
+gckGALDEVICE_Start_Threads(
+ IN gckGALDEVICE Device
+ )
+{
+ gceSTATUS status;
+ struct task_struct * task;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+#if 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. */
+ task = kthread_run(threadRoutine, Device, "galcore daemon thread");
+
+ if (IS_ERR(task))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Could not start the kernel thread.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ Device->threadCtxts[gcvCORE_MAJOR] = task;
+ Device->threadInitializeds[gcvCORE_MAJOR] = gcvTRUE;
+ }
+#endif
+
+ if (Device->kernels[gcvCORE_2D] != gcvNULL)
+ {
+ /* Start the kernel thread. */
+ task = kthread_run(threadRoutine2D, Device, "galcore daemon thread for 2D");
+
+ if (IS_ERR(task))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Could not start the kernel thread.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ Device->threadCtxts[gcvCORE_2D] = task;
+ Device->threadInitializeds[gcvCORE_2D] = gcvTRUE;
+ }
+ else
+ {
+ Device->threadInitializeds[gcvCORE_2D] = gcvFALSE;
+ }
+
+ if (Device->kernels[gcvCORE_VG] != gcvNULL)
+ {
+ /* Start the kernel thread. */
+ task = kthread_run(threadRoutineVG, Device, "galcore daemon thread for VG");
+
+ if (IS_ERR(task))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Could not start the kernel thread.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ Device->threadCtxts[gcvCORE_VG] = task;
+ Device->threadInitializeds[gcvCORE_VG] = gcvTRUE;
+ }
+ else
+ {
+ Device->threadInitializeds[gcvCORE_VG] = gcvFALSE;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Stop_Threads
+**
+** Stop the gal device, including the following actions: stop the daemon
+** thread, release the irq.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Stop_Threads(
+ gckGALDEVICE Device
+ )
+{
+ gctINT i;
+#if gcdMULTI_GPU
+ gctINT j;
+#endif
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; 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
+ {
+ /* 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;
+ }
+ }
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Start
+**
+** Start the gal device, including the following actions: setup the isr routine
+** and start the daemoni thread.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Start successfully.
+*/
+gceSTATUS
+gckGALDEVICE_Start(
+ IN gckGALDEVICE Device
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ /* Start the kernel thread. */
+ gcmkONERROR(gckGALDEVICE_Start_Threads(Device));
+
+ if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
+ {
+ /* Setup the ISR routine. */
+ gcmkONERROR(gckGALDEVICE_Setup_ISR(Device));
+
+ /* Switch to SUSPEND power state. */
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(
+ Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF_BROADCAST
+ ));
+ }
+
+ if (Device->kernels[gcvCORE_2D] != gcvNULL)
+ {
+ /* Setup the ISR routine. */
+ gcmkONERROR(gckGALDEVICE_Setup_ISR_2D(Device));
+
+ /* Switch to SUSPEND power state. */
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(
+ Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF_BROADCAST
+ ));
+ }
+
+ if (Device->kernels[gcvCORE_VG] != gcvNULL)
+ {
+ /* 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();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Stop
+**
+** Stop the gal device, including the following actions: stop the daemon
+** thread, release the irq.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Stop(
+ gckGALDEVICE Device
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
+ {
+ /* Switch to OFF power state. */
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(
+ Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF
+ ));
+
+ /* Remove the ISR routine. */
+ gcmkONERROR(gckGALDEVICE_Release_ISR(Device));
+ }
+
+ if (Device->kernels[gcvCORE_2D] != gcvNULL)
+ {
+ /* Setup the ISR routine. */
+ gcmkONERROR(gckGALDEVICE_Release_ISR_2D(Device));
+
+ /* Switch to OFF power state. */
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(
+ Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF
+ ));
+ }
+
+ if (Device->kernels[gcvCORE_VG] != gcvNULL)
+ {
+ /* Setup the ISR routine. */
+ gcmkONERROR(gckGALDEVICE_Release_ISR_VG(Device));
+
+#if gcdENABLE_VG
+ /* Switch to OFF power state. */
+ gcmkONERROR(gckVGHARDWARE_SetPowerManagementState(
+ Device->kernels[gcvCORE_VG]->vg->hardware, gcvPOWER_OFF
+ ));
+#endif
+ }
+
+ /* Stop the kernel thread. */
+ gcmkONERROR(gckGALDEVICE_Stop_Threads(Device));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
new file mode 100644
index 000000000000..84c97048e85d
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
@@ -0,0 +1,282 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_device_h_
+#define __gc_hal_kernel_device_h_
+
+#include "gc_hal_kernel_debugfs.h"
+
+/******************************************************************************\
+******************************* gckGALDEVICE Structure *******************************
+\******************************************************************************/
+
+typedef struct _gckGALDEVICE
+{
+ /* Objects. */
+ gckOS os;
+ gckKERNEL kernels[gcdMAX_GPU_COUNT];
+
+ gcsPLATFORM* platform;
+
+ /* Attributes. */
+ gctSIZE_T internalSize;
+ gctPHYS_ADDR internalPhysical;
+ gctUINT32 internalPhysicalName;
+ gctPOINTER internalLogical;
+ gckVIDMEM internalVidMem;
+ gctSIZE_T externalSize;
+ gctPHYS_ADDR externalPhysical;
+ gctUINT32 externalPhysicalName;
+ gctPOINTER externalLogical;
+ gckVIDMEM externalVidMem;
+ gckVIDMEM contiguousVidMem;
+ gctPOINTER contiguousBase;
+ gctPHYS_ADDR contiguousPhysical;
+ gctUINT32 contiguousPhysicalName;
+ 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];
+
+ /* 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];
+ gctBOOL killThread;
+
+ /* Signal management. */
+ gctINT signal;
+
+ /* Core mapping */
+ gceCORE coreMapping[8];
+
+ /* States before suspend. */
+ gceCHIPPOWERSTATE statesStored[gcdMAX_GPU_COUNT];
+
+ /* Device Debug File System Entry in kernel. */
+ struct _gcsDEBUGFS_Node * dbgNode;
+
+ gcsDEBUGFS_DIR debugfsDir;
+}
+* gckGALDEVICE;
+
+typedef struct _gcsHAL_PRIVATE_DATA
+{
+ gckGALDEVICE device;
+ gctPOINTER mappedMemory;
+ gctPOINTER contiguousLogical;
+ /* The process opening the device may not be the same as the one that closes it. */
+ gctUINT32 pidOpen;
+}
+gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
+
+typedef struct _gcsDEVICE_CONSTRUCT_ARGS
+{
+ gctBOOL recovery;
+ gctUINT stuckDump;
+ gctUINT gpu3DMinClock;
+
+ gctBOOL contiguousRequested;
+ gcsPLATFORM* platform;
+ gctBOOL mmu;
+ gctBOOL registerMemMapped;
+ gctPOINTER registerMemAddress;
+#if gcdENABLE_DEC_COMPRESSION
+ gctUINT32 registerMemBaseDEC300;
+ gctSIZE_T registerMemSizeDEC300;
+#endif
+}
+
+gcsDEVICE_CONSTRUCT_ARGS;
+
+gceSTATUS gckGALDEVICE_Setup_ISR(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Setup_ISR_2D(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Setup_ISR_VG(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Release_ISR(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Release_ISR_2D(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Release_ISR_VG(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Start_Threads(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Stop_Threads(
+ gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Start(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Stop(
+ gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Construct(
+#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,
+ IN gctINT IrqLineVG,
+ IN gctUINT32 RegisterMemBaseVG,
+ IN gctSIZE_T RegisterMemSizeVG,
+ IN gctUINT32 ContiguousBase,
+ IN gctSIZE_T ContiguousSize,
+ IN gctSIZE_T BankSize,
+ IN gctINT FastClear,
+ IN gctINT Compression,
+ IN gctUINT32 PhysBaseAddr,
+ IN gctUINT32 PhysSize,
+ IN gctINT Signal,
+ IN gctUINT LogFileSize,
+ IN gctINT PowerManagement,
+ IN gctINT GpuProfiler,
+ IN gcsDEVICE_CONSTRUCT_ARGS * Args,
+ OUT gckGALDEVICE *Device
+ );
+
+gceSTATUS gckGALDEVICE_Destroy(
+ IN gckGALDEVICE Device
+ );
+
+static gcmINLINE 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
+ {
+ gcmkASSERT(gcvFALSE);
+ return gcvNULL;
+ }
+}
+
+#endif /* __gc_hal_kernel_device_h_ */
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
index 000000000000..843b7e14f0d9
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_iommu.c
@@ -0,0 +1,250 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_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;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c
new file mode 100644
index 000000000000..ad053af14a67
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c
@@ -0,0 +1,534 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+
+#define _GC_OBJ_ZONE gcvZONE_KERNEL
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckKERNEL_QueryVideoMemory
+**
+** Query the amount of video memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to an gcsHAL_INTERFACE structure that will be filled in with
+** the memory information.
+*/
+gceSTATUS
+gckKERNEL_QueryVideoMemory(
+ IN gckKERNEL Kernel,
+ OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gckGALDEVICE device;
+
+ gcmkHEADER_ARG("Kernel=%p", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interface != NULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Get internal memory size and physical address. */
+ Interface->u.QueryVideoMemory.internalSize = device->internalSize;
+ Interface->u.QueryVideoMemory.internalPhysical = device->internalPhysicalName;
+
+ /* Get external memory size and physical address. */
+ Interface->u.QueryVideoMemory.externalSize = device->externalSize;
+ Interface->u.QueryVideoMemory.externalPhysical = device->externalPhysicalName;
+
+ /* Get contiguous memory size and physical address. */
+ Interface->u.QueryVideoMemory.contiguousSize = device->contiguousSize;
+ Interface->u.QueryVideoMemory.contiguousPhysical = device->contiguousPhysicalName;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_GetVideoMemoryPool
+**
+** Get the gckVIDMEM object belonging to the specified pool.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcePOOL Pool
+** Pool to query gckVIDMEM object for.
+**
+** OUTPUT:
+**
+** gckVIDMEM * VideoMemory
+** Pointer to a variable that will hold the pointer to the gckVIDMEM
+** object belonging to the requested pool.
+*/
+gceSTATUS
+gckKERNEL_GetVideoMemoryPool(
+ IN gckKERNEL Kernel,
+ IN gcePOOL Pool,
+ OUT gckVIDMEM * VideoMemory
+ )
+{
+ gckGALDEVICE device;
+ gckVIDMEM videoMemory;
+
+ gcmkHEADER_ARG("Kernel=%p Pool=%d", Kernel, Pool);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(VideoMemory != NULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Dispatch on pool. */
+ switch (Pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ videoMemory = device->internalVidMem;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ videoMemory = device->externalVidMem;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ videoMemory = device->contiguousVidMem;
+ break;
+
+ default:
+ /* Unknown pool. */
+ videoMemory = NULL;
+ }
+
+ /* Return pointer to the gckVIDMEM object. */
+ *VideoMemory = videoMemory;
+
+ /* Return status. */
+ gcmkFOOTER_ARG("*VideoMemory=%p", *VideoMemory);
+ return (videoMemory == NULL) ? gcvSTATUS_OUT_OF_MEMORY : gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapMemory
+**
+** Map video memory into the current process space.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of video memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the base address of the mapped
+** memory region.
+*/
+gceSTATUS
+gckKERNEL_MapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ gckKERNEL kernel = Kernel;
+ gctPHYS_ADDR physical = gcmNAME_TO_PTR(Physical);
+
+ return gckOS_MapMemory(Kernel->os, physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_UnmapMemory
+**
+** Unmap video memory from the current process space.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of video memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** gctPOINTER Logical
+** Base address of the mapped memory region.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_UnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ gckKERNEL kernel = Kernel;
+ gctPHYS_ADDR physical = gcmNAME_TO_PTR(Physical);
+
+ return gckOS_UnmapMemory(Kernel->os, physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapVideoMemory
+**
+** Get the logical address for a hardware specific memory address for the
+** current process.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE to map the memory into the user space.
+**
+** gctUINT32 Address
+** Hardware specific memory address.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** specified memory address.
+*/
+gceSTATUS
+gckKERNEL_MapVideoMemoryEx(
+ IN gckKERNEL Kernel,
+ IN gceCORE Core,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * Logical
+ )
+{
+ gckGALDEVICE device = gcvNULL;
+ PLINUX_MDL mdl = gcvNULL;
+ PLINUX_MDL_MAP mdlMap = gcvNULL;
+ gcePOOL pool = gcvPOOL_UNKNOWN;
+ gctUINT32 offset = 0;
+ gctUINT32 base = 0;
+ gceSTATUS status;
+ gctPOINTER logical = gcvNULL;
+ gctUINT32 baseAddress;
+ gctPHYS_ADDR_T physical;
+
+ gcmkHEADER_ARG("Kernel=%p InUserSpace=%d Address=%08x",
+ Kernel, InUserSpace, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+#if gcdENABLE_VG
+ if (Core == gcvCORE_VG)
+ {
+ /* Split the memory address into a pool type and offset. */
+ gcmkONERROR(
+ gckVGHARDWARE_SplitMemory(Kernel->vg->hardware, Address, &pool, &offset));
+ }
+ else
+#endif
+ {
+ /* Split the memory address into a pool type and offset. */
+ gcmkONERROR(
+ gckHARDWARE_SplitMemory(Kernel->hardware, Address, &pool, &offset));
+ }
+
+ /* Dispatch on pool. */
+ switch (pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ logical = device->internalLogical;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ logical = device->externalLogical;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ if (device->contiguousMapped)
+ {
+ logical = device->contiguousBase;
+ }
+ else
+ {
+ gctINT processID;
+ gckOS_GetProcessID(&processID);
+
+ mdl = (PLINUX_MDL) device->contiguousPhysical;
+
+ mdlMap = FindMdlMap(mdl, processID);
+ gcmkASSERT(mdlMap);
+
+ logical = (gctPOINTER) mdlMap->vmaAddr;
+ }
+#if gcdENABLE_VG
+ if (Core == gcvCORE_VG)
+ {
+ gcmkVERIFY_OK(
+ gckVGHARDWARE_SplitMemory(Kernel->vg->hardware,
+ device->contiguousVidMem->baseAddress,
+ &pool,
+ &base));
+ }
+ else
+#endif
+ {
+ gctUINT32 systemBaseAddress = 0;
+
+ if (Kernel->hardware->mmuVersion == 0)
+ {
+ gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &systemBaseAddress));
+ }
+
+ gcmkVERIFY_OK(
+ gckOS_CPUPhysicalToGPUPhysical(
+ Kernel->os,
+ device->contiguousVidMem->baseAddress - systemBaseAddress,
+ &physical
+ ));
+
+ gcmkSAFECASTPHYSADDRT(baseAddress, physical);
+
+ gcmkVERIFY_OK(
+ gckHARDWARE_SplitMemory(Kernel->hardware,
+ baseAddress,
+ &pool,
+ &base));
+ }
+ offset -= base;
+ break;
+
+ default:
+ /* Invalid memory pool. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Build logical address of specified address. */
+ *Logical = (gctPOINTER) ((gctUINT8_PTR) logical + offset);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Logical=%p", *Logical);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Retunn the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapVideoMemory
+**
+** Get the logical address for a hardware specific memory address for the
+** current process.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE to map the memory into the user space.
+**
+** gctUINT32 Address
+** Hardware specific memory address.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** specified memory address.
+*/
+gceSTATUS
+gckKERNEL_MapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * Logical
+ )
+{
+ return gckKERNEL_MapVideoMemoryEx(Kernel, gcvCORE_MAJOR, InUserSpace, Address, Logical);
+}
+/*******************************************************************************
+**
+** gckKERNEL_Notify
+**
+** This function iscalled by clients to notify the gckKERNRL object of an event.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gceNOTIFY Notification
+** Notification event.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Notify(
+ IN gckKERNEL Kernel,
+#if gcdMULTI_GPU
+ IN gctUINT CoreId,
+#endif
+ IN gceNOTIFY Notification,
+ IN gctBOOL Data
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Kernel=%p Notification=%d Data=%d",
+ Kernel, Notification, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Dispatch on notifcation. */
+ switch (Notification)
+ {
+ case gcvNOTIFY_INTERRUPT:
+ /* Process the interrupt. */
+#if COMMAND_PROCESSOR_VERSION > 1
+ status = gckINTERRUPT_Notify(Kernel->interrupt, Data);
+#else
+ status = gckHARDWARE_Interrupt(Kernel->hardware,
+#if gcdMULTI_GPU
+ CoreId,
+#endif
+ Data);
+#endif
+ break;
+
+ default:
+ status = gcvSTATUS_OK;
+ break;
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_QuerySettings(
+ IN gckKERNEL Kernel,
+ OUT gcsKERNEL_SETTINGS * Settings
+ )
+{
+ gckGALDEVICE device;
+
+ gcmkHEADER_ARG("Kernel=%p", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Settings != gcvNULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Fill in signal. */
+ Settings->signal = device->signal;
+
+ /* Success. */
+ gcmkFOOTER_ARG("Settings->signal=%d", Settings->signal);
+ return gcvSTATUS_OK;
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
new file mode 100644
index 000000000000..d8b23fef90c3
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
@@ -0,0 +1,437 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_linux_h_
+#define __gc_hal_kernel_linux_h_
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#ifdef FLAREON
+# include <asm/arch-realview/dove_gpio_irq.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/kthread.h>
+
+#include <linux/idr.h>
+
+#ifdef MODVERSIONS
+# include <linux/modversions.h>
+#endif
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+#include <linux/clk.h>
+#endif
+
+#define NTSTRSAFE_NO_CCH_FUNCTIONS
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_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_vpid(x)
+#else
+#define FIND_TASK_BY_PID(x) find_task_by_pid(x)
+#endif
+
+#define _WIDE(string) L##string
+#define WIDE(string) _WIDE(string)
+
+#define countof(a) (sizeof(a) / sizeof(a[0]))
+
+#ifndef DEVICE_NAME
+#ifdef CONFIG_DOVE_GPU
+# define DEVICE_NAME "dove_gpu"
+#else
+# define DEVICE_NAME "galcore"
+#endif
+#endif
+
+#ifndef CLASS_NAME
+# define CLASS_NAME "graphics_class"
+#endif
+
+#define GetPageCount(size, offset) ((((size) + ((offset) & ~PAGE_MASK)) + PAGE_SIZE - 1) >> PAGE_SHIFT)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,7,0)
+#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP)
+#else
+#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 gctPHYS_ADDR_T * Physical
+ );
+
+gctSTRING
+_CreateKernelVirtualMapping(
+ IN PLINUX_MDL Mdl
+ );
+
+void
+_DestoryKernelVirtualMapping(
+ IN gctSTRING Addr
+ );
+
+void
+_UnmapUserLogical(
+ IN gctPOINTER Logical,
+ IN gctUINT32 Size
+ );
+
+static inline gctINT
+_GetProcessID(
+ void
+ )
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ return task_tgid_vnr(current);
+#else
+ return current->tgid;
+#endif
+}
+
+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 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_ */
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c
new file mode 100644
index 000000000000..ae3c8a79a946
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c
@@ -0,0 +1,66 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+
+gctINT
+gckMATH_ModuloInt(
+ IN gctINT X,
+ IN gctINT Y
+ )
+{
+ if(Y ==0) {return 0;}
+ else {return X % Y;}
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_mutex.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_mutex.h
new file mode 100644
index 000000000000..7027d464e11b
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_mutex.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef _gc_hal_kernel_mutex_h_
+#define _gc_hal_kernel_mutex_h_
+
+#include "gc_hal.h"
+#include <linux/mutex.h>
+
+/* Create a new mutex. */
+#define gckOS_CreateMutex(Os, Mutex) \
+({ \
+ gceSTATUS _status; \
+ gcmkHEADER_ARG("Os=0x%X", Os); \
+ \
+ /* Validate the arguments. */ \
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); \
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL); \
+ \
+ /* Allocate the mutex structure. */ \
+ _status = gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex); \
+ \
+ if (gcmIS_SUCCESS(_status)) \
+ { \
+ /* Initialize the mutex. */ \
+ mutex_init(*(struct mutex **)Mutex); \
+ } \
+ \
+ /* Return status. */ \
+ gcmkFOOTER_ARG("*Mutex=0x%X", *(struct mutex **)Mutex); \
+ _status; \
+})
+
+#endif
+
+
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
new file mode 100644
index 000000000000..0d60dbe6bb63
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
@@ -0,0 +1,8955 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.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/workqueue.h>
+#include <linux/irqflags.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
+#include <linux/math64.h>
+#endif
+#include <linux/delay.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#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
+
+#include "gc_hal_kernel_allocator.h"
+
+#define MEMORY_LOCK(os) \
+ gcmkVERIFY_OK(gckOS_AcquireMutex( \
+ (os), \
+ (os)->memoryLock, \
+ gcvINFINITE))
+
+#define MEMORY_UNLOCK(os) \
+ gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
+
+#define MEMORY_MAP_LOCK(os) \
+ gcmkVERIFY_OK(gckOS_AcquireMutex( \
+ (os), \
+ (os)->memoryMapLock, \
+ gcvINFINITE))
+
+#define MEMORY_MAP_UNLOCK(os) \
+ gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
+
+
+/******************************************************************************\
+******************************* Private Functions ******************************
+\******************************************************************************/
+static gctINT
+_GetThreadID(
+ void
+ )
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ return task_pid_vnr(current);
+#else
+ return current->pid;
+#endif
+}
+
+static PLINUX_MDL
+_CreateMdl(
+ void
+ )
+{
+ PLINUX_MDL mdl;
+
+ gcmkHEADER();
+
+ mdl = (PLINUX_MDL)kzalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL | gcdNOWARN);
+
+ gcmkFOOTER_ARG("0x%X", mdl);
+ return mdl;
+}
+
+static gceSTATUS
+_DestroyMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN PLINUX_MDL_MAP MdlMap
+ );
+
+static gceSTATUS
+_DestroyMdl(
+ IN PLINUX_MDL Mdl
+ )
+{
+ PLINUX_MDL_MAP mdlMap, next;
+
+ gcmkHEADER_ARG("Mdl=0x%X", Mdl);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
+
+ mdlMap = Mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ next = mdlMap->next;
+
+ gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
+
+ mdlMap = next;
+ }
+
+ kfree(Mdl);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+static PLINUX_MDL_MAP
+_CreateMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN gctINT ProcessID
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+
+ gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
+
+ mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_KERNEL | gcdNOWARN);
+ if (mdlMap == gcvNULL)
+ {
+ gcmkFOOTER_NO();
+ return gcvNULL;
+ }
+
+ mdlMap->pid = ProcessID;
+ mdlMap->vmaAddr = gcvNULL;
+ mdlMap->vma = gcvNULL;
+ mdlMap->count = 0;
+
+ mdlMap->next = Mdl->maps;
+ Mdl->maps = mdlMap;
+
+ gcmkFOOTER_ARG("0x%X", mdlMap);
+ return mdlMap;
+}
+
+static gceSTATUS
+_DestroyMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN PLINUX_MDL_MAP MdlMap
+ )
+{
+ PLINUX_MDL_MAP prevMdlMap;
+
+ gcmkHEADER_ARG("Mdl=0x%X MdlMap=0x%X", Mdl, MdlMap);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
+ gcmkASSERT(Mdl->maps != gcvNULL);
+
+ if (Mdl->maps == MdlMap)
+ {
+ Mdl->maps = MdlMap->next;
+ }
+ else
+ {
+ prevMdlMap = Mdl->maps;
+
+ while (prevMdlMap->next != MdlMap)
+ {
+ prevMdlMap = prevMdlMap->next;
+
+ gcmkASSERT(prevMdlMap != gcvNULL);
+ }
+
+ prevMdlMap->next = MdlMap->next;
+ }
+
+ kfree(MdlMap);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+extern PLINUX_MDL_MAP
+FindMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN gctINT ProcessID
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+
+ gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
+ if(Mdl == gcvNULL)
+ {
+ gcmkFOOTER_NO();
+ return gcvNULL;
+ }
+ mdlMap = Mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ if (mdlMap->pid == ProcessID)
+ {
+ gcmkFOOTER_ARG("0x%X", mdlMap);
+ return mdlMap;
+ }
+
+ mdlMap = mdlMap->next;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvNULL;
+}
+
+/*******************************************************************************
+** Integer Id Management.
+*/
+gceSTATUS
+_AllocateIntegerId(
+ IN gcsINTEGER_DB_PTR Database,
+ IN gctPOINTER KernelPointer,
+ OUT gctUINT32 *Id
+ )
+{
+ int result;
+ gctINT next;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ idr_preload(GFP_KERNEL | gcdNOWARN);
+
+ spin_lock(&Database->lock);
+
+ next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
+
+ result = idr_alloc(&Database->idr, KernelPointer, next, 0, GFP_ATOMIC);
+
+ /* ID allocated should not be 0. */
+ gcmkASSERT(result != 0);
+
+ if (result > 0)
+ {
+ Database->curr = *Id = result;
+ }
+
+ spin_unlock(&Database->lock);
+
+ idr_preload_end();
+
+ if (result < 0)
+ {
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+#else
+again:
+ if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0)
+ {
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ spin_lock(&Database->lock);
+
+ next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
+
+ /* Try to get a id greater than 0. */
+ result = idr_get_new_above(&Database->idr, KernelPointer, next, Id);
+
+ if (!result)
+ {
+ Database->curr = *Id;
+ }
+
+ spin_unlock(&Database->lock);
+
+ if (result == -EAGAIN)
+ {
+ goto again;
+ }
+
+ if (result != 0)
+ {
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_QueryIntegerId(
+ IN gcsINTEGER_DB_PTR Database,
+ IN gctUINT32 Id,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gctPOINTER pointer;
+
+ spin_lock(&Database->lock);
+
+ pointer = idr_find(&Database->idr, Id);
+
+ spin_unlock(&Database->lock);
+
+ if(pointer)
+ {
+ *KernelPointer = pointer;
+ return gcvSTATUS_OK;
+ }
+ else
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_OS,
+ "%s(%d) Id = %d is not found",
+ __FUNCTION__, __LINE__, Id);
+
+ return gcvSTATUS_NOT_FOUND;
+ }
+}
+
+gceSTATUS
+_DestroyIntegerId(
+ IN gcsINTEGER_DB_PTR Database,
+ IN gctUINT32 Id
+ )
+{
+ spin_lock(&Database->lock);
+
+ idr_remove(&Database->idr, Id);
+
+ spin_unlock(&Database->lock);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_QueryProcessPageTable(
+ IN gctPOINTER Logical,
+ OUT gctPHYS_ADDR_T * Address
+ )
+{
+#ifndef CONFIG_DEBUG_SPINLOCK
+ spinlock_t *lock;
+#endif
+ gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ if (!current->mm)
+ {
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+ pgd = pgd_offset(current->mm, logical);
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ {
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+ pud = pud_offset(pgd, logical);
+ if (pud_none(*pud) || pud_bad(*pud))
+ {
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+ pmd = pmd_offset(pud, logical);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ {
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+#ifndef CONFIG_DEBUG_SPINLOCK
+ pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
+#else
+ spin_lock(&current->mm->page_table_lock);
+
+ pte = pte_offset_map(pmd, logical);
+#endif
+
+ if (!pte)
+ {
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+ if (!pte_present(*pte))
+ {
+#ifndef CONFIG_DEBUG_SPINLOCK
+ pte_unmap_unlock(pte, lock);
+#else
+ spin_unlock(&current->mm->page_table_lock);
+#endif
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+ *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
+#ifndef CONFIG_DEBUG_SPINLOCK
+ pte_unmap_unlock(pte, lock);
+#else
+ spin_unlock(&current->mm->page_table_lock);
+#endif
+
+ 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;
+ gctPHYS_ADDR_T 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, &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
+
+gctBOOL
+_AllowAccess(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address
+ )
+{
+ gctUINT32 data;
+
+ /* Check external clock state. */
+ if (Os->clockStates[Core] == gcvFALSE)
+ {
+ gcmkPRINT("[galcore]: %s(%d) External clock off", __FUNCTION__, __LINE__);
+ return gcvFALSE;
+ }
+
+ /* Check internal clock state. */
+ if (Address == 0)
+ {
+ return gcvTRUE;
+ }
+
+#if gcdMULTI_GPU
+ if (Core == gcvCORE_MAJOR)
+ {
+ data = readl((gctUINT8 *)Os->device->registerBase3D[gcvCORE_3D_0_ID] + 0x0);
+ }
+ else
+#endif
+ {
+ data = readl((gctUINT8 *)Os->device->registerBases[Core] + 0x0);
+ }
+
+ if ((data & 0x3) == 0x3)
+ {
+ gcmkPRINT("[galcore]: %s(%d) Internal clock off", __FUNCTION__, __LINE__);
+ return gcvFALSE;
+ }
+
+ 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)
+ {
+ platform->ops->shrinkMemory(platform);
+ }
+ else
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_Construct
+**
+** Construct a new gckOS object.
+**
+** INPUT:
+**
+** gctPOINTER Context
+** Pointer to the gckGALDEVICE class.
+**
+** OUTPUT:
+**
+** gckOS * Os
+** Pointer to a variable that will hold the pointer to the gckOS object.
+*/
+gceSTATUS
+gckOS_Construct(
+ IN gctPOINTER Context,
+ OUT gckOS * Os
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+ gctINT i;
+
+ gcmkHEADER_ARG("Context=0x%X", Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Os != gcvNULL);
+
+ /* Allocate the gckOS object. */
+ os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL | gcdNOWARN);
+
+ if (os == gcvNULL)
+ {
+ /* Out of memory. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ /* Zero the memory. */
+ gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
+
+ /* Initialize the gckOS object. */
+ os->object.type = gcvOBJ_OS;
+
+ /* Set device device. */
+ os->device = Context;
+
+ /* 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));
+ gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
+
+ /* Create debug lock mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &os->debugLock));
+
+ os->mdlHead = os->mdlTail = gcvNULL;
+
+ /* Get the kernel process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
+
+ /*
+ * Initialize the signal manager.
+ */
+
+ /* Initialize mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &os->signalMutex));
+
+ /* Initialize signal id database lock. */
+ spin_lock_init(&os->signalDB.lock);
+
+ /* Initialize signal id database. */
+ idr_init(&os->signalDB.idr);
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+ /*
+ * Initialize the sync point manager.
+ */
+
+ /* Initialize mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &os->syncPointMutex));
+
+ /* Initialize sync point id database lock. */
+ spin_lock_init(&os->syncPointDB.lock);
+
+ /* Initialize sync point id database. */
+ idr_init(&os->syncPointDB.idr);
+#endif
+
+ /* Create a workqueue for os timer. */
+ os->workqueue = create_singlethread_workqueue("galcore workqueue");
+
+ if (os->workqueue == gcvNULL)
+ {
+ /* Out of memory. */
+ 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;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Os=0x%X", *Os);
+ return gcvSTATUS_OK;
+
+OnError:
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+ if (os->syncPointMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->syncPointMutex));
+ }
+#endif
+
+ if (os->signalMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->signalMutex));
+ }
+
+ if (os->memoryMapLock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->memoryMapLock));
+ }
+
+ if (os->memoryLock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->memoryLock));
+ }
+
+ if (os->debugLock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->debugLock));
+ }
+
+ if (os->workqueue != gcvNULL)
+ {
+ destroy_workqueue(os->workqueue);
+ }
+
+ kfree(os);
+
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Destroy
+**
+** Destroy an gckOS object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object that needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Destroy(
+ IN gckOS Os
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ if (Os->paddingPage != gcvNULL)
+ {
+ ClearPageReserved(Os->paddingPage);
+ __free_page(Os->paddingPage);
+ Os->paddingPage = gcvNULL;
+ }
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+ /*
+ * Destroy the sync point manager.
+ */
+
+ /* Destroy the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->syncPointMutex));
+#endif
+
+ /*
+ * Destroy the signal manager.
+ */
+
+ /* Destroy the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->signalMutex));
+
+ /* Destroy the memory lock. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryMapLock));
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryLock));
+
+ /* Destroy debug lock mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->debugLock));
+
+ /* Wait for all works done. */
+ flush_workqueue(Os->workqueue);
+
+ /* 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);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_CreateKernelVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ )
+{
+ gceSTATUS status;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ gckALLOCATOR allocator = mdl->allocator;
+
+ gcmkHEADER();
+
+ *PageCount = mdl->numPages;
+
+ gcmkONERROR(allocator->ops->MapKernel(allocator, mdl, Logical));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_DestroyKernelVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ gckALLOCATOR allocator = mdl->allocator;
+
+ gcmkHEADER();
+
+ allocator->ops->UnmapKernel(allocator, mdl, Logical);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_CreateUserVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ )
+{
+ return gckOS_LockPages(Os, Physical, Bytes, gcvFALSE, Logical, PageCount);
+}
+
+gceSTATUS
+gckOS_DestroyUserVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ return gckOS_UnlockPages(Os, Physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+** gckOS_Allocate
+**
+** Allocate memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the allocated memory location.
+*/
+gceSTATUS
+gckOS_Allocate(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Free
+**
+** Free allocated memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Memory
+** Pointer to memory allocation to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Free(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Memory=0x%X", Os, Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ gcmkONERROR(gckOS_FreeMemory(Os, Memory));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocateMemory
+**
+** Allocate memory wrapper.
+**
+** INPUT:
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the allocated memory location.
+*/
+gceSTATUS
+gckOS_AllocateMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gctPOINTER memory;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ if (Bytes > PAGE_SIZE)
+ {
+ memory = (gctPOINTER) vmalloc(Bytes);
+ }
+ else
+ {
+ memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL | gcdNOWARN);
+ }
+
+ if (memory == gcvNULL)
+ {
+ /* Out of memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Increase count. */
+ atomic_inc(&Os->allocateCount);
+
+ /* Return pointer to the memory allocation. */
+ *Memory = memory;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeMemory
+**
+** Free allocated memory wrapper.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory allocation to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_FreeMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ )
+{
+ gcmkHEADER_ARG("Memory=0x%X", Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Free the memory from the OS pool. */
+ if (is_vmalloc_addr(Memory))
+ {
+ vfree(Memory);
+ }
+ else
+ {
+ kfree(Memory);
+ }
+
+ /* Decrease count. */
+ atomic_dec(&Os->allocateCount);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapMemory
+**
+** Map physical memory into the current process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the logical address of the
+** mapped memory.
+*/
+gceSTATUS
+gckOS_MapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ MEMORY_LOCK(Os);
+
+ mdlMap = FindMdlMap(mdl, _GetProcessID());
+
+ if (mdlMap == gcvNULL)
+ {
+ mdlMap = _CreateMdlMap(mdl, _GetProcessID());
+
+ if (mdlMap == gcvNULL)
+ {
+ MEMORY_UNLOCK(Os);
+
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ }
+
+ if (mdlMap->vmaAddr == gcvNULL)
+ {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+ mdlMap->vmaAddr = (char *)vm_mmap(gcvNULL,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+#else
+ down_write(&current->mm->mmap_sem);
+
+ mdlMap->vmaAddr = (char *)do_mmap_pgoff(gcvNULL,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+
+ up_write(&current->mm->mmap_sem);
+#endif
+
+ if (IS_ERR(mdlMap->vmaAddr))
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): do_mmap_pgoff error",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): mdl->numPages: %d mdl->vmaAddr: 0x%X",
+ __FUNCTION__, __LINE__,
+ mdl->numPages,
+ mdlMap->vmaAddr
+ );
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ MEMORY_UNLOCK(Os);
+
+ 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)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): find_vma error.",
+ __FUNCTION__, __LINE__
+ );
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ up_write(&current->mm->mmap_sem);
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+#ifndef NO_DMA_COHERENT
+ if (dma_mmap_writecombine(gcvNULL,
+ mdlMap->vma,
+ mdl->addr,
+ mdl->dmaHandle,
+ mdl->numPages * PAGE_SIZE) < 0)
+ {
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): dma_mmap_coherent error.",
+ __FUNCTION__, __LINE__
+ );
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+#else
+#if !gcdPAGED_MEMORY_CACHEABLE
+ mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
+ mdlMap->vma->vm_flags |= gcdVM_FLAGS;
+# endif
+ mdlMap->vma->vm_pgoff = 0;
+
+ if (remap_pfn_range(mdlMap->vma,
+ mdlMap->vma->vm_start,
+ mdl->dmaHandle >> PAGE_SHIFT,
+ mdl->numPages*PAGE_SIZE,
+ mdlMap->vma->vm_page_prot) < 0)
+ {
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): remap_pfn_range error.",
+ __FUNCTION__, __LINE__
+ );
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+#endif
+
+ up_write(&current->mm->mmap_sem);
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ *Logical = mdlMap->vmaAddr;
+
+ gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapMemory
+**
+** Unmap physical memory out of the current process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** gctPOINTER Memory
+** Pointer to a previously mapped memory region.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
+ Os, Physical, Bytes, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ gckOS_UnmapMemoryEx(Os, Physical, Bytes, Logical, _GetProcessID());
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckOS_UnmapMemoryEx
+**
+** Unmap physical memory in the specified process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** gctPOINTER Memory
+** Pointer to a previously mapped memory region.
+**
+** gctUINT32 PID
+** Pid of the process that opened the device and mapped this memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapMemoryEx(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical,
+ IN gctUINT32 PID
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X PID=%d",
+ Os, Physical, Bytes, Logical, PID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PID != 0);
+
+ MEMORY_LOCK(Os);
+
+ if (Logical)
+ {
+ mdlMap = FindMdlMap(mdl, PID);
+
+ if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
+ {
+ MEMORY_UNLOCK(Os);
+
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ _UnmapUserLogical(mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
+
+ gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapUserLogical
+**
+** Unmap user logical memory out of physical memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** gctPOINTER Memory
+** Pointer to a previously mapped memory region.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserLogical(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
+ Os, Physical, Bytes, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ gckOS_UnmapMemory(Os, Physical, Bytes, Logical);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocateNonPagedMemory
+**
+** Allocate a number of pages from non-paged memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the pages need to be mapped into user space.
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that holds the number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that hold the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that will hold the physical address of the
+** allocation.
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** allocation.
+*/
+gceSTATUS
+gckOS_AllocateNonPagedMemory(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+ gctSIZE_T bytes;
+ gctINT numPages;
+ PLINUX_MDL mdl = gcvNULL;
+ PLINUX_MDL_MAP mdlMap = gcvNULL;
+ gctSTRING addr;
+ gckKERNEL kernel;
+#ifdef NO_DMA_COHERENT
+ struct page * page;
+ long size, order;
+ gctPOINTER vaddr;
+#endif
+ gctBOOL locked = gcvFALSE;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
+ Os, InUserSpace, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
+ gcmkVERIFY_ARGUMENT(*Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Align number of bytes to page size. */
+ bytes = gcmALIGN(*Bytes, PAGE_SIZE);
+
+ /* Get total number of pages.. */
+ numPages = GetPageCount(bytes, 0);
+
+ /* Allocate mdl+vector structure */
+ mdl = _CreateMdl();
+ if (mdl == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ mdl->pagedMem = 0;
+ mdl->numPages = numPages;
+
+ MEMORY_LOCK(Os);
+ locked = gcvTRUE;
+
+#ifndef NO_DMA_COHERENT
+#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);
+
+ page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
+
+ if (page == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ vaddr = (gctPOINTER)page_address(page);
+ mdl->contiguous = gcvTRUE;
+ mdl->u.contiguousPages = page;
+ addr = _CreateKernelVirtualMapping(mdl);
+ mdl->dmaHandle = virt_to_phys(vaddr);
+ mdl->kaddr = vaddr;
+
+ /* Trigger a page fault. */
+ memset(addr, 0, numPages * PAGE_SIZE);
+
+#if !defined(CONFIG_PPC)
+ /* Cache invalidate. */
+ dma_sync_single_for_device(
+ gcvNULL,
+ page_to_phys(page),
+ bytes,
+ DMA_FROM_DEVICE);
+#endif
+
+ while (size > 0)
+ {
+ SetPageReserved(virt_to_page(vaddr));
+
+ vaddr += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+#endif
+
+ if (addr == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ kernel = Os->device->kernels[gcvCORE_MAJOR] != gcvNULL ?
+ Os->device->kernels[gcvCORE_MAJOR] : Os->device->kernels[gcvCORE_2D];
+
+#ifdef CONFLICT_BETWEEN_BASE_AND_PHYS
+ if (((Os->device->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000)) &&
+ kernel->hardware->mmuVersion == 0)
+ {
+ mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
+ | (Os->device->baseAddress & 0x80000000);
+ }
+#endif
+
+ mdl->addr = addr;
+
+ if (InUserSpace)
+ {
+ mdlMap = _CreateMdlMap(mdl, _GetProcessID());
+
+ if (mdlMap == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Only after mmap this will be valid. */
+
+ /* We need to map this to user space. */
+#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
+
+ if (IS_ERR(mdlMap->vmaAddr))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d): do_mmap_pgoff error",
+ __FUNCTION__, __LINE__
+ );
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ down_write(&current->mm->mmap_sem);
+
+ mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+ if (mdlMap->vma == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d): find_vma error",
+ __FUNCTION__, __LINE__
+ );
+
+ up_write(&current->mm->mmap_sem);
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+#ifndef NO_DMA_COHERENT
+ if (dma_mmap_coherent(gcvNULL,
+ mdlMap->vma,
+ mdl->addr,
+ mdl->dmaHandle,
+ mdl->numPages * PAGE_SIZE) < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d): dma_mmap_coherent error",
+ __FUNCTION__, __LINE__
+ );
+
+ up_write(&current->mm->mmap_sem);
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+#else
+#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;
+
+ if (remap_pfn_range(mdlMap->vma,
+ mdlMap->vma->vm_start,
+ mdl->dmaHandle >> PAGE_SHIFT,
+ mdl->numPages * PAGE_SIZE,
+ mdlMap->vma->vm_page_prot))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d): remap_pfn_range error",
+ __FUNCTION__, __LINE__
+ );
+
+ up_write(&current->mm->mmap_sem);
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+#endif /* NO_DMA_COHERENT */
+
+ up_write(&current->mm->mmap_sem);
+
+ *Logical = mdlMap->vmaAddr;
+ }
+ else
+ {
+#if gcdSECURITY
+ *Logical = (gctPOINTER)mdl->kaddr;
+#else
+ *Logical = (gctPOINTER)mdl->addr;
+#endif
+ }
+
+ /*
+ * Add this to a global list.
+ * Will be used by get physical address
+ * and mapuser pointer functions.
+ */
+
+ if (!Os->mdlHead)
+ {
+ /* Initialize the queue. */
+ Os->mdlHead = Os->mdlTail = mdl;
+ }
+ else
+ {
+ /* Add to the tail. */
+ mdl->prev = Os->mdlTail;
+ Os->mdlTail->next = mdl;
+ Os->mdlTail = mdl;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Return allocated memory. */
+ *Bytes = bytes;
+ *Physical = (gctPHYS_ADDR) mdl;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
+ *Bytes, *Physical, *Logical);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mdlMap != gcvNULL)
+ {
+ /* Free LINUX_MDL_MAP. */
+ gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+ }
+
+ if (mdl != gcvNULL)
+ {
+ /* Free LINUX_MDL. */
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+ }
+
+ if (locked)
+ {
+ /* Unlock memory. */
+ MEMORY_UNLOCK(Os);
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeNonPagedMemory
+**
+** Free previously allocated and mapped pages from non-paged memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes allocated.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocated memory.
+**
+** gctPOINTER Logical
+** Logical address of the allocated memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_FreeNonPagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ )
+{
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap;
+#ifdef NO_DMA_COHERENT
+ unsigned size;
+ gctPOINTER vaddr;
+#endif /* NO_DMA_COHERENT */
+
+ gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
+ Os, Bytes, Physical, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Convert physical address into a pointer to a MDL. */
+ mdl = (PLINUX_MDL) Physical;
+
+ MEMORY_LOCK(Os);
+
+#ifndef NO_DMA_COHERENT
+#ifdef CONFIG_ARM64
+ dma_free_coherent(gcvNULL,
+#else
+ dma_free_writecombine(gcvNULL,
+#endif
+ mdl->numPages * PAGE_SIZE,
+ mdl->addr,
+ mdl->dmaHandle);
+#else
+ size = mdl->numPages * PAGE_SIZE;
+ vaddr = mdl->kaddr;
+
+ while (size > 0)
+ {
+ ClearPageReserved(virt_to_page(vaddr));
+
+ vaddr += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+
+ free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
+
+ _DestoryKernelVirtualMapping(mdl->addr);
+#endif /* NO_DMA_COHERENT */
+
+ mdlMap = mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ /* No mapped memory exists when free nonpaged memory */
+ gcmkASSERT(mdlMap->vmaAddr == gcvNULL);
+
+ mdlMap = mdlMap->next;
+ }
+
+ /* Remove the node from global list.. */
+ if (mdl == Os->mdlHead)
+ {
+ if ((Os->mdlHead = mdl->next) == gcvNULL)
+ {
+ Os->mdlTail = gcvNULL;
+ }
+ }
+ else
+ {
+ mdl->prev->next = mdl->next;
+ if (mdl == Os->mdlTail)
+ {
+ Os->mdlTail = mdl->prev;
+ }
+ else
+ {
+ mdl->next->prev = mdl->prev;
+ }
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReadRegister
+**
+** Read data from a register.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Address of register.
+**
+** OUTPUT:
+**
+** gctUINT32 * Data
+** Pointer to a variable that receives the data read from the register.
+*/
+gceSTATUS
+gckOS_ReadRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ )
+{
+ return gckOS_ReadRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
+}
+
+gceSTATUS
+gckOS_ReadRegisterEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+#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->registerBase3D[CoreId] + Address);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Data=0x%08x", *Data);
+ return gcvSTATUS_OK;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckOS_WriteRegister
+**
+** Write data to a register.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Address of register.
+**
+** gctUINT32 Data
+** Data for register.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WriteRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ )
+{
+ return gckOS_WriteRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
+}
+
+gceSTATUS
+gckOS_WriteRegisterEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
+
+#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->registerBase3D[CoreId] + Address);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckOS_GetPageSize
+**
+** Get the system's page size.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * PageSize
+** Pointer to a variable that will receive the system's page size.
+*/
+gceSTATUS gckOS_GetPageSize(
+ IN gckOS Os,
+ OUT gctSIZE_T * PageSize
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
+
+ /* Return the page size. */
+ *PageSize = (gctSIZE_T) PAGE_SIZE;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*PageSize", *PageSize);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetPhysicalAddressProcess
+**
+** Get the physical system address of a corresponding virtual address for a
+** given process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctPOINTER Logical
+** Logical address.
+**
+** gctUINT32 ProcessID
+** Process ID.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Poinetr to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS
+_GetPhysicalAddressProcess(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctUINT32 ProcessID,
+ OUT gctPHYS_ADDR_T * Address
+ )
+{
+ 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);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ MEMORY_LOCK(Os);
+
+ /* First try the contiguous memory pool. */
+ if (Os->device->contiguousMapped)
+ {
+ base = (gctINT8_PTR) Os->device->contiguousBase;
+
+ if (((gctINT8_PTR) Logical >= base)
+ && ((gctINT8_PTR) Logical < base + Os->device->contiguousSize)
+ )
+ {
+ /* Convert logical address into physical. */
+ *Address = Os->device->contiguousVidMem->baseAddress
+ + (gctINT8_PTR) Logical - base;
+ status = gcvSTATUS_OK;
+ }
+ }
+ else
+ {
+ /* Try the contiguous memory pool. */
+ mdl = (PLINUX_MDL) Os->device->contiguousPhysical;
+ status = _ConvertLogical2Physical(Os,
+ Logical,
+ ProcessID,
+ mdl,
+ Address);
+ }
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Walk all MDLs. */
+ for (mdl = Os->mdlHead; mdl != gcvNULL; mdl = mdl->next)
+ {
+ /* Try this MDL. */
+ 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;
+ }
+ }
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkONERROR(status);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=0x%08x", *Address);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+
+
+/*******************************************************************************
+**
+** gckOS_GetPhysicalAddress
+**
+** Get the physical system address of a corresponding virtual address.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Logical address.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Poinetr to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS
+gckOS_GetPhysicalAddress(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ OUT gctPHYS_ADDR_T * Address
+ )
+{
+ gceSTATUS status;
+ gctUINT32 processID;
+
+ gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Query page table of current process first. */
+ status = _QueryProcessPageTable(Logical, Address);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Get current process ID. */
+ processID = _GetProcessID();
+
+ /* Route through other function. */
+ gcmkONERROR(
+ _GetPhysicalAddressProcess(Os, Logical, processID, Address));
+ }
+
+ gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Os, *Address, Address));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=0x%08x", *Address);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ 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 gctPHYS_ADDR_T * Address
+ )
+{
+ return gckOS_GetPhysicalAddress(Os, Logical, Address);
+}
+
+#if gcdSECURE_USER
+static gceSTATUS
+gckOS_AddMapping(
+ IN gckOS Os,
+ IN gctUINT32 Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ gceSTATUS status;
+ gcsUSER_MAPPING_PTR map;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
+ Os, Physical, Logical, Bytes);
+
+ gcmkONERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(gcsUSER_MAPPING),
+ (gctPOINTER *) &map));
+
+ map->next = Os->userMap;
+ map->physical = Physical - Os->device->baseAddress;
+ map->logical = Logical;
+ map->bytes = Bytes;
+ map->start = (gctINT8_PTR) Logical;
+ map->end = map->start + Bytes;
+
+ Os->userMap = map;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+gckOS_RemoveMapping(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ gceSTATUS status;
+ gcsUSER_MAPPING_PTR map, prev;
+
+ gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
+
+ for (map = Os->userMap, prev = gcvNULL; map != gcvNULL; map = map->next)
+ {
+ if ((map->logical == Logical)
+ && (map->bytes == Bytes)
+ )
+ {
+ break;
+ }
+
+ prev = map;
+ }
+
+ if (map == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
+ }
+
+ if (prev == gcvNULL)
+ {
+ Os->userMap = map->next;
+ }
+ else
+ {
+ prev->next = map->next;
+ }
+
+ gcmkONERROR(gcmkOS_SAFE_FREE(Os, map));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+gceSTATUS
+_ConvertLogical2Physical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctUINT32 ProcessID,
+ IN PLINUX_MDL Mdl,
+ OUT gctPHYS_ADDR_T * Physical
+ )
+{
+ gctINT8_PTR base, vBase;
+ gctUINT32 offset;
+ 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)
+ && ((gctINT8_PTR) Logical >= base)
+ && ((gctINT8_PTR) Logical < base + Mdl->numPages * PAGE_SIZE)
+ )
+ {
+ offset = (gctINT8_PTR) Logical - base;
+
+ if (Mdl->dmaHandle != 0)
+ {
+ /* The memory was from coherent area. */
+ *Physical = (gctUINT32) Mdl->dmaHandle + offset;
+ }
+ else if (Mdl->pagedMem && !Mdl->contiguous)
+ {
+ /* paged memory is not mapped to kernel space. */
+ return gcvSTATUS_INVALID_ADDRESS;
+ }
+ else
+ {
+ *Physical = gcmPTR2INT32(virt_to_phys(base)) + offset;
+ }
+
+ return gcvSTATUS_OK;
+ }
+
+ /* Walk user maps. */
+ for (userMap = Os->userMap; userMap != gcvNULL; userMap = userMap->next)
+ {
+ if (((gctINT8_PTR) Logical >= userMap->start)
+ && ((gctINT8_PTR) Logical < userMap->end)
+ )
+ {
+ *Physical = userMap->physical
+ + (gctUINT32) ((gctINT8_PTR) Logical - userMap->start);
+
+ return gcvSTATUS_OK;
+ }
+ }
+
+ if (ProcessID != Os->kernelProcessID)
+ {
+ map = FindMdlMap(Mdl, (gctINT) ProcessID);
+ vBase = (map == gcvNULL) ? gcvNULL : (gctINT8_PTR) map->vmaAddr;
+
+ /* Is the given address within that range. */
+ if ((vBase != gcvNULL)
+ && ((gctINT8_PTR) Logical >= vBase)
+ && ((gctINT8_PTR) Logical < vBase + Mdl->numPages * PAGE_SIZE)
+ )
+ {
+ offset = (gctINT8_PTR) Logical - vBase;
+
+ if (Mdl->dmaHandle != 0)
+ {
+ /* The memory was from coherent area. */
+ *Physical = (gctUINT32) Mdl->dmaHandle + offset;
+ }
+ else if (Mdl->pagedMem && !Mdl->contiguous)
+ {
+ *Physical = _NonContiguousToPhys(Mdl->u.nonContiguousPages, offset/PAGE_SIZE);
+ }
+ else
+ {
+ *Physical = page_to_phys(Mdl->u.contiguousPages) + offset;
+ }
+
+ return gcvSTATUS_OK;
+ }
+ }
+
+ /* Address not yet found. */
+ return gcvSTATUS_INVALID_ADDRESS;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapPhysical
+**
+** Map a physical address into kernel space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Physical
+** Physical address of the memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the base address of the mapped
+** memory.
+*/
+gceSTATUS
+gckOS_MapPhysical(
+ IN gckOS Os,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ gctPOINTER logical;
+ PLINUX_MDL mdl;
+ gctUINT32 physical = Physical;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ MEMORY_LOCK(Os);
+
+ /* Go through our mapping to see if we know this physical address already. */
+ mdl = Os->mdlHead;
+
+ while (mdl != gcvNULL)
+ {
+ if (mdl->dmaHandle != 0)
+ {
+ if ((physical >= mdl->dmaHandle)
+ && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
+ )
+ {
+ *Logical = mdl->addr + (physical - mdl->dmaHandle);
+ break;
+ }
+ }
+
+ mdl = mdl->next;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ if (mdl == gcvNULL)
+ {
+ struct page * page = pfn_to_page(physical >> PAGE_SHIFT);
+
+ 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);
+ }
+
+ 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
+ {
+ /* Map memory as cached memory. */
+ request_mem_region(physical, Bytes, "MapRegion");
+ logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
+
+ if (logical == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): Failed to ioremap",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Out of resources. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+ }
+
+ /* Return pointer to mapped memory. */
+ *Logical = logical;
+ }
+
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapPhysical
+**
+** Unmap a previously mapped memory region from kernel memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Pointer to the base address of the memory to unmap.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapPhysical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ PLINUX_MDL mdl;
+
+ gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ MEMORY_LOCK(Os);
+
+ mdl = Os->mdlHead;
+
+ while (mdl != gcvNULL)
+ {
+ if (mdl->addr != gcvNULL)
+ {
+ if (Logical >= (gctPOINTER)mdl->addr
+ && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
+ {
+ break;
+ }
+ }
+
+ mdl = mdl->next;
+ }
+
+ if (mdl == gcvNULL)
+ {
+ /* Unmap the memory. */
+ vunmap((void *)((unsigned long)Logical & PAGE_MASK));
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_DeleteMutex
+**
+** Delete a mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mute to be deleted.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DeleteMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os, Mutex);
+
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ /* Destroy the mutex. */
+ mutex_destroy((struct mutex *)Mutex);
+
+ /* Free the mutex structure. */
+ gcmkONERROR(gckOS_Free(Os, Mutex));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AcquireMutex
+**
+** Acquire a mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mutex to be acquired.
+**
+** gctUINT32 Timeout
+** Timeout value specified in milliseconds.
+** Specify the value of gcvINFINITE to keep the thread suspended
+** until the mutex has been acquired.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AcquireMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ )
+{
+ 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 (Timeout == gcvINFINITE)
+ {
+ /* Lock the mutex. */
+ mutex_lock(Mutex);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ for (;;)
+ {
+ /* Try to acquire the mutex. */
+ if (mutex_trylock(Mutex))
+ {
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ if (Timeout-- == 0)
+ {
+ break;
+ }
+
+ /* Wait for 1 millisecond. */
+ gcmkVERIFY_OK(gckOS_Delay(Os, 1));
+ }
+
+ /* Timeout. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
+ return gcvSTATUS_TIMEOUT;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReleaseMutex
+**
+** Release an acquired mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mutex to be released.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_ReleaseMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os, Mutex);
+
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ /* Release the mutex. */
+ mutex_unlock(Mutex);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomicExchange
+**
+** Atomically exchange a pair of 32-bit values.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN OUT gctINT32_PTR Target
+** Pointer to the 32-bit value to exchange.
+**
+** IN gctINT32 NewValue
+** Specifies a new value for the 32-bit value pointed to by Target.
+**
+** OUT gctINT32_PTR OldValue
+** The old value of the 32-bit value pointed to by Target.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomicExchange(
+ IN gckOS Os,
+ IN OUT gctUINT32_PTR Target,
+ IN gctUINT32 NewValue,
+ OUT gctUINT32_PTR OldValue
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os, Target, NewValue);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(OldValue != gcvNULL);
+
+ /* Exchange the pair of 32-bit values. */
+ *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*OldValue=%u", *OldValue);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomicExchangePtr
+**
+** Atomically exchange a pair of pointers.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN OUT gctPOINTER * Target
+** Pointer to the 32-bit value to exchange.
+**
+** IN gctPOINTER NewValue
+** Specifies a new value for the pointer pointed to by Target.
+**
+** OUT gctPOINTER * OldValue
+** The old value of the pointer pointed to by Target.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomicExchangePtr(
+ IN gckOS Os,
+ IN OUT gctPOINTER * Target,
+ IN gctPOINTER NewValue,
+ OUT gctPOINTER * OldValue
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os, Target, NewValue);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(OldValue != gcvNULL);
+
+ /* Exchange the pair of pointers. */
+ *OldValue = (gctPOINTER)(gctUINTPTR_T) atomic_xchg((atomic_t *) Target, (int)(gctUINTPTR_T) NewValue);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomicSetMask
+**
+** Atomically set mask to Atom
+**
+** INPUT:
+** IN OUT gctPOINTER Atom
+** Pointer to the atom to set.
+**
+** IN gctUINT32 Mask
+** Mask to set.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomSetMask(
+ IN gctPOINTER Atom,
+ IN gctUINT32 Mask
+ )
+{
+ gctUINT32 oval, nval;
+
+ gcmkHEADER_ARG("Atom=0x%0x", Atom);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ do
+ {
+ oval = atomic_read((atomic_t *) Atom);
+ nval = oval | Mask;
+ } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomClearMask
+**
+** Atomically clear mask from Atom
+**
+** INPUT:
+** IN OUT gctPOINTER Atom
+** Pointer to the atom to clear.
+**
+** IN gctUINT32 Mask
+** Mask to clear.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomClearMask(
+ IN gctPOINTER Atom,
+ IN gctUINT32 Mask
+ )
+{
+ gctUINT32 oval, nval;
+
+ gcmkHEADER_ARG("Atom=0x%0x", Atom);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ do
+ {
+ oval = atomic_read((atomic_t *) Atom);
+ nval = oval & ~Mask;
+ } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomConstruct
+**
+** Create an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Atom
+** Pointer to a variable receiving the constructed atom.
+*/
+gceSTATUS
+gckOS_AtomConstruct(
+ IN gckOS Os,
+ OUT gctPOINTER * Atom
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Allocate the atom. */
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
+
+ /* Initialize the atom. */
+ atomic_set((atomic_t *) *Atom, 0);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Atom=0x%X", *Atom);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomDestroy
+**
+** Destroy an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomDestroy(
+ IN gckOS Os,
+ OUT gctPOINTER Atom
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Free the atom. */
+ gcmkONERROR(gcmkOS_SAFE_FREE(Os, Atom));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomGet
+**
+** Get the 32-bit value protected by an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the value of the atom.
+*/
+gceSTATUS
+gckOS_AtomGet(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Return the current value of atom. */
+ *Value = atomic_read((atomic_t *) Atom);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=%d", *Value);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomSet
+**
+** Set the 32-bit value protected by an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** gctINT32 Value
+** The value of the atom.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomSet(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ IN gctINT32 Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Set the current value of atom. */
+ atomic_set((atomic_t *) Atom, Value);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomIncrement
+**
+** Atomically increment the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable that receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomIncrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Increment the atom. */
+ *Value = atomic_inc_return((atomic_t *) Atom) - 1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=%d", *Value);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomDecrement
+**
+** Atomically decrement the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable that receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomDecrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Decrement the atom. */
+ *Value = atomic_dec_return((atomic_t *) Atom) + 1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=%d", *Value);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_Delay
+**
+** Delay execution of the current thread for a number of milliseconds.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Delay
+** Delay to sleep, specified in milliseconds.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Delay(
+ IN gckOS Os,
+ IN gctUINT32 Delay
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Delay=%u", Os, Delay);
+
+ if (Delay > 0)
+ {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+ 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. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetTicks
+**
+** Get the number of milliseconds since the system started.
+**
+** INPUT:
+**
+** OUTPUT:
+**
+** gctUINT32_PTR Time
+** Pointer to a variable to get time.
+**
+*/
+gceSTATUS
+gckOS_GetTicks(
+ OUT gctUINT32_PTR Time
+ )
+{
+ gcmkHEADER();
+
+ *Time = jiffies_to_msecs(jiffies);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_TicksAfter
+**
+** Compare time values got from gckOS_GetTicks.
+**
+** INPUT:
+** gctUINT32 Time1
+** First time value to be compared.
+**
+** gctUINT32 Time2
+** Second time value to be compared.
+**
+** OUTPUT:
+**
+** gctBOOL_PTR IsAfter
+** Pointer to a variable to result.
+**
+*/
+gceSTATUS
+gckOS_TicksAfter(
+ IN gctUINT32 Time1,
+ IN gctUINT32 Time2,
+ OUT gctBOOL_PTR IsAfter
+ )
+{
+ gcmkHEADER();
+
+ *IsAfter = time_after((unsigned long)Time1, (unsigned long)Time2);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetTime
+**
+** Get the number of microseconds since the system started.
+**
+** INPUT:
+**
+** OUTPUT:
+**
+** gctUINT64_PTR Time
+** Pointer to a variable to get time.
+**
+*/
+gceSTATUS
+gckOS_GetTime(
+ OUT gctUINT64_PTR Time
+ )
+{
+ struct timeval tv;
+ gcmkHEADER();
+
+ /* Return the time of day in microseconds. */
+ do_gettimeofday(&tv);
+ *Time = (tv.tv_sec * 1000000ULL) + tv.tv_usec;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MemoryBarrier
+**
+** Make sure the CPU has executed everything up to this point and the data got
+** written to the specified pointer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Address
+** Address of memory that needs to be barriered.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_MemoryBarrier(
+ IN gckOS Os,
+ IN gctPOINTER Address
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+#if gcdNONPAGED_MEMORY_BUFFERABLE \
+ && defined (CONFIG_ARM) \
+ && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+ /* drain write buffer */
+ dsb();
+
+ /* drain outer cache's write buffer? */
+#else
+ mb();
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocatePagedMemory
+**
+** Allocate memory from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+*/
+gceSTATUS
+gckOS_AllocatePagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+
+ /* Allocate the memory. */
+ gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvALLOC_FLAG_NONE, Bytes, gcvNULL, Physical));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocatePagedMemoryEx
+**
+** Allocate memory from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** 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.
+*/
+gceSTATUS
+gckOS_AllocatePagedMemoryEx(
+ IN gckOS Os,
+ IN gctUINT32 Flag,
+ IN gctSIZE_T Bytes,
+ OUT gctUINT32 * Gid,
+ OUT gctPHYS_ADDR * Physical
+ )
+{
+ gctINT numPages;
+ PLINUX_MDL mdl = gcvNULL;
+ gctSIZE_T bytes;
+ gceSTATUS status = gcvSTATUS_OUT_OF_MEMORY;
+ gckALLOCATOR allocator;
+
+ gcmkHEADER_ARG("Os=0x%X Flag=%x Bytes=%lu", Os, Flag, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+
+ bytes = gcmALIGN(Bytes, PAGE_SIZE);
+
+ numPages = GetPageCount(bytes, 0);
+
+ mdl = _CreateMdl();
+ if (mdl == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Walk all allocators. */
+ list_for_each_entry(allocator, &Os->allocatorList, head)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d) flag = %x allocator->capability = %x",
+ __FUNCTION__, __LINE__, Flag, allocator->capability);
+
+ if ((Flag & allocator->capability) != Flag)
+ {
+ continue;
+ }
+
+ status = allocator->ops->Alloc(allocator, mdl, numPages, Flag);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ mdl->allocator = allocator;
+ break;
+ }
+ }
+
+ /* Check status. */
+ gcmkONERROR(status);
+
+ mdl->dmaHandle = 0;
+ mdl->addr = 0;
+ mdl->numPages = numPages;
+ mdl->pagedMem = 1;
+ mdl->contiguous = Flag & gcvALLOC_FLAG_CONTIGUOUS;
+
+ if (Gid != gcvNULL)
+ {
+ *Gid = mdl->gid;
+ }
+
+ MEMORY_LOCK(Os);
+
+ /*
+ * Add this to a global list.
+ * Will be used by get physical address
+ * and mapuser pointer functions.
+ */
+ if (!Os->mdlHead)
+ {
+ /* Initialize the queue. */
+ Os->mdlHead = Os->mdlTail = mdl;
+ }
+ else
+ {
+ /* Add to tail. */
+ mdl->prev = Os->mdlTail;
+ Os->mdlTail->next = mdl;
+ Os->mdlTail = mdl;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Return physical address. */
+ *Physical = (gctPHYS_ADDR) mdl;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mdl != gcvNULL)
+ {
+ /* Free the memory. */
+ _DestroyMdl(mdl);
+ }
+
+ /* Return the status. */
+ gcmkFOOTER_ARG("Os=0x%X Flag=%x Bytes=%lu", Os, Flag, Bytes);
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreePagedMemory
+**
+** Free memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_FreePagedMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes
+ )
+{
+ PLINUX_MDL mdl = (PLINUX_MDL) Physical;
+ gckALLOCATOR allocator = (gckALLOCATOR)mdl->allocator;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ MEMORY_LOCK(Os);
+
+ /* Remove the node from global list. */
+ if (mdl == Os->mdlHead)
+ {
+ if ((Os->mdlHead = mdl->next) == gcvNULL)
+ {
+ Os->mdlTail = gcvNULL;
+ }
+ }
+ else
+ {
+ mdl->prev->next = mdl->next;
+
+ if (mdl == Os->mdlTail)
+ {
+ Os->mdlTail = mdl->prev;
+ }
+ else
+ {
+ mdl->next->prev = mdl->prev;
+ }
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ allocator->ops->Free(allocator, mdl);
+
+ /* Free the structure... */
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_LockPages
+**
+** Lock memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** gctBOOL Cacheable
+** Cache mode of mapping.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the address of the mapped
+** memory.
+**
+** gctSIZE_T * PageCount
+** Pointer to a variable that receives the number of pages required for
+** the page table according to the GPU page size.
+*/
+gceSTATUS
+gckOS_LockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL Cacheable,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ )
+{
+ gceSTATUS status;
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap;
+ gckALLOCATOR allocator;
+
+ 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;
+ allocator = mdl->allocator;
+
+ 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)
+ {
+ status = allocator->ops->MapUser(allocator, mdl, mdlMap, Cacheable);
+
+ if (gcmIS_ERROR(status))
+ {
+ MEMORY_UNLOCK(Os);
+
+ gcmkFOOTER_ARG("*status=%d", status);
+ return status;
+ }
+ }
+
+ mdlMap->count++;
+
+ /* Convert pointer to MDL. */
+ *Logical = mdlMap->vmaAddr;
+
+ /* Return the page number according to the GPU page size. */
+ gcmkASSERT((PAGE_SIZE % 4096) == 0);
+ gcmkASSERT((PAGE_SIZE / 4096) >= 1);
+
+ *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkVERIFY_OK(gckOS_CacheFlush(
+ Os,
+ _GetProcessID(),
+ Physical,
+ gcvINVALID_ADDRESS,
+ (gctPOINTER)mdlMap->vmaAddr,
+ mdl->numPages * PAGE_SIZE
+ ));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical, *PageCount);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapPages
+**
+** Map paged memory into a page table.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T PageCount
+** Number of pages required for the physical address.
+**
+** gctPOINTER PageTable
+** Pointer to the page table to fill in.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_MapPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T PageCount,
+ IN gctPOINTER PageTable
+ )
+{
+ return gckOS_MapPagesEx(Os,
+ gcvCORE_MAJOR,
+ Physical,
+ PageCount,
+ 0,
+ PageTable);
+}
+
+gceSTATUS
+gckOS_MapPagesEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T PageCount,
+ IN gctUINT32 Address,
+ IN gctPOINTER PageTable
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ PLINUX_MDL mdl;
+ gctUINT32* table;
+ gctUINT32 offset;
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ gckMMU mmu;
+ PLINUX_MDL mmuMdl;
+ gctUINT32 bytes;
+ 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);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+
+ /* Convert pointer to MDL. */
+ mdl = (PLINUX_MDL)Physical;
+
+ allocator = mdl->allocator;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
+ __FUNCTION__, __LINE__,
+ (gctUINT32)(gctUINTPTR_T)Physical,
+ (gctUINT32)(gctUINTPTR_T)PageCount,
+ mdl->pagedMem
+ );
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gcmkONERROR(gckKERNEL_GetProcessMMU(kernel, &mmu));
+#endif
+
+ table = (gctUINT32 *)PageTable;
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ mmu = Os->device->kernels[Core]->mmu;
+ bytes = PageCount * sizeof(*table);
+ mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical;
+#endif
+
+ /* 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)
+ {
+ gctUINT i;
+ gctPHYS_ADDR_T phys = ~0U;
+
+ 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)
+ {
+ for (i = 0; i < (PAGE_SIZE / 4096); i++)
+ {
+ gcmkONERROR(
+ gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
+ phys + (i * 4096),
+ table++));
+ }
+ }
+ else
+#endif
+ {
+ 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(mmu,
+ phys + (i * 4096),
+ pageTableEntry));
+#else
+ gcmkONERROR(
+ gckMMU_SetPage(Os->device->kernels[Core]->mmu,
+ phys + (i * 4096),
+ table++));
+#endif
+ }
+ }
+ }
+
+ offset += 1;
+ }
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Get physical address of pageTable */
+ pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle +
+ ((gctUINT32 *)PageTable - mmu->pageTableLogical));
+
+ /* Flush the mmu page table cache. */
+ gcmkONERROR(gckOS_CacheClean(
+ Os,
+ _GetProcessID(),
+ gcvNULL,
+ pageTablePhysical,
+ PageTable,
+ bytes
+ ));
+#endif
+
+OnError:
+
+ /* 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
+**
+** Unlock memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** gctPOINTER Logical
+** Address of the mapped memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnlockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ gckALLOCATOR allocator = mdl->allocator;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
+ Os, Physical, Bytes, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ MEMORY_LOCK(Os);
+
+ mdlMap = mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ if ((mdlMap->vmaAddr != gcvNULL) && (_GetProcessID() == mdlMap->pid))
+ {
+ if (--mdlMap->count == 0)
+ {
+ allocator->ops->UnmapUser(
+ allocator,
+ mdlMap->vmaAddr,
+ mdl->numPages * PAGE_SIZE);
+
+ mdlMap->vmaAddr = gcvNULL;
+ }
+ }
+
+ mdlMap = mdlMap->next;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckOS_AllocateContiguous
+**
+** Allocate memory from the contiguous pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the pages need to be mapped into user space.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that receives the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the logical address of the
+** memory allocation.
+*/
+gceSTATUS
+gckOS_AllocateContiguous(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
+ Os, InUserSpace, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
+ gcmkVERIFY_ARGUMENT(*Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Same as non-paged memory for now. */
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(Os,
+ InUserSpace,
+ Bytes,
+ Physical,
+ Logical));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
+ *Bytes, *Physical, *Logical);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeContiguous
+**
+** Free memory allocated from the contiguous pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctPOINTER Logical
+** Logicval address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_FreeContiguous(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
+ Os, Physical, Logical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ /* Same of non-paged memory for now. */
+ gcmkONERROR(gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdENABLE_VG
+/******************************************************************************
+**
+** gckOS_GetKernelLogical
+**
+** Return the kernel logical pointer that corresponods to the specified
+** hardware address.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Hardware physical address.
+**
+** OUTPUT:
+**
+** gctPOINTER * KernelPointer
+** Pointer to a variable receiving the pointer in kernel address space.
+*/
+gceSTATUS
+gckOS_GetKernelLogical(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ return gckOS_GetKernelLogicalEx(Os, gcvCORE_MAJOR, Address, KernelPointer);
+}
+
+gceSTATUS
+gckOS_GetKernelLogicalEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%08x", Os, Core, Address);
+
+ do
+ {
+ gckGALDEVICE device;
+ gckKERNEL kernel;
+ gcePOOL pool;
+ gctUINT32 offset;
+ gctPOINTER logical;
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Os->device;
+
+ /* Kernel shortcut. */
+ kernel = device->kernels[Core];
+#if gcdENABLE_VG
+ if (Core == gcvCORE_VG)
+ {
+ gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(
+ kernel->vg->hardware, Address, &pool, &offset
+ ));
+ }
+ else
+#endif
+ {
+ /* Split the memory address into a pool type and offset. */
+ gcmkERR_BREAK(gckHARDWARE_SplitMemory(
+ kernel->hardware, Address, &pool, &offset
+ ));
+ }
+
+ /* Dispatch on pool. */
+ switch (pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ logical = device->internalLogical;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ logical = device->externalLogical;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ logical = device->contiguousBase;
+ break;
+
+ default:
+ /* Invalid memory pool. */
+ gcmkFOOTER();
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Build logical address of specified address. */
+ * KernelPointer = ((gctUINT8_PTR) logical) + offset;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckOS_MapUserPointer
+**
+** Map a pointer from the user process into the kernel address space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Pointer
+** Pointer in user process space that needs to be mapped.
+**
+** gctSIZE_T Size
+** Number of bytes that need to be mapped.
+**
+** OUTPUT:
+**
+** gctPOINTER * KernelPointer
+** Pointer to a variable receiving the mapped pointer in kernel address
+** space.
+*/
+gceSTATUS
+gckOS_MapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gctPOINTER buf = gcvNULL;
+ gctUINT32 len;
+
+ gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os, Pointer, Size);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+
+ buf = kmalloc(Size, GFP_KERNEL | gcdNOWARN);
+ if (buf == gcvNULL)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): Failed to allocate memory.",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ len = copy_from_user(buf, Pointer, Size);
+ if (len != 0)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): Failed to copy data from user.",
+ __FUNCTION__, __LINE__
+ );
+
+ if (buf != gcvNULL)
+ {
+ kfree(buf);
+ }
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_GENERIC_IO);
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ *KernelPointer = buf;
+
+ gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapUserPointer
+**
+** Unmap a user process pointer from the kernel address space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Pointer
+** Pointer in user process space that needs to be unmapped.
+**
+** gctSIZE_T Size
+** Number of bytes that need to be unmapped.
+**
+** gctPOINTER KernelPointer
+** Pointer in kernel address space that needs to be unmapped.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ IN gctPOINTER KernelPointer
+ )
+{
+ gctUINT32 len;
+
+ gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
+ Os, Pointer, Size, KernelPointer);
+
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+
+ len = copy_to_user(Pointer, KernelPointer, Size);
+
+ kfree(KernelPointer);
+
+ if (len != 0)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): Failed to copy data to user.",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_GENERIC_IO);
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_QueryNeedCopy
+**
+** Query whether the memory can be accessed or mapped directly or it has to be
+** copied.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 ProcessID
+** Process ID of the current process.
+**
+** OUTPUT:
+**
+** gctBOOL_PTR NeedCopy
+** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
+** gcvFALSE if the memory can be accessed or mapped dircetly.
+*/
+gceSTATUS
+gckOS_QueryNeedCopy(
+ IN gckOS Os,
+ IN gctUINT32 ProcessID,
+ OUT gctBOOL_PTR NeedCopy
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(NeedCopy != gcvNULL);
+
+ /* We need to copy data. */
+ *NeedCopy = gcvTRUE;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_CopyFromUserData
+**
+** Copy data from user to kernel memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER KernelPointer
+** Pointer to kernel memory.
+**
+** gctPOINTER Pointer
+** Pointer to user memory.
+**
+** gctSIZE_T Size
+** Number of bytes to copy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_CopyFromUserData(
+ IN gckOS Os,
+ IN gctPOINTER KernelPointer,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
+ Os, KernelPointer, Pointer, Size);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+
+ /* Copy data from user. */
+ if (copy_from_user(KernelPointer, Pointer, Size) != 0)
+ {
+ /* Could not copy all the bytes. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_CopyToUserData
+**
+** Copy data from kernel to user memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER KernelPointer
+** Pointer to kernel memory.
+**
+** gctPOINTER Pointer
+** Pointer to user memory.
+**
+** gctSIZE_T Size
+** Number of bytes to copy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_CopyToUserData(
+ IN gckOS Os,
+ IN gctPOINTER KernelPointer,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
+ Os, KernelPointer, Pointer, Size);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+
+ /* Copy data to user. */
+ if (copy_to_user(Pointer, KernelPointer, Size) != 0)
+ {
+ /* Could not copy all the bytes. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_WriteMemory
+**
+** Write data to a memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Address
+** Address of the memory to write to.
+**
+** gctUINT32 Data
+** Data for register.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WriteMemory(
+ IN gckOS Os,
+ IN gctPOINTER Address,
+ IN gctUINT32 Data
+ )
+{
+ gceSTATUS status;
+ gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Write memory. */
+ if (access_ok(VERIFY_WRITE, Address, 4))
+ {
+ /* User address. */
+ if(put_user(Data, (gctUINT32*)Address))
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
+ }
+ }
+ else
+ {
+ /* Kernel address. */
+ *(gctUINT32 *)Address = Data;
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapUserMemory
+**
+** Lock down a user buffer and return an DMA'able address to be used by the
+** hardware to access it.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory to lock down.
+**
+** gctSIZE_T Size
+** Size in bytes of the memory to lock down.
+**
+** OUTPUT:
+**
+** gctPOINTER * Info
+** Pointer to variable receiving the information record required by
+** gckOS_UnmapUserMemory.
+**
+** gctUINT32_PTR Address
+** Pointer to a variable that will receive the address DMA'able by the
+** hardware.
+*/
+gceSTATUS
+gckOS_MapUserMemory(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPOINTER Memory,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x Core=%d Memory=0x%x Size=%lu", Os, Core, Memory, Size);
+
+#if gcdSECURE_USER
+ gcmkONERROR(gckOS_AddMapping(Os, *Address, Memory, Size));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+#else
+{
+ gctSIZE_T pageCount, i, j;
+ gctUINT32_PTR pageTable;
+ gctUINT32 address = 0, physical = ~0U;
+ 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;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0U);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ do
+ {
+ gctSIZE_T extraPage;
+
+ memory = (gctUINTPTR_T) Memory;
+
+ /* Get the number of required pages. */
+ end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ start = memory >> PAGE_SHIFT;
+ pageCount = end - start;
+
+ /* Allocate extra page to avoid cache overflow */
+#if gcdENABLE_2D
+ extraPage = 2;
+#else
+ extraPage = (((memory + gcmALIGN(Size + 64, 64) + PAGE_SIZE - 1) >> PAGE_SHIFT) > end) ? 1 : 0;
+#endif
+
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): pageCount: %d.",
+ __FUNCTION__, __LINE__,
+ pageCount
+ );
+
+ /* Overflow. */
+ if ((memory + Size) < memory)
+ {
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ MEMORY_MAP_LOCK(Os);
+
+ /* Allocate the Info struct. */
+ info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL | gcdNOWARN);
+
+ if (info == gcvNULL)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ break;
+ }
+
+ info->extraPage = 0;
+
+ /* Allocate the array of page addresses. */
+ pages = (struct page **)kmalloc((pageCount + extraPage) * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
+
+ if (pages == gcvNULL)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ break;
+ }
+
+ if (Physical != ~0U)
+ {
+ for (i = 0; i < pageCount; i++)
+ {
+ pages[i] = pfn_to_page((Physical >> PAGE_SHIFT) + i);
+
+ if (pfn_valid(page_to_pfn(pages[i])))
+ {
+ get_page(pages[i]);
+ }
+ }
+ }
+ else
+ {
+ /* Get the user pages. */
+ down_read(&current->mm->mmap_sem);
+
+ result = get_user_pages(memory & PAGE_MASK,
+ pageCount,
+ FOLL_WRITE,
+ pages,
+ gcvNULL
+ );
+
+ up_read(&current->mm->mmap_sem);
+
+ if (result <=0 || result < pageCount)
+ {
+ struct vm_area_struct *vma;
+
+ /* Release the pages if any. */
+ if (result > 0)
+ {
+ for (i = 0; i < result; i++)
+ {
+ if (pages[i] == gcvNULL)
+ {
+ break;
+ }
+
+ put_page(pages[i]);
+ pages[i] = gcvNULL;
+ }
+
+ result = 0;
+ }
+
+ vma = find_vma(current->mm, memory);
+
+ if (vma && (vma->vm_flags & VM_PFNMAP))
+ {
+ pte_t * pte;
+ spinlock_t * ptl;
+ gctUINTPTR_T logical = memory;
+
+ for (i = 0; i < pageCount; i++)
+ {
+ pgd_t * pgd = pgd_offset(current->mm, logical);
+ pud_t * pud = pud_offset(pgd, logical);
+
+ if (pud)
+ {
+ pmd_t * pmd = pmd_offset(pud, logical);
+ pte = pte_offset_map_lock(current->mm, pmd, logical, &ptl);
+ if (!pte)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+ else
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ pages[i] = pte_page(*pte);
+ pte_unmap_unlock(pte, ptl);
+
+ /* Advance to next. */
+ logical += PAGE_SIZE;
+ }
+ }
+ else
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Check if this memory is contiguous for old mmu. */
+ if (Os->device->kernels[Core]->hardware->mmuVersion == 0)
+ {
+ for (i = 1; i < pageCount; i++)
+ {
+ if (pages[i] != nth_page(pages[0], i))
+ {
+ /* Non-contiguous. */
+ break;
+ }
+ }
+
+ if (i == pageCount)
+ {
+ /* Contiguous memory. */
+ physical = page_to_phys(pages[0]) | (memory & ~PAGE_MASK);
+
+ if (!((physical - Os->device->baseAddress) & 0x80000000))
+ {
+ gctPHYS_ADDR_T gpuPhysical;
+ kfree(pages);
+ pages = gcvNULL;
+
+ info->pages = gcvNULL;
+ info->pageTable = gcvNULL;
+
+ MEMORY_MAP_UNLOCK(Os);
+
+ *Address = physical - Os->device->baseAddress;
+ *Info = info;
+
+ gcmkVERIFY_OK(
+ gckOS_CPUPhysicalToGPUPhysical(Os, *Address, &gpuPhysical));
+
+ gcmkSAFECASTPHYSADDRT(*Address, gpuPhysical);
+
+ gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
+ *Info, *Address);
+
+ return gcvSTATUS_OK;
+ }
+ }
+ }
+
+ /* Reference pages. */
+ for (i = 0; i < pageCount; i++)
+ {
+ if (pfn_valid(page_to_pfn(pages[i])))
+ {
+ get_page(pages[i]);
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < pageCount; i++)
+ {
+#ifdef CONFIG_ARM
+ gctUINT32 data;
+ get_user(data, (gctUINT32*)((memory & PAGE_MASK) + i * PAGE_SIZE));
+#endif
+
+ /* Flush(clean) the data cache. */
+ gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
+ 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)
+ {
+ for (i = 0; i < extraPage; i++)
+ {
+ pages[pageCount++] = Os->paddingPage;
+ }
+ info->extraPage = extraPage;
+ }
+
+#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)
+ {
+ /* Allocate pages inside the page table. */
+ gcmkERR_BREAK(gckVGMMU_AllocatePages(Os->device->kernels[Core]->vg->mmu,
+ pageCount * (PAGE_SIZE/4096),
+ (gctPOINTER *) &pageTable,
+ &address));
+ }
+ else
+#endif
+ {
+#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. */
+ for (i = 0; i < pageCount; i++)
+ {
+ gctPHYS_ADDR_T 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]);
+
+#ifdef CONFIG_IOMMU_SUPPORT
+ if (Os->iommu)
+ {
+ 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
+ {
+
+#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
+ if (Core == gcvCORE_VG)
+ {
+ gcmkONERROR(gckVGMMU_Flush(Os->device->kernels[Core]->vg->mmu));
+ }
+ else
+#endif
+ {
+#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;
+ info->pages = pages;
+
+ *Info = (gctPOINTER) info;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): info->pages: 0x%X, info->pageTable: 0x%X, info: 0x%X.",
+ __FUNCTION__, __LINE__,
+ info->pages,
+ info->pageTable,
+ info
+ );
+
+ offset = (Physical != ~0U)
+ ? (Physical & ~PAGE_MASK)
+ : (memory & ~PAGE_MASK);
+
+ /* Return address. */
+ *Address = address + offset;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): Address: 0x%X.",
+ __FUNCTION__, __LINE__,
+ *Address
+ );
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+OnError:
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): error occured: %d.",
+ __FUNCTION__, __LINE__,
+ status
+ );
+
+ /* Release page array. */
+ if (result > 0 && pages != gcvNULL)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): error: page table is freed.",
+ __FUNCTION__, __LINE__
+ );
+
+ for (i = 0; i < result; i++)
+ {
+ if (pages[i] == gcvNULL)
+ {
+ break;
+ }
+ put_page(pages[i]);
+ }
+ }
+
+ if (info!= gcvNULL && pages != gcvNULL)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): error: pages is freed.",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Free the page table. */
+ kfree(pages);
+ info->pages = gcvNULL;
+ }
+
+ /* Release page info struct. */
+ if (info != gcvNULL)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): error: info is freed.",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Free the page info struct. */
+ kfree(info);
+ *Info = gcvNULL;
+ }
+ }
+
+ MEMORY_MAP_UNLOCK(Os);
+
+ /* Return the status. */
+ if (gcmIS_SUCCESS(status))
+ {
+ gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", *Info, *Address);
+ }
+ else
+ {
+ gcmkFOOTER();
+ }
+
+ return status;
+}
+#endif
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapUserMemory
+**
+** Unlock a user buffer and that was previously locked down by
+** gckOS_MapUserMemory.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory to unlock.
+**
+** gctSIZE_T Size
+** Size in bytes of the memory to unlock.
+**
+** gctPOINTER Info
+** Information record returned by gckOS_MapUserMemory.
+**
+** gctUINT32_PTR Address
+** The address returned by gckOS_MapUserMemory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserMemory(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Core=%d Memory=0x%X Size=%lu Info=0x%X Address0x%08x",
+ Os, Core, Memory, Size, Info, Address);
+
+#if gcdSECURE_USER
+ gcmkONERROR(gckOS_RemoveMapping(Os, Memory, Size));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+#else
+{
+ gctUINTPTR_T memory, start, end;
+ gcsPageInfo_PTR info;
+ gctSIZE_T pageCount, i;
+ struct page **pages;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+
+ do
+ {
+ info = (gcsPageInfo_PTR) Info;
+
+ pages = info->pages;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): info=0x%X, pages=0x%X.",
+ __FUNCTION__, __LINE__,
+ info, pages
+ );
+
+ /* Invalid page array. */
+ if (pages == gcvNULL && info->pageTable == gcvNULL)
+ {
+ kfree(info);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ memory = (gctUINTPTR_T)Memory;
+ end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ start = memory >> PAGE_SHIFT;
+ pageCount = end - start;
+
+ /* Overflow. */
+ if ((memory + Size) < memory)
+ {
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): memory: 0x%X, pageCount: %d, pageTable: 0x%X.",
+ __FUNCTION__, __LINE__,
+ memory, pageCount, info->pageTable
+ );
+
+ MEMORY_MAP_LOCK(Os);
+
+#if !gcdSECURITY
+ gcmkASSERT(info->pageTable != gcvNULL);
+#endif
+
+ if (info->extraPage)
+ {
+ pageCount += info->extraPage;
+ }
+
+#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)
+ {
+ /* Free the pages from the MMU. */
+ gcmkERR_BREAK(gckVGMMU_FreePages(Os->device->kernels[Core]->vg->mmu,
+ info->pageTable,
+ pageCount * (PAGE_SIZE/4096)
+ ));
+ }
+ else
+#endif
+ {
+ /* Free the pages from the MMU. */
+#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 -= info->extraPage;
+ info->extraPage = 0;
+ }
+
+ /* Release the page cache. */
+ if (pages)
+ {
+ for (i = 0; i < pageCount; i++)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): pages[%d]: 0x%X.",
+ __FUNCTION__, __LINE__,
+ i, pages[i]
+ );
+
+ if (!PageReserved(pages[i]))
+ {
+ SetPageDirty(pages[i]);
+ }
+
+ if (pfn_valid(page_to_pfn(pages[i])))
+ {
+ put_page(pages[i]);
+ }
+ }
+ }
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ if (info != gcvNULL)
+ {
+ /* Free the page array. */
+ if (info->pages != gcvNULL)
+ {
+ kfree(info->pages);
+ }
+
+ kfree(info);
+ }
+
+ MEMORY_MAP_UNLOCK(Os);
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+}
+
+/*******************************************************************************
+**
+** gckOS_GetBaseAddress
+**
+** Get the base address for the physical memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR BaseAddress
+** Pointer to a variable that will receive the base address.
+*/
+gceSTATUS
+gckOS_GetBaseAddress(
+ IN gckOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+ /* Return base address. */
+ *BaseAddress = Os->device->baseAddress;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+ IN gckOS Os
+ )
+{
+ return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
+}
+
+#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,
+ IN gceCORE Core
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ disable_irq(Os->device->irqLines[Core]);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+ IN gckOS Os
+ )
+{
+ 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,
+ IN gceCORE Core
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ enable_irq(Os->device->irqLines[Core]);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif
+
+gceSTATUS
+gckOS_MemCopy(
+ IN gctPOINTER Destination,
+ IN gctCONST_POINTER Source,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
+ Destination, Source, Bytes);
+
+ gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Source != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ memcpy(Destination, Source, Bytes);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ZeroMemory(
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory, Bytes);
+
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ memset(Memory, 0, Bytes);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+********************************* Cache Control ********************************
+*******************************************************************************/
+
+/*******************************************************************************
+** gckOS_CacheClean
+**
+** Clean the cache for the specified addresses. The GPU is going to need the
+** data. If the system is allocating memory as non-cachable, this function can
+** be ignored.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctUINT32 ProcessID
+** Process ID Logical belongs.
+**
+** gctPHYS_ADDR Handle
+** Physical address handle. If gcvNULL it is video memory.
+**
+** gctPOINTER Physical
+** Physical address to flush.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheClean(
+ IN gckOS Os,
+ IN gctUINT32 ProcessID,
+ IN gctPHYS_ADDR Handle,
+ IN gctPHYS_ADDR_T 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);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ 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
+
+ /* Inner cache. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
+ dmac_flush_range(Logical, Logical + Bytes);
+# else
+ dmac_clean_range(Logical, Logical + Bytes);
+# endif
+
+#if defined(CONFIG_OUTER_CACHE)
+ /* Outer cache. */
+#if gcdENABLE_OUTER_CACHE_PATCH
+ _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_CLEAN);
+#else
+ outer_clean_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
+#endif
+#endif
+
+#elif defined(CONFIG_MIPS)
+
+ dma_cache_wback((unsigned long) Logical, Bytes);
+
+#elif defined(CONFIG_PPC)
+
+ /* TODO */
+
+#else
+ dma_sync_single_for_device(
+ gcvNULL,
+ (dma_addr_t)Physical,
+ Bytes,
+ DMA_TO_DEVICE);
+#endif
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** gckOS_CacheInvalidate
+**
+** Invalidate the cache for the specified addresses. The GPU is going to need
+** data. If the system is allocating memory as non-cachable, this function can
+** be ignored.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctUINT32 ProcessID
+** Process ID Logical belongs.
+**
+** gctPHYS_ADDR Handle
+** Physical address handle. If gcvNULL it is video memory.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheInvalidate(
+ IN gckOS Os,
+ IN gctUINT32 ProcessID,
+ IN gctPHYS_ADDR Handle,
+ IN gctPHYS_ADDR_T 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);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ 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
+
+ /* Inner cache. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
+ dmac_flush_range(Logical, Logical + Bytes);
+# else
+ dmac_inv_range(Logical, Logical + Bytes);
+# endif
+
+#if defined(CONFIG_OUTER_CACHE)
+ /* Outer cache. */
+#if gcdENABLE_OUTER_CACHE_PATCH
+ _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
+#else
+ outer_inv_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
+#endif
+#endif
+
+#elif defined(CONFIG_MIPS)
+ dma_cache_inv((unsigned long) Logical, Bytes);
+#elif defined(CONFIG_PPC)
+ /* TODO */
+#else
+ dma_sync_single_for_device(
+ gcvNULL,
+ (dma_addr_t)Physical,
+ Bytes,
+ DMA_FROM_DEVICE);
+#endif
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** gckOS_CacheFlush
+**
+** Clean the cache for the specified addresses and invalidate the lines as
+** well. The GPU is going to need and modify the data. If the system is
+** allocating memory as non-cachable, this function can be ignored.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctUINT32 ProcessID
+** Process ID Logical belongs.
+**
+** gctPHYS_ADDR Handle
+** Physical address handle. If gcvNULL it is video memory.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheFlush(
+ IN gckOS Os,
+ IN gctUINT32 ProcessID,
+ IN gctPHYS_ADDR Handle,
+ IN gctPHYS_ADDR_T 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);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ 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. */
+ dmac_flush_range(Logical, Logical + Bytes);
+
+#if defined(CONFIG_OUTER_CACHE)
+ /* Outer cache. */
+#if gcdENABLE_OUTER_CACHE_PATCH
+ _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_FLUSH);
+#else
+ outer_flush_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
+#endif
+#endif
+
+#elif defined(CONFIG_MIPS)
+ dma_cache_wback_inv((unsigned long) Logical, Bytes);
+#elif defined(CONFIG_PPC)
+ /* TODO */
+#else
+ dma_sync_single_for_device(
+ gcvNULL,
+ (dma_addr_t)Physical,
+ Bytes,
+ DMA_BIDIRECTIONAL);
+#endif
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+********************************* Broadcasting *********************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_Broadcast
+**
+** System hook for broadcast events from the kernel driver.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gceBROADCAST Reason
+** Reason for the broadcast. Can be one of the following values:
+**
+** gcvBROADCAST_GPU_IDLE
+** Broadcasted when the kernel driver thinks the GPU might be
+** idle. This can be used to handle power management.
+**
+** gcvBROADCAST_GPU_COMMIT
+** Broadcasted when any client process commits a command
+** buffer. This can be used to handle power management.
+**
+** gcvBROADCAST_GPU_STUCK
+** Broadcasted when the kernel driver hits the timeout waiting
+** for the GPU.
+**
+** gcvBROADCAST_FIRST_PROCESS
+** First process is trying to connect to the kernel.
+**
+** gcvBROADCAST_LAST_PROCESS
+** Last process has detached from the kernel.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Broadcast(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gceBROADCAST Reason
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os, Hardware, Reason);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ switch (Reason)
+ {
+ case gcvBROADCAST_FIRST_PROCESS:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
+ break;
+
+ case gcvBROADCAST_LAST_PROCESS:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
+
+ /* Put GPU OFF. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Hardware,
+ gcvPOWER_OFF_BROADCAST));
+ break;
+
+ case gcvBROADCAST_GPU_IDLE:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
+
+ /* Put GPU IDLE. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Hardware,
+#if gcdPOWER_SUSPEND_WHEN_IDLE
+ gcvPOWER_SUSPEND_BROADCAST));
+#else
+ gcvPOWER_IDLE_BROADCAST));
+#endif
+
+ /* Add idle process DB. */
+ gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
+ 1,
+ gcvDB_IDLE,
+ gcvNULL, gcvNULL, 0));
+ break;
+
+ case gcvBROADCAST_GPU_COMMIT:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
+
+ /* Add busy process DB. */
+ gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
+ 0,
+ gcvDB_IDLE,
+ gcvNULL, gcvNULL, 0));
+
+ /* Put GPU ON. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON_AUTO));
+ break;
+
+ case gcvBROADCAST_GPU_STUCK:
+ gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
+ gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
+ break;
+
+ case gcvBROADCAST_AXI_BUS_ERROR:
+ gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
+ 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. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_BroadcastHurry
+**
+** The GPU is running too slow.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gctUINT Urgency
+** The higher the number, the higher the urgency to speed up the GPU.
+** The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_BroadcastHurry(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gctUINT Urgency
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os, Hardware, Urgency);
+
+ /* Do whatever you need to do to speed up the GPU now. */
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_BroadcastCalibrateSpeed
+**
+** Calibrate the speed of the GPU.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gctUINT Idle, Time
+** Idle/Time will give the percentage the GPU is idle, so you can use
+** this to calibrate the working point of the GPU.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_BroadcastCalibrateSpeed(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gctUINT Idle,
+ IN gctUINT Time
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
+ Os, Hardware, Idle, Time);
+
+ /* Do whatever you need to do to callibrate the GPU speed. */
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+********************************** Semaphores **********************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_CreateSemaphore
+**
+** Create a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Semaphore
+** Pointer to the variable that will receive the created semaphore.
+*/
+gceSTATUS
+gckOS_CreateSemaphore(
+ IN gckOS Os,
+ OUT gctPOINTER * Semaphore
+ )
+{
+ gceSTATUS status;
+ struct semaphore *sem = gcvNULL;
+
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Allocate the semaphore structure. */
+ sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
+ if (sem == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Initialize the semaphore. */
+ sema_init(sem, 1);
+
+ /* Return to caller. */
+ *Semaphore = (gctPOINTER) sem;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AcquireSemaphore
+**
+** Acquire a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be acquired.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AcquireSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os, Semaphore);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Acquire the semaphore. */
+ if (down_interruptible((struct semaphore *) Semaphore))
+ {
+ gcmkONERROR(gcvSTATUS_INTERRUPTED);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_TryAcquireSemaphore
+**
+** Try to acquire a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be acquired.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_TryAcquireSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Acquire the semaphore. */
+ if (down_trylock((struct semaphore *) Semaphore))
+ {
+ /* Timeout. */
+ status = gcvSTATUS_TIMEOUT;
+ gcmkFOOTER();
+ return status;
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReleaseSemaphore
+**
+** Release a previously acquired semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be released.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_ReleaseSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Release the semaphore. */
+ up((struct semaphore *) Semaphore);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroySemaphore
+**
+** Destroy a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroySemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Free the sempahore structure. */
+ kfree(Semaphore);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetProcessID
+**
+** Get current process ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ProcessID
+** Pointer to the variable that receives the process ID.
+*/
+gceSTATUS
+gckOS_GetProcessID(
+ OUT gctUINT32_PTR ProcessID
+ )
+{
+ /* Get process ID. */
+ if (ProcessID != gcvNULL)
+ {
+ *ProcessID = _GetProcessID();
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetThreadID
+**
+** Get current thread ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ThreadID
+** Pointer to the variable that receives the thread ID.
+*/
+gceSTATUS
+gckOS_GetThreadID(
+ OUT gctUINT32_PTR ThreadID
+ )
+{
+ /* Get thread ID. */
+ if (ThreadID != gcvNULL)
+ {
+ *ThreadID = _GetThreadID();
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetGPUPower
+**
+** Set the power of the GPU on or off.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gceCORE Core
+** GPU whose power is set.
+**
+** gctBOOL Clock
+** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
+**
+** gctBOOL Power
+** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SetGPUPower(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctBOOL Clock,
+ IN gctBOOL Power
+ )
+{
+ gcsPLATFORM * platform;
+
+ 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;
+
+ powerChange = (Power != Os->powerStates[Core]);
+
+ clockChange = (Clock != Os->clockStates[Core]);
+
+ if (powerChange && (Power == gcvTRUE))
+ {
+ if (platform && platform->ops->setPower)
+ {
+ gcmkVERIFY_OK(platform->ops->setPower(platform, Core, Power));
+ }
+
+ Os->powerStates[Core] = Power;
+ }
+
+ 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]);
+ }
+
+ if (powerChange && (Power == gcvFALSE))
+ {
+ if (platform && platform->ops->setPower)
+ {
+ gcmkVERIFY_OK(platform->ops->setPower(platform, Core, Power));
+ }
+
+ Os->powerStates[Core] = Power;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_ResetGPU
+**
+** Reset the GPU.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gckCORE Core
+** GPU whose power is set.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_ResetGPU(
+ IN gckOS Os,
+ IN gceCORE Core
+ )
+{
+ gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
+ gcsPLATFORM * platform;
+
+ gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ platform = Os->device->platform;
+
+ if (platform && platform->ops->reset)
+ {
+ status = platform->ops->reset(platform, Core);
+ }
+
+ gcmkFOOTER_NO();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_PrepareGPUFrequency
+**
+** Prepare to set GPU frequency and voltage.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gckCORE Core
+** GPU whose frequency and voltage will be set.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_PrepareGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_FinishGPUFrequency
+**
+** Finish GPU frequency setting.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gckCORE Core
+** GPU whose frequency and voltage is set.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_FinishGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_QueryGPUFrequency
+**
+** Query the current frequency of the GPU.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gckCORE Core
+** GPU whose power is set.
+**
+** gctUINT32 * Frequency
+** Pointer to a gctUINT32 to obtain current frequency, in MHz.
+**
+** gctUINT8 * Scale
+** Pointer to a gctUINT8 to obtain current scale(1 - 64).
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_QueryGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gctUINT32 * Frequency,
+ OUT gctUINT8 * Scale
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetGPUFrequency
+**
+** Set frequency and voltage of the GPU.
+**
+** 1. DVFS manager gives the target scale of full frequency, BSP must find
+** a real frequency according to this scale and board's configure.
+**
+** 2. BSP should find a suitable voltage for this frequency.
+**
+** 3. BSP must make sure setting take effect before this function returns.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gckCORE Core
+** GPU whose power is set.
+**
+** gctUINT8 Scale
+** Target scale of full frequency, range is [1, 64]. 1 means 1/64 of
+** full frequency and 64 means 64/64 of full frequency.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SetGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT8 Scale
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*----------------------------------------------------------------------------*/
+/*----- Profile --------------------------------------------------------------*/
+
+gceSTATUS
+gckOS_GetProfileTick(
+ OUT gctUINT64_PTR Tick
+ )
+{
+ struct timespec time;
+
+ ktime_get_ts(&time);
+
+ *Tick = time.tv_nsec + time.tv_sec * 1000000000ULL;
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_QueryProfileTickRate(
+ OUT gctUINT64_PTR TickRate
+ )
+{
+ struct timespec res;
+
+ res.tv_sec = 0;
+ res.tv_nsec = hrtimer_resolution;
+
+ *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
+
+ return gcvSTATUS_OK;
+}
+
+gctUINT32
+gckOS_ProfileToMS(
+ IN gctUINT64 Ticks
+ )
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
+ return div_u64(Ticks, 1000000);
+#else
+ gctUINT64 rem = Ticks;
+ gctUINT64 b = 1000000;
+ gctUINT64 res, d = 1;
+ gctUINT32 high = rem >> 32;
+
+ /* Reduce the thing a bit first */
+ res = 0;
+ if (high >= 1000000)
+ {
+ high /= 1000000;
+ res = (gctUINT64) high << 32;
+ rem -= (gctUINT64) (high * 1000000) << 32;
+ }
+
+ while (((gctINT64) b > 0) && (b < rem))
+ {
+ b <<= 1;
+ d <<= 1;
+ }
+
+ do
+ {
+ if (rem >= b)
+ {
+ rem -= b;
+ res += d;
+ }
+
+ b >>= 1;
+ d >>= 1;
+ }
+ while (d);
+
+ return (gctUINT32) res;
+#endif
+}
+
+/******************************************************************************\
+******************************* Signal Management ******************************
+\******************************************************************************/
+
+#undef _GC_OBJ_ZONE
+#define _GC_OBJ_ZONE gcvZONE_SIGNAL
+
+/*******************************************************************************
+**
+** gckOS_CreateSignal
+**
+** Create a new signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL ManualReset
+** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
+** order to set the signal to nonsignaled state.
+** If set to gcvFALSE, the signal will automatically be set to
+** nonsignaled state by gckOS_WaitSignal function.
+**
+** OUTPUT:
+**
+** gctSIGNAL * Signal
+** Pointer to a variable receiving the created gctSIGNAL.
+*/
+gceSTATUS
+gckOS_CreateSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctSIGNAL * Signal
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+
+ gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os, ManualReset);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ /* Create an event structure. */
+ signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | gcdNOWARN);
+
+ if (signal == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Save the process ID. */
+ signal->process = (gctHANDLE)(gctUINTPTR_T) _GetProcessID();
+ signal->manualReset = ManualReset;
+ signal->hardware = gcvNULL;
+ init_completion(&signal->obj);
+ atomic_set(&signal->ref, 1);
+
+ gcmkONERROR(_AllocateIntegerId(&Os->signalDB, signal, &signal->id));
+
+ *Signal = (gctSIGNAL)(gctUINTPTR_T)signal->id;
+
+ gcmkFOOTER_ARG("*Signal=0x%X", *Signal);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (signal != gcvNULL)
+ {
+ kfree(signal);
+ }
+
+ gcmkFOOTER_NO();
+ return status;
+}
+
+gceSTATUS
+gckOS_SignalQueryHardware(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ OUT gckHARDWARE * Hardware
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+
+ gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
+
+ gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
+
+ *Hardware = signal->hardware;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_SignalSetHardware(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+
+ gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
+
+ signal->hardware = Hardware;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroySignal
+**
+** Destroy a signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroySignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
+
+ gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
+
+ if (atomic_dec_and_test(&signal->ref))
+ {
+ gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id));
+
+ /* Free the sgianl. */
+ kfree(signal);
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
+ acquired = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Signal
+**
+** Set a state of the specified signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctBOOL State
+** If gcvTRUE, the signal will be set to signaled state.
+** If gcvFALSE, the signal will be set to nonsignaled state.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Signal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
+
+ gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
+
+ if (State)
+ {
+ /* unbind the signal from hardware. */
+ signal->hardware = gcvNULL;
+
+ /* Set the event to a signaled state. */
+ complete(&signal->obj);
+ }
+ else
+ {
+ /* Set the event to an unsignaled state. */
+#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));
+ acquired = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdENABLE_VG
+gceSTATUS
+gckOS_SetSignalVG(
+ IN gckOS Os,
+ IN gctHANDLE Process,
+ IN gctSIGNAL Signal
+ )
+{
+ gceSTATUS status;
+ gctINT result;
+ struct task_struct * userTask;
+ struct siginfo info;
+
+ userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
+
+ if (userTask != gcvNULL)
+ {
+ info.si_signo = 48;
+ info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
+ info.si_pid = 0;
+ info.si_uid = 0;
+ info.si_ptr = (gctPOINTER) Signal;
+
+ /* Signals with numbers between 32 and 63 are real-time,
+ send a real-time signal to the user process. */
+ result = send_sig_info(48, &info, userTask);
+
+ printk("gckOS_SetSignalVG:0x%x\n", result);
+ /* Error? */
+ if (result < 0)
+ {
+ status = gcvSTATUS_GENERIC_IO;
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): an error has occurred.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+ else
+ {
+ status = gcvSTATUS_OK;
+ }
+ }
+ else
+ {
+ status = gcvSTATUS_GENERIC_IO;
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): an error has occurred.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+
+ /* Return status. */
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckOS_UserSignal
+**
+** Set the specified signal which is owned by a process to signaled state.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process
+ )
+{
+ gceSTATUS status;
+ gctSIGNAL signal;
+
+ gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
+ Os, Signal, (gctINT32)(gctUINTPTR_T)Process);
+
+ /* Map the signal into kernel space. */
+ gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
+
+ /* Signal. */
+ status = gckOS_Signal(Os, signal, gcvTRUE);
+
+ /* Unmap the signal */
+ gcmkVERIFY_OK(gckOS_UnmapSignal(Os, Signal));
+
+ gcmkFOOTER();
+ return status;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_WaitSignal
+**
+** Wait for a signal to become signaled.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctUINT32 Wait
+** Number of milliseconds to wait.
+** Pass the value of gcvINFINITE for an infinite wait.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WaitSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gcsSIGNAL_PTR signal;
+
+ gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
+
+ gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
+
+ might_sleep();
+
+ spin_lock_irq(&signal->obj.wait.lock);
+
+ if (signal->obj.done)
+ {
+ if (!signal->manualReset)
+ {
+ signal->obj.done = 0;
+ }
+
+ status = gcvSTATUS_OK;
+ }
+ else if (Wait == 0)
+ {
+ status = gcvSTATUS_TIMEOUT;
+ }
+ else
+ {
+ /* Convert wait to milliseconds. */
+ long timeout = (Wait == gcvINFINITE)
+ ? MAX_SCHEDULE_TIMEOUT
+ : Wait * HZ / 1000;
+
+ DECLARE_WAITQUEUE(wait, current);
+ wait.flags |= WQ_FLAG_EXCLUSIVE;
+ __add_wait_queue_tail(&signal->obj.wait, &wait);
+
+ while (gcvTRUE)
+ {
+ if (signal_pending(current))
+ {
+ /* Interrupt received. */
+ status = gcvSTATUS_INTERRUPTED;
+ break;
+ }
+
+ __set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_irq(&signal->obj.wait.lock);
+ timeout = schedule_timeout(timeout);
+ spin_lock_irq(&signal->obj.wait.lock);
+
+ if (signal->obj.done)
+ {
+ if (!signal->manualReset)
+ {
+ signal->obj.done = 0;
+ }
+
+ status = gcvSTATUS_OK;
+ break;
+ }
+
+ if (timeout == 0)
+ {
+
+ status = gcvSTATUS_TIMEOUT;
+ break;
+ }
+ }
+
+ __remove_wait_queue(&signal->obj.wait, &wait);
+ }
+
+ spin_unlock_irq(&signal->obj.wait.lock);
+
+OnError:
+ /* Return status. */
+ gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapSignal
+**
+** Map a signal in to the current process space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to tha gctSIGNAL to map.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** gctSIGNAL * MappedSignal
+** Pointer to a variable receiving the mapped gctSIGNAL.
+*/
+gceSTATUS
+gckOS_MapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process,
+ OUT gctSIGNAL * MappedSignal
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process);
+
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+ gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
+
+ gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
+
+ if(atomic_inc_return(&signal->ref) <= 1)
+ {
+ /* The previous value is 0, it has been deleted. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ *MappedSignal = (gctSIGNAL) Signal;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER_NO();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapSignal
+**
+** Unmap a signal .
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to that gctSIGNAL mapped.
+*/
+gceSTATUS
+gckOS_UnmapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ )
+{
+ return gckOS_DestroySignal(Os, Signal);
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateUserSignal
+**
+** Create a new signal to be used in the user space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL ManualReset
+** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
+** order to set the signal to nonsignaled state.
+** If set to gcvFALSE, the signal will automatically be set to
+** nonsignaled state by gckOS_WaitSignal function.
+**
+** OUTPUT:
+**
+** gctINT * SignalID
+** Pointer to a variable receiving the created signal's ID.
+*/
+gceSTATUS
+gckOS_CreateUserSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctINT * SignalID
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T signal;
+
+ /* Create a new signal. */
+ gcmkONERROR(gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal));
+ *SignalID = (gctINT) signal;
+
+OnError:
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroyUserSignal
+**
+** Destroy a signal to be used in the user space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctINT SignalID
+** The signal's ID.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroyUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID
+ )
+{
+ return gckOS_DestroySignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID);
+}
+
+/*******************************************************************************
+**
+** gckOS_WaitUserSignal
+**
+** Wait for a signal used in the user mode to become signaled.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctINT SignalID
+** Signal ID.
+**
+** gctUINT32 Wait
+** Number of milliseconds to wait.
+** Pass the value of gcvINFINITE for an infinite wait.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WaitUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctUINT32 Wait
+ )
+{
+ return gckOS_WaitSignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, Wait);
+}
+
+/*******************************************************************************
+**
+** gckOS_SignalUserSignal
+**
+** Set a state of the specified signal to be used in the user space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctINT SignalID
+** SignalID.
+**
+** gctBOOL State
+** If gcvTRUE, the signal will be set to signaled state.
+** If gcvFALSE, the signal will be set to nonsignaled state.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SignalUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctBOOL State
+ )
+{
+ return gckOS_Signal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, State);
+}
+
+#if gcdENABLE_VG
+gceSTATUS
+gckOS_CreateSemaphoreVG(
+ IN gckOS Os,
+ OUT gctSEMAPHORE * Semaphore
+ )
+{
+ gceSTATUS status;
+ struct semaphore * newSemaphore;
+
+ gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ do
+ {
+ /* Allocate the semaphore structure. */
+ newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
+ if (newSemaphore == gcvNULL)
+ {
+ gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Initialize the semaphore. */
+ sema_init(newSemaphore, 0);
+
+ /* Set the handle. */
+ * Semaphore = (gctSEMAPHORE) newSemaphore;
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+
+gceSTATUS
+gckOS_IncrementSemaphore(
+ IN gckOS Os,
+ IN gctSEMAPHORE Semaphore
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Increment the semaphore's count. */
+ up((struct semaphore *) Semaphore);
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_DecrementSemaphore(
+ IN gckOS Os,
+ IN gctSEMAPHORE Semaphore
+ )
+{
+ gceSTATUS status;
+ gctINT result;
+
+ gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ do
+ {
+ /* Decrement the semaphore's count. If the count is zero, wait
+ until it gets incremented. */
+ result = down_interruptible((struct semaphore *) Semaphore);
+
+ /* Signal received? */
+ if (result != 0)
+ {
+ status = gcvSTATUS_TERMINATE;
+ break;
+ }
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetSignal
+**
+** Set the specified signal to signaled state.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SetSignal(
+ IN gckOS Os,
+ IN gctHANDLE Process,
+ IN gctSIGNAL Signal
+ )
+{
+ gceSTATUS status;
+ gctINT result;
+ struct task_struct * userTask;
+ struct siginfo info;
+
+ userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
+
+ if (userTask != gcvNULL)
+ {
+ info.si_signo = 48;
+ info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
+ info.si_pid = 0;
+ info.si_uid = 0;
+ info.si_ptr = (gctPOINTER) Signal;
+
+ /* Signals with numbers between 32 and 63 are real-time,
+ send a real-time signal to the user process. */
+ result = send_sig_info(48, &info, userTask);
+
+ /* Error? */
+ if (result < 0)
+ {
+ status = gcvSTATUS_GENERIC_IO;
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): an error has occurred.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+ else
+ {
+ status = gcvSTATUS_OK;
+ }
+ }
+ else
+ {
+ status = gcvSTATUS_GENERIC_IO;
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): an error has occurred.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+
+ /* Return status. */
+ return status;
+}
+
+/******************************************************************************\
+******************************** Thread Object *********************************
+\******************************************************************************/
+
+gceSTATUS
+gckOS_StartThread(
+ IN gckOS Os,
+ IN gctTHREADFUNC ThreadFunction,
+ IN gctPOINTER ThreadParameter,
+ OUT gctTHREAD * Thread
+ )
+{
+ gceSTATUS status;
+ struct task_struct * thread;
+
+ gcmkHEADER_ARG("Os=0x%X ", Os);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(ThreadFunction != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
+
+ do
+ {
+ /* Create the thread. */
+ thread = kthread_create(
+ ThreadFunction,
+ ThreadParameter,
+ "Vivante Kernel Thread"
+ );
+
+ /* Failed? */
+ if (IS_ERR(thread))
+ {
+ status = gcvSTATUS_GENERIC_IO;
+ break;
+ }
+
+ /* Start the thread. */
+ wake_up_process(thread);
+
+ /* Set the thread handle. */
+ * Thread = (gctTHREAD) thread;
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+gceSTATUS
+gckOS_StopThread(
+ IN gckOS Os,
+ IN gctTHREAD Thread
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
+
+ /* Thread should have already been enabled to terminate. */
+ kthread_stop((struct task_struct *) Thread);
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_VerifyThread(
+ IN gckOS Os,
+ IN gctTHREAD Thread
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+#endif
+
+/******************************************************************************\
+******************************** Software Timer ********************************
+\******************************************************************************/
+
+void
+_TimerFunction(
+ struct work_struct * work
+ )
+{
+ gcsOSTIMER_PTR timer = (gcsOSTIMER_PTR)work;
+
+ gctTIMERFUNCTION function = timer->function;
+
+ function(timer->data);
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateTimer
+**
+** Create a software timer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctTIMERFUNCTION Function.
+** Pointer to a call back function which will be called when timer is
+** expired.
+**
+** gctPOINTER Data.
+** Private data which will be passed to call back function.
+**
+** OUTPUT:
+**
+** gctPOINTER * Timer
+** Pointer to a variable receiving the created timer.
+*/
+gceSTATUS
+gckOS_CreateTimer(
+ IN gckOS Os,
+ IN gctTIMERFUNCTION Function,
+ IN gctPOINTER Data,
+ OUT gctPOINTER * Timer
+ )
+{
+ gceSTATUS status;
+ gcsOSTIMER_PTR pointer;
+ gcmkHEADER_ARG("Os=0x%X Function=0x%X Data=0x%X", Os, Function, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
+
+ gcmkONERROR(gckOS_Allocate(Os, sizeof(gcsOSTIMER), (gctPOINTER)&pointer));
+
+ pointer->function = Function;
+ pointer->data = Data;
+
+ INIT_DELAYED_WORK(&pointer->work, _TimerFunction);
+
+ *Timer = pointer;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroyTimer
+**
+** Destory a software timer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Timer
+** Pointer to the timer to be destoryed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroyTimer(
+ IN gckOS Os,
+ IN gctPOINTER Timer
+ )
+{
+ gcsOSTIMER_PTR timer;
+ gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
+
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
+
+ timer = (gcsOSTIMER_PTR)Timer;
+
+#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
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, Timer));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_StartTimer
+**
+** Schedule a software timer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Timer
+** Pointer to the timer to be scheduled.
+**
+** gctUINT32 Delay
+** Delay in milliseconds.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_StartTimer(
+ IN gckOS Os,
+ IN gctPOINTER Timer,
+ IN gctUINT32 Delay
+ )
+{
+ gcsOSTIMER_PTR timer;
+
+ gcmkHEADER_ARG("Os=0x%X Timer=0x%X Delay=%u", Os, Timer, Delay);
+
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Delay != 0);
+
+ 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 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;
+}
+
+/*******************************************************************************
+**
+** gckOS_StopTimer
+**
+** Cancel a unscheduled timer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Timer
+** Pointer to the timer to be cancel.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_StopTimer(
+ IN gckOS Os,
+ IN gctPOINTER Timer
+ )
+{
+ gcsOSTIMER_PTR timer;
+ gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
+
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
+
+ timer = (gcsOSTIMER_PTR)Timer;
+
+ cancel_delayed_work(&timer->work);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_GetProcessNameByPid(
+ IN gctINT Pid,
+ IN gctSIZE_T Length,
+ OUT gctUINT8_PTR String
+ )
+{
+ struct task_struct *task;
+
+ /* Get the task_struct of the task with pid. */
+ rcu_read_lock();
+
+ task = FIND_TASK_BY_PID(Pid);
+
+ if (task == gcvNULL)
+ {
+ rcu_read_unlock();
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+ /* Get name of process. */
+ strncpy(String, task->comm, Length);
+
+ rcu_read_unlock();
+
+ 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
+gckOS_CreateSyncPoint(
+ IN gckOS Os,
+ OUT gctSYNC_POINT * SyncPoint
+ )
+{
+ gceSTATUS status;
+ gcsSYNC_POINT_PTR syncPoint;
+
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ /* Create an sync point structure. */
+ syncPoint = (gcsSYNC_POINT_PTR) kmalloc(
+ sizeof(gcsSYNC_POINT), GFP_KERNEL | gcdNOWARN);
+
+ if (syncPoint == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Initialize the sync point. */
+ atomic_set(&syncPoint->ref, 1);
+ atomic_set(&syncPoint->state, 0);
+
+ gcmkONERROR(_AllocateIntegerId(&Os->syncPointDB, syncPoint, &syncPoint->id));
+
+ *SyncPoint = (gctSYNC_POINT)(gctUINTPTR_T)syncPoint->id;
+
+ gcmkFOOTER_ARG("*SyncPonint=%d", syncPoint->id);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (syncPoint != gcvNULL)
+ {
+ kfree(syncPoint);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_ReferenceSyncPoint(
+ IN gckOS Os,
+ IN gctSYNC_POINT SyncPoint
+ )
+{
+ gceSTATUS status;
+ gcsSYNC_POINT_PTR syncPoint;
+
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
+
+ gcmkONERROR(
+ _QueryIntegerId(&Os->syncPointDB,
+ (gctUINT32)(gctUINTPTR_T)SyncPoint,
+ (gctPOINTER)&syncPoint));
+
+ /* Initialize the sync point. */
+ atomic_inc(&syncPoint->ref);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_DestroySyncPoint(
+ IN gckOS Os,
+ IN gctSYNC_POINT SyncPoint
+ )
+{
+ gceSTATUS status;
+ gcsSYNC_POINT_PTR syncPoint;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
+
+ gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ gcmkONERROR(
+ _QueryIntegerId(&Os->syncPointDB,
+ (gctUINT32)(gctUINTPTR_T)SyncPoint,
+ (gctPOINTER)&syncPoint));
+
+ gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
+
+ if (atomic_dec_and_test(&syncPoint->ref))
+ {
+ gcmkVERIFY_OK(_DestroyIntegerId(&Os->syncPointDB, syncPoint->id));
+
+ /* Free the sgianl. */
+ syncPoint->timeline = gcvNULL;
+ kfree(syncPoint);
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
+ acquired = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_SignalSyncPoint(
+ IN gckOS Os,
+ IN gctSYNC_POINT SyncPoint
+ )
+{
+ 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);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
+
+ gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ gcmkONERROR(
+ _QueryIntegerId(&Os->syncPointDB,
+ (gctUINT32)(gctUINTPTR_T)SyncPoint,
+ (gctPOINTER)&syncPoint));
+
+ gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
+
+ /* Set signaled state. */
+ atomic_set(&syncPoint->state, 1);
+
+ /* 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;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_QuerySyncPoint(
+ IN gckOS Os,
+ IN gctSYNC_POINT SyncPoint,
+ OUT gctBOOL_PTR State
+ )
+{
+ gceSTATUS status;
+ gcsSYNC_POINT_PTR syncPoint;
+
+ gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
+
+ gcmkONERROR(
+ _QueryIntegerId(&Os->syncPointDB,
+ (gctUINT32)(gctUINTPTR_T)SyncPoint,
+ (gctPOINTER)&syncPoint));
+
+ gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
+
+ /* Get state. */
+ *State = atomic_read(&syncPoint->state);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*State=%d", *State);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_CreateSyncTimeline(
+ IN gckOS Os,
+ OUT gctHANDLE * Timeline
+ )
+{
+ struct viv_sync_timeline * timeline;
+
+ /* Create viv sync timeline. */
+ timeline = viv_sync_timeline_create("viv timeline", Os);
+
+ if (timeline == gcvNULL)
+ {
+ /* Out of memory. */
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ *Timeline = (gctHANDLE) timeline;
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_DestroySyncTimeline(
+ IN gckOS Os,
+ IN gctHANDLE Timeline
+ )
+{
+ struct viv_sync_timeline * timeline;
+ gcmkASSERT(Timeline != gcvNULL);
+
+ /* Destroy timeline. */
+ timeline = (struct viv_sync_timeline *) Timeline;
+ sync_timeline_destroy(&timeline->obj);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_CreateNativeFence(
+ IN gckOS Os,
+ IN gctHANDLE Timeline,
+ IN gctSYNC_POINT SyncPoint,
+ OUT gctINT * FenceFD
+ )
+{
+ int fd = -1;
+ struct viv_sync_timeline *timeline;
+ struct sync_pt * pt = gcvNULL;
+ struct sync_fence * fence;
+ char name[32];
+ gcsSYNC_POINT_PTR syncPoint;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Timeline=0x%X SyncPoint=%d",
+ Os, Timeline, (gctUINT)(gctUINTPTR_T)SyncPoint);
+
+ gcmkONERROR(
+ _QueryIntegerId(&Os->syncPointDB,
+ (gctUINT32)(gctUINTPTR_T)SyncPoint,
+ (gctPOINTER)&syncPoint));
+
+ /* Cast timeline. */
+ timeline = (struct viv_sync_timeline *) Timeline;
+
+ fd = get_unused_fd();
+
+ if (fd < 0)
+ {
+ /* Out of resources. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Create viv_sync_pt. */
+ pt = viv_sync_pt_create(timeline, SyncPoint);
+
+ if (pt == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Reference sync_timeline. */
+ syncPoint->timeline = &timeline->obj;
+
+ /* Build fence name. */
+ snprintf(name, 32, "viv sync_fence-%u", (gctUINT)(gctUINTPTR_T)SyncPoint);
+
+ /* Create sync_fence. */
+ fence = sync_fence_create(name, pt);
+
+ if (fence == NULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Install fence to fd. */
+ sync_fence_install(fence, fd);
+
+ *FenceFD = fd;
+ gcmkFOOTER_ARG("*FenceFD=%d", fd);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Error roll back. */
+ if (pt)
+ {
+ sync_pt_free(pt);
+ }
+
+ if (fd > 0)
+ {
+ put_unused_fd(fd);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_WaitNativeFence(
+ IN gckOS Os,
+ IN gctHANDLE Timeline,
+ IN gctINT FenceFD,
+ IN gctUINT32 Timeout
+ )
+{
+ struct sync_timeline * timeline;
+ struct list_head *pos;
+ struct sync_fence * fence;
+ gctBOOL wait = gcvFALSE;
+ gceSTATUS status = gcvSTATUS_OK;
+
+ gcmkHEADER_ARG("Os=0x%X Timeline=0x%X FenceFD=%d Timeout=%u",
+ Os, Timeline, FenceFD, Timeout);
+
+ /* Get shortcut. */
+ timeline = (struct sync_timeline *) Timeline;
+
+ /* Get sync fence. */
+ fence = sync_fence_fdget(FenceFD);
+
+ if (!fence)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ list_for_each(pos, &fence->pt_list_head)
+ {
+ struct sync_pt * pt =
+ container_of(pos, struct sync_pt, pt_list);
+
+ /* Do not need to wait on same timeline. */
+ if (pt->parent != timeline)
+ {
+ wait = gcvTRUE;
+ break;
+ }
+ }
+
+ if (wait)
+ {
+ int err;
+ long timeout = (Timeout == gcvINFINITE) ? - 1 : (long) Timeout;
+ err = sync_fence_wait(fence, timeout);
+
+ switch (err)
+ {
+ case 0:
+ break;
+ case -ETIME:
+ status = gcvSTATUS_TIMEOUT;
+ break;
+ default:
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+ }
+
+ /* Put the fence. */
+ sync_fence_put(fence);
+
+OnError:
+ gcmkFOOTER();
+ 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)
+ {
+ gctPHYS_ADDR_T 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 gctPHYS_ADDR_T CPUPhysical,
+ IN gctPHYS_ADDR_T * 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 gctPHYS_ADDR_T * 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;
+ }
+ else if (!strcmp(Option, "contiguousSize"))
+ {
+ *Value = device->contiguousSize;
+ 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,27)
+ *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
+}
+
+/*******************************************************************************
+**
+** gckOS_WrapMemory
+**
+** Import a number of pages allocated by other allocator.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Flag
+** Memory type.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that hold the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that will hold the physical address of the
+** allocation.
+*/
+gceSTATUS
+gckOS_WrapMemory(
+ IN gckOS Os,
+ IN gcsUSER_MEMORY_DESC_PTR Desc,
+ OUT gctSIZE_T *Bytes,
+ OUT gctPHYS_ADDR * Physical
+ )
+{
+ PLINUX_MDL mdl = gcvNULL;
+ gceSTATUS status = gcvSTATUS_OUT_OF_MEMORY;
+ gckALLOCATOR allocator;
+ gcsATTACH_DESC desc;
+ gctUINT32 flag;
+
+ gcmkHEADER_ARG("Os=0x%X ", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+
+ mdl = _CreateMdl();
+ if (mdl == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ desc.handle = Desc->handle;
+ desc.memory = gcmUINT64_TO_PTR(Desc->logical);
+ desc.physical = Desc->physical;
+ desc.size = Desc->size;
+ flag = Desc->flag;
+
+ /* Walk all allocators. */
+ list_for_each_entry(allocator, &Os->allocatorList, head)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d) Flag = %x allocator->capability = %x",
+ __FUNCTION__, __LINE__, flag, allocator->capability);
+
+ if ((flag & allocator->capability) != flag)
+ {
+ status = gcvSTATUS_NOT_SUPPORTED;
+ continue;
+ }
+
+ status = allocator->ops->Attach(allocator, &desc, mdl);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ mdl->allocator = allocator;
+ break;
+ }
+ }
+
+ /* Check status. */
+ gcmkONERROR(status);
+
+ mdl->dmaHandle = 0;
+ mdl->addr = 0;
+ mdl->pagedMem = 1;
+
+ *Bytes = mdl->numPages * PAGE_SIZE;
+
+ /* Return physical address. */
+ *Physical = (gctPHYS_ADDR) mdl;
+
+ MEMORY_LOCK(Os);
+
+ /*
+ * Add this to a global list.
+ * Will be used by get physical address
+ * and mapuser pointer functions.
+ */
+ if (!Os->mdlHead)
+ {
+ /* Initialize the queue. */
+ Os->mdlHead = Os->mdlTail = mdl;
+ }
+ else
+ {
+ /* Add to tail. */
+ mdl->prev = Os->mdlTail;
+ Os->mdlTail->next = mdl;
+ Os->mdlTail = mdl;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mdl != gcvNULL)
+ {
+ /* Free the memory. */
+ _DestroyMdl(mdl);
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h
new file mode 100644
index 000000000000..692a5a885355
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_os_h_
+#define __gc_hal_kernel_os_h_
+
+typedef struct _LINUX_MDL_MAP
+{
+ gctINT pid;
+ gctPOINTER vmaAddr;
+ gctUINT32 count;
+ struct vm_area_struct * vma;
+ struct _LINUX_MDL_MAP * next;
+}
+LINUX_MDL_MAP;
+
+typedef struct _LINUX_MDL_MAP * PLINUX_MDL_MAP;
+
+typedef struct _LINUX_MDL
+{
+ char * addr;
+
+ union _pages
+ {
+ /* Pointer to a array of pages. */
+ struct page * contiguousPages;
+ /* Pointer to a array of pointers to page. */
+ struct page ** nonContiguousPages;
+ }
+ u;
+
+#ifdef NO_DMA_COHERENT
+ gctPOINTER kaddr;
+#endif /* NO_DMA_COHERENT */
+
+ gctINT numPages;
+ gctINT pagedMem;
+ gctBOOL contiguous;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ gctBOOL exact;
+#endif
+ dma_addr_t dmaHandle;
+ 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;
+
+extern PLINUX_MDL_MAP
+FindMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN gctINT PID
+ );
+
+typedef struct _DRIVER_ARGS
+{
+ gctUINT64 InputBuffer;
+ gctUINT64 InputBufferSize;
+ gctUINT64 OutputBuffer;
+ gctUINT64 OutputBufferSize;
+}
+DRIVER_ARGS;
+
+#endif /* __gc_hal_kernel_os_h_ */
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
index 000000000000..bf19409129ff
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h
@@ -0,0 +1,342 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#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;
+ gctBOOL registerMemMapped;
+ gctPOINTER registerMemAddress;
+}
+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 gctPHYS_ADDR_T CPUPhysical,
+ OUT gctPHYS_ADDR_T * 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
+ );
+
+ /*******************************************************************************
+ **
+ ** name
+ **
+ ** Get name of platform code.
+ **
+ ** There is a helper macro gcmkPLATFORM_Name which defines a default callback
+ ** function _Name() which uses code path as name.
+ */
+ gceSTATUS
+ (*name)(
+ IN gckPLATFORM Platform,
+ IN gctCONST_STRING * Name
+ );
+
+}
+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
+ );
+
+#define gcmkPLATFROM_Name \
+static gceSTATUS \
+_Name( \
+ IN gckPLATFORM Platform, \
+ IN gctCONST_STRING * Name \
+ ) \
+{ \
+ * Name = __FILE__; \
+ return gcvSTATUS_OK; \
+} \
+
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_probe.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_probe.c
new file mode 100644
index 000000000000..4a29f0e776e2
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_probe.c
@@ -0,0 +1,1410 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include <linux/device.h>
+#include <linux/slab.h>
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_driver.h"
+
+#if USE_PLATFORM_DRIVER
+# include <linux/platform_device.h>
+#endif
+
+#ifdef CONFIG_PXA_DVFM
+# include <mach/dvfm.h>
+# include <mach/pxa3xx_dvfm.h>
+#endif
+
+
+/* Zone used for header/footer. */
+#define _GC_OBJ_ZONE gcvZONE_DRIVER
+
+MODULE_DESCRIPTION("Vivante Graphics Driver");
+MODULE_LICENSE("GPL");
+
+static struct class* gpuClass;
+
+static 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);
+
+static ulong registerMemBase = 0x80000000;
+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);
+
+static ulong registerMemBase2D = 0x00000000;
+module_param(registerMemBase2D, ulong, 0644);
+
+static ulong registerMemSize2D = 2 << 10;
+module_param(registerMemSize2D, ulong, 0644);
+
+static int irqLineVG = -1;
+module_param(irqLineVG, int, 0644);
+
+static ulong registerMemBaseVG = 0x00000000;
+module_param(registerMemBaseVG, ulong, 0644);
+
+static ulong registerMemSizeVG = 2 << 10;
+module_param(registerMemSizeVG, ulong, 0644);
+
+#if gcdENABLE_DEC_COMPRESSION
+static ulong registerMemBaseDEC300 = 0x00000000;
+module_param(registerMemBaseDEC300, ulong, 0644);
+
+static ulong registerMemSizeDEC300 = 2 << 10;
+module_param(registerMemSizeDEC300, ulong, 0644);
+#endif
+
+#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;
+module_param(contiguousBase, ulong, 0644);
+
+static ulong bankSize = 0;
+module_param(bankSize, ulong, 0644);
+
+static int fastClear = -1;
+module_param(fastClear, int, 0644);
+
+static int compression = -1;
+module_param(compression, int, 0644);
+
+static int powerManagement = -1;
+module_param(powerManagement, int, 0644);
+
+static int gpuProfiler = 0;
+module_param(gpuProfiler, int, 0644);
+
+static int signal = 48;
+module_param(signal, int, 0644);
+
+static ulong baseAddress = 0;
+module_param(baseAddress, ulong, 0644);
+
+static ulong physSize = 0;
+module_param(physSize, ulong, 0644);
+
+static 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 = 0;
+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);
+
+static int mmu = 1;
+module_param(mmu, int, 0644);
+
+static int gpu3DMinClock = 1;
+
+static int contiguousRequested = 0;
+
+
+static gctBOOL registerMemMapped = gcvFALSE;
+static gctPOINTER registerMemAddress = gcvNULL;
+
+static int drv_open(
+ struct inode* inode,
+ struct file* filp
+ );
+
+static int drv_release(
+ struct inode* inode,
+ struct file* filp
+ );
+
+static long drv_ioctl(
+ struct file* filp,
+ unsigned int ioctlCode,
+ unsigned long arg
+ );
+
+static int drv_mmap(
+ struct file* filp,
+ struct vm_area_struct* vma
+ );
+
+static struct file_operations driver_fops =
+{
+ .owner = THIS_MODULE,
+ .open = drv_open,
+ .release = drv_release,
+ .unlocked_ioctl = drv_ioctl,
+#ifdef HAVE_COMPAT_IOCTL
+ .compat_ioctl = drv_ioctl,
+#endif
+ .mmap = drv_mmap,
+};
+
+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;
+#if gcdENABLE_VG
+ irqLineVG = Param->irqLineVG;
+ registerMemBaseVG = Param->registerMemBaseVG;
+ registerMemSizeVG = Param->registerMemSizeVG;
+#endif
+ 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;
+ registerMemMapped = Param->registerMemMapped;
+ registerMemAddress = Param->registerMemAddress;
+}
+
+void
+gckOS_DumpParam(
+ void
+ )
+{
+ 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);
+
+ 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
+
+ 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);
+ }
+
+#if gcdENABLE_DEC_COMPRESSION
+ printk(" registerMemBaseDEC300 = 0x%08lX\n", registerMemBaseDEC300);
+ printk(" registerMemSizeDEC300 = 0x%08lX\n", registerMemSizeDEC300);
+#endif
+
+ 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);
+}
+
+int drv_open(
+ struct inode* inode,
+ struct file* filp
+ )
+{
+ gceSTATUS status;
+ gctBOOL attached = gcvFALSE;
+ gcsHAL_PRIVATE_DATA_PTR data = gcvNULL;
+ gctINT i;
+
+ gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
+
+ if (filp == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): filp is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ data = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL | __GFP_NOWARN);
+
+ if (data == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): private_data is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ data->device = galDevice;
+ data->mappedMemory = gcvNULL;
+ data->contiguousLogical = gcvNULL;
+ gcmkONERROR(gckOS_GetProcessID(&data->pidOpen));
+
+ /* Attached the process. */
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (galDevice->kernels[i] != gcvNULL)
+ {
+ gcmkONERROR(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvTRUE));
+ }
+ }
+ attached = gcvTRUE;
+
+ if (!galDevice->contiguousMapped)
+ {
+ if (galDevice->contiguousPhysical != gcvNULL)
+ {
+ gcmkONERROR(gckOS_MapMemory(
+ galDevice->os,
+ galDevice->contiguousPhysical,
+ galDevice->contiguousSize,
+ &data->contiguousLogical
+ ));
+ }
+ }
+
+ filp->private_data = data;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return 0;
+
+OnError:
+ if (data != gcvNULL)
+ {
+ if (data->contiguousLogical != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapMemory(
+ galDevice->os,
+ galDevice->contiguousPhysical,
+ galDevice->contiguousSize,
+ data->contiguousLogical
+ ));
+ }
+
+ kfree(data);
+ }
+
+ if (attached)
+ {
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (galDevice->kernels[i] != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvFALSE));
+ }
+ }
+ }
+
+ gcmkFOOTER();
+ return -ENOTTY;
+}
+
+int drv_release(
+ struct inode* inode,
+ struct file* filp
+ )
+{
+ gceSTATUS status;
+ gcsHAL_PRIVATE_DATA_PTR data;
+ gckGALDEVICE device;
+ gctINT i;
+
+ gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
+
+ if (filp == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): filp is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ data = filp->private_data;
+
+ if (data == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): private_data is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ device = data->device;
+
+ if (device == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): device is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (!device->contiguousMapped)
+ {
+ if (data->contiguousLogical != gcvNULL)
+ {
+ gcmkONERROR(gckOS_UnmapMemoryEx(
+ galDevice->os,
+ galDevice->contiguousPhysical,
+ galDevice->contiguousSize,
+ data->contiguousLogical,
+ data->pidOpen
+ ));
+
+ data->contiguousLogical = gcvNULL;
+ }
+ }
+
+ /* A process gets detached. */
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (galDevice->kernels[i] != gcvNULL)
+ {
+ gcmkONERROR(gckKERNEL_AttachProcessEx(galDevice->kernels[i], gcvFALSE, data->pidOpen));
+ }
+ }
+
+ kfree(data);
+ filp->private_data = NULL;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return 0;
+
+OnError:
+ gcmkFOOTER();
+ return -ENOTTY;
+}
+
+long drv_ioctl(
+ struct file* filp,
+ unsigned int ioctlCode,
+ unsigned long arg
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+ gctUINT32 copyLen;
+ DRIVER_ARGS drvArgs;
+ gckGALDEVICE device;
+ gcsHAL_PRIVATE_DATA_PTR data;
+ gctINT32 i, count;
+ gckVIDMEM_NODE nodeObject;
+
+ gcmkHEADER_ARG(
+ "filp=0x%08X ioctlCode=0x%08X arg=0x%08X",
+ filp, ioctlCode, arg
+ );
+
+ if (filp == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): filp is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ data = filp->private_data;
+
+ if (data == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): private_data is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ device = data->device;
+
+ if (device == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): device is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if ((ioctlCode != IOCTL_GCHAL_INTERFACE)
+ && (ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE)
+ )
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): unknown command %d\n",
+ __FUNCTION__, __LINE__,
+ ioctlCode
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Get the drvArgs. */
+ copyLen = copy_from_user(
+ &drvArgs, (void *) arg, sizeof(DRIVER_ARGS)
+ );
+
+ if (copyLen != 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): error copying of the input arguments.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Now bring in the gcsHAL_INTERFACE structure. */
+ if ((drvArgs.InputBufferSize != sizeof(gcsHAL_INTERFACE))
+ || (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE))
+ )
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): input or/and output structures are invalid.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ copyLen = copy_from_user(
+ &iface, gcmUINT64_TO_PTR(drvArgs.InputBuffer), sizeof(gcsHAL_INTERFACE)
+ );
+
+ if (copyLen != 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): error copying of input HAL interface.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (iface.command == gcvHAL_CHIP_INFO)
+ {
+ count = 0;
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (device->kernels[i] != gcvNULL)
+ {
+#if gcdENABLE_VG
+ if (i == gcvCORE_VG)
+ {
+ iface.u.ChipInfo.types[count] = gcvHARDWARE_VG;
+ }
+ else
+#endif
+ {
+ gcmkVERIFY_OK(gckHARDWARE_GetType(device->kernels[i]->hardware,
+ &iface.u.ChipInfo.types[count]));
+ }
+ count++;
+ }
+ }
+
+ iface.u.ChipInfo.count = count;
+ iface.status = status = gcvSTATUS_OK;
+ }
+ else
+ {
+ if (iface.hardwareType > 7)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): unknown hardwareType %d\n",
+ __FUNCTION__, __LINE__,
+ iface.hardwareType
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+#if gcdENABLE_VG
+ if (device->coreMapping[iface.hardwareType] == gcvCORE_VG)
+ {
+ status = gckVGKERNEL_Dispatch(device->kernels[gcvCORE_VG],
+ (ioctlCode == IOCTL_GCHAL_INTERFACE),
+ &iface);
+ }
+ else
+#endif
+ {
+ status = gckKERNEL_Dispatch(device->kernels[device->coreMapping[iface.hardwareType]],
+ (ioctlCode == IOCTL_GCHAL_INTERFACE),
+ &iface);
+ }
+ }
+
+ /* Redo system call after pending signal is handled. */
+ if (status == gcvSTATUS_INTERRUPTED)
+ {
+ gcmkFOOTER();
+ return -ERESTARTSYS;
+ }
+
+ if (gcmIS_SUCCESS(status) && (iface.command == gcvHAL_LOCK_VIDEO_MEMORY))
+ {
+ 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)
+ )
+ {
+ /* Compute offset into mapped memory. */
+ gctUINT32 offset
+ = (gctUINT8 *) gcmUINT64_TO_PTR(iface.u.LockVideoMemory.memory)
+ - (gctUINT8 *) device->contiguousBase;
+
+ /* Compute offset into user-mapped region. */
+ iface.u.LockVideoMemory.memory =
+ gcmPTR_TO_UINT64((gctUINT8 *) data->mappedMemory + offset);
+ }
+ }
+
+ /* Copy data back to the user. */
+ copyLen = copy_to_user(
+ gcmUINT64_TO_PTR(drvArgs.OutputBuffer), &iface, sizeof(gcsHAL_INTERFACE)
+ );
+
+ if (copyLen != 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): error copying of output HAL interface.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return 0;
+
+OnError:
+ gcmkFOOTER();
+ return -ENOTTY;
+}
+
+static int drv_mmap(
+ struct file* filp,
+ struct vm_area_struct* vma
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gcsHAL_PRIVATE_DATA_PTR data;
+ gckGALDEVICE device;
+
+ gcmkHEADER_ARG("filp=0x%08X vma=0x%08X", filp, vma);
+
+ if (filp == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): filp is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ data = filp->private_data;
+
+ if (data == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): private_data is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ device = data->device;
+
+ if (device == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): device is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+#if !gcdPAGED_MEMORY_CACHEABLE
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ vma->vm_flags |= gcdVM_FLAGS;
+#endif
+ vma->vm_pgoff = 0;
+
+ if (device->contiguousMapped)
+ {
+ unsigned long size = vma->vm_end - vma->vm_start;
+ int ret = 0;
+
+ if (size > device->contiguousSize)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Invalid mapping size.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ ret = io_remap_pfn_range(
+ vma,
+ vma->vm_start,
+ device->requestedContiguousBase >> PAGE_SHIFT,
+ size,
+ vma->vm_page_prot
+ );
+
+ if (ret != 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): io_remap_pfn_range failed %d\n",
+ __FUNCTION__, __LINE__,
+ ret
+ );
+
+ data->mappedMemory = gcvNULL;
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ data->mappedMemory = (gctPOINTER) vma->vm_start;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return 0;
+ }
+
+OnError:
+ gcmkFOOTER();
+ return -ENOTTY;
+}
+
+
+#if !USE_PLATFORM_DRIVER
+static int __init drv_init(void)
+#else
+static int drv_init(void)
+#endif
+{
+ int ret;
+ int result = -EINVAL;
+ gceSTATUS status;
+ gckGALDEVICE device = gcvNULL;
+ struct class* device_class = gcvNULL;
+
+ gcsDEVICE_CONSTRUCT_ARGS args = {
+ .recovery = recovery,
+ .stuckDump = stuckDump,
+ .gpu3DMinClock = gpu3DMinClock,
+ .contiguousRequested = contiguousRequested,
+ .platform = &platform,
+ .mmu = mmu,
+ .registerMemMapped = registerMemMapped,
+ .registerMemAddress = registerMemAddress,
+#if gcdENABLE_DEC_COMPRESSION
+ .registerMemBaseDEC300 = registerMemBaseDEC300,
+ .registerMemSizeDEC300 = registerMemSizeDEC300,
+#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)
+ {
+ powerManagement = 0;
+ }
+#endif
+
+ if (showArgs)
+ {
+ gckOS_DumpParam();
+ }
+
+ if (logFileSize != 0)
+ {
+ gckDEBUGFS_Initialize();
+ }
+
+ /* Create the GAL device. */
+ status = gckGALDEVICE_Construct(
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
+ irqLine3D0,
+ registerMemBase3D0, registerMemSize3D0,
+ irqLine3D1,
+ registerMemBase3D1, registerMemSize3D1,
+#else
+ irqLine,
+ registerMemBase, registerMemSize,
+#endif
+ irqLine2D,
+ registerMemBase2D, registerMemSize2D,
+ irqLineVG,
+ registerMemBaseVG, registerMemSizeVG,
+ contiguousBase, contiguousSize,
+ bankSize, fastClear, compression, baseAddress, physSize, signal,
+ logFileSize,
+ powerManagement,
+ gpuProfiler,
+ &args,
+ &device
+ );
+
+ 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));
+
+ if ((physSize != 0)
+ && (device->kernels[gcvCORE_MAJOR] != gcvNULL)
+ && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0))
+ {
+ /* Reset the base address */
+ device->baseAddress = 0;
+ }
+
+ /* Register the character device. */
+ ret = register_chrdev(major, DEVICE_NAME, &driver_fops);
+
+ if (ret < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Could not allocate major number for mmap.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ if (major == 0)
+ {
+ major = ret;
+ }
+
+ /* Create the device class. */
+ device_class = class_create(THIS_MODULE, CLASS_NAME);
+
+ if (IS_ERR(device_class))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Failed to create the class.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+ device_create(device_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
+#else
+ 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();
+ return 0;
+
+OnError:
+ /* Roll back. */
+ if (device_class != gcvNULL)
+ {
+ device_destroy(device_class, MKDEV(major, 0));
+ class_destroy(device_class);
+ }
+
+ if (device != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckGALDEVICE_Stop(device));
+ gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
+ }
+
+ gcmkFOOTER();
+ return result;
+}
+
+#if !USE_PLATFORM_DRIVER
+static void __exit drv_exit(void)
+#else
+static void drv_exit(void)
+#endif
+{
+ gcmkHEADER();
+
+ gcmkASSERT(gpuClass != gcvNULL);
+ device_destroy(gpuClass, MKDEV(major, 0));
+ class_destroy(gpuClass);
+
+ unregister_chrdev(major, DEVICE_NAME);
+
+ gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice));
+ gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice));
+
+ if(gckDEBUGFS_IsEnabled())
+ {
+ gckDEBUGFS_Terminate();
+ }
+
+ gcmkFOOTER_NO();
+}
+
+#if !USE_PLATFORM_DRIVER
+ module_init(drv_init);
+ module_exit(drv_exit);
+#else
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static int gpu_probe(struct platform_device *pdev)
+#else
+static int __devinit gpu_probe(struct platform_device *pdev)
+#endif
+{
+ int ret = -ENODEV;
+ gcsMODULE_PARAMETERS moduleParam = {
+#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
+#else
+ .irqLine = irqLine,
+ .registerMemBase = registerMemBase,
+ .registerMemSize = registerMemSize,
+#endif
+ .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,
+ .registerMemMapped = registerMemMapped,
+ };
+
+ gcmkHEADER();
+
+ platform.device = pdev;
+
+ if (platform.ops->getPower)
+ {
+ if (gcmIS_ERROR(platform.ops->getPower(&platform)))
+ {
+ gcmkFOOTER_NO();
+ return ret;
+ }
+ }
+
+ if (platform.ops->adjustParam)
+ {
+ /* Override default module param. */
+ platform.ops->adjustParam(&platform, &moduleParam);
+
+ /* Update module param because drv_init() uses them directly. */
+ _UpdateModuleParam(&moduleParam);
+ }
+
+ ret = drv_init();
+
+ if (!ret)
+ {
+ platform_set_drvdata(pdev, galDevice);
+
+ gcmkFOOTER_NO();
+ return ret;
+ }
+
+ gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret);
+ return ret;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static int gpu_remove(struct platform_device *pdev)
+#else
+static int __devexit gpu_remove(struct platform_device *pdev)
+#endif
+{
+ gcmkHEADER();
+
+ drv_exit();
+
+ if (platform.ops->putPower)
+ {
+ platform.ops->putPower(&platform);
+ }
+
+ gcmkFOOTER_NO();
+ return 0;
+}
+
+static int gpu_suspend(struct platform_device *dev, pm_message_t state)
+{
+ gceSTATUS status;
+ gckGALDEVICE device;
+ gctINT i;
+
+ device = platform_get_drvdata(dev);
+
+ if (!device)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (device->kernels[i] != gcvNULL)
+ {
+ /* Store states. */
+#if gcdENABLE_VG
+ if (i == gcvCORE_VG)
+ {
+ status = gckVGHARDWARE_QueryPowerManagementState(device->kernels[i]->vg->hardware, &device->statesStored[i]);
+ }
+ else
+#endif
+ {
+ status = gckHARDWARE_QueryPowerManagementState(device->kernels[i]->hardware, &device->statesStored[i]);
+ }
+
+ if (gcmIS_ERROR(status))
+ {
+ return -1;
+ }
+
+#if gcdENABLE_VG
+ if (i == gcvCORE_VG)
+ {
+ status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_OFF);
+ }
+ else
+#endif
+ {
+ status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF);
+ }
+
+ if (gcmIS_ERROR(status))
+ {
+ return -1;
+ }
+
+ }
+ }
+
+ return 0;
+}
+
+static int gpu_resume(struct platform_device *dev)
+{
+ gceSTATUS status;
+ gckGALDEVICE device;
+ gctINT i;
+ gceCHIPPOWERSTATE statesStored;
+
+ device = platform_get_drvdata(dev);
+
+ if (!device)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (device->kernels[i] != gcvNULL)
+ {
+#if gcdENABLE_VG
+ if (i == gcvCORE_VG)
+ {
+ status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_ON);
+ }
+ else
+#endif
+ {
+ status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_ON);
+ }
+
+ if (gcmIS_ERROR(status))
+ {
+ return -1;
+ }
+
+ /* Convert global state to crossponding internal state. */
+ switch(device->statesStored[i])
+ {
+ case gcvPOWER_OFF:
+ statesStored = gcvPOWER_OFF_BROADCAST;
+ break;
+ case gcvPOWER_IDLE:
+ statesStored = gcvPOWER_IDLE_BROADCAST;
+ break;
+ case gcvPOWER_SUSPEND:
+ statesStored = gcvPOWER_SUSPEND_BROADCAST;
+ break;
+ case gcvPOWER_ON:
+ statesStored = gcvPOWER_ON_AUTO;
+ break;
+ 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
+ {
+ status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, statesStored);
+ }
+
+ if (gcmIS_ERROR(status))
+ {
+ return -1;
+ }
+ }
+ }
+
+ 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);
+}
+
+static int gpu_system_resume(struct device *dev)
+{
+ return gpu_resume(to_platform_device(dev));
+}
+#endif
+
+static const struct dev_pm_ops gpu_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(gpu_system_suspend, gpu_system_resume)
+};
+#endif
+
+static struct platform_driver gpu_driver = {
+ .probe = gpu_probe,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+ .remove = gpu_remove,
+#else
+ .remove = __devexit_p(gpu_remove),
+#endif
+
+ .suspend = gpu_suspend,
+ .resume = gpu_resume,
+
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DEVICE_NAME,
+#if defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+ .pm = &gpu_pm_ops,
+#endif
+ }
+};
+
+static int __init gpu_init(void)
+{
+ int ret = 0;
+
+ memset(&platform, 0, sizeof(gcsPLATFORM));
+
+ gckPLATFORM_QueryOperations(&platform.ops);
+
+ if (platform.ops == gcvNULL)
+ {
+ printk(KERN_ERR "galcore: No platform specific operations.\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (platform.ops->allocPriv)
+ {
+ /* Allocate platform private data. */
+ if (gcmIS_ERROR(platform.ops->allocPriv(&platform)))
+ {
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
+ if (platform.ops->needAddDevice
+ && platform.ops->needAddDevice(&platform))
+ {
+ /* 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);
+ }
+
+ ret = platform_driver_register(&gpu_driver);
+ if (!ret)
+ {
+ goto out;
+ }
+
+ platform_device_del(platform.device);
+put_dev:
+ platform_device_put(platform.device);
+
+out:
+ return ret;
+}
+
+static void __exit gpu_exit(void)
+{
+ platform_driver_unregister(&gpu_driver);
+
+ 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);
+module_exit(gpu_exit);
+
+#endif
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
index 000000000000..9dfb755c0519
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel.c
@@ -0,0 +1,423 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_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;
+ gctPHYS_ADDR_T phyAddr;
+ 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 *)(gctUINT32)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);
+ if (shm == NULL)
+ {
+ return TEEC_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* 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;
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c
new file mode 100644
index 000000000000..3a0feac03b69
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c
@@ -0,0 +1,211 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include <gc_hal.h>
+#include <gc_hal_base.h>
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+
+#include "gc_hal_kernel_sync.h"
+
+static struct sync_pt *
+viv_sync_pt_dup(
+ struct sync_pt * sync_pt
+ )
+{
+ gceSTATUS status;
+ struct viv_sync_pt *pt;
+ struct viv_sync_pt *src;
+ struct viv_sync_timeline *obj;
+
+ src = (struct viv_sync_pt *) sync_pt;
+ obj = (struct viv_sync_timeline *) sync_pt->parent;
+
+ /* Create the new sync_pt. */
+ pt = (struct viv_sync_pt *)
+ sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
+
+ pt->stamp = src->stamp;
+ pt->sync = src->sync;
+
+ /* Reference sync point. */
+ status = gckOS_ReferenceSyncPoint(obj->os, pt->sync);
+
+ if (gcmIS_ERROR(status))
+ {
+ sync_pt_free((struct sync_pt *)pt);
+ return NULL;
+ }
+
+ return (struct sync_pt *)pt;
+}
+
+static int
+viv_sync_pt_has_signaled(
+ struct sync_pt * sync_pt
+ )
+{
+ gceSTATUS status;
+ gctBOOL state;
+ struct viv_sync_pt * pt;
+ struct viv_sync_timeline * obj;
+
+ pt = (struct viv_sync_pt *)sync_pt;
+ obj = (struct viv_sync_timeline *)sync_pt->parent;
+
+ status = gckOS_QuerySyncPoint(obj->os, pt->sync, &state);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Error. */
+ return -1;
+ }
+
+ return state;
+}
+
+static int
+viv_sync_pt_compare(
+ struct sync_pt * a,
+ struct sync_pt * b
+ )
+{
+ int ret;
+ struct viv_sync_pt * pt1 = (struct viv_sync_pt *) a;
+ struct viv_sync_pt * pt2 = (struct viv_sync_pt *) b;
+
+ ret = (pt1->stamp < pt2->stamp) ? -1
+ : (pt1->stamp == pt2->stamp) ? 0
+ : 1;
+
+ return ret;
+}
+
+static void
+viv_sync_pt_free(
+ struct sync_pt * sync_pt
+ )
+{
+ struct viv_sync_pt * pt;
+ struct viv_sync_timeline * obj;
+
+ pt = (struct viv_sync_pt *) sync_pt;
+ obj = (struct viv_sync_timeline *) sync_pt->parent;
+
+ gckOS_DestroySyncPoint(obj->os, pt->sync);
+}
+
+static struct sync_timeline_ops viv_timeline_ops =
+{
+ .driver_name = "viv_sync",
+ .dup = viv_sync_pt_dup,
+ .has_signaled = viv_sync_pt_has_signaled,
+ .compare = viv_sync_pt_compare,
+ .free_pt = viv_sync_pt_free,
+};
+
+struct viv_sync_timeline *
+viv_sync_timeline_create(
+ const char * name,
+ gckOS os
+ )
+{
+ struct viv_sync_timeline * obj;
+
+ obj = (struct viv_sync_timeline *)
+ sync_timeline_create(&viv_timeline_ops, sizeof(struct viv_sync_timeline), name);
+
+ obj->os = os;
+ obj->stamp = 0;
+
+ return obj;
+}
+
+struct sync_pt *
+viv_sync_pt_create(
+ struct viv_sync_timeline * obj,
+ gctSYNC_POINT SyncPoint
+ )
+{
+ gceSTATUS status;
+ struct viv_sync_pt * pt;
+
+ pt = (struct viv_sync_pt *)
+ sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
+
+ pt->stamp = obj->stamp++;
+ pt->sync = SyncPoint;
+
+ /* Dup signal. */
+ status = gckOS_ReferenceSyncPoint(obj->os, SyncPoint);
+
+ if (gcmIS_ERROR(status))
+ {
+ sync_pt_free((struct sync_pt *)pt);
+ return NULL;
+ }
+
+ return (struct sync_pt *) pt;
+}
+
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h
new file mode 100644
index 000000000000..658b205ecd54
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_sync_h_
+#define __gc_hal_kernel_sync_h_
+
+#include <linux/types.h>
+
+/* sync.h is in drivers/staging/android/ for now. */
+#include <sync.h>
+
+#include <gc_hal.h>
+#include <gc_hal_base.h>
+
+struct viv_sync_timeline
+{
+ /* Parent object. */
+ struct sync_timeline obj;
+
+ /* Timestamp when sync_pt is created. */
+ gctUINT stamp;
+
+ /* Pointer to os struct. */
+ gckOS os;
+};
+
+
+struct viv_sync_pt
+{
+ /* Parent object. */
+ struct sync_pt pt;
+
+ /* Reference sync point*/
+ gctSYNC_POINT sync;
+
+ /* Timestamp when sync_pt is created. */
+ gctUINT stamp;
+};
+
+/* Create viv_sync_timeline object. */
+struct viv_sync_timeline *
+viv_sync_timeline_create(
+ const char * Name,
+ gckOS Os
+ );
+
+/* Create viv_sync_pt object. */
+struct sync_pt *
+viv_sync_pt_create(
+ struct viv_sync_timeline * Obj,
+ gctSYNC_POINT SyncPoint
+ );
+
+#endif /* __gc_hal_kernel_sync_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
index 000000000000..e2a71d66c8ab
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c
@@ -0,0 +1,967 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_kernel_platform.h"
+#include "gc_hal_kernel_device.h"
+#include "gc_hal_driver.h"
+#include <linux/slab.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/of_address.h>
+#endif
+
+#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>
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
+#include <linux/busfreq-imx6.h>
+#include <linux/reset.h>
+#else
+#include <linux/busfreq-imx.h>
+#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;
+}
+
+extern gckKERNEL
+_GetValidKernel(
+ gckGALDEVICE Device
+ );
+
+gceSTATUS
+_ShrinkMemory(
+ IN gckPLATFORM Platform
+ )
+{
+ struct platform_device *pdev;
+ gckGALDEVICE galDevice;
+ gckKERNEL kernel;
+
+ pdev = Platform->device;
+
+ galDevice = platform_get_drvdata(pdev);
+
+ kernel = _GetValidKernel(galDevice);
+
+ 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 {
+ unsigned long 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;
+
+ if(Args->physSize == 0)
+ Args->physSize = 0x80000000;
+
+ 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
+_SetClock(
+ IN gckPLATFORM Platform,
+ IN gceCORE GPU,
+ IN gctBOOL Enable
+ );
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+static void imx6sx_optimize_qosc_for_GPU(IN gckPLATFORM Platform)
+{
+ struct device_node *np;
+ void __iomem *src_base;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-qosc");
+ if (!np)
+ return;
+
+ src_base = of_iomap(np, 0);
+ WARN_ON(!src_base);
+ _SetClock(Platform, gcvCORE_MAJOR, gcvTRUE);
+ writel_relaxed(0, src_base); /* Disable clkgate & soft_rst */
+ writel_relaxed(0, src_base+0x60); /* Enable all masters */
+ writel_relaxed(0, src_base+0x1400); /* Disable clkgate & soft_rst for gpu */
+ writel_relaxed(0x0f000222, src_base+0x1400+0xd0); /* Set Write QoS 2 for gpu */
+ writel_relaxed(0x0f000822, src_base+0x1400+0xe0); /* Set Read QoS 8 for gpu */
+ _SetClock(Platform, gcvCORE_MAJOR, gcvFALSE);
+ return;
+}
+#endif
+
+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
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ imx6sx_optimize_qosc_for_GPU(Platform);
+#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
+#ifdef CONFIG_PM_RUNTIME
+static int gpu_runtime_suspend(struct device *dev)
+{
+ release_bus_freq(BUS_FREQ_HIGH);
+ return 0;
+}
+
+static int gpu_runtime_resume(struct device *dev)
+{
+ request_bus_freq(BUS_FREQ_HIGH);
+ return 0;
+}
+#endif
+
+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;
+}
+
+gcmkPLATFROM_Name
+
+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
+ .name = _Name,
+};
+
+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
index 000000000000..5ba25b5de676
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config
@@ -0,0 +1,20 @@
+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
+
+EXTRA_CFLAGS += -DCLASS_NAME=\"gpu_class\"
+
+EXTRA_CFLAGS += -DDISABLE_RECORD_ARRAY_SIZE_OPTIMIZATION
+